Browse Source

Move expression initialize to expression implementation (#1677)

Marko Lahma 1 year ago
parent
commit
791384f34d

+ 7 - 6
Jint/Runtime/Interpreter/Expressions/BindingPatternAssignmentExpression.cs

@@ -12,20 +12,21 @@ namespace Jint.Runtime.Interpreter.Expressions
     {
     {
         private readonly BindingPattern _pattern;
         private readonly BindingPattern _pattern;
         private JintExpression _right = null!;
         private JintExpression _right = null!;
+        private bool _initialized;
 
 
         public BindingPatternAssignmentExpression(AssignmentExpression expression) : base(expression)
         public BindingPatternAssignmentExpression(AssignmentExpression expression) : base(expression)
         {
         {
             _pattern = (BindingPattern) expression.Left;
             _pattern = (BindingPattern) expression.Left;
-            _initialized = false;
-        }
-
-        protected override void Initialize(EvaluationContext context)
-        {
-            _right = Build(((AssignmentExpression) _expression).Right);
         }
         }
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                _right = Build(((AssignmentExpression) _expression).Right);
+                _initialized = true;
+            }
+
             var rightValue = _right.GetValue(context);
             var rightValue = _right.GetValue(context);
             if (context.IsAbrupt())
             if (context.IsAbrupt())
             {
             {

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintArrayExpression.cs

@@ -8,10 +8,10 @@ namespace Jint.Runtime.Interpreter.Expressions
     {
     {
         private JintExpression?[] _expressions = Array.Empty<JintExpression?>();
         private JintExpression?[] _expressions = Array.Empty<JintExpression?>();
         private bool _hasSpreads;
         private bool _hasSpreads;
+        private bool _initialized;
 
 
         private JintArrayExpression(ArrayExpression expression) : base(expression)
         private JintArrayExpression(ArrayExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
         public static JintExpression Build(ArrayExpression expression)
         public static JintExpression Build(ArrayExpression expression)
@@ -21,7 +21,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 : new JintArrayExpression(expression);
                 : new JintArrayExpression(expression);
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             ref readonly var elements = ref ((ArrayExpression) _expression).Elements;
             ref readonly var elements = ref ((ArrayExpression) _expression).Elements;
             var expressions = _expressions = new JintExpression[((ArrayExpression) _expression).Elements.Count];
             var expressions = _expressions = new JintExpression[((ArrayExpression) _expression).Elements.Count];
@@ -42,6 +42,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+
             var engine = context.Engine;
             var engine = context.Engine;
             var a = engine.Realm.Intrinsics.Array.ArrayCreate(_hasSpreads ? 0 : (uint) _expressions.Length);
             var a = engine.Realm.Intrinsics.Array.ArrayCreate(_hasSpreads ? 0 : (uint) _expressions.Length);
 
 

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintAssignmentExpression.cs

@@ -343,13 +343,13 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             private JintIdentifierExpression? _leftIdentifier;
             private JintIdentifierExpression? _leftIdentifier;
             private bool _evalOrArguments;
             private bool _evalOrArguments;
+            private bool _initialized;
 
 
             public SimpleAssignmentExpression(AssignmentExpression expression) : base(expression)
             public SimpleAssignmentExpression(AssignmentExpression expression) : base(expression)
             {
             {
-                _initialized = false;
             }
             }
 
 
-            protected override void Initialize(EvaluationContext context)
+            private void Initialize()
             {
             {
                 var assignmentExpression = (AssignmentExpression) _expression;
                 var assignmentExpression = (AssignmentExpression) _expression;
                 _left = Build((Expression) assignmentExpression.Left);
                 _left = Build((Expression) assignmentExpression.Left);
@@ -361,6 +361,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                if (!_initialized)
+                {
+                    Initialize();
+                    _initialized = true;
+                }
+
                 object? completion = null;
                 object? completion = null;
                 if (_leftIdentifier != null)
                 if (_leftIdentifier != null)
                 {
                 {

+ 7 - 5
Jint/Runtime/Interpreter/Expressions/JintAwaitExpression.cs

@@ -6,19 +6,21 @@ namespace Jint.Runtime.Interpreter.Expressions;
 internal sealed class JintAwaitExpression : JintExpression
 internal sealed class JintAwaitExpression : JintExpression
 {
 {
     private JintExpression _awaitExpression = null!;
     private JintExpression _awaitExpression = null!;
+    private bool _initialized;
 
 
     public JintAwaitExpression(AwaitExpression expression) : base(expression)
     public JintAwaitExpression(AwaitExpression expression) : base(expression)
     {
     {
         _initialized = false;
         _initialized = false;
     }
     }
 
 
-    protected override void Initialize(EvaluationContext context)
-    {
-        _awaitExpression = Build(((AwaitExpression) _expression).Argument);
-    }
-
     protected override object EvaluateInternal(EvaluationContext context)
     protected override object EvaluateInternal(EvaluationContext context)
     {
     {
+        if (!_initialized)
+        {
+            _awaitExpression = Build(((AwaitExpression) _expression).Argument);
+            _initialized = true;
+        }
+
         var engine = context.Engine;
         var engine = context.Engine;
         var asyncContext = engine.ExecutionContext;
         var asyncContext = engine.ExecutionContext;
 
 

+ 39 - 2
Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs

@@ -20,18 +20,25 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         private JintExpression _left = null!;
         private JintExpression _left = null!;
         private JintExpression _right = null!;
         private JintExpression _right = null!;
+        private bool _initialized;
 
 
         private JintBinaryExpression(BinaryExpression expression) : base(expression)
         private JintBinaryExpression(BinaryExpression expression) : base(expression)
         {
         {
             // TODO check https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
             // TODO check https://tc39.es/ecma262/#sec-applystringornumericbinaryoperator
-            _initialized = false;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private void EnsureInitialized()
         {
         {
+            if (_initialized)
+            {
+                return;
+            }
+
             var expression = (BinaryExpression) _expression;
             var expression = (BinaryExpression) _expression;
             _left = Build(expression.Left);
             _left = Build(expression.Left);
             _right = Build(expression.Right);
             _right = Build(expression.Right);
+            _initialized = true;
         }
         }
 
 
         internal static bool TryOperatorOverloading(
         internal static bool TryOperatorOverloading(
@@ -196,6 +203,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
                 var equal = left == right;
                 var equal = left == right;
@@ -211,6 +220,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
                 return left == right ? JsBoolean.False : JsBoolean.True;
                 return left == right ? JsBoolean.False : JsBoolean.True;
@@ -225,6 +236,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -248,6 +261,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -271,6 +286,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -314,6 +331,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -352,6 +371,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -393,6 +414,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -419,6 +442,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -448,6 +473,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var leftValue = _left.GetValue(context);
                 var leftValue = _left.GetValue(context);
                 var rightValue = _right.GetValue(context);
                 var rightValue = _right.GetValue(context);
 
 
@@ -473,6 +500,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var leftValue = _left.GetValue(context);
                 var leftValue = _left.GetValue(context);
                 var rightValue = _right.GetValue(context);
                 var rightValue = _right.GetValue(context);
                 return leftValue.InstanceofOperator(rightValue) ? JsBoolean.True : JsBoolean.False;
                 return leftValue.InstanceofOperator(rightValue) ? JsBoolean.True : JsBoolean.False;
@@ -487,6 +516,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var leftReference = _left.GetValue(context);
                 var leftReference = _left.GetValue(context);
                 var rightReference = _right.GetValue(context);
                 var rightReference = _right.GetValue(context);
 
 
@@ -612,6 +643,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -640,6 +673,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var left = _left.GetValue(context);
                 var left = _left.GetValue(context);
                 var right = _right.GetValue(context);
                 var right = _right.GetValue(context);
 
 
@@ -754,6 +789,8 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
             protected override object EvaluateInternal(EvaluationContext context)
             protected override object EvaluateInternal(EvaluationContext context)
             {
             {
+                EnsureInitialized();
+
                 var lval = _left.GetValue(context);
                 var lval = _left.GetValue(context);
                 var rval = _right.GetValue(context);
                 var rval = _right.GetValue(context);
 
 

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintCallExpression.cs

@@ -16,13 +16,13 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         private JintExpression _calleeExpression = null!;
         private JintExpression _calleeExpression = null!;
         private bool _hasSpreads;
         private bool _hasSpreads;
+        private bool _initialized;
 
 
         public JintCallExpression(CallExpression expression) : base(expression)
         public JintCallExpression(CallExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize(EvaluationContext context)
         {
         {
             var expression = (CallExpression) _expression;
             var expression = (CallExpression) _expression;
             ref readonly var expressionArguments = ref expression.Arguments;
             ref readonly var expressionArguments = ref expression.Arguments;
@@ -78,6 +78,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize(context);
+                _initialized = true;
+            }
+
             if (!context.Engine._stackGuard.TryEnterOnCurrentStack())
             if (!context.Engine._stackGuard.TryEnterOnCurrentStack())
             {
             {
                 return context.Engine._stackGuard.RunOnEmptyStack(EvaluateInternal, context);
                 return context.Engine._stackGuard.RunOnEmptyStack(EvaluateInternal, context);

+ 0 - 23
Jint/Runtime/Interpreter/Expressions/JintExpression.cs

@@ -10,9 +10,6 @@ namespace Jint.Runtime.Interpreter.Expressions
 {
 {
     internal abstract class JintExpression
     internal abstract class JintExpression
     {
     {
-        // require sub-classes to set to false explicitly to skip virtual call
-        protected bool _initialized = true;
-
         protected internal readonly Expression _expression;
         protected internal readonly Expression _expression;
 
 
         protected JintExpression(Expression expression)
         protected JintExpression(Expression expression)
@@ -43,12 +40,6 @@ namespace Jint.Runtime.Interpreter.Expressions
             var oldSyntaxElement = context.LastSyntaxElement;
             var oldSyntaxElement = context.LastSyntaxElement;
             context.PrepareFor(_expression);
             context.PrepareFor(_expression);
 
 
-            if (!_initialized)
-            {
-                Initialize(context);
-                _initialized = true;
-            }
-
             var result = EvaluateInternal(context);
             var result = EvaluateInternal(context);
 
 
             context.LastSyntaxElement = oldSyntaxElement;
             context.LastSyntaxElement = oldSyntaxElement;
@@ -59,23 +50,9 @@ namespace Jint.Runtime.Interpreter.Expressions
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal object EvaluateWithoutNodeTracking(EvaluationContext context)
         internal object EvaluateWithoutNodeTracking(EvaluationContext context)
         {
         {
-            if (!_initialized)
-            {
-                Initialize(context);
-                _initialized = true;
-            }
-
             return EvaluateInternal(context);
             return EvaluateInternal(context);
         }
         }
 
 
-        /// <summary>
-        /// Opportunity to build one-time structures and caching based on lexical context.
-        /// </summary>
-        /// <param name="context"></param>
-        protected virtual void Initialize(EvaluationContext context)
-        {
-        }
-
         protected abstract object EvaluateInternal(EvaluationContext context);
         protected abstract object EvaluateInternal(EvaluationContext context);
 
 
         /// <summary>
         /// <summary>

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintIdentifierExpression.cs

@@ -10,10 +10,10 @@ namespace Jint.Runtime.Interpreter.Expressions;
 internal sealed class JintIdentifierExpression : JintExpression
 internal sealed class JintIdentifierExpression : JintExpression
 {
 {
     private EnvironmentRecord.BindingName _identifier = null!;
     private EnvironmentRecord.BindingName _identifier = null!;
+    private bool _initialized;
 
 
     public JintIdentifierExpression(Identifier expression) : base(expression)
     public JintIdentifierExpression(Identifier expression) : base(expression)
     {
     {
-        _initialized = false;
     }
     }
 
 
     public EnvironmentRecord.BindingName Identifier
     public EnvironmentRecord.BindingName Identifier
@@ -25,7 +25,7 @@ internal sealed class JintIdentifierExpression : JintExpression
         }
         }
     }
     }
 
 
-    protected override void Initialize(EvaluationContext context)
+    private void Initialize()
     {
     {
         EnsureIdentifier();
         EnsureIdentifier();
     }
     }
@@ -47,6 +47,12 @@ internal sealed class JintIdentifierExpression : JintExpression
 
 
     protected override object EvaluateInternal(EvaluationContext context)
     protected override object EvaluateInternal(EvaluationContext context)
     {
     {
+        if (!_initialized)
+        {
+            Initialize();
+            _initialized = true;
+        }
+
         var engine = context.Engine;
         var engine = context.Engine;
         var env = engine.ExecutionContext.LexicalEnvironment;
         var env = engine.ExecutionContext.LexicalEnvironment;
         var strict = StrictModeScope.IsStrictModeCode;
         var strict = StrictModeScope.IsStrictModeCode;

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintImportExpression.cs

@@ -7,14 +7,14 @@ namespace Jint.Runtime.Interpreter.Expressions;
 internal sealed class JintImportExpression : JintExpression
 internal sealed class JintImportExpression : JintExpression
 {
 {
     private JintExpression _importExpression;
     private JintExpression _importExpression;
+    private bool _initialized;
 
 
     public JintImportExpression(ImportExpression expression) : base(expression)
     public JintImportExpression(ImportExpression expression) : base(expression)
     {
     {
-        _initialized = false;
         _importExpression = null!;
         _importExpression = null!;
     }
     }
 
 
-    protected override void Initialize(EvaluationContext context)
+    private void Initialize(EvaluationContext context)
     {
     {
         var expression = ((ImportExpression) _expression).Source;
         var expression = ((ImportExpression) _expression).Source;
         _importExpression = Build(expression);
         _importExpression = Build(expression);
@@ -25,6 +25,12 @@ internal sealed class JintImportExpression : JintExpression
     /// </summary>
     /// </summary>
     protected override object EvaluateInternal(EvaluationContext context)
     protected override object EvaluateInternal(EvaluationContext context)
     {
     {
+        if (!_initialized)
+        {
+            Initialize(context);
+            _initialized = true;
+        }
+
         var referencingScriptOrModule = context.Engine.GetActiveScriptOrModule();
         var referencingScriptOrModule = context.Engine.GetActiveScriptOrModule();
         var argRef = _importExpression.Evaluate(context);
         var argRef = _importExpression.Evaluate(context);
         var specifier = context.Engine.GetValue(argRef); //.UnwrapIfPromise();
         var specifier = context.Engine.GetValue(argRef); //.UnwrapIfPromise();

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintLogicalAndExpression.cs

@@ -7,13 +7,13 @@ namespace Jint.Runtime.Interpreter.Expressions
     {
     {
         private JintExpression _left = null!;
         private JintExpression _left = null!;
         private JintExpression _right = null!;
         private JintExpression _right = null!;
+        private bool _initialized;
 
 
         public JintLogicalAndExpression(BinaryExpression expression) : base(expression)
         public JintLogicalAndExpression(BinaryExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             var expression = (BinaryExpression) _expression;
             var expression = (BinaryExpression) _expression;
             _left = Build(expression.Left);
             _left = Build(expression.Left);
@@ -22,6 +22,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+
             var left = _left.GetValue(context);
             var left = _left.GetValue(context);
 
 
             if (left is JsBoolean b && !b._value)
             if (left is JsBoolean b && !b._value)

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintMemberExpression.cs

@@ -14,14 +14,14 @@ namespace Jint.Runtime.Interpreter.Expressions
         private JintExpression _objectExpression = null!;
         private JintExpression _objectExpression = null!;
         private JintExpression? _propertyExpression;
         private JintExpression? _propertyExpression;
         private JsValue? _determinedProperty;
         private JsValue? _determinedProperty;
+        private bool _initialized;
 
 
         public JintMemberExpression(MemberExpression expression) : base(expression)
         public JintMemberExpression(MemberExpression expression) : base(expression)
         {
         {
-            _initialized = false;
             _memberExpression = (MemberExpression) _expression;
             _memberExpression = (MemberExpression) _expression;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             _objectExpression = Build(_memberExpression.Object);
             _objectExpression = Build(_memberExpression.Object);
 
 
@@ -45,6 +45,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+
             JsValue? actualThis = null;
             JsValue? actualThis = null;
             string? baseReferenceName = null;
             string? baseReferenceName = null;
             JsValue? baseValue = null;
             JsValue? baseValue = null;

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintNewExpression.cs

@@ -8,13 +8,13 @@ namespace Jint.Runtime.Interpreter.Expressions
         private JintExpression _calleeExpression = null!;
         private JintExpression _calleeExpression = null!;
         private JintExpression[] _jintArguments = Array.Empty<JintExpression>();
         private JintExpression[] _jintArguments = Array.Empty<JintExpression>();
         private bool _hasSpreads;
         private bool _hasSpreads;
+        private bool _initialized;
 
 
         public JintNewExpression(NewExpression expression) : base(expression)
         public JintNewExpression(NewExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             var expression = (NewExpression) _expression;
             var expression = (NewExpression) _expression;
             _calleeExpression = Build(expression.Callee);
             _calleeExpression = Build(expression.Callee);
@@ -35,6 +35,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+
             var engine = context.Engine;
             var engine = context.Engine;
 
 
             // todo: optimize by defining a common abstract class or interface
             // todo: optimize by defining a common abstract class or interface

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintObjectExpression.cs

@@ -18,6 +18,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         // check if we can do a shortcut when all are object properties
         // check if we can do a shortcut when all are object properties
         // and don't require duplicate checking
         // and don't require duplicate checking
         private bool _canBuildFast;
         private bool _canBuildFast;
+        private bool _initialized;
 
 
         private sealed class ObjectProperty
         private sealed class ObjectProperty
         {
         {
@@ -54,7 +55,6 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         private JintObjectExpression(ObjectExpression expression) : base(expression)
         private JintObjectExpression(ObjectExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
         public static JintExpression Build(ObjectExpression expression)
         public static JintExpression Build(ObjectExpression expression)
@@ -64,7 +64,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 : new JintObjectExpression(expression);
                 : new JintObjectExpression(expression);
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             _canBuildFast = true;
             _canBuildFast = true;
             var expression = (ObjectExpression) _expression;
             var expression = (ObjectExpression) _expression;
@@ -120,6 +120,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+
             return _canBuildFast
             return _canBuildFast
                 ? BuildObjectFast(context)
                 ? BuildObjectFast(context)
                 : BuildObjectNormal(context);
                 : BuildObjectNormal(context);

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintSequenceExpression.cs

@@ -6,13 +6,13 @@ namespace Jint.Runtime.Interpreter.Expressions
     internal sealed class JintSequenceExpression : JintExpression
     internal sealed class JintSequenceExpression : JintExpression
     {
     {
         private JintExpression[] _expressions = Array.Empty<JintExpression>();
         private JintExpression[] _expressions = Array.Empty<JintExpression>();
+        private bool _initialized;
 
 
         public JintSequenceExpression(SequenceExpression expression) : base(expression)
         public JintSequenceExpression(SequenceExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             var expression = (SequenceExpression) _expression;
             var expression = (SequenceExpression) _expression;
             ref readonly var expressions = ref expression.Expressions;
             ref readonly var expressions = ref expression.Expressions;
@@ -27,6 +27,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+            
             var result = JsValue.Undefined;
             var result = JsValue.Undefined;
             foreach (var expression in _expressions)
             foreach (var expression in _expressions)
             {
             {

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintTaggedTemplateExpression.cs

@@ -12,13 +12,13 @@ internal sealed class JintTaggedTemplateExpression : JintExpression
 
 
     private JintExpression _tagIdentifier = null!;
     private JintExpression _tagIdentifier = null!;
     private JintTemplateLiteralExpression _quasi = null!;
     private JintTemplateLiteralExpression _quasi = null!;
+    private bool _initialized;
 
 
     public JintTaggedTemplateExpression(TaggedTemplateExpression expression) : base(expression)
     public JintTaggedTemplateExpression(TaggedTemplateExpression expression) : base(expression)
     {
     {
-        _initialized = false;
     }
     }
 
 
-    protected override void Initialize(EvaluationContext context)
+    private void Initialize()
     {
     {
         var taggedTemplateExpression = (TaggedTemplateExpression) _expression;
         var taggedTemplateExpression = (TaggedTemplateExpression) _expression;
         _tagIdentifier = Build(taggedTemplateExpression.Tag);
         _tagIdentifier = Build(taggedTemplateExpression.Tag);
@@ -28,6 +28,12 @@ internal sealed class JintTaggedTemplateExpression : JintExpression
 
 
     protected override object EvaluateInternal(EvaluationContext context)
     protected override object EvaluateInternal(EvaluationContext context)
     {
     {
+        if (!_initialized)
+        {
+            Initialize();
+            _initialized = true;
+        }
+
         var engine = context.Engine;
         var engine = context.Engine;
 
 
         var identifier = _tagIdentifier.Evaluate(context);
         var identifier = _tagIdentifier.Evaluate(context);

+ 9 - 8
Jint/Runtime/Interpreter/Expressions/JintTemplateLiteralExpression.cs

@@ -8,14 +8,14 @@ internal sealed class JintTemplateLiteralExpression : JintExpression
 {
 {
     internal readonly TemplateLiteral _templateLiteralExpression;
     internal readonly TemplateLiteral _templateLiteralExpression;
     internal JintExpression[] _expressions = Array.Empty<JintExpression>();
     internal JintExpression[] _expressions = Array.Empty<JintExpression>();
+    private bool _initialized;
 
 
     public JintTemplateLiteralExpression(TemplateLiteral expression) : base(expression)
     public JintTemplateLiteralExpression(TemplateLiteral expression) : base(expression)
     {
     {
         _templateLiteralExpression = expression;
         _templateLiteralExpression = expression;
-        _initialized = false;
     }
     }
 
 
-    protected override void Initialize(EvaluationContext context)
+    private void Initialize()
     {
     {
         DoInitialize();
         DoInitialize();
     }
     }
@@ -32,8 +32,14 @@ internal sealed class JintTemplateLiteralExpression : JintExpression
         _initialized = true;
         _initialized = true;
     }
     }
 
 
-    private JsString BuildString(EvaluationContext context)
+    protected override object EvaluateInternal(EvaluationContext context)
     {
     {
+        if (!_initialized)
+        {
+            Initialize();
+            _initialized = true;
+        }
+
         using var sb = StringBuilderPool.Rent();
         using var sb = StringBuilderPool.Rent();
         ref readonly var elements = ref _templateLiteralExpression.Quasis;
         ref readonly var elements = ref _templateLiteralExpression.Quasis;
         for (var i = 0; i < elements.Count; i++)
         for (var i = 0; i < elements.Count; i++)
@@ -49,9 +55,4 @@ internal sealed class JintTemplateLiteralExpression : JintExpression
 
 
         return JsString.Create(sb.ToString());
         return JsString.Create(sb.ToString());
     }
     }
-
-    protected override object EvaluateInternal(EvaluationContext context)
-    {
-        return BuildString(context);
-    }
 }
 }

+ 8 - 2
Jint/Runtime/Interpreter/Expressions/JintUpdateExpression.cs

@@ -13,13 +13,13 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         private JintIdentifierExpression? _leftIdentifier;
         private JintIdentifierExpression? _leftIdentifier;
         private bool _evalOrArguments;
         private bool _evalOrArguments;
+        private bool _initialized;
 
 
         public JintUpdateExpression(UpdateExpression expression) : base(expression)
         public JintUpdateExpression(UpdateExpression expression) : base(expression)
         {
         {
-            _initialized = false;
         }
         }
 
 
-        protected override void Initialize(EvaluationContext context)
+        private void Initialize()
         {
         {
             var expression = (UpdateExpression) _expression;
             var expression = (UpdateExpression) _expression;
             _prefix = expression.Prefix;
             _prefix = expression.Prefix;
@@ -43,6 +43,12 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
         protected override object EvaluateInternal(EvaluationContext context)
         protected override object EvaluateInternal(EvaluationContext context)
         {
         {
+            if (!_initialized)
+            {
+                Initialize();
+                _initialized = true;
+            }
+
             var fastResult = _leftIdentifier != null
             var fastResult = _leftIdentifier != null
                 ? UpdateIdentifier(context)
                 ? UpdateIdentifier(context)
                 : null;
                 : null;