Skip to content
Permalink
Browse files

Update webidl.py from upstream

  • Loading branch information...
Manishearth committed Feb 25, 2019
1 parent 4270032 commit 8f5db8a7e114ec9a6705da5284f9e5abc3bc7cd2
@@ -1,6 +1,6 @@
# 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
# 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. """

@@ -248,8 +248,14 @@ def __str__(self):
return self.QName()

def QName(self):
if self._name:
return self._name.QName() + "::"
# It's possible for us to be called before __init__ has been called, for
# 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 "::"

def ensureUnique(self, identifier, object):
@@ -327,6 +333,13 @@ def lookupIdentifier(self, identifier):
assert identifier.scope == self
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):
def __init__(self, location, scope, name):
@@ -504,8 +517,10 @@ def isExposedInWindow(self):
return 'Window' in self.exposureSet

def isExposedOnMainThread(self):
return (self.isExposedInWindow() or
self.isExposedInSystemGlobals())
return self.isExposedInWindow()

def isExposedOffMainThread(self):
return len(self.exposureSet - {'Window', 'FakeTestPrimaryGlobal'}) > 0

def isExposedInAnyWorker(self):
return len(self.getWorkerExposureSet()) > 0
@@ -516,9 +531,6 @@ def isExposedInWorkerDebugger(self):
def isExposedInAnyWorklet(self):
return len(self.getWorkletExposureSet()) > 0

def isExposedInSystemGlobals(self):
return 'BackstagePass' in self.exposureSet

def isExposedInSomeButNotAllWorkers(self):
"""
Returns true if the Exposed extended attribute for this interface
@@ -597,6 +609,34 @@ def _getDependentObjects(self):
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):
def __init__(self, location, name, members, nonPartialInterfaceOrNamespace):
assert isinstance(name, IDLUnresolvedIdentifier)
@@ -1322,7 +1362,6 @@ def checkDuplicateNames(member, name, attributeName):
for bindingAlias in member.bindingAliases:
checkDuplicateNames(member, bindingAlias, "BindingAlias")


# Conditional exposure makes no sense for interfaces with no
# interface object, unless they're navigator properties.
# And SecureContext makes sense for interfaces with no interface object,
@@ -1704,9 +1743,8 @@ def addExtendedAttributes(self, attrs):
self.globalNames = attr.args()
else:
self.globalNames = [self.identifier.name]
self.parentScope.globalNames.update(self.globalNames)
for globalName in self.globalNames:
self.parentScope.globalNameMapping[globalName].add(self.identifier.name)
self.parentScope.addIfaceGlobalNames(self.identifier.name,
self.globalNames)
self._isOnGlobalProtoChain = True
elif identifier == "PrimaryGlobal":
if not attr.noArguments():
@@ -1719,8 +1757,8 @@ def addExtendedAttributes(self, attrs):
self.parentScope.primaryGlobalAttr.location])
self.parentScope.primaryGlobalAttr = attr
self.parentScope.primaryGlobalName = self.identifier.name
self.parentScope.globalNames.add(self.identifier.name)
self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name)
self.parentScope.addIfaceGlobalNames(self.identifier.name,
[self.identifier.name])
self._isOnGlobalProtoChain = True
elif identifier == "SecureContext":
if not attr.noArguments():
@@ -1743,7 +1781,6 @@ def addExtendedAttributes(self, attrs):
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
identifier == "NonOrdinaryGetPrototypeOf" or
identifier == "Abstract" or
identifier == "Inline"):
# Known extended attributes that do not take values
@@ -1805,7 +1842,7 @@ def addExtendedAttributes(self, attrs):
if not attr.noArguments():
raise WebIDLError("[%s] must not have arguments" % identifier,
[attr.location])
elif identifier == "Pref":
elif identifier == "Pref" or identifier == "Func":
# Known extended attributes that take a string value
if not attr.hasValue():
raise WebIDLError("[%s] must have a value" % identifier,
@@ -1828,6 +1865,7 @@ def __init__(self, location, parentScope, name, parent, members):
self.parent = parent
self._finished = False
self.members = list(members)
self._partialDictionaries = []

IDLObjectWithScope.__init__(self, location, parentScope, name)

@@ -1864,6 +1902,11 @@ def finish(self, scope):
# looking at them.
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:
member.resolve(self)
if not member.isComplete():
@@ -1968,6 +2011,9 @@ def _getDependentObjects(self):
deps.add(self.parent)
return deps

def addPartialDictionary(self, partial):
assert self.identifier.name == partial.identifier.name
self._partialDictionaries.append(partial)

class IDLEnum(IDLObjectWithIdentifier):
def __init__(self, location, parentScope, name, values):
@@ -4333,7 +4379,7 @@ def handleExtendedAttribute(self, attr):
[attr.location, self.location])
elif (identifier == "CrossOriginReadable" or
identifier == "CrossOriginWritable"):
if not attr.noArguments() and identifier == "CrossOriginReadable":
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
[attr.location])
if self.isStatic():
@@ -4525,7 +4571,7 @@ def complete(self, scope):
if ((self.type.isDictionary() or
self.type.isUnion() and self.type.unroll().hasDictionaryType()) and
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.
self.defaultValue = IDLNullValue(self.location)
elif self.type.isAny():
@@ -5089,6 +5135,10 @@ def handleExtendedAttribute(self, attr):
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
[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":
if not attr.noArguments():
raise WebIDLError("[Pure] must take no arguments",
@@ -5293,7 +5343,7 @@ def t_INTEGER(self, t):
return 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')
return t

@@ -5518,9 +5568,10 @@ def p_CallbackRestOrInterface(self, p):
def handleNonPartialObject(self, location, identifier, constructor,
constructorArgs, nonPartialArgs):
"""
This handles non-partial objects (interfaces and namespaces) by
checking for an existing partial object, and promoting it to
non-partial as needed. The return value is the non-partial object.
This handles non-partial objects (interfaces, namespaces and
dictionaries) by checking for an existing partial object, and promoting
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
one: isKnownNonPartial.
@@ -5610,24 +5661,25 @@ def p_PartialDefinition(self, p):
"""
PartialDefinition : PartialInterface
| PartialNamespace
| PartialDictionary
"""
p[0] = p[1]

def handlePartialObject(self, location, identifier, nonPartialConstructor,
nonPartialConstructorArgs,
partialConstructorArgs):
"""
This handles partial objects (interfaces and namespaces) by checking for
an existing non-partial object, and adding ourselves to it as needed.
The return value is our partial object. For now we just use
IDLPartialInterfaceOrNamespace for partial objects.
This handles partial objects (interfaces, namespaces and dictionaries)
by checking for an existing non-partial object, and adding ourselves to
it as needed. The return value is our partial object. We use
IDLPartialInterfaceOrNamespace for partial interfaces or namespaces,
and IDLPartialDictionary for partial dictionaries.
nonPartialConstructorArgs are all the args for the non-partial
constructor except the last two: members and isKnownNonPartial.
partialConstructorArgs are the arguments for the
IDLPartialInterfaceOrNamespace constructor, except the last one (the
non-partial object).
partialConstructorArgs are the arguments for the partial object
constructor, except the last one (the non-partial object).
"""
# The name of the class starts with "IDL", so strip that off.
# Also, starts with a capital letter after that, so nix that
@@ -5652,9 +5704,19 @@ def handlePartialObject(self, location, identifier, nonPartialConstructor,
nonPartialObject = nonPartialConstructor(
# No members, False for isKnownNonPartial
*(nonPartialConstructorArgs + [[], False]))
partialInterface = IDLPartialInterfaceOrNamespace(
*(partialConstructorArgs + [nonPartialObject]))
return partialInterface

partialObject = None
if isinstance(nonPartialObject, IDLDictionary):
partialObject = IDLPartialDictionary(
*(partialConstructorArgs + [nonPartialObject]))
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):
"""
@@ -5682,6 +5744,19 @@ def p_PartialNamespace(self, p):
[location, self.globalScope(), identifier],
[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):
"""
Inheritance : COLON ScopedName
@@ -6894,16 +6969,13 @@ def __init__(self, outputdir='', lexer=None):
logger.reportGrammarErrors()

self._globalScope = IDLScope(BuiltinLocation("<Global Scope>"), None, None)

# To make our test harness work, pretend like we have a primary global already.
# Note that we _don't_ set _globalScope.primaryGlobalAttr,
# so we'll still be able to detect multiple PrimaryGlobal extended attributes.
self._globalScope.primaryGlobalName = "FakeTestPrimaryGlobal"
self._globalScope.globalNames.add("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._globalScope.addIfaceGlobalNames("FakeTestPrimaryGlobal", ["FakeTestPrimaryGlobal"])

self._installBuiltins(self._globalScope)
self._productions = []

@@ -1,12 +1,12 @@
--- WebIDL.py
+++ WebIDL.py
@@ -1744,7 +1744,8 @@
@@ -1786,7 +1786,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "ProbablyShortLivingWrapper" or
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
- identifier == "NonOrdinaryGetPrototypeOf"):
+ identifier == "NonOrdinaryGetPrototypeOf" or
- identifier == "WantsEventListenerHooks"):
+ identifier == "WantsEventListenerHooks" or
+ identifier == "Abstract"):
# Known extended attributes that do not take values
if not attr.noArguments():
raise WebIDLError("[%s] must take no arguments" % identifier,
raise WebIDLError("[%s] must take no arguments" % identifier,
@@ -1,22 +1,20 @@
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
@@ -2170,7 +2170,7 @@ class IDLUnresolvedType(IDLType):
@@ -2275,7 +2275,7 @@ class IDLUnresolvedType(IDLType):
return typedefType.complete(scope)
elif obj.isCallback() and not obj.isInterface():
assert self.name.name == obj.identifier.name
- return IDLCallbackType(self.location, obj)
+ return IDLCallbackType(obj.location, obj)

if self._promiseInnerType and not self._promiseInnerType.isComplete():
self._promiseInnerType = self._promiseInnerType.complete(scope)
@@ -6521,7 +6521,7 @@ class Parser(Tokenizer):
name = self.name.resolve(scope, None)
return IDLWrapperType(self.location, obj)
@@ -6688,7 +6688,7 @@ class Parser(Tokenizer):
type = IDLTypedefType(self.getLocation(p, 1), obj.innerType,
obj.identifier.name)
elif obj.isCallback() and not obj.isInterface():
- type = IDLCallbackType(self.getLocation(p, 1), obj)
+ type = IDLCallbackType(obj.location, obj)
else:
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
@@ -6823,7 +6823,8 @@ class Parser(Tokenizer):
@@ -6959,7 +6959,8 @@ class Parser(Tokenizer):
self.parser = yacc.yacc(module=self,
outputdir=outputdir,
tabmodule='webidlyacc',
@@ -1,9 +1,9 @@
--- WebIDL.py
+++ WebIDL.py
@@ -1695,7 +1695,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "ProbablyShortLivingObject" or
@@ -1787,7 +1787,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "NonOrdinaryGetPrototypeOf" or
identifier == "RunConstructorInCallerCompartment" or
identifier == "WantsEventListenerHooks" or
- identifier == "Abstract"):
+ identifier == "Abstract" or
+ identifier == "Inline"):
Oops, something went wrong.

0 comments on commit 8f5db8a

Please sign in to comment.
You can’t perform that action at this time.