diff options
Diffstat (limited to 'components/script/dom/bindings/codegen/parser/WebIDL.py')
-rw-r--r-- | components/script/dom/bindings/codegen/parser/WebIDL.py | 157 |
1 files changed, 90 insertions, 67 deletions
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py index 5045eae6493..b2daa1bce20 100644 --- a/components/script/dom/bindings/codegen/parser/WebIDL.py +++ b/components/script/dom/bindings/codegen/parser/WebIDL.py @@ -1095,12 +1095,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins): testInterface = testInterface.parent # Ensure that there's at most one of each {named,indexed} - # {getter,setter,creator,deleter}, at most one stringifier, + # {getter,setter,deleter}, at most one stringifier, # and at most one legacycaller. Note that this last is not # quite per spec, but in practice no one overloads # legacycallers. Also note that in practice we disallow # indexed deleters, but it simplifies some other code to - # treat deleter analogously to getter/setter/creator by + # treat deleter analogously to getter/setter by # prefixing it with "named". specialMembersSeen = {} for member in self.members: @@ -1111,8 +1111,6 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins): memberType = "getters" elif member.isSetter(): memberType = "setters" - elif member.isCreator(): - memberType = "creators" elif member.isDeleter(): memberType = "deleters" elif member.isStringifier(): @@ -1158,8 +1156,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins): ancestor = ancestor.parent if self._isOnGlobalProtoChain: - # Make sure we have no named setters, creators, or deleters - for memberType in ["setter", "creator", "deleter"]: + # Make sure we have no named setters or deleters + for memberType in ["setter", "deleter"]: memberId = "named " + memberType + "s" if memberId in specialMembersSeen: raise WebIDLError("Interface with [Global] has a named %s" % @@ -1183,6 +1181,22 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins): parent = parent.parent def validate(self): + + def checkDuplicateNames(member, name, attributeName): + for m in self.members: + if m.identifier.name == name: + raise WebIDLError("[%s=%s] has same name as interface member" % + (attributeName, name), + [member.location, m.location]) + if m.isMethod() and m != member and name in m.aliases: + raise WebIDLError("conflicting [%s=%s] definitions" % + (attributeName, name), + [member.location, m.location]) + if m.isAttr() and m != member and name in m.bindingAliases: + raise WebIDLError("conflicting [%s=%s] definitions" % + (attributeName, name), + [member.location, m.location]) + # We don't support consequential unforgeable interfaces. Need to check # this here, because in finish() an interface might not know yet that # it's consequential. @@ -1295,15 +1309,15 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins): raise WebIDLError("[Alias] must not be used on an " "[Unforgeable] operation", [member.location]) - for m in self.members: - if m.identifier.name == alias: - raise WebIDLError("[Alias=%s] has same name as " - "interface member" % alias, - [member.location, m.location]) - if m.isMethod() and m != member and alias in m.aliases: - raise WebIDLError("duplicate [Alias=%s] definitions" % - alias, - [member.location, m.location]) + + checkDuplicateNames(member, alias, "Alias") + + # Check that the name of a [BindingAlias] doesn't conflict with an + # interface member. + if member.isAttr(): + 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. @@ -1720,10 +1734,10 @@ class IDLInterface(IDLInterfaceOrNamespace): identifier == "OverrideBuiltins" or identifier == "ChromeOnly" or identifier == "Unforgeable" or - identifier == "UnsafeInPrerendering" or identifier == "LegacyEventInit" or identifier == "ProbablyShortLivingWrapper" or identifier == "LegacyUnenumerableNamedProperties" or + identifier == "RunConstructorInCallerCompartment" or identifier == "NonOrdinaryGetPrototypeOf" or identifier == "Abstract" or identifier == "Inline"): @@ -1780,10 +1794,16 @@ class IDLNamespace(IDLInterfaceOrNamespace): if not attr.hasValue(): raise WebIDLError("[%s] must have a value" % identifier, [attr.location]) - elif identifier == "ProtoObjectHack": + elif (identifier == "ProtoObjectHack" or + identifier == "ChromeOnly"): if not attr.noArguments(): raise WebIDLError("[%s] must not have arguments" % identifier, [attr.location]) + elif identifier == "Pref": + # Known extended attributes that take a string value + if not attr.hasValue(): + raise WebIDLError("[%s] must have a value" % identifier, + [attr.location]) else: raise WebIDLError("Unknown extended attribute %s on namespace" % identifier, @@ -3581,6 +3601,11 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): [self.location]) self.aliases.append(alias) + def _addBindingAlias(self, bindingAlias): + if bindingAlias in self.bindingAliases: + raise WebIDLError("Duplicate [BindingAlias=%s] on attribute" % bindingAlias, + [self.location]) + self.bindingAliases.append(bindingAlias) class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember): @@ -3701,6 +3726,11 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember): if isIteratorAlias: method.addExtendedAttributes( [IDLExtendedAttribute(self.location, ("Alias", "@@iterator"))]) + # Methods generated for iterables should be enumerable, but the ones for + # maplike/setlike should not be. + if not self.isIterable(): + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("NonEnumerable",))]) members.append(method) def resolve(self, parentScope): @@ -3824,11 +3854,15 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase): specification during parsing. """ # Both maplike and setlike have a size attribute - members.append(IDLAttribute(self.location, - IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"), - BuiltinTypes[IDLBuiltinType.Types.unsigned_long], - True, - maplikeOrSetlike=self)) + sizeAttr = IDLAttribute(self.location, + IDLUnresolvedIdentifier(BuiltinLocation("<auto-generated-identifier>"), "size"), + BuiltinTypes[IDLBuiltinType.Types.unsigned_long], + True, + maplikeOrSetlike=self) + # This should be non-enumerable. + sizeAttr.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("NonEnumerable",))]) + members.append(sizeAttr) self.reserved_ro_names = ["size"] self.disallowedMemberNames.append("size") @@ -3964,7 +3998,9 @@ class IDLConst(IDLInterfaceMember): elif (identifier == "Pref" or identifier == "ChromeOnly" or identifier == "Func" or - identifier == "SecureContext"): + identifier == "SecureContext" or + identifier == "NonEnumerable" or + identifier == "NeedsWindowsUndef"): # Known attributes that we don't need to do anything with here pass else: @@ -4000,6 +4036,7 @@ class IDLAttribute(IDLInterfaceMember): self.dependsOn = "Everything" self.affects = "Everything" self.navigatorObjectGetter = navigatorObjectGetter + self.bindingAliases = [] if static and identifier.name == "prototype": raise WebIDLError("The identifier of a static attribute must not be 'prototype'", @@ -4138,11 +4175,17 @@ class IDLAttribute(IDLInterfaceMember): def handleExtendedAttribute(self, attr): identifier = attr.identifier() - if ((identifier == "SetterThrows" or identifier == "SetterCanOOM") + if ((identifier == "SetterThrows" or identifier == "SetterCanOOM" or + identifier == "SetterNeedsSubjectPrincipal") and self.readonly): raise WebIDLError("Readonly attributes must not be flagged as " "[%s]" % identifier, [self.location]) + elif identifier == "BindingAlias": + if not attr.hasValue(): + raise WebIDLError("[BindingAlias] takes an identifier or string", + [attr.location]) + self._addBindingAlias(attr.value()) elif (((identifier == "Throws" or identifier == "GetterThrows" or identifier == "CanOOM" or identifier == "GetterCanOOM") and self.getExtendedAttribute("StoreInSlot")) or @@ -4338,11 +4381,13 @@ class IDLAttribute(IDLInterfaceMember): identifier == "SecureContext" or identifier == "Frozen" or identifier == "NewObject" or - identifier == "UnsafeInPrerendering" or identifier == "NeedsSubjectPrincipal" or + identifier == "SetterNeedsSubjectPrincipal" or + identifier == "GetterNeedsSubjectPrincipal" or identifier == "NeedsCallerType" or identifier == "ReturnValueNeedsContainsHack" or - identifier == "BinaryName"): + identifier == "BinaryName" or + identifier == "NonEnumerable"): # Known attributes that we don't need to do anything with here pass else: @@ -4606,7 +4651,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): Special = enum( 'Getter', 'Setter', - 'Creator', 'Deleter', 'LegacyCaller', base=IDLInterfaceMember.Special @@ -4619,7 +4663,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): ) def __init__(self, location, identifier, returnType, arguments, - static=False, getter=False, setter=False, creator=False, + static=False, getter=False, setter=False, deleter=False, specialType=NamedOrIndexed.Neither, legacycaller=False, stringifier=False, jsonifier=False, maplikeOrSetlikeOrIterable=None, htmlConstructor=False): @@ -4640,8 +4684,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): self._getter = getter assert isinstance(setter, bool) self._setter = setter - assert isinstance(creator, bool) - self._creator = creator assert isinstance(deleter, bool) self._deleter = deleter assert isinstance(legacycaller, bool) @@ -4682,7 +4724,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): assert not arguments[0].optional and not arguments[0].variadic assert not self._getter or not overload.returnType.isVoid() - if self._setter or self._creator: + if self._setter: assert len(self._overloads) == 1 arguments = self._overloads[0].arguments assert len(arguments) == 2 @@ -4715,9 +4757,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def isSetter(self): return self._setter - def isCreator(self): - return self._creator - def isDeleter(self): return self._deleter @@ -4750,7 +4789,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def isSpecial(self): return (self.isGetter() or self.isSetter() or - self.isCreator() or self.isDeleter() or self.isLegacycaller() or self.isStringifier() or @@ -4806,8 +4844,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): assert not method.isGetter() assert not self.isSetter() assert not method.isSetter() - assert not self.isCreator() - assert not method.isCreator() assert not self.isDeleter() assert not method.isDeleter() assert not self.isStringifier() @@ -4984,7 +5020,9 @@ class IDLMethod(IDLInterfaceMember, IDLScope): if (identifier == "GetterThrows" or identifier == "SetterThrows" or identifier == "GetterCanOOM" or - identifier == "SetterCanOOM"): + identifier == "SetterCanOOM" or + identifier == "SetterNeedsSubjectPrincipal" or + identifier == "GetterNeedsSubjectPrincipal"): raise WebIDLError("Methods must not be flagged as " "[%s]" % identifier, [attr.location, self.location]) @@ -5071,7 +5109,6 @@ class IDLMethod(IDLInterfaceMember, IDLScope): identifier == "CanOOM" or identifier == "NewObject" or identifier == "ChromeOnly" or - identifier == "UnsafeInPrerendering" or identifier == "Pref" or identifier == "Deprecated" or identifier == "Func" or @@ -5079,7 +5116,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope): identifier == "BinaryName" or identifier == "NeedsSubjectPrincipal" or identifier == "NeedsCallerType" or - identifier == "StaticClassOverride"): + identifier == "StaticClassOverride" or + identifier == "NonEnumerable"): # Known attributes that we don't need to do anything with here pass else: @@ -5262,7 +5300,6 @@ class Tokenizer(object): "static": "STATIC", "getter": "GETTER", "setter": "SETTER", - "creator": "CREATOR", "deleter": "DELETER", "legacycaller": "LEGACYCALLER", "optional": "OPTIONAL", @@ -5977,13 +6014,12 @@ class Parser(Tokenizer): getter = True if IDLMethod.Special.Getter in p[1] else False setter = True if IDLMethod.Special.Setter in p[1] else False - creator = True if IDLMethod.Special.Creator in p[1] else False deleter = True if IDLMethod.Special.Deleter in p[1] else False legacycaller = True if IDLMethod.Special.LegacyCaller in p[1] else False if getter or deleter: - if setter or creator: - raise WebIDLError("getter and deleter are incompatible with setter and creator", + if setter: + raise WebIDLError("getter and deleter are incompatible with setter", [self.getLocation(p, 1)]) (returnType, identifier, arguments) = p[2] @@ -6018,10 +6054,9 @@ class Parser(Tokenizer): if returnType.isVoid(): raise WebIDLError("getter cannot have void return type", [self.getLocation(p, 2)]) - if setter or creator: + if setter: if len(arguments) != 2: - raise WebIDLError("%s has wrong number of arguments" % - ("setter" if setter else "creator"), + raise WebIDLError("setter has wrong number of arguments", [self.getLocation(p, 2)]) argType = arguments[0].type if argType == BuiltinTypes[IDLBuiltinType.Types.domstring]: @@ -6029,18 +6064,15 @@ class Parser(Tokenizer): elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]: specialType = IDLMethod.NamedOrIndexed.Indexed else: - raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" % - ("setter" if setter else "creator"), + raise WebIDLError("settter has wrong argument type (must be DOMString or UnsignedLong)", [arguments[0].location]) if arguments[0].optional or arguments[0].variadic: - raise WebIDLError("%s cannot have %s argument" % - ("setter" if setter else "creator", - "optional" if arguments[0].optional else "variadic"), + raise WebIDLError("setter cannot have %s argument" % + ("optional" if arguments[0].optional else "variadic"), [arguments[0].location]) if arguments[1].optional or arguments[1].variadic: - raise WebIDLError("%s cannot have %s argument" % - ("setter" if setter else "creator", - "optional" if arguments[1].optional else "variadic"), + raise WebIDLError("setter cannot have %s argument" % + ("optional" if arguments[1].optional else "variadic"), [arguments[1].location]) if stringifier: @@ -6053,7 +6085,7 @@ class Parser(Tokenizer): # identifier might be None. This is only permitted for special methods. if not identifier: - if (not getter and not setter and not creator and + if (not getter and not setter and not deleter and not legacycaller and not stringifier): raise WebIDLError("Identifier required for non-special methods", [self.getLocation(p, 2)]) @@ -6061,19 +6093,18 @@ class Parser(Tokenizer): location = BuiltinLocation("<auto-generated-identifier>") identifier = IDLUnresolvedIdentifier( location, - "__%s%s%s%s%s%s%s" % + "__%s%s%s%s%s%s" % ("named" if specialType == IDLMethod.NamedOrIndexed.Named else "indexed" if specialType == IDLMethod.NamedOrIndexed.Indexed else "", "getter" if getter else "", "setter" if setter else "", "deleter" if deleter else "", - "creator" if creator else "", "legacycaller" if legacycaller else "", "stringifier" if stringifier else ""), allowDoubleUnderscore=True) method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments, - static=static, getter=getter, setter=setter, creator=creator, + static=static, getter=getter, setter=setter, deleter=deleter, specialType=specialType, legacycaller=legacycaller, stringifier=stringifier) p[0] = method @@ -6149,12 +6180,6 @@ class Parser(Tokenizer): """ p[0] = IDLMethod.Special.Setter - def p_SpecialCreator(self, p): - """ - Special : CREATOR - """ - p[0] = IDLMethod.Special.Creator - def p_SpecialDeleter(self, p): """ Special : DELETER @@ -6246,7 +6271,6 @@ class Parser(Tokenizer): | ATTRIBUTE | CALLBACK | CONST - | CREATOR | DELETER | DICTIONARY | ENUM @@ -6396,7 +6420,6 @@ class Parser(Tokenizer): | BYTE | LEGACYCALLER | CONST - | CREATOR | DELETER | DOUBLE | EXCEPTION |