diff options
Diffstat (limited to 'components/script/dom/bindings/codegen/parser')
3 files changed, 336 insertions, 103 deletions
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py index 7474f56baa2..a40c563ae35 100644 --- a/components/script/dom/bindings/codegen/parser/WebIDL.py +++ b/components/script/dom/bindings/codegen/parser/WebIDL.py @@ -204,7 +204,7 @@ class IDLObject(object): deps.add(self.filename()) for d in self._getDependentObjects(): - deps = deps.union(d.getDeps(visited)) + deps.update(d.getDeps(visited)) return deps @@ -338,7 +338,10 @@ class IDLUnresolvedIdentifier(IDLObject): assert len(name) > 0 - if name[:2] == "__" and name != "__content" and name != "___noSuchMethod__" and not allowDoubleUnderscore: + if name == "__noSuchMethod__": + raise WebIDLError("__noSuchMethod__ is deprecated", [location]) + + if name[:2] == "__" and name != "__content" and not allowDoubleUnderscore: raise WebIDLError("Identifiers beginning with __ are reserved", [location]) if name[0] == '_' and not allowDoubleUnderscore: @@ -448,7 +451,59 @@ class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): obj = self.identifier.resolve(scope, None) return scope.lookupIdentifier(obj) -class IDLExternalInterface(IDLObjectWithIdentifier): +class IDLExposureMixins(): + def __init__(self, location): + # _exposureGlobalNames are the global names listed in our [Exposed] + # extended attribute. exposureSet is the exposure set as defined in the + # Web IDL spec: it contains interface names. + self._exposureGlobalNames = set() + self.exposureSet = set() + self._location = location + self._globalScope = None + + def finish(self, scope): + assert scope.parentScope is None + self._globalScope = scope + + # Verify that our [Exposed] value, if any, makes sense. + for globalName in self._exposureGlobalNames: + if globalName not in scope.globalNames: + raise WebIDLError("Unknown [Exposed] value %s" % globalName, + [self._location]) + + if len(self._exposureGlobalNames) == 0: + self._exposureGlobalNames.add(scope.primaryGlobalName) + + globalNameSetToExposureSet(scope, self._exposureGlobalNames, + self.exposureSet) + + def isExposedInWindow(self): + return 'Window' in self.exposureSet + + def isExposedInAnyWorker(self): + return len(self.getWorkerExposureSet()) > 0 + + def isExposedInSystemGlobals(self): + return 'BackstagePass' in self.exposureSet + + def isExposedInSomeButNotAllWorkers(self): + """ + Returns true if the Exposed extended attribute for this interface + exposes it in some worker globals but not others. The return value does + not depend on whether the interface is exposed in Window or System + globals. + """ + if not self.isExposedInAnyWorker(): + return False + workerScopes = self.parentScope.globalNameMapping["Worker"] + return len(workerScopes.difference(self.exposureSet)) > 0 + + def getWorkerExposureSet(self): + workerScopes = self._globalScope.globalNameMapping["Worker"] + return workerScopes.intersection(self.exposureSet) + + +class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins): def __init__(self, location, parentScope, identifier): raise WebIDLError("Servo does not support external interfaces.", [self.location]) @@ -511,7 +566,7 @@ def globalNameSetToExposureSet(globalScope, nameSet, exposureSet): for name in nameSet: exposureSet.update(globalScope.globalNameMapping[name]) -class IDLInterface(IDLObjectWithScope): +class IDLInterface(IDLObjectWithScope, IDLExposureMixins): def __init__(self, location, parentScope, name, parent, members, isKnownNonPartial): assert isinstance(parentScope, IDLScope) @@ -546,13 +601,9 @@ class IDLInterface(IDLObjectWithScope): self.totalMembersInSlots = 0 # Tracking of the number of own own members we have in slots self._ownMembersInSlots = 0 - # _exposureGlobalNames are the global names listed in our [Exposed] - # extended attribute. exposureSet is the exposure set as defined in the - # Web IDL spec: it contains interface names. - self._exposureGlobalNames = set() - self.exposureSet = set() IDLObjectWithScope.__init__(self, location, parentScope, name) + IDLExposureMixins.__init__(self, location) if isKnownNonPartial: self.setNonPartial(location, parent, members) @@ -592,17 +643,7 @@ class IDLInterface(IDLObjectWithScope): "declaration" % self.identifier.name, [self.location]) - # Verify that our [Exposed] value, if any, makes sense. - for globalName in self._exposureGlobalNames: - if globalName not in scope.globalNames: - raise WebIDLError("Unknown [Exposed] value %s" % globalName, - [self.location]) - - if len(self._exposureGlobalNames) == 0: - self._exposureGlobalNames.add(scope.primaryGlobalName) - - globalNameSetToExposureSet(scope, self._exposureGlobalNames, - self.exposureSet) + IDLExposureMixins.finish(self, scope) # Now go ahead and merge in our partial interfaces. for partial in self._partialInterfaces: @@ -681,6 +722,17 @@ class IDLInterface(IDLObjectWithScope): self.parent.identifier.name), [self.location, self.parent.location]) + # Interfaces which have interface objects can't inherit + # from [NoInterfaceObject] interfaces. + if (self.parent.getExtendedAttribute("NoInterfaceObject") and + not self.getExtendedAttribute("NoInterfaceObject")): + raise WebIDLError("Interface %s does not have " + "[NoInterfaceObject] but inherits from " + "interface %s which does" % + (self.identifier.name, + self.parent.identifier.name), + [self.location, self.parent.location]) + for iface in self.implementedInterfaces: iface.finish(scope) @@ -718,9 +770,13 @@ class IDLInterface(IDLObjectWithScope): ctor = self.ctor() if ctor is not None: + assert len(ctor._exposureGlobalNames) == 0 + ctor._exposureGlobalNames.update(self._exposureGlobalNames) ctor.finish(scope) for ctor in self.namedConstructors: + assert len(ctor._exposureGlobalNames) == 0 + ctor._exposureGlobalNames.update(self._exposureGlobalNames) ctor.finish(scope) # Make a copy of our member list, so things that implement us @@ -921,10 +977,15 @@ class IDLInterface(IDLObjectWithScope): list(i.location for i in self.interfacesBasedOnSelf if i.parent == self)) - for member in self.members: member.validate() + if self.isCallback() and member.getExtendedAttribute("Replaceable"): + raise WebIDLError("[Replaceable] used on an attribute on " + "interface %s which is a callback interface" % + self.identifier.name, + [self.location, member.location]) + # Check that PutForwards refers to another attribute and that no # cycles exist in forwarded assignments. if member.isAttr(): @@ -966,10 +1027,25 @@ class IDLInterface(IDLObjectWithScope): if (self.getExtendedAttribute("Pref") and self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])): - raise WebIDLError("[Pref] used on an member that is not %s-only" % + raise WebIDLError("[Pref] used on an interface that is not %s-only" % + self.parentScope.primaryGlobalName, + [self.location]) + + if (self.getExtendedAttribute("CheckPermissions") and + self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])): + raise WebIDLError("[CheckPermissions] used on an interface that is " + "not %s-only" % self.parentScope.primaryGlobalName, [self.location]) + # Conditional exposure makes no sense for interfaces with no + # interface object, unless they're navigator properties. + if (self.isExposedConditionally() and + not self.hasInterfaceObject() and + not self.getNavigatorProperty()): + raise WebIDLError("Interface with no interface object is " + "exposed conditionally", + [self.location]) def isInterface(self): return True @@ -1151,10 +1227,11 @@ class IDLInterface(IDLObjectWithScope): self.parentScope.globalNames.add(self.identifier.name) self.parentScope.globalNameMapping[self.identifier.name].add(self.identifier.name) self._isOnGlobalProtoChain = True - elif (identifier == "NeedNewResolve" or + elif (identifier == "NeedResolve" or identifier == "OverrideBuiltins" or identifier == "ChromeOnly" or identifier == "Unforgeable" or + identifier == "UnsafeInPrerendering" or identifier == "LegacyEventInit"): # Known extended attributes that do not take values if not attr.noArguments(): @@ -1284,7 +1361,7 @@ class IDLInterface(IDLObjectWithScope): def _getDependentObjects(self): deps = set(self.members) - deps.union(self.implementedInterfaces) + deps.update(self.implementedInterfaces) if self.parent: deps.add(self.parent) return deps @@ -1292,6 +1369,13 @@ class IDLInterface(IDLObjectWithScope): def hasMembersInSlots(self): return self._ownMembersInSlots != 0 + def isExposedConditionally(self): + return (self.getExtendedAttribute("Pref") or + self.getExtendedAttribute("ChromeOnly") or + self.getExtendedAttribute("Func") or + self.getExtendedAttribute("AvailableIn") or + self.getExtendedAttribute("CheckPermissions")) + class IDLDictionary(IDLObjectWithScope): def __init__(self, location, parentScope, name, parent, members): assert isinstance(parentScope, IDLScope) @@ -1486,7 +1570,7 @@ class IDLType(IDLObject): 'any', 'domstring', 'bytestring', - 'scalarvaluestring', + 'usvstring', 'object', 'date', 'void', @@ -1539,7 +1623,7 @@ class IDLType(IDLObject): def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -1688,7 +1772,10 @@ class IDLNullableType(IDLType): assert not innerType.isVoid() assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any] - IDLType.__init__(self, location, innerType.name) + name = innerType.name + if innerType.isComplete(): + name += "OrNull" + IDLType.__init__(self, location, name) self.inner = innerType self.builtin = False @@ -1722,8 +1809,8 @@ class IDLNullableType(IDLType): def isDOMString(self): return self.inner.isDOMString() - def isScalarValueString(self): - return self.inner.isScalarValueString() + def isUSVString(self): + return self.inner.isUSVString() def isFloat(self): return self.inner.isFloat() @@ -1801,7 +1888,7 @@ class IDLNullableType(IDLType): "be a union type that itself has a nullable " "type as a member type", [self.location]) - self.name = self.inner.name + self.name = self.inner.name + "OrNull" return self def unroll(self): @@ -1824,6 +1911,10 @@ class IDLSequenceType(IDLType): IDLType.__init__(self, location, parameterType.name) self.inner = parameterType self.builtin = False + # Need to set self.name up front if our inner type is already complete, + # since in that case our .complete() won't be called. + if self.inner.isComplete(): + self.name = self.inner.name + "Sequence" def __eq__(self, other): return isinstance(other, IDLSequenceType) and self.inner == other.inner @@ -1846,7 +1937,7 @@ class IDLSequenceType(IDLType): def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -1885,7 +1976,7 @@ class IDLSequenceType(IDLType): def complete(self, scope): self.inner = self.inner.complete(scope) - self.name = self.inner.name + self.name = self.inner.name + "Sequence" return self def unroll(self): @@ -1896,7 +1987,8 @@ class IDLSequenceType(IDLType): # Just forward to the union; it'll deal return other.isDistinguishableFrom(self) return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isDate() or other.isNonCallbackInterface() or other.isMozMap()) + other.isDate() or other.isInterface() or other.isDictionary() or + other.isCallback() or other.isMozMap()) def _getDependentObjects(self): return self.inner._getDependentObjects() @@ -1911,6 +2003,10 @@ class IDLMozMapType(IDLType): IDLType.__init__(self, location, parameterType.name) self.inner = parameterType self.builtin = False + # Need to set self.name up front if our inner type is already complete, + # since in that case our .complete() won't be called. + if self.inner.isComplete(): + self.name = self.inner.name + "MozMap" def __eq__(self, other): return isinstance(other, IDLMozMapType) and self.inner == other.inner @@ -1936,7 +2032,7 @@ class IDLMozMapType(IDLType): def complete(self, scope): self.inner = self.inner.complete(scope) - self.name = self.inner.name + self.name = self.inner.name + "MozMap" return self def unroll(self): @@ -1970,6 +2066,10 @@ class IDLUnionType(IDLType): def __eq__(self, other): return isinstance(other, IDLUnionType) and self.memberTypes == other.memberTypes + def __hash__(self): + assert self.isComplete() + return self.name.__hash__() + def isVoid(self): return False @@ -2001,9 +2101,6 @@ class IDLUnionType(IDLType): return typeName(type._identifier.object()) if isinstance(type, IDLObjectWithIdentifier): return typeName(type.identifier) - if (isinstance(type, IDLType) and - (type.isArray() or type.isSequence() or type.isMozMap)): - return str(type) return type.name for (i, type) in enumerate(self.memberTypes): @@ -2114,7 +2211,7 @@ class IDLArrayType(IDLType): def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -2212,8 +2309,8 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier): def isDOMString(self): return self.inner.isDOMString() - def isScalarValueString(self): - return self.inner.isScalarValueString() + def isUSVString(self): + return self.inner.isUSVString() def isVoid(self): return self.inner.isVoid() @@ -2313,7 +2410,7 @@ class IDLWrapperType(IDLType): def isDOMString(self): return False - def isScalarValueString(self): + def isUSVString(self): return False def isVoid(self): @@ -2387,7 +2484,8 @@ class IDLWrapperType(IDLType): other.isDate()) if self.isDictionary() and other.nullable(): return False - if other.isPrimitive() or other.isString() or other.isEnum() or other.isDate(): + if (other.isPrimitive() or other.isString() or other.isEnum() or + other.isDate() or other.isSequence()): return True if self.isDictionary(): return other.isNonCallbackInterface() @@ -2405,7 +2503,7 @@ class IDLWrapperType(IDLType): (self.isNonCallbackInterface() or other.isNonCallbackInterface())) if (other.isDictionary() or other.isCallback() or - other.isSequence() or other.isMozMap() or other.isArray()): + other.isMozMap() or other.isArray()): return self.isNonCallbackInterface() # Not much else |other| can be @@ -2441,6 +2539,13 @@ class IDLWrapperType(IDLType): # Bindings.conf, which is still a global dependency. # 2) Changing an interface to a dictionary (or vice versa) with the # same identifier should be incredibly rare. + # + # On the other hand, if our type is a dictionary, we should + # depend on it, because the member types of a dictionary + # affect whether a method taking the dictionary as an argument + # takes a JSContext* argument or not. + if self.isDictionary(): + return set([self.inner]) return set() class IDLBuiltinType(IDLType): @@ -2466,7 +2571,7 @@ class IDLBuiltinType(IDLType): 'any', 'domstring', 'bytestring', - 'scalarvaluestring', + 'usvstring', 'object', 'date', 'void', @@ -2501,7 +2606,7 @@ class IDLBuiltinType(IDLType): Types.any: IDLType.Tags.any, Types.domstring: IDLType.Tags.domstring, Types.bytestring: IDLType.Tags.bytestring, - Types.scalarvaluestring: IDLType.Tags.scalarvaluestring, + Types.usvstring: IDLType.Tags.usvstring, Types.object: IDLType.Tags.object, Types.date: IDLType.Tags.date, Types.void: IDLType.Tags.void, @@ -2535,7 +2640,7 @@ class IDLBuiltinType(IDLType): def isString(self): return self._typeTag == IDLBuiltinType.Types.domstring or \ self._typeTag == IDLBuiltinType.Types.bytestring or \ - self._typeTag == IDLBuiltinType.Types.scalarvaluestring + self._typeTag == IDLBuiltinType.Types.usvstring def isByteString(self): return self._typeTag == IDLBuiltinType.Types.bytestring @@ -2543,8 +2648,8 @@ class IDLBuiltinType(IDLType): def isDOMString(self): return self._typeTag == IDLBuiltinType.Types.domstring - def isScalarValueString(self): - return self._typeTag == IDLBuiltinType.Types.scalarvaluestring + def isUSVString(self): + return self._typeTag == IDLBuiltinType.Types.usvstring def isInteger(self): return self._typeTag <= IDLBuiltinType.Types.unsigned_long_long @@ -2698,9 +2803,9 @@ BuiltinTypes = { IDLBuiltinType.Types.bytestring: IDLBuiltinType(BuiltinLocation("<builtin type>"), "ByteString", IDLBuiltinType.Types.bytestring), - IDLBuiltinType.Types.scalarvaluestring: - IDLBuiltinType(BuiltinLocation("<builtin type>"), "ScalarValueString", - IDLBuiltinType.Types.scalarvaluestring), + IDLBuiltinType.Types.usvstring: + IDLBuiltinType(BuiltinLocation("<builtin type>"), "USVString", + IDLBuiltinType.Types.usvstring), IDLBuiltinType.Types.object: IDLBuiltinType(BuiltinLocation("<builtin type>"), "Object", IDLBuiltinType.Types.object), @@ -2835,10 +2940,10 @@ class IDLValue(IDLObject): raise WebIDLError("Trying to convert unrestricted value %s to non-unrestricted" % self.value, [location]); return self - elif self.type.isString() and type.isScalarValueString(): - # Allow ScalarValueStrings to use default value just like + elif self.type.isString() and type.isUSVString(): + # Allow USVStrings to use default value just like # DOMString. No coercion is required in this case as Codegen.py - # treats ScalarValueString just like DOMString, but with an + # treats USVString just like DOMString, but with an # extra normalization step. assert self.type.isDOMString() return self @@ -2923,7 +3028,7 @@ class IDLUndefinedValue(IDLObject): def _getDependentObjects(self): return set() -class IDLInterfaceMember(IDLObjectWithIdentifier): +class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): Tags = enum( 'Const', @@ -2936,15 +3041,14 @@ class IDLInterfaceMember(IDLObjectWithIdentifier): 'Stringifier' ) + AffectsValues = ("Nothing", "Everything") + DependsOnValues = ("Nothing", "DOMState", "DeviceState", "Everything") + def __init__(self, location, identifier, tag): IDLObjectWithIdentifier.__init__(self, location, None, identifier) + IDLExposureMixins.__init__(self, location) self.tag = tag self._extendedAttrDict = {} - # _exposureGlobalNames are the global names listed in our [Exposed] - # extended attribute. exposureSet is the exposure set as defined in the - # Web IDL spec: it contains interface names. - self._exposureGlobalNames = set() - self.exposureSet = set() def isMethod(self): return self.tag == IDLInterfaceMember.Tags.Method @@ -2968,21 +3072,53 @@ class IDLInterfaceMember(IDLObjectWithIdentifier): return self._extendedAttrDict.get(name, None) def finish(self, scope): - for globalName in self._exposureGlobalNames: - if globalName not in scope.globalNames: - raise WebIDLError("Unknown [Exposed] value %s" % globalName, - [self.location]) - globalNameSetToExposureSet(scope, self._exposureGlobalNames, - self.exposureSet) - self._scope = scope + # We better be exposed _somewhere_. + if (len(self._exposureGlobalNames) == 0): + print self.identifier.name + assert len(self._exposureGlobalNames) != 0 + IDLExposureMixins.finish(self, scope) def validate(self): if (self.getExtendedAttribute("Pref") and - self.exposureSet != set([self._scope.primaryGlobalName])): + self.exposureSet != set([self._globalScope.primaryGlobalName])): raise WebIDLError("[Pref] used on an interface member that is not " - "%s-only" % self._scope.primaryGlobalName, + "%s-only" % self._globalScope.primaryGlobalName, + [self.location]) + + if (self.getExtendedAttribute("CheckPermissions") and + self.exposureSet != set([self._globalScope.primaryGlobalName])): + raise WebIDLError("[CheckPermissions] used on an interface member " + "that is not %s-only" % + self._globalScope.primaryGlobalName, [self.location]) + if self.isAttr() or self.isMethod(): + if self.affects == "Everything" and self.dependsOn != "Everything": + raise WebIDLError("Interface member is flagged as affecting " + "everything but not depending on everything. " + "That seems rather unlikely.", + [self.location]) + + def _setDependsOn(self, dependsOn): + if self.dependsOn != "Everything": + raise WebIDLError("Trying to specify multiple different DependsOn, " + "Pure, or Constant extended attributes for " + "attribute", [self.location]) + if dependsOn not in IDLInterfaceMember.DependsOnValues: + raise WebIDLError("Invalid [DependsOn=%s] on attribute" % dependsOn, + [self.location]) + self.dependsOn = dependsOn + + def _setAffects(self, affects): + if self.affects != "Everything": + raise WebIDLError("Trying to specify multiple different Affects, " + "Pure, or Constant extended attributes for " + "attribute", [self.location]) + if affects not in IDLInterfaceMember.AffectsValues: + raise WebIDLError("Invalid [Affects=%s] on attribute" % dependsOn, + [self.location]) + self.affects = affects + class IDLConst(IDLInterfaceMember): def __init__(self, location, identifier, type, value): IDLInterfaceMember.__init__(self, location, identifier, @@ -3061,6 +3197,8 @@ class IDLAttribute(IDLInterfaceMember): self.enforceRange = False self.clamp = False self.slotIndex = None + self.dependsOn = "Everything" + self.affects = "Everything" if static and identifier.name == "prototype": raise WebIDLError("The identifier of a static attribute must not be 'prototype'", @@ -3129,11 +3267,11 @@ class IDLAttribute(IDLInterfaceMember): if ((self.getExtendedAttribute("Cached") or self.getExtendedAttribute("StoreInSlot")) and - not self.getExtendedAttribute("Constant") and - not self.getExtendedAttribute("Pure")): + not self.affects == "Nothing"): raise WebIDLError("Cached attributes and attributes stored in " - "slots must be constant or pure, since the " - "getter won't always be called.", + "slots must be Constant or Pure or " + "Affects=Nothing, since the getter won't always " + "be called.", [self.location]) if self.getExtendedAttribute("Frozen"): if (not self.type.isSequence() and not self.type.isDictionary() and @@ -3158,8 +3296,7 @@ class IDLAttribute(IDLInterfaceMember): (identifier == "StoreInSlot" and (self.getExtendedAttribute("Throws") or self.getExtendedAttribute("GetterThrows")))): - raise WebIDLError("Throwing things can't be [Pure] or [Constant] " - "or [SameObject] or [StoreInSlot]", + raise WebIDLError("Throwing things can't be [StoreInSlot]", [attr.location]) elif identifier == "LenientThis": if not attr.noArguments(): @@ -3203,6 +3340,15 @@ class IDLAttribute(IDLInterfaceMember): raise WebIDLError("[PutForwards] takes an identifier", [attr.location, self.location]) elif identifier == "Replaceable": + if not attr.noArguments(): + raise WebIDLError("[Replaceable] must take no arguments", + [attr.location]) + if not self.readonly: + raise WebIDLError("[Replaceable] is only allowed on readonly " + "attributes", [attr.location, self.location]) + if self.isStatic(): + raise WebIDLError("[Replaceable] is only allowed on non-static " + "attributes", [attr.location, self.location]) if self.getExtendedAttribute("PutForwards") is not None: raise WebIDLError("[PutForwards] and [Replaceable] can't both " "appear on the same attribute", @@ -3250,18 +3396,43 @@ class IDLAttribute(IDLInterfaceMember): [attr.location, self.location]) elif identifier == "Exposed": convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) + elif identifier == "Pure": + if not attr.noArguments(): + raise WebIDLError("[Pure] must take no arguments", + [attr.location]) + self._setDependsOn("DOMState") + self._setAffects("Nothing") + elif identifier == "Constant" or identifier == "SameObject": + if not attr.noArguments(): + raise WebIDLError("[%s] must take no arguments" % identifier, + [attr.location]) + self._setDependsOn("Nothing") + self._setAffects("Nothing") + elif identifier == "Affects": + if not attr.hasValue(): + raise WebIDLError("[Affects] takes an identifier", + [attr.location]) + self._setAffects(attr.value()) + elif identifier == "DependsOn": + if not attr.hasValue(): + raise WebIDLError("[DependsOn] takes an identifier", + [attr.location]) + if (attr.value() != "Everything" and attr.value() != "DOMState" and + not self.readonly): + raise WebIDLError("[DependsOn=%s] only allowed on " + "readonly attributes" % attr.value(), + [attr.location, self.location]) + self._setDependsOn(attr.value()) elif (identifier == "Pref" or identifier == "SetterThrows" or - identifier == "Pure" or identifier == "Throws" or identifier == "GetterThrows" or identifier == "ChromeOnly" or - identifier == "SameObject" or - identifier == "Constant" or identifier == "Func" or identifier == "Frozen" or identifier == "AvailableIn" or identifier == "NewObject" or + identifier == "UnsafeInPrerendering" or identifier == "CheckPermissions" or identifier == "BinaryName"): # Known attributes that we don't need to do anything with here @@ -3306,6 +3477,7 @@ class IDLArgument(IDLObjectWithIdentifier): self._allowTreatNonCallableAsNull = False assert not variadic or optional + assert not variadic or not defaultValue def addExtendedAttributes(self, attrs): attrs = self.checkForStringHandlingExtendedAttributes( @@ -3354,9 +3526,9 @@ class IDLArgument(IDLObjectWithIdentifier): if ((self.type.isDictionary() or self.type.isUnion() and self.type.unroll().hasDictionaryType) and - self.optional and not self.defaultValue): - # Default optional dictionaries to null, for simplicity, - # so the codegen doesn't have to special-case this. + self.optional and not self.defaultValue and not self.variadic): + # Default optional non-variadic dictionaries to null, + # for simplicity, so the codegen doesn't have to special-case this. self.defaultValue = IDLNullValue(self.location) elif self.type.isAny(): assert (self.defaultValue is None or @@ -3383,6 +3555,9 @@ class IDLArgument(IDLObjectWithIdentifier): deps.add(self.defaultValue) return deps + def canHaveMissingValue(self): + return self.optional and not self.defaultValue + class IDLCallbackType(IDLType, IDLObjectWithScope): def __init__(self, location, parentScope, identifier, returnType, arguments): assert isinstance(returnType, IDLType) @@ -3442,7 +3617,8 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): # Just forward to the union; it'll deal return other.isDistinguishableFrom(self) return (other.isPrimitive() or other.isString() or other.isEnum() or - other.isNonCallbackInterface() or other.isDate()) + other.isNonCallbackInterface() or other.isDate() or + other.isSequence()) def addExtendedAttributes(self, attrs): unhandledAttrs = [] @@ -3538,6 +3714,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope): self._jsonifier = jsonifier self._specialType = specialType self._unforgeable = False + self.dependsOn = "Everything" + self.affects = "Everything" if static and identifier.name == "prototype": raise WebIDLError("The identifier of a static operation must not be 'prototype'", @@ -3618,7 +3796,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): return self._hasOverloads def isIdentifierLess(self): - return self.identifier.name[:2] == "__" and self.identifier.name != "__noSuchMethod__" + return self.identifier.name[:2] == "__" def resolve(self, parentScope): assert isinstance(parentScope, IDLScope) @@ -3849,16 +4027,32 @@ class IDLMethod(IDLInterfaceMember, IDLScope): [attr.location, self.location]) elif identifier == "Exposed": convertExposedAttrToGlobalNameSet(attr, self._exposureGlobalNames) - elif (identifier == "Pure" or - identifier == "CrossOriginCallable" or + elif (identifier == "CrossOriginCallable" or identifier == "WebGLHandlesContextLoss"): # Known no-argument attributes. if not attr.noArguments(): raise WebIDLError("[%s] must take no arguments" % identifier, [attr.location]) + elif identifier == "Pure": + if not attr.noArguments(): + raise WebIDLError("[Pure] must take no arguments", + [attr.location]) + self._setDependsOn("DOMState") + self._setAffects("Nothing") + elif identifier == "Affects": + if not attr.hasValue(): + raise WebIDLError("[Affects] takes an identifier", + [attr.location]) + self._setAffects(attr.value()) + elif identifier == "DependsOn": + if not attr.hasValue(): + raise WebIDLError("[DependsOn] takes an identifier", + [attr.location]) + self._setDependsOn(attr.value()) elif (identifier == "Throws" or identifier == "NewObject" or identifier == "ChromeOnly" or + identifier == "UnsafeInPrerendering" or identifier == "Pref" or identifier == "Func" or identifier == "AvailableIn" or @@ -3880,7 +4074,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def _getDependentObjects(self): deps = set() for overload in self._overloads: - deps.union(overload._getDependentObjects()) + deps.update(overload._getDependentObjects()) return deps class IDLImplementsStatement(IDLObject): @@ -3888,8 +4082,11 @@ class IDLImplementsStatement(IDLObject): IDLObject.__init__(self, location) self.implementor = implementor; self.implementee = implementee + self._finished = False def finish(self, scope): + if self._finished: + return assert(isinstance(self.implementor, IDLIdentifierPlaceholder)) assert(isinstance(self.implementee, IDLIdentifierPlaceholder)) implementor = self.implementor.finish(scope) @@ -3914,6 +4111,8 @@ class IDLImplementsStatement(IDLObject): "interface", [self.implementee.location]) implementor.addImplementedInterface(implementee) + self.implementor = implementor + self.implementee = implementee def validate(self): pass @@ -4044,7 +4243,7 @@ class Tokenizer(object): "Date": "DATE", "DOMString": "DOMSTRING", "ByteString": "BYTESTRING", - "ScalarValueString": "SCALARVALUESTRING", + "USVString": "USVSTRING", "any": "ANY", "boolean": "BOOLEAN", "byte": "BYTE", @@ -4053,8 +4252,8 @@ class Tokenizer(object): "long": "LONG", "object": "OBJECT", "octet": "OCTET", - "optional": "OPTIONAL", "Promise": "PROMISE", + "required": "REQUIRED", "sequence": "SEQUENCE", "MozMap": "MOZMAP", "short": "SHORT", @@ -4339,15 +4538,21 @@ class Parser(Tokenizer): def p_DictionaryMember(self, p): """ - DictionaryMember : Type IDENTIFIER Default SEMICOLON + DictionaryMember : Required Type IDENTIFIER Default SEMICOLON """ # These quack a lot like optional arguments, so just treat them that way. - t = p[1] + t = p[2] assert isinstance(t, IDLType) - identifier = IDLUnresolvedIdentifier(self.getLocation(p, 2), p[2]) - defaultValue = p[3] + identifier = IDLUnresolvedIdentifier(self.getLocation(p, 3), p[3]) + defaultValue = p[4] + optional = not p[1] + + if not optional and defaultValue: + raise WebIDLError("Required dictionary members can't have a default value.", + [self.getLocation(p, 4)]) - p[0] = IDLArgument(self.getLocation(p, 2), identifier, t, optional=True, + p[0] = IDLArgument(self.getLocation(p, 3), identifier, t, + optional=optional, defaultValue=defaultValue, variadic=False, dictionaryMember=True) @@ -4545,7 +4750,7 @@ class Parser(Tokenizer): def p_AttributeRest(self, p): """ - AttributeRest : ReadOnly ATTRIBUTE Type IDENTIFIER SEMICOLON + AttributeRest : ReadOnly ATTRIBUTE Type AttributeName SEMICOLON """ location = self.getLocation(p, 2) readonly = p[1] @@ -4874,6 +5079,7 @@ class Parser(Tokenizer): | INTERFACE | LEGACYCALLER | PARTIAL + | REQUIRED | SERIALIZER | SETTER | STATIC @@ -4884,6 +5090,13 @@ class Parser(Tokenizer): """ p[0] = p[1] + def p_AttributeName(self, p): + """ + AttributeName : IDENTIFIER + | REQUIRED + """ + p[0] = p[1] + def p_Optional(self, p): """ Optional : OPTIONAL @@ -4896,6 +5109,18 @@ class Parser(Tokenizer): """ p[0] = False + def p_Required(self, p): + """ + Required : REQUIRED + """ + p[0] = True + + def p_RequiredEmpty(self, p): + """ + Required : + """ + p[0] = False + def p_Ellipsis(self, p): """ Ellipsis : ELLIPSIS @@ -4982,7 +5207,7 @@ class Parser(Tokenizer): | DATE | DOMSTRING | BYTESTRING - | SCALARVALUESTRING + | USVSTRING | ANY | ATTRIBUTE | BOOLEAN @@ -5255,11 +5480,11 @@ class Parser(Tokenizer): """ p[0] = IDLBuiltinType.Types.bytestring - def p_PrimitiveOrStringTypeScalarValueString(self, p): + def p_PrimitiveOrStringTypeUSVString(self, p): """ - PrimitiveOrStringType : SCALARVALUESTRING + PrimitiveOrStringType : USVSTRING """ - p[0] = IDLBuiltinType.Types.scalarvaluestring + p[0] = IDLBuiltinType.Types.usvstring def p_UnsignedIntegerTypeUnsigned(self, p): """ @@ -5473,6 +5698,10 @@ class Parser(Tokenizer): 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._installBuiltins(self._globalScope) self._productions = [] @@ -5548,6 +5777,7 @@ class Parser(Tokenizer): # Builtin IDL defined by WebIDL _builtins = """ typedef unsigned long long DOMTimeStamp; + typedef (ArrayBufferView or ArrayBuffer) BufferSource; """ def main(): diff --git a/components/script/dom/bindings/codegen/parser/external.patch b/components/script/dom/bindings/codegen/parser/external.patch index 9464511a9d0..964a6d8774a 100644 --- a/components/script/dom/bindings/codegen/parser/external.patch +++ b/components/script/dom/bindings/codegen/parser/external.patch @@ -1,16 +1,18 @@ --- WebIDL.py +++ WebIDL.py -@@ -450,44 +450,8 @@ class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): +@@ -505,46 +505,8 @@ class IDLExposureMixins(): - class IDLExternalInterface(IDLObjectWithIdentifier): + class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins): def __init__(self, location, parentScope, identifier): - assert isinstance(identifier, IDLUnresolvedIdentifier) - assert isinstance(parentScope, IDLScope) - self.parent = None - IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) +- IDLExposureMixins.__init__(self, location) - IDLObjectWithIdentifier.resolve(self, parentScope) - - def finish(self, scope): +- IDLExposureMixins.finish(self, scope) - pass - - def validate(self): diff --git a/components/script/dom/bindings/codegen/parser/module.patch b/components/script/dom/bindings/codegen/parser/module.patch index f2ed1aff944..aaec7c61b7e 100644 --- a/components/script/dom/bindings/codegen/parser/module.patch +++ b/components/script/dom/bindings/codegen/parser/module.patch @@ -1,15 +1,16 @@ --- WebIDL.py +++ WebIDL.py -@@ -1422,6 +1422,9 @@ class IDLDictionary(IDLObjectWithScope): +@@ -1506,6 +1506,9 @@ class IDLDictionary(IDLObjectWithScope): self.identifier.name, [member.location] + locations) - + + def module(self): + return self.location.filename().split('/')[-1].split('.webidl')[0] + 'Binding' + def addExtendedAttributes(self, attrs): assert len(attrs) == 0 -@@ -3398,6 +3398,9 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): + +@@ -3574,6 +3577,9 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): self._treatNonCallableAsNull = False self._treatNonObjectAsNull = False |