Title: [260990] trunk
Revision
260990
Author
[email protected]
Date
2020-05-01 01:45:20 -0700 (Fri, 01 May 2020)

Log Message

We can't cast toLength result to unsigned
https://bugs.webkit.org/show_bug.cgi?id=211205
<rdar://problem/62625562>

Reviewed by Yusuke Suzuki.

JSTests:

* stress/array-length-cant-get-casted-to-unsigned.js: Added.
(assert):
(testArrayPop):
(testArrayPush):
(testArrayReverse):
(testArraySplice):
(testArrayUnshift):
(testArrayLastIndexOf):
(shouldThrowTypeError):
(testJSONStringify.get let):
(testJSONStringify):
* test262/expectations.yaml:

Source/_javascript_Core:

toLength, according to the spec, returns a 53-bit integer. In our
implementation, we return a double. However, there were many callsites
that did something like:
```
unsigned length = toLength(obj);
```

This is bad for a few reasons:
- Casting to unsigned from double is undefined behavior when the integer
is greater than UINT_MAX. In practice, this means that we'd have different
engine behavior depending on what architecture we'd be running on. For
example, if the length were UINT_MAX + 1, on x86, we'd treat the
length as zero. On arm64, we'd treat it as UINT_MAX. Both are wrong.
- We weren't spec compliant. We were just ignoring that these numbers could
be 53-bit integers.

This patch addresses each bad use of the undefined behavior, and by doing so,
makes us more spec compliant.

* dfg/DFGOperations.cpp:
* jit/JITOperations.cpp:
(JSC::getByVal):
* runtime/ArrayPrototype.cpp:
(JSC::getProperty):
(JSC::setLength):
(JSC::argumentClampedIndexFromStartOrEnd):
(JSC::shift):
(JSC::unshift):
(JSC::arrayProtoFuncToLocaleString):
(JSC::arrayProtoFuncPop):
(JSC::arrayProtoFuncPush):
(JSC::arrayProtoFuncReverse):
(JSC::arrayProtoFuncShift):
(JSC::arrayProtoFuncSlice):
(JSC::arrayProtoFuncSplice):
(JSC::arrayProtoFuncUnShift):
(JSC::fastIndexOf):
(JSC::arrayProtoFuncIndexOf):
(JSC::arrayProtoFuncLastIndexOf):
* runtime/Identifier.h:
(JSC::Identifier::from):
* runtime/IntlObject.cpp:
(JSC::canonicalizeLocaleList):
* runtime/JSONObject.cpp:
(JSC::Stringifier::Stringifier):
(JSC::Stringifier::Holder::appendNextProperty):
(JSC::Walker::walk):
* runtime/JSObject.cpp:
(JSC::JSObject::hasProperty const):
* runtime/JSObject.h:
(JSC::JSObject::putByIndexInline):
(JSC::JSObject::putDirectIndex):
(JSC::JSObject::canGetIndexQuickly const):
(JSC::JSObject::tryGetIndexQuickly const):
* runtime/JSObjectInlines.h:
(JSC::JSObject::getPropertySlot):
(JSC::JSObject::deleteProperty):
(JSC::JSObject::get const):
* runtime/PropertySlot.h:
(JSC::PropertySlot::getValue const):
* tools/JSDollarVM.cpp:
(JSC::functionSetUserPreferredLanguages):

Source/WebCore:

* bridge/NP_jsobject.cpp:

Source/WebKit:

* WebProcess/Plugins/Netscape/NPJSObject.cpp:
(WebKit::NPJSObject::hasProperty):
(WebKit::NPJSObject::getProperty):
(WebKit::NPJSObject::removeProperty):

LayoutTests:

* TestExpectations:
* ietestcenter/_javascript_/TestCases/15.4.4.14-3-28.js:
(ES5Harness.registerTest.test):
* ietestcenter/_javascript_/TestCases/15.4.4.14-3-29.js:
(ES5Harness.registerTest.test):
* ietestcenter/_javascript_/TestCases/15.4.4.15-3-25.js:
(ES5Harness.registerTest.test):
* ietestcenter/_javascript_/TestCases/15.4.4.15-3-28.js:
(ES5Harness.registerTest.test):

Modified Paths

Added Paths

Diff

Modified: trunk/JSTests/ChangeLog (260989 => 260990)


--- trunk/JSTests/ChangeLog	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/JSTests/ChangeLog	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1,3 +1,24 @@
+2020-05-01  Saam Barati  <[email protected]>
+
+        We can't cast toLength result to unsigned
+        https://bugs.webkit.org/show_bug.cgi?id=211205
+        <rdar://problem/62625562>
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/array-length-cant-get-casted-to-unsigned.js: Added.
+        (assert):
+        (testArrayPop):
+        (testArrayPush):
+        (testArrayReverse):
+        (testArraySplice):
+        (testArrayUnshift):
+        (testArrayLastIndexOf):
+        (shouldThrowTypeError):
+        (testJSONStringify.get let):
+        (testJSONStringify):
+        * test262/expectations.yaml:
+
 2020-04-30  Caio Lima  <[email protected]>
 
         Investigate stress/v8-bitint32-inc.js failure on mips

Added: trunk/JSTests/stress/array-length-cant-get-casted-to-unsigned.js (0 => 260990)


--- trunk/JSTests/stress/array-length-cant-get-casted-to-unsigned.js	                        (rev 0)
+++ trunk/JSTests/stress/array-length-cant-get-casted-to-unsigned.js	2020-05-01 08:45:20 UTC (rev 260990)
@@ -0,0 +1,202 @@
+function assert(b) {
+    if (!b)
+        throw new Error;
+}
+
+const boundary = 2**32; // UINT_MAX + 1
+const maxSafeInteger = 2**53 - 1;
+function testArrayPop() {
+    let obj = {
+        0: 42,
+        length: boundary 
+    };
+    Array.prototype.pop.call(obj);
+    assert(obj[0] === 42);
+    assert(obj.length === boundary - 1);
+}
+testArrayPop();
+
+function testArrayPush() {
+    let obj = {
+        0: 42,
+        length: boundary
+    };
+    Array.prototype.push.call(obj, 10);
+    assert(obj[0] === 42);
+    assert(obj.length === boundary + 1);
+}
+testArrayPush();
+
+// NOTE: this takes very long so we don't run it...
+function testArrayReverse() {
+    let obj = {
+        0: 42,
+        [boundary - 1]: 0,
+        length: boundary
+    };
+    Array.prototype.reverse.call(obj);
+    assert(obj[0] === 0);
+    assert(obj[boundary - 1] === 42);
+}
+//testArrayReverse();
+
+// NOTE: this takes very long so we don't run it...
+function testArrayShift() {
+    let obj = {
+        0: 42,
+        length: boundary
+    };
+    let elem = Array.prototype.shift.call(obj);
+    assert(elem === 42);
+    assert(obj.length === boundary - 1);
+    assert(obj[0] === undefined);
+}
+//testArrayShift();
+
+function testArraySlice() {
+    let obj = {
+        0: 42,
+        1: 43,
+        length: boundary
+    };
+    let arr = Array.prototype.slice.call(obj, 0, 2);
+    assert(arr[0] === 42);
+    assert(arr[1] === 43);
+    assert(arr.length === 2);
+}
+testArraySlice();
+
+function testArraySplice() {
+    let obj = {
+        0: 42,
+        1: 43,
+        length: boundary
+    };
+    Array.prototype.splice.call(obj, boundary-1, 0, 1, 2, 3);
+    assert(obj.length === boundary + 3);
+    assert(obj[boundary-1] === 1);
+    assert(obj[boundary] === 2);
+    assert(obj[boundary+1] === 3);
+}
+testArraySplice();
+
+// NOTE: this takes very long so we don't run it...
+function testArrayUnshift() {
+    let obj = {
+        1: 42,
+        length: boundary
+    };
+    Array.prototype.unshift.call(obj, 43);
+    assert(obj[0] === 43);
+    assert(obj[2] === 42);
+    assert(obj.length === boundary + 1);
+}
+//testArrayUnshift();
+
+function testArrayIndexOf() {
+    let obj = {
+        30: 42,
+        length: boundary
+    };
+    let r = Array.prototype.indexOf.call(obj, 42);
+    assert(r === 30);
+}
+testArrayIndexOf();
+
+function testArrayLastIndexOf() {
+    let obj = {
+        [boundary - 30]: 42,
+        length: boundary
+    };
+    let r = Array.prototype.lastIndexOf.call(obj, 42);
+    assert(r === boundary - 30);
+}
+testArrayLastIndexOf();
+
+function shouldThrowTypeError(f) {
+    let ok = false;
+    try {
+        f();
+    } catch(e) {
+        ok = e instanceof TypeError && e.message.indexOf("larger than (2 ** 53) - 1") >= 0;
+    }
+    assert(ok);
+}
+
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger
+    };
+    Array.prototype.push.call(obj, 10);
+});
+
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger - 1
+    };
+    Array.prototype.push.call(obj, 10, 20);
+});
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger
+    };
+    Array.prototype.unshift.call(obj, 10);
+});
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger - 1
+    };
+    Array.prototype.unshift.call(obj, 10, 20);
+});
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger
+    };
+    Array.prototype.splice.call(obj, obj.length - 10, 0, 10);
+});
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger - 1
+    };
+    Array.prototype.splice.call(obj, obj.length - 10, 0, 10, 20);
+});
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger - 1
+    };
+    Array.prototype.splice.call(obj, obj.length - 10, 1, 10, 20, 30);
+});
+shouldThrowTypeError(function() {
+    let obj = {
+        0: 42,
+        length: maxSafeInteger
+    };
+    Array.prototype.splice.call(obj, obj.length - 10, 1, 10, 20);
+});
+
+function testJSONStringify() {
+    let arr = [1,2,3];
+    let p = new Proxy(arr, {
+        get(target, prop, receiver) {
+            if (prop === "length") {
+                return boundary;
+            }
+            return Reflect.get(target, prop, receiver);
+        }
+    });
+    let ok = false;
+    try {
+        JSON.stringify(p);
+    } catch(e) {
+        ok = e.message.indexOf("Out of memory") >= 0;
+    }
+    assert(ok);
+}
+testJSONStringify();

Modified: trunk/JSTests/stress/array-reverse-proxy.js (260989 => 260990)


--- trunk/JSTests/stress/array-reverse-proxy.js	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/JSTests/stress/array-reverse-proxy.js	2020-05-01 08:45:20 UTC (rev 260990)
@@ -133,6 +133,10 @@
         }
     };
 
+
+    // When both start and end properties don't exist, spec says not to
+    // call the delete hook.
+
     let proxy = new Proxy(target, handler);
     let threw = false;
     try {
@@ -141,7 +145,7 @@
         threw = true;
         assert(e === error);
     }
-    assert(threw);
+    assert(!threw);
 });
 
 test(function() {

Modified: trunk/JSTests/test262/config.yaml (260989 => 260990)


--- trunk/JSTests/test262/config.yaml	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/JSTests/test262/config.yaml	2020-05-01 08:45:20 UTC (rev 260990)
@@ -86,27 +86,7 @@
 
     # https://bugs.webkit.org/show_bug.cgi?id=186749
     - test/built-ins/RegExp/property-escapes/character-class.js
-    
-    # https://bugs.webkit.org/show_bug.cgi?id=185495
-    - test/built-ins/Array/prototype/slice/S15.4.4.10_A3_T1.js
-    - test/built-ins/Array/prototype/slice/S15.4.4.10_A3_T2.js
-    - test/built-ins/Array/prototype/slice/create-non-array-invalid-len.js
-    - test/built-ins/Array/prototype/slice/create-proxied-array-invalid-len.js
-    - test/built-ins/Array/prototype/splice/create-species-undef-invalid-len.js
-    - test/built-ins/Array/prototype/splice/create-non-array-invalid-len.js
-    - test/built-ins/Array/prototype/splice/create-species-undef-invalid-len.js
-    - test/built-ins/Array/prototype/splice/length-near-integer-limit-grow-array.js
 
-    # https://bugs.webkit.org/show_bug.cgi?id=185625
-    - test/built-ins/Array/prototype/indexOf/15.4.4.14-3-28.js
-    - test/built-ins/Array/prototype/indexOf/15.4.4.14-3-29.js
-
-    # https://bugs.webkit.org/show_bug.cgi?id=164456
-    - test/built-ins/Array/prototype/lastIndexOf/15.4.4.15-3-28.js
-    - test/built-ins/Array/prototype/pop/S15.4.4.6_A3_T2.js
-    - test/built-ins/Array/prototype/push/S15.4.4.7_A4_T1.js
-    - test/built-ins/Array/prototype/push/length-near-integer-limit.js
-
     # [[OwnPropertyKeys]] order with large integer index keys up to 2 ** 53 - 1
     # https://bugs.webkit.org/show_bug.cgi?id=186691
     - test/built-ins/Reflect/ownKeys/return-on-corresponding-order-large-index.js

Modified: trunk/JSTests/test262/expectations.yaml (260989 => 260990)


--- trunk/JSTests/test262/expectations.yaml	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/JSTests/test262/expectations.yaml	2020-05-01 08:45:20 UTC (rev 260990)
@@ -642,63 +642,9 @@
 test/built-ins/Array/prototype/concat/is-concat-spreadable-get-order.js:
   default: 'Test262Error: Expected [isConcatSpreadable, constructor, isConcatSpreadable] and [constructor, isConcatSpreadable] to have the same contents. '
   strict mode: 'Test262Error: Expected [isConcatSpreadable, constructor, isConcatSpreadable] and [constructor, isConcatSpreadable] to have the same contents. '
-test/built-ins/Array/prototype/indexOf/length-near-integer-limit.js:
-  default: 'Test262Error: Expected SameValue(«-1», «9007199254740990») to be true'
-  strict mode: 'Test262Error: Expected SameValue(«-1», «9007199254740990») to be true'
-test/built-ins/Array/prototype/pop/S15.4.4.6_A2_T2.js:
-  default: 'Test262Error: #4: var obj = {}; obj.length = Number.POSITIVE_INFINITY; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 9007199254740990. Actual: 4294967294'
-  strict mode: 'Test262Error: #4: var obj = {}; obj.length = Number.POSITIVE_INFINITY; obj.pop = Array.prototype.pop; obj.pop(); obj.length === 9007199254740990. Actual: 4294967294'
-test/built-ins/Array/prototype/pop/S15.4.4.6_A3_T1.js:
-  default: 'Test262Error: #1: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; obj.pop() === "y". Actual: undefined'
-  strict mode: 'Test262Error: #1: var obj = {}; obj.pop = Array.prototype.pop; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; obj.pop() === "y". Actual: undefined'
-test/built-ins/Array/prototype/pop/clamps-to-integer-limit.js:
-  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967294», «9007199254740990») to be true'
-  strict mode: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967294», «9007199254740990») to be true'
-test/built-ins/Array/prototype/pop/length-near-integer-limit.js:
-  default: "Test262Error: arrayLike['9007199254740990'] is returned from pop() Expected SameValue(«undefined», «9007199254740990») to be true"
-  strict mode: "Test262Error: arrayLike['9007199254740990'] is returned from pop() Expected SameValue(«undefined», «9007199254740990») to be true"
-test/built-ins/Array/prototype/push/S15.4.4.7_A2_T2.js:
-  default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
-  strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
-test/built-ins/Array/prototype/push/clamps-to-integer-limit.js:
-  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-  strict mode: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-test/built-ins/Array/prototype/push/throws-if-integer-limit-exceeded.js:
-  default: 'Test262Error: Length is 2**53 - 1 Expected a TypeError to be thrown but no exception was thrown at all'
-  strict mode: 'Test262Error: Length is 2**53 - 1 Expected a TypeError to be thrown but no exception was thrown at all'
-test/built-ins/Array/prototype/reverse/length-exceeding-integer-limit-with-proxy.js:
-  default: 'Test262Error: Expected [Get:length, Has:0, Get:0, Has:4294967294, Delete:0, Set:4294967294, GetOwnPropertyDescriptor:4294967294, DefineProperty:4294967294, Has:1, Has:4294967293, Delete:1, Delete:4294967293, Has:2, Get:2, Has:4294967292, Delete:2, Set:4294967292, GetOwnPropertyDescriptor:4294967292, DefineProperty:4294967292, Has:3, Has:4294967291, Delete:3, Delete:4294967291, Has:4, Get:4] and [Get:length, Has:0, Get:0, Has:9007199254740990, Get:9007199254740990, Set:0, GetOwnPropertyDescriptor:0, DefineProperty:0, Set:9007199254740990, GetOwnPropertyDescriptor:9007199254740990, DefineProperty:9007199254740990, Has:1, Has:9007199254740989, Has:2, Get:2, Has:9007199254740988, Delete:2, Set:9007199254740988, GetOwnPropertyDescriptor:9007199254740988, DefineProperty:9007199254740988, Has:3, Has:9007199254740987, Get:9007199254740987, Set:3, GetOwnPropertyDescriptor:3, DefineProperty:3, Delete:9007199254740987, Has:4, Get:4] to have the same contents. '
-  strict mode: 'Test262Error: Expected [Get:length, Has:0, Get:0, Has:4294967294, Delete:0, Set:4294967294, GetOwnPropertyDescriptor:4294967294, DefineProperty:4294967294, Has:1, Has:4294967293, Delete:1, Delete:4294967293, Has:2, Get:2, Has:4294967292, Delete:2, Set:4294967292, GetOwnPropertyDescriptor:4294967292, DefineProperty:4294967292, Has:3, Has:4294967291, Delete:3, Delete:4294967291, Has:4, Get:4] and [Get:length, Has:0, Get:0, Has:9007199254740990, Get:9007199254740990, Set:0, GetOwnPropertyDescriptor:0, DefineProperty:0, Set:9007199254740990, GetOwnPropertyDescriptor:9007199254740990, DefineProperty:9007199254740990, Has:1, Has:9007199254740989, Has:2, Get:2, Has:9007199254740988, Delete:2, Set:9007199254740988, GetOwnPropertyDescriptor:9007199254740988, DefineProperty:9007199254740988, Has:3, Has:9007199254740987, Get:9007199254740987, Set:3, GetOwnPropertyDescriptor:3, DefineProperty:3, Delete:9007199254740987, Has:4, Get:4] to have the same contents. '
-test/built-ins/Array/prototype/slice/length-exceeding-integer-limit-proxied-array.js:
-  default: 'Test262Error: Expected [] and [9007199254740989, 9007199254740990] to have the same contents. slice(9007199254740989)'
-  strict mode: 'Test262Error: Expected [] and [9007199254740989, 9007199254740990] to have the same contents. slice(9007199254740989)'
-test/built-ins/Array/prototype/slice/length-exceeding-integer-limit.js:
-  default: 'Test262Error: Expected [] and [9007199254740989, 9007199254740990] to have the same contents. slice(9007199254740989)'
-  strict mode: 'Test262Error: Expected [] and [9007199254740989, 9007199254740990] to have the same contents. slice(9007199254740989)'
-test/built-ins/Array/prototype/splice/S15.4.4.12_A3_T1.js:
-  default: 'Test262Error: #1: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); arr.length === 1. Actual: 0'
-  strict mode: 'Test262Error: #1: var obj = {}; obj.splice = Array.prototype.splice; obj[0] = "x"; obj[4294967295] = "y"; obj.length = 4294967296; var arr = obj.splice(4294967295,1); arr.length === 1. Actual: 0'
-test/built-ins/Array/prototype/splice/clamps-length-to-integer-limit.js:
-  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-  strict mode: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-test/built-ins/Array/prototype/splice/create-species-length-exceeding-integer-limit.js:
-  default: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-  strict mode: 'Test262Error: length and deleteCount were correctly clamped to 2^53-1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-test/built-ins/Array/prototype/splice/length-and-deleteCount-exceeding-integer-limit.js:
-  default: "Test262Error: Expected [] and [9007199254740989, 9007199254740990] to have the same contents. arrayLike['9007199254740989'] and arrayLike['9007199254740990'] are removed"
-  strict mode: "Test262Error: Expected [] and [9007199254740989, 9007199254740990] to have the same contents. arrayLike['9007199254740989'] and arrayLike['9007199254740990'] are removed"
-test/built-ins/Array/prototype/splice/length-exceeding-integer-limit-shrink-array.js:
-  default: "Test262Error: Expected [] and [9007199254740987] to have the same contents. arrayLike['9007199254740987'] is removed"
-  strict mode: "Test262Error: Expected [] and [9007199254740987] to have the same contents. arrayLike['9007199254740987'] is removed"
 test/built-ins/Array/prototype/splice/property-traps-order-with-species.js:
   default: 'Test262Error: Expected [defineProperty, defineProperty, set, getOwnPropertyDescriptor, defineProperty] and [defineProperty, defineProperty] to have the same contents. '
   strict mode: 'Test262Error: Expected [defineProperty, defineProperty, set, getOwnPropertyDescriptor, defineProperty] and [defineProperty, defineProperty] to have the same contents. '
-test/built-ins/Array/prototype/splice/throws-if-integer-limit-exceeded.js:
-  default: 'Test262Error: Length is 2**53 - 1 Expected a TypeError but got a Error'
-  strict mode: 'Test262Error: Length is 2**53 - 1 Expected a TypeError but got a Error'
-test/built-ins/Array/prototype/unshift/clamps-to-integer-limit.js:
-  default: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
-  strict mode: 'Test262Error: Length is 2**53 - 1 Expected SameValue(«4294967295», «9007199254740991») to be true'
 test/built-ins/ArrayBuffer/prototype/byteLength/detached-buffer.js:
   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
@@ -3104,18 +3050,6 @@
 test/language/global-code/script-decl-var-err.js:
   default: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
   strict mode: 'Test262Error: Expected a TypeError to be thrown but no exception was thrown at all'
-test/language/identifiers/part-unicode-13.0.0-escaped.js:
-  default: "SyntaxError: Invalid unicode escape in identifier: '_\\u0B55'"
-  strict mode: "SyntaxError: Invalid unicode escape in identifier: '_\\u0B55'"
-test/language/identifiers/part-unicode-13.0.0.js:
-  default: "SyntaxError: Invalid character '\\u0b55'"
-  strict mode: "SyntaxError: Invalid character '\\u0b55'"
-test/language/identifiers/start-unicode-13.0.0-escaped.js:
-  default: "SyntaxError: Invalid unicode escape in identifier: '\\u08BE'"
-  strict mode: "SyntaxError: Invalid unicode escape in identifier: '\\u08BE'"
-test/language/identifiers/start-unicode-13.0.0.js:
-  default: "SyntaxError: Invalid character '\\u08be'"
-  strict mode: "SyntaxError: Invalid character '\\u08be'"
 test/language/literals/regexp/u-astral-char-class-invert.js:
   default: 'Test262Error: Expected SameValue(«�», «null») to be true'
   strict mode: 'Test262Error: Expected SameValue(«�», «null») to be true'

Modified: trunk/LayoutTests/ChangeLog (260989 => 260990)


--- trunk/LayoutTests/ChangeLog	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/LayoutTests/ChangeLog	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1,3 +1,21 @@
+2020-05-01  Saam Barati  <[email protected]>
+
+        We can't cast toLength result to unsigned
+        https://bugs.webkit.org/show_bug.cgi?id=211205
+        <rdar://problem/62625562>
+
+        Reviewed by Yusuke Suzuki.
+
+        * TestExpectations:
+        * ietestcenter/_javascript_/TestCases/15.4.4.14-3-28.js:
+        (ES5Harness.registerTest.test):
+        * ietestcenter/_javascript_/TestCases/15.4.4.14-3-29.js:
+        (ES5Harness.registerTest.test):
+        * ietestcenter/_javascript_/TestCases/15.4.4.15-3-25.js:
+        (ES5Harness.registerTest.test):
+        * ietestcenter/_javascript_/TestCases/15.4.4.15-3-28.js:
+        (ES5Harness.registerTest.test):
+
 2020-05-01  Antoine Quint  <[email protected]>
 
         REGRESSION: MotionMark 1.1 regressed due to r260016

Modified: trunk/LayoutTests/TestExpectations (260989 => 260990)


--- trunk/LayoutTests/TestExpectations	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/LayoutTests/TestExpectations	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1752,12 +1752,14 @@
 webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.14-3-7.html [ Failure ]
 webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.14-3-8.html [ Failure ]
 webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.15-3-12.html [ Failure ]
-webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.15-3-25.html [ Failure ]
 webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.15-3-7.html [ Failure ]
 
 webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.15-3-14.html [ Skip ]
 webkit.org/b/173506  ietestcenter/_javascript_/15.4.4.15-3-8.html [ Skip ]
 
+# This takes too long since it's searching through an array with ~4 billion elements.
+ietestcenter/_javascript_/15.4.4.15-3-29.html [ Skip ]
+
 # IDBVersionChangeEvent tests need to be rewritten to use event constructors instead of createEvent,
 # after we implement the IDBVersionChangeEvent constructor.
 webkit.org/b/145390 storage/indexeddb/events.html [ Failure ]

Modified: trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.14-3-28.js (260989 => 260990)


--- trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.14-3-28.js	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.14-3-28.js	2020-05-01 08:45:20 UTC (rev 260990)
@@ -36,7 +36,7 @@
             length: 4294967296
         };
 
-        return Array.prototype.indexOf.call(obj, targetObj) === -1;
+        return Array.prototype.indexOf.call(obj, targetObj) === 0;
     },
 
     precondition: function prereq() {

Modified: trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.14-3-29.js (260989 => 260990)


--- trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.14-3-29.js	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.14-3-29.js	2020-05-01 08:45:20 UTC (rev 260990)
@@ -36,7 +36,7 @@
         };
 
         return Array.prototype.indexOf.call(obj, targetObj) === 0 &&
-            Array.prototype.indexOf.call(obj, 4294967297) === -1;
+            Array.prototype.indexOf.call(obj, 4294967297) === 1;
     },
 
     precondition: function prereq() {

Modified: trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.15-3-25.js (260989 => 260990)


--- trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.15-3-25.js	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.15-3-25.js	2020-05-01 08:45:20 UTC (rev 260990)
@@ -31,7 +31,7 @@
 
         var obj = { 1: true, 2: false, length: -4294967294.5 };
 
-        return Array.prototype.lastIndexOf.call(obj, true) === 1 &&
+        return Array.prototype.lastIndexOf.call(obj, true) === -1 &&
             Array.prototype.lastIndexOf.call(obj, false) === -1;
     },
 

Modified: trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.15-3-28.js (260989 => 260990)


--- trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.15-3-28.js	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/LayoutTests/ietestcenter/_javascript_/TestCases/15.4.4.15-3-28.js	2020-05-01 08:45:20 UTC (rev 260990)
@@ -37,7 +37,7 @@
             length: 4294967296
         };
 
-        return Array.prototype.lastIndexOf.call(obj, targetObj) === -1; //verify length is 0 finally
+        return Array.prototype.lastIndexOf.call(obj, targetObj) === 4294967295;
     },
 
     precondition: function prereq() {

Modified: trunk/Source/_javascript_Core/ChangeLog (260989 => 260990)


--- trunk/Source/_javascript_Core/ChangeLog	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/ChangeLog	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1,3 +1,74 @@
+2020-05-01  Saam Barati  <[email protected]>
+
+        We can't cast toLength result to unsigned
+        https://bugs.webkit.org/show_bug.cgi?id=211205
+        <rdar://problem/62625562>
+
+        Reviewed by Yusuke Suzuki.
+
+        toLength, according to the spec, returns a 53-bit integer. In our
+        implementation, we return a double. However, there were many callsites
+        that did something like:
+        ```
+        unsigned length = toLength(obj);
+        ```
+        
+        This is bad for a few reasons:
+        - Casting to unsigned from double is undefined behavior when the integer
+        is greater than UINT_MAX. In practice, this means that we'd have different
+        engine behavior depending on what architecture we'd be running on. For
+        example, if the length were UINT_MAX + 1, on x86, we'd treat the
+        length as zero. On arm64, we'd treat it as UINT_MAX. Both are wrong.
+        - We weren't spec compliant. We were just ignoring that these numbers could
+        be 53-bit integers.
+        
+        This patch addresses each bad use of the undefined behavior, and by doing so,
+        makes us more spec compliant.
+
+        * dfg/DFGOperations.cpp:
+        * jit/JITOperations.cpp:
+        (JSC::getByVal):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::getProperty):
+        (JSC::setLength):
+        (JSC::argumentClampedIndexFromStartOrEnd):
+        (JSC::shift):
+        (JSC::unshift):
+        (JSC::arrayProtoFuncToLocaleString):
+        (JSC::arrayProtoFuncPop):
+        (JSC::arrayProtoFuncPush):
+        (JSC::arrayProtoFuncReverse):
+        (JSC::arrayProtoFuncShift):
+        (JSC::arrayProtoFuncSlice):
+        (JSC::arrayProtoFuncSplice):
+        (JSC::arrayProtoFuncUnShift):
+        (JSC::fastIndexOf):
+        (JSC::arrayProtoFuncIndexOf):
+        (JSC::arrayProtoFuncLastIndexOf):
+        * runtime/Identifier.h:
+        (JSC::Identifier::from):
+        * runtime/IntlObject.cpp:
+        (JSC::canonicalizeLocaleList):
+        * runtime/JSONObject.cpp:
+        (JSC::Stringifier::Stringifier):
+        (JSC::Stringifier::Holder::appendNextProperty):
+        (JSC::Walker::walk):
+        * runtime/JSObject.cpp:
+        (JSC::JSObject::hasProperty const):
+        * runtime/JSObject.h:
+        (JSC::JSObject::putByIndexInline):
+        (JSC::JSObject::putDirectIndex):
+        (JSC::JSObject::canGetIndexQuickly const):
+        (JSC::JSObject::tryGetIndexQuickly const):
+        * runtime/JSObjectInlines.h:
+        (JSC::JSObject::getPropertySlot):
+        (JSC::JSObject::deleteProperty):
+        (JSC::JSObject::get const):
+        * runtime/PropertySlot.h:
+        (JSC::PropertySlot::getValue const):
+        * tools/JSDollarVM.cpp:
+        (JSC::functionSetUserPreferredLanguages):
+
 2020-04-30  Ross Kirsling  <[email protected]>
 
         TriState should be an enum class and use "Indeterminate" instead of "Mixed"

Modified: trunk/Source/_javascript_Core/dfg/DFGOperations.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/dfg/DFGOperations.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -828,7 +828,7 @@
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     
     if (index >= 0) {
-        object->putByIndexInline(globalObject, index, JSValue::decode(encodedValue), true);
+        object->putByIndexInline(globalObject, static_cast<uint32_t>(index), JSValue::decode(encodedValue), true);
         return;
     }
     
@@ -844,7 +844,7 @@
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     
     if (index >= 0) {
-        object->putByIndexInline(globalObject, index, JSValue::decode(encodedValue), false);
+        object->putByIndexInline(globalObject, static_cast<uint32_t>(index), JSValue::decode(encodedValue), false);
         return;
     }
     
@@ -862,7 +862,7 @@
     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
     
     if (index >= 0) {
-        object->putByIndexInline(globalObject, index, jsValue, true);
+        object->putByIndexInline(globalObject, static_cast<uint32_t>(index), jsValue, true);
         return;
     }
     
@@ -880,7 +880,7 @@
     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
     
     if (index >= 0) {
-        object->putByIndexInline(globalObject, index, jsValue, false);
+        object->putByIndexInline(globalObject, static_cast<uint32_t>(index), jsValue, false);
         return;
     }
     
@@ -898,7 +898,7 @@
     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
 
     if (index >= 0) {
-        object->putDirectIndex(globalObject, index, jsValue, 0, PutDirectIndexShouldThrow);
+        object->putDirectIndex(globalObject, static_cast<uint32_t>(index), jsValue, 0, PutDirectIndexShouldThrow);
         return;
     }
 
@@ -915,7 +915,7 @@
     JSValue jsValue = JSValue(JSValue::EncodeAsDouble, value);
 
     if (index >= 0) {
-        object->putDirectIndex(globalObject, index, jsValue);
+        object->putDirectIndex(globalObject, static_cast<uint32_t>(index), jsValue);
         return;
     }
 
@@ -1003,7 +1003,7 @@
     CallFrame* callFrame = DECLARE_CALL_FRAME(vm);
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
     if (index >= 0) {
-        object->putDirectIndex(globalObject, index, JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
+        object->putDirectIndex(globalObject, static_cast<uint32_t>(index), JSValue::decode(encodedValue), 0, PutDirectIndexShouldThrow);
         return;
     }
     
@@ -1018,7 +1018,7 @@
     JITOperationPrologueCallFrameTracer tracer(vm, callFrame);
 
     if (index >= 0) {
-        object->putDirectIndex(globalObject, index, JSValue::decode(encodedValue));
+        object->putDirectIndex(globalObject, static_cast<uint32_t>(index), JSValue::decode(encodedValue));
         return;
     }
     

Modified: trunk/Source/_javascript_Core/jit/JITOperations.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/jit/JITOperations.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/jit/JITOperations.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1979,7 +1979,7 @@
                 arrayProfile->setOutOfBounds();
         } else if (baseValue.isObject()) {
             JSObject* object = asObject(baseValue);
-            if (object->canGetIndexQuickly(i))
+            if (object->canGetIndexQuickly(static_cast<uint32_t>(i)))
                 return object->getIndexQuickly(i);
 
             bool skipMarkingOutOfBounds = false;

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -147,7 +147,7 @@
 
 // ------------------------------ Array Functions ----------------------------
 
-static ALWAYS_INLINE JSValue getProperty(JSGlobalObject* globalObject, JSObject* object, unsigned index)
+static ALWAYS_INLINE JSValue getProperty(JSGlobalObject* globalObject, JSObject* object, uint64_t index)
 {
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
@@ -179,12 +179,13 @@
         throwTypeError(globalObject, scope, ReadonlyPropertyWriteError);
 }
 
-static ALWAYS_INLINE void setLength(JSGlobalObject* globalObject, VM& vm, JSObject* obj, unsigned value)
+static ALWAYS_INLINE void setLength(JSGlobalObject* globalObject, VM& vm, JSObject* obj, uint64_t value)
 {
     auto scope = DECLARE_THROW_SCOPE(vm);
     static constexpr bool throwException = true;
     if (isJSArray(obj)) {
-        jsCast<JSArray*>(obj)->setLength(globalObject, value, throwException);
+        ASSERT(static_cast<uint32_t>(value) == value);
+        jsCast<JSArray*>(obj)->setLength(globalObject, static_cast<uint32_t>(value), throwException);
         RETURN_IF_EXCEPTION(scope, void());
     }
     scope.release();
@@ -291,7 +292,7 @@
     RELEASE_AND_RETURN(scope, JSValue::encode(constructEmptyArray(globalObject, nullptr, static_cast<unsigned>(length))));
 }
 
-static inline unsigned argumentClampedIndexFromStartOrEnd(JSGlobalObject* globalObject, JSValue value, unsigned length, unsigned undefinedValue = 0)
+static inline uint64_t argumentClampedIndexFromStartOrEnd(JSGlobalObject* globalObject, JSValue value, uint64_t length, uint64_t undefinedValue = 0)
 {
     if (value.isUndefined())
         return undefinedValue;
@@ -299,9 +300,9 @@
     double indexDouble = value.toInteger(globalObject);
     if (indexDouble < 0) {
         indexDouble += length;
-        return indexDouble < 0 ? 0 : static_cast<unsigned>(indexDouble);
+        return indexDouble < 0 ? 0 : static_cast<uint64_t>(indexDouble);
     }
-    return indexDouble > length ? length : static_cast<unsigned>(indexDouble);
+    return indexDouble > length ? length : static_cast<uint64_t>(indexDouble);
 }
 
 // The shift/unshift function implement the shift/unshift behaviour required
@@ -320,13 +321,13 @@
 // must be introducing new values.
 
 template<JSArray::ShiftCountMode shiftCountMode>
-void shift(JSGlobalObject* globalObject, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
+void shift(JSGlobalObject* globalObject, JSObject* thisObj, uint64_t header, uint64_t currentCount, uint64_t resultCount, uint64_t length)
 {
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     RELEASE_ASSERT(currentCount > resultCount);
-    unsigned count = currentCount - resultCount;
+    uint64_t count = currentCount - resultCount;
 
     RELEASE_ASSERT(header <= length);
     RELEASE_ASSERT(currentCount <= (length - header));
@@ -333,13 +334,16 @@
 
     if (isJSArray(thisObj)) {
         JSArray* array = asArray(thisObj);
-        if (array->length() == length && array->shiftCount<shiftCountMode>(globalObject, header, count))
+        uint32_t header32 = header;
+        ASSERT(header32 == header);
+        if (array->length() == length && array->shiftCount<shiftCountMode>(globalObject, header32, count))
             return;
+        header = header32;
     }
 
-    for (unsigned k = header; k < length - currentCount; ++k) {
-        unsigned from = k + currentCount;
-        unsigned to = k + resultCount;
+    for (uint64_t k = header; k < length - currentCount; ++k) {
+        uint64_t from = k + currentCount;
+        uint64_t to = k + resultCount;
         JSValue value = getProperty(globalObject, thisObj, from);
         RETURN_IF_EXCEPTION(scope, void());
         if (value) {
@@ -346,7 +350,7 @@
             thisObj->putByIndexInline(globalObject, to, value, true);
             RETURN_IF_EXCEPTION(scope, void());
         } else {
-            bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, globalObject, to);
+            bool success = thisObj->deleteProperty(globalObject, to);
             RETURN_IF_EXCEPTION(scope, void());
             if (!success) {
                 throwTypeError(globalObject, scope, UnableToDeletePropertyError);
@@ -354,8 +358,8 @@
             }
         }
     }
-    for (unsigned k = length; k > length - count; --k) {
-        bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, globalObject, k - 1);
+    for (uint64_t k = length; k > length - count; --k) {
+        bool success = thisObj->deleteProperty(globalObject, k - 1);
         RETURN_IF_EXCEPTION(scope, void());
         if (!success) {
             throwTypeError(globalObject, scope, UnableToDeletePropertyError);
@@ -365,24 +369,29 @@
 }
 
 template<JSArray::ShiftCountMode shiftCountMode>
-void unshift(JSGlobalObject* globalObject, JSObject* thisObj, unsigned header, unsigned currentCount, unsigned resultCount, unsigned length)
+void unshift(JSGlobalObject* globalObject, JSObject* thisObj, uint64_t header, uint64_t currentCount, uint64_t resultCount, uint64_t length)
 {
+    ASSERT(header <= maxSafeInteger());
+    ASSERT(currentCount <= maxSafeInteger());
+    ASSERT(resultCount <= maxSafeInteger());
+    ASSERT(length <= maxSafeInteger());
+
     VM& vm = globalObject->vm();
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     RELEASE_ASSERT(resultCount > currentCount);
-    unsigned count = resultCount - currentCount;
+    uint64_t count = resultCount - currentCount;
 
     RELEASE_ASSERT(header <= length);
     RELEASE_ASSERT(currentCount <= (length - header));
 
-    // Guard against overflow.
-    if (count > UINT_MAX - length) {
-        throwOutOfMemoryError(globalObject, scope);
-        return;
-    }
+    if (isJSArray(thisObj)) {
+        // Spec says if we would produce an array of this size, we must throw a range error.
+        if (count + length > std::numeric_limits<uint32_t>::max()) {
+            throwRangeError(globalObject, scope, LengthExceededTheMaximumArrayLengthError);
+            return;
+        }
 
-    if (isJSArray(thisObj)) {
         JSArray* array = asArray(thisObj);
         if (array->length() == length) {
             bool handled = array->unshiftCount<shiftCountMode>(globalObject, header, count);
@@ -392,9 +401,9 @@
         }
     }
 
-    for (unsigned k = length - currentCount; k > header; --k) {
-        unsigned from = k + currentCount - 1;
-        unsigned to = k + resultCount - 1;
+    for (uint64_t k = length - currentCount; k > header; --k) {
+        uint64_t from = k + currentCount - 1;
+        uint64_t to = k + resultCount - 1;
         JSValue value = getProperty(globalObject, thisObj, from);
         RETURN_IF_EXCEPTION(scope, void());
         if (value) {
@@ -401,7 +410,7 @@
             thisObj->putByIndexInline(globalObject, to, value, true);
             RETURN_IF_EXCEPTION(scope, void());
         } else {
-            bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, globalObject, to);
+            bool success = thisObj->deleteProperty(globalObject, to);
             RETURN_IF_EXCEPTION(scope, void());
             if (UNLIKELY(!success)) {
                 throwTypeError(globalObject, scope, UnableToDeletePropertyError);
@@ -685,8 +694,12 @@
 
     JSObject* thisObject = thisValue.toObject(globalObject);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    unsigned length = toLength(globalObject, thisObject);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObject));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    if (length > std::numeric_limits<unsigned>::max()) {
+        throwOutOfMemoryError(globalObject, scope);
+        return encodedJSValue();
+    }
 
     StringRecursionChecker checker(globalObject, thisObject);
     EXCEPTION_ASSERT(!scope.exception() || checker.earlyReturnValue());
@@ -866,7 +879,7 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
-    unsigned length = toLength(globalObject, thisObj);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObj));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     if (length == 0) {
@@ -875,17 +888,24 @@
         return JSValue::encode(jsUndefined());
     }
 
-    JSValue result = thisObj->get(globalObject, length - 1);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    bool success = thisObj->methodTable(vm)->deletePropertyByIndex(thisObj, globalObject, length - 1);
-    RETURN_IF_EXCEPTION(scope, encodedJSValue());
-    if (UNLIKELY(!success)) {
-        throwTypeError(globalObject, scope, UnableToDeletePropertyError);
-        return encodedJSValue();
-    }
-    scope.release();
-    putLength(globalObject, vm, thisObj, jsNumber(length - 1));
-    return JSValue::encode(result);
+    auto performPop = [&] (auto index, JSValue indexValue) {
+        JSValue result = thisObj->get(globalObject, index);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        bool success = thisObj->deleteProperty(globalObject, index);
+        RETURN_IF_EXCEPTION(scope, encodedJSValue());
+        if (UNLIKELY(!success)) {
+            throwTypeError(globalObject, scope, UnableToDeletePropertyError);
+            return encodedJSValue();
+        }
+        scope.release();
+        putLength(globalObject, vm, thisObj, indexValue);
+        return JSValue::encode(result);
+    };
+
+    static_assert(MAX_ARRAY_INDEX + 1 > MAX_ARRAY_INDEX);
+    if (LIKELY(length <= MAX_ARRAY_INDEX + 1))
+        return performPop(static_cast<uint32_t>(length - 1), jsNumber(static_cast<uint32_t>(length - 1)));
+    return performPop(Identifier::from(vm, length - 1), jsNumber(length - 1));
 }
 
 EncodedJSValue JSC_HOST_CALL arrayProtoFuncPush(JSGlobalObject* globalObject, CallFrame* callFrame)
@@ -905,18 +925,19 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
-    unsigned length = toLength(globalObject, thisObj);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObj));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    unsigned argCount = callFrame->argumentCount();
 
-    for (unsigned n = 0; n < callFrame->argumentCount(); n++) {
-        // Check for integer overflow; where safe we can do a fast put by index.
-        if (length + n >= length)
-            thisObj->methodTable(vm)->putByIndex(thisObj, globalObject, length + n, callFrame->uncheckedArgument(n), true);
+    if (UNLIKELY(length + argCount > static_cast<uint64_t>(maxSafeInteger())))
+        return throwVMTypeError(globalObject, scope, "push cannot produce an array of length larger than (2 ** 53) - 1"_s);
+
+    for (unsigned n = 0; n < argCount; n++) {
+        if (LIKELY(length + n <= MAX_ARRAY_INDEX))
+            thisObj->methodTable(vm)->putByIndex(thisObj, globalObject, static_cast<uint32_t>(length + n), callFrame->uncheckedArgument(n), true);
         else {
             PutPropertySlot slot(thisObj);
-            auto string = JSValue(static_cast<int64_t>(length) + static_cast<int64_t>(n)).toWTFString(globalObject);
-            RETURN_IF_EXCEPTION(scope, encodedJSValue());
-            Identifier propertyName = Identifier::fromString(vm, string);
+            Identifier propertyName = Identifier::from(vm, length + n);
             thisObj->methodTable(vm)->put(thisObj, globalObject, propertyName, callFrame->uncheckedArgument(n), slot);
         }
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -938,7 +959,7 @@
     if (UNLIKELY(!thisObject))
         return encodedJSValue();
 
-    unsigned length = toLength(globalObject, thisObject);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObject));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     thisObject->ensureWritable(vm);
@@ -980,9 +1001,9 @@
     }
     }
 
-    unsigned middle = length / 2;
-    for (unsigned lower = 0; lower < middle; lower++) {
-        unsigned upper = length - lower - 1;
+    uint64_t middle = length / 2;
+    for (uint64_t lower = 0; lower < middle; lower++) {
+        uint64_t upper = length - lower - 1;
         bool lowerExists = thisObject->hasProperty(globalObject, lower);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
         JSValue lowerValue;
@@ -999,11 +1020,16 @@
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
         }
 
+        if (!lowerExists && !upperExists) {
+            // Spec says to do nothing when neither lower nor upper exist.
+            continue;
+        }
+
         if (upperExists) {
             thisObject->putByIndexInline(globalObject, lower, upperValue, true);
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
         } else {
-            bool success = thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, globalObject, lower);
+            bool success = thisObject->deleteProperty(globalObject, lower);
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
             if (UNLIKELY(!success)) {
                 throwTypeError(globalObject, scope, UnableToDeletePropertyError);
@@ -1015,7 +1041,7 @@
             thisObject->putByIndexInline(globalObject, upper, lowerValue, true);
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
         } else {
-            bool success = thisObject->methodTable(vm)->deletePropertyByIndex(thisObject, globalObject, upper);
+            bool success = thisObject->deleteProperty(globalObject, upper);
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
             if (UNLIKELY(!success)) {
                 throwTypeError(globalObject, scope, UnableToDeletePropertyError);
@@ -1034,7 +1060,7 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
-    unsigned length = toLength(globalObject, thisObj);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObj));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     if (length == 0) {
@@ -1061,12 +1087,12 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return { };
-    unsigned length = toLength(globalObject, thisObj);
+    uint64_t length = toLength(globalObject, thisObj);
     RETURN_IF_EXCEPTION(scope, { });
 
-    unsigned begin = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(0), length);
+    uint64_t begin = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(0), length);
     RETURN_IF_EXCEPTION(scope, { });
-    unsigned end = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(1), length, length);
+    uint64_t end = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(1), length, length);
     RETURN_IF_EXCEPTION(scope, { });
     if (end < begin)
         end = begin;
@@ -1088,7 +1114,11 @@
     if (speciesResult.first == SpeciesConstructResult::CreatedObject)
         result = speciesResult.second;
     else {
-        result = constructEmptyArray(globalObject, nullptr, end - begin);
+        if (UNLIKELY(end - begin > std::numeric_limits<uint32_t>::max())) {
+            throwRangeError(globalObject, scope, LengthExceededTheMaximumArrayLengthError);
+            return encodedJSValue();
+        }
+        result = constructEmptyArray(globalObject, nullptr, static_cast<uint32_t>(end - begin));
         RETURN_IF_EXCEPTION(scope, { });
     }
 
@@ -1096,8 +1126,8 @@
     // that can GC (e.g. allocating the result array).
     thisObj->use();
 
-    unsigned n = 0;
-    for (unsigned k = begin; k < end; k++, n++) {
+    uint64_t n = 0;
+    for (uint64_t k = begin; k < end; k++, n++) {
         JSValue v = getProperty(globalObject, thisObj, k);
         RETURN_IF_EXCEPTION(scope, { });
         if (v) {
@@ -1121,7 +1151,7 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
-    unsigned length = toLength(globalObject, thisObj);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObj));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     if (!callFrame->argumentCount()) {
@@ -1145,10 +1175,10 @@
         return JSValue::encode(result);
     }
 
-    unsigned actualStart = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(0), length);
+    uint64_t actualStart = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(0), length);
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
-    unsigned actualDeleteCount = length - actualStart;
+    uint64_t actualDeleteCount = length - actualStart;
     if (callFrame->argumentCount() > 1) {
         double deleteCount = callFrame->uncheckedArgument(1).toInteger(globalObject);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -1157,8 +1187,11 @@
         else if (deleteCount > length - actualStart)
             actualDeleteCount = length - actualStart;
         else
-            actualDeleteCount = static_cast<unsigned>(deleteCount);
+            actualDeleteCount = static_cast<uint64_t>(deleteCount);
     }
+    unsigned itemCount = std::max<int>(callFrame->argumentCount() - 2, 0);
+    if (UNLIKELY(length - actualDeleteCount + itemCount > static_cast<uint64_t>(maxSafeInteger())))
+        return throwVMTypeError(globalObject, scope, "Splice cannot produce an array of length larger than (2 ** 53) - 1"_s);
 
     std::pair<SpeciesConstructResult, JSObject*> speciesResult = speciesConstructArray(globalObject, thisObj, actualDeleteCount);
     EXCEPTION_ASSERT(!!scope.exception() == (speciesResult.first == SpeciesConstructResult::Exception));
@@ -1175,13 +1208,17 @@
         if (speciesResult.first == SpeciesConstructResult::CreatedObject)
             result = speciesResult.second;
         else {
-            result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), actualDeleteCount);
+            if (UNLIKELY(actualDeleteCount > std::numeric_limits<uint32_t>::max())) {
+                throwRangeError(globalObject, scope, LengthExceededTheMaximumArrayLengthError);
+                return encodedJSValue();
+            }
+            result = JSArray::tryCreate(vm, globalObject->arrayStructureForIndexingTypeDuringAllocation(ArrayWithUndecided), static_cast<uint32_t>(actualDeleteCount));
             if (UNLIKELY(!result)) {
                 throwOutOfMemoryError(globalObject, scope);
                 return encodedJSValue();
             }
         }
-        for (unsigned k = 0; k < actualDeleteCount; ++k) {
+        for (uint64_t k = 0; k < actualDeleteCount; ++k) {
             JSValue v = getProperty(globalObject, thisObj, k + actualStart);
             RETURN_IF_EXCEPTION(scope, encodedJSValue());
             if (UNLIKELY(!v))
@@ -1191,7 +1228,6 @@
         }
     }
 
-    unsigned itemCount = std::max<int>(callFrame->argumentCount() - 2, 0);
     if (itemCount < actualDeleteCount) {
         shift<JSArray::ShiftCountForSplice>(globalObject, thisObj, actualStart, actualDeleteCount, itemCount, length);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
@@ -1219,14 +1255,13 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObj);
     if (UNLIKELY(!thisObj))
         return encodedJSValue();
-    double doubleLength = toLength(globalObject, thisObj);
-    unsigned length = doubleLength;
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObj));
     RETURN_IF_EXCEPTION(scope, encodedJSValue());
 
     unsigned nrArgs = callFrame->argumentCount();
     if (nrArgs) {
-        if (UNLIKELY(doubleLength + static_cast<double>(nrArgs) > maxSafeInteger()))
-            return throwVMTypeError(globalObject, scope, "Cannot shift to offset greater than (2 ** 53) - 1"_s);
+        if (UNLIKELY(length + nrArgs > static_cast<uint64_t>(maxSafeInteger())))
+            return throwVMTypeError(globalObject, scope, "unshift cannot produce an array of length larger than (2 ** 53) - 1"_s);
         unshift<JSArray::ShiftCountForShift>(globalObject, thisObj, 0, 0, nrArgs, length);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
     }
@@ -1242,15 +1277,19 @@
 
 enum class IndexOfDirection { Forward, Backward };
 template<IndexOfDirection direction>
-ALWAYS_INLINE JSValue fastIndexOf(JSGlobalObject* globalObject, VM& vm, JSArray* array, unsigned length, JSValue searchElement, unsigned index)
+ALWAYS_INLINE JSValue fastIndexOf(JSGlobalObject* globalObject, VM& vm, JSArray* array, uint64_t length64, JSValue searchElement, uint64_t index64)
 {
     auto scope = DECLARE_THROW_SCOPE(vm);
 
     bool canDoFastPath = array->canDoFastIndexedAccess(vm)
-        && array->getArrayLength() == length; // The effects in getting `index` could have changed the length of this array.
+        && array->getArrayLength() == length64 // The effects in getting `index` could have changed the length of this array.
+        && static_cast<uint32_t>(index64) == index64;
     if (!canDoFastPath)
         return JSValue();
 
+    uint32_t length = static_cast<uint32_t>(length64);
+    uint32_t index = static_cast<uint32_t>(index64);
+
     switch (array->indexingType()) {
     case ALL_INT32_INDEXING_TYPES: {
         if (!searchElement.isNumber())
@@ -1351,10 +1390,10 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
     if (UNLIKELY(!thisObject))
         return { };
-    unsigned length = toLength(globalObject, thisObject);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObject));
     RETURN_IF_EXCEPTION(scope, { });
 
-    unsigned index = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(1), length);
+    uint64_t index = argumentClampedIndexFromStartOrEnd(globalObject, callFrame->argument(1), length);
     RETURN_IF_EXCEPTION(scope, { });
     JSValue searchElement = callFrame->argument(0);
 
@@ -1389,11 +1428,11 @@
     EXCEPTION_ASSERT(!!scope.exception() == !thisObject);
     if (UNLIKELY(!thisObject))
         return { };
-    unsigned length = toLength(globalObject, thisObject);
+    uint64_t length = static_cast<uint64_t>(toLength(globalObject, thisObject));
     if (UNLIKELY(scope.exception()) || !length)
         return JSValue::encode(jsNumber(-1));
 
-    unsigned index = length - 1;
+    uint64_t index = length - 1;
     if (callFrame->argumentCount() >= 2) {
         JSValue fromValue = callFrame->uncheckedArgument(1);
         double fromDouble = fromValue.toInteger(globalObject);
@@ -1404,7 +1443,7 @@
                 return JSValue::encode(jsNumber(-1));
         }
         if (fromDouble < length)
-            index = static_cast<unsigned>(fromDouble);
+            index = static_cast<uint64_t>(fromDouble);
     }
 
     JSValue searchElement = callFrame->argument(0);

Modified: trunk/Source/_javascript_Core/runtime/Identifier.h (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/Identifier.h	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/Identifier.h	2020-05-01 08:45:20 UTC (rev 260990)
@@ -130,7 +130,14 @@
 
     JS_EXPORT_PRIVATE static Identifier from(VM&, unsigned y);
     JS_EXPORT_PRIVATE static Identifier from(VM&, int y);
-    static Identifier from(VM&, double y);
+    JS_EXPORT_PRIVATE static Identifier from(VM&, double y);
+    ALWAYS_INLINE static Identifier from(VM& vm, uint64_t y)
+    {
+        if (static_cast<uint32_t>(y) == y)
+            return from(vm, static_cast<uint32_t>(y));
+        ASSERT(static_cast<uint64_t>(static_cast<double>(y)) == y);
+        return from(vm, static_cast<double>(y));
+    }
 
     bool isNull() const { return m_string.isNull(); }
     bool isEmpty() const { return m_string.isEmpty(); }

Modified: trunk/Source/_javascript_Core/runtime/IntlObject.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/IntlObject.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/IntlObject.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -385,11 +385,11 @@
     JSValue lengthProperty = localesObject->get(globalObject, vm.propertyNames->length);
     RETURN_IF_EXCEPTION(scope, Vector<String>());
 
-    double length = lengthProperty.toLength(globalObject);
+    uint64_t length = static_cast<uint64_t>(lengthProperty.toLength(globalObject));
     RETURN_IF_EXCEPTION(scope, Vector<String>());
 
     HashSet<String> seenSet;
-    for (double k = 0; k < length; ++k) {
+    for (uint64_t k = 0; k < length; ++k) {
         bool kPresent = localesObject->hasProperty(globalObject, k);
         RETURN_IF_EXCEPTION(scope, Vector<String>());
 

Modified: trunk/Source/_javascript_Core/runtime/JSONObject.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/JSONObject.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/JSONObject.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -236,9 +236,9 @@
             RETURN_IF_EXCEPTION(scope, );
             if (isArrayReplacer) {
                 m_usingArrayReplacer = true;
-                unsigned length = toLength(globalObject, replacerObject);
+                uint64_t length = static_cast<uint64_t>(toLength(globalObject, replacerObject));
                 RETURN_IF_EXCEPTION(scope, );
-                for (unsigned index = 0; index < length; ++index) {
+                for (uint64_t index = 0; index < length; ++index) {
                     JSValue name;
                     if (isJSArray(replacerObject) && replacerObject->canGetIndexQuickly(index))
                         name = replacerObject->getIndexQuickly(index);
@@ -476,8 +476,14 @@
     // First time through, initialize.
     if (!m_index) {
         if (m_isArray) {
-            m_size = toLength(globalObject, m_object);
+            uint64_t length = static_cast<uint64_t>(toLength(globalObject, m_object));
             RETURN_IF_EXCEPTION(scope, false);
+            if (UNLIKELY(length > std::numeric_limits<uint32_t>::max())) {
+                throwOutOfMemoryError(globalObject, scope);
+                return false;
+            }
+            m_size = static_cast<uint32_t>(length);
+            RETURN_IF_EXCEPTION(scope, false);
             builder.append('[');
         } else {
             if (stringifier.m_usingArrayReplacer)
@@ -645,9 +651,14 @@
 
                 JSObject* array = asObject(inValue);
                 markedStack.appendWithCrashOnOverflow(array);
-                unsigned length = toLength(m_globalObject, array);
+                uint64_t length = static_cast<uint64_t>(toLength(m_globalObject, array));
                 RETURN_IF_EXCEPTION(scope, { });
-                arrayLengthStack.append(length);
+                if (UNLIKELY(length > std::numeric_limits<uint32_t>::max())) {
+                    throwOutOfMemoryError(m_globalObject, scope);
+                    return { };
+                }
+                RETURN_IF_EXCEPTION(scope, { });
+                arrayLengthStack.append(static_cast<uint32_t>(length));
                 indexStack.append(0);
             }
             arrayStartVisitMember:

Modified: trunk/Source/_javascript_Core/runtime/JSObject.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/JSObject.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1958,6 +1958,14 @@
     return hasPropertyGeneric(globalObject, propertyName, PropertySlot::InternalMethodType::HasProperty);
 }
 
+bool JSObject::hasProperty(JSGlobalObject* globalObject, uint64_t propertyName) const
+{
+    if (LIKELY(propertyName <= MAX_ARRAY_INDEX))
+        return hasProperty(globalObject, static_cast<uint32_t>(propertyName));
+    ASSERT(propertyName <= maxSafeInteger());
+    return hasProperty(globalObject, Identifier::from(globalObject->vm(), propertyName));
+}
+
 bool JSObject::hasPropertyGeneric(JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot::InternalMethodType internalMethodType) const
 {
     PropertySlot slot(this, internalMethodType);

Modified: trunk/Source/_javascript_Core/runtime/JSObject.h (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/JSObject.h	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/JSObject.h	2020-05-01 08:45:20 UTC (rev 260990)
@@ -35,6 +35,7 @@
 #include "Heap.h"
 #include "IndexingHeaderInlines.h"
 #include "JSCast.h"
+#include "MathCommon.h"
 #include "ObjectInitializationScope.h"
 #include "PropertySlot.h"
 #include "PropertyStorage.h"
@@ -159,10 +160,12 @@
 
     JSValue get(JSGlobalObject*, PropertyName) const;
     JSValue get(JSGlobalObject*, unsigned propertyName) const;
+    JSValue get(JSGlobalObject*, uint64_t propertyName) const;
 
     template<bool checkNullStructure = false>
     bool getPropertySlot(JSGlobalObject*, PropertyName, PropertySlot&);
     bool getPropertySlot(JSGlobalObject*, unsigned propertyName, PropertySlot&);
+    bool getPropertySlot(JSGlobalObject*, uint64_t propertyName, PropertySlot&);
     template<typename CallbackWhenNoException> typename std::result_of<CallbackWhenNoException(bool, PropertySlot&)>::type getPropertySlot(JSGlobalObject*, PropertyName, CallbackWhenNoException) const;
     template<typename CallbackWhenNoException> typename std::result_of<CallbackWhenNoException(bool, PropertySlot&)>::type getPropertySlot(JSGlobalObject*, PropertyName, PropertySlot&, CallbackWhenNoException) const;
 
@@ -206,6 +209,16 @@
         }
         return methodTable(vm)->putByIndex(this, globalObject, propertyName, value, shouldThrow);
     }
+
+    ALWAYS_INLINE bool putByIndexInline(JSGlobalObject* globalObject, uint64_t propertyName, JSValue value, bool shouldThrow)
+    {
+        if (LIKELY(propertyName <= MAX_ARRAY_INDEX))
+            return putByIndexInline(globalObject, static_cast<uint32_t>(propertyName), value, shouldThrow);
+
+        ASSERT(propertyName <= maxSafeInteger());
+        PutPropertySlot slot(this, shouldThrow);
+        return putInlineForJSObject(this, globalObject, Identifier::from(getVM(globalObject), propertyName), value, slot);
+    }
         
     // This is similar to the putDirect* methods:
     //  - the prototype chain is not consulted
@@ -246,6 +259,13 @@
         return putDirectIndex(globalObject, propertyName, value, 0, PutDirectIndexLikePutDirect);
     }
 
+    ALWAYS_INLINE bool putDirectIndex(JSGlobalObject* globalObject, uint64_t propertyName, JSValue value, unsigned attributes, PutDirectIndexMode mode)
+    {
+        if (LIKELY(propertyName <= MAX_ARRAY_INDEX))
+            return putDirectIndex(globalObject, static_cast<uint32_t>(propertyName), value, attributes, mode);
+        return putDirect(getVM(globalObject), Identifier::from(getVM(globalObject), propertyName), value, attributes);
+    }
+
     // A generally non-throwing version of putDirect and putDirectIndex.
     // However, it's only guaranteed to not throw based on what the receiver is.
     // For example, if the receiver is a ProxyObject, this is not guaranteed, since
@@ -288,6 +308,14 @@
             return false;
         }
     }
+
+    bool canGetIndexQuickly(uint64_t i) const
+    {
+        ASSERT(i <= maxSafeInteger());
+        if (LIKELY(i <= MAX_ARRAY_INDEX))
+            return canGetIndexQuickly(static_cast<uint32_t>(i));
+        return false;
+    }
         
     JSValue getIndexQuickly(unsigned i) const
     {
@@ -348,6 +376,14 @@
         }
         return JSValue();
     }
+
+    JSValue tryGetIndexQuickly(uint64_t i) const
+    {
+        ASSERT(i <= maxSafeInteger());
+        if (LIKELY(i <= MAX_ARRAY_INDEX))
+            return tryGetIndexQuickly(static_cast<uint32_t>(i));
+        return JSValue();
+    }
         
     JSValue getDirectIndex(JSGlobalObject* globalObject, unsigned i)
     {
@@ -612,6 +648,7 @@
 
     JS_EXPORT_PRIVATE bool hasProperty(JSGlobalObject*, PropertyName) const;
     JS_EXPORT_PRIVATE bool hasProperty(JSGlobalObject*, unsigned propertyName) const;
+    bool hasProperty(JSGlobalObject*, uint64_t propertyName) const;
     bool hasPropertyGeneric(JSGlobalObject*, PropertyName, PropertySlot::InternalMethodType) const;
     bool hasPropertyGeneric(JSGlobalObject*, unsigned propertyName, PropertySlot::InternalMethodType) const;
     bool hasOwnProperty(JSGlobalObject*, PropertyName, PropertySlot&) const;
@@ -620,6 +657,9 @@
 
     JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName, DeletePropertySlot&);
     JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, JSGlobalObject*, unsigned propertyName);
+    bool deleteProperty(JSGlobalObject*, PropertyName);
+    bool deleteProperty(JSGlobalObject*, uint32_t propertyName);
+    bool deleteProperty(JSGlobalObject*, uint64_t propertyName);
 
     JS_EXPORT_PRIVATE static JSValue defaultValue(const JSObject*, JSGlobalObject*, PreferredPrimitiveType);
     JSValue ordinaryToPrimitive(JSGlobalObject*, PreferredPrimitiveType) const;

Modified: trunk/Source/_javascript_Core/runtime/JSObjectInlines.h (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/JSObjectInlines.h	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/JSObjectInlines.h	2020-05-01 08:45:20 UTC (rev 260990)
@@ -149,6 +149,13 @@
     }
 }
 
+ALWAYS_INLINE bool JSObject::getPropertySlot(JSGlobalObject* globalObject, uint64_t propertyName, PropertySlot& slot)
+{
+    if (LIKELY(propertyName <= MAX_ARRAY_INDEX))
+        return getPropertySlot(globalObject, static_cast<uint32_t>(propertyName), slot);
+    return getPropertySlot(globalObject, Identifier::from(globalObject->vm(), propertyName), slot);
+}
+
 ALWAYS_INLINE bool JSObject::getNonIndexPropertySlot(JSGlobalObject* globalObject, PropertyName propertyName, PropertySlot& slot)
 {
     // This method only supports non-index PropertyNames.
@@ -535,4 +542,31 @@
     return result;
 }
 
+inline bool JSObject::deleteProperty(JSGlobalObject* globalObject, PropertyName propertyName)
+{
+    DeletePropertySlot slot;
+    return this->methodTable(globalObject->vm())->deleteProperty(this, globalObject, propertyName, slot);
+}
+
+inline bool JSObject::deleteProperty(JSGlobalObject* globalObject, uint32_t propertyName)
+{
+    return this->methodTable(globalObject->vm())->deletePropertyByIndex(this, globalObject, propertyName);
+}
+
+inline bool JSObject::deleteProperty(JSGlobalObject* globalObject, uint64_t propertyName)
+{
+    if (LIKELY(propertyName <= MAX_ARRAY_INDEX))
+        return deleteProperty(globalObject, static_cast<uint32_t>(propertyName));
+    ASSERT(propertyName <= maxSafeInteger());
+    return deleteProperty(globalObject, Identifier::from(globalObject->vm(), propertyName));
+}
+
+inline JSValue JSObject::get(JSGlobalObject* globalObject, uint64_t propertyName) const
+{
+    if (LIKELY(propertyName <= MAX_ARRAY_INDEX))
+        return get(globalObject, static_cast<uint32_t>(propertyName));
+    ASSERT(propertyName <= maxSafeInteger());
+    return get(globalObject, Identifier::from(globalObject->vm(), propertyName));
+}
+
 } // namespace JSC

Modified: trunk/Source/_javascript_Core/runtime/PropertySlot.h (260989 => 260990)


--- trunk/Source/_javascript_Core/runtime/PropertySlot.h	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/runtime/PropertySlot.h	2020-05-01 08:45:20 UTC (rev 260990)
@@ -130,7 +130,7 @@
     typedef EncodedJSValue (*GetValueFunc)(JSGlobalObject*, EncodedJSValue thisValue, PropertyName);
 
     JSValue getValue(JSGlobalObject*, PropertyName) const;
-    JSValue getValue(JSGlobalObject*, unsigned propertyName) const;
+    JSValue getValue(JSGlobalObject*, uint64_t propertyName) const;
     JSValue getPureResult() const;
 
     bool isCacheable() const { return isUnset() || m_cacheability == CachingAllowed; }
@@ -422,7 +422,7 @@
     return customGetter(globalObject, propertyName);
 }
 
-ALWAYS_INLINE JSValue PropertySlot::getValue(JSGlobalObject* globalObject, unsigned propertyName) const
+ALWAYS_INLINE JSValue PropertySlot::getValue(JSGlobalObject* globalObject, uint64_t propertyName) const
 {
     VM& vm = getVM(globalObject);
     if (m_propertyType == TypeValue)

Modified: trunk/Source/_javascript_Core/tools/JSDollarVM.cpp (260989 => 260990)


--- trunk/Source/_javascript_Core/tools/JSDollarVM.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/_javascript_Core/tools/JSDollarVM.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -2967,7 +2967,7 @@
 
     Vector<String> languages;
     unsigned length = array->length();
-    for (size_t i = 0; i < length; i++) {
+    for (unsigned i = 0; i < length; i++) {
         String language = array->get(globalObject, i).toWTFString(globalObject);
         RETURN_IF_EXCEPTION(scope, encodedJSValue());
         languages.append(language);

Modified: trunk/Source/WebCore/ChangeLog (260989 => 260990)


--- trunk/Source/WebCore/ChangeLog	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/WebCore/ChangeLog	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1,3 +1,13 @@
+2020-05-01  Saam Barati  <[email protected]>
+
+        We can't cast toLength result to unsigned
+        https://bugs.webkit.org/show_bug.cgi?id=211205
+        <rdar://problem/62625562>
+
+        Reviewed by Yusuke Suzuki.
+
+        * bridge/NP_jsobject.cpp:
+
 2020-05-01  Antoine Quint  <[email protected]>
 
         REGRESSION: MotionMark 1.1 regressed due to r260016

Modified: trunk/Source/WebCore/bridge/NP_jsobject.cpp (260989 => 260990)


--- trunk/Source/WebCore/bridge/NP_jsobject.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/WebCore/bridge/NP_jsobject.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -311,7 +311,7 @@
         if (i->isString())
             result = obj->imp->get(lexicalGlobalObject, identifierFromNPIdentifier(lexicalGlobalObject, i->string()));
         else
-            result = obj->imp->get(lexicalGlobalObject, i->number());
+            result = obj->imp->get(lexicalGlobalObject, static_cast<uint32_t>(i->number()));
 
         convertValueToNPVariant(lexicalGlobalObject, result, variant);
         scope.clearException();
@@ -383,7 +383,7 @@
                 return false;
             }
         } else {
-            if (!obj->imp->hasProperty(lexicalGlobalObject, i->number())) {
+            if (!obj->imp->hasProperty(lexicalGlobalObject, static_cast<uint32_t>(i->number()))) {
                 scope.clearException();
                 return false;
             }
@@ -422,7 +422,7 @@
             return result;
         }
 
-        bool result = obj->imp->hasProperty(lexicalGlobalObject, i->number());
+        bool result = obj->imp->hasProperty(lexicalGlobalObject, static_cast<uint32_t>(i->number()));
         scope.clearException();
         return result;
     }

Modified: trunk/Source/WebKit/ChangeLog (260989 => 260990)


--- trunk/Source/WebKit/ChangeLog	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/WebKit/ChangeLog	2020-05-01 08:45:20 UTC (rev 260990)
@@ -1,3 +1,16 @@
+2020-05-01  Saam Barati  <[email protected]>
+
+        We can't cast toLength result to unsigned
+        https://bugs.webkit.org/show_bug.cgi?id=211205
+        <rdar://problem/62625562>
+
+        Reviewed by Yusuke Suzuki.
+
+        * WebProcess/Plugins/Netscape/NPJSObject.cpp:
+        (WebKit::NPJSObject::hasProperty):
+        (WebKit::NPJSObject::getProperty):
+        (WebKit::NPJSObject::removeProperty):
+
 2020-05-01  Adrian Perez de Castro  <[email protected]>
 
         [GTK4] Disable arrow on context menu popover

Modified: trunk/Source/WebKit/WebProcess/Plugins/Netscape/NPJSObject.cpp (260989 => 260990)


--- trunk/Source/WebKit/WebProcess/Plugins/Netscape/NPJSObject.cpp	2020-05-01 08:32:10 UTC (rev 260989)
+++ trunk/Source/WebKit/WebProcess/Plugins/Netscape/NPJSObject.cpp	2020-05-01 08:45:20 UTC (rev 260990)
@@ -157,7 +157,7 @@
     if (identifierRep->isString())
         result = m_jsObject->hasProperty(lexicalGlobalObject, identifierFromIdentifierRep(lexicalGlobalObject, identifierRep));
     else
-        result = m_jsObject->hasProperty(lexicalGlobalObject, identifierRep->number());
+        result = m_jsObject->hasProperty(lexicalGlobalObject, static_cast<uint32_t>(identifierRep->number()));
 
     scope.clearException();
     return result;
@@ -179,7 +179,7 @@
     if (identifierRep->isString())
         jsResult = m_jsObject->get(lexicalGlobalObject, identifierFromIdentifierRep(lexicalGlobalObject, identifierRep));
     else
-        jsResult = m_jsObject->get(lexicalGlobalObject, identifierRep->number());
+        jsResult = m_jsObject->get(lexicalGlobalObject, static_cast<uint32_t>(identifierRep->number()));
     
     m_objectMap->convertJSValueToNPVariant(lexicalGlobalObject, jsResult, *result);
     scope.clearException();
@@ -231,7 +231,7 @@
 
         JSCell::deleteProperty(m_jsObject.get(), lexicalGlobalObject, identifier);
     } else {
-        if (!m_jsObject->hasProperty(lexicalGlobalObject, identifierRep->number())) {
+        if (!m_jsObject->hasProperty(lexicalGlobalObject, static_cast<uint32_t>(identifierRep->number()))) {
             scope.clearException();
             return false;
         }
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to