ES6: Make Map/Set constructors support iterable values
authorarv@chromium.org <arv@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 Aug 2014 20:09:40 +0000 (20:09 +0000)
committerarv@chromium.org <arv@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 12 Aug 2014 20:09:40 +0000 (20:09 +0000)
Same for WeakMap/WeakSet

https://bugs.ecmascript.org/show_bug.cgi?id=3111

BUG=v8:3508
LOG=Y
R=dslomov@chromium.org

Review URL: https://codereview.chromium.org/466003002

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23091 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

src/collection.js
src/weak_collection.js
test/mjsunit/es6/collections.js

index 5e4421eb1072448a186f47eb85f909cb60bdf6bb..20887dd8f7adf5f4ae61c0919c8afbd09469e341 100644 (file)
@@ -23,7 +23,7 @@ function SetConstructor(iterable) {
   var iter, adder;
 
   if (!IS_NULL_OR_UNDEFINED(iterable)) {
-    iter = GetIterator(iterable);
+    iter = GetIterator(ToObject(iterable));
     adder = this.add;
     if (!IS_SPEC_FUNCTION(adder)) {
       throw MakeTypeError('property_not_function', ['add', this]);
@@ -147,7 +147,7 @@ function MapConstructor(iterable) {
   var iter, adder;
 
   if (!IS_NULL_OR_UNDEFINED(iterable)) {
-    iter = GetIterator(iterable);
+    iter = GetIterator(ToObject(iterable));
     adder = this.set;
     if (!IS_SPEC_FUNCTION(adder)) {
       throw MakeTypeError('property_not_function', ['set', this]);
index 73dd9de6ba9aa5c48d16596ffde2c015e1764673..1160176d66f6c34b8cf8acb59d0841d832055aae 100644 (file)
@@ -23,7 +23,7 @@ function WeakMapConstructor(iterable) {
   var iter, adder;
 
   if (!IS_NULL_OR_UNDEFINED(iterable)) {
-    iter = GetIterator(iterable);
+    iter = GetIterator(ToObject(iterable));
     adder = this.set;
     if (!IS_SPEC_FUNCTION(adder)) {
       throw MakeTypeError('property_not_function', ['set', this]);
@@ -139,7 +139,7 @@ function WeakSetConstructor(iterable) {
   var iter, adder;
 
   if (!IS_NULL_OR_UNDEFINED(iterable)) {
-    iter = GetIterator(iterable);
+    iter = GetIterator(ToObject(iterable));
     adder = this.add;
     if (!IS_SPEC_FUNCTION(adder)) {
       throw MakeTypeError('property_not_function', ['add', this]);
index c58571950c9545861dfa9d99e8ac25ebde8913d4..911b748ed9de632d7da903f203d744fea2cfaa44 100644 (file)
@@ -1015,6 +1015,9 @@ function TestSetConstructor(ctor) {
   assertThrows(function() {
     new ctor({});
   }, TypeError);
+  assertThrows(function() {
+    new ctor(true);
+  }, TypeError);
 
   // @@iterator not callable
   assertThrows(function() {
@@ -1148,6 +1151,39 @@ TestSetConstructorNextNotAnObject(WeakSet);
 })();
 
 
+function TestSetConstructorIterableValue(ctor) {
+  'use strict';
+  // Strict mode is required to prevent implicit wrapping in the getter.
+  Object.defineProperty(Number.prototype, Symbol.iterator, {
+    get: function() {
+      assertEquals('object', typeof this);
+      return function() {
+        return oneAndTwo.keys();
+      };
+    },
+    configurable: true
+  });
+
+  var set = new ctor(42);
+  assertSize(2, set);
+  assertTrue(set.has(k1));
+  assertTrue(set.has(k2));
+
+  delete Number.prototype[Symbol.iterator];
+}
+TestSetConstructorIterableValue(Set);
+TestSetConstructorIterableValue(WeakSet);
+
+
+(function TestSetConstructorStringValue() {
+  var s = new Set('abc');
+  assertSize(3, s);
+  assertTrue(s.has('a'));
+  assertTrue(s.has('b'));
+  assertTrue(s.has('c'));
+})();
+
+
 function TestMapConstructor(ctor) {
   var m = new ctor(null);
   assertSize(0, m);
@@ -1159,6 +1195,9 @@ function TestMapConstructor(ctor) {
   assertThrows(function() {
     new ctor({});
   }, TypeError);
+  assertThrows(function() {
+    new ctor(true);
+  }, TypeError);
 
   // @@iterator not callable
   assertThrows(function() {
@@ -1300,3 +1339,27 @@ TestMapConstructorIteratorNotObjectValues(WeakMap);
     new WeakMap([[1, 2]])
   }, TypeError);
 })();
+
+
+function TestMapConstructorIterableValue(ctor) {
+  'use strict';
+  // Strict mode is required to prevent implicit wrapping in the getter.
+  Object.defineProperty(Number.prototype, Symbol.iterator, {
+    get: function() {
+      assertEquals('object', typeof this);
+      return function() {
+        return oneAndTwo.entries();
+      };
+    },
+    configurable: true
+  });
+
+  var map = new ctor(42);
+  assertSize(2, map);
+  assertEquals(1, map.get(k1));
+  assertEquals(2, map.get(k2));
+
+  delete Number.prototype[Symbol.iterator];
+}
+TestMapConstructorIterableValue(Map);
+TestMapConstructorIterableValue(WeakMap);