mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-27 02:43:07 +00:00
Bug 918828, part 2 - Change iteration code to call iterable[Symbol.iterator]() rather than iterable["@@iterator"](). r=nbp.
--HG-- extra : rebase_source : 529d0cd48cd1993cd8cc648ac385ca12342ecfd1
This commit is contained in:
parent
1629fa04d9
commit
68b38c7094
@ -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
|
||||
|
@ -2662,7 +2662,7 @@ this.CustomizableUI = {
|
||||
* for (let window of CustomizableUI.windows) { ... }
|
||||
*/
|
||||
windows: {
|
||||
"@@iterator": function*() {
|
||||
*[Symbol.iterator]() {
|
||||
for (let [window,] of gBuildWindows)
|
||||
yield window;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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");
|
||||
|
@ -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");
|
||||
|
@ -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")
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
@ -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");
|
||||
|
@ -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)
|
||||
|
@ -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() : [];
|
||||
|
@ -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;
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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';
|
||||
|
@ -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);
|
||||
|
@ -5618,7 +5618,7 @@ JS::GetSymbolCode(Handle<Symbol*> 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)
|
||||
|
@ -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
|
||||
|
@ -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<T,impl>), 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),
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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 () {
|
||||
|
@ -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 () {
|
||||
|
@ -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 () {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
};
|
||||
|
@ -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);
|
||||
|
@ -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']);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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") \
|
||||
|
@ -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;
|
||||
|
@ -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) \
|
||||
|
@ -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;
|
||||
|
@ -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_;
|
||||
|
@ -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.");
|
||||
}
|
||||
|
@ -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), \
|
||||
|
@ -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 ||
|
||||
|
@ -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.");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user