From b1debd2d49c1b74a26ca8e30df7808bc5f867225 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Mon, 19 Oct 2015 20:17:39 -0400 Subject: [PATCH] Bug 1215755. Change the Web IDL parser to just put a next() method in iterator interfaces instead of using an additional IterableIterator interface. Fix up the other test failures in test_interface_maplikesetlikeiterable.py while I'm here. r=qdot --- dom/bindings/Bindings.conf | 4 --- dom/bindings/parser/WebIDL.py | 30 ++++++++-------- .../test_interface_maplikesetlikeiterable.py | 36 ++++++++++++------- dom/webidl/IterableIterator.webidl | 8 ----- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index 1ccd06b6c957..f79de248864d 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -700,10 +700,6 @@ DOMInterfaces = { 'notflattened': True }, -'IterableIterator': { - 'skipGen': True -}, - 'KeyEvent': { 'concrete': False }, diff --git a/dom/bindings/parser/WebIDL.py b/dom/bindings/parser/WebIDL.py index ee83ad33fc88..c0860584e228 100644 --- a/dom/bindings/parser/WebIDL.py +++ b/dom/bindings/parser/WebIDL.py @@ -740,7 +740,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): "interface that already has %s " "declaration" % (member.maplikeOrSetlikeOrIterableType, - self.maplikeOrSetlike.maplikeOrSetlikeOrIterableType), + self.maplikeOrSetlikeOrIterable.maplikeOrSetlikeOrIterableType), [self.maplikeOrSetlikeOrIterable.location, member.location]) self.maplikeOrSetlikeOrIterable = member @@ -6567,6 +6567,7 @@ class Parser(Tokenizer): interfaceStatements = [p for p in self._productions if isinstance(p, IDLInterface)] + iterableIteratorIface = None for iface in interfaceStatements: iterable = None # We haven't run finish() on the interface yet, so we don't know @@ -6578,33 +6579,30 @@ class Parser(Tokenizer): iterable = m break if iterable: + def simpleExtendedAttr(str): + return IDLExtendedAttribute(iface.location, (str, )) + nextMethod = IDLMethod( + iface.location, + IDLUnresolvedIdentifier(iface.location, "next"), + BuiltinTypes[IDLBuiltinType.Types.object], []) + nextMethod.addExtendedAttributes([simpleExtendedAttr("Throws")]) itr_ident = IDLUnresolvedIdentifier(iface.location, iface.identifier.name + "Iterator") itr_iface = IDLInterface(iface.location, self.globalScope(), - itr_ident, None, [], + itr_ident, None, [nextMethod], isKnownNonPartial=True) - itr_iface.addExtendedAttributes([IDLExtendedAttribute(iface.location, - ("NoInterfaceObject", ))]) + itr_iface.addExtendedAttributes([simpleExtendedAttr("NoInterfaceObject")]) # Make sure the exposure set for the iterator interface is the # same as the exposure set for the iterable interface, because # we're going to generate methods on the iterable that return # instances of the iterator. itr_iface._exposureGlobalNames = set(iface._exposureGlobalNames) - # Always append generated iterable interfaces and their - # matching implements statements after the interface they're a - # member of, otherwise nativeType generation won't work - # correctly. + # Always append generated iterable interfaces after the + # interface they're a member of, otherwise nativeType generation + # won't work correctly. itr_iface.iterableInterface = iface self._productions.append(itr_iface) iterable.iteratorType = IDLWrapperType(iface.location, itr_iface) - itrPlaceholder = IDLIdentifierPlaceholder(iface.location, - IDLUnresolvedIdentifier(iface.location, - "IterableIterator")) - implements = IDLImplementsStatement(iface.location, - IDLIdentifierPlaceholder(iface.location, - itr_ident), - itrPlaceholder) - self._productions.append(implements) # Then, finish all the IDLImplementsStatements. In particular, we # have to make sure we do those before we do the IDLInterfaces. diff --git a/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py b/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py index d9126dbae302..ed6f4c40a482 100644 --- a/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py +++ b/dom/bindings/parser/tests/test_interface_maplikesetlikeiterable.py @@ -10,20 +10,24 @@ def WebIDLTest(parser, harness): "%s - Should have production count %d" % (prefix, numProductions)) harness.ok(isinstance(results[0], WebIDL.IDLInterface), "%s - Should be an IDLInterface" % (prefix)) - harness.check(len(results[0].members), len(expectedMembers), - "%s - Should be %d members" % (prefix, - len(expectedMembers))) + # Make a copy, since we plan to modify it + expectedMembers = list(expectedMembers) for m in results[0].members: name = m.identifier.name if (name, type(m)) in expectedMembers: harness.ok(True, "%s - %s - Should be a %s" % (prefix, name, type(m))) - elif isinstance(m, WebIDL.IDLMaplikeOrSetlike): - harness.ok(True, "%s - %s - Should be a MaplikeOrSetlike" % - (prefix, name)) + expectedMembers.remove((name, type(m))) else: harness.ok(False, "%s - %s - Unknown symbol of type %s" % (prefix, name, type(m))) + # A bit of a hoop because we can't generate the error string if we pass + if len(expectedMembers) == 0: + harness.ok(True, "Found all the members") + else: + harness.ok(False, + "Expected member not found: %s of type %s" % + (expectedMembers[0][0], expectedMembers[0][1])) return results def shouldFail(prefix, iface): @@ -38,11 +42,11 @@ def WebIDLTest(parser, harness): prefix + " - Interface failed as expected") except Exception, e: harness.ok(False, - prefix + " - Interface failed but not as a WebIDLError exception") + 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"]] + + setROMembers = ([(x, WebIDL.IDLMethod) for x in ["has", "forEach"]] + [("__setlike", WebIDL.IDLMaplikeOrSetlike)] + iterableMembers) setROMembers.extend([("size", WebIDL.IDLAttribute)]) @@ -58,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", "forEach"]] + [("__maplike", WebIDL.IDLMaplikeOrSetlike)] + iterableMembers) mapROMembers.extend([("size", WebIDL.IDLAttribute)]) @@ -70,6 +74,10 @@ def WebIDLTest(parser, harness): "__delete"]] + mapRWMembers) + # OK, now that we've used iterableMembers to set up the above, append + # __iterable to it for the iterable<> case. + iterableMembers.append(("__iterable", WebIDL.IDLIterable)) + disallowedIterableNames = ["keys", "entries", "values"] disallowedMemberNames = ["forEach", "has", "size"] + disallowedIterableNames mapDisallowedMemberNames = ["get"] + disallowedMemberNames @@ -86,14 +94,18 @@ def WebIDLTest(parser, harness): interface Foo1 { iterable; }; - """, iterableMembers) + """, iterableMembers, + # numProductions == 2 because of the generated iterator iface, + numProductions=2) shouldPass("Iterable (key and value)", """ interface Foo1 { iterable; }; - """, iterableMembers) + """, iterableMembers, + # numProductions == 2 because of the generated iterator iface, + numProductions=2) shouldPass("Maplike (readwrite)", """ @@ -574,5 +586,5 @@ def WebIDLTest(parser, harness): if m.identifier.name in ["clear", "set", "delete"]: harness.ok(m.isMethod(), "%s should be a method" % m.identifier.name) harness.check(m.maxArgCount, 4, "%s should have 4 arguments" % m.identifier.name) - harness.ok(not m.isMaplikeOrSetlikeMethod(), + harness.ok(not m.isMaplikeOrSetlikeOrIterableMethod(), "%s should not be a maplike/setlike function" % m.identifier.name) diff --git a/dom/webidl/IterableIterator.webidl b/dom/webidl/IterableIterator.webidl index b71c95965798..633b67b1edb5 100644 --- a/dom/webidl/IterableIterator.webidl +++ b/dom/webidl/IterableIterator.webidl @@ -4,14 +4,6 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ -[NoInterfaceObject, - Exposed=(Window,Worker,System)] -interface IterableIterator -{ - [Throws] - object next(); -}; - dictionary IterableKeyOrValueResult { any value; boolean done = false;