Explorar o código

Move data from Completion and ExpressionResult to context (#1291)

Marko Lahma %!s(int64=2) %!d(string=hai) anos
pai
achega
b3154ca781
Modificáronse 29 ficheiros con 219 adicións e 246 borrados
  1. 2 2
      Jint.Tests/Runtime/EngineLimitTests.cs
  2. 1 1
      Jint/Engine.Modules.cs
  3. 46 75
      Jint/Runtime/Completion.cs
  4. 51 50
      Jint/Runtime/Environments/ExecutionContext.cs
  5. 13 0
      Jint/Runtime/Interpreter/EvaluationContext.cs
  6. 1 1
      Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs
  7. 11 13
      Jint/Runtime/Interpreter/Expressions/JintExpression.cs
  8. 1 4
      Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs
  9. 1 1
      Jint/Runtime/Interpreter/JintFunctionDefinition.cs
  10. 4 8
      Jint/Runtime/Interpreter/JintStatementList.cs
  11. 12 15
      Jint/Runtime/Interpreter/Statements/JintBreakStatement.cs
  12. 1 1
      Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs
  13. 12 15
      Jint/Runtime/Interpreter/Statements/JintContinueStatement.cs
  14. 1 1
      Jint/Runtime/Interpreter/Statements/JintDebuggerStatement.cs
  15. 3 3
      Jint/Runtime/Interpreter/Statements/JintDoWhileStatement.cs
  16. 8 9
      Jint/Runtime/Interpreter/Statements/JintEmptyStatement.cs
  17. 7 7
      Jint/Runtime/Interpreter/Statements/JintForInForOfStatement.cs
  18. 2 2
      Jint/Runtime/Interpreter/Statements/JintForStatement.cs
  19. 1 1
      Jint/Runtime/Interpreter/Statements/JintIfStatement.cs
  20. 2 2
      Jint/Runtime/Interpreter/Statements/JintLabeledStatement.cs
  21. 20 21
      Jint/Runtime/Interpreter/Statements/JintReturnStatement.cs
  22. 2 2
      Jint/Runtime/Interpreter/Statements/JintStatement.cs
  23. 1 1
      Jint/Runtime/Interpreter/Statements/JintSwitchBlock.cs
  24. 1 1
      Jint/Runtime/Interpreter/Statements/JintSwitchStatement.cs
  25. 1 1
      Jint/Runtime/Interpreter/Statements/JintThrowStatement.cs
  26. 4 4
      Jint/Runtime/Interpreter/Statements/JintWhileStatement.cs
  27. 2 0
      Jint/Runtime/Interpreter/Statements/ProbablyBlockStatement.cs
  28. 3 3
      Jint/Runtime/Modules/CyclicModuleRecord.cs
  29. 5 2
      Jint/StrictModeScope.cs

+ 2 - 2
Jint.Tests/Runtime/EngineLimitTests.cs

@@ -10,9 +10,9 @@ public class EngineLimitTests
     public void ShouldAllowReasonableCallStackDepth()
     {
 #if RELEASE
-        const int FunctionNestingCount = 740;
+        const int FunctionNestingCount = 810;
 #else
-        const int FunctionNestingCount = 400;
+        const int FunctionNestingCount = 460;
 #endif
 
         // generate call tree

+ 1 - 1
Jint/Engine.Modules.cs

@@ -150,7 +150,7 @@ namespace Jint
             else if (promise.State == PromiseState.Rejected)
             {
                 var node = EsprimaExtensions.CreateLocationNode(Location.From(new Position(), new Position(), specifier));
-                ExceptionHelper.ThrowJavaScriptException(this, promise.Value, new Completion(CompletionType.Throw, promise.Value, null, node));
+                ExceptionHelper.ThrowJavaScriptException(this, promise.Value, new Completion(CompletionType.Throw, promise.Value, node));
             }
             else if (promise.State != PromiseState.Fulfilled)
             {

+ 46 - 75
Jint/Runtime/Completion.cs

@@ -3,93 +3,64 @@ using System.Runtime.InteropServices;
 using Esprima;
 using Esprima.Ast;
 using Jint.Native;
-using Jint.Runtime.Interpreter.Expressions;
 
-namespace Jint.Runtime
-{
-    public enum CompletionType : byte
-    {
-        Normal = 0,
-        Return = 1,
-        Throw = 2,
-        Break,
-        Continue
-    }
-
-    /// <summary>
-    /// https://tc39.es/ecma262/#sec-completion-record-specification-type
-    /// </summary>
-    [StructLayout(LayoutKind.Auto)]
-    public readonly struct Completion
-    {
-        private static readonly Node _emptyNode = new Identifier("");
-        private static readonly Completion _emptyCompletion = new(CompletionType.Normal, null!, _emptyNode);
+namespace Jint.Runtime;
 
-        internal readonly SyntaxElement _source;
+public enum CompletionType : byte
+{
+    Normal = 0,
+    Return = 1,
+    Throw = 2,
+    Break,
+    Continue
+}
 
-        internal Completion(CompletionType type, JsValue value, string? target, SyntaxElement source)
-        {
-            Type = type;
-            Value = value;
-            Target = target;
-            _source = source;
-        }
+/// <summary>
+/// https://tc39.es/ecma262/#sec-completion-record-specification-type
+/// </summary>
+[StructLayout(LayoutKind.Auto)]
+public readonly struct Completion
+{
+    private static readonly Node _emptyNode = new Identifier("");
+    private static readonly Completion _emptyCompletion = new(CompletionType.Normal, null!, _emptyNode);
 
-        public Completion(CompletionType type, JsValue value, SyntaxElement source)
-        {
-            Type = type;
-            Value = value;
-            Target = null;
-            _source = source;
-        }
+    internal readonly SyntaxElement _source;
 
-        public Completion(CompletionType type, string target, SyntaxElement source)
-        {
-            Type = type;
-            Value = null!;
-            Target = target;
-            _source = source;
-        }
+    public Completion(CompletionType type, JsValue value, SyntaxElement source)
+    {
+        Type = type;
+        Value = value;
+        _source = source;
+    }
 
-        internal Completion(in ExpressionResult result)
-        {
-            Type = (CompletionType) result.Type;
-            // this cast protects us from getting from type
-            Value = (JsValue) result.Value;
-            Target = null;
-            _source = result._source;
-        }
+    public readonly CompletionType Type;
+    public readonly JsValue Value;
+    public ref readonly Location Location => ref _source.Location;
 
-        public readonly CompletionType Type;
-        public readonly JsValue Value;
-        public readonly string? Target;
-        public ref readonly Location Location => ref _source.Location;
+    public static ref readonly Completion Empty() => ref _emptyCompletion;
 
-        public static ref readonly Completion Empty() => ref _emptyCompletion;
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public JsValue GetValueOrDefault()
+    {
+        return Value ?? Undefined.Instance;
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public JsValue GetValueOrDefault()
-        {
-            return Value ?? Undefined.Instance;
-        }
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public bool IsAbrupt()
+    {
+        return Type != CompletionType.Normal;
+    }
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public bool IsAbrupt()
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-updateempty
+    /// </summary>
+    internal Completion UpdateEmpty(JsValue value)
+    {
+        if (Value is not null)
         {
-            return Type != CompletionType.Normal;
+            return this;
         }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-updateempty
-        /// </summary>
-        internal Completion UpdateEmpty(JsValue value)
-        {
-            if (Value is not null)
-            {
-                return this;
-            }
-
-            return new Completion(Type, value, Target, _source);
-        }
+        return new Completion(Type, value, _source);
     }
 }

+ 51 - 50
Jint/Runtime/Environments/ExecutionContext.cs

@@ -1,67 +1,68 @@
+using System.Runtime.InteropServices;
 using Jint.Native.Function;
 
-namespace Jint.Runtime.Environments
+namespace Jint.Runtime.Environments;
+
+[StructLayout(LayoutKind.Auto)]
+internal readonly struct ExecutionContext
 {
-    internal readonly struct ExecutionContext
+    internal ExecutionContext(
+        IScriptOrModule? scriptOrModule,
+        EnvironmentRecord lexicalEnvironment,
+        EnvironmentRecord variableEnvironment,
+        PrivateEnvironmentRecord? privateEnvironment,
+        Realm realm,
+        FunctionInstance? function = null)
     {
-        internal ExecutionContext(
-            IScriptOrModule? scriptOrModule,
-            EnvironmentRecord lexicalEnvironment,
-            EnvironmentRecord variableEnvironment,
-            PrivateEnvironmentRecord? privateEnvironment,
-            Realm realm,
-            FunctionInstance? function = null)
-        {
-            ScriptOrModule = scriptOrModule;
-            LexicalEnvironment = lexicalEnvironment;
-            VariableEnvironment = variableEnvironment;
-            PrivateEnvironment = privateEnvironment;
-            Realm = realm;
-            Function = function;
-        }
+        ScriptOrModule = scriptOrModule;
+        LexicalEnvironment = lexicalEnvironment;
+        VariableEnvironment = variableEnvironment;
+        PrivateEnvironment = privateEnvironment;
+        Realm = realm;
+        Function = function;
+    }
 
-        public readonly IScriptOrModule? ScriptOrModule;
-        public readonly EnvironmentRecord LexicalEnvironment;
-        public readonly EnvironmentRecord VariableEnvironment;
-        public readonly PrivateEnvironmentRecord? PrivateEnvironment;
-        public readonly Realm Realm;
-        public readonly FunctionInstance? Function;
+    public readonly IScriptOrModule? ScriptOrModule;
+    public readonly EnvironmentRecord LexicalEnvironment;
+    public readonly EnvironmentRecord VariableEnvironment;
+    public readonly PrivateEnvironmentRecord? PrivateEnvironment;
+    public readonly Realm Realm;
+    public readonly FunctionInstance? Function;
 
-        public ExecutionContext UpdateLexicalEnvironment(EnvironmentRecord lexicalEnvironment)
-        {
-            return new ExecutionContext(ScriptOrModule, lexicalEnvironment, VariableEnvironment, PrivateEnvironment, Realm, Function);
-        }
+    public ExecutionContext UpdateLexicalEnvironment(EnvironmentRecord lexicalEnvironment)
+    {
+        return new ExecutionContext(ScriptOrModule, lexicalEnvironment, VariableEnvironment, PrivateEnvironment, Realm, Function);
+    }
 
-        public ExecutionContext UpdateVariableEnvironment(EnvironmentRecord variableEnvironment)
-        {
-            return new ExecutionContext(ScriptOrModule, LexicalEnvironment, variableEnvironment, PrivateEnvironment, Realm, Function);
-        }
+    public ExecutionContext UpdateVariableEnvironment(EnvironmentRecord variableEnvironment)
+    {
+        return new ExecutionContext(ScriptOrModule, LexicalEnvironment, variableEnvironment, PrivateEnvironment, Realm, Function);
+    }
 
-        public ExecutionContext UpdatePrivateEnvironment(PrivateEnvironmentRecord? privateEnvironment)
-        {
-            return new ExecutionContext(ScriptOrModule, LexicalEnvironment, VariableEnvironment, privateEnvironment, Realm, Function);
-        }
+    public ExecutionContext UpdatePrivateEnvironment(PrivateEnvironmentRecord? privateEnvironment)
+    {
+        return new ExecutionContext(ScriptOrModule, LexicalEnvironment, VariableEnvironment, privateEnvironment, Realm, Function);
+    }
 
-        /// <summary>
-        /// https://tc39.es/ecma262/#sec-getthisenvironment
-        /// </summary>
-        internal EnvironmentRecord GetThisEnvironment()
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-getthisenvironment
+    /// </summary>
+    internal EnvironmentRecord GetThisEnvironment()
+    {
+        // The loop will always terminate because the list of environments always
+        // ends with the global environment which has a this binding.
+        var lex = LexicalEnvironment;
+        while (true)
         {
-            // The loop will always terminate because the list of environments always
-            // ends with the global environment which has a this binding.
-            var lex = LexicalEnvironment;
-            while (true)
+            if (lex != null)
             {
-                if (lex != null)
+                if (lex.HasThisBinding())
                 {
-                    if (lex.HasThisBinding())
-                    {
-                        return lex;
+                    return lex;
 
-                    }
-
-                    lex = lex._outerEnv;
                 }
+
+                lex = lex._outerEnv;
             }
         }
     }

+ 13 - 0
Jint/Runtime/Interpreter/EvaluationContext.cs

@@ -1,3 +1,4 @@
+using System.Runtime.CompilerServices;
 using Esprima.Ast;
 
 namespace Jint.Runtime.Interpreter;
@@ -24,6 +25,10 @@ internal sealed class EvaluationContext
     public SyntaxElement LastSyntaxElement = null!;
     public readonly bool OperatorOverloadingAllowed;
 
+    // completion record information
+    public string? Target;
+    public CompletionType Completion;
+
     public void RunBeforeExecuteStatementChecks(Statement statement)
     {
         if (_shouldRunBeforeExecuteStatementChecks)
@@ -31,4 +36,12 @@ internal sealed class EvaluationContext
             Engine.RunBeforeExecuteStatementChecks(statement);
         }
     }
+
+    [MethodImpl(MethodImplOptions.AggressiveInlining)]
+    public void PrepareFor(Node node)
+    {
+        LastSyntaxElement = node;
+        Target = null;
+        Completion = CompletionType.Normal;
+    }
 }

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs

@@ -415,7 +415,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                     }
 
                     environmentRecord.SetMutableBinding(left.Identifier, rval, strict);
-                    return ExpressionResult.Normal(rval, completion._source);
+                    return ExpressionResult.Normal(rval);
                 }
 
                 return null;

+ 11 - 13
Jint/Runtime/Interpreter/Expressions/JintExpression.cs

@@ -17,28 +17,25 @@ namespace Jint.Runtime.Interpreter.Expressions
     [StructLayout(LayoutKind.Auto)]
     internal readonly struct ExpressionResult
     {
-        internal readonly SyntaxElement _source;
-
         public readonly ExpressionCompletionType Type;
         public readonly object Value;
 
-        public ExpressionResult(ExpressionCompletionType type, object value, SyntaxElement source)
+        public ExpressionResult(ExpressionCompletionType type, object value)
         {
             Type = type;
             Value = value;
-            _source = source;
         }
 
         public bool IsAbrupt() => Type != ExpressionCompletionType.Normal && Type != ExpressionCompletionType.Reference;
 
         public static implicit operator ExpressionResult(in Completion result)
         {
-            return new ExpressionResult((ExpressionCompletionType) result.Type, result.Value, result._source);
+            return new ExpressionResult((ExpressionCompletionType) result.Type, result.Value);
         }
 
-        public static ExpressionResult? Normal(JsValue value, SyntaxElement source)
+        public static ExpressionResult? Normal(JsValue value)
         {
-            return new ExpressionResult(ExpressionCompletionType.Normal, value, source);
+            return new ExpressionResult(ExpressionCompletionType.Normal, value);
         }
     }
 
@@ -73,17 +70,18 @@ namespace Jint.Runtime.Interpreter.Expressions
             var result = Evaluate(context);
             if (result.Type != ExpressionCompletionType.Reference)
             {
-                return new Completion((CompletionType) result.Type, (JsValue) result.Value, result._source);
+                return new Completion((CompletionType) result.Type, (JsValue) result.Value, context.LastSyntaxElement);
             }
 
             var jsValue = context.Engine.GetValue((Reference) result.Value, true);
-            return new Completion(CompletionType.Normal, jsValue, null, _expression);
+            return new Completion(CompletionType.Normal, jsValue, context.LastSyntaxElement);
         }
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         public ExpressionResult Evaluate(EvaluationContext context)
         {
-            context.LastSyntaxElement = _expression;
+            context.PrepareFor(_expression);
+
             if (!_initialized)
             {
                 Initialize(context);
@@ -112,12 +110,12 @@ namespace Jint.Runtime.Interpreter.Expressions
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         protected ExpressionResult NormalCompletion(JsValue value)
         {
-            return new ExpressionResult(ExpressionCompletionType.Normal, value, _expression);
+            return new ExpressionResult(ExpressionCompletionType.Normal, value);
         }
 
         protected ExpressionResult NormalCompletion(Reference value)
         {
-            return new ExpressionResult(ExpressionCompletionType.Reference, value, _expression);
+            return new ExpressionResult(ExpressionCompletionType.Reference, value);
         }
 
         /// <summary>
@@ -130,7 +128,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         protected ExpressionResult ThrowCompletion(JsValue value)
         {
-            return new ExpressionResult(ExpressionCompletionType.Throw, value, _expression);
+            return new ExpressionResult(ExpressionCompletionType.Throw, value);
         }
 
         /// <summary>

+ 1 - 4
Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs

@@ -113,10 +113,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 : TypeConverter.ToPropertyKey(property);
 
             var rent = context.Engine._referencePool.Rent(baseValue, propertyKey, isStrictModeCode, thisValue: actualThis);
-            return new ExpressionResult(
-                ExpressionCompletionType.Reference,
-                rent,
-                _expression);
+            return new ExpressionResult(ExpressionCompletionType.Reference, rent);
         }
     }
 }

+ 1 - 1
Jint/Runtime/Interpreter/JintFunctionDefinition.cs

@@ -40,7 +40,7 @@ internal sealed class JintFunctionDefinition
             // https://tc39.es/ecma262/#sec-runtime-semantics-evaluateconcisebody
             _bodyExpression ??= JintExpression.Build(context.Engine, (Expression) Function.Body);
             var jsValue = _bodyExpression.GetValue(context).GetValueOrDefault().Clone();
-            result = new Completion(CompletionType.Return, jsValue, null, Function.Body);
+            result = new Completion(CompletionType.Return, jsValue, Function.Body);
         }
         else if (Function.Generator)
         {

+ 4 - 8
Jint/Runtime/Interpreter/JintStatementList.cs

@@ -96,11 +96,7 @@ namespace Jint.Runtime.Interpreter
 
                     if (c.Type != CompletionType.Normal)
                     {
-                        return new Completion(
-                            c.Type,
-                            c.Value ?? sl.Value!,
-                            c.Target,
-                            c._source);
+                        return new Completion(c.Type, c.Value ?? sl.Value!, c._source);
                     }
                     sl = c;
                     if (c.Value is not null)
@@ -119,7 +115,7 @@ namespace Jint.Runtime.Interpreter
                 throw;
             }
 
-            return new Completion(c.Type, lastValue ?? JsValue.Undefined, c.Target, c._source!);
+            return new Completion(c.Type, lastValue ?? JsValue.Undefined, c._source!);
         }
 
         private static Completion HandleException(EvaluationContext context, Exception exception, JintStatement? s)
@@ -144,7 +140,7 @@ namespace Jint.Runtime.Interpreter
         private static Completion CreateThrowCompletion(ErrorConstructor errorConstructor, Exception e, JintStatement s)
         {
             var error = errorConstructor.Construct(new JsValue[] { e.Message });
-            return new Completion(CompletionType.Throw, error, null, s._statement);
+            return new Completion(CompletionType.Throw, error, s._statement);
         }
 
         private static Completion CreateThrowCompletion(JintStatement? s, JavaScriptException v)
@@ -155,7 +151,7 @@ namespace Jint.Runtime.Interpreter
                 source = EsprimaExtensions.CreateLocationNode(v.Location);
             }
 
-            return new Completion(CompletionType.Throw, v.Error, null, source);
+            return new Completion(CompletionType.Throw, v.Error, source);
         }
 
         /// <summary>

+ 12 - 15
Jint/Runtime/Interpreter/Statements/JintBreakStatement.cs

@@ -1,22 +1,19 @@
 using Esprima.Ast;
 
-namespace Jint.Runtime.Interpreter.Statements
+namespace Jint.Runtime.Interpreter.Statements;
+
+/// <summary>
+/// http://www.ecma-international.org/ecma-262/5.1/#sec-12.8
+/// </summary>
+internal sealed class JintBreakStatement : JintStatement<BreakStatement>
 {
-    /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.8
-    /// </summary>
-    internal sealed class JintBreakStatement : JintStatement<BreakStatement>
+    public JintBreakStatement(BreakStatement statement) : base(statement)
     {
-        private readonly string? _label;
-
-        public JintBreakStatement(BreakStatement statement) : base(statement)
-        {
-            _label = statement.Label?.Name;
-        }
+    }
 
-        protected override Completion ExecuteInternal(EvaluationContext context)
-        {
-            return new Completion(CompletionType.Break, null!, _label, _statement);
-        }
+    protected override Completion ExecuteInternal(EvaluationContext context)
+    {
+        context.Target = _statement.Label?.Name;
+        return new Completion(CompletionType.Break, null!, _statement);
     }
 }

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintClassDeclarationStatement.cs

@@ -29,7 +29,7 @@ namespace Jint.Runtime.Interpreter.Statements
                 env.InitializeBinding(classBinding, completion.Value);
             }
 
-            return new Completion(CompletionType.Normal, null!, null, _statement);
+            return new Completion(CompletionType.Normal, null!, _statement);
         }
     }
 }

+ 12 - 15
Jint/Runtime/Interpreter/Statements/JintContinueStatement.cs

@@ -1,22 +1,19 @@
 using Esprima.Ast;
 
-namespace Jint.Runtime.Interpreter.Statements
+namespace Jint.Runtime.Interpreter.Statements;
+
+/// <summary>
+/// http://www.ecma-international.org/ecma-262/5.1/#sec-12.7
+/// </summary>
+internal sealed class JintContinueStatement : JintStatement<ContinueStatement>
 {
-    /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.7
-    /// </summary>
-    internal sealed class JintContinueStatement : JintStatement<ContinueStatement>
+    public JintContinueStatement(ContinueStatement statement) : base(statement)
     {
-        private readonly string? _labelName;
-
-        public JintContinueStatement(ContinueStatement statement) : base(statement)
-        {
-            _labelName = _statement.Label?.Name;
-        }
+    }
 
-        protected override Completion ExecuteInternal(EvaluationContext context)
-        {
-            return new Completion(CompletionType.Continue, _labelName!, _statement);
-        }
+    protected override Completion ExecuteInternal(EvaluationContext context)
+    {
+        context.Target = _statement.Label?.Name;
+        return new Completion(CompletionType.Continue, null!, _statement);
     }
 }

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintDebuggerStatement.cs

@@ -29,7 +29,7 @@ namespace Jint.Runtime.Interpreter.Statements
                     break;
             }
 
-            return new Completion(CompletionType.Normal, null!, null, _statement);
+            return new Completion(CompletionType.Normal, null!, _statement);
         }
     }
 }

+ 3 - 3
Jint/Runtime/Interpreter/Statements/JintDoWhileStatement.cs

@@ -37,11 +37,11 @@ namespace Jint.Runtime.Interpreter.Statements
                     v = completion.Value;
                 }
 
-                if (completion.Type != CompletionType.Continue || completion.Target != _labelSetName)
+                if (completion.Type != CompletionType.Continue || context.Target != _labelSetName)
                 {
-                    if (completion.Type == CompletionType.Break && (completion.Target == null || completion.Target == _labelSetName))
+                    if (completion.Type == CompletionType.Break && (context.Target == null || context.Target == _labelSetName))
                     {
-                        return new Completion(CompletionType.Normal, v, null, _statement);
+                        return new Completion(CompletionType.Normal, v, _statement);
                     }
 
                     if (completion.Type != CompletionType.Normal)

+ 8 - 9
Jint/Runtime/Interpreter/Statements/JintEmptyStatement.cs

@@ -1,16 +1,15 @@
 using Esprima.Ast;
 
-namespace Jint.Runtime.Interpreter.Statements
+namespace Jint.Runtime.Interpreter.Statements;
+
+internal sealed class JintEmptyStatement : JintStatement<EmptyStatement>
 {
-    internal sealed class JintEmptyStatement : JintStatement<EmptyStatement>
+    public JintEmptyStatement(EmptyStatement statement) : base(statement)
     {
-        public JintEmptyStatement(EmptyStatement statement) : base(statement)
-        {
-        }
+    }
 
-        protected override Completion ExecuteInternal(EvaluationContext context)
-        {
-            return new Completion(CompletionType.Normal, null!, null, _statement);
-        }
+    protected override Completion ExecuteInternal(EvaluationContext context)
+    {
+        return new Completion(CompletionType.Normal, null!, _statement);
     }
 }

+ 7 - 7
Jint/Runtime/Interpreter/Statements/JintForInForOfStatement.cs

@@ -95,7 +95,7 @@ namespace Jint.Runtime.Interpreter.Statements
         {
             if (!HeadEvaluation(context, out var keyResult))
             {
-                return new Completion(CompletionType.Normal, JsValue.Undefined, null, _statement);
+                return new Completion(CompletionType.Normal, JsValue.Undefined, _statement);
             }
 
             return BodyEvaluation(context, _expr, _body, keyResult, IterationKind.Enumerate, _lhsKind);
@@ -170,7 +170,7 @@ namespace Jint.Runtime.Interpreter.Statements
                     if (!iteratorRecord.TryIteratorStep(out var nextResult))
                     {
                         close = true;
-                        return new Completion(CompletionType.Normal, v, null, _statement!);
+                        return new Completion(CompletionType.Normal, v, _statement!);
                     }
 
                     if (iteratorKind == IteratorKind.Async)
@@ -203,7 +203,7 @@ namespace Jint.Runtime.Interpreter.Statements
                         {
                             var identifier = (Identifier) ((VariableDeclaration) _leftNode).Declarations[0].Id;
                             lhsName ??= identifier.Name;
-                            lhsRef = new ExpressionResult(ExpressionCompletionType.Normal, engine.ResolveBinding(lhsName), identifier);
+                            lhsRef = new ExpressionResult(ExpressionCompletionType.Normal, engine.ResolveBinding(lhsName));
                         }
                     }
 
@@ -218,7 +218,7 @@ namespace Jint.Runtime.Interpreter.Statements
                         if (lhsRef.IsAbrupt())
                         {
                             close = true;
-                            status = new Completion(lhsRef);
+                            status = new Completion((CompletionType) lhsRef.Type, (JsValue) lhsRef.Value!, context.LastSyntaxElement);
                         }
                         else if (lhsKind == LhsKind.LexicalBinding)
                         {
@@ -278,13 +278,13 @@ namespace Jint.Runtime.Interpreter.Statements
                         v = result.Value;
                     }
 
-                    if (result.Type == CompletionType.Break && (result.Target == null || result.Target == _statement?.LabelSet?.Name))
+                    if (result.Type == CompletionType.Break && (context.Target == null || context.Target == _statement?.LabelSet?.Name))
                     {
                         completionType = CompletionType.Normal;
-                        return new Completion(CompletionType.Normal, v, null, _statement!);
+                        return new Completion(CompletionType.Normal, v, _statement!);
                     }
 
-                    if (result.Type != CompletionType.Continue || (result.Target != null && result.Target != _statement?.LabelSet?.Name))
+                    if (result.Type != CompletionType.Continue || (context.Target != null && context.Target != _statement?.LabelSet?.Name))
                     {
                         completionType = result.Type;
                         if (result.IsAbrupt())

+ 2 - 2
Jint/Runtime/Interpreter/Statements/JintForStatement.cs

@@ -141,12 +141,12 @@ namespace Jint.Runtime.Interpreter.Statements
                     v = result.Value;
                 }
 
-                if (result.Type == CompletionType.Break && (result.Target == null || result.Target == _statement?.LabelSet?.Name))
+                if (result.Type == CompletionType.Break && (context.Target == null || context.Target == _statement?.LabelSet?.Name))
                 {
                     return new Completion(CompletionType.Normal, result.Value!, ((JintStatement) this)._statement);
                 }
 
-                if (result.Type != CompletionType.Continue || (result.Target != null && result.Target != _statement?.LabelSet?.Name))
+                if (result.Type != CompletionType.Continue || (context.Target != null && context.Target != _statement?.LabelSet?.Name))
                 {
                     if (result.Type != CompletionType.Normal)
                     {

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintIfStatement.cs

@@ -33,7 +33,7 @@ namespace Jint.Runtime.Interpreter.Statements
             }
             else
             {
-                return new Completion(CompletionType.Normal, null!, _statement);
+                result = new Completion(CompletionType.Normal, null!, _statement);
             }
 
             return result;

+ 2 - 2
Jint/Runtime/Interpreter/Statements/JintLabeledStatement.cs

@@ -23,10 +23,10 @@ namespace Jint.Runtime.Interpreter.Statements
             // containing label and could keep a table per program with all the labels
             // labeledStatement.Body.LabelSet = labeledStatement.Label;
             var result = _body.Execute(context);
-            if (result.Type == CompletionType.Break && result.Target == _labelName)
+            if (result.Type == CompletionType.Break && context.Target == _labelName)
             {
                 var value = result.Value;
-                return new Completion(CompletionType.Normal, value, null, _statement);
+                return new Completion(CompletionType.Normal, value, _statement);
             }
 
             return result;

+ 20 - 21
Jint/Runtime/Interpreter/Statements/JintReturnStatement.cs

@@ -2,30 +2,29 @@ using Esprima.Ast;
 using Jint.Native;
 using Jint.Runtime.Interpreter.Expressions;
 
-namespace Jint.Runtime.Interpreter.Statements
+namespace Jint.Runtime.Interpreter.Statements;
+
+/// <summary>
+/// http://www.ecma-international.org/ecma-262/5.1/#sec-12.9
+/// </summary>
+internal sealed class JintReturnStatement : JintStatement<ReturnStatement>
 {
-    /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-12.9
-    /// </summary>
-    internal sealed class JintReturnStatement : JintStatement<ReturnStatement>
-    {
-        private JintExpression? _argument;
+    private JintExpression? _argument;
 
-        public JintReturnStatement(ReturnStatement statement) : base(statement)
-        {
-        }
+    public JintReturnStatement(ReturnStatement statement) : base(statement)
+    {
+    }
 
-        protected override void Initialize(EvaluationContext context)
-        {
-            _argument = _statement.Argument != null
-                ? JintExpression.Build(context.Engine, _statement.Argument)
-                : null;
-        }
+    protected override void Initialize(EvaluationContext context)
+    {
+        _argument = _statement.Argument != null
+            ? JintExpression.Build(context.Engine, _statement.Argument)
+            : null;
+    }
 
-        protected override Completion ExecuteInternal(EvaluationContext context)
-        {
-            var jsValue = _argument?.GetValue(context).Value ?? Undefined.Instance;
-            return new Completion(CompletionType.Return, jsValue, null, _statement);
-        }
+    protected override Completion ExecuteInternal(EvaluationContext context)
+    {
+        var jsValue = _argument?.GetValue(context).Value ?? Undefined.Instance;
+        return new Completion(CompletionType.Return, jsValue, _statement);
     }
 }

+ 2 - 2
Jint/Runtime/Interpreter/Statements/JintStatement.cs

@@ -31,7 +31,7 @@ namespace Jint.Runtime.Interpreter.Statements
         {
             if (_statement.Type != Nodes.BlockStatement)
             {
-                context.LastSyntaxElement = _statement;
+                context.PrepareFor(_statement);
                 context.RunBeforeExecuteStatementChecks(_statement);
             }
 
@@ -110,7 +110,7 @@ namespace Jint.Runtime.Interpreter.Statements
                 var jsValue = JintLiteralExpression.ConvertToJsValue(l);
                 if (jsValue is not null)
                 {
-                    return new Completion(CompletionType.Return, jsValue, null, rs);
+                    return new Completion(CompletionType.Return, jsValue, rs);
                 }
             }
 

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

@@ -112,7 +112,7 @@ namespace Jint.Runtime.Interpreter.Statements
                 v = r.Value ?? Undefined.Instance;
             }
 
-            return new Completion(CompletionType.Normal, v, null, l);
+            return new Completion(CompletionType.Normal, v, l);
         }
 
         private sealed class JintSwitchCase

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintSwitchStatement.cs

@@ -26,7 +26,7 @@ namespace Jint.Runtime.Interpreter.Statements
         {
             var value = _discriminant.GetValue(context).Value;
             var r = _switchBlock.Execute(context, value);
-            if (r.Type == CompletionType.Break && r.Target == _statement.LabelSet?.Name)
+            if (r.Type == CompletionType.Break && context.Target == _statement.LabelSet?.Name)
             {
                 return new Completion(CompletionType.Normal, r.Value, ((JintStatement) this)._statement);
             }

+ 1 - 1
Jint/Runtime/Interpreter/Statements/JintThrowStatement.cs

@@ -22,7 +22,7 @@ namespace Jint.Runtime.Interpreter.Statements
         protected override Completion ExecuteInternal(EvaluationContext context)
         {
             var completion = _argument.GetValue(context);
-            return new Completion(CompletionType.Throw, completion.Value, null, completion._source);
+            return new Completion(CompletionType.Throw, completion.Value, completion._source);
         }
     }
 }

+ 4 - 4
Jint/Runtime/Interpreter/Statements/JintWhileStatement.cs

@@ -37,7 +37,7 @@ namespace Jint.Runtime.Interpreter.Statements
                 var jsValue = _test.GetValue(context).Value;
                 if (!TypeConverter.ToBoolean(jsValue))
                 {
-                    return new Completion(CompletionType.Normal, v, null, _statement);
+                    return new Completion(CompletionType.Normal, v, _statement);
                 }
 
                 var completion = _body.Execute(context);
@@ -47,11 +47,11 @@ namespace Jint.Runtime.Interpreter.Statements
                     v = completion.Value;
                 }
 
-                if (completion.Type != CompletionType.Continue || completion.Target != _labelSetName)
+                if (completion.Type != CompletionType.Continue || context.Target != _labelSetName)
                 {
-                    if (completion.Type == CompletionType.Break && (completion.Target == null || completion.Target == _labelSetName))
+                    if (completion.Type == CompletionType.Break && (context.Target == null || context.Target == _labelSetName))
                     {
-                        return new Completion(CompletionType.Normal, v, null, _statement);
+                        return new Completion(CompletionType.Normal, v, _statement);
                     }
 
                     if (completion.Type != CompletionType.Normal)

+ 2 - 0
Jint/Runtime/Interpreter/Statements/ProbablyBlockStatement.cs

@@ -1,4 +1,5 @@
 using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
 using Esprima.Ast;
 
 namespace Jint.Runtime.Interpreter.Statements;
@@ -7,6 +8,7 @@ namespace Jint.Runtime.Interpreter.Statements;
 /// Helper to remove virtual dispatch from block statements when it's most common target.
 /// This is especially true for things like for statements body
 /// </summary>
+[StructLayout(LayoutKind.Auto)]
 internal readonly struct ProbablyBlockStatement
 {
     private readonly JintStatement  _target;

+ 3 - 3
Jint/Runtime/Modules/CyclicModuleRecord.cs

@@ -256,7 +256,7 @@ public abstract class CyclicModuleRecord : ModuleRecord
         {
             if (_evalError is null)
             {
-                return new Completion(CompletionType.Normal, index, null, default);
+                return new Completion(CompletionType.Normal, index, default);
             }
 
             return _evalError.Value;
@@ -264,7 +264,7 @@ public abstract class CyclicModuleRecord : ModuleRecord
 
         if (Status == ModuleStatus.Evaluating)
         {
-            return new Completion(CompletionType.Normal, index, null, default);
+            return new Completion(CompletionType.Normal, index, default);
         }
 
         if (Status != ModuleStatus.Linked)
@@ -527,7 +527,7 @@ public abstract class CyclicModuleRecord : ModuleRecord
             ExceptionHelper.ThrowInvalidOperationException("Error while evaluating module: Module is in an invalid state");
         }
 
-        module._evalError = new Completion(CompletionType.Throw, error, null, default);
+        module._evalError = new Completion(CompletionType.Throw, error, default);
         module.Status = ModuleStatus.Evaluated;
 
         var asyncParentModules = module._asyncParentModules;

+ 5 - 2
Jint/StrictModeScope.cs

@@ -1,12 +1,15 @@
+using System.Runtime.InteropServices;
+
 namespace Jint
 {
+    [StructLayout(LayoutKind.Auto)]
     public readonly struct StrictModeScope : IDisposable
     {
         private readonly bool _strict;
         private readonly bool _force;
         private readonly ushort _forcedRefCount;
 
-        [ThreadStatic] 
+        [ThreadStatic]
         private static ushort _refCount;
 
         public StrictModeScope(bool strict = true, bool force = false)
@@ -40,7 +43,7 @@ namespace Jint
             if (_force)
             {
                 _refCount = _forcedRefCount;
-            } 
+            }
         }
 
         public static bool IsStrictModeCode => _refCount > 0;