2
0
Marko Lahma 3 жил өмнө
parent
commit
c596da23ce

+ 0 - 1
Jint.Tests.Test262/Test262Harness.settings.json

@@ -7,7 +7,6 @@
   "ExcludedFeatures": [
     "__getter__",
     "__setter__",
-    "AggregateError",
     "async-functions",
     "async-iteration",
     "Atomics",

+ 67 - 0
Jint/Native/AggregateError/AggregateErrorConstructor.cs

@@ -0,0 +1,67 @@
+#nullable enable
+
+using Jint.Native.Error;
+using Jint.Native.Function;
+using Jint.Native.Object;
+using Jint.Native.TypedArray;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.AggregateError;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-aggregate-error-constructor
+/// </summary>
+internal sealed class AggregateErrorConstructor : FunctionInstance, IConstructor
+{
+    private static readonly JsString _name = new("AggregateError");
+
+    internal AggregateErrorConstructor(
+        Engine engine,
+        Realm realm,
+        ErrorConstructor errorConstructor)
+        : base(engine, realm, _name)
+    {
+        _prototype = errorConstructor;
+        PrototypeObject = new AggregateErrorPrototype(engine, realm, this, errorConstructor.PrototypeObject);
+        _length = new PropertyDescriptor(JsNumber.PositiveTwo, PropertyFlag.Configurable);
+        _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
+    }
+
+    private AggregateErrorPrototype PrototypeObject { get; }
+
+    protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
+    {
+        return Construct(arguments, this);
+    }
+
+    ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget) => Construct(arguments, newTarget);
+
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-nativeerror
+    /// </summary>
+    private ObjectInstance Construct(JsValue[] arguments, JsValue newTarget)
+    {
+        var errors = arguments.At(0);
+        var message = arguments.At(1);
+        var options = arguments.At(2);
+
+        var o = OrdinaryCreateFromConstructor(
+            newTarget,
+            static intrinsics => intrinsics.AggregateError.PrototypeObject,
+            static (Engine engine, Realm _, object? _) => new ErrorInstance(engine));
+
+        if (!message.IsUndefined())
+        {
+            var msg = TypeConverter.ToString(message);
+            o.CreateNonEnumerableDataPropertyOrThrow("message", msg);
+        }
+
+        o.InstallErrorCause(options);
+
+        var errorsList = TypedArrayConstructor.IterableToList(_realm, errors);
+        o.DefinePropertyOrThrow("errors", new PropertyDescriptor(_realm.Intrinsics.Array.CreateArrayFromList(errorsList), configurable: true, enumerable: false, writable: true));
+
+        return o;
+    }
+}

+ 38 - 0
Jint/Native/AggregateError/AggregateErrorPrototype.cs

@@ -0,0 +1,38 @@
+#nullable enable
+
+using Jint.Collections;
+using Jint.Native.Object;
+using Jint.Runtime;
+using Jint.Runtime.Descriptors;
+
+namespace Jint.Native.AggregateError;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-properties-of-the-aggregate-error-prototype-objects
+/// </summary>
+internal sealed class AggregateErrorPrototype : Prototype
+{
+    private readonly AggregateErrorConstructor _constructor;
+
+    internal AggregateErrorPrototype(
+        Engine engine,
+        Realm realm,
+        AggregateErrorConstructor constructor,
+        ObjectInstance prototype)
+        : base(engine, realm)
+    {
+        _constructor = constructor;
+        _prototype = prototype;
+    }
+
+    protected override void Initialize()
+    {
+        var properties = new PropertyDictionary(3, checkExistingKeys: false)
+        {
+            ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
+            ["message"] = new PropertyDescriptor(JsString.Empty, PropertyFlag.Configurable | PropertyFlag.Writable),
+            ["name"] = new PropertyDescriptor("AggregateError", PropertyFlag.Configurable | PropertyFlag.Writable),
+        };
+        SetProperties(properties);
+    }
+}

+ 2 - 7
Jint/Native/Error/ErrorConstructor.cs

@@ -20,7 +20,7 @@ namespace Jint.Native.Error
         {
             _intrinsicDefaultProto = intrinsicDefaultProto;
             _prototype = functionPrototype;
-            PrototypeObject = new ErrorPrototype(engine, realm, this, objectPrototype, name, ObjectClass.Object);
+            PrototypeObject = new ErrorPrototype(engine, realm, this, objectPrototype, name);
             _length = new PropertyDescriptor(JsNumber.PositiveOne, PropertyFlag.Configurable);
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
@@ -64,12 +64,7 @@ namespace Jint.Native.Error
 
             var options = arguments.At(1);
 
-            if (options is ObjectInstance oi && oi.HasProperty("cause"))
-            {
-                var cause = oi.Get("cause");
-                var causeDesc = new PropertyDescriptor(cause, PropertyFlag.NonEnumerable);
-                o.DefinePropertyOrThrow("cause", causeDesc);
-            }
+            o.InstallErrorCause(options);
 
             return o;
         }

+ 22 - 11
Jint/Native/Error/ErrorInstance.cs

@@ -1,20 +1,31 @@
-using Jint.Native.Object;
+#nullable enable
+
+using Jint.Native.Object;
 using Jint.Runtime;
 
-namespace Jint.Native.Error
+namespace Jint.Native.Error;
+
+public class ErrorInstance : ObjectInstance
 {
-    public class ErrorInstance : ObjectInstance
+    internal ErrorInstance(Engine engine, ObjectClass objectClass = ObjectClass.Error)
+        : base(engine, objectClass)
     {
-        internal ErrorInstance(
-            Engine engine,
-            ObjectClass objectClass = ObjectClass.Error)
-            : base(engine, objectClass)
-        {
-        }
+    }
 
-        public override string ToString()
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-installerrorcause
+    /// </summary>
+    internal void InstallErrorCause(JsValue options)
+    {
+        if (options is ObjectInstance oi && oi.HasProperty("cause"))
         {
-            return Engine.Realm.Intrinsics.Error.PrototypeObject.ToString(this, Arguments.Empty).ToObject().ToString();
+            var cause = oi.Get("cause");
+            CreateNonEnumerableDataPropertyOrThrow("cause", cause);
         }
     }
+
+    public override string ToString()
+    {
+        return Engine.Realm.Intrinsics.Error.PrototypeObject.ToString(this, Arguments.Empty).ToObject().ToString();
+    }
 }

+ 2 - 3
Jint/Native/Error/ErrorPrototype.cs

@@ -20,9 +20,8 @@ namespace Jint.Native.Error
             Realm realm,
             ErrorConstructor constructor,
             ObjectInstance prototype,
-            JsString name,
-            ObjectClass objectClass)
-            : base(engine, objectClass)
+            JsString name)
+            : base(engine, ObjectClass.Object)
         {
             _realm = realm;
             _name = name;

+ 1 - 1
Jint/Native/Global/GlobalObject.cs

@@ -35,7 +35,7 @@ namespace Jint.Native.Global
 
             var properties = new PropertyDictionary(55, checkExistingKeys: false)
             {
-                ["AggregateError"] = new LazyPropertyDescriptor(this, static state => Undefined, propertyFlags),
+                ["AggregateError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.AggregateError, propertyFlags),
                 ["Array"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.Array, propertyFlags),
                 ["ArrayBuffer"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.ArrayBuffer, propertyFlags),
                 ["Atomics"] = new LazyPropertyDescriptor(this, static state => Undefined, propertyFlags),

+ 9 - 0
Jint/Native/Object/ObjectInstance.cs

@@ -1234,6 +1234,15 @@ namespace Jint.Native.Object
             return true;
         }
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-createnonenumerabledatapropertyorthrow
+        /// </summary>
+        internal void CreateNonEnumerableDataPropertyOrThrow(JsValue p, JsValue v)
+        {
+            var newDesc = new PropertyDescriptor(v, true, false, true);
+            DefinePropertyOrThrow(p, newDesc);
+        }
+
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal ICallable GetMethod(JsValue property)
         {

+ 1 - 1
Jint/Native/TypedArray/TypedArrayConstructor.cs

@@ -119,7 +119,7 @@ namespace Jint.Native.TypedArray
         /// <summary>
         /// https://tc39.es/ecma262/#sec-iterabletolist
         /// </summary>
-        internal static List<JsValue> IterableToList(Realm realm, JsValue items, ICallable usingIterator)
+        internal static List<JsValue> IterableToList(Realm realm, JsValue items, ICallable method = null)
         {
             var iteratorRecord = items.GetIterator(realm);
             var values = new List<JsValue>();

+ 5 - 0
Jint/Runtime/Intrinsics.cs

@@ -1,4 +1,5 @@
 using Jint.Native;
+using Jint.Native.AggregateError;
 using Jint.Native.Array;
 using Jint.Native.ArrayBuffer;
 using Jint.Native.BigInt;
@@ -42,6 +43,7 @@ namespace Jint.Runtime
 
         // lazy properties
         private ThrowTypeError _throwTypeError;
+        private AggregateErrorConstructor _aggregateError;
         private ErrorConstructor _error;
         private ErrorConstructor _evalError;
         private ErrorConstructor _rangeError;
@@ -113,6 +115,9 @@ namespace Jint.Runtime
         public ArrayConstructor Array =>
             _array ??= new ArrayConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
 
+        internal AggregateErrorConstructor AggregateError =>
+            _aggregateError ??= new AggregateErrorConstructor(_engine, _realm, Error);
+
         internal ArrayIteratorPrototype ArrayIteratorPrototype =>
             _arrayIteratorPrototype ??= new ArrayIteratorPrototype(_engine, _realm, this.IteratorPrototype);
 

+ 2 - 1
README.md

@@ -88,7 +88,8 @@ The entire execution engine was rebuild with performance in mind, in many cases
 
 - ✔ Logical Assignment Operators (`&&=` `||=` `??=`)
 - ✔ Numeric Separators (`1_000`)
-- ❌ `Promise.any` and `AggregateError`
+- ✔ `AggregateError`
+- ❌ `Promise.any` 
 - ✔ `String.prototype.replaceAll`
 - ❌ `WeakRef` and `FinalizationRegistry`