Skip to content

Commit 6d2a452

Browse files
committed
Array.prototype methods must use ToLength
https://bugs.webkit.org/show_bug.cgi?id=144128 Reviewed by Oliver Hunt. Source/JavaScriptCore: Per https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength This patch introduces ToLength and ToInteger JS implementation to encourage the DFG/FTL's inlining. These implementations are located in GlobalObject.js. And set to the JSGlobalObject with the private symbols @ToLength and @ToInteger manually. * builtins/Array.prototype.js: (every): (forEach): (filter): (map): (some): (fill): (find): (findIndex): (includes): * builtins/ArrayConstructor.js: (from): * builtins/GlobalObject.js: Copied from Source/JavaScriptCore/builtins/StringConstructor.js. (ToInteger): (ToLength): * builtins/StringConstructor.js: (raw): * runtime/JSGlobalObject.cpp: (JSC::JSGlobalObject::init): * runtime/JSGlobalObjectFunctions.h: LayoutTests: * fast/profiler/built-in-function-calls-anonymous-expected.txt: * fast/profiler/built-in-function-calls-user-defined-function-expected.txt: * js/array-every-expected.txt: * js/array-fill-expected.txt: * js/array-filter-expected.txt: * js/array-find-expected.txt: * js/array-findIndex-expected.txt: * js/array-functions-non-arrays-expected.txt: * js/array-includes-expected.txt: * js/script-tests/array-every.js: (throwError): * js/script-tests/array-fill.js: (throwError): * js/script-tests/array-filter.js: (throwError): * js/script-tests/array-find.js: (throwError): * js/script-tests/array-findIndex.js: (toObject): (throwError): * js/script-tests/array-functions-non-arrays.js: (throwError): * js/script-tests/array-includes.js: Canonical link: https://commits.webkit.org/163178@main git-svn-id: https://svn.webkit.org/repository/webkit/trunk@184582 268f45cc-cd09-0410-ab3c-d52691b4dbfc
1 parent c6278dd commit 6d2a452

24 files changed

Lines changed: 302 additions & 63 deletions

LayoutTests/ChangeLog

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,36 @@
1+
2015-05-19 Yusuke Suzuki <utatane.tea@gmail.com>
2+
3+
Array.prototype methods must use ToLength
4+
https://bugs.webkit.org/show_bug.cgi?id=144128
5+
6+
Reviewed by Oliver Hunt.
7+
8+
Patch by Jordan Harband <ljharb@gmail.com> and Yusuke Suzuki <utatane.tea@gmail.com>
9+
10+
* fast/profiler/built-in-function-calls-anonymous-expected.txt:
11+
* fast/profiler/built-in-function-calls-user-defined-function-expected.txt:
12+
* js/array-every-expected.txt:
13+
* js/array-fill-expected.txt:
14+
* js/array-filter-expected.txt:
15+
* js/array-find-expected.txt:
16+
* js/array-findIndex-expected.txt:
17+
* js/array-functions-non-arrays-expected.txt:
18+
* js/array-includes-expected.txt:
19+
* js/script-tests/array-every.js:
20+
(throwError):
21+
* js/script-tests/array-fill.js:
22+
(throwError):
23+
* js/script-tests/array-filter.js:
24+
(throwError):
25+
* js/script-tests/array-find.js:
26+
(throwError):
27+
* js/script-tests/array-findIndex.js:
28+
(toObject):
29+
(throwError):
30+
* js/script-tests/array-functions-non-arrays.js:
31+
(throwError):
32+
* js/script-tests/array-includes.js:
33+
134
2015-05-19 Zalan Bujtas <zalan@apple.com>
235

336
Merged anonymous blocks should invalidate simple line layout path.

LayoutTests/fast/profiler/built-in-function-calls-anonymous-expected.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Thread_1 (no file) (line 0:0)
88
Array (no file) (line 0:0)
99
map (no file) (line 0:0)
1010
Object (no file) (line 0:0)
11+
ToLength (no file) (line 0:0)
12+
ToInteger (no file) (line 0:0)
13+
Number (no file) (line 0:0)
14+
(anonymous function) (no file) (line 0:0)
1115
myFunction built-in-function-calls-anonymous.html (line 14:45)
1216
arrayOperatorFunction profiler-test-JS-resources.js (line 25:46)
1317
endTest profiler-test-JS-resources.js (line 1:20)

LayoutTests/fast/profiler/built-in-function-calls-user-defined-function-expected.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ Thread_1 (no file) (line 0:0)
88
Array (no file) (line 0:0)
99
map (no file) (line 0:0)
1010
Object (no file) (line 0:0)
11+
ToLength (no file) (line 0:0)
12+
ToInteger (no file) (line 0:0)
13+
Number (no file) (line 0:0)
14+
(anonymous function) (no file) (line 0:0)
1115
arrayOperatorFunction profiler-test-JS-resources.js (line 25:46)
1216
endTest profiler-test-JS-resources.js (line 1:20)
1317

LayoutTests/js/array-every-expected.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ This test checks the behavior of the every() method on Array objects.
33
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
44

55

6+
PASS Array.prototype.every.length is 1
7+
PASS Array.prototype.every.name is 'every'
8+
69
1.0 Single Argument Testing
710
PASS [12, 5, 8, 130, 44].every(isBigEnough) is false
811
PASS [12, 54, 18, 130, 44].every(isBigEnough) is true
@@ -46,6 +49,12 @@ PASS accumulator.toString() is [12, 54, 18, 130, 44].toString()
4649
7.0 Behavior for Holes in Arrays
4750
PASS arr.every(isNotUndefined) is true
4851
PASS arr.every(isNotUndefined) is true
52+
53+
8.0 Array-like object with invalid lengths
54+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.every.call(obj, throwError) is true
55+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.every.call(obj, throwError) is true
56+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.every.call(obj, throwError) is true
57+
4958
PASS successfullyParsed is true
5059

5160
TEST COMPLETE

LayoutTests/js/array-fill-expected.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ This test checks the behavior of the Array.prototype.fill()
33
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
44

55

6+
PASS Array.prototype.fill.length is 1
7+
PASS Array.prototype.fill.name is 'fill'
68
PASS [0, 0, 0, 0, 0].fill() is [undefined, undefined, undefined, undefined, undefined]
79
PASS [0, 0, 0, 0, 0].fill(3) is [3, 3, 3, 3, 3]
810
PASS [0, 0, 0, 0, 0].fill(3, 1) is [0, 3, 3, 3, 3]
@@ -14,6 +16,10 @@ PASS [0, 0, 0, 0, 0].fill(3, -2, -1) is [0, 0, 0, 3, 0]
1416
PASS [0, 0, 0, 0, 0].fill(3, -2, -3) is [0, 0, 0, 0, 0]
1517
PASS [0, 0, 0, 0, 0].fill(3, undefined, 4) is [3, 3, 3, 3, 0]
1618
PASS [ , , , , 0].fill(3, 1, 3) is [, 3, 3, , 0]
19+
Array-like object with invalid lengths
20+
PASS var obj = Object.freeze({ 0: 1, length: 0 }); Array.prototype.fill.call(obj, throwError); JSON.stringify(obj) is '{"0":1,"length":0}'
21+
PASS var obj = Object.freeze({ 0: 1, length: -0 }); Array.prototype.fill.call(obj, throwError); JSON.stringify(obj) is '{"0":1,"length":0}'
22+
PASS var obj = Object.freeze({ 0: 1, length: -3 }); Array.prototype.fill.call(obj, throwError); JSON.stringify(obj) is '{"0":1,"length":-3}'
1723
PASS successfullyParsed is true
1824

1925
TEST COMPLETE

LayoutTests/js/array-filter-expected.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,30 @@ Tests for Array.prototype.filter
33
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
44

55

6+
PASS Array.prototype.filter.length is 1
7+
PASS Array.prototype.filter.name is 'filter'
68
PASS [undefined].filter(passUndefined) is [undefined]
79
PASS (new Array(20)).filter(passUndefined) is []
810
PASS [0,1,2,3,4,5,6,7,8,9].filter(passEven) is [0,2,4,6,8]
911
PASS [0,1,2,3,4,5,6,7,8,9].filter(passAfter5) is [5,6,7,8,9]
1012
PASS mixPartialAndFast.filter(passAfter5) is [5,6,7,8,9,sparseArrayLength-1]
13+
Generic Object
1114
PASS toObject([undefined]).filter(passUndefined) is [undefined]
1215
PASS toObject(new Array(20)).filter(passUndefined) is []
1316
PASS toObject([0,1,2,3,4,5,6,7,8,9]).filter(passEven) is [0,2,4,6,8]
1417
PASS toObject([0,1,2,3,4,5,6,7,8,9]).filter(passAfter5) is [5,6,7,8,9]
1518
PASS toObject(mixPartialAndFast).filter(passAfter5) is [5,6,7,8,9,sparseArrayLength-1]
19+
Array-like object with invalid lengths
20+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.filter.call(obj, throwError) is []
21+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.filter.call(obj, throwError) is []
22+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.filter.call(obj, throwError) is []
23+
Reversed generic Object
1624
PASS reverseInsertionOrder([undefined]).filter(passUndefined) is [undefined]
1725
PASS reverseInsertionOrder(new Array(20)).filter(passUndefined) is []
1826
PASS reverseInsertionOrder([0,1,2,3,4,5,6,7,8,9]).filter(passEven) is [0,2,4,6,8]
1927
PASS reverseInsertionOrder([0,1,2,3,4,5,6,7,8,9]).filter(passAfter5) is [5,6,7,8,9]
2028
PASS reverseInsertionOrder(mixPartialAndFast).filter(passAfter5) is [5,6,7,8,9,sparseArrayLength-1]
29+
Log evaluation order
2130
,0,[object Object]
2231
PASS reverseInsertionOrder([undefined]).filter(filterLog(passUndefined)) is [undefined]
2332
PASS reverseInsertionOrder(new Array(20)).filter(filterLog(passUndefined)) is []

LayoutTests/js/array-find-expected.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Tests for Array.prototype.find
33
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
44

55

6+
PASS Array.prototype.find.length is 1
7+
PASS Array.prototype.find.name is 'find'
68
PASS [undefined, 0, null, false, ''].find(passUndefined) is undefined
79
PASS [undefined, 0, null, false, ''].find(passZero) is 0
810
PASS [undefined, 0, null, false, ''].find(passNull) is null
@@ -14,11 +16,13 @@ PASS [undefined, 0, null, ''].find(passFalse) is undefined
1416
PASS [undefined, 0, null, false].find(passEmptyString) is undefined
1517
PASS [undefined, null, false, ''].find(passZero) is undefined
1618
PASS (new Array(20)).find(passUndefined) is undefined
19+
Array with holes
1720
PASS arrayWithHoles.find(passUndefined) is undefined
1821
PASS arrayWithHoles.find(passZero) is 0
1922
PASS arrayWithHoles.find(passNull) is null
2023
PASS arrayWithHoles.find(passFalse) is false
2124
PASS arrayWithHoles.find(passEmptyString) is ''
25+
Generic Object
2226
PASS toObject([undefined, 0, null, false, '']).find(passUndefined) is undefined
2327
PASS toObject([undefined, 0, null, false, '']).find(passZero) is 0
2428
PASS toObject([undefined, 0, null, false, '']).find(passNull) is null
@@ -30,8 +34,14 @@ PASS toObject([undefined, 0, null, '']).find(passFalse) is undefined
3034
PASS toObject([undefined, 0, null, false]).find(passEmptyString) is undefined
3135
PASS toObject([undefined, null, false, '']).find(passZero) is undefined
3236
PASS toObject(new Array(20)).find(passUndefined) is undefined
37+
Array-like object with invalid lengths
38+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.find.call(obj, throwError) is undefined.
39+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.find.call(obj, throwError) is undefined.
40+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.find.call(obj, throwError) is undefined.
41+
Modification during search
3342
PASS [0,1,2,3,4,5,6,7,8,9].find(findItemAddedDuringSearch) is undefined
3443
PASS [0,1,2,3,4,5,6,7,8,9].find(findItemRemovedDuringSearch) is undefined
44+
Exceptions
3545
PASS Array.prototype.find.call(undefined, function() {}) threw exception TypeError: Array.prototype.find requires that |this| not be undefined.
3646
PASS Array.prototype.find.call(null, function() {}) threw exception TypeError: Array.prototype.find requires that |this| not be null.
3747
PASS [].find(1) threw exception TypeError: Array.prototype.find callback must be a function.
@@ -40,6 +50,7 @@ PASS [].find([]) threw exception TypeError: Array.prototype.find callback must b
4050
PASS [].find({}) threw exception TypeError: Array.prototype.find callback must be a function.
4151
PASS [].find(null) threw exception TypeError: Array.prototype.find callback must be a function.
4252
PASS [].find(undefined) threw exception TypeError: Array.prototype.find callback must be a function.
53+
Callbacks in the expected order and skipping holes
4354
find callback called with index 10
4455
find callback called with index 20
4556
find callback called with index 30

LayoutTests/js/array-findIndex-expected.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ Tests for Array.prototype.findIndex
33
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
44

55

6+
PASS Array.prototype.findIndex.length is 1
7+
PASS Array.prototype.findIndex.name is 'findIndex'
68
PASS [undefined, 0, null, false, ''].findIndex(passUndefined) is 0
79
PASS [undefined, 0, null, false, ''].findIndex(passZero) is 1
810
PASS [undefined, 0, null, false, ''].findIndex(passNull) is 2
@@ -14,12 +16,14 @@ PASS [undefined, 0, null, ''].findIndex(passFalse) is -1
1416
PASS [undefined, 0, null, false].findIndex(passEmptyString) is -1
1517
PASS [undefined, null, false, ''].findIndex(passZero) is -1
1618
PASS (new Array(20)).findIndex(passUndefined) is -1
19+
Array with holes
1720
PASS arrayWithHoles.findIndex(passUndefined) is -1
1821
PASS arrayWithHoles.findIndex(passZero) is 10
1922
PASS arrayWithHoles.findIndex(passNull) is 20
2023
PASS arrayWithHoles.findIndex(passFalse) is 30
2124
PASS arrayWithHoles.findIndex(passEmptyString) is 40
2225
PASS arrayWithHoles.findIndex(passUndefined) is 50
26+
Generic Object
2327
PASS toObject([undefined, 0, null, false, '']).findIndex(passUndefined) is 0
2428
PASS toObject([undefined, 0, null, false, '']).findIndex(passZero) is 1
2529
PASS toObject([undefined, 0, null, false, '']).findIndex(passNull) is 2
@@ -31,8 +35,14 @@ PASS toObject([undefined, 0, null, '']).findIndex(passFalse) is -1
3135
PASS toObject([undefined, 0, null, false]).findIndex(passEmptyString) is -1
3236
PASS toObject([undefined, null, false, '']).findIndex(passZero) is -1
3337
PASS toObject(new Array(20)).findIndex(passUndefined) is -1
38+
Array-like object with invalid lengths
39+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.findIndex.call(obj, throwError) is -1
40+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.findIndex.call(obj, throwError) is -1
41+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.findIndex.call(obj, throwError) is -1
42+
Modification during search
3443
PASS [0,1,2,3,4,5,6,7,8,9].findIndex(findItemAddedDuringSearch) is -1
3544
PASS [0,1,2,3,4,5,6,7,8,9].findIndex(findItemRemovedDuringSearch) is -1
45+
Exceptions
3646
PASS Array.prototype.findIndex.call(undefined, function() {}) threw exception TypeError: Array.prototype.findIndex requires that |this| not be undefined.
3747
PASS Array.prototype.findIndex.call(null, function() {}) threw exception TypeError: Array.prototype.findIndex requires that |this| not be null.
3848
PASS [].findIndex(1) threw exception TypeError: Array.prototype.findIndex callback must be a function.
@@ -41,6 +51,7 @@ PASS [].findIndex([]) threw exception TypeError: Array.prototype.findIndex callb
4151
PASS [].findIndex({}) threw exception TypeError: Array.prototype.findIndex callback must be a function.
4252
PASS [].findIndex(null) threw exception TypeError: Array.prototype.findIndex callback must be a function.
4353
PASS [].findIndex(undefined) threw exception TypeError: Array.prototype.findIndex callback must be a function.
54+
Callbacks in the expected order and skipping holes
4455
find callback called with index 10
4556
find callback called with index 20
4657
find callback called with index 30

LayoutTests/js/array-functions-non-arrays-expected.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,16 @@ PASS Array.prototype.unshift.call(x = {}, 'c'); properties(x) is '0:c, length:1'
9393
PASS Array.prototype.unshift.call(x = ['b', 'a'], 'c'); properties(x) is '0:c, 1:b, 2:a, length:3(DontDelete, DontEnum)'
9494
PASS Array.prototype.unshift.call(x = { length:2, 0:'b', 1:'a' }, 'c'); properties(x) is '0:c, 1:b, 2:a, length:3'
9595
PASS Array.prototype.unshift.call(x = new TwoItemConstructor, 'c'); properties(x) is '0:c, 1:b, 2:a, length:3'
96+
Array-like object with invalid lengths
97+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.forEach.call(obj, throwError) is undefined.
98+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.forEach.call(obj, throwError) is undefined.
99+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.forEach.call(obj, throwError) is undefined.
100+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.map.call(obj, throwError) is []
101+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.map.call(obj, throwError) is []
102+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.map.call(obj, throwError) is []
103+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: 0 }; Array.prototype.some.call(obj, throwError) is false
104+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -0 }; Array.prototype.some.call(obj, throwError) is false
105+
PASS var obj = { 0: 1, 1: 2, 2: 3, length: -3 }; Array.prototype.some.call(obj, throwError) is false
96106
PASS successfullyParsed is true
97107

98108
TEST COMPLETE

LayoutTests/js/array-includes-expected.txt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ Tests for Array.prototype.includes
33
On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
44

55

6-
PASS [].includes.length is 1
6+
PASS Array.prototype.includes.length is 1
7+
PASS Array.prototype.includes.name is 'includes'
78
PASS [1, 2, 3].includes(2) is true
89
PASS [1, 2, 3].includes(4) is false
910
PASS [].includes(1) is false
@@ -22,13 +23,17 @@ PASS [1, 2, 3].includes(1, -3) is true
2223
PASS [1, 2, NaN, 4].includes(NaN) is true
2324
PASS ['egg', 'bacon', 'sausage'].includes('egg') is true
2425
PASS ['egg', 'bacon', 'sausage'].includes('spinach') is false
25-
Array with holes
26+
Array with holes (sparse array)
2627
PASS a.includes('egg') is true
2728
PASS a.includes('sausage') is true
2829
PASS a.includes('hashbrown') is false
2930
PASS a.includes('toast') is false
3031
PASS Array.prototype.includes.call(undefined, 1) threw exception TypeError: Array.prototype.includes requires that |this| not be undefined.
3132
PASS Array.prototype.includes.call(null, 1) threw exception TypeError: Array.prototype.includes requires that |this| not be null.
33+
Array-like object with invalid lengths
34+
PASS var obj = { 0: 1, 1: 1, 2: 1, length: 0 }; Array.prototype.includes.call(obj, 1) is false
35+
PASS var obj = { 0: 1, 1: 1, 2: 1, length: -0 }; Array.prototype.includes.call(obj, 1) is false
36+
PASS var obj = { 0: 1, 1: 1, 2: 1, length: -3 }; Array.prototype.includes.call(obj, 1) is false
3237
PASS successfullyParsed is true
3338

3439
TEST COMPLETE

0 commit comments

Comments
 (0)