Преглед изворни кода

Fix switch's case block lexical scope handling (#1392)

fixes https://github.com/sebastienros/jint/issues/1391
Marko Lahma пре 2 година
родитељ
комит
dc75d1a396

+ 29 - 0
Jint.Tests/Runtime/SwitchTests.cs

@@ -0,0 +1,29 @@
+namespace Jint.Tests.Runtime;
+
+public class JintFailureTest
+{
+    [Fact]
+    public void ShouldHandleCaseBlockLexicalScopeCorrectly()
+    {
+        var engine = new Engine();
+        engine.SetValue("switchVal", 1);
+        engine.SetValue("getCoffee", new Func<string>(() => "coffee"));
+
+        engine.Execute(@"
+        function myFunc() {
+            switch(switchVal) {
+                case 0:
+                    const text = getCoffee();
+                    return text;
+                    break;
+                case 1:
+                    const line = getCoffee();
+                    return line;
+                    break;
+            }
+        }
+        ");
+
+        Assert.Equal("coffee", engine.Evaluate("myFunc()"));
+    }
+}

+ 5 - 0
Jint/Runtime/Environments/DeclarativeEnvironmentRecord.cs

@@ -180,5 +180,10 @@ namespace Jint.Runtime.Environments
         {
             return Undefined;
         }
+
+        public void Clear()
+        {
+            _dictionary = null;
+        }
     }
 }

+ 10 - 1
Jint/Runtime/Interpreter/Statements/JintSwitchBlock.cs

@@ -42,6 +42,8 @@ namespace Jint.Runtime.Interpreter.Statements
             EnvironmentRecord? oldEnv = null;
             var temp = _jintSwitchBlock;
 
+            DeclarativeEnvironmentRecord? blockEnv = null;
+
             start:
             for (; i < temp.Length; i++)
             {
@@ -49,7 +51,9 @@ namespace Jint.Runtime.Interpreter.Statements
                 if (clause.LexicalDeclarations is not null && oldEnv is null)
                 {
                     oldEnv = context.Engine.ExecutionContext.LexicalEnvironment;
-                    var blockEnv = JintEnvironment.NewDeclarativeEnvironment(context.Engine, oldEnv);
+                    blockEnv ??= JintEnvironment.NewDeclarativeEnvironment(context.Engine, oldEnv);
+                    blockEnv.Clear();
+
                     JintStatementList.BlockDeclarationInstantiation(context.Engine, blockEnv, clause.LexicalDeclarations);
                     context.Engine.UpdateLexicalEnvironment(blockEnv);
                 }
@@ -71,6 +75,11 @@ namespace Jint.Runtime.Interpreter.Statements
 
                 if (!hit)
                 {
+                    if (oldEnv is not null)
+                    {
+                        context.Engine.UpdateLexicalEnvironment(oldEnv);
+                        oldEnv = null;
+                    }
                     continue;
                 }