Auto merge of #22934 - Manishearth:update-webidl, r=nox

Update WebIDL.py

I'm working on getting [attributes on types landed in upstream webidl](https://bugzilla.mozilla.org/show_bug.cgi?id=1359269). In preparation for that, I'd like to update WebIDL.py and deal with all the conflicts first so that updating for that bug is easier.

(This PR doesn't need to be reviewed and landed right now, I can just roll it into the PR for implementing attributes on types, but I suspect it would be easier to land this first)

Probably should squash before landing, the steps are separated out for ease of review.

r? @nox @jdm

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/22934)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2019-03-01 15:44:43 -05:00 committed by GitHub
commit 27f443fd00
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 201 additions and 76 deletions

View file

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
""" A WebIDL parser. """ """ A WebIDL parser. """
@ -248,8 +248,14 @@ class IDLScope(IDLObject):
return self.QName() return self.QName()
def QName(self): def QName(self):
if self._name: # It's possible for us to be called before __init__ has been called, for
return self._name.QName() + "::" # the IDLObjectWithScope case. In that case, self._name won't be set yet.
if hasattr(self, "_name"):
name = self._name
else:
name = None
if name:
return name.QName() + "::"
return "::" return "::"
def ensureUnique(self, identifier, object): def ensureUnique(self, identifier, object):
@ -327,6 +333,13 @@ class IDLScope(IDLObject):
assert identifier.scope == self assert identifier.scope == self
return self._lookupIdentifier(identifier) return self._lookupIdentifier(identifier)
def addIfaceGlobalNames(self, interfaceName, globalNames):
"""Record the global names (from |globalNames|) that can be used in
[Exposed] to expose things in a global named |interfaceName|"""
self.globalNames.update(globalNames)
for name in globalNames:
self.globalNameMapping[name].add(interfaceName)
class IDLIdentifier(IDLObject): class IDLIdentifier(IDLObject):
def __init__(self, location, scope, name): def __init__(self, location, scope, name):
@ -504,8 +517,10 @@ class IDLExposureMixins():
return 'Window' in self.exposureSet return 'Window' in self.exposureSet
def isExposedOnMainThread(self): def isExposedOnMainThread(self):
return (self.isExposedInWindow() or return self.isExposedInWindow()
self.isExposedInSystemGlobals())
def isExposedOffMainThread(self):
return len(self.exposureSet - {'Window', 'FakeTestPrimaryGlobal'}) > 0
def isExposedInAnyWorker(self): def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0 return len(self.getWorkerExposureSet()) > 0
@ -516,9 +531,6 @@ class IDLExposureMixins():
def isExposedInAnyWorklet(self): def isExposedInAnyWorklet(self):
return len(self.getWorkletExposureSet()) > 0 return len(self.getWorkletExposureSet()) > 0
def isExposedInSystemGlobals(self):
return 'BackstagePass' in self.exposureSet
def isExposedInSomeButNotAllWorkers(self): def isExposedInSomeButNotAllWorkers(self):
""" """
Returns true if the Exposed extended attribute for this interface Returns true if the Exposed extended attribute for this interface
@ -597,6 +609,34 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
return set() return set()
class IDLPartialDictionary(IDLObject):
def __init__(self, location, name, members, nonPartialDictionary):
assert isinstance(name, IDLUnresolvedIdentifier)
IDLObject.__init__(self, location)
self.identifier = name
self.members = members
self._nonPartialDictionary = nonPartialDictionary
self._finished = False
nonPartialDictionary.addPartialDictionary(self)
def addExtendedAttributes(self, attrs):
pass
def finish(self, scope):
if self._finished:
return
self._finished = True
# Need to make sure our non-partial dictionary gets
# finished so it can report cases when we only have partial
# dictionaries.
self._nonPartialDictionary.finish(scope)
def validate(self):
pass
class IDLPartialInterfaceOrNamespace(IDLObject): class IDLPartialInterfaceOrNamespace(IDLObject):
def __init__(self, location, name, members, nonPartialInterfaceOrNamespace): def __init__(self, location, name, members, nonPartialInterfaceOrNamespace):
assert isinstance(name, IDLUnresolvedIdentifier) assert isinstance(name, IDLUnresolvedIdentifier)
@ -1322,7 +1362,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
for bindingAlias in member.bindingAliases: for bindingAlias in member.bindingAliases:
checkDuplicateNames(member, bindingAlias, "BindingAlias") checkDuplicateNames(member, bindingAlias, "BindingAlias")
# Conditional exposure makes no sense for interfaces with no # Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties. # interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object, # And SecureContext makes sense for interfaces with no interface object,
@ -1704,9 +1743,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.globalNames = attr.args() self.globalNames = attr.args()
else: else:
self.globalNames = [self.identifier.name] self.globalNames = [self.identifier.name]
self.parentScope.globalNames.update(self.globalNames) self.parentScope.addIfaceGlobalNames(self.identifier.name,
for globalName in self.globalNames: self.globalNames)
self.parentScope.globalNameMapping[globalName].add(self.identifier.name)
self._isOnGlobalProtoChain = True self._isOnGlobalProtoChain = True
elif identifier == "PrimaryGlobal": elif identifier == "PrimaryGlobal":
if not attr.noArguments(): if not attr.noArguments():
@ -1719,8 +1757,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
self.parentScope.primaryGlobalAttr.location]) self.parentScope.primaryGlobalAttr.location])
self.parentScope.primaryGlobalAttr = attr self.parentScope.primaryGlobalAttr = attr
self.parentScope.primaryGlobalName = self.identifier.name self.parentScope.primaryGlobalName = self.identifier.name
self.parentScope.globalNames.add(self.identifier.name) self.parentScope.addIfaceGlobalNames(self.identifier.name,
self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name) [self.identifier.name])
self._isOnGlobalProtoChain = True self._isOnGlobalProtoChain = True
elif identifier == "SecureContext": elif identifier == "SecureContext":
if not attr.noArguments(): if not attr.noArguments():
@ -1743,7 +1781,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or identifier == "WantsEventListenerHooks" or
identifier == "NonOrdinaryGetPrototypeOf" or
identifier == "Abstract" or identifier == "Abstract" or
identifier == "Inline"): identifier == "Inline"):
# Known extended attributes that do not take values # Known extended attributes that do not take values
@ -1805,7 +1842,7 @@ class IDLNamespace(IDLInterfaceOrNamespace):
if not attr.noArguments(): if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier, raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location]) [attr.location])
elif identifier == "Pref": elif identifier == "Pref" or identifier == "Func":
# Known extended attributes that take a string value # Known extended attributes that take a string value
if not attr.hasValue(): if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier, raise WebIDLError("[%s] must have a value" % identifier,
@ -1828,6 +1865,7 @@ class IDLDictionary(IDLObjectWithScope):
self.parent = parent self.parent = parent
self._finished = False self._finished = False
self.members = list(members) self.members = list(members)
self._partialDictionaries = []
IDLObjectWithScope.__init__(self, location, parentScope, name) IDLObjectWithScope.__init__(self, location, parentScope, name)
@ -1864,6 +1902,11 @@ class IDLDictionary(IDLObjectWithScope):
# looking at them. # looking at them.
self.parent.finish(scope) self.parent.finish(scope)
# Now go ahead and merge in our partial dictionaries.
for partial in self._partialDictionaries:
partial.finish(scope)
self.members.extend(partial.members)
for member in self.members: for member in self.members:
member.resolve(self) member.resolve(self)
if not member.isComplete(): if not member.isComplete():
@ -1968,6 +2011,9 @@ class IDLDictionary(IDLObjectWithScope):
deps.add(self.parent) deps.add(self.parent)
return deps return deps
def addPartialDictionary(self, partial):
assert self.identifier.name == partial.identifier.name
self._partialDictionaries.append(partial)
class IDLEnum(IDLObjectWithIdentifier): class IDLEnum(IDLObjectWithIdentifier):
def __init__(self, location, parentScope, name, values): def __init__(self, location, parentScope, name, values):
@ -4333,7 +4379,7 @@ class IDLAttribute(IDLInterfaceMember):
[attr.location, self.location]) [attr.location, self.location])
elif (identifier == "CrossOriginReadable" or elif (identifier == "CrossOriginReadable" or
identifier == "CrossOriginWritable"): identifier == "CrossOriginWritable"):
if not attr.noArguments() and identifier == "CrossOriginReadable": if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier, raise WebIDLError("[%s] must take no arguments" % identifier,
[attr.location]) [attr.location])
if self.isStatic(): if self.isStatic():
@ -4525,7 +4571,7 @@ class IDLArgument(IDLObjectWithIdentifier):
if ((self.type.isDictionary() or if ((self.type.isDictionary() or
self.type.isUnion() and self.type.unroll().hasDictionaryType()) and self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
self.optional and not self.defaultValue and not self.variadic): self.optional and not self.defaultValue and not self.variadic):
# Default optional non-variadic dictionaries to null, # Default optional non-variadic dictionary arguments to null,
# for simplicity, so the codegen doesn't have to special-case this. # for simplicity, so the codegen doesn't have to special-case this.
self.defaultValue = IDLNullValue(self.location) self.defaultValue = IDLNullValue(self.location)
elif self.type.isAny(): elif self.type.isAny():
@ -5089,6 +5135,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
if not attr.noArguments(): if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier, raise WebIDLError("[%s] must take no arguments" % identifier,
[attr.location]) [attr.location])
if identifier == "CrossOriginCallable" and self.isStatic():
raise WebIDLError("[CrossOriginCallable] is only allowed on non-static "
"attributes"
[attr.location, self.location])
elif identifier == "Pure": elif identifier == "Pure":
if not attr.noArguments(): if not attr.noArguments():
raise WebIDLError("[Pure] must take no arguments", raise WebIDLError("[Pure] must take no arguments",
@ -5293,7 +5343,7 @@ class Tokenizer(object):
return t return t
def t_IDENTIFIER(self, t): def t_IDENTIFIER(self, t):
r'[A-Z_a-z][0-9A-Z_a-z-]*' r'[_-]?[A-Za-z][0-9A-Z_a-z-]*'
t.type = self.keywords.get(t.value, 'IDENTIFIER') t.type = self.keywords.get(t.value, 'IDENTIFIER')
return t return t
@ -5518,9 +5568,10 @@ class Parser(Tokenizer):
def handleNonPartialObject(self, location, identifier, constructor, def handleNonPartialObject(self, location, identifier, constructor,
constructorArgs, nonPartialArgs): constructorArgs, nonPartialArgs):
""" """
This handles non-partial objects (interfaces and namespaces) by This handles non-partial objects (interfaces, namespaces and
checking for an existing partial object, and promoting it to dictionaries) by checking for an existing partial object, and promoting
non-partial as needed. The return value is the non-partial object. it to non-partial as needed. The return value is the non-partial
object.
constructorArgs are all the args for the constructor except the last constructorArgs are all the args for the constructor except the last
one: isKnownNonPartial. one: isKnownNonPartial.
@ -5610,6 +5661,7 @@ class Parser(Tokenizer):
""" """
PartialDefinition : PartialInterface PartialDefinition : PartialInterface
| PartialNamespace | PartialNamespace
| PartialDictionary
""" """
p[0] = p[1] p[0] = p[1]
@ -5617,17 +5669,17 @@ class Parser(Tokenizer):
nonPartialConstructorArgs, nonPartialConstructorArgs,
partialConstructorArgs): partialConstructorArgs):
""" """
This handles partial objects (interfaces and namespaces) by checking for This handles partial objects (interfaces, namespaces and dictionaries)
an existing non-partial object, and adding ourselves to it as needed. by checking for an existing non-partial object, and adding ourselves to
The return value is our partial object. For now we just use it as needed. The return value is our partial object. We use
IDLPartialInterfaceOrNamespace for partial objects. IDLPartialInterfaceOrNamespace for partial interfaces or namespaces,
and IDLPartialDictionary for partial dictionaries.
nonPartialConstructorArgs are all the args for the non-partial nonPartialConstructorArgs are all the args for the non-partial
constructor except the last two: members and isKnownNonPartial. constructor except the last two: members and isKnownNonPartial.
partialConstructorArgs are the arguments for the partialConstructorArgs are the arguments for the partial object
IDLPartialInterfaceOrNamespace constructor, except the last one (the constructor, except the last one (the non-partial object).
non-partial object).
""" """
# The name of the class starts with "IDL", so strip that off. # The name of the class starts with "IDL", so strip that off.
# Also, starts with a capital letter after that, so nix that # Also, starts with a capital letter after that, so nix that
@ -5652,9 +5704,19 @@ class Parser(Tokenizer):
nonPartialObject = nonPartialConstructor( nonPartialObject = nonPartialConstructor(
# No members, False for isKnownNonPartial # No members, False for isKnownNonPartial
*(nonPartialConstructorArgs + [[], False])) *(nonPartialConstructorArgs + [[], False]))
partialInterface = IDLPartialInterfaceOrNamespace(
partialObject = None
if isinstance(nonPartialObject, IDLDictionary):
partialObject = IDLPartialDictionary(
*(partialConstructorArgs + [nonPartialObject])) *(partialConstructorArgs + [nonPartialObject]))
return partialInterface elif isinstance(nonPartialObject, (IDLInterface, IDLNamespace)):
partialObject = IDLPartialInterfaceOrNamespace(
*(partialConstructorArgs + [nonPartialObject]))
else:
raise WebIDLError("Unknown partial object type %s" %
type(partialObject))
return partialObject
def p_PartialInterface(self, p): def p_PartialInterface(self, p):
""" """
@ -5682,6 +5744,19 @@ class Parser(Tokenizer):
[location, self.globalScope(), identifier], [location, self.globalScope(), identifier],
[location, identifier, members]) [location, identifier, members])
def p_PartialDictionary(self, p):
"""
PartialDictionary : DICTIONARY IDENTIFIER LBRACE DictionaryMembers RBRACE SEMICOLON
"""
location = self.getLocation(p, 1)
identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2])
members = p[4]
p[0] = self.handlePartialObject(
location, identifier, IDLDictionary,
[location, self.globalScope(), identifier],
[location, identifier, members])
def p_Inheritance(self, p): def p_Inheritance(self, p):
""" """
Inheritance : COLON ScopedName Inheritance : COLON ScopedName
@ -6894,16 +6969,13 @@ class Parser(Tokenizer):
logger.reportGrammarErrors() logger.reportGrammarErrors()
self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None) self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)
# To make our test harness work, pretend like we have a primary global already. # To make our test harness work, pretend like we have a primary global already.
# Note that we _don't_ set _globalScope.primaryGlobalAttr, # Note that we _don't_ set _globalScope.primaryGlobalAttr,
# so we'll still be able to detect multiple PrimaryGlobal extended attributes. # so we'll still be able to detect multiple PrimaryGlobal extended attributes.
self._globalScope.primaryGlobalName = "FakeTestPrimaryGlobal" self._globalScope.primaryGlobalName = "FakeTestPrimaryGlobal"
self._globalScope.globalNames.add("FakeTestPrimaryGlobal") self._globalScope.addIfaceGlobalNames("FakeTestPrimaryGlobal", ["FakeTestPrimaryGlobal"])
self._globalScope.globalNameMapping["FakeTestPrimaryGlobal"].add("FakeTestPrimaryGlobal")
# And we add the special-cased "System" global name, which
# doesn't have any corresponding interfaces.
self._globalScope.globalNames.add("System")
self._globalScope.globalNameMapping["System"].add("BackstagePass")
self._installBuiltins(self._globalScope) self._installBuiltins(self._globalScope)
self._productions = [] self._productions = []

View file

@ -1,11 +1,11 @@
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -1744,7 +1744,8 @@ @@ -1786,7 +1786,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "ProbablyShortLivingWrapper" or
identifier == "LegacyUnenumerableNamedProperties" or identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or - identifier == "WantsEventListenerHooks"):
- identifier == "NonOrdinaryGetPrototypeOf"): + identifier == "WantsEventListenerHooks" or
+ identifier == "NonOrdinaryGetPrototypeOf" or
+ identifier == "Abstract"): + identifier == "Abstract"):
# Known extended attributes that do not take values # Known extended attributes that do not take values
if not attr.noArguments(): if not attr.noArguments():

View file

@ -1,17 +1,15 @@
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index da32340..81c52b7 100644
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType): @@ -2275,7 +2275,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope) return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface(): elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj) - return IDLCallbackType(self.location, obj)
+ return IDLCallbackType(obj.location, obj) + return IDLCallbackType(obj.location, obj)
if self._promiseInnerType and not self._promiseInnerType.isComplete(): name = self.name.resolve(scope, None)
self._promiseInnerType = self._promiseInnerType.complete(scope) return IDLWrapperType(self.location, obj)
@@ -6521,7 +6521,7 @@ class Parser(Tokenizer): @@ -6688,7 +6688,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType, type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name) obj.identifier.name)
elif obj.isCallback() and not obj.isInterface(): elif obj.isCallback() and not obj.isInterface():
@ -19,4 +17,4 @@ index da32340..81c52b7 100644
+ type = IDLCallbackType(obj.location, obj) + type = IDLCallbackType(obj.location, obj)
else: else:
type = IDLWrapperType(self.getLocation(p, 1), p[1]) type = IDLWrapperType(self.getLocation(p, 1), p[1])
p[0] = self.handleModifiers(type, p[2]) p[0] = self.handleNullable(type, p[2])

View file

@ -1,6 +1,6 @@
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -6823,7 +6823,8 @@ class Parser(Tokenizer): @@ -6959,7 +6959,8 @@ class Parser(Tokenizer):
self.parser = yacc.yacc(module=self, self.parser = yacc.yacc(module=self,
outputdir=outputdir, outputdir=outputdir,
tabmodule='webidlyacc', tabmodule='webidlyacc',

View file

@ -1,9 +1,9 @@
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -1695,7 +1695,8 @@ class IDLInterface(IDLInterfaceOrNamespace): @@ -1787,7 +1787,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "ProbablyShortLivingObject" or
identifier == "LegacyUnenumerableNamedProperties" or identifier == "LegacyUnenumerableNamedProperties" or
identifier == "NonOrdinaryGetPrototypeOf" or identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
- identifier == "Abstract"): - identifier == "Abstract"):
+ identifier == "Abstract" or + identifier == "Abstract" or
+ identifier == "Inline"): + identifier == "Inline"):

View file

@ -26,6 +26,31 @@ def WebIDLTest(parser, harness):
harness.check(dict2.members[1].identifier.name, "child", harness.check(dict2.members[1].identifier.name, "child",
"'a' really comes before 'c'") "'a' really comes before 'c'")
# Test partial dictionary.
parser = parser.reset();
parser.parse("""
dictionary A {
long c;
long g;
};
partial dictionary A {
long h;
long d;
};
""")
results = parser.finish()
dict1 = results[0];
harness.check(len(dict1.members), 4, "Dict1 has four members")
harness.check(dict1.members[0].identifier.name, "c",
"c should be first")
harness.check(dict1.members[1].identifier.name, "d",
"d should come after c")
harness.check(dict1.members[2].identifier.name, "g",
"g should come after d")
harness.check(dict1.members[3].identifier.name, "h",
"h should be last")
# Now reset our parser # Now reset our parser
parser = parser.reset() parser = parser.reset()
threw = False threw = False
@ -42,6 +67,24 @@ def WebIDLTest(parser, harness):
harness.ok(threw, "Should not allow name duplication in a dictionary") harness.ok(threw, "Should not allow name duplication in a dictionary")
# Test no name duplication across normal and partial dictionary.
parser = parser.reset();
threw = False
try:
parser.parse("""
dictionary A {
long prop = 5;
};
partial dictionary A {
long prop;
};
""")
results = parser.finish()
except:
threw = True
harness.ok(threw, "Should not allow name duplication across normal and partial dictionary")
# Now reset our parser again # Now reset our parser again
parser = parser.reset() parser = parser.reset()
threw = False threw = False

View file

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code): def should_throw(parser, harness, message, code):
parser = parser.reset(); parser = parser.reset();

View file

@ -1,6 +1,6 @@
# This Source Code Form is subject to the terms of the Mozilla Public # This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
def should_throw(parser, harness, message, code): def should_throw(parser, harness, message, code):
parser = parser.reset(); parser = parser.reset();

View file

@ -0,0 +1,12 @@
--- WebIDL.py
+++ WebIDL.py
@@ -4570,8 +4570,7 @@ class IDLArgument(IDLObjectWithIdentifier):
if ((self.type.isDictionary() or
self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
- self.optional and not self.defaultValue and not self.variadic and
- not self.dictionaryMember):
+ self.optional and not self.defaultValue and not self.variadic):
# Default optional non-variadic dictionary arguments to null,
# for simplicity, so the codegen doesn't have to special-case this.
self.defaultValue = IDLNullValue(self.location)

View file

@ -1,22 +1,22 @@
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -2481,10 +2481,18 @@ class IDLUnionType(IDLType): @@ -2613,10 +2613,18 @@ class IDLUnionType(IDLType):
return type.name return type.name
for (i, type) in enumerate(self.memberTypes): for (i, type) in enumerate(self.memberTypes):
- if not type.isComplete():
+ # Exclude typedefs because if given "typedef (B or C) test", + # Exclude typedefs because if given "typedef (B or C) test",
+ # we want AOrTest, not AOrBOrC + # we want AOrTest, not AOrBOrC
+ if not type.isComplete() and not isinstance(type, IDLTypedefType): + if not type.isComplete() and not isinstance(type, IDLTypedefType):
+ self.memberTypes[i] = type.complete(scope) self.memberTypes[i] = type.complete(scope)
+
+ self.name = "Or".join(typeName(type) for type in self.memberTypes) self.name = "Or".join(typeName(type) for type in self.memberTypes)
+ +
+ # We do this again to complete the typedef types + # We do this again to complete the typedef types
+ for (i, type) in enumerate(self.memberTypes): + for (i, type) in enumerate(self.memberTypes):
if not type.isComplete(): + if not type.isComplete():
self.memberTypes[i] = type.complete(scope) + self.memberTypes[i] = type.complete(scope)
+
- self.name = "Or".join(typeName(type) for type in self.memberTypes)
self.flatMemberTypes = list(self.memberTypes) self.flatMemberTypes = list(self.memberTypes)
i = 0 i = 0
while i < len(self.flatMemberTypes): while i < len(self.flatMemberTypes):

View file

@ -5,6 +5,7 @@ patch < pref-main-thread.patch
patch < callback-location.patch patch < callback-location.patch
patch < union-typedef.patch patch < union-typedef.patch
patch < inline.patch patch < inline.patch
patch < undo-dictionary-optional.patch
wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz wget https://hg.mozilla.org/mozilla-central/archive/tip.tar.gz/dom/bindings/parser/tests/ -O tests.tar.gz
rm -r tests rm -r tests

View file

@ -1,26 +1,25 @@
--- WebIDL.py --- WebIDL.py
+++ WebIDL.py +++ WebIDL.py
@@ -1239,12 +1239,6 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): @@ -1362,12 +1362,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
alias, for bindingAlias in member.bindingAliases:
[member.location, m.location]) checkDuplicateNames(member, bindingAlias, "BindingAlias")
- if (self.getExtendedAttribute("Pref") and -
- self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])): - if self.getExtendedAttribute("Pref") and self.isExposedOffMainThread():
- raise WebIDLError("[Pref] used on an interface that is not %s-only" % - raise WebIDLError("[Pref] used on an interface that is not "
- self.parentScope.primaryGlobalName, - "main-thread-only",
- [self.location]) - [self.location])
- -
# Conditional exposure makes no sense for interfaces with no # Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties. # interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object, # And SecureContext makes sense for interfaces with no interface object,
@@ -3459,12 +3453,6 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): @@ -3619,11 +3613,6 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
IDLExposureMixins.finish(self, scope) IDLExposureMixins.finish(self, scope)
def validate(self): def validate(self):
- if (self.getExtendedAttribute("Pref") and - if self.getExtendedAttribute("Pref") and self.isExposedOffMainThread():
- self.exposureSet != set([self._globalScope.primaryGlobalName])):
- raise WebIDLError("[Pref] used on an interface member that is not " - raise WebIDLError("[Pref] used on an interface member that is not "
- "%s-only" % self._globalScope.primaryGlobalName, - "main-thread-only",
- [self.location]) - [self.location])
- -
if self.isAttr() or self.isMethod(): if self.isAttr() or self.isMethod():