diff --git a/src/Asynkron.JsEngine/Ast/SwitchInstantiationPlan.cs b/src/Asynkron.JsEngine/Ast/SwitchInstantiationPlan.cs index 50e16769a..a8320d8d4 100644 --- a/src/Asynkron.JsEngine/Ast/SwitchInstantiationPlan.cs +++ b/src/Asynkron.JsEngine/Ast/SwitchInstantiationPlan.cs @@ -7,6 +7,7 @@ namespace Asynkron.JsEngine.Ast; internal sealed record SwitchInstantiationPlan( + bool IsStrict, ImmutableArray LexicalBindings, ImmutableArray FunctionBindings, ImmutableArray ClassBindings); diff --git a/src/Asynkron.JsEngine/Ast/SwitchStatement.cs b/src/Asynkron.JsEngine/Ast/SwitchStatement.cs index 2f69411c3..9b338f348 100644 --- a/src/Asynkron.JsEngine/Ast/SwitchStatement.cs +++ b/src/Asynkron.JsEngine/Ast/SwitchStatement.cs @@ -25,8 +25,15 @@ SwitchInstantiationPlan IAstCacheable.GetOrCreateCache( var functionBindings = ImmutableArray.CreateBuilder(); var classBindings = ImmutableArray.CreateBuilder(); + var isStrict = false; + foreach (var switchCase in self.Cases) { + if (switchCase.Body.IsStrict) + { + isStrict = true; + } + foreach (var stmt in switchCase.Body.Statements) { if (stmt is VariableDeclaration @@ -49,9 +56,7 @@ or VariableKind.AwaitUsing { var isAsyncOrGenerator = funcDecl.Function.IsAsync || funcDecl.Function.WasAsync || funcDecl.Function.IsGenerator; - functionBindings.Add(new SwitchFunctionBinding( - funcDecl.Name, - funcDecl.Function, + functionBindings.Add(new SwitchFunctionBinding(funcDecl.Name, funcDecl.Function, !isAsyncOrGenerator)); continue; } @@ -64,6 +69,7 @@ or VariableKind.AwaitUsing } return new SwitchInstantiationPlan( + isStrict, lexicalBindings.ToImmutable(), functionBindings.ToImmutable(), classBindings.ToImmutable()); diff --git a/src/Asynkron.JsEngine/Ast/SwitchStatementExtensions.cs b/src/Asynkron.JsEngine/Ast/SwitchStatementExtensions.cs index c3b10af6d..c6ac98107 100644 --- a/src/Asynkron.JsEngine/Ast/SwitchStatementExtensions.cs +++ b/src/Asynkron.JsEngine/Ast/SwitchStatementExtensions.cs @@ -25,17 +25,16 @@ private JsValue EvaluateSwitchJsValue(JsEnvironment environment, var instantiationPlan = ((IAstCacheable)statement).GetOrCreateCache(); - var isStrict = context.CurrentScope.IsStrict; // Create a lexical environment for the entire switch block // This environment is shared by all case clause bodies - var switchEnv = new JsEnvironment(environment, false, isStrict); + var switchEnv = new JsEnvironment(environment, false, instantiationPlan.IsStrict); // Push a scope context for the switch block - var scopeMode = isStrict ? ScopeMode.Strict : ScopeMode.Sloppy; + var scopeMode = instantiationPlan.IsStrict ? ScopeMode.Strict : ScopeMode.Sloppy; using var scopeHandle = context.PushScope(ScopeKind.Block, scopeMode); // Hoist lexical declarations from all case bodies - SwitchStatement.InstantiateSwitchLexicalDeclarations(instantiationPlan, switchEnv, context, isStrict); + SwitchStatement.InstantiateSwitchLexicalDeclarations(instantiationPlan, switchEnv, context); // V = undefined (spec step 1) var completionValue = JsValue.Undefined; @@ -109,7 +108,7 @@ private JsValue EvaluateSwitchJsValue(JsEnvironment environment, } private static void InstantiateSwitchLexicalDeclarations(SwitchInstantiationPlan plan, JsEnvironment switchEnv, - EvaluationContext context, bool isStrict) + EvaluationContext context) { foreach (var binding in plan.LexicalBindings) { @@ -129,8 +128,6 @@ private static void InstantiateSwitchLexicalDeclarations(SwitchInstantiationPlan continue; } - // In strict mode, block-scoped function declarations are initialized at switch entry - // (mirrors block evaluation behavior). var functionValue = funcBinding.Function.CreateFunctionValue(switchEnv, context, skipInternalNameBinding: true); switchEnv.DefineJsValue(