diff --git a/addon-sdk/source/lib/sdk/util/iteration.js b/addon-sdk/source/lib/sdk/util/iteration.js index b0ed01e4f0ea..d2750a726f6c 100644 --- a/addon-sdk/source/lib/sdk/util/iteration.js +++ b/addon-sdk/source/lib/sdk/util/iteration.js @@ -7,20 +7,9 @@ module.metadata = { "stability": "experimental" }; -// This is known as @@iterator in the ES6 spec. Until it is bound to -// some well-known name, find the @@iterator object by expecting it as -// the first property accessed on a for-of iterable. -const iteratorSymbol = (function() { - try { - for (var _ of Proxy.create({get: function(_, name) { throw name; } })) - break; - } catch (name) { - return name; - } - throw new TypeError; -})(); - -exports.iteratorSymbol = iteratorSymbol; +// Legacy binding for Symbol.iterator. (This export existed before Symbols were +// implemented in the JS engine.) +exports.iteratorSymbol = Symbol.iterator; // An adaptor that, given an object that is iterable with for-of, is // suitable for being bound to __iterator__ in order to make the object diff --git a/browser/components/customizableui/CustomizableUI.jsm b/browser/components/customizableui/CustomizableUI.jsm index 85727b90afcb..af87bb42cc9d 100644 --- a/browser/components/customizableui/CustomizableUI.jsm +++ b/browser/components/customizableui/CustomizableUI.jsm @@ -2662,7 +2662,7 @@ this.CustomizableUI = { * for (let window of CustomizableUI.windows) { ... } */ windows: { - "@@iterator": function*() { + *[Symbol.iterator]() { for (let [window,] of gBuildWindows) yield window; } diff --git a/browser/devtools/debugger/debugger-panes.js b/browser/devtools/debugger/debugger-panes.js index 7c308449f547..511df2c88b1a 100644 --- a/browser/devtools/debugger/debugger-panes.js +++ b/browser/devtools/debugger/debugger-panes.js @@ -3261,9 +3261,9 @@ LineResults.prototype = { /** * A generator-iterator over the global, source or line results. */ -GlobalResults.prototype["@@iterator"] = -SourceResults.prototype["@@iterator"] = -LineResults.prototype["@@iterator"] = function*() { +GlobalResults.prototype[Symbol.iterator] = +SourceResults.prototype[Symbol.iterator] = +LineResults.prototype[Symbol.iterator] = function*() { yield* this._store; }; diff --git a/browser/devtools/framework/gDevTools.jsm b/browser/devtools/framework/gDevTools.jsm index 8b5358b0eb83..0b6a0f82161f 100644 --- a/browser/devtools/framework/gDevTools.jsm +++ b/browser/devtools/framework/gDevTools.jsm @@ -475,14 +475,14 @@ DevTools.prototype = { // for (let [target, toolbox] of this._toolboxes) toolbox.destroy(); // Is taken care of by the gDevToolsBrowser.forgetBrowserWindow }, +}; - /** - * Iterator that yields each of the toolboxes. - */ - '@@iterator': function*() { - for (let toolbox of this._toolboxes) { - yield toolbox; - } +/** + * Iterator that yields each of the toolboxes. + */ +Devtools.prototype[Symbol.iterator] = function*() { + for (let toolbox of this._toolboxes) { + yield toolbox; } }; diff --git a/browser/devtools/shared/widgets/VariablesView.jsm b/browser/devtools/shared/widgets/VariablesView.jsm index 061faf0b1cfb..cc1d28bcb0fa 100644 --- a/browser/devtools/shared/widgets/VariablesView.jsm +++ b/browser/devtools/shared/widgets/VariablesView.jsm @@ -3056,10 +3056,10 @@ Property.prototype = Heritage.extend(Variable.prototype, { /** * A generator-iterator over the VariablesView, Scopes, Variables and Properties. */ -VariablesView.prototype["@@iterator"] = -Scope.prototype["@@iterator"] = -Variable.prototype["@@iterator"] = -Property.prototype["@@iterator"] = function*() { +VariablesView.prototype[Symbol.iterator] = +Scope.prototype[Symbol.iterator] = +Variable.prototype[Symbol.iterator] = +Property.prototype[Symbol.iterator] = function*() { yield* this._store; }; diff --git a/browser/devtools/shared/widgets/ViewHelpers.jsm b/browser/devtools/shared/widgets/ViewHelpers.jsm index 68b4be71259d..e3f6c2f88d39 100644 --- a/browser/devtools/shared/widgets/ViewHelpers.jsm +++ b/browser/devtools/shared/widgets/ViewHelpers.jsm @@ -1729,7 +1729,7 @@ this.WidgetMethods = { /** * A generator-iterator over all the items in this container. */ -Item.prototype["@@iterator"] = -WidgetMethods["@@iterator"] = function*() { +Item.prototype[Symbol.iterator] = +WidgetMethods[Symbol.iterator] = function*() { yield* this._itemsByElement.values(); }; diff --git a/content/html/content/test/test_formelements.html b/content/html/content/test/test_formelements.html index b6836314d152..c4714aa6b6f9 100644 --- a/content/html/content/test/test_formelements.html +++ b/content/html/content/test/test_formelements.html @@ -32,7 +32,7 @@ names = []; for (var name in x) { names.push(name); } -is(names.length, 10, "Should have 10 enumerated names"); +is(names.length, 9, "Should have 9 enumerated names"); is(names[0], "0", "Enum entry 1"); is(names[1], "1", "Enum entry 2"); is(names[2], "2", "Enum entry 3"); @@ -41,8 +41,7 @@ is(names[4], "4", "Enum entry 5"); is(names[5], "something", "Enum entry 6"); is(names[6], "namedItem", "Enum entry 7"); is(names[7], "item", "Enum entry 8"); -is(names[8], "@@iterator", "Enum entry 9"); -is(names[9], "length", "Enum entry 10"); +is(names[8], "length", "Enum entry 9"); names = Object.getOwnPropertyNames(x); is(names.length, 10, "Should have 10 items"); diff --git a/content/html/content/test/test_htmlcollection.html b/content/html/content/test/test_htmlcollection.html index e5dd5bfb0e8e..7be164429d48 100644 --- a/content/html/content/test/test_htmlcollection.html +++ b/content/html/content/test/test_htmlcollection.html @@ -28,7 +28,7 @@ var names = []; for (var name in x) { names.push(name); } -is(names.length, 9, "Should have 9 enumerated names"); +is(names.length, 8, "Should have 8 enumerated names"); is(names[0], "0", "Enum entry 1") is(names[1], "1", "Enum entry 2") is(names[2], "2", "Enum entry 3") @@ -36,8 +36,7 @@ is(names[3], "3", "Enum entry 4") is(names[4], "something", "Enum entry 5") is(names[5], "item", "Enum entry 6") is(names[6], "namedItem", "Enum entry 7") -is(names[7], "@@iterator", "Enum entry 8") -is(names[8], "length", "Enum entry 9") +is(names[7], "length", "Enum entry 8") names = Object.getOwnPropertyNames(x); is(names.length, 9, "Should have 9 items"); diff --git a/content/html/content/test/test_named_options.html b/content/html/content/test/test_named_options.html index 160c0589440d..b6e84a9f2c33 100644 --- a/content/html/content/test/test_named_options.html +++ b/content/html/content/test/test_named_options.html @@ -42,7 +42,7 @@ var names2 = []; for (var name in opt) { names2.push(name); } -is(names2.length, 12, "Should have twelve enumerated names"); +is(names2.length, 11, "Should have eleven enumerated names"); is(names2[0], "0", "Enum entry 1") is(names2[1], "1", "Enum entry 2") is(names2[2], "2", "Enum entry 3") @@ -54,7 +54,6 @@ is(names2[7], "length", "Enum entry 8") is(names2[8], "selectedIndex", "Enum entry 9") is(names2[9], "item", "Enum entry 10") is(names2[10], "namedItem", "Enum entry 11") -is(names2[11], "@@iterator", "Enum entry 12") diff --git a/content/html/content/test/test_rowscollection.html b/content/html/content/test/test_rowscollection.html index 54483e9e2fc5..6e80e62d4bc3 100644 --- a/content/html/content/test/test_rowscollection.html +++ b/content/html/content/test/test_rowscollection.html @@ -38,7 +38,7 @@ var names = []; for (var name in x) { names.push(name); } -is(names.length, 11, "Should have 11 enumerated names"); +is(names.length, 10, "Should have 10 enumerated names"); is(names[0], "0", "Enum entry 1") is(names[1], "1", "Enum entry 2") is(names[2], "2", "Enum entry 3") @@ -48,8 +48,7 @@ is(names[5], "5", "Enum entry 6") is(names[6], "something", "Enum entry 7") is(names[7], "item", "Enum entry 8") is(names[8], "namedItem", "Enum entry 9") -is(names[9], "@@iterator", "Enum entry 10") -is(names[10], "length", "Enum entry 11") +is(names[9], "length", "Enum entry 10") names = Object.getOwnPropertyNames(x); is(names.length, 11, "Should have 11 items"); diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 7a127de556e2..dd45688ae2e0 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -1942,7 +1942,7 @@ class PropertyDefiner: getAvailableInTestFunc(interfaceMember), descriptor.checkPermissionsIndicesForMembers.get(interfaceMember.identifier.name)) - def generatePrefableArray(self, array, name, specTemplate, specTerminator, + def generatePrefableArray(self, array, name, specFormatter, specTerminator, specType, getCondition, getDataTuple, doIdArrays): """ This method generates our various arrays. @@ -1951,7 +1951,8 @@ class PropertyDefiner: name is the name as passed to generateArray - specTemplate is a template for each entry of the spec array + specFormatter is a function that takes a single argument, a tuple, + and returns a string, a spec array entry specTerminator is a terminator for the spec array (inserted every time our controlling pref changes and at the end of the array) @@ -1962,7 +1963,7 @@ class PropertyDefiner: returns the corresponding MemberCondition. getDataTuple is a callback function that takes an array entry and - returns a tuple suitable for substitution into specTemplate. + returns a tuple suitable to be passed to specFormatter. """ # We want to generate a single list of specs, but with specTerminator @@ -2005,7 +2006,7 @@ class PropertyDefiner: switchToCondition(self, curCondition) lastCondition = curCondition # And the actual spec - specs.append(specTemplate % getDataTuple(member)) + specs.append(specFormatter(getDataTuple(member))) specs.append(specTerminator) prefableSpecs.append(" { false, nullptr }") @@ -2279,9 +2280,15 @@ class MethodDefiner(PropertyDefiner): return (m["name"], accessor, jitinfo, m["length"], flags(m), selfHostedName) + def formatSpec(fields): + if fields[0].startswith("@@"): + fields = (fields[0][2:],) + fields[1:] + return ' JS_SYM_FNSPEC(%s, %s, %s, %s, %s, %s)' % fields + return ' JS_FNSPEC("%s", %s, %s, %s, %s, %s)' % fields + return self.generatePrefableArray( array, name, - ' JS_FNSPEC("%s", %s, %s, %s, %s, %s)', + formatSpec, ' JS_FS_END', 'JSFunctionSpec', condition, specData, doIdArrays) @@ -2384,7 +2391,7 @@ class AttrDefiner(PropertyDefiner): return self.generatePrefableArray( array, name, - ' { "%s", %s, %s, %s}', + lambda fields: ' { "%s", %s, %s, %s}' % fields, ' JS_PS_END', 'JSPropertySpec', PropertyDefiner.getControllingCondition, specData, doIdArrays) @@ -2412,7 +2419,7 @@ class ConstDefiner(PropertyDefiner): return self.generatePrefableArray( array, name, - ' { "%s", %s }', + lambda fields: ' { "%s", %s }' % fields, ' { 0, JS::UndefinedValue() }', 'ConstantSpec', PropertyDefiner.getControllingCondition, specData, doIdArrays) diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js index eaaf2c3b0eb2..1b2c365cb725 100644 --- a/js/src/builtin/Array.js +++ b/js/src/builtin/Array.js @@ -678,7 +678,7 @@ function ArrayFrom(arrayLike, mapfn=undefined, thisArg=undefined) { var attrs = ATTR_CONFIGURABLE | ATTR_ENUMERABLE | ATTR_WRITABLE; // Steps 6-8. - var usingIterator = items["@@iterator"]; + var usingIterator = items[std_iterator]; if (usingIterator !== undefined) { // Steps 8.a-c. var A = IsConstructor(C) ? new C() : []; diff --git a/js/src/builtin/MapObject.cpp b/js/src/builtin/MapObject.cpp index 257a97988bfe..156b57444a4c 100644 --- a/js/src/builtin/MapObject.cpp +++ b/js/src/builtin/MapObject.cpp @@ -876,7 +876,7 @@ const Class MapIteratorObject::class_ = { }; const JSFunctionSpec MapIteratorObject::methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "IteratorIdentity", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0), JS_FN("next", next, 0, 0), JS_FS_END }; @@ -1074,7 +1074,8 @@ MapObject::initClass(JSContext *cx, JSObject *obj) // Define its alias. RootedValue funval(cx, ObjectValue(*fun)); - if (!JS_DefineProperty(cx, proto, js_std_iterator_str, funval, 0)) + RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); + if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0)) return nullptr; } return proto; @@ -1524,7 +1525,7 @@ const Class SetIteratorObject::class_ = { }; const JSFunctionSpec SetIteratorObject::methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "IteratorIdentity", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0), JS_FN("next", next, 0, 0), JS_FS_END }; @@ -1697,7 +1698,8 @@ SetObject::initClass(JSContext *cx, JSObject *obj) RootedValue funval(cx, ObjectValue(*fun)); if (!JS_DefineProperty(cx, proto, "keys", funval, 0)) return nullptr; - if (!JS_DefineProperty(cx, proto, js_std_iterator_str, funval, 0)) + RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); + if (!JS_DefinePropertyById(cx, proto, iteratorId, funval, 0)) return nullptr; } return proto; diff --git a/js/src/builtin/Utilities.js b/js/src/builtin/Utilities.js index fae2a5b68650..8d0cc9667181 100644 --- a/js/src/builtin/Utilities.js +++ b/js/src/builtin/Utilities.js @@ -83,7 +83,7 @@ var std_WeakMap_clear = WeakMap.prototype.clear; var std_WeakMap_delete = WeakMap.prototype.delete; var std_Map_has = Map.prototype.has; var std_Set_has = Set.prototype.has; -var std_iterator = '@@iterator'; // FIXME: Change to be a symbol. +var std_iterator = Symbol.iterator; var std_StopIteration = StopIteration; var std_Map_iterator = Map.prototype[std_iterator]; var std_Set_iterator = Set.prototype[std_iterator]; diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index deab2d22fc54..db1661c67d27 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -4657,9 +4657,9 @@ EmitIterator(ExclusiveContext *cx, BytecodeEmitter *bce) // Convert iterable to iterator. if (Emit1(cx, bce, JSOP_DUP) < 0) // OBJ OBJ return false; - if (!EmitAtomOp(cx, cx->names().std_iterator, JSOP_CALLPROP, bce)) // OBJ @@ITERATOR + if (Emit2(cx, bce, JSOP_SYMBOL, jsbytecode(JS::SymbolCode::iterator)) < 0) // OBJ OBJ @@ITERATOR return false; - if (Emit1(cx, bce, JSOP_SWAP) < 0) // @@ITERATOR OBJ + if (!EmitElemOpBase(cx, bce, JSOP_CALLELEM)) // FN OBJ return false; if (EmitCall(cx, bce, JSOP_CALL, 0) < 0) // ITER return false; @@ -5478,9 +5478,9 @@ EmitYieldStar(ExclusiveContext *cx, BytecodeEmitter *bce, ParseNode *iter) // Convert iterable to iterator. if (Emit1(cx, bce, JSOP_DUP) < 0) // ITERABLE ITERABLE return false; - if (!EmitAtomOp(cx, cx->names().std_iterator, JSOP_CALLPROP, bce)) // ITERABLE @@ITERATOR + if (Emit2(cx, bce, JSOP_SYMBOL, jsbytecode(JS::SymbolCode::iterator)) < 0) // ITERABLE ITERABLE @@ITERATOR return false; - if (Emit1(cx, bce, JSOP_SWAP) < 0) // @@ITERATOR ITERABLE + if (!EmitElemOpBase(cx, bce, JSOP_CALLELEM)) // FN ITERABLE return false; if (EmitCall(cx, bce, JSOP_CALL, 0, iter) < 0) // ITER return false; diff --git a/js/src/jit-test/lib/iteration.js b/js/src/jit-test/lib/iteration.js index 500b28303ec9..04e2495e7260 100644 --- a/js/src/jit-test/lib/iteration.js +++ b/js/src/jit-test/lib/iteration.js @@ -5,8 +5,7 @@ load(libdir + "asserts.js"); -// FIXME: Import from std::iteration. -const std_iterator = '@@iterator'; +const std_iterator = Symbol.iterator; if (typeof assertIteratorResult === 'undefined') { var assertIteratorResult = function assertIteratorResult(result, value, done) { diff --git a/js/src/jit-test/tests/arguments/destructuring-exprbody.js b/js/src/jit-test/tests/arguments/destructuring-exprbody.js index 81289b92d1c6..7f7bf536a030 100644 --- a/js/src/jit-test/tests/arguments/destructuring-exprbody.js +++ b/js/src/jit-test/tests/arguments/destructuring-exprbody.js @@ -1,7 +1,7 @@ // See bug 763313 function f([a]) a var i = 0; -var o = {'@@iterator': function () { i++; return { +var o = {[Symbol.iterator]: function () { i++; return { next: function () { i++; return {value: 42, done: false}; }}}}; assertEq(f(o), 42); assertEq(i, 2); diff --git a/js/src/jit-test/tests/basic/expression-autopsy.js b/js/src/jit-test/tests/basic/expression-autopsy.js index 26bd4100b42d..ad2985d16adc 100644 --- a/js/src/jit-test/tests/basic/expression-autopsy.js +++ b/js/src/jit-test/tests/basic/expression-autopsy.js @@ -109,8 +109,8 @@ check("o[- (o)]"); // A few one off tests check_one("6", (function () { 6() }), " is not a function"); check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only"); -check_one("(intermediate value)['@@iterator'](...).next(...).value", function () { var [{ x }] = [null, {}]; }, " is null"); -check_one("(intermediate value)['@@iterator'](...).next(...).value", function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined"); +check_one("(intermediate value)[(intermediate value)](...).next(...).value", function () { var [{ x }] = [null, {}]; }, " is null"); +check_one("(intermediate value)[(intermediate value)](...).next(...).value", function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined"); // Check fallback behavior assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError); diff --git a/js/src/jit-test/tests/collections/WeakSet-error.js b/js/src/jit-test/tests/collections/WeakSet-error.js index 57726671c7d8..a162d3859b22 100644 --- a/js/src/jit-test/tests/collections/WeakSet-error.js +++ b/js/src/jit-test/tests/collections/WeakSet-error.js @@ -19,7 +19,7 @@ testMethod("add"); testMethod("delete"); testMethod("clear", false); -assertThrowsInstanceOf(function() { new WeakSet({"@@iterator": 2}) }, TypeError); -assertEq(typeof []["@@iterator"], "function"); // Make sure we fail when @@iterator is removed +assertThrowsInstanceOf(function() { new WeakSet({[Symbol.iterator]: 2}) }, TypeError); +assertEq(typeof [][Symbol.iterator], "function"); assertThrowsInstanceOf(function() { WeakSet(); }, TypeError); diff --git a/js/src/jit-test/tests/collections/iterator-proto-surfaces.js b/js/src/jit-test/tests/collections/iterator-proto-surfaces.js index 13c52dc8ba05..a0ad0b218b09 100644 --- a/js/src/jit-test/tests/collections/iterator-proto-surfaces.js +++ b/js/src/jit-test/tests/collections/iterator-proto-surfaces.js @@ -6,8 +6,8 @@ load(libdir + "iteration.js"); function test(constructor) { var proto = Object.getPrototypeOf(constructor()[std_iterator]()); var names = Object.getOwnPropertyNames(proto); - names.sort(); - assertDeepEq(names, [std_iterator, 'next']); + assertDeepEq(names, ['next']); + assertEq(proto.hasOwnProperty(std_iterator), true); var desc = Object.getOwnPropertyDescriptor(proto, 'next'); assertEq(desc.configurable, true); diff --git a/js/src/jit-test/tests/for-of/next-3.js b/js/src/jit-test/tests/for-of/next-3.js index f0eadc64116a..65661c223525 100644 --- a/js/src/jit-test/tests/for-of/next-3.js +++ b/js/src/jit-test/tests/for-of/next-3.js @@ -8,6 +8,6 @@ load(libdir + "asserts.js"); load(libdir + "iteration.js"); var g = newGlobal(); -g.eval("var it = [1, 2]['" + std_iterator + "']();"); +g.eval("var it = [1, 2][Symbol.iterator]();"); assertIteratorNext(g.it, 1); assertThrowsInstanceOf([][std_iterator]().next.bind(g.it), TypeError) diff --git a/js/src/jit-test/tests/for-of/semantics-08.js b/js/src/jit-test/tests/for-of/semantics-08.js index 9c0cc08ea994..0bb801e56a13 100644 --- a/js/src/jit-test/tests/for-of/semantics-08.js +++ b/js/src/jit-test/tests/for-of/semantics-08.js @@ -3,7 +3,8 @@ load(libdir + "iteration.js"); var g = newGlobal(); -var it = g.eval("({ '" + std_iterator + "': function () { return this; }, " + - "next: function () { return { done: true } } });"); -for (x of it) +g.eval("var obj = {};\n" + + "obj[Symbol.iterator] = function () { return this; };\n" + + "obj.next = function () { return { done: true }; };\n"); +for (x of g.obj) throw 'FAIL'; diff --git a/js/src/jit-test/tests/for-of/string-iterator-surfaces.js b/js/src/jit-test/tests/for-of/string-iterator-surfaces.js index 81e5fd841f1c..dee308792ff7 100644 --- a/js/src/jit-test/tests/for-of/string-iterator-surfaces.js +++ b/js/src/jit-test/tests/for-of/string-iterator-surfaces.js @@ -57,7 +57,8 @@ var iterProto = Object.getPrototypeOf(iter); assertEq(Object.getPrototypeOf(iterProto), Object.prototype); // Own properties for StringIterator.prototype: "next" and @@iterator -arraysEqual(Object.getOwnPropertyNames(iterProto).sort(), ["next", std_iterator].sort()); +arraysEqual(Object.getOwnPropertyNames(iterProto), ["next"]); +assertEq(iterProto.hasOwnProperty(std_iterator), true); // StringIterator.prototype[@@iterator] is a built-in function assertBuiltinFunction(iterProto, std_iterator, 0); diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 4c87931504a4..3941e9e9463a 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -5618,7 +5618,7 @@ JS::GetSymbolCode(Handle symbol) JS_PUBLIC_API(JS::Symbol *) JS::GetWellKnownSymbol(JSContext *cx, JS::SymbolCode which) { - return cx->runtime()->wellKnownSymbols->get(uint32_t(which)); + return cx->wellKnownSymbols().get(uint32_t(which)); } JS_PUBLIC_API(bool) diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp index a191279f2b77..ff895b1e6e0b 100644 --- a/js/src/jsarray.cpp +++ b/js/src/jsarray.cpp @@ -3020,7 +3020,7 @@ static const JSFunctionSpec array_methods[] = { JS_SELF_HOSTED_FN("fill", "ArrayFill", 3,0), - JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0,0), + JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0,0), JS_SELF_HOSTED_FN("entries", "ArrayEntries", 0,0), JS_SELF_HOSTED_FN("keys", "ArrayKeys", 0,0), JS_FS_END diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 4ed25f630808..7e26ce4a560a 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -885,7 +885,7 @@ iterator_next(JSContext *cx, unsigned argc, Value *vp) } static const JSFunctionSpec iterator_methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "LegacyIteratorShim", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "LegacyIteratorShim", 0, 0), JS_FN("next", iterator_next, 0, 0), JS_FS_END }; @@ -964,7 +964,7 @@ const Class ArrayIteratorObject::class_ = { }; static const JSFunctionSpec array_iterator_methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "ArrayIteratorIdentity", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "ArrayIteratorIdentity", 0, 0), JS_SELF_HOSTED_FN("next", "ArrayIteratorNext", 0, 0), JS_FS_END }; @@ -1003,7 +1003,7 @@ const Class StringIteratorObject::class_ = { }; static const JSFunctionSpec string_iterator_methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "StringIteratorIdentity", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "StringIteratorIdentity", 0, 0), JS_SELF_HOSTED_FN("next", "StringIteratorNext", 0, 0), JS_FS_END }; @@ -1405,7 +1405,8 @@ ForOfIterator::init(HandleValue iterable, NonIterableBehavior nonIterableBehavio args.setThis(ObjectValue(*iterableObj)); RootedValue callee(cx); - if (!JSObject::getProperty(cx, iterableObj, iterableObj, cx->names().std_iterator, &callee)) + RootedId iteratorId(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); + if (!JSObject::getGeneric(cx, iterableObj, iterableObj, iteratorId, &callee)) return false; // Throw if obj[@@iterator] isn't callable if we were asked to do so. @@ -2014,14 +2015,14 @@ NativeMethod(JSContext *cx, unsigned argc, Value *vp) #define JS_METHOD(name, T, impl, len, attrs) JS_FN(name, (NativeMethod), len, attrs) static const JSFunctionSpec star_generator_methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "IteratorIdentity", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "IteratorIdentity", 0, 0), JS_METHOD("next", StarGeneratorObject, star_generator_next, 1, 0), JS_METHOD("throw", StarGeneratorObject, star_generator_throw, 1, 0), JS_FS_END }; static const JSFunctionSpec legacy_generator_methods[] = { - JS_SELF_HOSTED_FN("@@iterator", "LegacyGeneratorIteratorShim", 0, 0), + JS_SELF_HOSTED_SYM_FN(iterator, "LegacyGeneratorIteratorShim", 0, 0), // "send" is an alias for "next". JS_METHOD("next", LegacyGeneratorObject, legacy_generator_next, 1, JSPROP_ROPERM), JS_METHOD("send", LegacyGeneratorObject, legacy_generator_next, 1, JSPROP_ROPERM), diff --git a/js/src/jsstr.cpp b/js/src/jsstr.cpp index b9ebfba31e94..9c6d7c64b14c 100644 --- a/js/src/jsstr.cpp +++ b/js/src/jsstr.cpp @@ -4200,7 +4200,7 @@ static const JSFunctionSpec string_methods[] = { JS_SELF_HOSTED_FN("fontcolor","String_fontcolor", 1,0), JS_SELF_HOSTED_FN("fontsize", "String_fontsize", 1,0), - JS_SELF_HOSTED_FN("@@iterator", "String_iterator", 0,0), + JS_SELF_HOSTED_SYM_FN(iterator, "String_iterator", 0,0), JS_FS_END }; diff --git a/js/src/tests/ecma_6/Array/for_of_2.js b/js/src/tests/ecma_6/Array/for_of_2.js index 8d72fb7b50bb..1d5dd81fc616 100644 --- a/js/src/tests/ecma_6/Array/for_of_2.js +++ b/js/src/tests/ecma_6/Array/for_of_2.js @@ -25,7 +25,7 @@ function TestChangeArrayIteratorNext() { return M2; } - var iter = ([])['@@iterator'](); + var iter = ([])[Symbol.iterator](); var iterProto = Object.getPrototypeOf(iter); var OldNext = iterProto.next; var NewNext = function () { diff --git a/js/src/tests/ecma_6/Array/for_of_3.js b/js/src/tests/ecma_6/Array/for_of_3.js index 9895da2f00a1..c90eb1f000ba 100644 --- a/js/src/tests/ecma_6/Array/for_of_3.js +++ b/js/src/tests/ecma_6/Array/for_of_3.js @@ -27,7 +27,7 @@ function TestIncreaseArrayLength() { return M2; } - var iter = ([])['@@iterator'](); + var iter = ([])[Symbol.iterator](); var iterProto = Object.getPrototypeOf(iter); var OldNext = iterProto.next; var NewNext = function () { diff --git a/js/src/tests/ecma_6/Array/for_of_4.js b/js/src/tests/ecma_6/Array/for_of_4.js index 1596038839d4..4572727a1fd3 100644 --- a/js/src/tests/ecma_6/Array/for_of_4.js +++ b/js/src/tests/ecma_6/Array/for_of_4.js @@ -26,7 +26,7 @@ function TestDecreaseArrayLength() { return M2; } - var iter = ([])['@@iterator'](); + var iter = ([])[Symbol.iterator](); var iterProto = Object.getPrototypeOf(iter); var OldNext = iterProto.next; var NewNext = function () { diff --git a/js/src/tests/ecma_6/Array/from_errors.js b/js/src/tests/ecma_6/Array/from_errors.js index ad494a3507c0..0bc08744b15a 100644 --- a/js/src/tests/ecma_6/Array/from_errors.js +++ b/js/src/tests/ecma_6/Array/from_errors.js @@ -132,12 +132,12 @@ assertEq(obj instanceof C, true); // It's a TypeError if the iterator's .next() method returns a primitive. for (var primitive of [undefined, null, 17]) { + var iterable = {}; + iterable[Symbol.iterator] = () => { + next: () => primitive + }; assertThrowsInstanceOf( - () => Array.from({ - "@@iterator": () => { - next: () => primitive - } - }), + () => Array.from(iterable), TypeError); } diff --git a/js/src/tests/ecma_6/Array/from_iterable.js b/js/src/tests/ecma_6/Array/from_iterable.js index 2fe3f890ad44..568181961271 100644 --- a/js/src/tests/ecma_6/Array/from_iterable.js +++ b/js/src/tests/ecma_6/Array/from_iterable.js @@ -8,7 +8,7 @@ // If an object has both .length and [@@iterator] properties, [@@iterator] is used. var a = ['a', 'e', 'i', 'o', 'u']; -a["@@iterator"] = function* () { +a[Symbol.iterator] = function* () { for (var i = 5; i--; ) yield this[i]; }; diff --git a/js/src/tests/ecma_6/Array/from_proxy.js b/js/src/tests/ecma_6/Array/from_proxy.js index 40505e8a83e9..5a5cc5b93711 100644 --- a/js/src/tests/ecma_6/Array/from_proxy.js +++ b/js/src/tests/ecma_6/Array/from_proxy.js @@ -6,19 +6,19 @@ var log = []; function LoggingProxy(target) { var h = { defineProperty: function (t, id) { - log.push("define " + id); + log.push("define", id); return undefined; }, has: function (t, id) { - log.push("has " + id); + log.push("has", id); return id in t; }, get: function (t, id) { - log.push("get " + id); + log.push("get", id); return t[id]; }, set: function (t, id, v) { - log.push("set " + id); + log.push("set", id); t[id] = v; } }; @@ -30,23 +30,25 @@ function LoggingProxy(target) { // but handler.set to set the length. LoggingProxy.from = Array.from; LoggingProxy.from([3, 4, 5]); -assertDeepEq(log, ["define 0", "define 1", "define 2", "set length"]); +assertDeepEq(log, ["define", "0", "define", "1", "define", "2", "set", "length"]); // When the argument passed to Array.from is a Proxy, Array.from // calls handler.get on it. log = []; assertDeepEq(Array.from(new LoggingProxy([3, 4, 5])), [3, 4, 5]); -assertDeepEq(log, ["get @@iterator", - "get length", "get 0", "get length", "get 1", "get length", "get 2", - "get length"]); +assertDeepEq(log, ["get", Symbol.iterator, + "get", "length", "get", "0", + "get", "length", "get", "1", + "get", "length", "get", "2", + "get", "length"]); // Array-like iteration only gets the length once. log = []; var arr = [5, 6, 7]; -arr["@@iterator"] = undefined; +arr[Symbol.iterator] = undefined; assertDeepEq(Array.from(new LoggingProxy(arr)), [5, 6, 7]); -assertDeepEq(log, ["get @@iterator", - "get length", "get 0", "get 1", "get 2"]); +assertDeepEq(log, ["get", Symbol.iterator, + "get", "length", "get", "0", "get", "1", "get", "2"]); if (typeof reportCompare === 'function') reportCompare(0, 0); diff --git a/js/src/tests/ecma_6/Array/from_string.js b/js/src/tests/ecma_6/Array/from_string.js index 892954621789..3ad19e253a68 100644 --- a/js/src/tests/ecma_6/Array/from_string.js +++ b/js/src/tests/ecma_6/Array/from_string.js @@ -11,11 +11,11 @@ assertDeepEq(Array.from(gclef), [gclef]); assertDeepEq(Array.from(gclef + " G"), [gclef, " ", "G"]); // Array.from on a string calls the @@iterator method. -String.prototype["@@iterator"] = function* () { yield 1; yield 2; }; +String.prototype[Symbol.iterator] = function* () { yield 1; yield 2; }; assertDeepEq(Array.from("anything"), [1, 2]); // If the iterator method is deleted, Strings are still arraylike. -delete String.prototype["@@iterator"]; +delete String.prototype[Symbol.iterator]; assertDeepEq(Array.from("works"), ['w', 'o', 'r', 'k', 's']); assertDeepEq(Array.from(gclef), ['\uD834', '\uDD1E']); diff --git a/js/src/tests/ecma_6/Generators/runtime.js b/js/src/tests/ecma_6/Generators/runtime.js index 4c4ece9c3b84..2c69a5c7e320 100644 --- a/js/src/tests/ecma_6/Generators/runtime.js +++ b/js/src/tests/ecma_6/Generators/runtime.js @@ -17,8 +17,6 @@ function* g() { yield 1; } var GeneratorFunctionPrototype = Object.getPrototypeOf(g); var GeneratorFunction = GeneratorFunctionPrototype.constructor; var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype; -// FIXME: This should be a symbol. -var std_iterator = "@@iterator"; // A generator function should have the same set of properties as any @@ -66,7 +64,7 @@ function TestGeneratorObjectPrototype() { assertEq(Object.getPrototypeOf((function*(){yield 1}).prototype), GeneratorObjectPrototype); - var expected_property_names = ["next", "throw", "constructor", std_iterator]; + var expected_property_names = ["next", "throw", "constructor"]; var found_property_names = Object.getOwnPropertyNames(GeneratorObjectPrototype); diff --git a/js/src/tests/ecma_6/Symbol/property-reflection.js b/js/src/tests/ecma_6/Symbol/property-reflection.js index c7e30ddb4d4e..43bd5dffdb38 100644 --- a/js/src/tests/ecma_6/Symbol/property-reflection.js +++ b/js/src/tests/ecma_6/Symbol/property-reflection.js @@ -67,9 +67,7 @@ if (typeof Symbol === "function") { assertEq(descs.hasOwnProperty(s2), true); assertEq(descs.hasOwnProperty(s3), false); assertEq([].hasOwnProperty(Symbol.iterator), false); - if (!("@@iterator" in [])) - throw new Error("Congratulations on implementing Symbol.iterator! Please update this test."); - assertEq(Array.prototype.hasOwnProperty(Symbol.iterator), false); // should be true + assertEq(Array.prototype.hasOwnProperty(Symbol.iterator), true); // Object.prototype.propertyIsEnumerable assertEq(n.propertyIsEnumerable(s1), true); diff --git a/js/src/tests/js1_8/regress/regress-469625-03.js b/js/src/tests/js1_8/regress/regress-469625-03.js index e48034f6a5cc..2c3047bc92b1 100644 --- a/js/src/tests/js1_8/regress/regress-469625-03.js +++ b/js/src/tests/js1_8/regress/regress-469625-03.js @@ -26,7 +26,7 @@ function test() var [a, b, [c0, c1]] = [x, x, x]; } - expect = 'TypeError: (intermediate value)[\'@@iterator\'](...).next(...).value is null'; + expect = 'TypeError: (intermediate value)[(intermediate value)](...).next(...).value is null'; actual = 'No Error'; try { diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h index a5f3aaf97233..a24ab0c89876 100644 --- a/js/src/vm/CommonPropertyNames.h +++ b/js/src/vm/CommonPropertyNames.h @@ -44,7 +44,6 @@ macro(count, count, "count") \ macro(currency, currency, "currency") \ macro(currencyDisplay, currencyDisplay, "currencyDisplay") \ - macro(std_iterator, std_iterator, "@@iterator") \ macro(DateTimeFormat, DateTimeFormat, "DateTimeFormat") \ macro(DateTimeFormatFormatGet, DateTimeFormatFormatGet, "Intl_DateTimeFormat_format_get") \ macro(decodeURI, decodeURI, "decodeURI") \ diff --git a/js/src/vm/Interpreter.cpp b/js/src/vm/Interpreter.cpp index 2216b6bdd566..d683f54ddae5 100644 --- a/js/src/vm/Interpreter.cpp +++ b/js/src/vm/Interpreter.cpp @@ -1133,6 +1133,7 @@ HandleError(JSContext *cx, InterpreterRegs ®s) #define PUSH_BOOLEAN(b) REGS.sp++->setBoolean(b) #define PUSH_DOUBLE(d) REGS.sp++->setDouble(d) #define PUSH_INT32(i) REGS.sp++->setInt32(i) +#define PUSH_SYMBOL(s) REGS.sp++->setSymbol(s) #define PUSH_STRING(s) do { REGS.sp++->setString(s); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0) #define PUSH_OBJECT(obj) do { REGS.sp++->setObject(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0) #define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); assertSameCompartmentDebugOnly(cx, REGS.sp[-1]); } while (0) @@ -1611,7 +1612,6 @@ CASE(EnableInterruptsPseudoOpcode) /* Various 1-byte no-ops. */ CASE(JSOP_NOP) CASE(JSOP_UNUSED2) -CASE(JSOP_UNUSED45) CASE(JSOP_UNUSED46) CASE(JSOP_UNUSED47) CASE(JSOP_UNUSED48) @@ -2755,6 +2755,10 @@ CASE(JSOP_TOSTRING) } END_CASE(JSOP_TOSTRING) +CASE(JSOP_SYMBOL) + PUSH_SYMBOL(cx->wellKnownSymbols().get(GET_UINT8(REGS.pc))); +END_CASE(JSOP_SYMBOL) + CASE(JSOP_OBJECT) { RootedObject &ref = rootObject0; diff --git a/js/src/vm/Opcodes.h b/js/src/vm/Opcodes.h index f0de8c52fc72..6984a4c6468e 100644 --- a/js/src/vm/Opcodes.h +++ b/js/src/vm/Opcodes.h @@ -416,7 +416,15 @@ */ \ macro(JSOP_DUPAT, 44, "dupat", NULL, 4, 0, 1, JOF_UINT24) \ \ - macro(JSOP_UNUSED45, 45, "unused45", NULL, 1, 0, 0, JOF_BYTE) \ + /* + * Push a well-known symbol onto the operand stack. + * Category: Literals + * Type: Constants + * Operands: uint8_t n, the JS::SymbolCode of the symbol to use + * Stack: => symbol + */ \ + macro(JSOP_SYMBOL, 45, "symbol", NULL, 2, 0, 1, JOF_UINT8) \ + \ macro(JSOP_UNUSED46, 46, "unused46", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED47, 47, "unused47", NULL, 1, 0, 0, JOF_BYTE) \ macro(JSOP_UNUSED48, 48, "unused48", NULL, 1, 0, 0, JOF_BYTE) \ diff --git a/js/src/vm/PIC.cpp b/js/src/vm/PIC.cpp index 455b7c40311e..46fbf946d736 100644 --- a/js/src/vm/PIC.cpp +++ b/js/src/vm/PIC.cpp @@ -44,8 +44,9 @@ js::ForOfPIC::Chain::initialize(JSContext *cx) // do set disabled_ now, and clear it later when we succeed. disabled_ = true; - // Look up '@@iterator' on Array.prototype, ensure it's a slotful shape. - Shape *iterShape = arrayProto->nativeLookup(cx, cx->names().std_iterator); + // Look up Array.prototype[@@iterator], ensure it's a slotful shape. + Shape *iterShape = + arrayProto->nativeLookup(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator)); if (!iterShape || !iterShape->hasSlot() || !iterShape->hasDefaultGetter()) return true; @@ -144,8 +145,8 @@ js::ForOfPIC::Chain::tryOptimizeArray(JSContext *cx, HandleObject array, bool *o if (!isOptimizableArray(array)) return true; - // Ensure array doesn't define '@@iterator' directly. - if (array->nativeLookup(cx, cx->names().std_iterator)) + // Ensure array doesn't define @@iterator directly. + if (array->nativeLookup(cx, SYMBOL_TO_JSID(cx->wellKnownSymbols().iterator))) return true; // Good to optimize now, create stub to add. @@ -198,7 +199,7 @@ js::ForOfPIC::Chain::isArrayStateStillSane() if (arrayProto_->lastProperty() != arrayProtoShape_) return false; - // Ensure that Array.prototype['@@iterator'] contains the + // Ensure that Array.prototype[@@iterator] contains the // canonical iterator function. if (arrayProto_->getSlot(arrayProtoIteratorSlot_) != canonicalIteratorFunc_) return false; diff --git a/js/src/vm/PIC.h b/js/src/vm/PIC.h index 8aa04f7706b2..ff76bfd95309 100644 --- a/js/src/vm/PIC.h +++ b/js/src/vm/PIC.h @@ -130,7 +130,7 @@ struct ForOfPIC /* * A ForOfPIC has only one kind of stub for now: one that holds the shape - * of an array object that does not override its '@@iterator' property. + * of an array object that does not override its @@iterator property. */ class Stub : public BaseStub { @@ -164,8 +164,8 @@ struct ForOfPIC * ArrayIterator.prototype's shape (arrayIteratorProtoShape_) * To ensure that an ArrayIterator.prototype has not been modified. * - * Array.prototype's slot number for '@@iterator' (arrayProtoIteratorSlot_) - * Array.prototype's canonical value for '@@iterator' (canonicalIteratorFunc_) + * Array.prototype's slot number for @@iterator (arrayProtoIteratorSlot_) + * Array.prototype's canonical value for @@iterator (canonicalIteratorFunc_) * To quickly retreive and ensure that the iterator constructor * stored in the slot has not changed. * @@ -182,7 +182,7 @@ struct ForOfPIC HeapPtrObject arrayIteratorProto_; // Shape of matching Array.prototype object, and slot containing - // the '@@iterator' for it, and the canonical value. + // the @@iterator for it, and the canonical value. HeapPtrShape arrayProtoShape_; uint32_t arrayProtoIteratorSlot_; HeapValue canonicalIteratorFunc_; diff --git a/js/src/vm/SelfHosting.cpp b/js/src/vm/SelfHosting.cpp index 5544a6ab816e..525f6673db50 100644 --- a/js/src/vm/SelfHosting.cpp +++ b/js/src/vm/SelfHosting.cpp @@ -1256,6 +1256,12 @@ CloneValue(JSContext *cx, HandleValue selfHostedValue, MutableHandleValue vp) if (!clone) return false; vp.setString(clone); + } else if (selfHostedValue.isSymbol()) { + // Well-known symbols are shared. + JS::Symbol *sym = selfHostedValue.toSymbol(); + MOZ_ASSERT(sym->isWellKnownSymbol()); + MOZ_ASSERT(cx->wellKnownSymbols().get(size_t(sym->code())) == sym); + vp.set(selfHostedValue); } else { MOZ_CRASH("Self-hosting CloneValue can't clone given value."); } diff --git a/js/src/vm/TypedArrayObject.cpp b/js/src/vm/TypedArrayObject.cpp index cb4535fcc84c..fdf2c2160b17 100644 --- a/js/src/vm/TypedArrayObject.cpp +++ b/js/src/vm/TypedArrayObject.cpp @@ -1590,7 +1590,7 @@ TypedArrayObject::setElement(TypedArrayObject &obj, uint32_t index, double d) #define IMPL_TYPED_ARRAY_STATICS(_typedArray) \ const JSFunctionSpec _typedArray##Object::jsfuncs[] = { \ - JS_SELF_HOSTED_FN("@@iterator", "ArrayValues", 0, 0), \ + JS_SELF_HOSTED_SYM_FN(iterator, "ArrayValues", 0, 0), \ JS_FN("subarray", _typedArray##Object::fun_subarray, 2, JSFUN_GENERIC_NATIVE), \ JS_FN("set", _typedArray##Object::fun_set, 2, JSFUN_GENERIC_NATIVE), \ JS_FN("copyWithin", _typedArray##Object::fun_copyWithin, 2, JSFUN_GENERIC_NATIVE), \ diff --git a/js/xpconnect/tests/chrome/test_xrayToJS.xul b/js/xpconnect/tests/chrome/test_xrayToJS.xul index d5fdff2aa673..8b13c77ed3c6 100644 --- a/js/xpconnect/tests/chrome/test_xrayToJS.xul +++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul @@ -174,14 +174,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681 ["length", "toSource", "toString", "toLocaleString", "join", "reverse", "sort", "push", "pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find", - "findIndex", "copyWithin", "fill", "@@iterator", "entries", "keys", "constructor"]; + "findIndex", "copyWithin", "fill", Symbol.iterator, "entries", "keys", "constructor"]; if (isNightlyBuild) { let pjsMethods = ['mapPar', 'reducePar', 'scanPar', 'scatterPar', 'filterPar']; gPrototypeProperties['Array'] = gPrototypeProperties['Array'].concat(pjsMethods); } for (var c of typedArrayClasses) { gPrototypeProperties[c] = ["constructor", "BYTES_PER_ELEMENT", "length", "buffer", - "byteLength", "byteOffset", "@@iterator", "subarray", "set", + "byteLength", "byteOffset", "Symbol.iterator", "subarray", "set", "copyWithin"]; } for (var c of errorObjectClasses) { @@ -211,9 +211,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681 let xrayProto = Object.getPrototypeOf(xray); let localProto = window[classname].prototype; is(Object.getOwnPropertyNames(localProto).sort().toSource(), - gPrototypeProperties[classname].sort().toSource(), + gPrototypeProperties[classname].filter(id => typeof id === "string").sort().toSource(), "A property on the " + classname + - " prototype has changed! You need a security audit from an XPConnect peer"); + " prototype has been changed! You need a security audit from an XPConnect peer"); + is(Object.getOwnPropertySymbols(localProto).map(uneval).sort().toSource(), + gPrototypeProperties[classname].filter(id => typeof id !== "string").map(uneval).sort().toSource(), + "A symbol-keyed property on the " + classname + + " prototype has been changed! You need a security audit from an XPConnect peer"); let protoProps = filterOut(Object.getOwnPropertyNames(localProto), propsToSkip).sort(); let protoCallables = protoProps.filter(name => Object.getOwnPropertyDescriptor(localProto, name).get || diff --git a/toolkit/modules/Promise-backend.js b/toolkit/modules/Promise-backend.js index 2390b01e650b..852df9c47b87 100644 --- a/toolkit/modules/Promise-backend.js +++ b/toolkit/modules/Promise-backend.js @@ -511,7 +511,7 @@ Promise.reject = function (aReason) */ Promise.all = function (aValues) { - if (aValues == null || typeof(aValues["@@iterator"]) != "function") { + if (aValues == null || typeof(aValues[Symbol.iterator]) != "function") { throw new Error("Promise.all() expects an iterable."); } @@ -562,7 +562,7 @@ Promise.all = function (aValues) */ Promise.race = function (aValues) { - if (aValues == null || typeof(aValues["@@iterator"]) != "function") { + if (aValues == null || typeof(aValues[Symbol.iterator]) != "function") { throw new Error("Promise.race() expects an iterable."); }