Bug 918341 - new Map(iterable) should check that iterator values are objects. r=jorendorff
authorSankha Narayan Guria <sankha93@gmail.com>
Thu, 17 Oct 2013 12:36:52 +0530
changeset 151149 ae664f27e66337dd3d878289e32d32e14a1c92eb
parent 151148 fa7709266585498718027f85d0a299df47af58ec
child 151150 ae8714cdf381c196880974e7cd98e241ec9f280e
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
reviewersjorendorff
bugs918341
milestone27.0a1
Bug 918341 - new Map(iterable) should check that iterator values are objects. r=jorendorff
js/src/builtin/MapObject.cpp
js/src/jit-test/tests/collections/Map-constructor-5.js
js/src/js.msg
--- a/js/src/builtin/MapObject.cpp
+++ b/js/src/builtin/MapObject.cpp
@@ -1158,19 +1158,22 @@ MapObject::construct(JSContext *cx, unsi
         RootedValue pairVal(cx);
         RootedObject pairObj(cx);
         while (true) {
             bool done;
             if (!iter.next(&pairVal, &done))
                 return false;
             if (done)
                 break;
-            // FIXME: We're supposed to throw if pairVal isn't an object.  Bug
-            // 918341.
-            pairObj = ToObject(cx, pairVal);
+            if (!pairVal.isObject()) {
+                JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_INVALID_MAP_ITERABLE);
+                return false;
+            }
+
+            pairObj = &pairVal.toObject();
             if (!pairObj)
                 return false;
 
             RootedValue key(cx);
             if (!JSObject::getElement(cx, pairObj, pairObj, 0, &key))
                 return false;
 
             AutoHashableValueRooter hkey(cx);
--- a/js/src/jit-test/tests/collections/Map-constructor-5.js
+++ b/js/src/jit-test/tests/collections/Map-constructor-5.js
@@ -1,7 +1,15 @@
 // Map(arr) throws if arr contains holes (or undefined values).
 
 load(libdir + "asserts.js");
 assertThrowsInstanceOf(function () { Map([undefined]); }, TypeError);
 assertThrowsInstanceOf(function () { Map([null]); }, TypeError);
 assertThrowsInstanceOf(function () { Map([[0, 0], [1, 1], , [3, 3]]); }, TypeError);
 assertThrowsInstanceOf(function () { Map([[0, 0], [1, 1], ,]); }, TypeError);
+
+// Map(iterable) throws if iterable doesn't have array-like objects
+
+assertThrowsInstanceOf(function () { Map([1, 2, 3]); }, TypeError);
+assertThrowsInstanceOf(function () {
+	let s = new Set([1, 2, "abc"]);
+	new Map(s);
+}, TypeError);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -217,17 +217,17 @@ MSG_DEF(JSMSG_USELESS_EXPR,           16
 MSG_DEF(JSMSG_REDECLARED_PARAM,       164, 1, JSEXN_TYPEERR, "redeclaration of formal parameter {0}")
 MSG_DEF(JSMSG_NEWREGEXP_FLAGGED,      165, 0, JSEXN_TYPEERR, "can't supply flags when constructing one RegExp from another")
 MSG_DEF(JSMSG_RESERVED_SLOT_RANGE,    166, 0, JSEXN_RANGEERR, "reserved slot index out of range")
 MSG_DEF(JSMSG_CANT_DECODE_PRINCIPALS, 167, 0, JSEXN_INTERNALERR, "can't decode JSPrincipals")
 MSG_DEF(JSMSG_CANT_SEAL_OBJECT,       168, 1, JSEXN_ERR, "can't seal {0} objects")
 MSG_DEF(JSMSG_TOO_MANY_CATCH_VARS,    169, 0, JSEXN_SYNTAXERR, "too many catch variables")
 MSG_DEF(JSMSG_NEGATIVE_REPETITION_COUNT, 170, 0, JSEXN_RANGEERR, "repeat count must be non-negative")
 MSG_DEF(JSMSG_INVALID_FOR_OF_INIT,    171, 0, JSEXN_SYNTAXERR, "for-of loop variable declaration may not have an initializer")
-MSG_DEF(JSMSG_UNUSED172,              172, 0, JSEXN_NONE, "")
+MSG_DEF(JSMSG_INVALID_MAP_ITERABLE,   172, 0, JSEXN_TYPEERR, "iterable for map should have array-like objects")
 MSG_DEF(JSMSG_UNUSED173,              173, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_UNUSED174,              174, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_NESTING_GENERATOR,      175, 0, JSEXN_TYPEERR, "already executing generator")
 MSG_DEF(JSMSG_UNUSED176,              176, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_UNUSED177,              177, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_UNUSED178,              178, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_UNUSED179,              179, 0, JSEXN_NONE, "")
 MSG_DEF(JSMSG_UNUSED180,              180, 0, JSEXN_NONE, "")