mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 1216751 part 4. Implement forEach for iterable interfaces. r=qdot
This commit is contained in:
parent
ac58157b15
commit
6f458fb1f3
@ -2289,7 +2289,7 @@ class MethodDefiner(PropertyDefiner):
|
|||||||
maplikeOrSetlikeOrIterable and
|
maplikeOrSetlikeOrIterable and
|
||||||
maplikeOrSetlikeOrIterable.isIterable() and
|
maplikeOrSetlikeOrIterable.isIterable() and
|
||||||
maplikeOrSetlikeOrIterable.isValueIterator()):
|
maplikeOrSetlikeOrIterable.isValueIterator()):
|
||||||
# Add our keys/values/entries
|
# Add our keys/values/entries/forEach
|
||||||
self.regular.append({
|
self.regular.append({
|
||||||
"name": "keys",
|
"name": "keys",
|
||||||
"methodInfo": False,
|
"methodInfo": False,
|
||||||
@ -2317,6 +2317,15 @@ class MethodDefiner(PropertyDefiner):
|
|||||||
"condition": PropertyDefiner.getControllingCondition(m,
|
"condition": PropertyDefiner.getControllingCondition(m,
|
||||||
descriptor)
|
descriptor)
|
||||||
})
|
})
|
||||||
|
self.regular.append({
|
||||||
|
"name": "forEach",
|
||||||
|
"methodInfo": False,
|
||||||
|
"selfHostedName": "ArrayForEach",
|
||||||
|
"length": 0,
|
||||||
|
"flags": "JSPROP_ENUMERATE",
|
||||||
|
"condition": PropertyDefiner.getControllingCondition(m,
|
||||||
|
descriptor)
|
||||||
|
})
|
||||||
|
|
||||||
if not static:
|
if not static:
|
||||||
stringifier = descriptor.operations['Stringifier']
|
stringifier = descriptor.operations['Stringifier']
|
||||||
@ -15811,6 +15820,31 @@ class CGIterableMethodGenerator(CGGeneric):
|
|||||||
using CGCallGenerator.
|
using CGCallGenerator.
|
||||||
"""
|
"""
|
||||||
def __init__(self, descriptor, iterable, methodName):
|
def __init__(self, descriptor, iterable, methodName):
|
||||||
|
if methodName == "forEach":
|
||||||
|
CGGeneric.__init__(self, fill(
|
||||||
|
"""
|
||||||
|
if (!JS::IsCallable(arg0)) {
|
||||||
|
ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "Argument 1 of ${ifaceName}.forEach");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
JS::AutoValueArray<3> callArgs(cx);
|
||||||
|
callArgs[2].setObject(*obj);
|
||||||
|
JS::Rooted<JS::Value> ignoredReturnVal(cx);
|
||||||
|
for (size_t i = 0; i < self->GetIterableLength(); ++i) {
|
||||||
|
if (!ToJSValue(cx, self->GetValueAtIndex(i), callArgs[0])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ToJSValue(cx, self->GetKeyAtIndex(i), callArgs[1])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs),
|
||||||
|
&ignoredReturnVal)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""",
|
||||||
|
ifaceName=descriptor.interface.identifier.name))
|
||||||
|
return
|
||||||
CGGeneric.__init__(self, fill(
|
CGGeneric.__init__(self, fill(
|
||||||
"""
|
"""
|
||||||
typedef ${iterClass} itrType;
|
typedef ${iterClass} itrType;
|
||||||
|
@ -3617,6 +3617,17 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
|||||||
deps.add(self.valueType)
|
deps.add(self.valueType)
|
||||||
return deps
|
return deps
|
||||||
|
|
||||||
|
def getForEachArguments(self):
|
||||||
|
return [IDLArgument(self.location,
|
||||||
|
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||||
|
"callback"),
|
||||||
|
BuiltinTypes[IDLBuiltinType.Types.object]),
|
||||||
|
IDLArgument(self.location,
|
||||||
|
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
||||||
|
"thisArg"),
|
||||||
|
BuiltinTypes[IDLBuiltinType.Types.any],
|
||||||
|
optional=True)]
|
||||||
|
|
||||||
# Iterable adds ES6 iterator style functions and traits
|
# Iterable adds ES6 iterator style functions and traits
|
||||||
# (keys/values/entries/@@iterator) to an interface.
|
# (keys/values/entries/@@iterator) to an interface.
|
||||||
class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||||
@ -3652,6 +3663,11 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
|||||||
self.addMethod("values", members, False, self.iteratorType,
|
self.addMethod("values", members, False, self.iteratorType,
|
||||||
affectsNothing=True, newObject=True)
|
affectsNothing=True, newObject=True)
|
||||||
|
|
||||||
|
# void forEach(callback(valueType, keyType), optional any thisArg)
|
||||||
|
self.addMethod("forEach", members, False,
|
||||||
|
BuiltinTypes[IDLBuiltinType.Types.void],
|
||||||
|
self.getForEachArguments())
|
||||||
|
|
||||||
def isValueIterator(self):
|
def isValueIterator(self):
|
||||||
return not self.isPairIterator()
|
return not self.isPairIterator()
|
||||||
|
|
||||||
@ -3703,17 +3719,8 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
|||||||
affectsNothing=True, isIteratorAlias=self.isSetlike())
|
affectsNothing=True, isIteratorAlias=self.isSetlike())
|
||||||
|
|
||||||
# void forEach(callback(valueType, keyType), thisVal)
|
# void forEach(callback(valueType, keyType), thisVal)
|
||||||
foreachArguments = [IDLArgument(self.location,
|
|
||||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
|
||||||
"callback"),
|
|
||||||
BuiltinTypes[IDLBuiltinType.Types.object]),
|
|
||||||
IDLArgument(self.location,
|
|
||||||
IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"),
|
|
||||||
"thisArg"),
|
|
||||||
BuiltinTypes[IDLBuiltinType.Types.any],
|
|
||||||
optional=True)]
|
|
||||||
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
self.addMethod("forEach", members, False, BuiltinTypes[IDLBuiltinType.Types.void],
|
||||||
foreachArguments)
|
self.getForEachArguments())
|
||||||
|
|
||||||
def getKeyArg():
|
def getKeyArg():
|
||||||
return IDLArgument(self.location,
|
return IDLArgument(self.location,
|
||||||
|
@ -45,8 +45,8 @@ def WebIDLTest(parser, harness):
|
|||||||
prefix + " - Interface failed but not as a WebIDLError exception: %s" % e)
|
prefix + " - Interface failed but not as a WebIDLError exception: %s" % e)
|
||||||
|
|
||||||
iterableMembers = [(x, WebIDL.IDLMethod) for x in ["entries", "keys",
|
iterableMembers = [(x, WebIDL.IDLMethod) for x in ["entries", "keys",
|
||||||
"values"]]
|
"values", "forEach"]]
|
||||||
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has", "forEach"]] +
|
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has"]] +
|
||||||
[("__setlike", WebIDL.IDLMaplikeOrSetlike)] +
|
[("__setlike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||||
iterableMembers)
|
iterableMembers)
|
||||||
setROMembers.extend([("size", WebIDL.IDLAttribute)])
|
setROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||||
@ -62,7 +62,7 @@ def WebIDLTest(parser, harness):
|
|||||||
"__clear",
|
"__clear",
|
||||||
"__delete"]] +
|
"__delete"]] +
|
||||||
setRWMembers)
|
setRWMembers)
|
||||||
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has", "forEach"]] +
|
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has"]] +
|
||||||
[("__maplike", WebIDL.IDLMaplikeOrSetlike)] +
|
[("__maplike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||||
iterableMembers)
|
iterableMembers)
|
||||||
mapROMembers.extend([("size", WebIDL.IDLAttribute)])
|
mapROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||||
|
@ -14,7 +14,8 @@
|
|||||||
|
|
||||||
base_properties = [["entries", "function", 0],
|
base_properties = [["entries", "function", 0],
|
||||||
["keys", "function", 0],
|
["keys", "function", 0],
|
||||||
["values", "function", 0]]
|
["values", "function", 0],
|
||||||
|
["forEach", "function", 1]]
|
||||||
var testExistence = function testExistence(prefix, obj, properties) {
|
var testExistence = function testExistence(prefix, obj, properties) {
|
||||||
for (var [name, type, args] of properties) {
|
for (var [name, type, args] of properties) {
|
||||||
// Properties are somewhere up the proto chain, hasOwnProperty won't work
|
// Properties are somewhere up the proto chain, hasOwnProperty won't work
|
||||||
@ -58,6 +59,8 @@
|
|||||||
"IterableSingle: Should be using %ArrayIterator% for 'entries'");
|
"IterableSingle: Should be using %ArrayIterator% for 'entries'");
|
||||||
is(itr.values, itr[Symbol.iterator],
|
is(itr.values, itr[Symbol.iterator],
|
||||||
"IterableSingle: Should be using @@iterator for 'values'");
|
"IterableSingle: Should be using @@iterator for 'values'");
|
||||||
|
is(itr.forEach, Array.prototype.forEach,
|
||||||
|
"IterableSingle: Should be using %ArrayIterator% for 'forEach'");
|
||||||
var keys = [...itr.keys()];
|
var keys = [...itr.keys()];
|
||||||
var values = [...itr.values()];
|
var values = [...itr.values()];
|
||||||
var entries = [...itr.entries()];
|
var entries = [...itr.entries()];
|
||||||
@ -81,6 +84,23 @@
|
|||||||
is(entry.value[1], entries[i][1],
|
is(entry.value[1], entries[i][1],
|
||||||
"IterableSingle: Entry iterator value 1 should match destructuring " + i);
|
"IterableSingle: Entry iterator value 1 should match destructuring " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var callsToForEachCallback = 0;
|
||||||
|
var thisArg = {};
|
||||||
|
itr.forEach(function(value, index, obj) {
|
||||||
|
is(index, callsToForEachCallback,
|
||||||
|
`IterableSingle: Should have the right index at ${callsToForEachCallback} calls to forEach callback`);
|
||||||
|
is(value, values[index],
|
||||||
|
`IterableSingle: Should have the right value at ${callsToForEachCallback} calls to forEach callback`);
|
||||||
|
is(this, thisArg,
|
||||||
|
"IterableSingle: Should have the right this value for forEach callback");
|
||||||
|
is(obj, itr,
|
||||||
|
"IterableSingle: Should have the right third arg for forEach callback");
|
||||||
|
++callsToForEachCallback;
|
||||||
|
}, thisArg);
|
||||||
|
is(callsToForEachCallback, 3,
|
||||||
|
"IterableSingle: Should have right total number of calls to forEach callback");
|
||||||
|
|
||||||
var key = key_itr.next();
|
var key = key_itr.next();
|
||||||
var value = value_itr.next();
|
var value = value_itr.next();
|
||||||
var entry = entries_itr.next();
|
var entry = entries_itr.next();
|
||||||
@ -124,6 +144,23 @@
|
|||||||
is(entry.value[1], entries[i][1],
|
is(entry.value[1], entries[i][1],
|
||||||
"IterableDouble: Entry iterator value 1 should match destructuring " + i);
|
"IterableDouble: Entry iterator value 1 should match destructuring " + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callsToForEachCallback = 0;
|
||||||
|
thisArg = {};
|
||||||
|
itr.forEach(function(value, key, obj) {
|
||||||
|
is(key, keys[callsToForEachCallback],
|
||||||
|
`IterableDouble: Should have the right key at ${callsToForEachCallback} calls to forEach callback`);
|
||||||
|
is(value, values[callsToForEachCallback],
|
||||||
|
`IterableDouble: Should have the right value at ${callsToForEachCallback} calls to forEach callback`);
|
||||||
|
is(this, thisArg,
|
||||||
|
"IterableDouble: Should have the right this value for forEach callback");
|
||||||
|
is(obj, itr,
|
||||||
|
"IterableSingle: Should have the right third arg for forEach callback");
|
||||||
|
++callsToForEachCallback;
|
||||||
|
}, thisArg);
|
||||||
|
is(callsToForEachCallback, 3,
|
||||||
|
"IterableDouble: Should have right total number of calls to forEach callback");
|
||||||
|
|
||||||
var key = key_itr.next();
|
var key = key_itr.next();
|
||||||
var value = value_itr.next();
|
var value = value_itr.next();
|
||||||
var entry = entries_itr.next()
|
var entry = entries_itr.next()
|
||||||
|
Loading…
Reference in New Issue
Block a user