[ES6] Implement Array.prototype.values
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 12 Apr 2015 09:50:40 +0000 (09:50 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sun, 12 Apr 2015 09:50:40 +0000 (09:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=143633

Reviewed by Darin Adler.

Source/JavaScriptCore:

Symbol.unscopables is implemented, so we can implement Array.prototype.values
without largely breaking the web. The following script passes.

var array = [];
var values = 42;
with (array) {
    assert(values, 42);
}

* runtime/ArrayPrototype.cpp:
* tests/stress/array-iterators-next.js:
* tests/stress/map-iterators-next.js:
* tests/stress/set-iterators-next.js:
* tests/stress/values-unscopables.js: Added.
(test):

LayoutTests:

* js/Object-getOwnPropertyNames-expected.txt:
* js/array-iterators-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:
* js/script-tests/array-iterators.js:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@182668 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/js/Object-getOwnPropertyNames-expected.txt
LayoutTests/js/array-iterators-expected.txt
LayoutTests/js/script-tests/Object-getOwnPropertyNames.js
LayoutTests/js/script-tests/array-iterators.js
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/runtime/ArrayPrototype.cpp
Source/JavaScriptCore/tests/stress/array-iterators-next.js
Source/JavaScriptCore/tests/stress/map-iterators-next.js
Source/JavaScriptCore/tests/stress/set-iterators-next.js
Source/JavaScriptCore/tests/stress/values-unscopables.js [new file with mode: 0644]

index 18b4fca..e1ebbb1 100644 (file)
@@ -1,3 +1,15 @@
+2015-04-12  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement Array.prototype.values
+        https://bugs.webkit.org/show_bug.cgi?id=143633
+
+        Reviewed by Darin Adler.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/array-iterators-expected.txt:
+        * js/script-tests/Object-getOwnPropertyNames.js:
+        * js/script-tests/array-iterators.js:
+
 2015-04-11  Alexey Proskuryakov  <ap@apple.com>
 
         editing/spelling/spelling-marker-description.html times out on Mac
index f126d9b..53956ac 100644 (file)
@@ -45,7 +45,7 @@ PASS getSortedOwnPropertyNames(Object.prototype) is ['__defineGetter__', '__defi
 PASS getSortedOwnPropertyNames(Function) is ['length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(Function.prototype) is ['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']
 PASS getSortedOwnPropertyNames(Array) is ['from', 'isArray', 'length', 'name', 'of', 'prototype']
-PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift']
+PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']
 PASS getSortedOwnPropertyNames(String) is ['fromCharCode', 'length', 'name', 'prototype']
 PASS getSortedOwnPropertyNames(String.prototype) is ['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']
 PASS getSortedOwnPropertyNames(Boolean) is ['length', 'name', 'prototype']
index 4dd763d..b1e4819 100644 (file)
@@ -3,7 +3,44 @@ This test checks the behavior of the iterator methods on Array objects.
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS 'values' in [] is false
+PASS 'values' in [] is true
+PASS value is testArray[i]
+PASS value is 1
+PASS value is testArray[i]
+PASS value is 2
+PASS value is testArray[i]
+PASS value is 3
+PASS value is testArray[i]
+PASS value is 4
+PASS value is testArray[i]
+PASS value is 5
+PASS value is testArray[i]
+PASS value is 6
+PASS testArray.length is 6
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS value is testArray[i]
+PASS testArray.length is 9
+PASS i is 0
+PASS value is o[i]
+PASS value is 1
+PASS value is o[i]
+PASS value is 2
+PASS value is o[i]
+PASS value is 3
+PASS value is o[i]
+PASS value is 4
+PASS value is o[i]
+PASS value is 5
+PASS value is o[i]
+PASS value is 6
+PASS o.length is 6
 PASS key is 0
 PASS key is 1
 PASS key is 2
index 91bbb8f..3a37436 100644 (file)
@@ -53,7 +53,7 @@ var expectedPropertyNamesSet = {
     "Function": "['length', 'name', 'prototype']",
     "Function.prototype": "['apply', 'bind', 'call', 'constructor', 'length', 'name', 'toString']",
     "Array": "['from', 'isArray', 'length', 'name', 'of', 'prototype']",
-    "Array.prototype": "['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift']",
+    "Array.prototype": "['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']",
     "String": "['fromCharCode', 'length', 'name', 'prototype']",
     "String.prototype": "['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']",
     "Boolean": "['length', 'name', 'prototype']",
index 76059cf..d96c36b 100644 (file)
@@ -2,7 +2,58 @@ description(
 "This test checks the behavior of the iterator methods on Array objects."
 );
 
-shouldBeFalse("'values' in []");
+shouldBeTrue("'values' in []");
+
+var testArray = [1,2,3,4,5,6]
+var values = testArray.values();
+var i = 0;
+for (var value of values) {
+    shouldBe("value", "testArray[i]")
+    i++
+    shouldBe("value", String(i))
+}
+
+shouldBe("testArray.length", String(i))
+
+var testArray = [1,2,3,4,5,6]
+var values = testArray.values();
+var i = 0;
+for (var value of values) {
+    shouldBe("value", "testArray[i]")
+    i++
+    if (i % 2 == 0)
+        testArray[i] *= 2;
+    if (i < 4)
+        testArray.push(testArray.length)
+    if (i == 4)
+        delete testArray[4]
+    if (i == 5)
+        testArray[4] = 5
+}
+shouldBe("testArray.length", String(i))
+
+var o = {};
+for (var i =0; i < 6; i++)
+    o[i]=i+1
+
+
+var values = Array.prototype.values.call(o);
+var i = 0;
+for (var value of values) {
+    fail();
+}
+shouldBe("i", "0")
+
+o.length=6;
+
+var values = Array.prototype.values.call(o);
+var i = 0;
+for (var value of values) {
+    shouldBe("value", "o[i]")
+    i++
+    shouldBe("value", String(i))
+}
+shouldBe("o.length", String(i))
 
 var testArray = [1,2,3,4,5,6]
 var keys = testArray.keys();
index 720dd86..7795632 100644 (file)
@@ -1,3 +1,26 @@
+2015-04-12  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement Array.prototype.values
+        https://bugs.webkit.org/show_bug.cgi?id=143633
+
+        Reviewed by Darin Adler.
+
+        Symbol.unscopables is implemented, so we can implement Array.prototype.values
+        without largely breaking the web. The following script passes.
+
+        var array = [];
+        var values = 42;
+        with (array) {
+            assert(values, 42);
+        }
+
+        * runtime/ArrayPrototype.cpp:
+        * tests/stress/array-iterators-next.js:
+        * tests/stress/map-iterators-next.js:
+        * tests/stress/set-iterators-next.js:
+        * tests/stress/values-unscopables.js: Added.
+        (test):
+
 2015-04-11  Yusuke Suzuki  <utatane.tea@gmail.com>
 
         Run flaky conservative GC related test first before polluting stack and registers
index 9267432..ca5f36e 100644 (file)
@@ -114,6 +114,7 @@ const ClassInfo ArrayPrototype::s_info = {"Array", &JSArray::s_info, &arrayProto
   reduce         arrayProtoFuncReduce         DontEnum|Function 1
   reduceRight    arrayProtoFuncReduceRight    DontEnum|Function 1
   map            arrayProtoFuncMap            DontEnum|Function 1
+  values         arrayProtoFuncValues         DontEnum|Function 0
   entries        arrayProtoFuncEntries        DontEnum|Function 0
   keys           arrayProtoFuncKeys           DontEnum|Function 0
   find           arrayProtoFuncFind           DontEnum|Function 1
index 334c0e4..200e803 100644 (file)
@@ -37,6 +37,24 @@ var value = values.next().value;
 if (value !== undefined)
     throw "Error: bad value: " + value;
 
+var values = testArray.values();
+var i = 0;
+while (true) {
+    var {done, value} = values.next();
+    if (done)
+        break;
+    i++;
+    if (value !== i)
+        throw "Error: bad value: " + value;
+}
+
+if (testArray.length !== i)
+    throw "Error: bad value: " + i;
+
+var value = values.next().value;
+if (value !== undefined)
+    throw "Error: bad value: " + value;
+
 var entries = testArray.entries();
 var i = 0;
 do {
index 5329eae..f893b73 100644 (file)
@@ -23,25 +23,23 @@ var value = keys.next().value;
 if (value !== undefined)
     throw "Error: bad value: " + value;
 
-// TODO: Map.prototype.values() is not exposed.
-//
-// var values = testMap.values();
-// var i = 0;
-// while (true) {
-//     var {done, value} = values.next();
-//     if (done)
-//         break;
-//     i++;
-//     if (testArray.indexOf(value) === -1)
-//         throw "Error: bad value: " + value;
-// }
-//
-// if (testMap.size !== i)
-//     throw "Error: bad value: " + i;
-//
-// var value = values.next().value;
-// if (value !== undefined)
-//     throw "Error: bad value: " + value;
+var values = testMap.values();
+var i = 0;
+while (true) {
+    var {done, value} = values.next();
+    if (done)
+        break;
+    i++;
+    if (testArray.indexOf(value) === -1)
+        throw "Error: bad value: " + value;
+}
+
+if (testMap.size !== i)
+    throw "Error: bad value: " + i;
+
+var value = values.next().value;
+if (value !== undefined)
+    throw "Error: bad value: " + value;
 
 var entries = testMap.entries();
 var i = 0;
index 871dc7e..a0e4165 100644 (file)
@@ -23,25 +23,23 @@ var value = keys.next().value;
 if (value !== undefined)
     throw "Error: bad value: " + value;
 
-// TODO: Set.prototype.values() is not exposed.
-//
-// var values = testSet.values();
-// var i = 0;
-// while (true) {
-//     var {done, value} = values.next();
-//     if (done)
-//         break;
-//     i++;
-//     if (testArray.indexOf(value) === -1)
-//         throw "Error: bad value: " + value;
-// }
-//
-// if (testSet.size !== i)
-//     throw "Error: bad value: " + i;
-//
-// var value = values.next().value;
-// if (value !== undefined)
-//     throw "Error: bad value: " + value;
+var values = testSet.values();
+var i = 0;
+while (true) {
+    var {done, value} = values.next();
+    if (done)
+        break;
+    i++;
+    if (testArray.indexOf(value) === -1)
+        throw "Error: bad value: " + value;
+}
+
+if (testSet.size !== i)
+    throw "Error: bad value: " + i;
+
+var value = values.next().value;
+if (value !== undefined)
+    throw "Error: bad value: " + value;
 
 var entries = testSet.entries();
 var i = 0;
diff --git a/Source/JavaScriptCore/tests/stress/values-unscopables.js b/Source/JavaScriptCore/tests/stress/values-unscopables.js
new file mode 100644 (file)
index 0000000..3deb96c
--- /dev/null
@@ -0,0 +1,53 @@
+function test(actual, expected) {
+    if (actual !== expected)
+        throw new Error('bad value: ' + actual);
+}
+
+(function () {
+    var array = [];
+    var values = 42;
+
+    with (array) {
+        test(values, 42);
+    }
+
+    array[Symbol.unscopables].values = false;
+
+    with (array) {
+        test(values, Array.prototype.values);
+    }
+}());
+
+(function () {
+    var map  = new Map();
+    var values = 42;
+
+    with (map) {
+        test(values, Map.prototype.values);
+    }
+
+    map[Symbol.unscopables] = {
+        values: true
+    };
+
+    with (map) {
+        test(values, 42);
+    }
+}());
+
+(function () {
+    var set  = new Set();
+    var values = 42;
+
+    with (set) {
+        test(values, Set.prototype.values);
+    }
+
+    set[Symbol.unscopables] = {
+        values: true
+    };
+
+    with (set) {
+        test(values, 42);
+    }
+}());