mirror of
https://github.com/servo/servo.git
synced 2025-08-01 19:50:30 +01:00
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:
commit
27f443fd00
12 changed files with 201 additions and 76 deletions
|
@ -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 = []
|
||||||
|
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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])
|
||||||
|
|
|
@ -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',
|
||||||
|
|
|
@ -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"):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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)
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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():
|
Loading…
Add table
Add a link
Reference in a new issue