aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen/parser/WebIDL.py
diff options
context:
space:
mode:
Diffstat (limited to 'components/script/dom/bindings/codegen/parser/WebIDL.py')
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py310
1 files changed, 190 insertions, 120 deletions
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index b934c21db5b..5e8b958e3de 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -554,9 +554,6 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def hasProbablyShortLivingWrapper(self):
return False
- def isNavigatorProperty(self):
- return False
-
def isSerializable(self):
return False
@@ -611,7 +608,7 @@ class IDLPartialInterfaceOrNamespace(IDLObject):
for attr in attrs:
identifier = attr.identifier()
- if identifier in ["Constructor", "NamedConstructor"]:
+ if identifier == "NamedConstructor":
self.propagatedExtendedAttrs.append(attr)
elif identifier == "SecureContext":
self._haveSecureContextExtendedAttribute = True
@@ -737,7 +734,7 @@ class IDLInterfaceOrInterfaceMixinOrNamespace(IDLObjectWithScope, IDLExposureMix
self.location = location
# Put the new members at the beginning
self.members = members + self.members
-
+
def addPartial(self, partial):
assert self.identifier.name == partial.identifier.name
self._partials.append(partial)
@@ -790,7 +787,7 @@ class IDLInterfaceMixin(IDLInterfaceOrInterfaceMixinOrNamespace):
def __str__(self):
return "Interface mixin '%s'" % self.identifier.name
-
+
def finish(self, scope):
if self._finished:
return
@@ -969,7 +966,11 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
(self.identifier.name,
self.parent.identifier.name),
[self.location])
- assert not parent or isinstance(parent, IDLInterface)
+ if parent and not isinstance(parent, IDLInterface):
+ raise WebIDLError("%s inherits from %s which is not an interface " %
+ (self.identifier.name,
+ self.parent.identifier.name),
+ [self.location, parent.location])
self.parent = parent
@@ -1076,11 +1077,34 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
ctor = self.ctor()
if ctor is not None:
- assert len(ctor._exposureGlobalNames) == 0
+ if not self.hasInterfaceObject():
+ raise WebIDLError(
+ "Can't have both a constructor and [NoInterfaceObject]",
+ [self.location, ctor.location])
+
+ if self.globalNames:
+ raise WebIDLError(
+ "Can't have both a constructor and [Global]",
+ [self.location, ctor.location])
+
+ assert(len(ctor._exposureGlobalNames) == 0 or
+ ctor._exposureGlobalNames == self._exposureGlobalNames)
ctor._exposureGlobalNames.update(self._exposureGlobalNames)
- ctor.finish(scope)
+ if ctor in self.members:
+ # constructor operation.
+ self.members.remove(ctor)
+ else:
+ # extended attribute. This can only happen with
+ # [HTMLConstructor] and this is the only way we can get into this
+ # code with len(ctor._exposureGlobalNames) !=
+ # self._exposureGlobalNames.
+ ctor.finish(scope)
for ctor in self.namedConstructors:
+ if self.globalNames:
+ raise WebIDLError(
+ "Can't have both a named constructor and [Global]",
+ [self.location, self.namedConstructors.location])
assert len(ctor._exposureGlobalNames) == 0
ctor._exposureGlobalNames.update(self._exposureGlobalNames)
ctor.finish(scope)
@@ -1462,12 +1486,11 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
# Conditional exposure makes no sense for interfaces with no
- # interface object, unless they're navigator properties.
+ # interface object.
# And SecureContext makes sense for interfaces with no interface object,
# since it is also propagated to interface members.
if (self.isExposedConditionally(exclusions=["SecureContext"]) and
- not self.hasInterfaceObject() and
- not self.isNavigatorProperty()):
+ not self.hasInterfaceObject()):
raise WebIDLError("Interface with no interface object is "
"exposed conditionally",
[self.location])
@@ -1640,39 +1663,6 @@ class IDLInterfaceOrNamespace(IDLInterfaceOrInterfaceMixinOrNamespace):
current = current.parent
return False
- def isNavigatorProperty(self):
- naviProp = self.getExtendedAttribute("NavigatorProperty")
- if not naviProp:
- return False
- assert len(naviProp) == 1
- assert isinstance(naviProp, list)
- assert len(naviProp[0]) != 0
- return True
-
- def getNavigatorProperty(self):
- naviProp = self.getExtendedAttribute("NavigatorProperty")
- if not naviProp:
- return None
- assert len(naviProp) == 1
- assert isinstance(naviProp, list)
- assert len(naviProp[0]) != 0
- conditionExtendedAttributes = self._extendedAttrDict.viewkeys() & IDLInterfaceOrNamespace.conditionExtendedAttributes
- attr = IDLAttribute(self.location,
- IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), naviProp[0]),
- IDLUnresolvedType(self.location, IDLUnresolvedIdentifier(self.location, self.identifier.name)),
- True,
- extendedAttrDict={ a: self._extendedAttrDict[a] for a in conditionExtendedAttributes },
- navigatorObjectGetter=True)
- attr._exposureGlobalNames = self._exposureGlobalNames
- # We're abusing Constant a little bit here, because we need Cached. The
- # getter will create a new object every time, but we're never going to
- # clear the cached value.
- extendedAttrs = [ IDLExtendedAttribute(self.location, ("Throws", )),
- IDLExtendedAttribute(self.location, ("Cached", )),
- IDLExtendedAttribute(self.location, ("Constant", )) ]
- attr.addExtendedAttributes(extendedAttrs)
- return attr
-
def hasChildInterfaces(self):
return self._hasChildInterfaces
@@ -1731,67 +1721,39 @@ class IDLInterface(IDLInterfaceOrNamespace):
raise WebIDLError("[NoInterfaceObject] must take no arguments",
[attr.location])
- if self.ctor():
- raise WebIDLError("Constructor and NoInterfaceObject are incompatible",
- [self.location])
-
self._noInterfaceObject = True
- elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
- if identifier == "Constructor" and not self.hasInterfaceObject():
- raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
- [self.location])
-
+ elif identifier == "NamedConstructor" or identifier == "HTMLConstructor":
if identifier == "NamedConstructor" and not attr.hasValue():
raise WebIDLError("NamedConstructor must either take an identifier or take a named argument list",
[attr.location])
- if identifier == "ChromeConstructor" and not self.hasInterfaceObject():
- raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
- [self.location])
-
if identifier == "HTMLConstructor":
- if not self.hasInterfaceObject():
- raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
- [self.location])
-
if not attr.noArguments():
raise WebIDLError(str(identifier) + " must take no arguments",
[attr.location])
- if self.globalNames:
- raise WebIDLError("[%s] must not be specified together with "
- "[Global]" % identifier,
- [self.location, attr.location])
-
args = attr.args() if attr.hasArgs() else []
retType = IDLWrapperType(self.location, self)
- if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
+ if identifier == "HTMLConstructor":
name = "constructor"
allowForbidden = True
else:
name = attr.value()
allowForbidden = False
- methodIdentifier = IDLUnresolvedIdentifier(self.location, name,
- allowForbidden=allowForbidden)
+ method = IDLConstructor(
+ attr.location, args, name,
+ htmlConstructor=(identifier == "HTMLConstructor"))
+ method.reallyInit(self)
- method = IDLMethod(self.location, methodIdentifier, retType,
- args, static=True,
- htmlConstructor=(identifier == "HTMLConstructor"))
- # Constructors are always NewObject and are always
- # assumed to be able to throw (since there's no way to
- # indicate otherwise) and never have any other
- # extended attributes.
+ # Are always assumed to be able to throw (since there's no way to
+ # indicate otherwise).
method.addExtendedAttributes(
- [IDLExtendedAttribute(self.location, ("NewObject",)),
- IDLExtendedAttribute(self.location, ("Throws",))])
- if identifier == "ChromeConstructor":
- method.addExtendedAttributes(
- [IDLExtendedAttribute(self.location, ("ChromeOnly",))])
+ [IDLExtendedAttribute(self.location, ("Throws",))])
- if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
+ if identifier == "HTMLConstructor":
method.resolve(self)
else:
# We need to detect conflicts for NamedConstructors across
@@ -1823,10 +1785,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
"an interface with inherited interfaces",
[attr.location, self.location])
elif identifier == "Global":
- if self.ctor() or self.namedConstructors:
- raise WebIDLError("[Global] cannot be specified on an "
- "interface with a constructor",
- [attr.location, self.location]);
if attr.hasValue():
self.globalNames = [attr.value()]
elif attr.hasArgs():
@@ -1896,7 +1854,6 @@ class IDLInterface(IDLInterfaceOrNamespace):
elif (identifier == "Pref" or
identifier == "JSImplementation" or
identifier == "HeaderFile" or
- identifier == "NavigatorProperty" or
identifier == "Func" or
identifier == "Deprecated"):
# Known extended attributes that take a string value
@@ -1923,6 +1880,17 @@ class IDLInterface(IDLInterfaceOrNamespace):
def isSerializable(self):
return self.getExtendedAttribute("Serializable")
+ def setNonPartial(self, location, parent, members):
+ # Before we do anything else, finish initializing any constructors that
+ # might be in "members", so we don't have partially-initialized objects
+ # hanging around. We couldn't do it before now because we needed to have
+ # to have the IDLInterface on hand to properly set the return type.
+ for member in members:
+ if isinstance(member, IDLConstructor):
+ member.reallyInit(self)
+
+ IDLInterfaceOrNamespace.setNonPartial(self, location, parent, members)
+
class IDLNamespace(IDLInterfaceOrNamespace):
def __init__(self, location, parentScope, name, members, isKnownNonPartial):
@@ -2193,6 +2161,7 @@ class IDLType(IDLObject):
'domstring',
'bytestring',
'usvstring',
+ 'jsstring',
'object',
'date',
'void',
@@ -2254,6 +2223,9 @@ class IDLType(IDLObject):
def isUSVString(self):
return False
+ def isJSString(self):
+ return False
+
def isVoid(self):
return self.name == "Void"
@@ -2479,6 +2451,9 @@ class IDLNullableType(IDLParametrizedType):
def isUSVString(self):
return self.inner.isUSVString()
+ def isJSString(self):
+ return self.inner.isJSString()
+
def isFloat(self):
return self.inner.isFloat()
@@ -2600,6 +2575,9 @@ class IDLSequenceType(IDLParametrizedType):
def isUSVString(self):
return False
+ def isJSString(self):
+ return False
+
def isVoid(self):
return False
@@ -2861,6 +2839,9 @@ class IDLTypedefType(IDLType):
def isUSVString(self):
return self.inner.isUSVString()
+ def isJSString(self):
+ return self.inner.isJSString()
+
def isVoid(self):
return self.inner.isVoid()
@@ -2991,6 +2972,9 @@ class IDLWrapperType(IDLType):
def isUSVString(self):
return False
+ def isJSString(self):
+ return False
+
def isVoid(self):
return False
@@ -3190,6 +3174,7 @@ class IDLBuiltinType(IDLType):
'domstring',
'bytestring',
'usvstring',
+ 'jsstring',
'object',
'date',
'void',
@@ -3227,6 +3212,7 @@ class IDLBuiltinType(IDLType):
Types.domstring: IDLType.Tags.domstring,
Types.bytestring: IDLType.Tags.bytestring,
Types.usvstring: IDLType.Tags.usvstring,
+ Types.jsstring: IDLType.Tags.jsstring,
Types.object: IDLType.Tags.object,
Types.date: IDLType.Tags.date,
Types.void: IDLType.Tags.void,
@@ -3311,7 +3297,8 @@ class IDLBuiltinType(IDLType):
def isString(self):
return (self._typeTag == IDLBuiltinType.Types.domstring or
self._typeTag == IDLBuiltinType.Types.bytestring or
- self._typeTag == IDLBuiltinType.Types.usvstring)
+ self._typeTag == IDLBuiltinType.Types.usvstring or
+ self._typeTag == IDLBuiltinType.Types.jsstring)
def isByteString(self):
return self._typeTag == IDLBuiltinType.Types.bytestring
@@ -3322,6 +3309,9 @@ class IDLBuiltinType(IDLType):
def isUSVString(self):
return self._typeTag == IDLBuiltinType.Types.usvstring
+ def isJSString(self):
+ return self._typeTag == IDLBuiltinType.Types.jsstring
+
def isInteger(self):
return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long
@@ -3524,6 +3514,9 @@ BuiltinTypes = {
IDLBuiltinType.Types.usvstring:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "USVString",
IDLBuiltinType.Types.usvstring),
+ IDLBuiltinType.Types.jsstring:
+ IDLBuiltinType(BuiltinLocation("<builtin type>"), "JSString",
+ IDLBuiltinType.Types.jsstring),
IDLBuiltinType.Types.object:
IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object",
IDLBuiltinType.Types.object),
@@ -3690,8 +3683,8 @@ class IDLValue(IDLObject):
# TreatNullAsEmpty is a different type for resolution reasons,
# however once you have a value it doesn't matter
return self
- elif self.type.isString() and type.isByteString():
- # Allow ByteStrings to use a default value like DOMString.
+ elif self.type.isString() and (type.isByteString() or type.isJSString()):
+ # Allow ByteStrings and JSStrings to use a default value like DOMString.
# No coercion is required as Codegen.py will handle the
# extra steps. We want to make sure that our string contains
# only valid characters, so we check that here.
@@ -4340,7 +4333,7 @@ class IDLConst(IDLInterfaceMember):
class IDLAttribute(IDLInterfaceMember):
def __init__(self, location, identifier, type, readonly, inherit=False,
static=False, stringifier=False, maplikeOrSetlike=None,
- extendedAttrDict=None, navigatorObjectGetter=False):
+ extendedAttrDict=None):
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Attr,
extendedAttrDict=extendedAttrDict)
@@ -4358,7 +4351,6 @@ class IDLAttribute(IDLInterfaceMember):
self.maplikeOrSetlike = maplikeOrSetlike
self.dependsOn = "Everything"
self.affects = "Everything"
- self.navigatorObjectGetter = navigatorObjectGetter
self.bindingAliases = []
if static and identifier.name == "prototype":
@@ -5239,7 +5231,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert argument.type.isComplete()
if ((argument.type.isDictionary() and
- argument.type.inner.canBeEmpty())or
+ argument.type.unroll().inner.canBeEmpty()) or
(argument.type.isUnion() and
argument.type.unroll().hasPossiblyEmptyDictionaryType())):
# Optional dictionaries and unions containing optional
@@ -5263,12 +5255,16 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
"must have a default value",
[argument.location])
- # An argument cannot be a Nullable Dictionary
- if argument.type.nullable():
- raise WebIDLError("An argument cannot be a nullable "
- "dictionary or nullable union "
- "containing a dictionary",
- [argument.location])
+ # An argument cannot be a nullable dictionary or a
+ # nullable union containing a dictionary.
+ if (argument.type.nullable() and
+ (argument.type.isDictionary() or
+ (argument.type.isUnion() and
+ argument.type.unroll().hasDictionaryType()))):
+ raise WebIDLError("An argument cannot be a nullable "
+ "dictionary or nullable union "
+ "containing a dictionary",
+ [argument.location])
# Only the last argument can be variadic
if variadicArgument:
@@ -5497,6 +5493,52 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
return deps
+class IDLConstructor(IDLMethod):
+ def __init__(self, location, args, name, htmlConstructor=False):
+ # We can't actually init our IDLMethod yet, because we do not know the
+ # return type yet. Just save the info we have for now and we will init
+ # it later.
+ self._initLocation = location
+ self._initArgs = args
+ self._initName = name
+ self._htmlConstructor = htmlConstructor
+ self._inited = False
+ self._initExtendedAttrs = []
+
+ def addExtendedAttributes(self, attrs):
+ if self._inited:
+ return IDLMethod.addExtendedAttributes(self, attrs)
+ self._initExtendedAttrs.extend(attrs)
+
+ def handleExtendedAttribute(self, attr):
+ identifier = attr.identifier()
+ if (identifier == "BinaryName" or
+ identifier == "ChromeOnly" or
+ identifier == "NewObject" or
+ identifier == "SecureContext" or
+ identifier == "Throws"):
+ IDLMethod.handleExtendedAttribute(self, attr)
+ else:
+ raise WebIDLError("Unknown extended attribute %s on method" % identifier,
+ [attr.location])
+
+ def reallyInit(self, parentInterface):
+ name = self._initName
+ location = self._initLocation
+ identifier = IDLUnresolvedIdentifier(location, name, allowForbidden=True)
+ retType = IDLWrapperType(parentInterface.location, parentInterface)
+ IDLMethod.__init__(self, location, identifier, retType, self._initArgs,
+ static=True, htmlConstructor=self._htmlConstructor)
+ self._inited = True;
+ # Propagate through whatever extended attributes we already had
+ self.addExtendedAttributes(self._initExtendedAttrs)
+ self._initExtendedAttrs = []
+ # Constructors are always NewObject. Whether they throw or not is
+ # indicated by [Throws] annotations in the usual way.
+ self.addExtendedAttributes(
+ [IDLExtendedAttribute(self.location, ("NewObject",))])
+
+
class IDLImplementsStatement(IDLObject):
def __init__(self, location, implementor, implementee):
IDLObject.__init__(self, location)
@@ -5712,6 +5754,7 @@ class Tokenizer(object):
"DOMString": "DOMSTRING",
"ByteString": "BYTESTRING",
"USVString": "USVSTRING",
+ "JSString": "JSSTRING",
"any": "ANY",
"boolean": "BOOLEAN",
"byte": "BYTE",
@@ -6076,7 +6119,7 @@ class Parser(Tokenizer):
def p_PartialInterfaceRest(self, p):
"""
- PartialInterfaceRest : IDENTIFIER LBRACE InterfaceMembers RBRACE SEMICOLON
+ PartialInterfaceRest : IDENTIFIER LBRACE PartialInterfaceMembers RBRACE SEMICOLON
"""
location = self.getLocation(p, 1)
identifier = IDLUnresolvedIdentifier(location, p[1])
@@ -6157,12 +6200,42 @@ class Parser(Tokenizer):
def p_InterfaceMember(self, p):
"""
- InterfaceMember : Const
- | AttributeOrOperationOrMaplikeOrSetlikeOrIterable
+ InterfaceMember : PartialInterfaceMember
+ | Constructor
"""
p[0] = p[1]
-
+ def p_Constructor(self, p):
+ """
+ Constructor : CONSTRUCTOR LPAREN ArgumentList RPAREN SEMICOLON
+ """
+ p[0] = IDLConstructor(self.getLocation(p, 1), p[3], "constructor")
+
+ def p_PartialInterfaceMembers(self, p):
+ """
+ PartialInterfaceMembers : ExtendedAttributeList PartialInterfaceMember PartialInterfaceMembers
+ """
+ p[0] = [p[2]]
+
+ assert not p[1] or p[2]
+ p[2].addExtendedAttributes(p[1])
+
+ p[0].extend(p[3])
+
+ def p_PartialInterfaceMembersEmpty(self, p):
+ """
+ PartialInterfaceMembers :
+ """
+ p[0] = []
+
+ def p_PartialInterfaceMember(self, p):
+ """
+ PartialInterfaceMember : Const
+ | AttributeOrOperationOrMaplikeOrSetlikeOrIterable
+ """
+ p[0] = p[1]
+
+
def p_MixinMembersEmpty(self, p):
"""
MixinMembers :
@@ -6778,7 +6851,9 @@ class Parser(Tokenizer):
"""
t = p[2]
assert isinstance(t, IDLType)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
+ # Arg names can be reserved identifiers
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3],
+ allowForbidden=True)
defaultValue = p[4]
@@ -6795,7 +6870,9 @@ class Parser(Tokenizer):
"""
t = p[1]
assert isinstance(t, IDLType)
- identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3])
+ # Arg names can be reserved identifiers
+ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3],
+ allowForbidden=True)
variadic = p[2]
@@ -6934,6 +7011,7 @@ class Parser(Tokenizer):
| DOMSTRING
| BYTESTRING
| USVSTRING
+ | JSSTRING
| ANY
| ATTRIBUTE
| BOOLEAN
@@ -7216,6 +7294,12 @@ class Parser(Tokenizer):
"""
p[0] = IDLBuiltinType.Types.usvstring
+ def p_BuiltinStringTypeJSString(self, p):
+ """
+ BuiltinStringType : JSSTRING
+ """
+ p[0] = IDLBuiltinType.Types.jsstring
+
def p_UnsignedIntegerTypeUnsigned(self, p):
"""
UnsignedIntegerType : UNSIGNED IntegerType
@@ -7443,23 +7527,9 @@ class Parser(Tokenizer):
for p in self._productions:
if isinstance(p, IDLInterface):
interfaceStatements.append(p)
- if p.identifier.name == "Navigator":
- navigatorInterface = p
iterableIteratorIface = None
for iface in interfaceStatements:
- navigatorProperty = iface.getNavigatorProperty()
- if navigatorProperty:
- # We're generating a partial interface to add a readonly
- # property to the Navigator interface for every interface
- # annotated with NavigatorProperty.
- partialInterface = IDLPartialInterfaceOrNamespace(
- iface.location,
- IDLUnresolvedIdentifier(iface.location, "Navigator"),
- [ navigatorProperty ],
- navigatorInterface)
- self._productions.append(partialInterface)
-
iterable = None
# We haven't run finish() on the interface yet, so we don't know
# whether our interface is maplike/setlike/iterable or not. This