mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 06:11:37 +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.isIterable() and
|
||||
maplikeOrSetlikeOrIterable.isValueIterator()):
|
||||
# Add our keys/values/entries
|
||||
# Add our keys/values/entries/forEach
|
||||
self.regular.append({
|
||||
"name": "keys",
|
||||
"methodInfo": False,
|
||||
@ -2317,6 +2317,15 @@ class MethodDefiner(PropertyDefiner):
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor)
|
||||
})
|
||||
self.regular.append({
|
||||
"name": "forEach",
|
||||
"methodInfo": False,
|
||||
"selfHostedName": "ArrayForEach",
|
||||
"length": 0,
|
||||
"flags": "JSPROP_ENUMERATE",
|
||||
"condition": PropertyDefiner.getControllingCondition(m,
|
||||
descriptor)
|
||||
})
|
||||
|
||||
if not static:
|
||||
stringifier = descriptor.operations['Stringifier']
|
||||
@ -15811,6 +15820,31 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||
using CGCallGenerator.
|
||||
"""
|
||||
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(
|
||||
"""
|
||||
typedef ${iterClass} itrType;
|
||||
|
@ -3617,6 +3617,17 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
|
||||
deps.add(self.valueType)
|
||||
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
|
||||
# (keys/values/entries/@@iterator) to an interface.
|
||||
class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
@ -3652,6 +3663,11 @@ class IDLIterable(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
self.addMethod("values", members, False, self.iteratorType,
|
||||
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):
|
||||
return not self.isPairIterator()
|
||||
|
||||
@ -3703,17 +3719,8 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
|
||||
affectsNothing=True, isIteratorAlias=self.isSetlike())
|
||||
|
||||
# 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],
|
||||
foreachArguments)
|
||||
self.getForEachArguments())
|
||||
|
||||
def getKeyArg():
|
||||
return IDLArgument(self.location,
|
||||
|
@ -45,8 +45,8 @@ def WebIDLTest(parser, harness):
|
||||
prefix + " - Interface failed but not as a WebIDLError exception: %s" % e)
|
||||
|
||||
iterableMembers = [(x, WebIDL.IDLMethod) for x in ["entries", "keys",
|
||||
"values"]]
|
||||
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has", "forEach"]] +
|
||||
"values", "forEach"]]
|
||||
setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has"]] +
|
||||
[("__setlike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||
iterableMembers)
|
||||
setROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
@ -62,7 +62,7 @@ def WebIDLTest(parser, harness):
|
||||
"__clear",
|
||||
"__delete"]] +
|
||||
setRWMembers)
|
||||
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has", "forEach"]] +
|
||||
mapROMembers = ([(x, WebIDL.IDLMethod) for x in ["get", "has"]] +
|
||||
[("__maplike", WebIDL.IDLMaplikeOrSetlike)] +
|
||||
iterableMembers)
|
||||
mapROMembers.extend([("size", WebIDL.IDLAttribute)])
|
||||
|
@ -14,7 +14,8 @@
|
||||
|
||||
base_properties = [["entries", "function", 0],
|
||||
["keys", "function", 0],
|
||||
["values", "function", 0]]
|
||||
["values", "function", 0],
|
||||
["forEach", "function", 1]]
|
||||
var testExistence = function testExistence(prefix, obj, properties) {
|
||||
for (var [name, type, args] of properties) {
|
||||
// Properties are somewhere up the proto chain, hasOwnProperty won't work
|
||||
@ -58,6 +59,8 @@
|
||||
"IterableSingle: Should be using %ArrayIterator% for 'entries'");
|
||||
is(itr.values, itr[Symbol.iterator],
|
||||
"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 values = [...itr.values()];
|
||||
var entries = [...itr.entries()];
|
||||
@ -81,6 +84,23 @@
|
||||
is(entry.value[1], entries[i][1],
|
||||
"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 value = value_itr.next();
|
||||
var entry = entries_itr.next();
|
||||
@ -124,6 +144,23 @@
|
||||
is(entry.value[1], entries[i][1],
|
||||
"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 value = value_itr.next();
|
||||
var entry = entries_itr.next()
|
||||
|
Loading…
Reference in New Issue
Block a user