diff options
Diffstat (limited to 'components/script/dom/bindings/codegen/parser/WebIDL.py')
-rw-r--r-- | components/script/dom/bindings/codegen/parser/WebIDL.py | 310 |
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 |