Browse Source

Fix iterator prototype and Reflect/Proxy issues (#1072)

Marko Lahma 3 years ago
parent
commit
2d16a66ccc

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

@@ -13,7 +13,7 @@ namespace Jint.Native.Array
         internal ArrayIteratorPrototype(
         internal ArrayIteratorPrototype(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectPrototype objectPrototype) : base(engine, realm, "Array Iterator", objectPrototype)
+            IteratorPrototype objectPrototype) : base(engine, realm, "Array Iterator", objectPrototype)
         {
         {
         }
         }
 
 

+ 2 - 2
Jint/Native/Iterator/IteratorPrototype.cs

@@ -19,7 +19,7 @@ namespace Jint.Native.Iterator
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
             string name,
             string name,
-            ObjectPrototype objectPrototype) : base(engine, realm)
+            Prototype objectPrototype) : base(engine, realm)
         {
         {
             _prototype = objectPrototype;
             _prototype = objectPrototype;
             _name = name;
             _name = name;
@@ -36,7 +36,7 @@ namespace Jint.Native.Iterator
 
 
             var symbols = new SymbolDictionary(_name != null ? 2 : 1)
             var symbols = new SymbolDictionary(_name != null ? 2 : 1)
             {
             {
-                [GlobalSymbolRegistry.Iterator] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "iterator", ToIterator, 1, PropertyFlag.Configurable), true, false, true),
+                [GlobalSymbolRegistry.Iterator] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "[Symbol.iterator]", ToIterator, 0, PropertyFlag.Configurable), true, false, true),
             };
             };
 
 
             if (_name != null)
             if (_name != null)

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

@@ -12,7 +12,7 @@ namespace Jint.Native.Map
         internal MapIteratorPrototype(
         internal MapIteratorPrototype(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectPrototype objectPrototype) : base(engine, realm, "Map Iterator", objectPrototype)
+            Prototype objectPrototype) : base(engine, realm, "Map Iterator", objectPrototype)
         {
         {
         }
         }
 
 

+ 4 - 5
Jint/Native/Object/ObjectPrototype.cs

@@ -7,17 +7,15 @@ using Jint.Runtime.Interop;
 
 
 namespace Jint.Native.Object
 namespace Jint.Native.Object
 {
 {
-    public sealed class ObjectPrototype : ObjectInstance
+    public sealed class ObjectPrototype : Prototype
     {
     {
-        private readonly Realm _realm;
         private readonly ObjectConstructor _constructor;
         private readonly ObjectConstructor _constructor;
 
 
         internal ObjectPrototype(
         internal ObjectPrototype(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectConstructor constructor) : base(engine)
+            ObjectConstructor constructor) : base(engine, realm)
         {
         {
-            _realm = realm;
             _constructor = constructor;
             _constructor = constructor;
         }
         }
 
 
@@ -111,11 +109,12 @@ namespace Jint.Native.Object
             }
             }
 
 
             var o = TypeConverter.ToObject(_realm, thisObject);
             var o = TypeConverter.ToObject(_realm, thisObject);
+            var isArray = o.IsArray();
 
 
             var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
             var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
             if (!tag.IsString())
             if (!tag.IsString())
             {
             {
-                if (o.IsArray())
+                if (isArray)
                 {
                 {
                     tag = "Array";
                     tag = "Array";
                 }
                 }

+ 7 - 6
Jint/Native/Proxy/ProxyInstance.cs

@@ -114,14 +114,15 @@ namespace Jint.Native.Proxy
         /// </summary>
         /// </summary>
         public override JsValue Get(JsValue property, JsValue receiver)
         public override JsValue Get(JsValue property, JsValue receiver)
         {
         {
-            if (property == KeyFunctionRevoke || !TryCallHandler(TrapGet, new[] {_target, TypeConverter.ToPropertyKey(property), this }, out var result))
+            AssertTargetNotRevoked(property);
+            var target = _target;
+
+            if (property == KeyFunctionRevoke || !TryCallHandler(TrapGet, new[] {target, TypeConverter.ToPropertyKey(property), this }, out var result))
             {
             {
-                AssertTargetNotRevoked(property);
-                return _target.Get(property, receiver);
+                return target.Get(property, receiver);
             }
             }
 
 
-            AssertTargetNotRevoked(property);
-            var targetDesc = _target.GetOwnProperty(property);
+            var targetDesc = target.GetOwnProperty(property);
             if (targetDesc != PropertyDescriptor.Undefined)
             if (targetDesc != PropertyDescriptor.Undefined)
             {
             {
                 if (targetDesc.IsDataDescriptor() && !targetDesc.Configurable && !targetDesc.Writable && !ReferenceEquals(result, targetDesc._value))
                 if (targetDesc.IsDataDescriptor() && !targetDesc.Configurable && !targetDesc.Writable && !ReferenceEquals(result, targetDesc._value))
@@ -339,7 +340,7 @@ namespace Jint.Native.Proxy
         /// </summary>
         /// </summary>
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         {
         {
-            var arguments = new[] { _target, TypeConverter.ToPropertyKey(property), PropertyDescriptor.FromPropertyDescriptor(_engine, desc) };
+            var arguments = new[] { _target, TypeConverter.ToPropertyKey(property), PropertyDescriptor.FromPropertyDescriptor(_engine, desc, strictUndefined: true) };
             if (!TryCallHandler(TrapDefineProperty, arguments, out var result))
             if (!TryCallHandler(TrapDefineProperty, arguments, out var result))
             {
             {
                 return _target.DefineOwnProperty(property, desc);
                 return _target.DefineOwnProperty(property, desc);

+ 1 - 1
Jint/Native/RegExp/RegExpStringIteratorPrototype.cs

@@ -12,7 +12,7 @@ namespace Jint.Native.RegExp
         internal RegExpStringIteratorPrototype(
         internal RegExpStringIteratorPrototype(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectPrototype objectPrototype) : base(engine, realm, "RegExp String Iterator", objectPrototype)
+            Prototype objectPrototype) : base(engine, realm, "RegExp String Iterator", objectPrototype)
         {
         {
         }
         }
 
 

+ 1 - 1
Jint/Native/RegExp/RegExpStringIteratorPrototypeObject.cs

@@ -9,7 +9,7 @@ namespace Jint.Native.RegExp
         internal RegExpStringIteratorPrototypeObject(
         internal RegExpStringIteratorPrototypeObject(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectPrototype objectPrototype) : base(engine, realm, "RegExp String Iterator", objectPrototype)
+            Prototype objectPrototype) : base(engine, realm, "RegExp String Iterator", objectPrototype)
         {
         {
         }
         }
 
 

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

@@ -12,7 +12,7 @@ namespace Jint.Native.Set
         internal SetIteratorPrototype(
         internal SetIteratorPrototype(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectPrototype objectPrototype) : base(engine, realm, "Set Iterator", objectPrototype)
+            Prototype objectPrototype) : base(engine, realm, "Set Iterator", objectPrototype)
         {
         {
         }
         }
 
 

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

@@ -12,7 +12,7 @@ namespace Jint.Native.String
         internal StringIteratorPrototype(
         internal StringIteratorPrototype(
             Engine engine,
             Engine engine,
             Realm realm,
             Realm realm,
-            ObjectPrototype objectPrototype) : base(engine, realm, "String Iterator", objectPrototype)
+            Prototype objectPrototype) : base(engine, realm, "String Iterator", objectPrototype)
         {
         {
         }
         }
 
 

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

@@ -39,7 +39,7 @@ namespace Jint.Native.TypedArray
         {
         {
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag propertyFlags = PropertyFlag.Writable | PropertyFlag.Configurable;
             const PropertyFlag propertyFlags = PropertyFlag.Writable | PropertyFlag.Configurable;
-            var properties = new PropertyDictionary(31, false)
+            var properties = new PropertyDictionary(33, false)
             {
             {
                 ["buffer"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(_engine, "get buffer", Buffer, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
                 ["buffer"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(_engine, "get buffer", Buffer, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
                 ["byteLength"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(_engine, "get byteLength", ByteLength, 0, lengthFlags), Undefined, PropertyFlag.Configurable),
                 ["byteLength"] = new GetSetPropertyDescriptor(new ClrFunctionInstance(_engine, "get byteLength", ByteLength, 0, lengthFlags), Undefined, PropertyFlag.Configurable),

+ 4 - 4
Jint/Runtime/Descriptors/PropertyDescriptor.cs

@@ -311,7 +311,7 @@ namespace Jint.Runtime.Descriptors
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-frompropertydescriptor
         /// https://tc39.es/ecma262/#sec-frompropertydescriptor
         /// </summary>
         /// </summary>
-        public static JsValue FromPropertyDescriptor(Engine engine, PropertyDescriptor desc)
+        public static JsValue FromPropertyDescriptor(Engine engine, PropertyDescriptor desc, bool strictUndefined = false)
         {
         {
             if (ReferenceEquals(desc, Undefined))
             if (ReferenceEquals(desc, Undefined))
             {
             {
@@ -321,7 +321,7 @@ namespace Jint.Runtime.Descriptors
             var obj = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             var obj = engine.Realm.Intrinsics.Object.Construct(Arguments.Empty);
             var properties = new PropertyDictionary(4, checkExistingKeys: false);
             var properties = new PropertyDictionary(4, checkExistingKeys: false);
 
 
-            // TODO should not check for PropertyFlag.None, but needs a bigger cleanup
+            // TODO should not check for strictUndefined, but needs a bigger cleanup
             // we should have possibility to leave out the properties in property descriptors as newer tests
             // we should have possibility to leave out the properties in property descriptors as newer tests
             // also assert properties to be undefined
             // also assert properties to be undefined
 
 
@@ -339,12 +339,12 @@ namespace Jint.Runtime.Descriptors
                 properties["set"] = new PropertyDescriptor(desc.Set ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
                 properties["set"] = new PropertyDescriptor(desc.Set ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
             }
             }
 
 
-            if (desc._flags != PropertyFlag.None || desc.EnumerableSet)
+            if (!strictUndefined || desc.EnumerableSet)
             {
             {
                 properties["enumerable"] = new PropertyDescriptor(desc.Enumerable, PropertyFlag.ConfigurableEnumerableWritable);
                 properties["enumerable"] = new PropertyDescriptor(desc.Enumerable, PropertyFlag.ConfigurableEnumerableWritable);
             }
             }
 
 
-            if (desc._flags != PropertyFlag.None || desc.ConfigurableSet)
+            if (!strictUndefined || desc.ConfigurableSet)
             {
             {
                 properties["configurable"] = new PropertyDescriptor(desc.Configurable, PropertyFlag.ConfigurableEnumerableWritable);
                 properties["configurable"] = new PropertyDescriptor(desc.Configurable, PropertyFlag.ConfigurableEnumerableWritable);
             }
             }

+ 4 - 4
Jint/Runtime/Interpreter/Expressions/JintBinaryExpression.cs

@@ -319,7 +319,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                 }
                 }
                 else if (AreNonBigIntOperands(left, right))
                 else if (AreNonBigIntOperands(left, right))
                 {
                 {
-                    number = JsNumber.Create(TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right));
+                    number = JsNumber.Create(left.AsNumber() - right.AsNumber());
                 }
                 }
                 else
                 else
                 {
                 {
@@ -358,7 +358,7 @@ namespace Jint.Runtime.Interpreter.Expressions
 
 
                     if (leftNumeric.IsNumber())
                     if (leftNumeric.IsNumber())
                     {
                     {
-                        result = JsNumber.Create(TypeConverter.ToNumber(left) * TypeConverter.ToNumber(right));
+                        result = JsNumber.Create(leftNumeric.AsNumber() * rightNumeric.AsNumber());
                     }
                     }
                     else
                     else
                     {
                     {
@@ -656,8 +656,8 @@ namespace Jint.Runtime.Interpreter.Expressions
                 }
                 }
                 else if (AreNonBigIntOperands(left, right))
                 else if (AreNonBigIntOperands(left, right))
                 {
                 {
-                    var n = TypeConverter.ToNumber(left);
-                    var d = TypeConverter.ToNumber(right);
+                    var n = left.AsNumber();
+                    var d = right.AsNumber();
 
 
                     if (double.IsNaN(n) || double.IsNaN(d) || double.IsInfinity(n))
                     if (double.IsNaN(n) || double.IsNaN(d) || double.IsInfinity(n))
                     {
                     {

+ 3 - 3
Jint/Runtime/Intrinsics.cs

@@ -111,7 +111,7 @@ namespace Jint.Runtime
             _array ??= new ArrayConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
             _array ??= new ArrayConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
 
 
         internal ArrayIteratorPrototype ArrayIteratorPrototype =>
         internal ArrayIteratorPrototype ArrayIteratorPrototype =>
-            _arrayIteratorPrototype ??= new ArrayIteratorPrototype(_engine, _realm, Object.PrototypeObject);
+            _arrayIteratorPrototype ??= new ArrayIteratorPrototype(_engine, _realm, this.IteratorPrototype);
 
 
         public DataViewConstructor DataView =>
         public DataViewConstructor DataView =>
             _dataView ??= new DataViewConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
             _dataView ??= new DataViewConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
@@ -183,13 +183,13 @@ namespace Jint.Runtime
             _string ??= new StringConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
             _string ??= new StringConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
 
 
         internal StringIteratorPrototype StringIteratorPrototype =>
         internal StringIteratorPrototype StringIteratorPrototype =>
-            _stringIteratorPrototype ??= new StringIteratorPrototype(_engine, _realm, Object.PrototypeObject);
+            _stringIteratorPrototype ??= new StringIteratorPrototype(_engine, _realm, IteratorPrototype);
 
 
         public RegExpConstructor RegExp =>
         public RegExpConstructor RegExp =>
             _regExp ??= new RegExpConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
             _regExp ??= new RegExpConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
 
 
         internal RegExpStringIteratorPrototype RegExpStringIteratorPrototype =>
         internal RegExpStringIteratorPrototype RegExpStringIteratorPrototype =>
-            _regExpStringIteratorPrototype ??= new RegExpStringIteratorPrototype(_engine, _realm, Object.PrototypeObject);
+            _regExpStringIteratorPrototype ??= new RegExpStringIteratorPrototype(_engine, _realm, IteratorPrototype);
 
 
         public BooleanConstructor Boolean =>
         public BooleanConstructor Boolean =>
             _boolean ??= new BooleanConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);
             _boolean ??= new BooleanConstructor(_engine, _realm, Function.PrototypeObject, Object.PrototypeObject);