From f95b81a6ef6d5278726eb9661e4692925606f805 Mon Sep 17 00:00:00 2001 From: "arv@chromium.org" Date: Tue, 12 Aug 2014 20:09:40 +0000 Subject: [PATCH] ES6: Make Map/Set constructors support iterable values 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 | 4 +-- src/weak_collection.js | 4 +-- test/mjsunit/es6/collections.js | 63 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/src/collection.js b/src/collection.js index 5e4421e..20887dd 100644 --- a/src/collection.js +++ b/src/collection.js @@ -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]); diff --git a/src/weak_collection.js b/src/weak_collection.js index 73dd9de..1160176 100644 --- a/src/weak_collection.js +++ b/src/weak_collection.js @@ -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]); diff --git a/test/mjsunit/es6/collections.js b/test/mjsunit/es6/collections.js index c585719..911b748 100644 --- a/test/mjsunit/es6/collections.js +++ b/test/mjsunit/es6/collections.js @@ -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); -- 2.7.4