Diff
Modified: trunk/JSTests/ChakraCore/test/Array/array_sort.baseline-jsc (267513 => 267514)
--- trunk/JSTests/ChakraCore/test/Array/array_sort.baseline-jsc 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/JSTests/ChakraCore/test/Array/array_sort.baseline-jsc 2020-09-24 02:46:41 UTC (rev 267514)
@@ -7,5 +7,5 @@
1,2,3
10
1,1.2,4,4.8,12
-TypeError: Array.prototype.sort requires the comparsion function be a function or undefined
+TypeError: Array.prototype.sort requires the comparator argument to be a function or undefined
1,2,3
Modified: trunk/JSTests/ChangeLog (267513 => 267514)
--- trunk/JSTests/ChangeLog 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/JSTests/ChangeLog 2020-09-24 02:46:41 UTC (rev 267514)
@@ -1,3 +1,26 @@
+2020-09-23 Alexey Shvayka <[email protected]>
+
+ Update Array.prototype.sort to be consistent with tightened spec
+ https://bugs.webkit.org/show_bug.cgi?id=202582
+
+ Reviewed by Yusuke Suzuki and Keith Miller.
+
+ Provided microbenchmarks test receivers that are half-sorted: 50% of their
+ items and item pairs (to accomodate merge sort) are at the right place.
+
+ Arrays of multiple sizes (8/24/64 items) are tested with both userland
+ and default comparator (to cover bucket sort).
+
+ * ChakraCore/test/Array/array_sort.baseline-jsc: Fix typo in error message.
+ * microbenchmarks/array-prototype-sort-large-array-comparator.js: Added.
+ * microbenchmarks/array-prototype-sort-large-array.js: Added.
+ * microbenchmarks/array-prototype-sort-medium-array-comparator.js: Added.
+ * microbenchmarks/array-prototype-sort-medium-array.js: Added.
+ * microbenchmarks/array-prototype-sort-small-array-comparator.js: Added.
+ * microbenchmarks/array-prototype-sort-small-array.js: Added.
+ * mozilla/js1_5/Array/regress-157652.js: Skip sorting sparse array of UINT_MAX size.
+ * stress/regress-188577.js: Replace sort() with unshift() and refactor.
+
2020-09-23 Yusuke Suzuki <[email protected]>
[JSC] Intl spec update: handle awkward rounding behavior
Added: trunk/JSTests/microbenchmarks/array-prototype-sort-large-array-comparator.js (0 => 267514)
--- trunk/JSTests/microbenchmarks/array-prototype-sort-large-array-comparator.js (rev 0)
+++ trunk/JSTests/microbenchmarks/array-prototype-sort-large-array-comparator.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,9 @@
+var comparator = (a, b) => a - b;
+
+for (var i = 0; i < 1e4; ++i) {
+ [
+ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,31,30,29,28,27,26,25,24,23,22,21,20,19,
+ 18,17,16,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,63,62,61,60,59,58,57,
+ 56,55,54,53,52,51,50,49,48
+ ].sort(comparator);
+}
Added: trunk/JSTests/microbenchmarks/array-prototype-sort-large-array.js (0 => 267514)
--- trunk/JSTests/microbenchmarks/array-prototype-sort-large-array.js (rev 0)
+++ trunk/JSTests/microbenchmarks/array-prototype-sort-large-array.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,7 @@
+for (var i = 0; i < 1e4; ++i) {
+ [
+ "0","1","2","3","4","5","6","7","8","9",":",";","<","=",">","?","O","N","M","L","K","J","I",
+ "H","G","F","E","D","C","B","A","@","P","Q","R","S","T","U","V","W","X","Y","Z","[","\\","]",
+ "^","_","o","n","m","l","k","j","i","h","g","f","e","d","c","b","a","`"
+ ].sort();
+}
Added: trunk/JSTests/microbenchmarks/array-prototype-sort-medium-array-comparator.js (0 => 267514)
--- trunk/JSTests/microbenchmarks/array-prototype-sort-medium-array-comparator.js (rev 0)
+++ trunk/JSTests/microbenchmarks/array-prototype-sort-medium-array-comparator.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,5 @@
+var comparator = (a, b) => a - b;
+
+for (var i = 0; i < 1e5; ++i) {
+ [0,1,2,3,4,5,11,10,9,8,7,6,12,13,14,15,16,17,23,22,21,20,19,18].sort(comparator);
+}
Added: trunk/JSTests/microbenchmarks/array-prototype-sort-medium-array.js (0 => 267514)
--- trunk/JSTests/microbenchmarks/array-prototype-sort-medium-array.js (rev 0)
+++ trunk/JSTests/microbenchmarks/array-prototype-sort-medium-array.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,3 @@
+for (var i = 0; i < 1e5; ++i) {
+ ["A","B","C","D","E","F","L","K","J","I","H","G","M","N","O","P","Q","R","X","W","V","U","T","S"].sort();
+}
Added: trunk/JSTests/microbenchmarks/array-prototype-sort-small-array-comparator.js (0 => 267514)
--- trunk/JSTests/microbenchmarks/array-prototype-sort-small-array-comparator.js (rev 0)
+++ trunk/JSTests/microbenchmarks/array-prototype-sort-small-array-comparator.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,5 @@
+var comparator = (a, b) => a - b;
+
+for (var i = 0; i < 1e5; ++i) {
+ [0,1,2,3,7,6,5,4].sort(comparator);
+}
Added: trunk/JSTests/microbenchmarks/array-prototype-sort-small-array.js (0 => 267514)
--- trunk/JSTests/microbenchmarks/array-prototype-sort-small-array.js (rev 0)
+++ trunk/JSTests/microbenchmarks/array-prototype-sort-small-array.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,3 @@
+for (var i = 0; i < 1e5; ++i) {
+ ["A","B","C","D","H","G","F","E"].sort();
+}
Modified: trunk/JSTests/mozilla/js1_5/Array/regress-157652.js (267513 => 267514)
--- trunk/JSTests/mozilla/js1_5/Array/regress-157652.js 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/JSTests/mozilla/js1_5/Array/regress-157652.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -117,9 +117,12 @@
printStatus(summary);
// JSC doesn't run out of memory, so we don't expect an abnormal exit code
-//expectExitCode(3);
-var IN_RHINO = inRhino();
+// expectExitCode(3);
+// As of https://webkit.org/b/202582, JSC copies internal spare array to a
+// temporary buffer like Rhino, SpiderMonkey, and V8.
+// var IN_RHINO = inRhino();
+var IN_RHINO = true;
if (!IN_RHINO)
{
var a1=Array(0xFFFFFFFF);
Modified: trunk/JSTests/stress/regress-188577.js (267513 => 267514)
--- trunk/JSTests/stress/regress-188577.js 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/JSTests/stress/regress-188577.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -2,16 +2,11 @@
var exception;
try {
- var i = 25000;
- var args = [];
- var v3;
- while (i--)
- args[i] = "a";
- var argsList = args.join();
- setter = Function(argsList, "");
- Object.defineProperty(args, '0', {set: setter});
- args.sort();
-
+ var args = new Array(25000).fill("a");
+ Object.defineProperty(args, "0", {
+ set: new Function(args.join(), ""),
+ });
+ args.unshift(1);
} catch (e) {
exception = e;
}
Modified: trunk/LayoutTests/ChangeLog (267513 => 267514)
--- trunk/LayoutTests/ChangeLog 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/LayoutTests/ChangeLog 2020-09-24 02:46:41 UTC (rev 267514)
@@ -1,3 +1,29 @@
+2020-09-23 Alexey Shvayka <[email protected]>
+
+ Update Array.prototype.sort to be consistent with tightened spec
+ https://bugs.webkit.org/show_bug.cgi?id=202582
+
+ Reviewed by Yusuke Suzuki and Keith Miller.
+
+ While adding new LayoutTests for JS-only features is undesirable, it's a
+ quick-and-dirty way to import the tests [1] and fix the call count/order
+ of observable operations via debug() and text expectations.
+
+ The tests are imported into LayoutTests/js/dom instead of LayoutTests/js for
+ run-_javascript_core-tests to ignore them as they require array-sort-harness.js.
+
+ These files will be removed shortly in favor of thorough test262 coverage,
+ which is required for the proposal [2] to be merged.
+
+ [1]: https://gist.github.com/szuend/05ae15b4e1329b264ab4c9a1cda09242
+ [2]: https://github.com/tc39/ecma262/pull/1585
+
+ * TestExpectations: Mark a test as slow.
+ * js/dom/array-sort-*-expected.txt: Added.
+ * js/dom/array-sort-*.html: Added.
+ * js/dom/script-tests/array-sort-*.js: Added.
+ * js/resources/array-sort-harness.js: Added.
+
2020-09-23 Yusuke Suzuki <[email protected]>
Unreviewed, we should put it under js/dom since it is not usable in JSC shell
Modified: trunk/LayoutTests/TestExpectations (267513 => 267514)
--- trunk/LayoutTests/TestExpectations 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/LayoutTests/TestExpectations 2020-09-24 02:46:41 UTC (rev 267514)
@@ -1810,6 +1810,7 @@
webkit.org/b/121452 [ Debug ] fast/frames/lots-of-iframes.html [ Slow ]
webkit.org/b/135053 [ Debug ] html5lib/webkit-resumer.html [ Slow ]
[ Debug ] js/dfg-double-vote-fuzz.html [ Slow ]
+[ Debug ] js/array-sort-small-sparse-array-with-large-length.html [ Slow ]
[ Debug ] js/dom/string-replacement-outofmemory.html [ Slow ]
[ Debug ] js/dfg-osr-entry-hoisted-clobbered-structure-check.html [ Slow ]
[ Debug ] editing/selection/move-by-character-brute-force.html [ Slow ]
Added: trunk/LayoutTests/js/dom/array-sort-accessor-adds-two-elements-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-adds-two-elements-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-adds-two-elements-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined,hole,foo,bar,foo,bar
+.sort():
+a,b,c,d,undefined,undefined,undefined,hole,foo,bar
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-adds-two-elements.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-adds-two-elements.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-adds-two-elements.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-decreases-length-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-decreases-length-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-decreases-length-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort():
+b,c,undefined,undefined
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-decreases-length.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-decreases-length.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-decreases-length.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-deletes-predecessor-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-deletes-predecessor-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-deletes-predecessor-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined,hole
+.sort():
+a,hole,c,d,undefined,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-deletes-predecessor.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-deletes-predecessor.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-deletes-predecessor.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-deletes-successor-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-deletes-successor-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-deletes-successor-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort():
+a,c,d,hole,undefined,undefined,hole,hole
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-deletes-successor.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-deletes-successor.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-deletes-successor.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-increases-length-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-increases-length-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-increases-length-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined,hole,hole,hole,hole,hole
+.sort():
+a,b,c,d,undefined,undefined,undefined,hole,hole,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-increases-length.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-increases-length.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-increases-length.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-removes-two-elements-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-removes-two-elements-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-removes-two-elements-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort():
+b,c,undefined,undefined
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-removes-two-elements.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-removes-two-elements.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-removes-two-elements.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-sets-predecessor-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-sets-predecessor-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-sets-predecessor-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined,hole
+.sort():
+a,foobar,c,d,undefined,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-sets-predecessor.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-sets-predecessor.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-sets-predecessor.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessor-sets-successor-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-sets-successor-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-sets-successor-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort():
+a,c,d,foobar,undefined,undefined,undefined,hole
+.sort(comparator):
+c,b,a,d,undefined,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessor-sets-successor.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessor-sets-successor.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessor-sets-successor.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessors-on-array-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessors-on-array-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessors-on-array-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,12 @@
+.sort(comparator):
+get [2]
+get [3]
+set [2] with d
+set [3] with undefined
+get [2]
+get [3]
+c,a,d,undefined,undefined,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessors-on-array.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessors-on-array.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessors-on-array.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-accessors-on-object-proto-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessors-on-object-proto-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessors-on-object-proto-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,8 @@
+.sort(comparator):
+get [2]
+set [2] with a
+c,b,hole,d,undefined,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-accessors-on-object-proto.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-accessors-on-object-proto.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-accessors-on-object-proto.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-non-configurable-element-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-configurable-element-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-configurable-element-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,5 @@
+PASS array.sort() threw exception TypeError: Unable to delete property..
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-non-configurable-element.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-configurable-element.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-configurable-element.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-non-configurable-proto-hole-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-configurable-proto-hole-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-configurable-proto-hole-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,6 @@
+.sort():
+a,b,c,d,foo,undefined,undefined,hole
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-non-configurable-proto-hole.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-configurable-proto-hole.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-configurable-proto-hole.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-non-writeable-element-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-writeable-element-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-writeable-element-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,5 @@
+PASS array.sort((a, b) => a - b) threw exception TypeError: Attempted to assign to readonly property..
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-non-writeable-element.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-writeable-element.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-writeable-element.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-non-writeable-proto-hole-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-writeable-proto-hole-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-writeable-proto-hole-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,5 @@
+PASS array.sort() threw exception TypeError: Attempted to assign to readonly property..
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-non-writeable-proto-hole.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-non-writeable-proto-hole.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-non-writeable-proto-hole.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,10 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-proxy-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-proxy-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-proxy-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,28 @@
+.sort():
+get ['length']
+has ['0']
+get ['0']
+has ['1']
+get ['1']
+has ['2']
+has ['3']
+get ['3']
+has ['4']
+get ['4']
+has ['5']
+has ['6']
+get ['6']
+has ['7']
+get ['7']
+set ['0'] = a
+set ['1'] = b
+set ['2'] = c
+set ['3'] = d
+set ['4'] = undefined
+set ['5'] = undefined
+delete ['6']
+delete ['7']
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-proxy-proto-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-proxy-proto-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-proxy-proto-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,9 @@
+.sort(comparator):
+has ['2']
+has ['5']
+set ['2'] = a
+set ['5'] = undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-proxy-proto.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-proxy-proto.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-proxy-proto.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-proxy.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-proxy.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-proxy.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/array-sort-short-arrays-expected.txt (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-short-arrays-expected.txt (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-short-arrays-expected.txt 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,12 @@
+.sort(comparator) 0-length array:
+get [0]
+undefined
+.sort() 1-length array:
+get [0]
+set [0] with bar
+get [0]
+bar,undefined
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
Added: trunk/LayoutTests/js/dom/array-sort-short-arrays.html (0 => 267514)
--- trunk/LayoutTests/js/dom/array-sort-short-arrays.html (rev 0)
+++ trunk/LayoutTests/js/dom/array-sort-short-arrays.html 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-adds-two-elements.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-adds-two-elements.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-adds-two-elements.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { array.push('foo'); array.push('bar'); return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { array.push('foo'); array.push('bar'); this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-decreases-length.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-decreases-length.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-decreases-length.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { array.length = array.length - 2; return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { array.length = array.length - 2; this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-deletes-predecessor.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-deletes-predecessor.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-deletes-predecessor.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { delete array[1]; return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { delete array[1]; this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-deletes-successor.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-deletes-successor.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-deletes-successor.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { delete array[3]; return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { delete array[3]; this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-increases-length.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-increases-length.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-increases-length.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { array.length = array.length + 2; return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { array.length = array.length + 2; this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-removes-two-elements.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-removes-two-elements.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-removes-two-elements.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { array.pop(); array.pop(); return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { array.pop(); array.pop(); this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-sets-predecessor.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-sets-predecessor.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-sets-predecessor.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { array[1] = 'foobar'; return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { array[1] = 'foobar'; this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-sets-successor.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-sets-successor.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessor-sets-successor.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,23 @@
+// author: Simon Zünd
+
+let array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { array[3] = 'foobar'; return this.foo; },
+ set(v) { this.foo = v; }
+});
+
+debug('.sort():');
+array.sort();
+log(array);
+
+array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { return this.foo; },
+ set(v) { array[3] = 'foobar'; this.foo = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessors-on-array.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessors-on-array.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessors-on-array.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,17 @@
+// author: Simon Zünd
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '2', {
+ get() { debug('get [2]'); return this.foo; },
+ set(v) { debug(`set [2] with ${v}`); this.foo = v; }
+});
+
+Object.defineProperty(array, '3', {
+ get() { debug('get [3]'); return this.bar; },
+ set(v) { debug(`set [3] with ${v}`); this.bar = v; }
+});
+
+debug('.sort(comparator):');
+array.sort((a, b) => a - b);
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-accessors-on-object-proto.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-accessors-on-object-proto.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-accessors-on-object-proto.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,21 @@
+// author: Simon Zünd
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+const object = {};
+
+Object.defineProperty(object, '2', {
+ get() { debug('get [2]'); return this.foo; },
+ set(v) { debug(`set [2] with ${v}`); this.foo = v; }
+});
+
+Object.defineProperty(object, '3', {
+ get() { debug('get [3]'); return this.bar; },
+ set(v) { debug(`set [3] with ${v}`); this.bar = v; }
+});
+
+array.__proto__ = object;
+
+debug('.sort(comparator):');
+Array.prototype.sort.call(array, (a, b) => a - b);
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-non-configurable-element.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-non-configurable-element.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-non-configurable-element.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,19 @@
+// author: Simon Zünd
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '6', {
+ value: 'a',
+ configurable: false,
+ enumerable: true,
+ writable: true,
+});
+
+Object.defineProperty(array, '7', {
+ value: 'd',
+ configurable: false,
+ enumerable: true,
+ writable: true,
+});
+
+shouldThrow('array.sort()', '"TypeError: Unable to delete property."');
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-non-configurable-proto-hole.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-non-configurable-proto-hole.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-non-configurable-proto-hole.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,14 @@
+// author: Simon Zünd
+
+Object.defineProperty(Object.prototype, '2', {
+ value: 'foo',
+ configurable: false,
+ enumerable: true,
+ writable: true,
+});
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+debug('.sort():');
+array.sort();
+log(array);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-non-writeable-element.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-non-writeable-element.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-non-writeable-element.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,19 @@
+// author: Simon Zünd
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+Object.defineProperty(array, '1', {
+ value: 'c',
+ configurable: true,
+ enumerable: true,
+ writable: false,
+});
+
+Object.defineProperty(array, '3', {
+ value: 'b',
+ configurable: true,
+ enumerable: true,
+ writable: false,
+});
+
+shouldThrow('array.sort((a, b) => a - b)', '"TypeError: Attempted to assign to readonly property."');
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-non-writeable-proto-hole.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-non-writeable-proto-hole.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-non-writeable-proto-hole.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,12 @@
+// author: Simon Zünd
+
+Object.defineProperty(Object.prototype, '2', {
+ value: 'foo',
+ configurable: true,
+ enumerable: true,
+ writable: false,
+});
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+shouldThrow('array.sort()', '"TypeError: Attempted to assign to readonly property."');
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-proxy-proto.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-proxy-proto.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-proxy-proto.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,31 @@
+// author: Simon Zünd
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+const proxy = new Proxy({}, {
+ get: (target, name) => {
+ debug("get ['" + name + "']");
+ return target[name];
+ },
+
+ set: (target, name, value) => {
+ debug("set ['" + name + "'] = " + value);
+ target[name] = value;
+ return true;
+ },
+
+ has: (target, name) => {
+ debug("has ['" + name + "']");
+ return name in target;
+ },
+
+ deleteProperty: (target, name) => {
+ debug("delete ['" + name + "']");
+ return delete target[name];
+ }
+});
+
+array.__proto__ = proxy;
+
+debug('.sort(comparator):');
+Array.prototype.sort.call(array, (a, b) => a - b);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-proxy.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-proxy.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-proxy.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,29 @@
+// author: Simon Zünd
+
+const array = [undefined, 'c', /*hole*/, 'b', undefined, /*hole*/, 'a', 'd'];
+
+const proxy = new Proxy(array, {
+ get: (target, name) => {
+ debug("get ['" + name + "']");
+ return target[name];
+ },
+
+ set: (target, name, value) => {
+ debug("set ['" + name + "'] = " + value);
+ target[name] = value;
+ return true;
+ },
+
+ has: (target, name) => {
+ debug("has ['" + name + "']");
+ return name in target;
+ },
+
+ deleteProperty: (target, name) => {
+ debug("delete ['" + name + "']");
+ return delete target[name];
+ }
+});
+
+debug('.sort():');
+Array.prototype.sort.call(proxy);
Added: trunk/LayoutTests/js/dom/script-tests/array-sort-short-arrays.js (0 => 267514)
--- trunk/LayoutTests/js/dom/script-tests/array-sort-short-arrays.js (rev 0)
+++ trunk/LayoutTests/js/dom/script-tests/array-sort-short-arrays.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,17 @@
+// author: Simon Zünd
+
+const array = [];
+
+Object.defineProperty(array, '0', {
+ get() { debug('get [0]'); return this.foo; },
+ set(v) { debug(`set [0] with ${v}`); this.foo = v; }
+});
+
+debug(".sort(comparator) 0-length array:");
+array.sort((a, b) => a - b);
+log(array);
+
+debug(".sort() 1-length array:");
+array.push('bar');
+array.sort();
+log(array);
Added: trunk/LayoutTests/js/resources/array-sort-harness.js (0 => 267514)
--- trunk/LayoutTests/js/resources/array-sort-harness.js (rev 0)
+++ trunk/LayoutTests/js/resources/array-sort-harness.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -0,0 +1,12 @@
+function log(array) {
+ let buf = '';
+ for (let index = 0; index < array.length; index++) {
+ if (array.hasOwnProperty(index)) {
+ buf += String(array[index]);
+ } else {
+ buf += 'hole';
+ }
+ if (index < array.length - 1) buf += ',';
+ }
+ debug(buf);
+}
Modified: trunk/Source/_javascript_Core/ChangeLog (267513 => 267514)
--- trunk/Source/_javascript_Core/ChangeLog 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/Source/_javascript_Core/ChangeLog 2020-09-24 02:46:41 UTC (rev 267514)
@@ -1,3 +1,62 @@
+2020-09-23 Alexey Shvayka <[email protected]>
+
+ Update Array.prototype.sort to be consistent with tightened spec
+ https://bugs.webkit.org/show_bug.cgi?id=202582
+
+ Reviewed by Yusuke Suzuki and Keith Miller.
+
+ This patch implements the spec change [1] that reduces amount of cases resulting
+ in an implementation-defined sort order, aligning JSC with V8 and SpiderMonkey.
+
+ To achieve this, we collect all existing non-undefined receiver elements to a
+ temporary array, sort it, and write back sorted items, followed by `undefined`
+ values and holes.
+
+ This change is proven to be web-compatible (shipping since Chrome 76) and neutral
+ on peak memory consumption in the wild.
+
+ Although we can unobservably detect sparse receivers, we can't avoid creating a
+ temporary array for common case since userland comparators may throw; string
+ sorting won't measurably benefit from this, only increasing code complexity.
+
+ This change uses @putByValDirect unless the spec requires [[Set]], avoids using
+ closure variables, and adds a few drive-by optimizations, resulting in ~22%
+ faster string sorting and 13% speed-up for userland comparators.
+ Dromaeo/jslib is neutral.
+
+ [1]: https://github.com/tc39/ecma262/pull/1585
+
+ * builtins/ArrayPrototype.js:
+ (sort.stringComparator):
+ Optimization #1: replace char-by-char comparison loop with > operator, aligning
+ JSC with V8 and SpiderMonkey. This semantically equivalent change alone is a ~15%
+ progression for string sort.
+
+ (sort.compact):
+ (sort.commit):
+ Optimization #2: copy large non-numeric arrays in a loop rather than @appendMemcpy.
+ Using the latter unconditionally regresses provided microbenchmarks.
+
+ (sort.merge):
+ Optimization #3: replace `typeof` check and negation with strict equality.
+
+ (sort.mergeSort):
+ Optimization #4: always return sorted array instead of copying, even if it's the buffer.
+ Tweak: create the buffer with correct length.
+
+ (sort.bucketSort):
+ Optimization #5: avoid emitting 2 extra get_by_val ops by saving bucket lookup to a variable.
+ Tweak: create new bucket via array literal.
+
+ (sort): Fix typo in error message.
+ (sort.compactSparse): Deleted.
+ (sort.compactSlow): Deleted.
+ (sort.comparatorSort): Deleted.
+ (sort.stringSort): Deleted.
+ * runtime/ObjectConstructor.cpp:
+ (JSC::ObjectConstructor::finishCreation):
+ Remove @Object.@getPrototypeOf as it's now unused and we have @getPrototypeOf intrinsic anyway.
+
2020-09-23 Yusuke Suzuki <[email protected]>
[JSC] Intl spec update: handle awkward rounding behavior
Modified: trunk/Source/_javascript_Core/builtins/ArrayPrototype.js (267513 => 267514)
--- trunk/Source/_javascript_Core/builtins/ArrayPrototype.js 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/Source/_javascript_Core/builtins/ArrayPrototype.js 2020-09-24 02:46:41 UTC (rev 267514)
@@ -320,107 +320,56 @@
var aString = a.string;
var bString = b.string;
- var aLength = aString.length;
- var bLength = bString.length;
- var length = min(aLength, bLength);
+ if (aString === bString)
+ return 0;
- for (var i = 0; i < length; ++i) {
- var aCharCode = aString.@charCodeAt(i);
- var bCharCode = bString.@charCodeAt(i);
-
- if (aCharCode == bCharCode)
- continue;
-
- return aCharCode - bCharCode;
- }
-
- return aLength - bLength;
+ return aString > bString ? 1 : -1;
}
- // Move undefineds and holes to the end of a sparse array. Result is [values..., undefineds..., holes...].
- function compactSparse(array, dst, src, length)
+ function compact(receiver, receiverLength, compacted, isStringSort)
{
- var values = [ ];
- var seen = { };
- var valueCount = 0;
var undefinedCount = 0;
+ var compactedIndex = 0;
- // Clean up after the in-progress non-sparse compaction that failed.
- for (var i = dst; i < src; ++i)
- delete array[i];
-
- for (var object = array; object; object = @Object.@getPrototypeOf(object)) {
- var propertyNames = @Object.@getOwnPropertyNames(object);
- for (var i = 0; i < propertyNames.length; ++i) {
- var index = propertyNames[i];
- if (index < length) { // Exclude non-numeric properties and properties past length.
- if (seen[index]) // Exclude duplicates.
- continue;
- seen[index] = 1;
-
- var value = array[index];
- delete array[index];
-
- if (value === @undefined) {
- ++undefinedCount;
- continue;
- }
-
- array[valueCount++] = value;
+ for (var i = 0; i < receiverLength; ++i) {
+ if (i in receiver) {
+ var value = receiver[i];
+ if (value === @undefined)
+ ++undefinedCount;
+ else {
+ @putByValDirect(compacted, compactedIndex,
+ isStringSort ? {string: @toString(value), value} : value);
+ ++compactedIndex;
}
}
}
- for (var i = valueCount; i < valueCount + undefinedCount; ++i)
- array[i] = @undefined;
-
- return valueCount;
+ return undefinedCount;
}
- function compactSlow(array, length)
+ // Move undefineds and holes to the end of an array. Result is [values..., undefineds..., holes...].
+ function commit(receiver, receiverLength, sorted, undefinedCount)
{
- var holeCount = 0;
+ @assert(@isJSArray(sorted));
+ var sortedLength = sorted.length;
+ @assert(sortedLength + undefinedCount <= receiverLength);
- var dst = 0;
- var src = ""
- for (; src < length; ++src) {
- if (!(src in array)) {
- ++holeCount;
- if (holeCount < 256)
- continue;
- return compactSparse(array, dst, src, length);
- }
-
- var value = array[src];
- if (value === @undefined)
- continue;
-
- array[dst++] = value;
+ var i = 0;
+ if (@isJSArray(receiver) && sortedLength >= 64 && typeof sorted[0] !== "number") { // heuristic
+ @appendMemcpy(receiver, sorted, 0);
+ i = sortedLength;
+ } else {
+ for (; i < sortedLength; ++i)
+ receiver[i] = sorted[i];
}
- var valueCount = dst;
- var undefinedCount = length - valueCount - holeCount;
+ for (; i < sortedLength + undefinedCount; ++i)
+ receiver[i] = @undefined;
- for (var i = valueCount; i < valueCount + undefinedCount; ++i)
- array[i] = @undefined;
-
- for (var i = valueCount + undefinedCount; i < length; ++i)
- delete array[i];
-
- return valueCount;
+ for (; i < receiverLength; ++i)
+ delete receiver[i];
}
- // Move undefineds and holes to the end of an array. Result is [values..., undefineds..., holes...].
- function compact(array, length)
- {
- for (var i = 0; i < array.length; ++i) {
- if (array[i] === @undefined)
- return compactSlow(array, length);
- }
-
- return length;
- }
-
function merge(dst, src, srcIndex, srcEnd, width, comparator)
{
var left = srcIndex;
@@ -431,26 +380,30 @@
for (var dstIndex = left; dstIndex < rightEnd; ++dstIndex) {
if (right < rightEnd) {
if (left >= leftEnd) {
- dst[dstIndex] = src[right++];
+ @putByValDirect(dst, dstIndex, src[right]);
+ ++right;
continue;
}
+ // See https://bugs.webkit.org/show_bug.cgi?id=47825 on boolean special-casing
var comparisonResult = comparator(src[right], src[left]);
- if ((typeof comparisonResult === "boolean" && !comparisonResult) || comparisonResult < 0) {
- dst[dstIndex] = src[right++];
+ if (comparisonResult === false || comparisonResult < 0) {
+ @putByValDirect(dst, dstIndex, src[right]);
+ ++right;
continue;
}
}
- dst[dstIndex] = src[left++];
+ @putByValDirect(dst, dstIndex, src[left]);
+ ++left;
}
}
- function mergeSort(array, valueCount, comparator)
+ function mergeSort(array, comparator)
{
- var buffer = [ ];
- buffer.length = valueCount;
+ var valueCount = array.length;
+ var buffer = @newArrayWithSize(valueCount);
var dst = buffer;
var src = ""
@@ -463,18 +416,17 @@
dst = tmp;
}
- if (src != array) {
- for(var i = 0; i < valueCount; i++)
- array[i] = src[i];
- }
+ return src;
}
function bucketSort(array, dst, bucket, depth)
{
if (bucket.length < 32 || depth > 32) {
- mergeSort(bucket, bucket.length, stringComparator);
- for (var i = 0; i < bucket.length; ++i)
- array[dst++] = bucket[i].value;
+ var sorted = mergeSort(bucket, stringComparator);
+ for (var i = 0; i < sorted.length; ++i) {
+ @putByValDirect(array, dst, sorted[i].value);
+ ++dst;
+ }
return dst;
}
@@ -483,14 +435,17 @@
var entry = bucket[i];
var string = entry.string;
if (string.length == depth) {
- array[dst++] = entry.value;
+ @putByValDirect(array, dst, entry.value);
+ ++dst;
continue;
}
var c = string.@charCodeAt(depth);
- if (!buckets[c])
- buckets[c] = [ ];
- buckets[c][buckets[c].length] = entry;
+ var cBucket = buckets[c];
+ if (cBucket)
+ @putByValDirect(cBucket, cBucket.length, entry);
+ else
+ @putByValDirect(buckets, c, [ entry ]);
}
for (var i = 0; i < buckets.length; ++i) {
@@ -502,42 +457,32 @@
return dst;
}
- function comparatorSort(array, length, comparator)
- {
- var valueCount = compact(array, length);
- mergeSort(array, valueCount, comparator);
- }
+ var isStringSort = false;
+ if (comparator === @undefined)
+ isStringSort = true;
+ else if (!@isCallable(comparator))
+ @throwTypeError("Array.prototype.sort requires the comparator argument to be a function or undefined");
- function stringSort(array, length)
- {
- var valueCount = compact(array, length);
+ var receiver = @toObject(this, "Array.prototype.sort requires that |this| not be null or undefined");
+ var receiverLength = @toLength(receiver.length);
- var strings = @newArrayWithSize(valueCount);
- for (var i = 0; i < valueCount; ++i)
- strings[i] = { string: @toString(array[i]), value: array[i] };
+ // For compatibility with Firefox and Chrome, do nothing observable
+ // to the target array if it has 0 or 1 sortable properties.
+ if (receiverLength < 2)
+ return receiver;
- bucketSort(array, 0, strings, 0);
- }
+ var compacted = [ ];
+ var sorted = null;
+ var undefinedCount = compact(receiver, receiverLength, compacted, isStringSort);
- var sortFunction;
- if (@isCallable(comparator))
- sortFunction = comparatorSort;
- else if (comparator === @undefined)
- sortFunction = stringSort;
- else
- @throwTypeError("Array.prototype.sort requires the comparsion function be a function or undefined");
+ if (isStringSort) {
+ sorted = @newArrayWithSize(compacted.length);
+ bucketSort(sorted, 0, compacted, 0);
+ } else
+ sorted = mergeSort(compacted, comparator);
- var array = @toObject(this, "Array.prototype.sort requires that |this| not be null or undefined");
-
- var length = @toLength(array.length);
-
- // For compatibility with Firefox and Chrome, do nothing observable
- // to the target array if it has 0 or 1 sortable properties.
- if (length < 2)
- return array;
-
- sortFunction(array, length, comparator);
- return array;
+ commit(receiver, receiverLength, sorted, undefinedCount);
+ return receiver;
}
@globalPrivate
Modified: trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp (267513 => 267514)
--- trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2020-09-24 02:34:03 UTC (rev 267513)
+++ trunk/Source/_javascript_Core/runtime/ObjectConstructor.cpp 2020-09-24 02:46:41 UTC (rev 267514)
@@ -99,7 +99,6 @@
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().createPrivateName(), objectConstructorCreate, static_cast<unsigned>(PropertyAttribute::DontEnum), 2);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().definePropertyPrivateName(), objectConstructorDefineProperty, static_cast<unsigned>(PropertyAttribute::DontEnum), 3);
- JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getPrototypeOfPrivateName(), objectConstructorGetPrototypeOf, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
JSC_NATIVE_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->builtinNames().getOwnPropertyNamesPrivateName(), objectConstructorGetOwnPropertyNames, static_cast<unsigned>(PropertyAttribute::DontEnum), 1);
}