diff --git a/Jint.Tests/Runtime/ScriptStatementListReuseTests.cs b/Jint.Tests/Runtime/ScriptStatementListReuseTests.cs
new file mode 100644
index 000000000..d902525bb
--- /dev/null
+++ b/Jint.Tests/Runtime/ScriptStatementListReuseTests.cs
@@ -0,0 +1,91 @@
+namespace Jint.Tests.Runtime;
+
+///
+/// Pins the semantics of the per-engine top-level (Program) statement-list cache: re-evaluating the
+/// same prepared script on one engine reuses the top-level handler tree (and, through it, top-level
+/// function-expression definitions and their warm inline caches) while every closure, environment and
+/// per-run value stays strictly per evaluation. A first evaluation - the fresh-engine-per-op shape -
+/// builds the tree fresh and caches nothing, so those hosts stay byte-identical to the historical path;
+/// these tests exercise the RE-evaluation branch that the cache actually engages on.
+///
+public class ScriptStatementListReuseTests
+{
+ // Each case is (source, expected string result). Re-evaluated many times on ONE engine: the result
+ // must be identical every time, matching a fresh engine — the reused top-level tree must not carry
+ // stale per-run state.
+ public static TheoryData Cases() => new()
+ {
+ { "var x = 1 + 1 === 2; '' + x;", "true" },
+ { "var t = 0; for (var i = 0; i < 10; i++) { t += i; } '' + t;", "45" },
+ { "var s = 0; { let y = 3; const z = y * 2; s = y + z; } '' + s;", "9" },
+ { "var out = ''; for (var k of [1, 2, 3]) { out += k; } out;", "123" },
+ { "var o = { a: 1, b: 2 }; var ks = ''; for (var p in o) { ks += p; } ks;", "ab" },
+ { "var r; try { r = 1; throw 'e'; } catch (e) { r = 2; } finally { r += 10; } '' + r;", "12" },
+ { "'use strict'; var q = (function () { return 42; })(); '' + q;", "42" },
+ { "var m = [1, 2, 3].map(function (v) { return v * v; }).reduce(function (a, b) { return a + b; }, 0); '' + m;", "14" },
+ { "function g(n) { var r = 0; for (var i = 0; i < n; i++) { r += i; } return r; } '' + g(100);", "4950" },
+ { "var sw = ''; switch (2) { case 1: sw = 'one'; break; case 2: sw = 'two'; break; default: sw = 'd'; } sw;", "two" },
+ };
+
+ [Theory]
+ [MemberData(nameof(Cases))]
+ public void RepeatedEvaluationMatchesFreshEngine(string source, string expected)
+ {
+ var prepared = Engine.PrepareScript(source);
+
+ // Baseline: a first evaluation on a fresh engine (the uncached path).
+ Assert.Equal(expected, new Engine().Evaluate(prepared).ToString());
+
+ // Re-evaluations on a single engine must produce the identical value every time.
+ var engine = new Engine();
+ for (var i = 0; i < 5; i++)
+ {
+ Assert.Equal(expected, engine.Evaluate(prepared).ToString());
+ }
+ }
+
+ [Fact]
+ public void ReusedTopLevelFunctionExpressionRecapturesCurrentState()
+ {
+ // A top-level function expression's interpreter definition is reused across evaluations once the
+ // top-level tree is cached, but each evaluation must still produce a closure over THIS run's
+ // freshly re-declared global state — not a stale binding from an earlier run.
+ var engine = new Engine();
+ var prepared = Engine.PrepareScript("""
+ var base = seed * 10;
+ var add = function (n) { return base + n; };
+ add(seed);
+ """);
+
+ engine.SetValue("seed", 1);
+ Assert.Equal(11, engine.Evaluate(prepared).AsNumber()); // base=10, add(1)=11
+
+ engine.SetValue("seed", 5);
+ Assert.Equal(55, engine.Evaluate(prepared).AsNumber()); // base=50, add(5)=55
+
+ engine.SetValue("seed", 9);
+ Assert.Equal(99, engine.Evaluate(prepared).AsNumber()); // base=90, add(9)=99
+ }
+
+ [Fact]
+ public void ReusedTopLevelIifeKeepsIndependentPerRunState()
+ {
+ // The dominant embedding shape (module-pattern library) is a single top-level IIFE. Caching the
+ // top-level list reuses the IIFE's body tree across runs; each run must still get fresh internal
+ // state (the counter starts at 0 every evaluation).
+ var engine = new Engine();
+ var prepared = Engine.PrepareScript("""
+ (function () {
+ var count = 0;
+ function bump() { count += 1; return count; }
+ bump(); bump(); bump();
+ return count;
+ })();
+ """);
+
+ for (var i = 0; i < 4; i++)
+ {
+ Assert.Equal(3, engine.Evaluate(prepared).AsNumber());
+ }
+ }
+}
diff --git a/Jint/Engine.cs b/Jint/Engine.cs
index 1c4726d5e..059664140 100644
--- a/Jint/Engine.cs
+++ b/Jint/Engine.cs
@@ -75,6 +75,38 @@ public sealed partial class Engine : IDisposable
// above only engages on RE-evaluation (see GlobalDeclarationInstantiation).
private readonly HashSet