Browse Source

Fix more issues related to built-in objects (#1053)

Marko Lahma 3 years ago
parent
commit
6a87e76706
47 changed files with 756 additions and 597 deletions
  1. 2 2
      Jint.Tests.Ecma/TestCases/alltests.json
  2. 0 21
      Jint.Tests.Test262/test/built-ins/Proxy/create-handler-is-revoked-proxy.js
  3. 0 21
      Jint.Tests.Test262/test/built-ins/Proxy/create-target-is-revoked-proxy.js
  4. 0 19
      Jint.Tests.Test262/test/built-ins/Proxy/revocable/revocation-function-name.js
  5. 0 26
      Jint.Tests.Test262/test/language/computed-property-names/class/static/method-number.js
  6. 0 26
      Jint.Tests.Test262/test/language/computed-property-names/class/static/method-string.js
  7. 0 33
      Jint.Tests.Test262/test/language/computed-property-names/class/static/method-symbol.js
  8. 2 3
      Jint.Tests/Runtime/NullPropagation.cs
  9. 29 34
      Jint/Native/Array/ArrayConstructor.cs
  10. 45 25
      Jint/Native/Array/ArrayInstance.cs
  11. 5 5
      Jint/Native/Array/ArrayOperations.cs
  12. 138 124
      Jint/Native/Array/ArrayPrototype.cs
  13. 1 1
      Jint/Native/Boolean/BooleanConstructor.cs
  14. 6 3
      Jint/Native/Date/DateConstructor.cs
  15. 1 1
      Jint/Native/Date/DateInstance.cs
  16. 3 0
      Jint/Native/Function/FunctionConstructor.cs
  17. 1 17
      Jint/Native/Function/FunctionInstance.cs
  18. 33 7
      Jint/Native/Function/FunctionPrototype.cs
  19. 4 4
      Jint/Native/Global/GlobalObject.cs
  20. 1 1
      Jint/Native/Iterator/IteratorInstance.cs
  21. 1 1
      Jint/Native/JsString.cs
  22. 3 0
      Jint/Native/JsSymbol.cs
  23. 2 2
      Jint/Native/JsValue.cs
  24. 4 5
      Jint/Native/Map/MapInstance.cs
  25. 0 1
      Jint/Native/Object/ObjectClass.cs
  26. 181 76
      Jint/Native/Object/ObjectConstructor.cs
  27. 26 10
      Jint/Native/Object/ObjectInstance.cs
  28. 13 1
      Jint/Native/Object/ObjectPrototype.cs
  29. 1 1
      Jint/Native/Promise/PromiseConstructor.cs
  30. 37 30
      Jint/Native/Proxy/ProxyConstructor.cs
  31. 83 20
      Jint/Native/Proxy/ProxyInstance.cs
  32. 9 6
      Jint/Native/Reflect/ReflectInstance.cs
  33. 1 1
      Jint/Native/RegExp/RegExpPrototype.cs
  34. 4 5
      Jint/Native/Set/SetInstance.cs
  35. 4 2
      Jint/Native/String/StringConstructor.cs
  36. 16 5
      Jint/Native/String/StringInstance.cs
  37. 29 26
      Jint/Native/String/StringPrototype.cs
  38. 11 11
      Jint/Native/Symbol/SymbolConstructor.cs
  39. 5 3
      Jint/Native/Symbol/SymbolInstance.cs
  40. 14 4
      Jint/Native/Symbol/SymbolPrototype.cs
  41. 30 6
      Jint/Runtime/Descriptors/PropertyDescriptor.cs
  42. 2 2
      Jint/Runtime/Environments/FunctionEnvironmentRecord.cs
  43. 3 0
      Jint/Runtime/Environments/GlobalEnvironmentRecord.cs
  44. 2 2
      Jint/Runtime/Interpreter/Expressions/BindingPatternAssignmentExpression.cs
  45. 1 1
      Jint/Runtime/Interpreter/Expressions/JintArrayExpression.cs
  46. 2 2
      Jint/Runtime/Interpreter/Expressions/JintTaggedTemplateExpression.cs
  47. 1 1
      Jint/Runtime/Modules/ModuleNamespace.cs

+ 2 - 2
Jint.Tests.Ecma/TestCases/alltests.json

@@ -41310,8 +41310,8 @@
     source: "ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js"
     source: "ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-7.js"
   },
   },
   {
   {
-    skip: false,
-    reason: "",
+    skip: true,
+    reason: "not tested anymore, really slow",
     source: "ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-8.js"
     source: "ch15/15.4/15.4.4/15.4.4.15/15.4.4.15-3-8.js"
   },
   },
   {
   {

+ 0 - 21
Jint.Tests.Test262/test/built-ins/Proxy/create-handler-is-revoked-proxy.js

@@ -1,21 +0,0 @@
-// Copyright (C) 2015 the V8 project authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-/*---
-es6id: 9.5.15
-description: >
-    Proxy ( target, handler )
-    ...
-    4.  If handler is a Proxy exotic object and the value of the
-    [[ProxyHandler]] internal slot of handler is null, throw a
-    TypeError exception.
-    ...
-features: [Proxy]
----*/
-
-var revocable = Proxy.revocable({}, {});
-
-revocable.revoke();
-
-assert.throws(TypeError, function() {
-  new Proxy({}, revocable.proxy);
-});

+ 0 - 21
Jint.Tests.Test262/test/built-ins/Proxy/create-target-is-revoked-proxy.js

@@ -1,21 +0,0 @@
-// Copyright (C) 2015 the V8 project authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-/*---
-es6id: 9.5.15
-description: >
-    Proxy ( target, handler )
-    ...
-    2. If target is a Proxy exotic object and the value of the
-    [[ProxyHandler]] internal slot of target is null, throw a
-    TypeError exception.
-    ...
-features: [Proxy]
----*/
-
-var revocable = Proxy.revocable({}, {});
-
-revocable.revoke();
-
-assert.throws(TypeError, function() {
-  new Proxy(revocable.proxy, {});
-});

+ 0 - 19
Jint.Tests.Test262/test/built-ins/Proxy/revocable/revocation-function-name.js

@@ -1,19 +0,0 @@
-// Copyright (C) 2015 André Bargull. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-
-/*---
-es6id: 26.2.2.1.1
-description: The `name` property of Proxy Revocation functions
-info: |
-  A Proxy revocation function is an anonymous function.
-
-  17 ECMAScript Standard Built-in Objects:
-    Every built-in Function object, including constructors, that is not
-    identified as an anonymous function has a name property whose value
-    is a String.
-features: [Proxy]
----*/
-
-var revocationFunction = Proxy.revocable({}, {}).revoke;
-
-assert.sameValue(Object.prototype.hasOwnProperty.call(revocationFunction, "name"), false);

+ 0 - 26
Jint.Tests.Test262/test/language/computed-property-names/class/static/method-number.js

@@ -1,26 +0,0 @@
-// Copyright (C) 2014 the V8 project authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-/*---
-es6id: 12.2.5
-description: >
-    In a class, static computed property method names can be a number
-includes: [compareArray.js]
----*/
-class C {
-  static a() { return 'A'; }
-  static [1]() { return 'B'; }
-  static c() { return 'C'; }
-  static [2]() { return 'D'; }
-}
-assert.sameValue(C.a(), 'A', "`C.a()` returns `'A'`. Defined as `static a() { return 'A'; }`");
-assert.sameValue(C[1](), 'B', "`C[1]()` returns `'B'`. Defined as `static [1]() { return 'B'; }`");
-assert.sameValue(C.c(), 'C', "`C.c()` returns `'C'`. Defined as `static c() { return 'C'; }`");
-assert.sameValue(C[2](), 'D', "`C[2]()` returns `'D'`. Defined as `static [2]() { return 'D'; }`");
-assert(
-  compareArray(Object.keys(C), []),
-  "`compareArray(Object.keys(C), [])` returns `true`"
-);
-assert(
-  compareArray(Object.getOwnPropertyNames(C), ['1', '2', 'length', 'prototype', 'a', 'c', 'name']),
-  "`compareArray(Object.getOwnPropertyNames(C), ['1', '2', 'length', 'prototype', 'a', 'c', 'name'])` returns `true`"
-);

+ 0 - 26
Jint.Tests.Test262/test/language/computed-property-names/class/static/method-string.js

@@ -1,26 +0,0 @@
-// Copyright (C) 2014 the V8 project authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-/*---
-es6id: 12.2.5
-description: >
-    In a class, static computed property method names can be a string
-includes: [compareArray.js]
----*/
-class C {
-  static a() { return 'A'}
-  static ['b']() { return 'B'; }
-  static c() { return 'C'; }
-  static ['d']() { return 'D'; }
-}
-assert.sameValue(C.a(), 'A', "`C.a()` returns `'A'`. Defined as `static a() { return 'A'}`");
-assert.sameValue(C.b(), 'B', "`C.b()` returns `'B'`. Defined as `static ['b']() { return 'B'; }`");
-assert.sameValue(C.c(), 'C', "`C.c()` returns `'C'`. Defined as `static c() { return 'C'; }`");
-assert.sameValue(C.d(), 'D', "`C.d()` returns `'D'`. Defined as `static ['d']() { return 'D'; }`");
-assert(
-  compareArray(Object.keys(C), []),
-  "`compareArray(Object.keys(C), [])` returns `true`"
-);
-assert(
-  compareArray(Object.getOwnPropertyNames(C), ['length', 'prototype', 'a', 'b', 'c', 'd', 'name']),
-  "`compareArray(Object.getOwnPropertyNames(C), ['length', 'prototype', 'a', 'b', 'c', 'd', 'name'])` returns `true`"
-);

+ 0 - 33
Jint.Tests.Test262/test/language/computed-property-names/class/static/method-symbol.js

@@ -1,33 +0,0 @@
-// Copyright (C) 2014 the V8 project authors. All rights reserved.
-// This code is governed by the BSD license found in the LICENSE file.
-/*---
-es6id: 12.2.5
-description: >
-    In a class, static computed property method names can be a symbol
-includes: [compareArray.js]
-features: [Symbol]
----*/
-var sym1 = Symbol();
-var sym2 = Symbol();
-class C {
-  static a() { return 'A'; }
-  static [sym1]() { return 'B'; }
-  static c() { return 'C'; }
-  static [sym2]() { return 'D'; }
-}
-assert.sameValue(C.a(), 'A', "`C.a()` returns `'A'`. Defined as `static a() { return 'A'; }`");
-assert.sameValue(C[sym1](), 'B', "`C[sym1]()` returns `'B'`. Defined as `static [sym1]() { return 'B'; }`");
-assert.sameValue(C.c(), 'C', "`C.c()` returns `'C'`. Defined as `static c() { return 'C'; }`");
-assert.sameValue(C[sym2](), 'D', "`C[sym2]()` returns `'D'`. Defined as `static [sym2]() { return 'D'; }`");
-assert(
-  compareArray(Object.keys(C), []),
-  "`compareArray(Object.keys(C), [])` returns `true`"
-);
-assert(
-  compareArray(Object.getOwnPropertyNames(C), ['length', 'prototype', 'a', 'c', 'name']),
-  "`compareArray(Object.getOwnPropertyNames(C), ['length', 'prototype', 'a', 'c', 'name'])` returns `true`"
-);
-assert(
-  compareArray(Object.getOwnPropertySymbols(C), [sym1, sym2]),
-  "`compareArray(Object.getOwnPropertySymbols(C), [sym1, sym2])` returns `true`"
-);

+ 2 - 3
Jint.Tests/Runtime/NullPropagation.cs

@@ -1,5 +1,4 @@
-using System;
-using Esprima;
+using Esprima;
 using Jint.Native;
 using Jint.Native;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Interop;
 using Jint.Runtime.Interop;
@@ -30,7 +29,7 @@ namespace Jint.Tests.Runtime
                     var name = reference.GetReferencedName().AsString();
                     var name = reference.GetReferencedName().AsString();
                     if (name == "filter")
                     if (name == "filter")
                     {
                     {
-                        value = new ClrFunctionInstance(engine, "map", (thisObj, values) => engine.Realm.Intrinsics.Array.ConstructFast(0));
+                        value = new ClrFunctionInstance(engine, "map", (thisObj, values) => engine.Realm.Intrinsics.Array.ArrayCreate(0));
                         return true;
                         return true;
                     }
                     }
                 }
                 }

+ 29 - 34
Jint/Native/Array/ArrayConstructor.cs

@@ -1,6 +1,5 @@
 using System.Collections;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Runtime.CompilerServices;
 using Jint.Collections;
 using Jint.Collections;
 using Jint.Native.Function;
 using Jint.Native.Function;
 using Jint.Native.Iterator;
 using Jint.Native.Iterator;
@@ -62,7 +61,7 @@ namespace Jint.Native.Array
 
 
             if (source is JsString jsString)
             if (source is JsString jsString)
             {
             {
-                var a = _realm.Intrinsics.Array.ConstructFast((uint) jsString.Length);
+                var a = _realm.Intrinsics.Array.ArrayCreate((uint) jsString.Length);
                 for (int i = 0; i < jsString._value.Length; i++)
                 for (int i = 0; i < jsString._value.Length; i++)
                 {
                 {
                     a.SetIndexValue((uint) i, JsString.Create(jsString._value[i]), updateLength: false);
                     a.SetIndexValue((uint) i, JsString.Create(jsString._value[i]), updateLength: false);
@@ -70,9 +69,9 @@ namespace Jint.Native.Array
                 return a;
                 return a;
             }
             }
 
 
-            if (thisObj.IsNull() || !(source is ObjectInstance objectInstance))
+            if (thisObj.IsNull() || source is not ObjectInstance objectInstance)
             {
             {
-                return _realm.Intrinsics.Array.ConstructFast(0);
+                return _realm.Intrinsics.Array.ArrayCreate(0);
             }
             }
 
 
             if (objectInstance is IObjectWrapper wrapper && wrapper.Target is IEnumerable enumerable)
             if (objectInstance is IObjectWrapper wrapper && wrapper.Target is IEnumerable enumerable)
@@ -92,7 +91,7 @@ namespace Jint.Native.Array
             }
             }
             else
             else
             {
             {
-                instance = _realm.Intrinsics.Array.ConstructFast(0);
+                instance = _realm.Intrinsics.Array.ArrayCreate(0);
             }
             }
 
 
             if (objectInstance.TryGetIterator(_realm, out var iterator))
             if (objectInstance.TryGetIterator(_realm, out var iterator))
@@ -124,7 +123,7 @@ namespace Jint.Native.Array
             }
             }
             else
             else
             {
             {
-                a = _realm.Intrinsics.Array.ConstructFast(length);
+                a = _realm.Intrinsics.Array.ArrayCreate(length);
             }
             }
 
 
             var args = !ReferenceEquals(callable, null)
             var args = !ReferenceEquals(callable, null)
@@ -151,7 +150,7 @@ namespace Jint.Native.Array
                     jsValue = value;
                     jsValue = value;
                 }
                 }
 
 
-                target.Set(i, jsValue, updateLength: false, throwOnError: false);
+                target.CreateDataPropertyOrThrow(i, jsValue);
                 n++;
                 n++;
             }
             }
 
 
@@ -164,7 +163,7 @@ namespace Jint.Native.Array
             return a;
             return a;
         }
         }
 
 
-        internal sealed class ArrayProtocol : IteratorProtocol
+        private sealed class ArrayProtocol : IteratorProtocol
         {
         {
             private readonly JsValue _thisArg;
             private readonly JsValue _thisArg;
             private readonly ArrayOperations _instance;
             private readonly ArrayOperations _instance;
@@ -198,7 +197,7 @@ namespace Jint.Native.Array
                     jsValue = currentValue;
                     jsValue = currentValue;
                 }
                 }
 
 
-                _instance.Set((uint) _index, jsValue, updateLength: false, throwOnError: true);
+                _instance.CreateDataPropertyOrThrow((ulong) _index, jsValue);
             }
             }
 
 
             protected override void IterationEnd()
             protected override void IterationEnd()
@@ -288,12 +287,12 @@ namespace Jint.Native.Array
                 static intrinsics => intrinsics.Array.PrototypeObject);
                 static intrinsics => intrinsics.Array.PrototypeObject);
 
 
             // check if we can figure out good size
             // check if we can figure out good size
-            var capacity = arguments.Length > 0 ? (uint) arguments.Length : 0;
+            var capacity = arguments.Length > 0 ? (ulong) arguments.Length : 0;
             if (arguments.Length == 1 && arguments[0].IsNumber())
             if (arguments.Length == 1 && arguments[0].IsNumber())
             {
             {
                 var number = ((JsNumber) arguments[0])._value;
                 var number = ((JsNumber) arguments[0])._value;
                 ValidateLength(number);
                 ValidateLength(number);
-                capacity = (uint) number;
+                capacity = (ulong) number;
             }
             }
             return Construct(arguments, capacity, proto);
             return Construct(arguments, capacity, proto);
         }
         }
@@ -313,7 +312,7 @@ namespace Jint.Native.Array
             return Construct(arguments, capacity, PrototypeObject);
             return Construct(arguments, capacity, PrototypeObject);
         }
         }
 
 
-        private ArrayInstance Construct(JsValue[] arguments, uint capacity, ObjectInstance prototypeObject)
+        private ArrayInstance Construct(JsValue[] arguments, ulong capacity, ObjectInstance prototypeObject)
         {
         {
             var instance = ArrayCreate(capacity, prototypeObject);
             var instance = ArrayCreate(capacity, prototypeObject);
 
 
@@ -350,10 +349,15 @@ namespace Jint.Native.Array
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-arraycreate
         /// https://tc39.es/ecma262/#sec-arraycreate
         /// </summary>
         /// </summary>
-        internal ArrayInstance ArrayCreate(uint length, ObjectInstance proto = null)
+        internal ArrayInstance ArrayCreate(ulong length, ObjectInstance proto = null)
         {
         {
+            if (length > ArrayOperations.MaxArrayLength)
+            {
+                ExceptionHelper.ThrowRangeError(_realm, "Invalid array length " + length);
+            }
+
             proto ??= PrototypeObject;
             proto ??= PrototypeObject;
-            var instance = new ArrayInstance(Engine, length)
+            var instance = new ArrayInstance(Engine, (uint) length)
             {
             {
                 _prototype = proto,
                 _prototype = proto,
                 _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable)
                 _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable)
@@ -378,7 +382,7 @@ namespace Jint.Native.Array
 
 
         public ArrayInstance ConstructFast(JsValue[] contents)
         public ArrayInstance ConstructFast(JsValue[] contents)
         {
         {
-            var instance = ConstructFast((ulong) contents.Length);
+            var instance = ArrayCreate((ulong) contents.Length);
             for (var i = 0; i < contents.Length; i++)
             for (var i = 0; i < contents.Length; i++)
             {
             {
                 instance.SetIndexValue((uint) i, contents[i], updateLength: false);
                 instance.SetIndexValue((uint) i, contents[i], updateLength: false);
@@ -388,7 +392,7 @@ namespace Jint.Native.Array
 
 
         internal ArrayInstance ConstructFast(List<JsValue> contents)
         internal ArrayInstance ConstructFast(List<JsValue> contents)
         {
         {
-            var instance = ConstructFast((ulong) contents.Count);
+            var instance = ArrayCreate((ulong) contents.Count);
             for (var i = 0; i < contents.Count; i++)
             for (var i = 0; i < contents.Count; i++)
             {
             {
                 instance.SetIndexValue((uint) i, contents[i], updateLength: false);
                 instance.SetIndexValue((uint) i, contents[i], updateLength: false);
@@ -396,24 +400,15 @@ namespace Jint.Native.Array
             return instance;
             return instance;
         }
         }
 
 
-        [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal ArrayInstance ConstructFast(ulong length)
-        {
-            ValidateLength(length);
-            var instance = new ArrayInstance(Engine, (uint) length)
-            {
-                _prototype = PrototypeObject,
-                _length = new PropertyDescriptor(length, PropertyFlag.OnlyWritable)
-            };
-            return instance;
-        }
-
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-arrayspeciescreate
+        /// </summary>
         public ObjectInstance ArraySpeciesCreate(ObjectInstance originalArray, ulong length)
         public ObjectInstance ArraySpeciesCreate(ObjectInstance originalArray, ulong length)
         {
         {
             var isArray = originalArray.IsArray();
             var isArray = originalArray.IsArray();
             if (!isArray)
             if (!isArray)
             {
             {
-                return ConstructFast(length);
+                return ArrayCreate(length);
             }
             }
 
 
             var c = originalArray.Get(CommonProperties.Constructor);
             var c = originalArray.Get(CommonProperties.Constructor);
@@ -431,9 +426,9 @@ namespace Jint.Native.Array
                 }
                 }
             }
             }
 
 
-            if (c is ObjectInstance oi)
+            if (c.IsObject())
             {
             {
-                c = oi.Get(GlobalSymbolRegistry.Species);
+                c = c.Get(GlobalSymbolRegistry.Species);
                 if (c.IsNull())
                 if (c.IsNull())
                 {
                 {
                     c = Undefined;
                     c = Undefined;
@@ -442,7 +437,7 @@ namespace Jint.Native.Array
 
 
             if (c.IsUndefined())
             if (c.IsUndefined())
             {
             {
-                return ConstructFast(length);
+                return ArrayCreate(length);
             }
             }
 
 
             if (!c.IsConstructor)
             if (!c.IsConstructor)
@@ -455,7 +450,7 @@ namespace Jint.Native.Array
 
 
         internal JsValue CreateArrayFromList(List<JsValue> values)
         internal JsValue CreateArrayFromList(List<JsValue> values)
         {
         {
-            var jsArray = ConstructFast((uint) values.Count);
+            var jsArray = ArrayCreate((uint) values.Count);
             var index = 0;
             var index = 0;
             for (; index < values.Count; index++)
             for (; index < values.Count; index++)
             {
             {
@@ -469,7 +464,7 @@ namespace Jint.Native.Array
 
 
         private void ValidateLength(double length)
         private void ValidateLength(double length)
         {
         {
-            if (length < 0 || length > ArrayOperations.MaxArrayLength || ((long) length) != length)
+            if (length < 0 || length > ArrayOperations.MaxArrayLikeLength || ((long) length) != length)
             {
             {
                 ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");
                 ExceptionHelper.ThrowRangeError(_realm, "Invalid array length");
             }
             }

+ 45 - 25
Jint/Native/Array/ArrayInstance.cs

@@ -1,7 +1,6 @@
 using System.Collections;
 using System.Collections;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
-
 using Jint.Native.Object;
 using Jint.Native.Object;
 using Jint.Native.Symbol;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime;
@@ -72,9 +71,6 @@ namespace Jint.Native.Array
 
 
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         {
         {
-            var oldLenDesc = _length;
-            var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc.Value);
-
             if (property == CommonProperties.Length)
             if (property == CommonProperties.Length)
             {
             {
                 var value = desc.Value;
                 var value = desc.Value;
@@ -90,6 +86,9 @@ namespace Jint.Native.Array
                     ExceptionHelper.ThrowRangeError(_engine.Realm);
                     ExceptionHelper.ThrowRangeError(_engine.Realm);
                 }
                 }
 
 
+                var oldLenDesc = _length;
+                var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc.Value);
+
                 newLenDesc.Value = newLen;
                 newLenDesc.Value = newLen;
                 if (newLen >= oldLen)
                 if (newLen >= oldLen)
                 {
                 {
@@ -205,29 +204,38 @@ namespace Jint.Native.Array
 
 
                 return true;
                 return true;
             }
             }
-            else if (IsArrayIndex(property, out var index))
+
+            if (IsArrayIndex(property, out var index))
             {
             {
-                if (index >= oldLen && !oldLenDesc.Writable)
-                {
-                    return false;
-                }
+                return DefineOwnProperty(index, desc);
+            }
 
 
-                var succeeded = base.DefineOwnProperty(property, desc);
-                if (!succeeded)
-                {
-                    return false;
-                }
+            return base.DefineOwnProperty(property, desc);
+        }
 
 
-                if (index >= oldLen)
-                {
-                    oldLenDesc.Value = index + 1;
-                    base.DefineOwnProperty(CommonProperties.Length, oldLenDesc);
-                }
+        private bool DefineOwnProperty(uint index, PropertyDescriptor desc)
+        {
+            var oldLenDesc = _length;
+            var oldLen = (uint) TypeConverter.ToNumber(oldLenDesc.Value);
 
 
-                return true;
+            if (index >= oldLen && !oldLenDesc.Writable)
+            {
+                return false;
             }
             }
 
 
-            return base.DefineOwnProperty(property, desc);
+            var succeeded = base.DefineOwnProperty(index, desc);
+            if (!succeeded)
+            {
+                return false;
+            }
+
+            if (index >= oldLen)
+            {
+                oldLenDesc.Value = index + 1;
+                base.DefineOwnProperty(CommonProperties.Length, oldLenDesc);
+            }
+
+            return true;
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -265,6 +273,11 @@ namespace Jint.Native.Array
 
 
         public override List<JsValue> GetOwnPropertyKeys(Types types = Types.None | Types.String | Types.Symbol)
         public override List<JsValue> GetOwnPropertyKeys(Types types = Types.None | Types.String | Types.Symbol)
         {
         {
+            if ((types & Types.String) == 0)
+            {
+                return base.GetOwnPropertyKeys(types);
+            }
+
             var properties = new List<JsValue>(_dense?.Length ?? 0 + 1);
             var properties = new List<JsValue>(_dense?.Length ?? 0 + 1);
             if (_dense != null)
             if (_dense != null)
             {
             {
@@ -734,7 +747,7 @@ namespace Jint.Native.Array
             }
             }
             else
             else
             {
             {
-                if (!Set(CommonProperties.Length, newLength, this))
+                if (!Set(CommonProperties.Length, newLength))
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_engine.Realm);
                     ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
@@ -750,7 +763,7 @@ namespace Jint.Native.Array
                 return _length.Writable;
                 return _length.Writable;
             }
             }
             var set = _length.Set;
             var set = _length.Set;
-            return !(set is null) && !set.IsUndefined();
+            return set is not null && !set.IsUndefined();
         }
         }
 
 
         [MethodImpl(MethodImplOptions.NoInlining)]
         [MethodImpl(MethodImplOptions.NoInlining)]
@@ -774,7 +787,7 @@ namespace Jint.Native.Array
             var len = GetLength();
             var len = GetLength();
 
 
             var callable = GetCallable(callbackfn);
             var callable = GetCallable(callbackfn);
-            var a = Engine.Realm.Intrinsics.Array.ConstructFast(len);
+            var a = Engine.Realm.Intrinsics.Array.ArrayCreate(len);
             var args = _engine._jsValueArrayPool.RentArray(3);
             var args = _engine._jsValueArrayPool.RentArray(3);
             args[2] = this;
             args[2] = this;
             for (uint k = 0; k < len; k++)
             for (uint k = 0; k < len; k++)
@@ -867,9 +880,14 @@ namespace Jint.Native.Array
                 return;
                 return;
             }
             }
 
 
-            var dense = _dense;
             var sourceDense = source._dense;
             var sourceDense = source._dense;
 
 
+            if (sourceDense is not null)
+            {
+                EnsureCapacity((uint) sourceDense.LongLength);
+            }
+
+            var dense = _dense;
             if (dense != null && sourceDense != null
             if (dense != null && sourceDense != null
                                && (uint) dense.Length >= targetStartIndex + length
                                && (uint) dense.Length >= targetStartIndex + length
                                && dense[targetStartIndex] is null)
                                && dense[targetStartIndex] is null)
@@ -895,6 +913,8 @@ namespace Jint.Native.Array
                     {
                     {
                         SetIndexValue(targetStartIndex, subElement, updateLength: false);
                         SetIndexValue(targetStartIndex, subElement, updateLength: false);
                     }
                     }
+
+                    targetStartIndex++;
                 }
                 }
             }
             }
         }
         }

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

@@ -72,7 +72,7 @@ namespace Jint.Native.Array
 
 
         public abstract void CreateDataPropertyOrThrow(ulong index, JsValue value);
         public abstract void CreateDataPropertyOrThrow(ulong index, JsValue value);
 
 
-        public abstract void Set(ulong index, JsValue value, bool updateLength, bool throwOnError);
+        public abstract void Set(ulong index, JsValue value, bool throwOnError);
 
 
         public abstract void DeletePropertyOrThrow(ulong index);
         public abstract void DeletePropertyOrThrow(ulong index);
 
 
@@ -226,7 +226,7 @@ namespace Jint.Native.Array
             public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
             public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
                 => _target.CreateDataPropertyOrThrow(JsString.Create(index), value);
                 => _target.CreateDataPropertyOrThrow(JsString.Create(index), value);
 
 
-            public override void Set(ulong index, JsValue value, bool updateLength, bool throwOnError)
+            public override void Set(ulong index, JsValue value, bool throwOnError)
                 => _target.Set(JsString.Create(index), value, throwOnError);
                 => _target.Set(JsString.Create(index), value, throwOnError);
 
 
             public override void DeletePropertyOrThrow(ulong index)
             public override void DeletePropertyOrThrow(ulong index)
@@ -297,8 +297,8 @@ namespace Jint.Native.Array
             public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
             public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
                 => _target.SetIndexValue((uint) index, value, updateLength: false);
                 => _target.SetIndexValue((uint) index, value, updateLength: false);
 
 
-            public override void Set(ulong index, JsValue value, bool updateLength, bool throwOnError)
-                => _target.SetIndexValue((uint) index, value, updateLength);
+            public override void Set(ulong index, JsValue value, bool throwOnError)
+                => _target.Set((uint) index, value, throwOnError);
         }
         }
 
 
         private sealed class TypedArrayInstanceOperations : ArrayOperations
         private sealed class TypedArrayInstanceOperations : ArrayOperations
@@ -357,7 +357,7 @@ namespace Jint.Native.Array
             public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
             public override void CreateDataPropertyOrThrow(ulong index, JsValue value)
                 => _target.CreateDataPropertyOrThrow(index, value);
                 => _target.CreateDataPropertyOrThrow(index, value);
 
 
-            public override void Set(ulong index, JsValue value, bool updateLength, bool throwOnError)
+            public override void Set(ulong index, JsValue value, bool throwOnError)
                 => _target[(int) index] = value;
                 => _target[(int) index] = value;
 
 
             public override void DeletePropertyOrThrow(ulong index)
             public override void DeletePropertyOrThrow(ulong index)

+ 138 - 124
Jint/Native/Array/ArrayPrototype.cs

@@ -14,7 +14,7 @@ using Jint.Runtime.Interop;
 namespace Jint.Native.Array
 namespace Jint.Native.Array
 {
 {
     /// <summary>
     /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4
+    /// https://tc39.es/ecma262/#sec-properties-of-the-array-prototype-object
     /// </summary>
     /// </summary>
     public sealed class ArrayPrototype : ArrayInstance
     public sealed class ArrayPrototype : ArrayInstance
     {
     {
@@ -134,65 +134,64 @@ namespace Jint.Native.Array
             return null;
             return null;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.fill
+        /// </summary>
         private JsValue Fill(JsValue thisObj, JsValue[] arguments)
         private JsValue Fill(JsValue thisObj, JsValue[] arguments)
         {
         {
-            if (thisObj.IsNullOrUndefined())
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Cannot convert undefined or null to object");
-            }
+            var o = TypeConverter.ToObject(_realm, thisObj);
 
 
-            var operations = ArrayOperations.For(thisObj as ObjectInstance);
-            var length = operations.GetLength();
+            var operations = ArrayOperations.For(o);
+            var length = operations.GetLongLength();
 
 
             var value = arguments.At(0);
             var value = arguments.At(0);
 
 
             var start = ConvertAndCheckForInfinity(arguments.At(1), 0);
             var start = ConvertAndCheckForInfinity(arguments.At(1), 0);
 
 
             var relativeStart = TypeConverter.ToInteger(start);
             var relativeStart = TypeConverter.ToInteger(start);
-            uint actualStart;
+            ulong actualStart;
             if (relativeStart < 0)
             if (relativeStart < 0)
             {
             {
-                actualStart = (uint) System.Math.Max(length + relativeStart, 0);
+                actualStart = (ulong) System.Math.Max(length + relativeStart, 0);
             }
             }
             else
             else
             {
             {
-                actualStart = (uint) System.Math.Min(relativeStart, length);
+                actualStart = (ulong) System.Math.Min(relativeStart, length);
             }
             }
 
 
-            var end = ConvertAndCheckForInfinity(arguments.At(2), length);
+            var end = ConvertAndCheckForInfinity(arguments.At(2), (long) length);
             var relativeEnd = TypeConverter.ToInteger(end);
             var relativeEnd = TypeConverter.ToInteger(end);
-            uint actualEnd;
+            ulong actualEnd;
             if (relativeEnd < 0)
             if (relativeEnd < 0)
             {
             {
-                actualEnd = (uint) System.Math.Max(length + relativeEnd, 0);
+                actualEnd = (ulong) System.Math.Max(length + relativeEnd, 0);
             }
             }
             else
             else
             {
             {
-                actualEnd = (uint) System.Math.Min(relativeEnd, length);
+                actualEnd = (ulong) System.Math.Min(relativeEnd, length);
             }
             }
 
 
             for (var i = actualStart; i < actualEnd; ++i)
             for (var i = actualStart; i < actualEnd; ++i)
             {
             {
-                operations.Set(i, value, updateLength: false, throwOnError: false);
+                operations.Set(i, value, throwOnError: false);
             }
             }
 
 
-            return thisObj;
+            return o;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.copywithin
+        /// </summary>
         private JsValue CopyWithin(JsValue thisObj, JsValue[] arguments)
         private JsValue CopyWithin(JsValue thisObj, JsValue[] arguments)
         {
         {
-            // Steps 1-2.
-            if (thisObj.IsNullOrUndefined())
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "this is null or not defined");
-            }
+            var o = TypeConverter.ToObject(_realm, thisObj);
 
 
             JsValue target = arguments.At(0);
             JsValue target = arguments.At(0);
             JsValue start = arguments.At(1);
             JsValue start = arguments.At(1);
             JsValue end = arguments.At(2);
             JsValue end = arguments.At(2);
 
 
-            var operations = ArrayOperations.For(thisObj as ObjectInstance);
-            var initialLength = operations.GetLength();
+            var operations = ArrayOperations.For(o);
+            var initialLength = operations.GetLongLength();
             var len = ConvertAndCheckForInfinity(initialLength, 0);
             var len = ConvertAndCheckForInfinity(initialLength, 0);
 
 
             var relativeTarget = ConvertAndCheckForInfinity(target, 0);
             var relativeTarget = ConvertAndCheckForInfinity(target, 0);
@@ -215,13 +214,13 @@ namespace Jint.Native.Array
 
 
             var count = System.Math.Min(final - from, len - to);
             var count = System.Math.Min(final - from, len - to);
 
 
-            var direction = 1;
+            long direction = 1;
 
 
             if (from < to && to < from + count)
             if (from < to && to < from + count)
             {
             {
                 direction = -1;
                 direction = -1;
-                from += (uint) count - 1;
-                to += (uint) count - 1;
+                from += count - 1;
+                to += count - 1;
             }
             }
 
 
             while (count > 0)
             while (count > 0)
@@ -230,21 +229,21 @@ namespace Jint.Native.Array
                 if (fromPresent)
                 if (fromPresent)
                 {
                 {
                     var fromValue = operations.Get((ulong) from);
                     var fromValue = operations.Get((ulong) from);
-                    operations.Set((ulong) to, fromValue, updateLength: true, throwOnError: true);
+                    operations.Set((ulong) to, fromValue, throwOnError: true);
                 }
                 }
                 else
                 else
                 {
                 {
                     operations.DeletePropertyOrThrow((ulong) to);
                     operations.DeletePropertyOrThrow((ulong) to);
                 }
                 }
-                from = (uint) (from + direction);
-                to = (uint) (to + direction);
+                from += direction;
+                to += direction;
                 count--;
                 count--;
             }
             }
 
 
-            return thisObj;
+            return o;
         }
         }
 
 
-        long ConvertAndCheckForInfinity(JsValue jsValue, long defaultValue)
+        static long ConvertAndCheckForInfinity(JsValue jsValue, long defaultValue)
         {
         {
             if (jsValue.IsUndefined())
             if (jsValue.IsUndefined())
             {
             {
@@ -261,13 +260,16 @@ namespace Jint.Native.Array
             return (long) num;
             return (long) num;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.lastindexof
+        /// </summary>
         private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments)
         {
         {
             var o = ArrayOperations.For(_realm, thisObj);
             var o = ArrayOperations.For(_realm, thisObj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             if (len == 0)
             if (len == 0)
             {
             {
-                return -1;
+                return JsNumber.IntegerNegativeOne;
             }
             }
 
 
             var n = arguments.Length > 1
             var n = arguments.Length > 1
@@ -283,14 +285,14 @@ namespace Jint.Native.Array
                 k = len - System.Math.Abs(n);
                 k = len - System.Math.Abs(n);
             }
             }
 
 
-            if (k < 0 || k > uint.MaxValue)
+            if (k < 0 || k > ArrayOperations.MaxArrayLikeLength)
             {
             {
-                return -1;
+                return JsNumber.IntegerNegativeOne;
             }
             }
 
 
             var searchElement = arguments.At(0);
             var searchElement = arguments.At(0);
-            var i = (uint) k;
-            for (;; i--)
+            var i = (ulong) k;
+            for (; ; i--)
             {
             {
                 var kPresent = o.HasProperty(i);
                 var kPresent = o.HasProperty(i);
                 if (kPresent)
                 if (kPresent)
@@ -308,9 +310,12 @@ namespace Jint.Native.Array
                 }
                 }
             }
             }
 
 
-            return -1;
+            return JsNumber.IntegerNegativeOne;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.reduce
+        /// </summary>
         private JsValue Reduce(JsValue thisObj, JsValue[] arguments)
         private JsValue Reduce(JsValue thisObj, JsValue[] arguments)
         {
         {
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
@@ -370,6 +375,9 @@ namespace Jint.Native.Array
             return accumulator;
             return accumulator;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.filter
+        /// </summary>
         private JsValue Filter(JsValue thisObj, JsValue[] arguments)
         private JsValue Filter(JsValue thisObj, JsValue[] arguments)
         {
         {
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
@@ -395,7 +403,7 @@ namespace Jint.Native.Array
                     var selected = callable.Call(thisArg, args);
                     var selected = callable.Call(thisArg, args);
                     if (TypeConverter.ToBoolean(selected))
                     if (TypeConverter.ToBoolean(selected))
                     {
                     {
-                        operations.Set(to, kvalue, updateLength: false, throwOnError: false);
+                        operations.CreateDataPropertyOrThrow(to, kvalue);
                         to++;
                         to++;
                     }
                     }
                 }
                 }
@@ -407,6 +415,9 @@ namespace Jint.Native.Array
             return a;
             return a;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.map
+        /// </summary>
         private JsValue Map(JsValue thisObj, JsValue[] arguments)
         private JsValue Map(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj is ArrayInstance arrayInstance && !arrayInstance.HasOwnProperty(CommonProperties.Constructor))
             if (thisObj is ArrayInstance arrayInstance && !arrayInstance.HasOwnProperty(CommonProperties.Constructor))
@@ -436,7 +447,7 @@ namespace Jint.Native.Array
                     args[0] = kvalue;
                     args[0] = kvalue;
                     args[1] = k;
                     args[1] = k;
                     var mappedValue = callable.Call(thisArg, args);
                     var mappedValue = callable.Call(thisArg, args);
-                    a.Set(k, mappedValue, updateLength: false, throwOnError: false);
+                    a.CreateDataPropertyOrThrow(k, mappedValue);
                 }
                 }
             }
             }
             _engine._jsValueArrayPool.ReturnArray(args);
             _engine._jsValueArrayPool.ReturnArray(args);
@@ -678,9 +689,9 @@ namespace Jint.Native.Array
                 ? TypeConverter.ToNumber(arguments[1])
                 ? TypeConverter.ToNumber(arguments[1])
                 : 0;
                 : 0;
 
 
-            if (startIndex > uint.MaxValue)
+            if (startIndex > ArrayOperations.MaxArrayLikeLength)
             {
             {
-                return -1;
+                return JsNumber.IntegerNegativeOne;
             }
             }
 
 
             ulong k;
             ulong k;
@@ -772,12 +783,16 @@ namespace Jint.Native.Array
             return target.Get(actualIndex);
             return target.Get(actualIndex);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.splice
+        /// </summary>
         private JsValue Splice(JsValue thisObj, JsValue[] arguments)
         private JsValue Splice(JsValue thisObj, JsValue[] arguments)
         {
         {
             var start = arguments.At(0);
             var start = arguments.At(0);
             var deleteCount = arguments.At(1);
             var deleteCount = arguments.At(1);
 
 
-            var o = ArrayOperations.For(_realm, thisObj);
+            var obj = TypeConverter.ToObject(_realm, thisObj);
+            var o = ArrayOperations.For(_realm, obj);
             var len = o.GetLongLength();
             var len = o.GetLongLength();
             var relativeStart = TypeConverter.ToInteger(start);
             var relativeStart = TypeConverter.ToInteger(start);
 
 
@@ -823,7 +838,7 @@ namespace Jint.Native.Array
                 ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
                 ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
             }
             }
 
 
-            var instance = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), actualDeleteCount);
+            var instance = _realm.Intrinsics.Array.ArraySpeciesCreate(obj, actualDeleteCount);
             var a = ArrayOperations.For(instance);
             var a = ArrayOperations.For(instance);
             for (uint k = 0; k < actualDeleteCount; k++)
             for (uint k = 0; k < actualDeleteCount; k++)
             {
             {
@@ -847,7 +862,7 @@ namespace Jint.Native.Array
                     if (o.HasProperty(from))
                     if (o.HasProperty(from))
                     {
                     {
                         var fromValue = o.Get(from);
                         var fromValue = o.Get(from);
-                        o.Set(to, fromValue, updateLength: false, throwOnError: false);
+                        o.Set(to, fromValue, throwOnError: false);
                     }
                     }
                     else
                     else
                     {
                     {
@@ -869,7 +884,7 @@ namespace Jint.Native.Array
                     if (o.HasProperty(from))
                     if (o.HasProperty(from))
                     {
                     {
                         var fromValue = o.Get(from);
                         var fromValue = o.Get(from);
-                        o.Set(to, fromValue, updateLength: false, throwOnError: true);
+                        o.Set(to, fromValue, throwOnError: true);
                     }
                     }
                     else
                     else
                     {
                     {
@@ -881,7 +896,7 @@ namespace Jint.Native.Array
             for (uint k = 0; k < items.Length; k++)
             for (uint k = 0; k < items.Length; k++)
             {
             {
                 var e = items[k];
                 var e = items[k];
-                o.Set(k + actualStart, e, updateLength: false, throwOnError: true);
+                o.Set(k + actualStart, e, throwOnError: true);
             }
             }
 
 
             o.SetLength(length);
             o.SetLength(length);
@@ -907,7 +922,7 @@ namespace Jint.Native.Array
                 var to = k + argCount - 1;
                 var to = k + argCount - 1;
                 if (o.TryGetValue(from, out var fromValue))
                 if (o.TryGetValue(from, out var fromValue))
                 {
                 {
-                    o.Set(to, fromValue, false, true);
+                    o.Set(to, fromValue, true);
                 }
                 }
                 else
                 else
                 {
                 {
@@ -917,32 +932,31 @@ namespace Jint.Native.Array
 
 
             for (uint j = 0; j < argCount; j++)
             for (uint j = 0; j < argCount; j++)
             {
             {
-                o.Set(j, arguments[j], false, true);
+                o.Set(j, arguments[j], true);
             }
             }
 
 
             o.SetLength(len + argCount);
             o.SetLength(len + argCount);
             return len + argCount;
             return len + argCount;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.sort
+        /// </summary>
         private JsValue Sort(JsValue thisObj, JsValue[] arguments)
         private JsValue Sort(JsValue thisObj, JsValue[] arguments)
         {
         {
-            if (!thisObj.IsObject())
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Array.prototype.sort can only be applied on objects");
-            }
-
-            var obj = ArrayOperations.For(thisObj.AsObject());
+            var obj = ArrayOperations.For(TypeConverter.ToObject(_realm, thisObj));
 
 
             var compareArg = arguments.At(0);
             var compareArg = arguments.At(0);
             ICallable compareFn = null;
             ICallable compareFn = null;
             if (!compareArg.IsUndefined())
             if (!compareArg.IsUndefined())
             {
             {
-                if (compareArg.IsNull() || !(compareArg is ICallable))
+                if (compareArg is not ICallable callable)
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_realm, "The comparison function must be either a function or undefined");
                     ExceptionHelper.ThrowTypeError(_realm, "The comparison function must be either a function or undefined");
+                    return null;
                 }
                 }
 
 
-                compareFn = (ICallable) compareArg;
+                compareFn = callable;
             }
             }
 
 
             var len = obj.GetLength();
             var len = obj.GetLength();
@@ -951,22 +965,35 @@ namespace Jint.Native.Array
                 return obj.Target;
                 return obj.Target;
             }
             }
 
 
+            var items = new List<JsValue>((int) System.Math.Min(10_000, obj.GetLength()));
+            for (ulong k = 0; k < len; ++k)
+            {
+                if (obj.TryGetValue(k, out var kValue))
+                {
+                    items.Add(kValue);
+                }
+            }
+
+            var itemCount = items.Count;
+
             // don't eat inner exceptions
             // don't eat inner exceptions
             try
             try
             {
             {
-                var array = obj.OrderBy(x => x, ArrayComparer.WithFunction(_engine, compareFn)).ToArray();
+                var array = items.OrderBy(x => x, ArrayComparer.WithFunction(_engine, compareFn)).ToArray();
 
 
-                for (uint i = 0; i < (uint) array.Length; ++i)
+                uint j;
+                for (j = 0; j < itemCount; ++j)
                 {
                 {
-                    if (!ReferenceEquals(array[i], null))
-                    {
-                        obj.Set(i, array[i], updateLength: false, throwOnError: false);
-                    }
-                    else
+                    if (!ReferenceEquals(array[j], null))
                     {
                     {
-                        obj.DeletePropertyOrThrow(i);
+                        obj.Set(j, array[j], throwOnError: true);
                     }
                     }
                 }
                 }
+
+                for (; j < len; ++j)
+                {
+                    obj.DeletePropertyOrThrow(j);
+                }
             }
             }
             catch (InvalidOperationException e)
             catch (InvalidOperationException e)
             {
             {
@@ -976,6 +1003,9 @@ namespace Jint.Native.Array
             return obj.Target;
             return obj.Target;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.slice
+        /// </summary>
         private JsValue Slice(JsValue thisObj, JsValue[] arguments)
         private JsValue Slice(JsValue thisObj, JsValue[] arguments)
         {
         {
             var start = arguments.At(0);
             var start = arguments.At(0);
@@ -1032,11 +1062,11 @@ namespace Jint.Native.Array
                 {
                 {
                     if (o.TryGetValue(k, out var kValue))
                     if (o.TryGetValue(k, out var kValue))
                     {
                     {
-                        operations.Set(n, kValue, updateLength: false, throwOnError: false);
+                        operations.CreateDataPropertyOrThrow(n, kValue);
                     }
                     }
                 }
                 }
             }
             }
-            a.DefineOwnProperty(CommonProperties.Length, new PropertyDescriptor(length, PropertyFlag.None));
+            a.DefineOwnProperty(CommonProperties.Length, new PropertyDescriptor(length, PropertyFlag.ConfigurableEnumerableWritable));
 
 
             return a;
             return a;
         }
         }
@@ -1057,7 +1087,7 @@ namespace Jint.Native.Array
                 var to = k - 1;
                 var to = k - 1;
                 if (o.TryGetValue(k, out var fromVal))
                 if (o.TryGetValue(k, out var fromVal))
                 {
                 {
-                    o.Set(to, fromVal, updateLength: false, throwOnError: false);
+                    o.Set(to, fromVal, throwOnError: false);
                 }
                 }
                 else
                 else
                 {
                 {
@@ -1071,6 +1101,9 @@ namespace Jint.Native.Array
             return first;
             return first;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.reverse
+        /// </summary>
         private JsValue Reverse(JsValue thisObj, JsValue[] arguments)
         private JsValue Reverse(JsValue thisObj, JsValue[] arguments)
         {
         {
             var o = ArrayOperations.For(_realm, thisObj);
             var o = ArrayOperations.For(_realm, thisObj);
@@ -1089,20 +1122,20 @@ namespace Jint.Native.Array
 
 
                 if (lowerExists && upperExists)
                 if (lowerExists && upperExists)
                 {
                 {
-                    o.Set(lower, upperValue, updateLength: true, throwOnError: true);
-                    o.Set(upper, lowerValue, updateLength: true, throwOnError: true);
+                    o.Set(lower, upperValue, throwOnError: true);
+                    o.Set(upper, lowerValue, throwOnError: true);
                 }
                 }
 
 
                 if (!lowerExists && upperExists)
                 if (!lowerExists && upperExists)
                 {
                 {
-                    o.Set(lower, upperValue, updateLength: true, throwOnError: true);
+                    o.Set(lower, upperValue, throwOnError: true);
                     o.DeletePropertyOrThrow(upper);
                     o.DeletePropertyOrThrow(upper);
                 }
                 }
 
 
                 if (lowerExists && !upperExists)
                 if (lowerExists && !upperExists)
                 {
                 {
                     o.DeletePropertyOrThrow(lower);
                     o.DeletePropertyOrThrow(lower);
-                    o.Set(upper, lowerValue, updateLength: true, throwOnError: true);
+                    o.Set(upper, lowerValue, throwOnError: true);
                 }
                 }
 
 
                 lower++;
                 lower++;
@@ -1200,79 +1233,56 @@ namespace Jint.Native.Array
             return r;
             return r;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.concat
+        /// </summary>
         private JsValue Concat(JsValue thisObj, JsValue[] arguments)
         private JsValue Concat(JsValue thisObj, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, thisObj);
             var o = TypeConverter.ToObject(_realm, thisObj);
             var items = new List<JsValue>(arguments.Length + 1) {o};
             var items = new List<JsValue>(arguments.Length + 1) {o};
             items.AddRange(arguments);
             items.AddRange(arguments);
 
 
-            // try to find best capacity
-            bool hasObjectSpreadables = false;
-            ulong capacity = 0;
+            uint n = 0;
+            var a = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), 0);
+            var aOperations = ArrayOperations.For(a);
             for (var i = 0; i < items.Count; i++)
             for (var i = 0; i < items.Count; i++)
             {
             {
-                ulong increment;
-                if (items[i] is not ObjectInstance objectInstance)
-                {
-                    increment = 1;
-                }
-                else
+                var e = items[i];
+                if (e is ObjectInstance oi && oi.IsConcatSpreadable)
                 {
                 {
-                    var isConcatSpreadable = objectInstance.IsConcatSpreadable;
-                    hasObjectSpreadables |= isConcatSpreadable;
-                    if (isConcatSpreadable)
+                    if (e is ArrayInstance eArray && a is ArrayInstance a2)
                     {
                     {
-                        increment = ArrayOperations.For(objectInstance).GetLongLength();
+                        a2.CopyValues(eArray, 0, n, eArray.GetLength());
+                        n += eArray.GetLength();
                     }
                     }
                     else
                     else
                     {
                     {
-                        increment = 1;
-                    }
-                }
-                capacity += increment;
-            }
+                        var operations = ArrayOperations.For(oi);
+                        var len = operations.GetLongLength();
 
 
-            if (capacity > NumberConstructor.MaxSafeInteger)
-            {
-                ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
-            }
+                        if (n + len > ArrayOperations.MaxArrayLikeLength)
+                        {
+                            ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
+                        }
 
 
-            uint n = 0;
-            var a = _realm.Intrinsics.Array.ArraySpeciesCreate(TypeConverter.ToObject(_realm, thisObj), capacity);
-            var aOperations = ArrayOperations.For(a);
-            for (var i = 0; i < items.Count; i++)
-            {
-                var e = items[i];
-                if (e is ArrayInstance eArray
-                    && eArray.IsConcatSpreadable
-                    && a is ArrayInstance a2)
-                {
-                    a2.CopyValues(eArray, 0, n, eArray.GetLength());
-                    n += eArray.GetLength();
-                }
-                else if (hasObjectSpreadables
-                         && e is ObjectInstance oi
-                         && oi.IsConcatSpreadable)
-                {
-                    var operations = ArrayOperations.For(oi);
-                    var len = operations.GetLength();
-                    for (uint k = 0; k < len; k++)
-                    {
-                        operations.TryGetValue(k, out var subElement);
-                        aOperations.Set(n, subElement, updateLength: false, throwOnError: false);
-                        n++;
+                        for (uint k = 0; k < len; k++)
+                        {
+                            operations.TryGetValue(k, out var subElement);
+                            aOperations.CreateDataPropertyOrThrow(n, subElement);
+                            n++;
+                        }
                     }
                     }
                 }
                 }
                 else
                 else
                 {
                 {
-                    aOperations.Set(n, e, updateLength: false, throwOnError: false);
+                    aOperations.CreateDataPropertyOrThrow(n, e);
                     n++;
                     n++;
                 }
                 }
             }
             }
 
 
             // this is not in the specs, but is necessary in case the last element of the last
             // this is not in the specs, but is necessary in case the last element of the last
             // array doesn't exist, and thus the length would not be incremented
             // array doesn't exist, and thus the length would not be incremented
-            a.DefineOwnProperty(CommonProperties.Length, new PropertyDescriptor(n, PropertyFlag.None));
+            a.DefineOwnProperty(CommonProperties.Length, new PropertyDescriptor(n, PropertyFlag.OnlyWritable));
 
 
             return a;
             return a;
         }
         }
@@ -1282,8 +1292,7 @@ namespace Jint.Native.Array
             var array = TypeConverter.ToObject(_realm, thisObj);
             var array = TypeConverter.ToObject(_realm, thisObj);
 
 
             Func<JsValue, JsValue[], JsValue> func;
             Func<JsValue, JsValue[], JsValue> func;
-            var joinFunc = array.Get("join") as ICallable;
-            if (joinFunc is not null)
+            if (array.Get("join") is ICallable joinFunc)
             {
             {
                 func = joinFunc.Call;
                 func = joinFunc.Call;
             }
             }
@@ -1295,6 +1304,9 @@ namespace Jint.Native.Array
             return func(array, Arguments.Empty);
             return func(array, Arguments.Empty);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.reduceright
+        /// </summary>
         private JsValue ReduceRight(JsValue thisObj, JsValue[] arguments)
         private JsValue ReduceRight(JsValue thisObj, JsValue[] arguments)
         {
         {
             var callbackfn = arguments.At(0);
             var callbackfn = arguments.At(0);
@@ -1351,6 +1363,9 @@ namespace Jint.Native.Array
             return accumulator;
             return accumulator;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-array.prototype.push
+        /// </summary>
         public JsValue Push(JsValue thisObject, JsValue[] arguments)
         public JsValue Push(JsValue thisObject, JsValue[] arguments)
         {
         {
             if (thisObject is ArrayInstance arrayInstance)
             if (thisObject is ArrayInstance arrayInstance)
@@ -1358,7 +1373,7 @@ namespace Jint.Native.Array
                 return arrayInstance.Push(arguments);
                 return arrayInstance.Push(arguments);
             }
             }
 
 
-            var o = ArrayOperations.For(thisObject as ObjectInstance);
+            var o = ArrayOperations.For(TypeConverter.ToObject(_realm, thisObject));
             var n = o.GetLongLength();
             var n = o.GetLongLength();
 
 
             if (n + (ulong) arguments.Length > ArrayOperations.MaxArrayLikeLength)
             if (n + (ulong) arguments.Length > ArrayOperations.MaxArrayLikeLength)
@@ -1366,10 +1381,9 @@ namespace Jint.Native.Array
                 ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
                 ExceptionHelper.ThrowTypeError(_realm, "Invalid array length");
             }
             }
 
 
-            // cast to double as we need to prevent an overflow
             foreach (var a in arguments)
             foreach (var a in arguments)
             {
             {
-                o.Set(n, a, false, false);
+                o.Set(n, a, true);
                 n++;
                 n++;
             }
             }
 
 

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

@@ -22,7 +22,7 @@ namespace Jint.Native.Boolean
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
-        public BooleanPrototype PrototypeObject { get; private set; }
+        public BooleanPrototype PrototypeObject { get; }
 
 
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         public override JsValue Call(JsValue thisObject, JsValue[] arguments)
         {
         {

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

@@ -9,6 +9,9 @@ using Jint.Runtime.Interop;
 
 
 namespace Jint.Native.Date
 namespace Jint.Native.Date
 {
 {
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-date-constructor
+    /// </summary>
     public sealed class DateConstructor : FunctionInstance, IConstructor
     public sealed class DateConstructor : FunctionInstance, IConstructor
     {
     {
         internal static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
         internal static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
@@ -67,6 +70,8 @@ namespace Jint.Native.Date
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
+        public DatePrototype PrototypeObject { get; }
+
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
@@ -103,7 +108,7 @@ namespace Jint.Native.Date
             return FromDateTime(result);
             return FromDateTime(result);
         }
         }
 
 
-        private JsValue Utc(JsValue thisObj, JsValue[] arguments)
+        private static JsValue Utc(JsValue thisObj, JsValue[] arguments)
         {
         {
             var y = TypeConverter.ToNumber(arguments.At(0));
             var y = TypeConverter.ToNumber(arguments.At(0));
             var m = TypeConverter.ToNumber(arguments.At(1, JsNumber.PositiveZero));
             var m = TypeConverter.ToNumber(arguments.At(1, JsNumber.PositiveZero));
@@ -194,8 +199,6 @@ namespace Jint.Native.Date
             return o;
             return o;
         }
         }
 
 
-        public DatePrototype PrototypeObject { get; private set; }
-
         public DateInstance Construct(DateTimeOffset value)
         public DateInstance Construct(DateTimeOffset value)
         {
         {
             return Construct(value.UtcDateTime);
             return Construct(value.UtcDateTime);

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

@@ -5,7 +5,7 @@ using Jint.Runtime;
 
 
 namespace Jint.Native.Date
 namespace Jint.Native.Date
 {
 {
-    public class DateInstance : ObjectInstance
+    public sealed class DateInstance : ObjectInstance
     {
     {
         // Maximum allowed value to prevent DateTime overflow
         // Maximum allowed value to prevent DateTime overflow
         private static readonly double Max = (DateTime.MaxValue - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
         private static readonly double Max = (DateTime.MaxValue - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;

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

@@ -8,6 +8,9 @@ using Jint.Runtime.Interpreter;
 
 
 namespace Jint.Native.Function
 namespace Jint.Native.Function
 {
 {
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-function-constructor
+    /// </summary>
     public sealed class FunctionConstructor : FunctionInstance, IConstructor
     public sealed class FunctionConstructor : FunctionInstance, IConstructor
     {
     {
         private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };
         private static readonly ParserOptions ParserOptions = new ParserOptions { AdaptRegexp = true, Tolerant = false };

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

@@ -103,20 +103,6 @@ namespace Jint.Native.Function
             }
             }
         }
         }
 
 
-        public override List<JsValue> GetOwnPropertyKeys(Types types)
-        {
-            var keys = base.GetOwnPropertyKeys(types);
-
-            // works around a problem where we don't use property for function names and classes should report it last
-            // as it's the last operation when creating a class constructor
-            if ((types & Types.String) != 0 && _nameDescriptor != null && this is ScriptFunctionInstance { _isClassConstructor: true })
-            {
-                keys.Add(CommonProperties.Name);
-            }
-
-            return keys;
-        }
-
         internal override IEnumerable<JsValue> GetInitialOwnStringPropertyKeys()
         internal override IEnumerable<JsValue> GetInitialOwnStringPropertyKeys()
         {
         {
             if (_length != null)
             if (_length != null)
@@ -124,9 +110,7 @@ namespace Jint.Native.Function
                 yield return CommonProperties.Length;
                 yield return CommonProperties.Length;
             }
             }
 
 
-            // works around a problem where we don't use property for function names and classes should report it last
-            // as it's the last operation when creating a class constructor
-            if (_nameDescriptor != null && this is not ScriptFunctionInstance { _isClassConstructor: true })
+            if (_nameDescriptor != null)
             {
             {
                 yield return CommonProperties.Name;
                 yield return CommonProperties.Name;
             }
             }

+ 33 - 7
Jint/Native/Function/FunctionPrototype.cs

@@ -9,7 +9,7 @@ using Jint.Runtime.Interop;
 namespace Jint.Native.Function
 namespace Jint.Native.Function
 {
 {
     /// <summary>
     /// <summary>
-    ///     http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4
+    /// https://tc39.es/ecma262/#sec-properties-of-the-function-prototype-object
     /// </summary>
     /// </summary>
     public sealed class FunctionPrototype : FunctionInstance
     public sealed class FunctionPrototype : FunctionInstance
     {
     {
@@ -46,11 +46,17 @@ namespace Jint.Native.Function
             SetSymbols(symbols);
             SetSymbols(symbols);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-function.prototype-@@hasinstance
+        /// </summary>
         private static JsValue HasInstance(JsValue thisObj, JsValue[] arguments)
         private static JsValue HasInstance(JsValue thisObj, JsValue[] arguments)
         {
         {
             return thisObj.OrdinaryHasInstance(arguments.At(0));
             return thisObj.OrdinaryHasInstance(arguments.At(0));
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-function.prototype.bind
+        /// </summary>
         private JsValue Bind(JsValue thisObj, JsValue[] arguments)
         private JsValue Bind(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj is not ICallable)
             if (thisObj is not ICallable)
@@ -66,16 +72,27 @@ namespace Jint.Native.Function
             if (targetHasLength)
             if (targetHasLength)
             {
             {
                 var targetLen = thisObj.Get(CommonProperties.Length);
                 var targetLen = thisObj.Get(CommonProperties.Length);
-                if (!targetLen.IsNumber())
+                if (targetLen is not JsNumber number)
                 {
                 {
                     l = JsNumber.PositiveZero;
                     l = JsNumber.PositiveZero;
                 }
                 }
                 else
                 else
                 {
                 {
-                    targetLen = TypeConverter.ToInteger(targetLen);
-                    // first argument is target
-                    var argumentsLength = System.Math.Max(0, arguments.Length - 1);
-                    l = JsNumber.Create((uint) System.Math.Max(((JsNumber) targetLen)._value - argumentsLength, 0));
+                    if (number.IsPositiveInfinity())
+                    {
+                        l = number;
+                    }
+                    else if (number.IsNegativeInfinity())
+                    {
+                        l = JsNumber.PositiveZero;
+                    }
+                    else
+                    {
+                        var targetLenAsInt = (long) TypeConverter.ToIntegerOrInfinity(targetLen);
+                        // first argument is target
+                        var argumentsLength = System.Math.Max(0, arguments.Length - 1);
+                        l = JsNumber.Create((ulong) System.Math.Max(targetLenAsInt - argumentsLength, 0));
+                    }
                 }
                 }
             }
             }
             else
             else
@@ -106,6 +123,9 @@ namespace Jint.Native.Function
             return obj;
             return obj;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-function.prototype.tostring
+        /// </summary>
         private JsValue ToString(JsValue thisObj, JsValue[] arguments)
         private JsValue ToString(JsValue thisObj, JsValue[] arguments)
         {
         {
             if (thisObj.IsObject() && thisObj.IsCallable)
             if (thisObj.IsObject() && thisObj.IsCallable)
@@ -117,7 +137,10 @@ namespace Jint.Native.Function
             return null;
             return null;
         }
         }
 
 
-        internal JsValue Apply(JsValue thisObject, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-function.prototype.apply
+        /// </summary>
+        private JsValue Apply(JsValue thisObject, JsValue[] arguments)
         {
         {
             var func = thisObject as ICallable;
             var func = thisObject as ICallable;
             if (func is null)
             if (func is null)
@@ -157,6 +180,9 @@ namespace Jint.Native.Function
             return argList;
             return argList;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-function.prototype.call
+        /// </summary>
         private JsValue CallImpl(JsValue thisObject, JsValue[] arguments)
         private JsValue CallImpl(JsValue thisObject, JsValue[] arguments)
         {
         {
             var func = thisObject as ICallable;
             var func = thisObject as ICallable;

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

@@ -75,9 +75,9 @@ namespace Jint.Native.Global
                 ["SyntaxError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.SyntaxError, propertyFlags),
                 ["SyntaxError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.SyntaxError, propertyFlags),
                 ["TypeError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.TypeError, propertyFlags),
                 ["TypeError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.TypeError, propertyFlags),
                 ["URIError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.UriError, propertyFlags),
                 ["URIError"] = new LazyPropertyDescriptor(this, static state => ((GlobalObject) state)._realm.Intrinsics.UriError, propertyFlags),
-                ["NaN"] = new PropertyDescriptor(double.NaN, PropertyFlag.None),
-                ["Infinity"] = new PropertyDescriptor(double.PositiveInfinity, PropertyFlag.None),
-                ["undefined"] = new PropertyDescriptor(Undefined, PropertyFlag.None),
+                ["NaN"] = new PropertyDescriptor(double.NaN, PropertyFlag.AllForbidden),
+                ["Infinity"] = new PropertyDescriptor(double.PositiveInfinity, PropertyFlag.AllForbidden),
+                ["undefined"] = new PropertyDescriptor(Undefined, PropertyFlag.AllForbidden),
                 ["parseInt"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "parseInt", ParseInt, 2, lengthFlags), propertyFlags),
                 ["parseInt"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "parseInt", ParseInt, 2, lengthFlags), propertyFlags),
                 ["parseFloat"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "parseFloat", ParseFloat, 1, lengthFlags), propertyFlags),
                 ["parseFloat"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "parseFloat", ParseFloat, 1, lengthFlags), propertyFlags),
                 ["isNaN"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "isNaN", IsNaN, 1, lengthFlags), propertyFlags),
                 ["isNaN"] = new LazyPropertyDescriptor(this, static state => new ClrFunctionInstance(((GlobalObject) state)._engine, "isNaN", IsNaN, 1, lengthFlags), propertyFlags),
@@ -827,7 +827,7 @@ namespace Jint.Native.Global
                 return DefineOwnProperty(property, new PropertyDescriptor(value, PropertyFlag.None));
                 return DefineOwnProperty(property, new PropertyDescriptor(value, PropertyFlag.None));
             }
             }
 
 
-            if (!(existingDescriptor.Set is ICallable setter))
+            if (existingDescriptor.Set is not ICallable setter)
             {
             {
                 return false;
                 return false;
             }
             }

+ 1 - 1
Jint/Native/Iterator/IteratorInstance.cs

@@ -68,7 +68,7 @@ namespace Jint.Native.Iterator
                 var done = ReferenceEquals(null, key) && ReferenceEquals(null, value);
                 var done = ReferenceEquals(null, key) && ReferenceEquals(null, value);
                 if (!done)
                 if (!done)
                 {
                 {
-                    var arrayInstance = engine.Realm.Intrinsics.Array.ConstructFast(2);
+                    var arrayInstance = engine.Realm.Intrinsics.Array.ArrayCreate(2);
                     arrayInstance.SetIndexValue(0, key, false);
                     arrayInstance.SetIndexValue(0, key, false);
                     arrayInstance.SetIndexValue(1, value, false);
                     arrayInstance.SetIndexValue(1, value, false);
                     SetProperty("value", new PropertyDescriptor(arrayInstance, PropertyFlag.AllForbidden));
                     SetProperty("value", new PropertyDescriptor(arrayInstance, PropertyFlag.AllForbidden));

+ 1 - 1
Jint/Native/JsString.cs

@@ -197,7 +197,7 @@ namespace Jint.Native
 
 
         public ArrayInstance ToArray(Engine engine)
         public ArrayInstance ToArray(Engine engine)
         {
         {
-            var array = engine.Realm.Intrinsics.Array.ConstructFast((uint) _value.Length);
+            var array = engine.Realm.Intrinsics.Array.ArrayCreate((uint) _value.Length);
             for (int i = 0; i < _value.Length; ++i)
             for (int i = 0; i < _value.Length; ++i)
             {
             {
                 array.SetIndexValue((uint) i, _value[i], updateLength: false);
                 array.SetIndexValue((uint) i, _value[i], updateLength: false);

+ 3 - 0
Jint/Native/JsSymbol.cs

@@ -25,6 +25,9 @@ namespace Jint.Native
             return _value;
             return _value;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symboldescriptivestring
+        /// </summary>
         public override string ToString()
         public override string ToString()
         {
         {
             var value = _value.IsUndefined() ? "" : _value.AsString();
             var value = _value.IsUndefined() ? "" : _value.AsString();

+ 2 - 2
Jint/Native/JsValue.cs

@@ -166,7 +166,7 @@ namespace Jint.Native
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// http://www.ecma-international.org/ecma-262/5.1/#sec-8.12.3
+        /// https://tc39.es/ecma262/#sec-get-o-p
         /// </summary>
         /// </summary>
         public virtual JsValue Get(JsValue property, JsValue receiver)
         public virtual JsValue Get(JsValue property, JsValue receiver)
         {
         {
@@ -174,7 +174,7 @@ namespace Jint.Native
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// https://tc39.es/ecma262/#sec-ordinary-object-internal-methods-and-internal-slots-set-p-v-receiver
+        /// https://tc39.es/ecma262/#sec-set-o-p-v-throw
         /// </summary>
         /// </summary>
         public virtual bool Set(JsValue property, JsValue value, JsValue receiver)
         public virtual bool Set(JsValue property, JsValue value, JsValue receiver)
         {
         {

+ 4 - 5
Jint/Native/Map/MapInstance.cs

@@ -5,13 +5,12 @@ using Jint.Runtime.Descriptors;
 
 
 namespace Jint.Native.Map
 namespace Jint.Native.Map
 {
 {
-    public class MapInstance : ObjectInstance
+    public sealed class MapInstance : ObjectInstance
     {
     {
         private readonly Realm _realm;
         private readonly Realm _realm;
         internal readonly OrderedDictionary<JsValue, JsValue> _map;
         internal readonly OrderedDictionary<JsValue, JsValue> _map;
 
 
-        public MapInstance(Engine engine, Realm realm)
-            : base(engine, objectClass: ObjectClass.Map)
+        public MapInstance(Engine engine, Realm realm) : base(engine)
         {
         {
             _realm = realm;
             _realm = realm;
             _map = new OrderedDictionary<JsValue, JsValue>(SameValueZeroComparer.Instance);
             _map = new OrderedDictionary<JsValue, JsValue>(SameValueZeroComparer.Instance);
@@ -21,7 +20,7 @@ namespace Jint.Native.Map
         {
         {
             if (property == CommonProperties.Size)
             if (property == CommonProperties.Size)
             {
             {
-                return new PropertyDescriptor(_map.Count, PropertyFlag.None);
+                return new PropertyDescriptor(_map.Count, PropertyFlag.AllForbidden);
             }
             }
 
 
             return base.GetOwnProperty(property);
             return base.GetOwnProperty(property);
@@ -31,7 +30,7 @@ namespace Jint.Native.Map
         {
         {
             if (property == CommonProperties.Size)
             if (property == CommonProperties.Size)
             {
             {
-                descriptor = new PropertyDescriptor(_map.Count, PropertyFlag.None);
+                descriptor = new PropertyDescriptor(_map.Count, PropertyFlag.AllForbidden);
                 return true;
                 return true;
             }
             }
 
 

+ 0 - 1
Jint/Native/Object/ObjectClass.cs

@@ -10,7 +10,6 @@ namespace Jint.Native.Object
         Function,
         Function,
         Iterator,
         Iterator,
         JSON,
         JSON,
-        Map,
         Math,
         Math,
         Number,
         Number,
         Object,
         Object,

+ 181 - 76
Jint/Native/Object/ObjectConstructor.cs

@@ -22,6 +22,8 @@ namespace Jint.Native.Object
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
+        public ObjectPrototype PrototypeObject { get; }
+
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             _prototype = _realm.Intrinsics.Function.PrototypeObject;
             _prototype = _realm.Intrinsics.Function.PrototypeObject;
@@ -42,7 +44,7 @@ namespace Jint.Native.Object
                 ["defineProperty"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "defineProperty", DefineProperty, 3), propertyFlags),
                 ["defineProperty"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "defineProperty", DefineProperty, 3), propertyFlags),
                 ["defineProperties"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "defineProperties", DefineProperties, 2), propertyFlags),
                 ["defineProperties"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "defineProperties", DefineProperties, 2), propertyFlags),
                 ["is"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "is", Is, 2, lengthFlags), propertyFlags),
                 ["is"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "is", Is, 2, lengthFlags), propertyFlags),
-                ["seal"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "seal", Seal, 1), propertyFlags),
+                ["seal"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "seal", Seal, 1, lengthFlags), propertyFlags),
                 ["freeze"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "freeze", Freeze, 1), propertyFlags),
                 ["freeze"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "freeze", Freeze, 1), propertyFlags),
                 ["preventExtensions"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "preventExtensions", PreventExtensions, 1), propertyFlags),
                 ["preventExtensions"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "preventExtensions", PreventExtensions, 1), propertyFlags),
                 ["isSealed"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isSealed", IsSealed, 1), propertyFlags),
                 ["isSealed"] = new PropertyDescriptor(new ClrFunctionInstance(Engine, "isSealed", IsSealed, 1), propertyFlags),
@@ -56,6 +58,9 @@ namespace Jint.Native.Object
             SetProperties(properties);
             SetProperties(properties);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.assign
+        /// </summary>
         private JsValue Assign(JsValue thisObject, JsValue[] arguments)
         private JsValue Assign(JsValue thisObject, JsValue[] arguments)
         {
         {
             var to = TypeConverter.ToObject(_realm, arguments.At(0));
             var to = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -87,6 +92,9 @@ namespace Jint.Native.Object
             return to;
             return to;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.entries
+        /// </summary>
         private JsValue Entries(JsValue thisObject, JsValue[] arguments)
         private JsValue Entries(JsValue thisObject, JsValue[] arguments)
         {
         {
             var obj = TypeConverter.ToObject(_realm, arguments.At(0));
             var obj = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -94,6 +102,9 @@ namespace Jint.Native.Object
             return nameList;
             return nameList;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.fromentries
+        /// </summary>
         private JsValue FromEntries(JsValue thisObject, JsValue[] arguments)
         private JsValue FromEntries(JsValue thisObject, JsValue[] arguments)
         {
         {
             var iterable = arguments.At(0);
             var iterable = arguments.At(0);
@@ -109,13 +120,14 @@ namespace Jint.Native.Object
             return obj;
             return obj;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.is
+        /// </summary>
         private static JsValue Is(JsValue thisObject, JsValue[] arguments)
         private static JsValue Is(JsValue thisObject, JsValue[] arguments)
         {
         {
             return SameValue(arguments.At(0), arguments.At(1));
             return SameValue(arguments.At(0), arguments.At(1));
         }
         }
 
 
-        public ObjectPrototype PrototypeObject { get; private set; }
-
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-object-value
         /// https://tc39.es/ecma262/#sec-object-value
         /// </summary>
         /// </summary>
@@ -180,12 +192,18 @@ namespace Jint.Native.Object
             return obj;
             return obj;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.getprototypeof
+        /// </summary>
         public JsValue GetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         public JsValue GetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         {
         {
             var obj = TypeConverter.ToObject(_realm, arguments.At(0));
             var obj = TypeConverter.ToObject(_realm, arguments.At(0));
             return obj.Prototype ?? Null;
             return obj.Prototype ?? Null;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.setprototypeof
+        /// </summary>
         private JsValue SetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         private JsValue SetPrototypeOf(JsValue thisObject, JsValue[] arguments)
         {
         {
             var oArg = arguments.At(0);
             var oArg = arguments.At(0);
@@ -209,6 +227,9 @@ namespace Jint.Native.Object
             return o;
             return o;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.hasown
+        /// </summary>
         private JsValue HasOwn(JsValue thisObject, JsValue[] arguments)
         private JsValue HasOwn(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -216,6 +237,9 @@ namespace Jint.Native.Object
             return o.HasOwnProperty(property) ? JsBoolean.True : JsBoolean.False;
             return o.HasOwnProperty(property) ? JsBoolean.True : JsBoolean.False;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.getownpropertydescriptor
+        /// </summary>
         internal JsValue GetOwnPropertyDescriptor(JsValue thisObject, JsValue[] arguments)
         internal JsValue GetOwnPropertyDescriptor(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -227,6 +251,9 @@ namespace Jint.Native.Object
             return PropertyDescriptor.FromPropertyDescriptor(Engine, desc);
             return PropertyDescriptor.FromPropertyDescriptor(Engine, desc);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.getownpropertydescriptors
+        /// </summary>
         private JsValue GetOwnPropertyDescriptors(JsValue thisObject, JsValue[] arguments)
         private JsValue GetOwnPropertyDescriptors(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -244,13 +271,19 @@ namespace Jint.Native.Object
             return descriptors;
             return descriptors;
         }
         }
 
 
-        public JsValue GetOwnPropertyNames(JsValue thisObject, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.getownpropertynames
+        /// </summary>
+        private JsValue GetOwnPropertyNames(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var names = o.GetOwnPropertyKeys(Types.String);
             var names = o.GetOwnPropertyKeys(Types.String);
             return _realm.Intrinsics.Array.ConstructFast(names);
             return _realm.Intrinsics.Array.ConstructFast(names);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.getownpropertysymbols
+        /// </summary>
         private JsValue GetOwnPropertySymbols(JsValue thisObject, JsValue[] arguments)
         private JsValue GetOwnPropertySymbols(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -258,6 +291,9 @@ namespace Jint.Native.Object
             return _realm.Intrinsics.Array.ConstructFast(keys);
             return _realm.Intrinsics.Array.ConstructFast(keys);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.create
+        /// </summary>
         private JsValue Create(JsValue thisObject, JsValue[] arguments)
         private JsValue Create(JsValue thisObject, JsValue[] arguments)
         {
         {
             var prototype = arguments.At(0);
             var prototype = arguments.At(0);
@@ -272,16 +308,15 @@ namespace Jint.Native.Object
             var properties = arguments.At(1);
             var properties = arguments.At(1);
             if (!properties.IsUndefined())
             if (!properties.IsUndefined())
             {
             {
-                var jsValues = _engine._jsValueArrayPool.RentArray(2);
-                jsValues[0] = obj;
-                jsValues[1] = properties;
-                DefineProperties(thisObject, jsValues);
-                _engine._jsValueArrayPool.ReturnArray(jsValues);
+                ObjectDefineProperties(obj, properties);
             }
             }
 
 
             return obj;
             return obj;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.defineproperty
+        /// </summary>
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = arguments.At(0) as ObjectInstance;
             var o = arguments.At(0) as ObjectInstance;
@@ -300,6 +335,9 @@ namespace Jint.Native.Object
             return arguments.At(0);
             return arguments.At(0);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.defineproperties
+        /// </summary>
         private JsValue DefineProperties(JsValue thisObject, JsValue[] arguments)
         private JsValue DefineProperties(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = arguments.At(0) as ObjectInstance;
             var o = arguments.At(0) as ObjectInstance;
@@ -309,19 +347,31 @@ namespace Jint.Native.Object
             }
             }
 
 
             var properties = arguments.At(1);
             var properties = arguments.At(1);
+            return ObjectDefineProperties(o, properties);
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-objectdefineproperties
+        /// </summary>
+        private JsValue ObjectDefineProperties(ObjectInstance o, JsValue properties)
+        {
             var props = TypeConverter.ToObject(_realm, properties);
             var props = TypeConverter.ToObject(_realm, properties);
+            var keys = props.GetOwnPropertyKeys();
             var descriptors = new List<KeyValuePair<JsValue, PropertyDescriptor>>();
             var descriptors = new List<KeyValuePair<JsValue, PropertyDescriptor>>();
-            foreach (var p in props.GetOwnProperties())
+            for (var i = 0; i < keys.Count; i++)
             {
             {
-                if (!p.Value.Enumerable)
+                var nextKey = keys[i];
+                var propDesc = props.GetOwnProperty(nextKey);
+                if (propDesc == PropertyDescriptor.Undefined || !propDesc.Enumerable)
                 {
                 {
                     continue;
                     continue;
                 }
                 }
 
 
-                var descObj = props.Get(p.Key, props);
+                var descObj = props.UnwrapJsValue(propDesc);
                 var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, descObj);
                 var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, descObj);
-                descriptors.Add(new KeyValuePair<JsValue, PropertyDescriptor>(p.Key, desc));
+                descriptors.Add(new KeyValuePair<JsValue, PropertyDescriptor>(nextKey, desc));
             }
             }
+
             foreach (var pair in descriptors)
             foreach (var pair in descriptors)
             {
             {
                 o.DefinePropertyOrThrow(pair.Key, pair.Value);
                 o.DefinePropertyOrThrow(pair.Key, pair.Value);
@@ -330,132 +380,181 @@ namespace Jint.Native.Object
             return o;
             return o;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.seal
+        /// </summary>
         private JsValue Seal(JsValue thisObject, JsValue[] arguments)
         private JsValue Seal(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            if (arguments.At(0) is not ObjectInstance o)
             {
             {
                 return arguments.At(0);
                 return arguments.At(0);
             }
             }
 
 
-            var properties = new List<KeyValuePair<JsValue, PropertyDescriptor>>(o.GetOwnProperties());
-            foreach (var prop in properties)
+            var status = SetIntegrityLevel(o, IntegrityLevel.Sealed);
+
+            if (!status)
             {
             {
-                var propertyDescriptor = prop.Value;
-                if (propertyDescriptor.Configurable)
-                {
-                    propertyDescriptor.Configurable = false;
-                    FastSetProperty(prop.Key, propertyDescriptor);
-                }
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
 
 
-                o.DefinePropertyOrThrow(prop.Key, propertyDescriptor);
+            return o;
+        }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.freeze
+        /// </summary>
+        private JsValue Freeze(JsValue thisObject, JsValue[] arguments)
+        {
+            if (arguments.At(0) is not ObjectInstance o)
+            {
+                return arguments.At(0);
             }
             }
 
 
-            o.PreventExtensions();
+            var status = SetIntegrityLevel(o, IntegrityLevel.Frozen);
+
+            if (!status)
+            {
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
 
 
             return o;
             return o;
         }
         }
 
 
-        private static JsValue Freeze(JsValue thisObject, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-setintegritylevel
+        /// </summary>
+        private static bool SetIntegrityLevel(ObjectInstance o, IntegrityLevel level)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            var status = o.PreventExtensions();
+            if (!status)
             {
             {
-                return arguments.At(0);
+                return false;
             }
             }
 
 
-            foreach (var p in o.GetOwnProperties())
+            var keys = o.GetOwnPropertyKeys();
+            if (level == IntegrityLevel.Sealed)
             {
             {
-                var desc = o.GetOwnProperty(p.Key);
-                if (desc.IsDataDescriptor())
+                for (var i = 0; i < keys.Count; i++)
                 {
                 {
-                    if (desc.Writable)
-                    {
-                        var mutable = desc;
-                        mutable.Writable = false;
-                        desc = mutable;
-                    }
+                    var k = keys[i];
+                    o.DefinePropertyOrThrow(k, new PropertyDescriptor { Configurable = false });
                 }
                 }
-                if (desc.Configurable)
+            }
+            else
+            {
+                for (var i = 0; i < keys.Count; i++)
                 {
                 {
-                    var mutable = desc;
-                    mutable.Configurable = false;
-                    desc = mutable;
+                    var k = keys[i];
+                    var currentDesc = o.GetOwnProperty(k);
+                    if (currentDesc != PropertyDescriptor.Undefined)
+                    {
+                        PropertyDescriptor desc;
+                        if (currentDesc.IsAccessorDescriptor())
+                        {
+                            desc = new PropertyDescriptor { Configurable = false };
+                        }
+                        else
+                        {
+                            desc = new PropertyDescriptor { Configurable = false, Writable = false };
+                        }
+
+                        o.DefinePropertyOrThrow(k, desc);
+                    }
                 }
                 }
-                o.DefinePropertyOrThrow(p.Key, desc);
             }
             }
 
 
-            o.PreventExtensions();
+            return true;
+        }
 
 
-            return o;
+        private enum IntegrityLevel
+        {
+            Sealed,
+            Frozen
         }
         }
 
 
-        private static JsValue PreventExtensions(JsValue thisObject, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.preventextensions
+        /// </summary>
+        private JsValue PreventExtensions(JsValue thisObject, JsValue[] arguments)
         {
         {
             if (!(arguments.At(0) is ObjectInstance o))
             if (!(arguments.At(0) is ObjectInstance o))
             {
             {
                 return arguments.At(0);
                 return arguments.At(0);
             }
             }
 
 
-            o.PreventExtensions();
+            if (!o.PreventExtensions())
+            {
+                ExceptionHelper.ThrowTypeError(_realm);
+            }
+
             return o;
             return o;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.issealed
+        /// </summary>
         private static JsValue IsSealed(JsValue thisObject, JsValue[] arguments)
         private static JsValue IsSealed(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            if (arguments.At(0) is not ObjectInstance o)
             {
             {
                 return arguments.At(0);
                 return arguments.At(0);
             }
             }
 
 
-            foreach (var prop in o.GetOwnProperties())
-            {
-                if (prop.Value.Configurable)
-                {
-                    return false;
-                }
-            }
+            return TestIntegrityLevel(o, IntegrityLevel.Sealed);
+        }
 
 
-            if (o.Extensible == false)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.isfrozen
+        /// </summary>
+        private static JsValue IsFrozen(JsValue thisObject, JsValue[] arguments)
+        {
+            if (arguments.At(0) is not ObjectInstance o)
             {
             {
-                return true;
+                return arguments.At(0);
             }
             }
 
 
-            return false;
+            return TestIntegrityLevel(o, IntegrityLevel.Frozen);
         }
         }
 
 
-        private static JsValue IsFrozen(JsValue thisObject, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-testintegritylevel
+        /// </summary>
+        private static JsValue TestIntegrityLevel(ObjectInstance o, IntegrityLevel level)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            if (o.Extensible)
             {
             {
-                return arguments.At(0);
+                return JsBoolean.False;
             }
             }
 
 
-            foreach (var pair in o.GetOwnProperties())
+            foreach (var k in o.GetOwnPropertyKeys())
             {
             {
-                var desc = pair.Value;
-                if (desc.IsDataDescriptor())
+                var currentDesc = o.GetOwnProperty(k);
+                if (currentDesc != PropertyDescriptor.Undefined)
                 {
                 {
-                    if (desc.Writable)
+                    if (currentDesc.Configurable)
                     {
                     {
-                        return false;
+                        return JsBoolean.False;
                     }
                     }
-                }
-                if (desc.Configurable)
-                {
-                    return false;
-                }
-            }
 
 
-            if (o.Extensible == false)
-            {
-                return true;
+                    if (level == IntegrityLevel.Frozen && currentDesc.IsDataDescriptor())
+                    {
+                        if (currentDesc.Writable)
+                        {
+                            return JsBoolean.False;
+                        }
+                    }
+                }
             }
             }
 
 
-            return false;
+            return JsBoolean.True;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.isextensible
+        /// </summary>
         private static JsValue IsExtensible(JsValue thisObject, JsValue[] arguments)
         private static JsValue IsExtensible(JsValue thisObject, JsValue[] arguments)
         {
         {
-            if (!(arguments.At(0) is ObjectInstance o))
+            if (arguments.At(0) is not ObjectInstance o)
             {
             {
                 return arguments.At(0);
                 return arguments.At(0);
             }
             }
@@ -463,12 +562,18 @@ namespace Jint.Native.Object
             return o.Extensible;
             return o.Extensible;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.keys
+        /// </summary>
         private JsValue Keys(JsValue thisObject, JsValue[] arguments)
         private JsValue Keys(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             return o.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Key);
             return o.EnumerableOwnPropertyNames(EnumerableOwnPropertyNamesKind.Key);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-object.values
+        /// </summary>
         private JsValue Values(JsValue thisObject, JsValue[] arguments)
         private JsValue Values(JsValue thisObject, JsValue[] arguments)
         {
         {
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
             var o = TypeConverter.ToObject(_realm, arguments.At(0));
@@ -477,7 +582,7 @@ namespace Jint.Native.Object
 
 
         private sealed class CreateDataPropertyOnObject : ICallable
         private sealed class CreateDataPropertyOnObject : ICallable
         {
         {
-            internal static readonly CreateDataPropertyOnObject Instance = new CreateDataPropertyOnObject();
+            internal static readonly CreateDataPropertyOnObject Instance = new();
 
 
             private CreateDataPropertyOnObject()
             private CreateDataPropertyOnObject()
             {
             {

+ 26 - 10
Jint/Native/Object/ObjectInstance.cs

@@ -215,6 +215,8 @@ namespace Jint.Native.Object
             }
             }
         }
         }
 
 
+
+
         public virtual List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
         public virtual List<JsValue> GetOwnPropertyKeys(Types types = Types.String | Types.Symbol)
         {
         {
             EnsureInitialized();
             EnsureInitialized();
@@ -313,8 +315,14 @@ namespace Jint.Native.Object
 
 
         public override JsValue Get(JsValue property, JsValue receiver)
         public override JsValue Get(JsValue property, JsValue receiver)
         {
         {
-            var desc = GetProperty(property);
-            return UnwrapJsValue(desc, receiver);
+            var desc = GetOwnProperty(property);
+
+            if (desc != PropertyDescriptor.Undefined)
+            {
+                return UnwrapJsValue(desc, receiver);
+            }
+
+            return Prototype?.Get(property, receiver) ?? Undefined;
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
@@ -456,6 +464,9 @@ namespace Jint.Native.Object
             return Set(property, value, this);
             return Set(property, value, this);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-ordinarysetwithowndescriptor
+        /// </summary>
         public override bool Set(JsValue property, JsValue value, JsValue receiver)
         public override bool Set(JsValue property, JsValue value, JsValue receiver)
         {
         {
             var ownDesc = GetOwnProperty(property);
             var ownDesc = GetOwnProperty(property);
@@ -477,7 +488,7 @@ namespace Jint.Native.Object
                     return false;
                     return false;
                 }
                 }
 
 
-                if (!(receiver is ObjectInstance oi))
+                if (receiver is not ObjectInstance oi)
                 {
                 {
                     return false;
                     return false;
                 }
                 }
@@ -688,12 +699,17 @@ namespace Jint.Native.Object
                             };
                             };
                         }
                         }
 
 
-                        propertyDescriptor._flags |= desc._flags & PropertyFlag.MutableBinding;
                         o.SetOwnProperty(property, propertyDescriptor);
                         o.SetOwnProperty(property, propertyDescriptor);
                     }
                     }
                     else
                     else
                     {
                     {
-                        o.SetOwnProperty(property, new GetSetPropertyDescriptor(desc));
+                        var descriptor = new GetSetPropertyDescriptor(desc.Get, desc.Set, PropertyFlag.None)
+                        {
+                            Enumerable = desc.Enumerable,
+                            Configurable = desc.Configurable
+                        };
+
+                        o.SetOwnProperty(property, descriptor);
                     }
                     }
                 }
                 }
 
 
@@ -705,6 +721,7 @@ namespace Jint.Native.Object
             var currentSet = current.Set;
             var currentSet = current.Set;
             var currentValue = current.Value;
             var currentValue = current.Value;
 
 
+            // 4. If every field in Desc is absent, return true.
             if ((current._flags & (PropertyFlag.ConfigurableSet | PropertyFlag.EnumerableSet | PropertyFlag.WritableSet)) == 0 &&
             if ((current._flags & (PropertyFlag.ConfigurableSet | PropertyFlag.EnumerableSet | PropertyFlag.WritableSet)) == 0 &&
                 ReferenceEquals(currentGet, null) &&
                 ReferenceEquals(currentGet, null) &&
                 ReferenceEquals(currentSet, null) &&
                 ReferenceEquals(currentSet, null) &&
@@ -750,7 +767,6 @@ namespace Jint.Native.Object
                         return false;
                         return false;
                     }
                     }
 
 
-
                     if (o is object)
                     if (o is object)
                     {
                     {
                         var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet | PropertyFlag.CustomJsValue);
                         var flags = current.Flags & ~(PropertyFlag.Writable | PropertyFlag.WritableSet | PropertyFlag.CustomJsValue);
@@ -1110,10 +1126,10 @@ namespace Jint.Native.Object
 
 
         public virtual uint Length => (uint) TypeConverter.ToLength(Get(CommonProperties.Length));
         public virtual uint Length => (uint) TypeConverter.ToLength(Get(CommonProperties.Length));
 
 
-        public virtual JsValue PreventExtensions()
+        public virtual bool PreventExtensions()
         {
         {
             Extensible = false;
             Extensible = false;
-            return JsBoolean.True;
+            return true;
         }
         }
 
 
         protected internal virtual ObjectInstance GetPrototypeOf()
         protected internal virtual ObjectInstance GetPrototypeOf()
@@ -1266,7 +1282,7 @@ namespace Jint.Native.Object
         {
         {
             var ownKeys = GetOwnPropertyKeys(Types.String);
             var ownKeys = GetOwnPropertyKeys(Types.String);
 
 
-            var array = Engine.Realm.Intrinsics.Array.ConstructFast((uint) ownKeys.Count);
+            var array = Engine.Realm.Intrinsics.Array.ArrayCreate((uint) ownKeys.Count);
             uint index = 0;
             uint index = 0;
 
 
             for (var i = 0; i < ownKeys.Count; i++)
             for (var i = 0; i < ownKeys.Count; i++)
@@ -1294,7 +1310,7 @@ namespace Jint.Native.Object
                         }
                         }
                         else
                         else
                         {
                         {
-                            var objectInstance = _engine.Realm.Intrinsics.Array.ConstructFast(2);
+                            var objectInstance = _engine.Realm.Intrinsics.Array.ArrayCreate(2);
                             objectInstance.SetIndexValue(0,  property, updateLength: false);
                             objectInstance.SetIndexValue(0,  property, updateLength: false);
                             objectInstance.SetIndexValue(1, value, updateLength: false);
                             objectInstance.SetIndexValue(1, value, updateLength: false);
                             array.SetIndexValue(index, objectInstance, updateLength: false);
                             array.SetIndexValue(index, objectInstance, updateLength: false);

+ 13 - 1
Jint/Native/Object/ObjectPrototype.cs

@@ -1,4 +1,5 @@
 using Jint.Collections;
 using Jint.Collections;
+using Jint.Native.Proxy;
 using Jint.Native.Symbol;
 using Jint.Native.Symbol;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
@@ -114,7 +115,18 @@ namespace Jint.Native.Object
             var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
             var tag = o.Get(GlobalSymbolRegistry.ToStringTag);
             if (!tag.IsString())
             if (!tag.IsString())
             {
             {
-                tag = o.Class.ToString();
+                if (o.IsArray())
+                {
+                    tag = "Array";
+                }
+                else if (o.IsCallable)
+                {
+                    tag = "Function";
+                }
+                else
+                {
+                    tag = (o is ProxyInstance ? ObjectClass.Object : o.Class).ToString();
+                }
             }
             }
 
 
             return "[object " + tag + "]";
             return "[object " + tag + "]";

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

@@ -305,7 +305,7 @@ namespace Jint.Native.Promise
             // resolve the promise sync
             // resolve the promise sync
             if (results.Count == 0)
             if (results.Count == 0)
             {
             {
-                resolve.Call(Undefined, new JsValue[] {_realm.Intrinsics.Array.ConstructFast(0)});
+                resolve.Call(Undefined, new JsValue[] {_realm.Intrinsics.Array.ArrayCreate(0)});
             }
             }
 
 
             return resultingPromise;
             return resultingPromise;

+ 37 - 30
Jint/Native/Proxy/ProxyConstructor.cs

@@ -39,21 +39,14 @@ namespace Jint.Native.Proxy
             return null;
             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>
-        private ObjectInstance Construct(JsValue[] arguments)
+        ObjectInstance IConstructor.Construct(JsValue[] arguments, JsValue newTarget)
         {
         {
-            var target = arguments.At(0);
-            var handler = arguments.At(1);
-
-            if (!target.IsObject() || !handler.IsObject())
+            if (newTarget.IsUndefined())
             {
             {
-                ExceptionHelper.ThrowTypeError(_realm, "Cannot create proxy with a non-object as target or handler");
+                ExceptionHelper.ThrowTypeError(_realm);
             }
             }
-            return Construct(target.AsObject(), handler.AsObject());
+
+            return Construct(arguments.At(0), arguments.At(1));
         }
         }
 
 
         protected internal override ObjectInstance GetPrototypeOf()
         protected internal override ObjectInstance GetPrototypeOf()
@@ -64,36 +57,50 @@ namespace Jint.Native.Proxy
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-proxy-target-handler
         /// https://tc39.es/ecma262/#sec-proxy-target-handler
         /// </summary>
         /// </summary>
-        public ProxyInstance Construct(ObjectInstance target, ObjectInstance handler)
+        public ProxyInstance Construct(JsValue target, JsValue handler)
         {
         {
-            if (target is ProxyInstance targetProxy && targetProxy._handler is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-            if (handler is ProxyInstance handlerProxy && handlerProxy._handler is null)
-            {
-                ExceptionHelper.ThrowTypeError(_realm);
-            }
-            var instance = new ProxyInstance(Engine, target, handler);
-            return instance;
+            return ProxyCreate(target, handler);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-proxy.revocable
+        /// </summary>
         private JsValue Revocable(JsValue thisObject, JsValue[] arguments)
         private JsValue Revocable(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var p = Construct(arguments);
+            var p = ProxyCreate(arguments.At(0), arguments.At(1));
 
 
-            System.Func<JsValue, JsValue[], JsValue> revoke = (thisObject, arguments) =>
+            JsValue Revoke(JsValue thisObject, JsValue[] arguments)
             {
             {
-                var proxy = (ProxyInstance) p;
-                proxy._handler = null;
-                proxy._target = null;
+                p._handler = null;
+                p._target = null;
                 return Undefined;
                 return Undefined;
-            };
+            }
 
 
             var result = _realm.Intrinsics.Object.Construct(System.Array.Empty<JsValue>());
             var result = _realm.Intrinsics.Object.Construct(System.Array.Empty<JsValue>());
-            result.DefineOwnProperty(PropertyRevoke, new PropertyDescriptor(new ClrFunctionInstance(_engine, name: null, revoke, 0, PropertyFlag.Configurable), PropertyFlag.ConfigurableEnumerableWritable));
+            result.DefineOwnProperty(PropertyRevoke, new PropertyDescriptor(new ClrFunctionInstance(_engine, name: "", Revoke, 0, PropertyFlag.Configurable), PropertyFlag.ConfigurableEnumerableWritable));
             result.DefineOwnProperty(PropertyProxy, new PropertyDescriptor(p, PropertyFlag.ConfigurableEnumerableWritable));
             result.DefineOwnProperty(PropertyProxy, new PropertyDescriptor(p, PropertyFlag.ConfigurableEnumerableWritable));
             return result;
             return result;
         }
         }
+
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-proxycreate
+        /// </summary>
+        private ProxyInstance ProxyCreate(JsValue target, JsValue handler)
+        {
+            if (target is not ObjectInstance targetObject)
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "Cannot create proxy with a non-object as target");
+                return null;
+            }
+
+            if (handler is not ObjectInstance targetHandler)
+            {
+                ExceptionHelper.ThrowTypeError(_realm, "Cannot create proxy with a non-object as handler");
+                return null;
+            }
+
+            var p = new ProxyInstance(Engine, targetObject, targetHandler);
+            return p;
+        }
     }
     }
 }
 }

+ 83 - 20
Jint/Native/Proxy/ProxyInstance.cs

@@ -36,6 +36,7 @@ namespace Jint.Native.Proxy
         {
         {
             _target = target;
             _target = target;
             _handler = handler;
             _handler = handler;
+            IsCallable = target.IsCallable;
         }
         }
 
 
         /// <summary>
         /// <summary>
@@ -154,7 +155,7 @@ namespace Jint.Native.Proxy
             }
             }
 
 
             var extensibleTarget = _target.Extensible;
             var extensibleTarget = _target.Extensible;
-            var targetKeys = _target.GetOwnPropertyKeys(types);
+            var targetKeys = _target.GetOwnPropertyKeys();
             var targetConfigurableKeys = new List<JsValue>();
             var targetConfigurableKeys = new List<JsValue>();
             var targetNonconfigurableKeys = new List<JsValue>();
             var targetNonconfigurableKeys = new List<JsValue>();
 
 
@@ -169,7 +170,6 @@ namespace Jint.Native.Proxy
                 {
                 {
                     targetConfigurableKeys.Add(property);
                     targetConfigurableKeys.Add(property);
                 }
                 }
-
             }
             }
 
 
             var uncheckedResultKeys = new HashSet<JsValue>(trapResult);
             var uncheckedResultKeys = new HashSet<JsValue>(trapResult);
@@ -209,19 +209,19 @@ namespace Jint.Native.Proxy
         /// </summary>
         /// </summary>
         public override PropertyDescriptor GetOwnProperty(JsValue property)
         public override PropertyDescriptor GetOwnProperty(JsValue property)
         {
         {
-            if (!TryCallHandler(TrapGetOwnPropertyDescriptor, new[] { _target, TypeConverter.ToPropertyKey(property) }, out var result))
+            if (!TryCallHandler(TrapGetOwnPropertyDescriptor, new[] { _target, TypeConverter.ToPropertyKey(property) }, out var trapResultObj))
             {
             {
                 return _target.GetOwnProperty(property);
                 return _target.GetOwnProperty(property);
             }
             }
 
 
-            if (!result.IsObject() && !result.IsUndefined())
+            if (!trapResultObj.IsObject() && !trapResultObj.IsUndefined())
             {
             {
                 ExceptionHelper.ThrowTypeError(_engine.Realm);
                 ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
             var targetDesc = _target.GetOwnProperty(property);
             var targetDesc = _target.GetOwnProperty(property);
 
 
-            if (result.IsUndefined())
+            if (trapResultObj.IsUndefined())
             {
             {
                 if (targetDesc == PropertyDescriptor.Undefined)
                 if (targetDesc == PropertyDescriptor.Undefined)
                 {
                 {
@@ -237,7 +237,8 @@ namespace Jint.Native.Proxy
             }
             }
 
 
             var extensibleTarget = _target.Extensible;
             var extensibleTarget = _target.Extensible;
-            var resultDesc = PropertyDescriptor.ToPropertyDescriptor(_engine.Realm, result);
+            var resultDesc = PropertyDescriptor.ToPropertyDescriptor(_engine.Realm, trapResultObj);
+            CompletePropertyDescriptor(resultDesc);
 
 
             var valid = IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc);
             var valid = IsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc);
             if (!valid)
             if (!valid)
@@ -245,14 +246,55 @@ namespace Jint.Native.Proxy
                 ExceptionHelper.ThrowTypeError(_engine.Realm);
                 ExceptionHelper.ThrowTypeError(_engine.Realm);
             }
             }
 
 
-            if (!resultDesc.Configurable && (targetDesc == PropertyDescriptor.Undefined || targetDesc.Configurable))
+            if (!resultDesc.Configurable)
             {
             {
-                ExceptionHelper.ThrowTypeError(_engine.Realm);
+                if (targetDesc == PropertyDescriptor.Undefined || targetDesc.Configurable)
+                {
+                    ExceptionHelper.ThrowTypeError(_engine.Realm);
+                }
+
+                if (resultDesc.WritableSet && !resultDesc.Writable)
+                {
+                    if (targetDesc.Writable)
+                    {
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
+                    }
+                }
             }
             }
 
 
             return resultDesc;
             return resultDesc;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-completepropertydescriptor
+        /// </summary>
+        private void CompletePropertyDescriptor(PropertyDescriptor desc)
+        {
+            if (desc.IsGenericDescriptor() || desc.IsDataDescriptor())
+            {
+                desc.Value ??= Undefined;
+                if (!desc.WritableSet)
+                {
+                    desc.Writable = false;
+                }
+            }
+            else
+            {
+                var getSet = (GetSetPropertyDescriptor) desc;
+                getSet.SetGet(getSet.Get ?? Undefined);
+                getSet.SetSet(getSet.Set ?? Undefined);
+            }
+
+            if (!desc.EnumerableSet)
+            {
+                desc.Enumerable = false;
+            }
+            if (!desc.ConfigurableSet)
+            {
+                desc.Configurable = false;
+            }
+        }
+
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
         /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-set-p-v-receiver
         /// </summary>
         /// </summary>
@@ -293,7 +335,7 @@ namespace Jint.Native.Proxy
         }
         }
 
 
         /// <summary>
         /// <summary>
-        /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-getownproperty-p
+        /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-defineownproperty-p-desc
         /// </summary>
         /// </summary>
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         public override bool DefineOwnProperty(JsValue property, PropertyDescriptor desc)
         {
         {
@@ -311,7 +353,7 @@ namespace Jint.Native.Proxy
 
 
             var targetDesc = _target.GetOwnProperty(property);
             var targetDesc = _target.GetOwnProperty(property);
             var extensibleTarget = _target.Extensible;
             var extensibleTarget = _target.Extensible;
-            var settingConfigFalse = !desc.Configurable;
+            var settingConfigFalse = desc.ConfigurableSet && !desc.Configurable;
 
 
             if (targetDesc == PropertyDescriptor.Undefined)
             if (targetDesc == PropertyDescriptor.Undefined)
             {
             {
@@ -330,6 +372,14 @@ namespace Jint.Native.Proxy
                 {
                 {
                     ExceptionHelper.ThrowTypeError(_engine.Realm);
                     ExceptionHelper.ThrowTypeError(_engine.Realm);
                 }
                 }
+
+                if (targetDesc.IsDataDescriptor() && !targetDesc.Configurable && targetDesc.Writable)
+                {
+                    if (desc.WritableSet && !desc.Writable)
+                    {
+                        ExceptionHelper.ThrowTypeError(_engine.Realm);
+                    }
+                }
             }
             }
 
 
             return true;
             return true;
@@ -382,24 +432,37 @@ namespace Jint.Native.Proxy
                 return _target.Delete(property);
                 return _target.Delete(property);
             }
             }
 
 
-            var success = TypeConverter.ToBoolean(result);
+            var booleanTrapResult = TypeConverter.ToBoolean(result);
 
 
-            if (success)
+            if (!booleanTrapResult)
             {
             {
-                var targetDesc = _target.GetOwnProperty(property);
-                if (targetDesc != PropertyDescriptor.Undefined && !targetDesc.Configurable)
-                {
-                    ExceptionHelper.ThrowTypeError(_engine.Realm, $"'deleteProperty' on proxy: trap returned truish for property '{property}' which is non-configurable in the proxy target");
-                }
+                return false;
             }
             }
 
 
-            return success;
+            var targetDesc = _target.GetOwnProperty(property);
+
+            if (targetDesc == PropertyDescriptor.Undefined)
+            {
+                return true;
+            }
+
+            if (!targetDesc.Configurable)
+            {
+                ExceptionHelper.ThrowTypeError(_engine.Realm, $"'deleteProperty' on proxy: trap returned truish for property '{property}' which is non-configurable in the proxy target");
+            }
+
+            if (!_target.Extensible)
+            {
+                ExceptionHelper.ThrowTypeError(_engine.Realm);
+            }
+
+            return true;
         }
         }
 
 
         /// <summary>
         /// <summary>
         /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-preventextensions
         /// https://tc39.es/ecma262/#sec-proxy-object-internal-methods-and-internal-slots-preventextensions
         /// </summary>
         /// </summary>
-        public override JsValue PreventExtensions()
+        public override bool PreventExtensions()
         {
         {
             if (!TryCallHandler(TrapPreventExtensions, new JsValue[] { _target }, out var result))
             if (!TryCallHandler(TrapPreventExtensions, new JsValue[] { _target }, out var result))
             {
             {
@@ -496,7 +559,7 @@ namespace Jint.Native.Proxy
             return true;
             return true;
         }
         }
 
 
-        internal override bool IsCallable => _target is not null && _target.IsCallable;
+        internal override bool IsCallable { get; }
 
 
         private bool TryCallHandler(JsValue propertyName, JsValue[] arguments, out JsValue result)
         private bool TryCallHandler(JsValue propertyName, JsValue[] arguments, out JsValue result)
         {
         {

+ 9 - 6
Jint/Native/Reflect/ReflectInstance.cs

@@ -82,21 +82,24 @@ namespace Jint.Native.Reflect
             return target.Construct(args, newTargetArgument);
             return target.Construct(args, newTargetArgument);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-reflect.defineproperty
+        /// </summary>
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         private JsValue DefineProperty(JsValue thisObject, JsValue[] arguments)
         {
         {
-            var o = arguments.At(0) as ObjectInstance;
-            if (o is null)
+            var target = arguments.At(0) as ObjectInstance;
+            if (target is null)
             {
             {
                 ExceptionHelper.ThrowTypeError(_realm, "Reflect.defineProperty called on non-object");
                 ExceptionHelper.ThrowTypeError(_realm, "Reflect.defineProperty called on non-object");
             }
             }
 
 
-            var p = arguments.At(1);
-            var name = TypeConverter.ToPropertyKey(p);
-
+            var propertyKey = arguments.At(1);
             var attributes = arguments.At(2);
             var attributes = arguments.At(2);
+
+            var key = TypeConverter.ToPropertyKey(propertyKey);
             var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, attributes);
             var desc = PropertyDescriptor.ToPropertyDescriptor(_realm, attributes);
 
 
-            return o.DefineOwnProperty(name, desc);
+            return target.DefineOwnProperty(key, desc);
         }
         }
 
 
         private JsValue DeleteProperty(JsValue thisObject, JsValue[] arguments)
         private JsValue DeleteProperty(JsValue thisObject, JsValue[] arguments)

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

@@ -896,7 +896,7 @@ namespace Jint.Native.RegExp
 
 
         private static ArrayInstance CreateReturnValueArray(Engine engine, Match match, string inputValue, bool fullUnicode)
         private static ArrayInstance CreateReturnValueArray(Engine engine, Match match, string inputValue, bool fullUnicode)
         {
         {
-            var array = engine.Realm.Intrinsics.Array.ArrayCreate((uint) match.Groups.Count);
+            var array = engine.Realm.Intrinsics.Array.ArrayCreate((ulong) match.Groups.Count);
             array.CreateDataProperty(PropertyIndex, match.Index);
             array.CreateDataProperty(PropertyIndex, match.Index);
             array.CreateDataProperty(PropertyInput, inputValue);
             array.CreateDataProperty(PropertyInput, inputValue);
 
 

+ 4 - 5
Jint/Native/Set/SetInstance.cs

@@ -4,12 +4,11 @@ using Jint.Runtime.Descriptors;
 
 
 namespace Jint.Native.Set
 namespace Jint.Native.Set
 {
 {
-    public class SetInstance : ObjectInstance
+    public sealed class SetInstance : ObjectInstance
     {
     {
         internal readonly OrderedSet<JsValue> _set;
         internal readonly OrderedSet<JsValue> _set;
 
 
-        public SetInstance(Engine engine)
-            : base(engine, ObjectClass.Map)
+        public SetInstance(Engine engine) : base(engine)
         {
         {
             _set = new OrderedSet<JsValue>(SameValueZeroComparer.Instance);
             _set = new OrderedSet<JsValue>(SameValueZeroComparer.Instance);
         }
         }
@@ -18,7 +17,7 @@ namespace Jint.Native.Set
         {
         {
             if (property == CommonProperties.Size)
             if (property == CommonProperties.Size)
             {
             {
-                return new PropertyDescriptor(_set.Count, PropertyFlag.None);
+                return new PropertyDescriptor(_set.Count, PropertyFlag.AllForbidden);
             }
             }
 
 
             return base.GetOwnProperty(property);
             return base.GetOwnProperty(property);
@@ -28,7 +27,7 @@ namespace Jint.Native.Set
         {
         {
             if (property == CommonProperties.Size)
             if (property == CommonProperties.Size)
             {
             {
-                descriptor = new PropertyDescriptor(_set.Count, PropertyFlag.None);
+                descriptor = new PropertyDescriptor(_set.Count, PropertyFlag.AllForbidden);
                 return true;
                 return true;
             }
             }
 
 

+ 4 - 2
Jint/Native/String/StringConstructor.cs

@@ -3,7 +3,6 @@ using Jint.Collections;
 using Jint.Native.Array;
 using Jint.Native.Array;
 using Jint.Native.Function;
 using Jint.Native.Function;
 using Jint.Native.Object;
 using Jint.Native.Object;
-using Jint.Native.Symbol;
 using Jint.Pooling;
 using Jint.Pooling;
 using Jint.Runtime;
 using Jint.Runtime;
 using Jint.Runtime.Descriptors;
 using Jint.Runtime.Descriptors;
@@ -12,6 +11,9 @@ using Jint.Runtime.Interpreter.Expressions;
 
 
 namespace Jint.Native.String
 namespace Jint.Native.String
 {
 {
+    /// <summary>
+    /// https://tc39.es/ecma262/#sec-string-constructor
+    /// </summary>
     public sealed class StringConstructor : FunctionInstance, IConstructor
     public sealed class StringConstructor : FunctionInstance, IConstructor
     {
     {
         private static readonly JsString _functionName = new JsString("String");
         private static readonly JsString _functionName = new JsString("String");
@@ -156,7 +158,7 @@ namespace Jint.Native.String
                 var value = arguments.At(0);
                 var value = arguments.At(0);
                 if (newTarget.IsUndefined() && value.IsSymbol())
                 if (newTarget.IsUndefined() && value.IsSymbol())
                 {
                 {
-                    return StringCreate(JsString.Create(SymbolPrototype.SymbolDescriptiveString((JsSymbol) value)), PrototypeObject);
+                    return StringCreate(JsString.Create(((JsSymbol) value).ToString()), PrototypeObject);
                 }
                 }
                 s = TypeConverter.ToJsString(arguments[0]);
                 s = TypeConverter.ToJsString(arguments[0]);
             }
             }

+ 16 - 5
Jint/Native/String/StringInstance.cs

@@ -78,17 +78,28 @@ namespace Jint.Native.String
             }
             }
         }
         }
 
 
+        internal override IEnumerable<JsValue> GetInitialOwnStringPropertyKeys()
+        {
+            return new[] { JsString.LengthString };
+        }
+
         public override List<JsValue> GetOwnPropertyKeys(Types types)
         public override List<JsValue> GetOwnPropertyKeys(Types types)
         {
         {
             var keys = new List<JsValue>(StringData.Length + 1);
             var keys = new List<JsValue>(StringData.Length + 1);
-            for (uint i = 0; i < StringData.Length; ++i)
+            if ((types & Types.String) != 0)
             {
             {
-                keys.Add(JsString.Create(i));
+                for (uint i = 0; i < StringData.Length; ++i)
+                {
+                    keys.Add(JsString.Create(i));
+                }
+
+                keys.AddRange(base.GetOwnPropertyKeys(Types.String));
             }
             }
 
 
-            keys.AddRange(base.GetOwnPropertyKeys(Types.String));
-            keys.AddRange(base.GetOwnPropertyKeys(Types.Symbol));
-            keys.Add(JsString.LengthString);
+            if ((types & Types.Symbol) != 0)
+            {
+                keys.AddRange(base.GetOwnPropertyKeys(Types.Symbol));
+            }
 
 
             return keys;
             return keys;
         }
         }

+ 29 - 26
Jint/Native/String/StringPrototype.cs

@@ -14,7 +14,7 @@ using Jint.Runtime.Interop;
 namespace Jint.Native.String
 namespace Jint.Native.String
 {
 {
     /// <summary>
     /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4
+    /// https://tc39.es/ecma262/#sec-properties-of-the-string-prototype-object
     /// </summary>
     /// </summary>
     public sealed class StringPrototype : StringInstance
     public sealed class StringPrototype : StringInstance
     {
     {
@@ -117,13 +117,13 @@ namespace Jint.Native.String
         const char BOM_CHAR = '\uFEFF';
         const char BOM_CHAR = '\uFEFF';
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        internal static bool IsWhiteSpaceEx(char c)
+        private static bool IsWhiteSpaceEx(char c)
         {
         {
             return char.IsWhiteSpace(c) || c == BOM_CHAR;
             return char.IsWhiteSpace(c) || c == BOM_CHAR;
         }
         }
 
 
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public static string TrimEndEx(string s)
+        private static string TrimEndEx(string s)
         {
         {
             if (s.Length == 0)
             if (s.Length == 0)
                 return string.Empty;
                 return string.Empty;
@@ -293,7 +293,7 @@ namespace Jint.Native.String
             return new JsString(s.Substring(from, length));
             return new JsString(s.Substring(from, length));
         }
         }
 
 
-        private JsValue Substr(JsValue thisObj, JsValue[] arguments)
+        private static JsValue Substr(JsValue thisObj, JsValue[] arguments)
         {
         {
             var s = TypeConverter.ToString(thisObj);
             var s = TypeConverter.ToString(thisObj);
             var start = TypeConverter.ToInteger(arguments.At(0));
             var start = TypeConverter.ToInteger(arguments.At(0));
@@ -317,10 +317,12 @@ namespace Jint.Native.String
             return s.Substring(startIndex, l);
             return s.Substring(startIndex, l);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-string.prototype.split
+        /// </summary>
         private JsValue Split(JsValue thisObj, JsValue[] arguments)
         private JsValue Split(JsValue thisObj, JsValue[] arguments)
         {
         {
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
             TypeConverter.CheckObjectCoercible(Engine, thisObj);
-            var s = TypeConverter.ToString(thisObj);
 
 
             var separator = arguments.At(0);
             var separator = arguments.At(0);
             var limit = arguments.At(1);
             var limit = arguments.At(1);
@@ -340,25 +342,16 @@ namespace Jint.Native.String
                 }
                 }
             }
             }
 
 
+            var s = TypeConverter.ToString(thisObj);
+
             // Coerce into a number, true will become 1
             // Coerce into a number, true will become 1
             var lim = limit.IsUndefined() ? uint.MaxValue : TypeConverter.ToUint32(limit);
             var lim = limit.IsUndefined() ? uint.MaxValue : TypeConverter.ToUint32(limit);
 
 
-            if (lim == 0)
-            {
-                return _realm.Intrinsics.Array.Construct(Arguments.Empty);
-            }
-
             if (separator.IsNull())
             if (separator.IsNull())
             {
             {
                 separator = Native.Null.Text;
                 separator = Native.Null.Text;
             }
             }
-            else if (separator.IsUndefined())
-            {
-                var arrayInstance = _realm.Intrinsics.Array.ConstructFast(1);
-                arrayInstance.SetIndexValue(0, s, updateLength: false);
-                return arrayInstance;
-            }
-            else
+            else if (!separator.IsUndefined())
             {
             {
                 if (!separator.IsRegExp())
                 if (!separator.IsRegExp())
                 {
                 {
@@ -366,6 +359,18 @@ namespace Jint.Native.String
                 }
                 }
             }
             }
 
 
+            if (lim == 0)
+            {
+                return _realm.Intrinsics.Array.ArrayCreate(0);
+            }
+
+            if (separator.IsUndefined())
+            {
+                var arrayInstance = _realm.Intrinsics.Array.ArrayCreate(1);
+                arrayInstance.SetIndexValue(0, s, updateLength: false);
+                return arrayInstance;
+            }
+
             return SplitWithStringSeparator(_realm, separator, s, lim);
             return SplitWithStringSeparator(_realm, separator, s, lim);
         }
         }
 
 
@@ -395,7 +400,7 @@ namespace Jint.Native.String
             }
             }
 
 
             var length = (uint) System.Math.Min(segments.Count, lim);
             var length = (uint) System.Math.Min(segments.Count, lim);
-            var a = realm.Intrinsics.Array.ConstructFast(length);
+            var a = realm.Intrinsics.Array.ArrayCreate(length);
             for (int i = 0; i < length; i++)
             for (int i = 0; i < length; i++)
             {
             {
                 a.SetIndexValue((uint) i, segments[i], updateLength: false);
                 a.SetIndexValue((uint) i, segments[i], updateLength: false);
@@ -1019,16 +1024,14 @@ namespace Jint.Native.String
                 return new string(str[0], n);
                 return new string(str[0], n);
             }
             }
 
 
-            using (var sb = StringBuilderPool.Rent())
+            using var sb = StringBuilderPool.Rent();
+            sb.Builder.EnsureCapacity(n * str.Length);
+            for (var i = 0; i < n; ++i)
             {
             {
-                sb.Builder.EnsureCapacity(n * str.Length);
-                for (var i = 0; i < n; ++i)
-                {
-                    sb.Builder.Append(str);
-                }
-
-                return sb.ToString();
+                sb.Builder.Append(str);
             }
             }
+
+            return sb.ToString();
         }
         }
     }
     }
 }
 }

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

@@ -28,6 +28,8 @@ namespace Jint.Native.Symbol
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
             _prototypeDescriptor = new PropertyDescriptor(PrototypeObject, PropertyFlag.AllForbidden);
         }
         }
 
 
+        public SymbolPrototype PrototypeObject { get; }
+
         protected override void Initialize()
         protected override void Initialize()
         {
         {
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
             const PropertyFlag lengthFlags = PropertyFlag.Configurable;
@@ -68,7 +70,10 @@ namespace Jint.Native.Symbol
             return value;
             return value;
         }
         }
 
 
-        public JsValue For(JsValue thisObj, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symbol.for
+        /// </summary>
+        private JsValue For(JsValue thisObj, JsValue[] arguments)
         {
         {
             var stringKey = TypeConverter.ToJsString(arguments.At(0));
             var stringKey = TypeConverter.ToJsString(arguments.At(0));
 
 
@@ -83,7 +88,10 @@ namespace Jint.Native.Symbol
             return symbol;
             return symbol;
         }
         }
 
 
-        public JsValue KeyFor(JsValue thisObj, JsValue[] arguments)
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symbol.keyfor
+        /// </summary>
+        private JsValue KeyFor(JsValue thisObj, JsValue[] arguments)
         {
         {
             var symbol = arguments.At(0) as JsSymbol;
             var symbol = arguments.At(0) as JsSymbol;
             if (symbol is null)
             if (symbol is null)
@@ -107,15 +115,7 @@ namespace Jint.Native.Symbol
 
 
         public SymbolInstance Construct(JsSymbol symbol)
         public SymbolInstance Construct(JsSymbol symbol)
         {
         {
-            var instance = new SymbolInstance(Engine)
-            {
-                _prototype = PrototypeObject,
-                SymbolData = symbol
-            };
-
-            return instance;
+            return new SymbolInstance(Engine, PrototypeObject, symbol);
         }
         }
-
-        public SymbolPrototype PrototypeObject { get; private set; }
     }
     }
 }
 }

+ 5 - 3
Jint/Native/Symbol/SymbolInstance.cs

@@ -3,17 +3,19 @@ using Jint.Runtime;
 
 
 namespace Jint.Native.Symbol
 namespace Jint.Native.Symbol
 {
 {
-    public class SymbolInstance : ObjectInstance, IPrimitiveInstance
+    public sealed class SymbolInstance : ObjectInstance, IPrimitiveInstance
     {
     {
-        public SymbolInstance(Engine engine)
+        internal SymbolInstance(Engine engine, SymbolPrototype prototype, JsSymbol symbol)
             : base(engine, ObjectClass.Symbol)
             : base(engine, ObjectClass.Symbol)
         {
         {
+            _prototype = prototype;
+            SymbolData = symbol;
         }
         }
 
 
         Types IPrimitiveInstance.Type => Types.Symbol;
         Types IPrimitiveInstance.Type => Types.Symbol;
 
 
         JsValue IPrimitiveInstance.PrimitiveValue => SymbolData;
         JsValue IPrimitiveInstance.PrimitiveValue => SymbolData;
 
 
-        public JsSymbol SymbolData { get; set; }
+        public JsSymbol SymbolData { get; }
     }
     }
 }
 }

+ 14 - 4
Jint/Native/Symbol/SymbolPrototype.cs

@@ -7,7 +7,7 @@ using Jint.Runtime.Interop;
 namespace Jint.Native.Symbol
 namespace Jint.Native.Symbol
 {
 {
     /// <summary>
     /// <summary>
-    /// http://www.ecma-international.org/ecma-262/5.1/#sec-15.5.4
+    /// https://tc39.es/ecma262/#sec-properties-of-the-symbol-prototype-object
     /// </summary>
     /// </summary>
     public sealed class SymbolPrototype : Prototype
     public sealed class SymbolPrototype : Prototype
     {
     {
@@ -44,30 +44,40 @@ namespace Jint.Native.Symbol
             );
             );
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symbol.prototype.description
+        /// </summary>
         private JsValue Description(JsValue thisObject, JsValue[] arguments)
         private JsValue Description(JsValue thisObject, JsValue[] arguments)
         {
         {
             var sym = ThisSymbolValue(thisObject);
             var sym = ThisSymbolValue(thisObject);
             return sym._value;
             return sym._value;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symbol.prototype.tostring
+        /// </summary>
         private JsValue ToSymbolString(JsValue thisObject, JsValue[] arguments)
         private JsValue ToSymbolString(JsValue thisObject, JsValue[] arguments)
         {
         {
             var sym = ThisSymbolValue(thisObject);
             var sym = ThisSymbolValue(thisObject);
-            return new JsString(SymbolDescriptiveString(sym));
+            return new JsString(sym.ToString());
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symbol.prototype.valueof
+        /// </summary>
         private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         private JsValue ValueOf(JsValue thisObject, JsValue[] arguments)
         {
         {
             return ThisSymbolValue(thisObject);
             return ThisSymbolValue(thisObject);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-symbol.prototype-@@toprimitive
+        /// </summary>
         private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
         private JsValue ToPrimitive(JsValue thisObject, JsValue[] arguments)
         {
         {
             return ThisSymbolValue(thisObject);
             return ThisSymbolValue(thisObject);
         }
         }
 
 
-        internal static string SymbolDescriptiveString(JsSymbol symbol) => symbol.ToString();
-
         private JsSymbol ThisSymbolValue(JsValue thisObject)
         private JsSymbol ThisSymbolValue(JsValue thisObject)
         {
         {
             if (thisObject is JsSymbol s)
             if (thisObject is JsSymbol s)

+ 30 - 6
Jint/Runtime/Descriptors/PropertyDescriptor.cs

@@ -14,6 +14,10 @@ namespace Jint.Runtime.Descriptors
         internal PropertyFlag _flags;
         internal PropertyFlag _flags;
         internal JsValue _value;
         internal JsValue _value;
 
 
+        public PropertyDescriptor() : this(PropertyFlag.None)
+        {
+        }
+
         protected PropertyDescriptor(PropertyFlag flags)
         protected PropertyDescriptor(PropertyFlag flags)
         {
         {
             _flags = flags;
             _flags = flags;
@@ -215,15 +219,18 @@ namespace Jint.Runtime.Descriptors
         internal PropertyFlag Flags
         internal PropertyFlag Flags
         {
         {
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
             [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            get { return _flags; }
+            get => _flags;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-topropertydescriptor
+        /// </summary>
         public static PropertyDescriptor ToPropertyDescriptor(Realm realm, JsValue o)
         public static PropertyDescriptor ToPropertyDescriptor(Realm realm, JsValue o)
         {
         {
-            var obj = o.TryCast<ObjectInstance>();
-            if (ReferenceEquals(obj, null))
+            if (o is not ObjectInstance obj)
             {
             {
                 ExceptionHelper.ThrowTypeError(realm);
                 ExceptionHelper.ThrowTypeError(realm);
+                return null;
             }
             }
 
 
             var getProperty = obj.GetProperty(CommonProperties.Get);
             var getProperty = obj.GetProperty(CommonProperties.Get);
@@ -301,6 +308,9 @@ namespace Jint.Runtime.Descriptors
             return desc;
             return desc;
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-frompropertydescriptor
+        /// </summary>
         public static JsValue FromPropertyDescriptor(Engine engine, PropertyDescriptor desc)
         public static JsValue FromPropertyDescriptor(Engine engine, PropertyDescriptor desc)
         {
         {
             if (ReferenceEquals(desc, Undefined))
             if (ReferenceEquals(desc, Undefined))
@@ -311,10 +321,17 @@ 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
+            // we should have possibility to leave out the properties in property descriptors as newer tests
+            // also assert properties to be undefined
+
             if (desc.IsDataDescriptor())
             if (desc.IsDataDescriptor())
             {
             {
                 properties["value"] =  new PropertyDescriptor(desc.Value ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
                 properties["value"] =  new PropertyDescriptor(desc.Value ?? Native.Undefined.Instance, PropertyFlag.ConfigurableEnumerableWritable);
-                properties["writable"] = new PropertyDescriptor(desc.Writable, PropertyFlag.ConfigurableEnumerableWritable);
+                if (desc._flags != PropertyFlag.None || desc.WritableSet)
+                {
+                    properties["writable"] = new PropertyDescriptor(desc.Writable, PropertyFlag.ConfigurableEnumerableWritable);
+                }
             }
             }
             else
             else
             {
             {
@@ -322,8 +339,15 @@ 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);
             }
             }
 
 
-            properties["enumerable"] = new PropertyDescriptor(desc.Enumerable, PropertyFlag.ConfigurableEnumerableWritable);
-            properties["configurable"] = new PropertyDescriptor(desc.Configurable, PropertyFlag.ConfigurableEnumerableWritable);
+            if (desc._flags != PropertyFlag.None || desc.EnumerableSet)
+            {
+                properties["enumerable"] = new PropertyDescriptor(desc.Enumerable, PropertyFlag.ConfigurableEnumerableWritable);
+            }
+
+            if (desc._flags != PropertyFlag.None || desc.ConfigurableSet)
+            {
+                properties["configurable"] = new PropertyDescriptor(desc.Configurable, PropertyFlag.ConfigurableEnumerableWritable);
+            }
 
 
             obj.SetProperties(properties);
             obj.SetProperties(properties);
             return obj;
             return obj;

+ 2 - 2
Jint/Runtime/Environments/FunctionEnvironmentRecord.cs

@@ -259,7 +259,7 @@ namespace Jint.Runtime.Environments
             }
             }
             else if (argument.IsObject() && argument.TryGetIterator(_functionObject._realm, out var iterator))
             else if (argument.IsObject() && argument.TryGetIterator(_functionObject._realm, out var iterator))
             {
             {
-                array = _engine.Realm.Intrinsics.Array.ConstructFast(0);
+                array = _engine.Realm.Intrinsics.Array.ArrayCreate(0);
                 var max = arrayPattern.Elements.Count;
                 var max = arrayPattern.Elements.Count;
                 if (max > 0 && arrayPattern.Elements[max - 1]?.Type == Nodes.RestElement)
                 if (max > 0 && arrayPattern.Elements[max - 1]?.Type == Nodes.RestElement)
                 {
                 {
@@ -297,7 +297,7 @@ namespace Jint.Runtime.Environments
             int restCount = arguments.Length - (index + 1) + 1;
             int restCount = arguments.Length - (index + 1) + 1;
             uint count = restCount > 0 ? (uint) restCount : 0;
             uint count = restCount > 0 ? (uint) restCount : 0;
 
 
-            var rest = _engine.Realm.Intrinsics.Array.ConstructFast(count);
+            var rest = _engine.Realm.Intrinsics.Array.ArrayCreate(count);
 
 
             uint targetIndex = 0;
             uint targetIndex = 0;
             for (var argIndex = index; argIndex < arguments.Length; ++argIndex)
             for (var argIndex = index; argIndex < arguments.Length; ++argIndex)

+ 3 - 0
Jint/Runtime/Environments/GlobalEnvironmentRecord.cs

@@ -271,6 +271,9 @@ namespace Jint.Runtime.Environments
             _varNames.Add(name);
             _varNames.Add(name);
         }
         }
 
 
+        /// <summary>
+        /// https://tc39.es/ecma262/#sec-createglobalfunctionbinding
+        /// </summary>
         public void CreateGlobalFunctionBinding(string name, JsValue value, bool canBeDeleted)
         public void CreateGlobalFunctionBinding(string name, JsValue value, bool canBeDeleted)
         {
         {
             var existingProp = _global.GetOwnProperty(name);
             var existingProp = _global.GetOwnProperty(name);

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

@@ -186,7 +186,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         if (arrayOperations != null)
                         if (arrayOperations != null)
                         {
                         {
                             var length = arrayOperations.GetLength();
                             var length = arrayOperations.GetLength();
-                            array = engine.Realm.Intrinsics.Array.ConstructFast(length - i);
+                            array = engine.Realm.Intrinsics.Array.ArrayCreate(length - i);
                             for (uint j = i; j < length; ++j)
                             for (uint j = i; j < length; ++j)
                             {
                             {
                                 arrayOperations.TryGetValue(j, out var indexValue);
                                 arrayOperations.TryGetValue(j, out var indexValue);
@@ -195,7 +195,7 @@ namespace Jint.Runtime.Interpreter.Expressions
                         }
                         }
                         else
                         else
                         {
                         {
-                            array = engine.Realm.Intrinsics.Array.ConstructFast(0);
+                            array = engine.Realm.Intrinsics.Array.ArrayCreate(0);
                             uint index = 0;
                             uint index = 0;
                             done = true;
                             done = true;
                             do
                             do

+ 1 - 1
Jint/Runtime/Interpreter/Expressions/JintArrayExpression.cs

@@ -38,7 +38,7 @@ namespace Jint.Runtime.Interpreter.Expressions
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)
         protected override ExpressionResult EvaluateInternal(EvaluationContext context)
         {
         {
             var engine = context.Engine;
             var engine = context.Engine;
-            var a = engine.Realm.Intrinsics.Array.ConstructFast(_hasSpreads ? 0 : (uint) _expressions.Length);
+            var a = engine.Realm.Intrinsics.Array.ArrayCreate(_hasSpreads ? 0 : (uint) _expressions.Length);
 
 
             uint arrayIndexCounter = 0;
             uint arrayIndexCounter = 0;
             foreach (var expr in _expressions)
             foreach (var expr in _expressions)

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

@@ -60,8 +60,8 @@ namespace Jint.Runtime.Interpreter.Expressions
         private ArrayInstance GetTemplateObject(EvaluationContext context)
         private ArrayInstance GetTemplateObject(EvaluationContext context)
         {
         {
             var count = (uint) _quasi._templateLiteralExpression.Quasis.Count;
             var count = (uint) _quasi._templateLiteralExpression.Quasis.Count;
-            var template = context.Engine.Realm.Intrinsics.Array.ConstructFast(count);
-            var rawObj = context.Engine.Realm.Intrinsics.Array.ConstructFast(count);
+            var template = context.Engine.Realm.Intrinsics.Array.ArrayCreate(count);
+            var rawObj = context.Engine.Realm.Intrinsics.Array.ArrayCreate(count);
             for (uint i = 0; i < _quasi._templateLiteralExpression.Quasis.Count; ++i)
             for (uint i = 0; i < _quasi._templateLiteralExpression.Quasis.Count; ++i)
             {
             {
                 var templateElementValue = _quasi._templateLiteralExpression.Quasis[(int) i].Value;
                 var templateElementValue = _quasi._templateLiteralExpression.Quasis[(int) i].Value;

+ 1 - 1
Jint/Runtime/Modules/ModuleNamespace.cs

@@ -32,7 +32,7 @@ internal sealed class ModuleNamespace : ObjectInstance
 
 
     public override bool Extensible => false;
     public override bool Extensible => false;
 
 
-    public override JsValue PreventExtensions() => JsBoolean.True;
+    public override bool PreventExtensions() => true;
 
 
     public override PropertyDescriptor GetOwnProperty(JsValue property)
     public override PropertyDescriptor GetOwnProperty(JsValue property)
     {
     {