Переглянути джерело

Add Engine.Construct method (#1047)

* add Engine.Construct(string constructorName, params JsValue[] arguments) method
* add overload Engine.Construct(JsValue, params JsValue[] arguments)
* internalize IConstructor
* internalize ICallable
Marko Lahma 3 роки тому
батько
коміт
ceee6b2ccb
38 змінених файлів з 182 додано та 110 видалено
  1. 24 1
      Jint.Tests/Runtime/FunctionTests.cs
  2. 2 2
      Jint.Tests/Runtime/InteropTests.MemberAccess.cs
  3. 4 6
      Jint.Tests/Runtime/InteropTests.cs
  4. 40 13
      Jint/Engine.cs
  5. 13 14
      Jint/JsValueExtensions.cs
  6. 3 1
      Jint/Native/Array/ArrayConstructor.cs
  7. 2 2
      Jint/Native/ArrayBuffer/ArrayBufferConstructor.cs
  8. 2 2
      Jint/Native/BigInt/BigIntConstructor.cs
  9. 1 1
      Jint/Native/Boolean/BooleanConstructor.cs
  10. 2 2
      Jint/Native/DataView/DataViewConstructor.cs
  11. 3 1
      Jint/Native/Date/DateConstructor.cs
  12. 3 1
      Jint/Native/Error/ErrorConstructor.cs
  13. 2 2
      Jint/Native/Function/BindFunctionInstance.cs
  14. 3 1
      Jint/Native/Function/FunctionConstructor.cs
  15. 2 2
      Jint/Native/Function/ScriptFunctionInstance.cs
  16. 2 2
      Jint/Native/ICallable.cs
  17. 1 1
      Jint/Native/IConstructor.cs
  18. 2 2
      Jint/Native/Map/MapConstructor.cs
  19. 1 1
      Jint/Native/Number/NumberConstructor.cs
  20. 3 1
      Jint/Native/Object/ObjectConstructor.cs
  21. 2 2
      Jint/Native/Object/ObjectInstance.cs
  22. 2 2
      Jint/Native/Promise/PromiseConstructor.cs
  23. 20 12
      Jint/Native/Proxy/ProxyConstructor.cs
  24. 4 4
      Jint/Native/Proxy/ProxyInstance.cs
  25. 2 2
      Jint/Native/Reflect/ReflectInstance.cs
  26. 3 1
      Jint/Native/RegExp/RegExpConstructor.cs
  27. 2 2
      Jint/Native/Set/SetConstructor.cs
  28. 1 1
      Jint/Native/String/StringConstructor.cs
  29. 1 1
      Jint/Native/Symbol/SymbolConstructor.cs
  30. 2 2
      Jint/Native/TypedArray/IntrinsicTypedArrayConstructor.cs
  31. 4 2
      Jint/Native/TypedArray/TypedArrayConstructor.cs
  32. 2 2
      Jint/Native/WeakMap/WeakMapConstructor.cs
  33. 2 2
      Jint/Native/WeakSet/WeakSetConstructor.cs
  34. 4 4
      Jint/Runtime/Host.cs
  35. 2 2
      Jint/Runtime/Interop/NamespaceReference.cs
  36. 4 2
      Jint/Runtime/Interop/TypeReference.cs
  37. 2 2
      Jint/Runtime/Interpreter/Expressions/JintNewExpression.cs
  38. 8 7
      Jint/Runtime/Modules/JsModule.cs

+ 24 - 1
Jint.Tests/Runtime/FunctionTests.cs

@@ -1,5 +1,6 @@
 using System;
 using Jint.Native;
+using Jint.Native.Array;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
 using Xunit;
@@ -101,5 +102,27 @@ assertEqual(booleanCount, 1);
             var engine = new Engine();
             Assert.True(engine.Evaluate("(()=>{}).hasOwnProperty('name')").AsBoolean());
         }
+
+        [Fact]
+        public void CanInvokeConstructorsFromEngine()
+        {
+            var engine = new Engine();
+
+            engine.Evaluate("class TestClass { constructor(a, b) { this.a = a; this.b = b; }}");
+            engine.Evaluate("function TestFunction(a, b) { this.a = a; this.b = b; }");
+
+            var instanceFromClass = engine.Construct("TestClass", "abc", 123).AsObject();
+            Assert.Equal("abc", instanceFromClass.Get("a"));
+            Assert.Equal(123, instanceFromClass.Get("b"));
+
+            var instanceFromFunction = engine.Construct("TestFunction", "abc", 123).AsObject();
+            Assert.Equal("abc", instanceFromFunction.Get("a"));
+            Assert.Equal(123, instanceFromFunction.Get("b"));
+
+            var arrayInstance = (ArrayInstance) engine.Construct("Array", "abc", 123).AsObject();
+            Assert.Equal((uint) 2, arrayInstance.Length);
+            Assert.Equal("abc", arrayInstance[0]);
+            Assert.Equal(123, arrayInstance[1]);
+        }
     }
-}
+}

+ 2 - 2
Jint.Tests/Runtime/InteropTests.MemberAccess.cs

@@ -84,7 +84,7 @@ namespace Jint.Tests.Runtime
                 options.Interop.AllowSystemReflection = true;
             });
             engine.SetValue("m", new HiddenMembers());
-            Assert.True(engine.Evaluate("m.GetType").IsCallable());
+            Assert.True(engine.Evaluate("m.GetType").IsCallable);
 
             // reflection could bypass some safeguards
             Assert.Equal("Method1", engine.Evaluate("m.GetType().GetMethod('Method1').Invoke(m, [])").AsString());
@@ -130,4 +130,4 @@ namespace Jint.Tests.Runtime
             public static string Hidden(string message) => message;
         }
     }
-}
+}

+ 4 - 6
Jint.Tests/Runtime/InteropTests.cs

@@ -2681,12 +2681,10 @@ namespace Jint.Tests.Runtime
             engine.Evaluate("var f = () => true;");
 
             var result = engine.GetValue("f");
-            Assert.True(result.IsCallable());
+            Assert.True(result.IsCallable);
 
-            var callable = result.AsCallable();
-            Assert.True(callable.Call(JsValue.Undefined, Array.Empty<JsValue>()).AsBoolean());
-
-            Assert.True(callable.Call().AsBoolean());
+            Assert.True(result.Call(Array.Empty<JsValue>()).AsBoolean());
+            Assert.True(result.Call().AsBoolean());
         }
 
         [Fact]
@@ -2756,4 +2754,4 @@ namespace Jint.Tests.Runtime
             public int AnyProperty => throw new NotSupportedException("NOT SUPPORTED");
         }
     }
-}
+}

+ 40 - 13
Jint/Engine.cs

@@ -555,15 +555,6 @@ namespace Jint
             }
         }
 
-        /// <summary>
-        /// http://www.ecma-international.org/ecma-262/6.0/#sec-initializereferencedbinding
-        /// </summary>
-        public void InitializeReferenceBinding(Reference reference, JsValue value)
-        {
-            var baseValue = (EnvironmentRecord) reference.GetBase();
-            baseValue.InitializeBinding(TypeConverter.ToString(reference.GetReferencedName()), value);
-        }
-
         /// <summary>
         /// Invoke the current value as function.
         /// </summary>
@@ -1236,7 +1227,43 @@ namespace Jint
             return callable.Call(thisObject, arguments);
         }
 
-        internal JsValue Construct(IConstructor constructor, JsValue[] arguments, JsValue newTarget,
+        /// <summary>
+        /// Calls the named constructor and returns the resulting object.
+        /// </summary>
+        /// <param name="constructorName">The name of the constructor to call.</param>
+        /// <param name="arguments">The arguments of the constructor call.</param>
+        /// <returns>The value returned by the constructor call.</returns>
+        public ObjectInstance Construct(string constructorName, params JsValue[] arguments)
+        {
+            var constructor = Evaluate(constructorName);
+            return Construct(constructor, arguments);
+        }
+
+        /// <summary>
+        /// Calls the constructor and returns the resulting object.
+        /// </summary>
+        /// <param name="constructor">The name of the constructor to call.</param>
+        /// <param name="arguments">The arguments of the constructor call.</param>
+        /// <returns>The value returned by the constructor call.</returns>
+        public ObjectInstance Construct(JsValue constructor, params JsValue[] arguments)
+        {
+            ObjectInstance Callback()
+            {
+                if (!constructor.IsConstructor)
+                {
+                    ExceptionHelper.ThrowArgumentException(constructor + " is not a constructor");
+                }
+
+                return Construct(constructor, arguments, constructor, null);
+            }
+
+            return ExecuteWithConstraints(Options.Strict, Callback);
+        }
+
+        internal ObjectInstance Construct(
+            JsValue constructor,
+            JsValue[] arguments,
+            JsValue newTarget,
             JintExpression expression)
         {
             if (constructor is FunctionInstance functionInstance)
@@ -1244,7 +1271,7 @@ namespace Jint
                 return Construct(functionInstance, arguments, newTarget, expression);
             }
 
-            return constructor.Construct(arguments, newTarget);
+            return ((IConstructor) constructor).Construct(arguments, newTarget);
         }
 
         internal JsValue Call(
@@ -1270,7 +1297,7 @@ namespace Jint
             return result;
         }
 
-        internal JsValue Construct(
+        private ObjectInstance Construct(
             FunctionInstance functionInstance,
             JsValue[] arguments,
             JsValue newTarget,
@@ -1293,4 +1320,4 @@ namespace Jint
             return result;
         }
     }
-}
+}

+ 13 - 14
Jint/JsValueExtensions.cs

@@ -6,6 +6,7 @@ using Esprima;
 using Jint.Native;
 using Jint.Native.Array;
 using Jint.Native.Date;
+using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Native.Promise;
 using Jint.Native.RegExp;
@@ -418,28 +419,26 @@ namespace Jint
 
         [Pure]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static bool IsCallable(this JsValue value)
+        public static FunctionInstance AsFunctionInstance(this JsValue value)
         {
-            return value.IsCallable;
-        }
-
-        [Pure]
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static ICallable AsCallable(this JsValue value)
-        {
-            if (!value.IsCallable())
+            if (value is not FunctionInstance instance)
             {
-                ThrowWrongTypeException(value, "Callable");
+                ThrowWrongTypeException(value, "FunctionInstance");
+                return null;
             }
 
-            return value as ICallable;
+            return instance;
         }
 
         [Pure]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static JsValue Call(this ICallable value, params JsValue[] arguments)
+        public static JsValue Call(this JsValue value, params JsValue[] arguments)
         {
-            return value.Call(JsValue.Undefined, arguments);
+            if (!value.IsCallable)
+            {
+                ExceptionHelper.ThrowArgumentException(value + " is not callable");
+            }
+            return ((ICallable) value).Call(JsValue.Undefined, arguments);
         }
 
         /// <summary>
@@ -494,4 +493,4 @@ namespace Jint
             }
         }
     }
-}
+}

+ 3 - 1
Jint/Native/Array/ArrayConstructor.cs

@@ -274,7 +274,9 @@ namespace Jint.Native.Array
             return Construct(arguments, this);
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
+        internal ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {

+ 2 - 2
Jint/Native/ArrayBuffer/ArrayBufferConstructor.cs

@@ -71,7 +71,7 @@ namespace Jint.Native.ArrayBuffer
             return Undefined;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -93,4 +93,4 @@ namespace Jint.Native.ArrayBuffer
             return obj;
         }
     }
-}
+}

+ 2 - 2
Jint/Native/BigInt/BigIntConstructor.cs

@@ -101,7 +101,7 @@ public sealed class BigIntConstructor : FunctionInstance, IConstructor
     /// <summary>
     /// https://tc39.es/ecma262/#sec-bigint-constructor-number-value
     /// </summary>
-    public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
     {
         var value = arguments.Length > 0
             ? JsBigInt.Create(arguments[0].ToBigInteger(_engine))
@@ -131,4 +131,4 @@ public sealed class BigIntConstructor : FunctionInstance, IConstructor
 
         return instance;
     }
-}
+}

+ 1 - 1
Jint/Native/Boolean/BooleanConstructor.cs

@@ -37,7 +37,7 @@ namespace Jint.Native.Boolean
         /// <summary>
         /// https://tc39.es/ecma262/#sec-boolean-constructor-boolean-value
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             var b = TypeConverter.ToBoolean(arguments.At(0))
                 ? JsBoolean.True

+ 2 - 2
Jint/Native/DataView/DataViewConstructor.cs

@@ -34,7 +34,7 @@ namespace Jint.Native.DataView
             return Undefined;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -94,4 +94,4 @@ namespace Jint.Native.DataView
             return o;
         }
     }
-}
+}

+ 3 - 1
Jint/Native/Date/DateConstructor.cs

@@ -136,10 +136,12 @@ namespace Jint.Native.Date
             return PrototypeObject.ToString(Construct(Arguments.Empty, thisObject), Arguments.Empty);
         }
 
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
         /// <summary>
         /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.3
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
             double dv;
             if (arguments.Length == 0 || newTarget.IsUndefined())

+ 3 - 1
Jint/Native/Error/ErrorConstructor.cs

@@ -36,7 +36,9 @@ namespace Jint.Native.Error
             return Construct(arguments, this);
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
+        private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
             var o = OrdinaryCreateFromConstructor(
                 newTarget,

+ 2 - 2
Jint/Native/Function/BindFunctionInstance.cs

@@ -40,7 +40,7 @@ namespace Jint.Native.Function
         /// </summary>
         public JsValue[] BoundArguments { get; }
 
-        public JsValue Call(JsValue thisObject, JsValue[] arguments)
+        JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
         {
             var f = BoundTargetFunction as FunctionInstance;
             if (f is null)
@@ -55,7 +55,7 @@ namespace Jint.Native.Function
             return value;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             var target = BoundTargetFunction as IConstructor;
             if (target is null)

+ 3 - 1
Jint/Native/Function/FunctionConstructor.cs

@@ -33,10 +33,12 @@ namespace Jint.Native.Function
             return Construct(arguments, thisObject);
         }
 
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
         /// <summary>
         /// https://tc39.es/ecma262/#sec-createdynamicfunction
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
             var argCount = arguments.Length;
             string p = "";

+ 2 - 2
Jint/Native/Function/ScriptFunctionInstance.cs

@@ -109,7 +109,7 @@ namespace Jint.Native.Function
         /// <summary>
         /// https://tc39.es/ecma262/#sec-ecmascript-function-objects-construct-argumentslist-newtarget
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             var callerContext = _engine.ExecutionContext;
             var kind = _constructorKind;
@@ -268,4 +268,4 @@ namespace Jint.Native.Function
             }
         }
     }
-}
+}

+ 2 - 2
Jint/Native/ICallable.cs

@@ -1,7 +1,7 @@
 namespace Jint.Native
 {
-    public interface ICallable
+    internal interface ICallable
     {
         JsValue Call(JsValue thisObject, JsValue[] arguments);
     }
-}
+}

+ 1 - 1
Jint/Native/IConstructor.cs

@@ -2,7 +2,7 @@
 
 namespace Jint.Native
 {
-    public interface IConstructor
+    internal interface IConstructor
     {
         ObjectInstance Construct(JsValue[] arguments, JsValue newTarget);
     }

+ 2 - 2
Jint/Native/Map/MapConstructor.cs

@@ -51,7 +51,7 @@ namespace Jint.Native.Map
         /// <summary>
         /// https://tc39.es/ecma262/#sec-map-iterable
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -73,4 +73,4 @@ namespace Jint.Native.Map
             return map;
         }
     }
-}
+}

+ 1 - 1
Jint/Native/Number/NumberConstructor.cs

@@ -121,7 +121,7 @@ namespace Jint.Native.Number
         /// <summary>
         /// https://tc39.es/ecma262/#sec-number-constructor-number-value
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             var n = ProcessFirstParameter(arguments);
 

+ 3 - 1
Jint/Native/Object/ObjectConstructor.cs

@@ -142,7 +142,9 @@ namespace Jint.Native.Object
             return Construct(arguments, this);
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
+        private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (!ReferenceEquals(this, newTarget) && !newTarget.IsUndefined())
             {

+ 2 - 2
Jint/Native/Object/ObjectInstance.cs

@@ -1076,7 +1076,7 @@ namespace Jint.Native.Object
             return false;
         }
 
-        protected ICallable GetCallable(JsValue source)
+        internal ICallable GetCallable(JsValue source)
         {
             if (source is ICallable callable)
             {
@@ -1358,4 +1358,4 @@ namespace Jint.Native.Object
             return TypeConverter.ToString(this);
         }
     }
-}
+}

+ 2 - 2
Jint/Native/Promise/PromiseConstructor.cs

@@ -71,7 +71,7 @@ namespace Jint.Native.Promise
             return null;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -499,4 +499,4 @@ namespace Jint.Native.Promise
             return new PromiseCapability(instance, resolve, reject, rejectArg);
         }
     }
-}
+}

+ 20 - 12
Jint/Native/Proxy/ProxyConstructor.cs

@@ -7,6 +7,9 @@ using Jint.Runtime.Interop;
 
 namespace Jint.Native.Proxy
 {
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-proxy-constructor
+    /// </summary>
     public sealed class ProxyConstructor : FunctionInstance, IConstructor
     {
         private static readonly JsString _name = new JsString("Proxy");
@@ -21,16 +24,27 @@ namespace Jint.Native.Proxy
             _length = new PropertyDescriptor(2, PropertyFlag.Configurable);
         }
 
+        protected override void Initialize()
+        {
+            var properties = new PropertyDictionary(1, checkExistingKeys: false)
+            {
+                ["revocable"] = new PropertyDescriptor(new ClrFunctionInstance(_engine, "revocable", Revocable, 2, PropertyFlag.Configurable), true, true, true)
+            };
+            SetProperties(properties);
+        }
+
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             ExceptionHelper.ThrowTypeError(_realm, "Constructor Proxy requires 'new'");
             return null;
         }
 
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments);
+
         /// <summary>
         /// https://www.ecma-international.org/ecma-262/6.0/index.html#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        private ObjectInstance Construct(JsValue[] arguments)
         {
             var target = arguments.At(0);
             var handler = arguments.At(1);
@@ -42,20 +56,14 @@ namespace Jint.Native.Proxy
             return Construct(target.AsObject(), handler.AsObject());
         }
 
-        protected override void Initialize()
-        {
-            var properties = new PropertyDictionary(1, checkExistingKeys: false)
-            {
-                ["revocable"] = new PropertyDescriptor(new ClrFunctionInstance(_engine, "revocable", Revocable, 2, PropertyFlag.Configurable), true, true, true)
-            };
-            SetProperties(properties);
-        }
-
         protected internal override ObjectInstance GetPrototypeOf()
         {
             return _realm.Intrinsics.Function.Prototype;
         }
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-proxy-target-handler
+        /// </summary>
         public ProxyInstance Construct(ObjectInstance target, ObjectInstance handler)
         {
             if (target is ProxyInstance targetProxy && targetProxy._handler is null)
@@ -72,9 +80,9 @@ namespace Jint.Native.Proxy
 
         private JsValue Revocable(JsValue thisObject, JsValue[] arguments)
         {
-            var p = Construct(arguments, thisObject);
+            var p = Construct(arguments);
 
-            System.Func<JsValue, JsValue[], JsValue> revoke = (JsValue thisObject, JsValue[] arguments) =>
+            System.Func<JsValue, JsValue[], JsValue> revoke = (thisObject, arguments) =>
             {
                 var proxy = (ProxyInstance) p;
                 proxy._handler = null;

+ 4 - 4
Jint/Native/Proxy/ProxyInstance.cs

@@ -6,7 +6,7 @@ using Jint.Runtime.Descriptors;
 
 namespace Jint.Native.Proxy
 {
-    public class ProxyInstance : ObjectInstance, IConstructor, ICallable
+    public sealed class ProxyInstance : ObjectInstance, IConstructor, ICallable
     {
         internal ObjectInstance _target;
         internal ObjectInstance _handler;
@@ -41,7 +41,7 @@ namespace Jint.Native.Proxy
         /// <summary>
         /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-call-thisargument-argumentslist
         /// </summary>
-        public JsValue Call(JsValue thisObject, JsValue[] arguments)
+        JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
         {
             var jsValues = new[] { _target, thisObject, _engine.Realm.Intrinsics.Array.ConstructFast(arguments) };
             if (TryCallHandler(TrapApply, jsValues, out var result))
@@ -61,7 +61,7 @@ namespace Jint.Native.Proxy
         /// <summary>
         /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-construct-argumentslist-newtarget
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             var argArray = _engine.Realm.Intrinsics.Array.Construct(arguments, _engine.Realm.Intrinsics.Array);
 
@@ -537,4 +537,4 @@ namespace Jint.Native.Proxy
 
         public override string ToString() => "function () { [native code] }";
     }
-}
+}

+ 2 - 2
Jint/Native/Reflect/ReflectInstance.cs

@@ -66,7 +66,7 @@ namespace Jint.Native.Reflect
 
             // 3. Perform PrepareForTailCall().
 
-            return target.AsCallable().Call(thisArgument, args);
+            return ((ICallable) target).Call(thisArgument, args);
         }
 
         private JsValue Construct(JsValue thisObject, JsValue[] arguments)
@@ -227,4 +227,4 @@ namespace Jint.Native.Reflect
             return o.SetPrototypeOf(prototype);
         }
     }
-}
+}

+ 3 - 1
Jint/Native/RegExp/RegExpConstructor.cs

@@ -47,10 +47,12 @@ namespace Jint.Native.RegExp
             return Construct(arguments, this);
         }
 
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
         /// <summary>
         /// https://tc39.es/ecma262/#sec-regexp-pattern-flags
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
         {
             var pattern = arguments.At(0);
             var flags = arguments.At(1);

+ 2 - 2
Jint/Native/Set/SetConstructor.cs

@@ -51,7 +51,7 @@ namespace Jint.Native.Set
         /// <summary>
         /// https://tc39.es/ecma262/#sec-set-iterable
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -98,4 +98,4 @@ namespace Jint.Native.Set
             return set;
         }
     }
-}
+}

+ 1 - 1
Jint/Native/String/StringConstructor.cs

@@ -144,7 +144,7 @@ namespace Jint.Native.String
         /// <summary>
         /// https://tc39.es/ecma262/#sec-string-constructor-string-value
         /// </summary>
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             JsString s;
             if (arguments.Length == 0)

+ 1 - 1
Jint/Native/Symbol/SymbolConstructor.cs

@@ -99,7 +99,7 @@ namespace Jint.Native.Symbol
             return Undefined;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             ExceptionHelper.ThrowTypeError(_realm);
             return null;

+ 2 - 2
Jint/Native/TypedArray/IntrinsicTypedArrayConstructor.cs

@@ -189,10 +189,10 @@ namespace Jint.Native.TypedArray
             return Undefined;
         }
 
-        public ObjectInstance Construct(JsValue[] args, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] args, JsValue newTarget)
         {
             ExceptionHelper.ThrowTypeError(_realm, "Abstract class TypedArray not directly constructable");
             return null;
         }
     }
-}
+}

+ 4 - 2
Jint/Native/TypedArray/TypedArrayConstructor.cs

@@ -50,7 +50,9 @@ namespace Jint.Native.TypedArray
             return Undefined;
         }
 
-        public ObjectInstance Construct(JsValue[] args, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] args, JsValue newTarget) => Construct(args, newTarget);
+
+        internal ObjectInstance Construct(JsValue[] args, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -303,4 +305,4 @@ namespace Jint.Native.TypedArray
             }
         }
     }
-}
+}

+ 2 - 2
Jint/Native/WeakMap/WeakMapConstructor.cs

@@ -31,7 +31,7 @@ namespace Jint.Native.WeakMap
             return null;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -53,4 +53,4 @@ namespace Jint.Native.WeakMap
             return map;
         }
     }
-}
+}

+ 2 - 2
Jint/Native/WeakSet/WeakSetConstructor.cs

@@ -30,7 +30,7 @@ namespace Jint.Native.WeakSet
             return null;
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
             if (newTarget.IsUndefined())
             {
@@ -76,4 +76,4 @@ namespace Jint.Native.WeakSet
             return set;
         }
     }
-}
+}

+ 4 - 4
Jint/Runtime/Host.cs

@@ -148,11 +148,11 @@ namespace Jint.Runtime
                 try
                 {
                     var ns = JsModule.GetModuleNamespace(moduleRecord);
-                    promiseCapability.Resolve.Call(ns);
+                    promiseCapability.Resolve.Call(JsValue.Undefined, new[] { ns });
                 }
                 catch (JavaScriptException ex)
                 {
-                    promiseCapability.Reject.Call(ex.Error);
+                    promiseCapability.Reject.Call(JsValue.Undefined, new [] { ex.Error });
                 }
                 return JsValue.Undefined;
             }, 0, PropertyFlag.Configurable);
@@ -160,11 +160,11 @@ namespace Jint.Runtime
             var onRejected = new ClrFunctionInstance(Engine, "", (thisObj, args) =>
             {
                 var error = args.At(0);
-                promiseCapability.Reject.Call(error);
+                promiseCapability.Reject.Call(JsValue.Undefined, new [] { error });
                 return JsValue.Undefined;
             }, 0, PropertyFlag.Configurable);
 
             PromiseOperations.PerformPromiseThen(Engine, innerPromise, onFulfilled, onRejected, null);
         }
     }
-}
+}

+ 2 - 2
Jint/Runtime/Interop/NamespaceReference.cs

@@ -33,7 +33,7 @@ namespace Jint.Runtime.Interop
             return false;
         }
 
-        public JsValue Call(JsValue thisObject, JsValue[] arguments)
+        JsValue ICallable.Call(JsValue thisObject, JsValue[] arguments)
         {
             // direct calls on a NamespaceReference constructor object is creating a generic type
             var genericTypes = new Type[arguments.Length];
@@ -196,4 +196,4 @@ namespace Jint.Runtime.Interop
             return "[Namespace: " + _path + "]";
         }
     }
-}
+}

+ 4 - 2
Jint/Runtime/Interop/TypeReference.cs

@@ -43,10 +43,12 @@ namespace Jint.Runtime.Interop
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
             // direct calls on a TypeReference constructor object is equivalent to the new operator
-            return Construct(arguments, thisObject);
+            return Construct(arguments);
         }
 
-        public ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments);
+
+        private ObjectInstance Construct(JsValue[] arguments)
         {
             if (arguments.Length == 0 && ReferenceType.IsValueType)
             {

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

@@ -64,11 +64,11 @@ namespace Jint.Runtime.Interpreter.Expressions
             }
 
             // construct the new instance using the Function's constructor method
-            var instance = engine.Construct((IConstructor) jsValue, arguments, jsValue, _calleeExpression);
+            var instance = engine.Construct(jsValue, arguments, jsValue, _calleeExpression);
 
             engine._jsValueArrayPool.ReturnArray(arguments);
 
             return NormalCompletion(instance);
         }
     }
-}
+}

+ 8 - 7
Jint/Runtime/Modules/JsModule.cs

@@ -1,4 +1,5 @@
-using Esprima.Ast;
+using System;
+using Esprima.Ast;
 using System.Collections.Generic;
 using System.Linq;
 using Jint.Native;
@@ -334,7 +335,7 @@ public sealed class JsModule : JsValue
                 m.Status = ModuleStatus.Evaluated;
                 m._evalError = result;
             }
-            capability.Reject.Call(result.Value);
+            capability.Reject.Call(Undefined, new [] { result.Value });
         }
         else
         {
@@ -355,7 +356,7 @@ public sealed class JsModule : JsValue
                     ExceptionHelper.ThrowInvalidOperationException("Error while evaluating module: Module is in an invalid state");
                 }
 
-                capability.Resolve.Call(Undefined);
+                capability.Resolve.Call(Undefined, Array.Empty<JsValue>());
             }
 
             if (stack.Any())
@@ -807,7 +808,7 @@ public sealed class JsModule : JsValue
                 ExceptionHelper.ThrowInvalidOperationException("Error while evaluating module: Module is in an invalid state");
             }
 
-            module._topLevelCapability.Resolve.Call(Undefined);
+            module._topLevelCapability.Resolve.Call(Undefined, Array.Empty<JsValue>());
         }
 
         var execList = new List<JsModule>();
@@ -842,7 +843,7 @@ public sealed class JsModule : JsValue
                             ExceptionHelper.ThrowInvalidOperationException("Error while evaluating module: Module is in an invalid state");
                         }
 
-                        m._topLevelCapability.Resolve.Call(Undefined);
+                        m._topLevelCapability.Resolve.Call(Undefined, Array.Empty<JsValue>());
                     }
                 }
             }
@@ -893,7 +894,7 @@ public sealed class JsModule : JsValue
                 ExceptionHelper.ThrowInvalidOperationException("Error while evaluating module: Module is in an invalid state");
             }
 
-            module._topLevelCapability.Reject.Call(error);
+            module._topLevelCapability.Reject.Call(Undefined, new [] { error });
         }
 
 
@@ -910,4 +911,4 @@ public sealed class JsModule : JsValue
         ExceptionHelper.ThrowNotSupportedException();
         return null;
     }
-}
+}