Przeglądaj źródła

Optimize iterators a bit (#1363)

Marko Lahma 2 lat temu
rodzic
commit
4259645984

Plik diff jest za duży
+ 8 - 0
Jint.Benchmark/ForBenchmark.cs


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

@@ -868,7 +868,7 @@ namespace Jint.Tests.Runtime
             ");
             ");
 
 
             var obj = _engine.GetValue("obj").AsObject();
             var obj = _engine.GetValue("obj").AsObject();
-            var getFoo = obj.Get("getFoo", obj);
+            var getFoo = obj.Get("getFoo");
 
 
             Assert.Equal("foo is 5, bar is 7", _engine.Invoke(getFoo, obj, new object[] { 7 }).AsString());
             Assert.Equal("foo is 5, bar is 7", _engine.Invoke(getFoo, obj, new object[] { 7 }).AsString());
         }
         }
@@ -881,7 +881,7 @@ namespace Jint.Tests.Runtime
             ");
             ");
 
 
             var obj = _engine.GetValue("obj").AsObject();
             var obj = _engine.GetValue("obj").AsObject();
-            var foo = obj.Get("foo", obj);
+            var foo = obj.Get("foo");
 
 
             Assert.Throws<JavaScriptException>(() => _engine.Invoke(foo, obj, new object[] { }));
             Assert.Throws<JavaScriptException>(() => _engine.Invoke(foo, obj, new object[] { }));
         }
         }

+ 1 - 1
Jint.Tests/Runtime/JsValueConversionTests.cs

@@ -33,7 +33,7 @@ namespace Jint.Tests.Runtime
         [Fact]
         [Fact]
         public void ShouldBeABoolean()
         public void ShouldBeABoolean()
         {
         {
-            var value = new JsBoolean(true);
+            var value = JsBoolean.True;
             Assert.Equal(true, value.IsBoolean());
             Assert.Equal(true, value.IsBoolean());
             Assert.Equal(false, value.IsArray());
             Assert.Equal(false, value.IsArray());
             Assert.Equal(false, value.IsDate());
             Assert.Equal(false, value.IsDate());

+ 9 - 0
Jint/Native/Array/ArrayInstance.cs

@@ -474,6 +474,15 @@ namespace Jint.Native.Array
                 return value;
                 return value;
             }
             }
 
 
+            if (property == CommonProperties.Length)
+            {
+                var length = _length?._value;
+                if (length is not null)
+                {
+                    return length;
+                }
+            }
+
             return base.Get(property, receiver);
             return base.Get(property, receiver);
         }
         }
 
 

+ 7 - 7
Jint/Native/Array/ArrayIteratorPrototype.cs

@@ -85,9 +85,9 @@ internal sealed class ArrayIteratorPrototype : IteratorPrototype
                 {
                 {
                     nextItem = _kind switch
                     nextItem = _kind switch
                     {
                     {
-                        ArrayIteratorType.Key => new ValueIteratorPosition(_engine, _position),
-                        ArrayIteratorType.Value => new ValueIteratorPosition(_engine, _typedArray[(int) _position]),
-                        _ => new KeyValueIteratorPosition(_engine, _position, _typedArray[(int) _position])
+                        ArrayIteratorType.Key => IteratorResult.CreateValueIteratorPosition(_engine, JsNumber.Create(_position)),
+                        ArrayIteratorType.Value => IteratorResult.CreateValueIteratorPosition(_engine, _typedArray[(int) _position]),
+                        _ => IteratorResult.CreateKeyValueIteratorPosition(_engine, JsNumber.Create(_position), _typedArray[(int) _position])
                     };
                     };
                 }
                 }
                 else
                 else
@@ -95,15 +95,15 @@ internal sealed class ArrayIteratorPrototype : IteratorPrototype
                     _operations!.TryGetValue(_position, out var value);
                     _operations!.TryGetValue(_position, out var value);
                     if (_kind == ArrayIteratorType.Key)
                     if (_kind == ArrayIteratorType.Key)
                     {
                     {
-                        nextItem = new ValueIteratorPosition(_engine, _position);
+                        nextItem = IteratorResult.CreateValueIteratorPosition(_engine, JsNumber.Create(_position));
                     }
                     }
                     else if (_kind == ArrayIteratorType.Value)
                     else if (_kind == ArrayIteratorType.Value)
                     {
                     {
-                        nextItem = new ValueIteratorPosition(_engine, value);
+                        nextItem = IteratorResult.CreateValueIteratorPosition(_engine, value);
                     }
                     }
                     else
                     else
                     {
                     {
-                        nextItem = new KeyValueIteratorPosition(_engine, _position, value);
+                        nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine, JsNumber.Create(_position), value);
                     }
                     }
                 }
                 }
 
 
@@ -112,7 +112,7 @@ internal sealed class ArrayIteratorPrototype : IteratorPrototype
             }
             }
 
 
             _closed = true;
             _closed = true;
-            nextItem = KeyValueIteratorPosition.Done(_engine);
+            nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
             return false;
             return false;
         }
         }
     }
     }

+ 3 - 3
Jint/Native/Array/ArrayOperations.cs

@@ -146,7 +146,7 @@ namespace Jint.Native.Array
 
 
             private double GetIntegerLength()
             private double GetIntegerLength()
             {
             {
-                var descValue = _target.Get(CommonProperties.Length, _target);
+                var descValue = _target.Get(CommonProperties.Length);
                 if (!ReferenceEquals(descValue, null))
                 if (!ReferenceEquals(descValue, null))
                 {
                 {
                     return TypeConverter.ToInteger(descValue);
                     return TypeConverter.ToInteger(descValue);
@@ -185,7 +185,7 @@ namespace Jint.Native.Array
             }
             }
 
 
             public override JsValue Get(ulong index)
             public override JsValue Get(ulong index)
-                => _target.Get(JsString.Create(index), _target);
+                => _target.Get(JsString.Create(index));
 
 
             public override bool TryGetValue(ulong index, out JsValue value)
             public override bool TryGetValue(ulong index, out JsValue value)
             {
             {
@@ -297,7 +297,7 @@ namespace Jint.Native.Array
                     return _target.Length;
                     return _target.Length;
                 }
                 }
 
 
-                var descValue = _target.Get(CommonProperties.Length, _target);
+                var descValue = _target.Get(CommonProperties.Length);
                 if (!ReferenceEquals(descValue, null))
                 if (!ReferenceEquals(descValue, null))
                 {
                 {
                     return (uint) TypeConverter.ToInteger(descValue);
                     return (uint) TypeConverter.ToInteger(descValue);

+ 2 - 2
Jint/Native/Array/ArrayPrototype.cs

@@ -1273,7 +1273,7 @@ namespace Jint.Native.Array
             else
             else
             {
             {
                 var elementObj = TypeConverter.ToObject(_realm, firstElement);
                 var elementObj = TypeConverter.ToObject(_realm, firstElement);
-                var func = elementObj.Get("toLocaleString", elementObj) as ICallable;
+                var func = elementObj.Get("toLocaleString") as ICallable;
                 if (func is null)
                 if (func is null)
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_realm);
                     ExceptionHelper.ThrowTypeError(_realm);
@@ -1292,7 +1292,7 @@ namespace Jint.Native.Array
                 else
                 else
                 {
                 {
                     var elementObj = TypeConverter.ToObject(_realm, nextElement);
                     var elementObj = TypeConverter.ToObject(_realm, nextElement);
-                    var func = elementObj.Get("toLocaleString", elementObj) as ICallable;
+                    var func = elementObj.Get("toLocaleString") as ICallable;
                     if (func is null)
                     if (func is null)
                     {
                     {
                         ExceptionHelper.ThrowTypeError(_realm);
                         ExceptionHelper.ThrowTypeError(_realm);

+ 1 - 1
Jint/Native/Date/DatePrototype.cs

@@ -815,7 +815,7 @@ namespace Jint.Native.Date
                 return Null;
                 return Null;
             }
             }
 
 
-            var toIso = o.Get("toISOString", o);
+            var toIso = o.Get("toISOString");
             var callable = toIso as ICallable;
             var callable = toIso as ICallable;
             if (callable is null)
             if (callable is null)
             {
             {

+ 1 - 1
Jint/Native/Function/FunctionInstance.cs

@@ -229,7 +229,7 @@ namespace Jint.Native.Function
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         internal ObjectInstance GetPrototypeFromConstructor(JsValue constructor, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
         internal ObjectInstance GetPrototypeFromConstructor(JsValue constructor, Func<Intrinsics, ObjectInstance> intrinsicDefaultProto)
         {
         {
-            if (constructor.Get(CommonProperties.Prototype, constructor) is not ObjectInstance proto)
+            if (constructor.Get(CommonProperties.Prototype) is not ObjectInstance proto)
             {
             {
                 var realm = GetFunctionRealm(constructor);
                 var realm = GetFunctionRealm(constructor);
                 proto = intrinsicDefaultProto(realm.Intrinsics);
                 proto = intrinsicDefaultProto(realm.Intrinsics);

+ 6 - 40
Jint/Native/Iterator/IteratorInstance.cs

@@ -2,7 +2,6 @@ using System.Globalization;
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Native.RegExp;
 using Jint.Native.RegExp;
 using Jint.Runtime;
 using Jint.Runtime;
-using Jint.Runtime.Descriptors;
 
 
 namespace Jint.Native.Iterator
 namespace Jint.Native.Iterator
 {
 {
@@ -33,11 +32,11 @@ namespace Jint.Native.Iterator
         {
         {
             if (_enumerable.MoveNext())
             if (_enumerable.MoveNext())
             {
             {
-                nextItem = new ValueIteratorPosition(_engine, _enumerable.Current);
+                nextItem = IteratorResult.CreateValueIteratorPosition(_engine, _enumerable.Current);
                 return true;
                 return true;
             }
             }
 
 
-            nextItem = ValueIteratorPosition.Done(_engine);
+            nextItem = IteratorResult.CreateValueIteratorPosition(_engine, done: JsBoolean.True);
             return false;
             return false;
         }
         }
 
 
@@ -50,40 +49,7 @@ namespace Jint.Native.Iterator
         /// </summary>
         /// </summary>
         private ObjectInstance CreateIterResultObject(JsValue value, bool done)
         private ObjectInstance CreateIterResultObject(JsValue value, bool done)
         {
         {
-            return new IteratorResult(_engine, value, done ? JsBoolean.True :  JsBoolean.False);
-        }
-
-        internal sealed class KeyValueIteratorPosition : ObjectInstance
-        {
-            internal static ObjectInstance Done(Engine engine) => new KeyValueIteratorPosition(engine, null, null);
-
-            public KeyValueIteratorPosition(Engine engine, JsValue? key, JsValue? value) : base(engine)
-            {
-                var done = ReferenceEquals(null, key) && ReferenceEquals(null, value);
-                if (!done)
-                {
-                    var arrayInstance = engine.Realm.Intrinsics.Array.ArrayCreate(2);
-                    arrayInstance.SetIndexValue(0, key!, false);
-                    arrayInstance.SetIndexValue(1, value!, false);
-                    SetProperty("value", new PropertyDescriptor(arrayInstance, PropertyFlag.AllForbidden));
-                }
-                SetProperty("done", done ? PropertyDescriptor.AllForbiddenDescriptor.BooleanTrue : PropertyDescriptor.AllForbiddenDescriptor.BooleanFalse);
-            }
-        }
-
-        internal sealed class ValueIteratorPosition : ObjectInstance
-        {
-            internal static ObjectInstance Done(Engine engine, JsValue? value = null)
-                => new ValueIteratorPosition(engine, value ?? Undefined, true);
-
-            public ValueIteratorPosition(Engine engine, JsValue value, bool? done = null) : base(engine)
-            {
-                if (value is not null)
-                {
-                    SetProperty("value", new PropertyDescriptor(value, PropertyFlag.AllForbidden));
-                }
-                SetProperty("done", new PropertyDescriptor(done ?? value is null, PropertyFlag.AllForbidden));
-            }
+            return new IteratorResult(_engine, value, JsBoolean.Create(done));
         }
         }
 
 
         internal sealed class ObjectIterator : IteratorInstance
         internal sealed class ObjectIterator : IteratorInstance
@@ -94,7 +60,7 @@ namespace Jint.Native.Iterator
             public ObjectIterator(ObjectInstance target) : base(target.Engine)
             public ObjectIterator(ObjectInstance target) : base(target.Engine)
             {
             {
                 _target = target;
                 _target = target;
-                if (target.Get(CommonProperties.Next, target) is not ICallable callable)
+                if (target.Get(CommonProperties.Next) is not ICallable callable)
                 {
                 {
                     ExceptionHelper.ThrowTypeError(target.Engine.Realm);
                     ExceptionHelper.ThrowTypeError(target.Engine.Realm);
                     return;
                     return;
@@ -173,11 +139,11 @@ namespace Jint.Native.Iterator
             {
             {
                 if (_iterator.MoveNext())
                 if (_iterator.MoveNext())
                 {
                 {
-                    nextItem = new ValueIteratorPosition(_engine, (string) _iterator.Current);
+                    nextItem = IteratorResult.CreateValueIteratorPosition(_engine, (string) _iterator.Current);
                     return true;
                     return true;
                 }
                 }
 
 
-                nextItem = KeyValueIteratorPosition.Done(_engine);
+                nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
                 return false;
                 return false;
             }
             }
         }
         }

+ 34 - 25
Jint/Native/Iterator/IteratorResult.cs

@@ -1,40 +1,49 @@
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Runtime;
 using Jint.Runtime;
 
 
-namespace Jint.Native.Iterator
+namespace Jint.Native.Iterator;
+
+/// <summary>
+/// https://tc39.es/ecma262/#sec-createiterresultobject
+/// </summary>
+internal class IteratorResult : ObjectInstance
 {
 {
-    /// <summary>
-    /// https://tc39.es/ecma262/#sec-createiterresultobject
-    /// </summary>
-    internal sealed class IteratorResult : ObjectInstance
+    private readonly JsValue _value;
+    private readonly JsBoolean _done;
+
+    public IteratorResult(Engine engine, JsValue value, JsBoolean done) : base(engine)
     {
     {
-        private readonly JsValue _value;
-        private readonly JsBoolean _done;
+        _value = value;
+        _done = done;
+    }
 
 
-        public IteratorResult(Engine engine, JsValue value, JsBoolean done) : base(engine)
-        {
-            _value = value;
-            _done = done;
-        }
+    public static IteratorResult CreateValueIteratorPosition(Engine engine, JsValue? value = null, JsBoolean? done = null)
+    {
+        return new IteratorResult(engine, value ?? Undefined, done ?? JsBoolean.False);
+    }
 
 
-        public override JsValue Get(JsValue property, JsValue receiver)
-        {
-            if (property == CommonProperties.Value)
-            {
-                return _value;
-            }
+    public static IteratorResult CreateKeyValueIteratorPosition(Engine engine, JsValue? key = null, JsValue? value = null)
+    {
+        var done = ReferenceEquals(null, key) && ReferenceEquals(null, value);
+        var array = done ? Undefined : new JsArray(engine, new[] { key!, value! });
 
 
-            if (property == CommonProperties.Done)
-            {
-                return _done;
-            }
+        return new IteratorResult(engine, array, JsBoolean.Create(done));
+    }
 
 
-            return base.Get(property, receiver);
+    public override JsValue Get(JsValue property, JsValue receiver)
+    {
+        if (property == CommonProperties.Value)
+        {
+            return _value;
         }
         }
 
 
-        public override object ToObject()
+        if (property == CommonProperties.Done)
         {
         {
-            return this;
+            return _done;
         }
         }
+
+        return base.Get(property, receiver);
     }
     }
+
+    public override object ToObject() => this;
 }
 }

+ 3 - 1
Jint/Native/JsBoolean.cs

@@ -12,11 +12,13 @@ public sealed class JsBoolean : JsValue, IEquatable<JsBoolean>
 
 
     internal readonly bool _value;
     internal readonly bool _value;
 
 
-    public JsBoolean(bool value) : base(Types.Boolean)
+    private JsBoolean(bool value) : base(Types.Boolean)
     {
     {
         _value = value;
         _value = value;
     }
     }
 
 
+    internal static JsBoolean Create(bool value) => value ? True : False;
+
     public override object ToObject()
     public override object ToObject()
     {
     {
         return _value ? BoxedTrue : BoxedFalse;
         return _value ? BoxedTrue : BoxedFalse;

+ 1 - 1
Jint/Native/Json/JsonInstance.cs

@@ -41,7 +41,7 @@ namespace Jint.Native.Json
 
 
         private static JsValue InternalizeJSONProperty(JsValue holder, JsValue name, ICallable reviver)
         private static JsValue InternalizeJSONProperty(JsValue holder, JsValue name, ICallable reviver)
         {
         {
-            JsValue temp = holder.Get(name, holder);
+            var temp = holder.Get(name);
             if (temp is ObjectInstance val)
             if (temp is ObjectInstance val)
             {
             {
                 if (val.IsArray())
                 if (val.IsArray())

+ 2 - 2
Jint/Native/Json/JsonSerializer.cs

@@ -137,7 +137,7 @@ namespace Jint.Native.Json
         /// </summary>
         /// </summary>
         private JsValue SerializeJSONProperty(JsValue key, JsValue holder)
         private JsValue SerializeJSONProperty(JsValue key, JsValue holder)
         {
         {
-            var value = holder.Get(key, holder);
+            var value = holder.Get(key);
             var isBigInt = value is BigIntInstance || value.IsBigInt();
             var isBigInt = value is BigIntInstance || value.IsBigInt();
             if (value.IsObject() || isBigInt)
             if (value.IsObject() || isBigInt)
             {
             {
@@ -312,7 +312,7 @@ namespace Jint.Native.Json
             var stepback = _indent;
             var stepback = _indent;
             _indent += _gap;
             _indent += _gap;
             var partial = new List<string>();
             var partial = new List<string>();
-            var len = TypeConverter.ToUint32(value.Get(CommonProperties.Length, value));
+            var len = TypeConverter.ToUint32(value.Get(CommonProperties.Length));
             for (int i = 0; i < len; i++)
             for (int i = 0; i < len; i++)
             {
             {
                 var strP = SerializeJSONProperty(i, value);
                 var strP = SerializeJSONProperty(i, value);

+ 7 - 7
Jint/Native/Map/MapIteratorPrototype.cs

@@ -67,29 +67,29 @@ internal sealed class MapIteratorPrototype : IteratorPrototype
 
 
     private sealed class MapIterator : IteratorInstance
     private sealed class MapIterator : IteratorInstance
     {
     {
-        private readonly MapInstance _map;
+        private readonly OrderedDictionary<JsValue, JsValue> _map;
 
 
         private int _position;
         private int _position;
 
 
         public MapIterator(Engine engine, MapInstance map) : base(engine)
         public MapIterator(Engine engine, MapInstance map) : base(engine)
         {
         {
-            _map = map;
+            _map = map._map;
             _position = 0;
             _position = 0;
         }
         }
 
 
         public override bool TryIteratorStep(out ObjectInstance nextItem)
         public override bool TryIteratorStep(out ObjectInstance nextItem)
         {
         {
-            if (_position < _map.GetSize())
+            if (_position < _map.Count)
             {
             {
-                var key = _map._map.GetKey(_position);
-                var value = _map._map[key];
+                var key = _map.GetKey(_position);
+                var value = _map[key];
 
 
                 _position++;
                 _position++;
-                nextItem = new KeyValueIteratorPosition(_engine, key, value);
+                nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine, key, value);
                 return true;
                 return true;
             }
             }
 
 
-            nextItem = KeyValueIteratorPosition.Done(_engine);
+            nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
             return false;
             return false;
         }
         }
     }
     }

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

@@ -1061,7 +1061,7 @@ namespace Jint.Native.Object
             {
             {
                 var property = JsString.Create(idx);
                 var property = JsString.Create(idx);
                 var kPresent = HasProperty(property);
                 var kPresent = HasProperty(property);
-                jsValue = kPresent ? Get(property, this) : Undefined;
+                jsValue = kPresent ? Get(property) : Undefined;
                 return kPresent;
                 return kPresent;
             }
             }
 
 
@@ -1117,7 +1117,7 @@ namespace Jint.Native.Object
         {
         {
             get
             get
             {
             {
-                var spreadable = Get(GlobalSymbolRegistry.IsConcatSpreadable, this);
+                var spreadable = Get(GlobalSymbolRegistry.IsConcatSpreadable);
                 if (!spreadable.IsUndefined())
                 if (!spreadable.IsUndefined())
                 {
                 {
                     return TypeConverter.ToBoolean(spreadable);
                     return TypeConverter.ToBoolean(spreadable);

+ 4 - 4
Jint/Native/Set/SetIteratorPrototype.cs

@@ -65,11 +65,11 @@ internal sealed class SetIteratorPrototype : IteratorPrototype
             {
             {
                 var value = _set._set[_position];
                 var value = _set._set[_position];
                 _position++;
                 _position++;
-                nextItem = new KeyValueIteratorPosition(_engine, value, value);
+                nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine, value, value);
                 return true;
                 return true;
             }
             }
 
 
-            nextItem = KeyValueIteratorPosition.Done(_engine);
+            nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
             return false;
             return false;
         }
         }
     }
     }
@@ -93,12 +93,12 @@ internal sealed class SetIteratorPrototype : IteratorPrototype
             {
             {
                 var value = _values[_position];
                 var value = _values[_position];
                 _position++;
                 _position++;
-                nextItem = new ValueIteratorPosition(_engine, value);
+                nextItem = IteratorResult.CreateValueIteratorPosition(_engine, value);
                 return true;
                 return true;
             }
             }
 
 
             _closed = true;
             _closed = true;
-            nextItem = KeyValueIteratorPosition.Done(_engine);
+            nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
             return false;
             return false;
         }
         }
     }
     }

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

@@ -120,7 +120,7 @@ namespace Jint.Native.String
         private JsValue Raw(JsValue thisObj, JsValue[] arguments)
         private JsValue Raw(JsValue thisObj, JsValue[] arguments)
         {
         {
             var cooked = TypeConverter.ToObject(_realm, arguments.At(0));
             var cooked = TypeConverter.ToObject(_realm, arguments.At(0));
-            var raw = TypeConverter.ToObject(_realm, cooked.Get(JintTaggedTemplateExpression.PropertyRaw, cooked));
+            var raw = TypeConverter.ToObject(_realm, cooked.Get(JintTaggedTemplateExpression.PropertyRaw));
 
 
             var operations = ArrayOperations.For(raw);
             var operations = ArrayOperations.For(raw);
             var length = operations.GetLength();
             var length = operations.GetLength();

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

@@ -1274,7 +1274,7 @@ namespace Jint.Native.TypedArray
             else
             else
             {
             {
                 var elementObj = TypeConverter.ToObject(_realm, firstElement);
                 var elementObj = TypeConverter.ToObject(_realm, firstElement);
-                var func = elementObj.Get("toLocaleString", elementObj) as ICallable;
+                var func = elementObj.Get("toLocaleString") as ICallable;
                 if (func is null)
                 if (func is null)
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_realm);
                     ExceptionHelper.ThrowTypeError(_realm);
@@ -1287,7 +1287,7 @@ namespace Jint.Native.TypedArray
             {
             {
                 var s = r + separator;
                 var s = r + separator;
                 var elementObj = TypeConverter.ToObject(_realm, array[k]);
                 var elementObj = TypeConverter.ToObject(_realm, array[k]);
-                var func = elementObj.Get("toLocaleString", elementObj) as ICallable;
+                var func = elementObj.Get("toLocaleString") as ICallable;
                 if (func is null)
                 if (func is null)
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_realm);
                     ExceptionHelper.ThrowTypeError(_realm);

+ 17 - 4
Jint/Native/WeakSet/WeakSetConstructor.cs

@@ -7,7 +7,7 @@ namespace Jint.Native.WeakSet
 {
 {
     internal sealed class WeakSetConstructor : FunctionInstance, IConstructor
     internal sealed class WeakSetConstructor : FunctionInstance, IConstructor
     {
     {
-        private static readonly JsString _functionName = new JsString("WeakSet");
+        private static readonly JsString _functionName = new("WeakSet");
 
 
         internal WeakSetConstructor(
         internal WeakSetConstructor(
             Engine engine,
             Engine engine,
@@ -22,7 +22,7 @@ namespace Jint.Native.WeakSet
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public WeakSetPrototype PrototypeObject { get; }
+        private WeakSetPrototype PrototypeObject { get; }
 
 
         protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
         protected internal override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {
@@ -42,9 +42,22 @@ namespace Jint.Native.WeakSet
                 static intrinsics => intrinsics.WeakSet.PrototypeObject,
                 static intrinsics => intrinsics.WeakSet.PrototypeObject,
                 static (Engine engine, Realm _, object? _) => new WeakSetInstance(engine));
                 static (Engine engine, Realm _, object? _) => new WeakSetInstance(engine));
 
 
-            if (arguments.Length > 0 && !arguments[0].IsNullOrUndefined())
+            var arg1 = arguments.At(0);
+            if (!arg1.IsNullOrUndefined())
             {
             {
                 var adder = set.Get("add") as ICallable;
                 var adder = set.Get("add") as ICallable;
+
+                // check fast path
+                if (arg1 is JsArray array && ReferenceEquals(adder, _engine.Realm.Intrinsics.WeakSet.PrototypeObject._originalAddFunction))
+                {
+                    foreach (var value in array)
+                    {
+                        set.WeakSetAdd(value);
+                    }
+
+                    return set;
+                }
+
                 if (adder is null)
                 if (adder is null)
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_realm, "add must be callable");
                     ExceptionHelper.ThrowTypeError(_realm, "add must be callable");
@@ -62,7 +75,7 @@ namespace Jint.Native.WeakSet
                             return set;
                             return set;
                         }
                         }
 
 
-                        next.TryGetValue(CommonProperties.Value, out var nextValue);
+                        var nextValue = next.Get(CommonProperties.Value);
                         args[0] = nextValue;
                         args[0] = nextValue;
                         adder.Call(set, args);
                         adder.Call(set, args);
                     } while (true);
                     } while (true);

+ 10 - 7
Jint/Native/WeakSet/WeakSetPrototype.cs

@@ -13,6 +13,7 @@ namespace Jint.Native.WeakSet
     internal sealed class WeakSetPrototype : Prototype
     internal sealed class WeakSetPrototype : Prototype
     {
     {
         private readonly WeakSetConstructor _constructor;
         private readonly WeakSetConstructor _constructor;
+        internal ClrFunctionInstance _originalAddFunction = null!;
 
 
         internal WeakSetPrototype(
         internal WeakSetPrototype(
             Engine engine,
             Engine engine,
@@ -26,20 +27,22 @@ namespace Jint.Native.WeakSet
 
 
         protected override void Initialize()
         protected override void Initialize()
         {
         {
-            const PropertyFlag propertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
+            _originalAddFunction = new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable);
+
+            const PropertyFlag PropertyFlags = PropertyFlag.Configurable | PropertyFlag.Writable;
             var properties = new PropertyDictionary(5, checkExistingKeys: false)
             var properties = new PropertyDictionary(5, checkExistingKeys: false)
             {
             {
-                ["length"] = new PropertyDescriptor(0, PropertyFlag.Configurable),
-                ["constructor"] = new PropertyDescriptor(_constructor, PropertyFlag.NonEnumerable),
-                ["delete"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), propertyFlags),
-                ["add"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "add", Add, 1, PropertyFlag.Configurable), propertyFlags),
-                ["has"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), propertyFlags),
+                ["length"] = new(0, PropertyFlag.Configurable),
+                ["constructor"] = new(_constructor, PropertyFlag.NonEnumerable),
+                ["delete"] = new(new ClrFunctionInstance(Engine, "delete", Delete, 1, PropertyFlag.Configurable), PropertyFlags),
+                ["add"] = new(_originalAddFunction, PropertyFlags),
+                ["has"] = new(new ClrFunctionInstance(Engine, "has", Has, 1, PropertyFlag.Configurable), PropertyFlags),
             };
             };
             SetProperties(properties);
             SetProperties(properties);
 
 
             var symbols = new SymbolDictionary(1)
             var symbols = new SymbolDictionary(1)
             {
             {
-                [GlobalSymbolRegistry.ToStringTag] = new PropertyDescriptor("WeakSet", false, false, true)
+                [GlobalSymbolRegistry.ToStringTag] = new("WeakSet", false, false, true)
             };
             };
             SetSymbols(symbols);
             SetSymbols(symbols);
         }
         }

+ 4 - 4
Jint/Runtime/Interop/ObjectWrapper.cs

@@ -321,11 +321,11 @@ namespace Jint.Runtime.Interop
                     var key = _enumerator.Current;
                     var key = _enumerator.Current;
                     var value = _target.Get(key);
                     var value = _target.Get(key);
 
 
-                    nextItem = new KeyValueIteratorPosition(_engine, key, value);
+                    nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine, key, value);
                     return true;
                     return true;
                 }
                 }
 
 
-                nextItem = KeyValueIteratorPosition.Done(_engine);
+                nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
                 return false;
                 return false;
             }
             }
         }
         }
@@ -350,11 +350,11 @@ namespace Jint.Runtime.Interop
                 if (_enumerator.MoveNext())
                 if (_enumerator.MoveNext())
                 {
                 {
                     var value = _enumerator.Current;
                     var value = _enumerator.Current;
-                    nextItem = new ValueIteratorPosition(_engine, FromObject(_engine, value));
+                    nextItem = IteratorResult.CreateValueIteratorPosition(_engine, FromObject(_engine, value));
                     return true;
                     return true;
                 }
                 }
 
 
-                nextItem = KeyValueIteratorPosition.Done(_engine);
+                nextItem = IteratorResult.CreateKeyValueIteratorPosition(_engine);
                 return false;
                 return false;
             }
             }
         }
         }

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików