From 3c5a2d72f09ff339d27f17ff33e51d9a63f4cf4f Mon Sep 17 00:00:00 2001 From: Anthony Ramine Date: Tue, 18 Aug 2015 12:58:09 -0600 Subject: [PATCH] servo: Merge #7230 - Support required dictionary members (fixes #7216) (from nox:required-dictionary-member); r=Ms2ger Source-Repo: https://github.com/servo/servo Source-Revision: ef98e574297ed738f3b117c128bc578f623a35d5 --- .../dom/bindings/codegen/CodegenRust.py | 21 +- .../dom/bindings/codegen/parser/WebIDL.py | 1529 ++++++++++++----- .../script/dom/webidls/BrowserElement.webidl | 80 +- .../script/dom/webidls/TestBinding.webidl | 1 + 4 files changed, 1181 insertions(+), 450 deletions(-) diff --git a/servo/components/script/dom/bindings/codegen/CodegenRust.py b/servo/components/script/dom/bindings/codegen/CodegenRust.py index 12399ecc2ed8..4e8b3d401018 100644 --- a/servo/components/script/dom/bindings/codegen/CodegenRust.py +++ b/servo/components/script/dom/bindings/codegen/CodegenRust.py @@ -918,7 +918,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None, assert not type.treatNonObjectAsNull() or type.nullable() assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull() - declType = CGGeneric('%s::%s' % (type.unroll().module(), type.unroll().identifier.name)) + callback = type.unroll().callback + declType = CGGeneric('%s::%s' % (callback.module(), callback.identifier.name)) finalDeclType = CGTemplatedType("Rc", declType) conversion = CGCallbackTempRoot(declType.define()) @@ -1285,8 +1286,8 @@ def getRetvalDeclarationForType(returnType, descriptorProvider): result = CGWrapper(result, pre="Option<", post=">") return result if returnType.isCallback(): - result = CGGeneric('Rc<%s::%s>' % (returnType.unroll().module(), - returnType.unroll().identifier.name)) + callback = returnType.unroll().callback + result = CGGeneric('Rc<%s::%s>' % (callback.module(), callback.identifier.name)) if returnType.nullable(): result = CGWrapper(result, pre="Option<", post=">") return result @@ -4798,7 +4799,7 @@ class CGDictionary(CGThing): def getMemberType(self, memberInfo): member, info = memberInfo declType = info.declType - if not member.defaultValue: + if member.optional and not member.defaultValue: declType = CGWrapper(info.declType, pre="Option<", post=">") return declType.define() @@ -4815,7 +4816,11 @@ class CGDictionary(CGThing): conversion = "%s.get()" % conversion assert (member.defaultValue is None) == (default is None) - if not default: + if not member.optional: + assert default is None + default = ("throw_type_error(cx, \"Missing required member \\\"%s\\\".\");\n" + "return Err(());") % member.identifier.name + elif not default: default = "None" conversion = "Some(%s)" % conversion @@ -4935,7 +4940,7 @@ class CGBindingRoot(CGThing): # Do codegen for all the callback interfaces. cgthings.extend(CGList([CGCallbackInterface(x), - CGCallbackFunctionImpl(x)], "\n") + CGCallbackFunctionImpl(x.interface)], "\n") for x in callbackDescriptors) # And make sure we have the right number of newlines at the end @@ -5258,7 +5263,7 @@ impl ToJSValConvertible for ${type} { self.callback().to_jsval(cx, rval); } }\ -""").substitute({"type": callback.name}) +""").substitute({"type": callback.identifier.name}) CGGeneric.__init__(self, impl) @@ -5687,7 +5692,7 @@ class GlobalGenRoots(): def Bindings(config): descriptors = (set(d.name + "Binding" for d in config.getDescriptors(register=True)) | - set(d.unroll().module() for d in config.callbacks) | + set(d.module() for d in config.callbacks) | set(d.module() for d in config.getDictionaries())) curr = CGList([CGGeneric("pub mod %s;\n" % name) for name in sorted(descriptors)]) curr = CGWrapper(curr, pre=AUTOGENERATED_WARNING_COMMENT) diff --git a/servo/components/script/dom/bindings/codegen/parser/WebIDL.py b/servo/components/script/dom/bindings/codegen/parser/WebIDL.py index 5741ab8fce57..09368e45aa7d 100644 --- a/servo/components/script/dom/bindings/codegen/parser/WebIDL.py +++ b/servo/components/script/dom/bindings/codegen/parser/WebIDL.py @@ -13,6 +13,7 @@ from collections import defaultdict # Machinery + def parseInt(literal): string = literal sign = 0 @@ -37,6 +38,7 @@ def parseInt(literal): value = int(string, base) return value * sign + # Magic for creating enums def M_add_class_attribs(attribs, start): def foo(name, bases, dict_): @@ -47,6 +49,7 @@ def M_add_class_attribs(attribs, start): return type(name, bases, dict_) return foo + def enum(*names, **kw): if len(kw) == 1: base = kw['base'].__class__ @@ -55,12 +58,15 @@ def enum(*names, **kw): assert len(kw) == 0 base = object start = 0 + class Foo(base): __metaclass__ = M_add_class_attribs(names, start) + def __setattr__(self, name, value): # this makes it read-only raise NotImplementedError return Foo() + class WebIDLError(Exception): def __init__(self, message, locations, warning=False): self.message = message @@ -69,9 +75,10 @@ class WebIDLError(Exception): def __str__(self): return "%s: %s%s%s" % (self.warning and 'warning' or 'error', - self.message, - ", " if len(self.locations) != 0 else "", - "\n".join(self.locations)) + self.message, + ", " if len(self.locations) != 0 else "", + "\n".join(self.locations)) + class Location(object): def __init__(self, lexer, lineno, lexpos, filename): @@ -82,8 +89,8 @@ class Location(object): self._file = filename if filename else "" def __eq__(self, other): - return self._lexpos == other._lexpos and \ - self._file == other._file + return (self._lexpos == other._lexpos and + self._file == other._file) def filename(self): return self._file @@ -115,13 +122,14 @@ class Location(object): return "%s line %s:%s\n%s\n%s" % (self._file, self._lineno, self._colno, self._line, self._pointerline()) + class BuiltinLocation(object): def __init__(self, text): self.msg = text + "\n" def __eq__(self, other): - return isinstance(other, BuiltinLocation) and \ - self.msg == other.msg + return (isinstance(other, BuiltinLocation) and + self.msg == other.msg) def filename(self): return '' @@ -138,6 +146,7 @@ class BuiltinLocation(object): # Data Model + class IDLObject(object): def __init__(self, location): self.location = location @@ -159,11 +168,14 @@ class IDLObject(object): return False def isDictionary(self): - return False; + return False def isUnion(self): return False + def isTypedef(self): + return False + def getUserData(self, key, default): return self.userData.get(key, default) @@ -171,13 +183,13 @@ class IDLObject(object): self.userData[key] = value def addExtendedAttributes(self, attrs): - assert False # Override me! + assert False # Override me! def handleExtendedAttribute(self, attr): - assert False # Override me! + assert False # Override me! def _getDependentObjects(self): - assert False # Override me! + assert False # Override me! def getDeps(self, visited=None): """ Return a set of files that this object depends on. If any of @@ -191,7 +203,7 @@ class IDLObject(object): # NB: We can't use visited=set() above because the default value is # evaluated when the def statement is evaluated, not when the function # is executed, so there would be one set for all invocations. - if visited == None: + if visited is None: visited = set() if self in visited: @@ -208,6 +220,7 @@ class IDLObject(object): return deps + class IDLScope(IDLObject): def __init__(self, location, parentScope, identifier): IDLObject.__init__(self, location) @@ -263,9 +276,9 @@ class IDLScope(IDLObject): self._dict[identifier.name] = object def resolveIdentifierConflict(self, scope, identifier, originalObject, newObject): - if isinstance(originalObject, IDLExternalInterface) and \ - isinstance(newObject, IDLExternalInterface) and \ - originalObject.identifier.name == newObject.identifier.name: + if (isinstance(originalObject, IDLExternalInterface) and + isinstance(newObject, IDLExternalInterface) and + originalObject.identifier.name == newObject.identifier.name): return originalObject if (isinstance(originalObject, IDLExternalInterface) or @@ -288,13 +301,15 @@ class IDLScope(IDLObject): # because we need to merge overloads of NamedConstructors and we need to # detect conflicts in those across interfaces. See also the comment in # IDLInterface.addExtendedAttributes for "NamedConstructor". - if originalObject.tag == IDLInterfaceMember.Tags.Method and \ - newObject.tag == IDLInterfaceMember.Tags.Method: + if (originalObject.tag == IDLInterfaceMember.Tags.Method and + newObject.tag == IDLInterfaceMember.Tags.Method): return originalObject.addOverload(newObject) # Default to throwing, derived classes can override. - conflictdesc = "\n\t%s at %s\n\t%s at %s" % \ - (originalObject, originalObject.location, newObject, newObject.location) + conflictdesc = "\n\t%s at %s\n\t%s at %s" % (originalObject, + originalObject.location, + newObject, + newObject.location) raise WebIDLError( "Multiple unresolvable definitions of identifier '%s' in scope '%s%s" @@ -308,6 +323,7 @@ class IDLScope(IDLObject): assert identifier.scope == self return self._lookupIdentifier(identifier) + class IDLIdentifier(IDLObject): def __init__(self, location, scope, name): IDLObject.__init__(self, location) @@ -331,9 +347,10 @@ class IDLIdentifier(IDLObject): def object(self): return self.scope.lookupIdentifier(self) + class IDLUnresolvedIdentifier(IDLObject): - def __init__(self, location, name, allowDoubleUnderscore = False, - allowForbidden = False): + def __init__(self, location, name, allowDoubleUnderscore=False, + allowForbidden=False): IDLObject.__init__(self, location) assert len(name) > 0 @@ -374,7 +391,8 @@ class IDLUnresolvedIdentifier(IDLObject): return identifier def finish(self): - assert False # Should replace with a resolved identifier first. + assert False # Should replace with a resolved identifier first. + class IDLObjectWithIdentifier(IDLObject): def __init__(self, location, parentScope, identifier): @@ -429,6 +447,7 @@ class IDLObjectWithIdentifier(IDLObject): return unhandledAttrs + class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope): def __init__(self, location, parentScope, identifier): assert isinstance(identifier, IDLUnresolvedIdentifier) @@ -436,6 +455,7 @@ class IDLObjectWithScope(IDLObjectWithIdentifier, IDLScope): IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) IDLScope.__init__(self, location, parentScope, self.identifier) + class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): def __init__(self, location, identifier): assert isinstance(identifier, IDLUnresolvedIdentifier) @@ -451,6 +471,7 @@ class IDLIdentifierPlaceholder(IDLObjectWithIdentifier): obj = self.identifier.resolve(scope, None) return scope.lookupIdentifier(obj) + class IDLExposureMixins(): def __init__(self, location): # _exposureGlobalNames are the global names listed in our [Exposed] @@ -508,6 +529,7 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins): raise WebIDLError("Servo does not support external interfaces.", [self.location]) + class IDLPartialInterface(IDLObject): def __init__(self, location, name, members, nonPartialInterface): assert isinstance(name, IDLUnresolvedIdentifier) @@ -562,10 +584,12 @@ def convertExposedAttrToGlobalNameSet(exposedAttr, targetSet): assert exposedAttr.hasArgs() targetSet.update(exposedAttr.args()) + def globalNameSetToExposureSet(globalScope, nameSet, exposureSet): for name in nameSet: exposureSet.update(globalScope.globalNameMapping[name]) + class IDLInterface(IDLObjectWithScope, IDLExposureMixins): def __init__(self, location, parentScope, name, parent, members, isKnownNonPartial): @@ -578,6 +602,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): self._callback = False self._finished = False self.members = [] + self.maplikeOrSetlike = None self._partialInterfaces = [] self._extendedAttrDict = {} # namedConstructors needs deterministic ordering because bindings code @@ -651,6 +676,27 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): self.addExtendedAttributes(partial.propagatedExtendedAttrs) self.members.extend(partial.members) + # Generate maplike/setlike interface members. Since generated members + # need to be treated like regular interface members, do this before + # things like exposure setting. + for member in self.members: + if member.isMaplikeOrSetlike(): + # Check that we only have one interface declaration (currently + # there can only be one maplike/setlike declaration per + # interface) + if self.maplikeOrSetlike: + raise WebIDLError("%s declaration used on " + "interface that already has %s " + "declaration" % + (member.maplikeOrSetlikeType, + self.maplikeOrSetlike.maplikeOrSetlikeType), + [self.maplikeOrSetlike.location, + member.location]) + self.maplikeOrSetlike = member + # If we've got a maplike or setlike declaration, we'll be building all of + # our required methods in Codegen. Generate members now. + self.maplikeOrSetlike.expand(self.members, self.isJSImplemented()) + # Now that we've merged in our partial interfaces, set the # _exposureGlobalNames on any members that don't have it set yet. Note # that any partial interfaces that had [Exposed] set have already set up @@ -680,7 +726,6 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): if self.parent: self.parent.finish(scope) - self.parent._hasChildInterfaces = True self.totalMembersInSlots = self.parent.totalMembersInSlots @@ -798,7 +843,18 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): "consequential interface %s is not exposed." % (self.identifier.name, iface.identifier.name), [self.location, iface.location]) - additionalMembers = iface.originalMembers; + + # If we have a maplike or setlike, and the consequential interface + # also does, throw an error. + if iface.maplikeOrSetlike and self.maplikeOrSetlike: + raise WebIDLError("Maplike/setlike interface %s cannot have " + "maplike/setlike interface %s as a " + "consequential interface" % + (self.identifier.name, + iface.identifier.name), + [self.maplikeOrSetlike.location, + iface.maplikeOrSetlike.location]) + additionalMembers = iface.originalMembers for additionalMember in additionalMembers: for member in self.members: if additionalMember.identifier.name == member.identifier.name: @@ -811,6 +867,15 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): for ancestor in self.getInheritedInterfaces(): ancestor.interfacesBasedOnSelf.add(self) + if (ancestor.maplikeOrSetlike is not None and + self.maplikeOrSetlike is not None): + raise WebIDLError("Cannot have maplike/setlike on %s that " + "inherits %s, which is already " + "maplike/setlike" % + (self.identifier.name, + ancestor.identifier.name), + [self.maplikeOrSetlike.location, + ancestor.maplikeOrSetlike.location]) for ancestorConsequential in ancestor.getConsequentialInterfaces(): ancestorConsequential.interfacesBasedOnSelf.add(self) @@ -847,12 +912,14 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): not hasattr(member, "originatingInterface")): member.originatingInterface = self - # Compute slot indices for our members before we pull in - # unforgeable members from our parent. + # Compute slot indices for our members before we pull in unforgeable + # members from our parent. Also, maplike/setlike declarations get a + # slot to hold their backing object. for member in self.members: - if (member.isAttr() and - (member.getExtendedAttribute("StoreInSlot") or - member.getExtendedAttribute("Cached"))): + if ((member.isAttr() and + (member.getExtendedAttribute("StoreInSlot") or + member.getExtendedAttribute("Cached"))) or + member.isMaplikeOrSetlike()): member.slotIndex = self.totalMembersInSlots self.totalMembersInSlots += 1 if member.getExtendedAttribute("StoreInSlot"): @@ -869,13 +936,13 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): for unforgeableMember in (member for member in self.parent.members if (member.isAttr() or member.isMethod()) and member.isUnforgeable()): - shadows = [ m for m in self.members if - (m.isAttr() or m.isMethod()) and - not m.isStatic() and - m.identifier.name == unforgeableMember.identifier.name ] + shadows = [m for m in self.members if + (m.isAttr() or m.isMethod()) and + not m.isStatic() and + m.identifier.name == unforgeableMember.identifier.name] if len(shadows) != 0: - locs = [unforgeableMember.location] + [ s.location for s - in shadows ] + locs = [unforgeableMember.location] + [s.location for s + in shadows] raise WebIDLError("Interface %s shadows [Unforgeable] " "members of %s" % (self.identifier.name, @@ -889,6 +956,18 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): # complicated and seems unnecessary. self.members.append(unforgeableMember) + # At this point, we have all of our members. If the current interface + # uses maplike/setlike, check for collisions anywhere in the current + # interface or higher in the inheritance chain. + if self.maplikeOrSetlike: + testInterface = self + isAncestor = False + while testInterface: + self.maplikeOrSetlike.checkCollisions(testInterface.members, + isAncestor) + isAncestor = True + testInterface = testInterface.parent + # Ensure that there's at most one of each {named,indexed} # {getter,setter,creator,deleter}, at most one stringifier, # and at most one legacycaller. Note that this last is not @@ -926,9 +1005,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): if memberType in specialMembersSeen: raise WebIDLError("Multiple " + memberType + " on %s" % (self), - [self.location, - specialMembersSeen[memberType].location, - member.location]) + [self.location, + specialMembersSeen[memberType].location, + member.location]) specialMembersSeen[memberType] = member @@ -967,15 +1046,16 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): self.identifier.name, [self.location] + list(i.location for i in - (self.interfacesBasedOnSelf - { self }) )) + (self.interfacesBasedOnSelf - {self}))) # We also don't support inheriting from unforgeable interfaces. if self.getExtendedAttribute("Unforgeable") and self.hasChildInterfaces(): + locations = ([self.location] + + list(i.location for i in + self.interfacesBasedOnSelf if i.parent == self)) raise WebIDLError("%s is an unforgeable ancestor interface" % - self.identifier.name, - [self.location] + - list(i.location for i in - self.interfacesBasedOnSelf if i.parent == self)) + self.identifier.name, + locations) for member in self.members: member.validate() @@ -1018,25 +1098,66 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): if fowardAttr is None: raise WebIDLError("Attribute %s on %s forwards to " "missing attribute %s" % - (attr.identifier.name, iface, putForwards), - [attr.location]) + (attr.identifier.name, iface, putForwards), + [attr.location]) iface = forwardIface attr = fowardAttr putForwards = attr.getExtendedAttribute("PutForwards") + # Check that the name of an [Alias] doesn't conflict with an + # interface member. + if member.isMethod(): + for alias in member.aliases: + if self.isOnGlobalProtoChain(): + raise WebIDLError("[Alias] must not be used on a " + "[Global] interface operation", + [member.location]) + if (member.getExtendedAttribute("Exposed") or + member.getExtendedAttribute("ChromeOnly") or + member.getExtendedAttribute("Pref") or + member.getExtendedAttribute("Func") or + member.getExtendedAttribute("AvailableIn") or + member.getExtendedAttribute("CheckAnyPermissions") or + member.getExtendedAttribute("CheckAllPermissions")): + raise WebIDLError("[Alias] must not be used on a " + "conditionally exposed operation", + [member.location]) + if member.isStatic(): + raise WebIDLError("[Alias] must not be used on a " + "static operation", + [member.location]) + if member.isIdentifierLess(): + raise WebIDLError("[Alias] must not be used on an " + "identifierless operation", + [member.location]) + if member.isUnforgeable(): + 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]) + if (self.getExtendedAttribute("Pref") and self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])): 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]) + for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]: + if (self.getExtendedAttribute(attribute) and + self._exposureGlobalNames != set([self.parentScope.primaryGlobalName])): + raise WebIDLError("[%s] used on an interface that is " + "not %s-only" % + (attribute, self.parentScope.primaryGlobalName), + [self.location]) # Conditional exposure makes no sense for interfaces with no # interface object, unless they're navigator properties. @@ -1138,7 +1259,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): args = attr.args() if attr.hasArgs() else [] - retType = IDLWrapperType(self.location, self) + if self.identifier.name == "Promise": + promiseType = BuiltinTypes[IDLBuiltinType.Types.any] + else: + promiseType = None + retType = IDLWrapperType(self.location, self, promiseType) if identifier == "Constructor" or identifier == "ChromeConstructor": name = "constructor" @@ -1183,7 +1308,7 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): newMethod = self.parentScope.lookupIdentifier(method.identifier) if newMethod == method: self.namedConstructors.append(method) - elif not newMethod in self.namedConstructors: + elif newMethod not in self.namedConstructors: raise WebIDLError("NamedConstructor conflicts with a NamedConstructor of a different interface", [method.location, newMethod.location]) elif (identifier == "ArrayClass"): @@ -1204,11 +1329,11 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): [attr.location, self.location]) elif identifier == "Global": if attr.hasValue(): - self.globalNames = [ attr.value() ] + self.globalNames = [attr.value()] elif attr.hasArgs(): self.globalNames = attr.args() else: - self.globalNames = [ self.identifier.name ] + self.globalNames = [self.identifier.name] self.parentScope.globalNames.update(self.globalNames) for globalName in self.globalNames: self.parentScope.globalNameMapping[globalName].add(self.identifier.name) @@ -1246,7 +1371,8 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): identifier == "NavigatorProperty" or identifier == "AvailableIn" or identifier == "Func" or - identifier == "CheckPermissions"): + identifier == "CheckAnyPermissions" or + identifier == "CheckAllPermissions"): # Known extended attributes that take a string value if not attr.hasValue(): raise WebIDLError("[%s] must have a value" % identifier, @@ -1374,7 +1500,9 @@ class IDLInterface(IDLObjectWithScope, IDLExposureMixins): self.getExtendedAttribute("ChromeOnly") or self.getExtendedAttribute("Func") or self.getExtendedAttribute("AvailableIn") or - self.getExtendedAttribute("CheckPermissions")) + self.getExtendedAttribute("CheckAnyPermissions") or + self.getExtendedAttribute("CheckAllPermissions")) + class IDLDictionary(IDLObjectWithScope): def __init__(self, location, parentScope, name, parent, members): @@ -1392,7 +1520,15 @@ class IDLDictionary(IDLObjectWithScope): return "Dictionary '%s'" % self.identifier.name def isDictionary(self): - return True; + return True + + def canBeEmpty(self): + """ + Returns true if this dictionary can be empty (that is, it has no + required members and neither do any of its ancestors). + """ + return (all(member.optional for member in self.members) and + (not self.parent or self.parent.canBeEmpty())) def finish(self, scope): if self._finished: @@ -1466,7 +1602,7 @@ class IDLDictionary(IDLObjectWithScope): if memberType.inner == dictionary: return (True, [memberType.location]) - (contains, locations) = dictionaryContainsDictionary(memberType.inner, \ + (contains, locations) = dictionaryContainsDictionary(memberType.inner, dictionary) if contains: return (True, [memberType.location] + locations) @@ -1518,6 +1654,7 @@ class IDLDictionary(IDLObjectWithScope): deps.add(self.parent) return deps + class IDLEnum(IDLObjectWithIdentifier): def __init__(self, location, parentScope, name, values): assert isinstance(parentScope, IDLScope) @@ -1548,6 +1685,7 @@ class IDLEnum(IDLObjectWithIdentifier): def _getDependentObjects(self): return set() + class IDLType(IDLObject): Tags = enum( # The integer types @@ -1644,9 +1782,18 @@ class IDLType(IDLObject): def isArrayBufferView(self): return False + def isSharedArrayBuffer(self): + return False + + def isSharedArrayBufferView(self): + return False + def isTypedArray(self): return False + def isSharedTypedArray(self): + return False + def isCallbackInterface(self): return False @@ -1664,9 +1811,12 @@ class IDLType(IDLObject): """ Returns a boolean indicating whether this type is an 'interface' type that is implemented in Spidermonkey. At the moment, this only returns true for the types from the TypedArray spec. """ - return self.isInterface() and (self.isArrayBuffer() or \ - self.isArrayBufferView() or \ - self.isTypedArray()) + return self.isInterface() and (self.isArrayBuffer() or + self.isArrayBufferView() or + self.isSharedArrayBuffer() or + self.isSharedArrayBufferView() or + self.isTypedArray() or + self.isSharedTypedArray()) def isDictionary(self): return False @@ -1703,15 +1853,15 @@ class IDLType(IDLObject): return False def tag(self): - assert False # Override me! + assert False # Override me! def treatNonCallableAsNull(self): assert self.tag() == IDLType.Tags.callback - return self.nullable() and self.inner._treatNonCallableAsNull + return self.nullable() and self.inner.callback._treatNonCallableAsNull def treatNonObjectAsNull(self): assert self.tag() == IDLType.Tags.callback - return self.nullable() and self.inner._treatNonObjectAsNull + return self.nullable() and self.inner.callback._treatNonObjectAsNull def addExtendedAttributes(self, attrs): assert len(attrs) == 0 @@ -1729,6 +1879,7 @@ class IDLType(IDLObject): def isExposedInAllOf(self, exposureSet): return True + class IDLUnresolvedType(IDLType): """ Unresolved types are interface types @@ -1751,11 +1902,17 @@ class IDLUnresolvedType(IDLType): assert obj if obj.isType(): - # obj itself might not be complete; deal with that. - assert obj != self - if not obj.isComplete(): - obj = obj.complete(scope) - return obj + print obj + assert not obj.isType() + if obj.isTypedef(): + assert self.name.name == obj.identifier.name + typedefType = IDLTypedefType(self.location, obj.innerType, + obj.identifier) + assert not typedefType.isComplete() + return typedefType.complete(scope) + elif obj.isCallback() and not obj.isInterface(): + assert self.name.name == obj.identifier.name + return IDLCallbackType(self.location, obj) if self._promiseInnerType and not self._promiseInnerType.isComplete(): self._promiseInnerType = self._promiseInnerType.complete(scope) @@ -1767,6 +1924,7 @@ class IDLUnresolvedType(IDLType): raise TypeError("Can't tell whether an unresolved type is or is not " "distinguishable from other things") + class IDLNullableType(IDLType): def __init__(self, location, innerType): assert not innerType.isVoid() @@ -1842,15 +2000,27 @@ class IDLNullableType(IDLType): def isArrayBufferView(self): return self.inner.isArrayBufferView() + def isSharedArrayBuffer(self): + return self.inner.isSharedArrayBuffer() + + def isSharedArrayBufferView(self): + return self.inner.isSharedArrayBufferView() + def isTypedArray(self): return self.inner.isTypedArray() + def isSharedTypedArray(self): + return self.inner.isSharedTypedArray() + def isDictionary(self): return self.inner.isDictionary() def isInterface(self): return self.inner.isInterface() + def isPromise(self): + return self.inner.isPromise() + def isCallbackInterface(self): return self.inner.isCallbackInterface() @@ -1904,6 +2074,7 @@ class IDLNullableType(IDLType): def _getDependentObjects(self): return self.inner._getDependentObjects() + class IDLSequenceType(IDLType): def __init__(self, location, parameterType): assert not parameterType.isVoid() @@ -1926,10 +2097,10 @@ class IDLSequenceType(IDLType): return False def isPrimitive(self): - return False; + return False def isString(self): - return False; + return False def isByteString(self): return False @@ -1983,16 +2154,20 @@ class IDLSequenceType(IDLType): return self.inner.unroll() def isDistinguishableFrom(self, other): + if other.isPromise(): + return False if other.isUnion(): # 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.isInterface() or other.isDictionary() or + other.isDate() or other.isInterface() or + other.isDictionary() or other.isCallback() or other.isMozMap()) def _getDependentObjects(self): return self.inner._getDependentObjects() + class IDLMozMapType(IDLType): # XXXbz This is pretty similar to IDLSequenceType in various ways. # And maybe to IDLNullableType. Should we have a superclass for @@ -2042,6 +2217,8 @@ class IDLMozMapType(IDLType): return self def isDistinguishableFrom(self, other): + if other.isPromise(): + return False if other.isUnion(): # Just forward to the union; it'll deal return other.isDistinguishableFrom(self) @@ -2054,12 +2231,13 @@ class IDLMozMapType(IDLType): def _getDependentObjects(self): return self.inner._getDependentObjects() + class IDLUnionType(IDLType): def __init__(self, location, memberTypes): IDLType.__init__(self, location, "") self.memberTypes = memberTypes self.hasNullableType = False - self.hasDictionaryType = False + self._dictionaryType = None self.flatMemberTypes = None self.builtin = False @@ -2115,10 +2293,10 @@ class IDLUnionType(IDLType): if self.hasNullableType: raise WebIDLError("Can't have more than one nullable types in a union", [nullableType.location, self.flatMemberTypes[i].location]) - if self.hasDictionaryType: + if self.hasDictionaryType(): raise WebIDLError("Can't have a nullable type and a " "dictionary type in a union", - [dictionaryType.location, + [self._dictionaryType.location, self.flatMemberTypes[i].location]) self.hasNullableType = True nullableType = self.flatMemberTypes[i] @@ -2130,8 +2308,7 @@ class IDLUnionType(IDLType): "dictionary type in a union", [nullableType.location, self.flatMemberTypes[i].location]) - self.hasDictionaryType = True - dictionaryType = self.flatMemberTypes[i] + self._dictionaryType = self.flatMemberTypes[i] elif self.flatMemberTypes[i].isUnion(): self.flatMemberTypes[i:i + 1] = self.flatMemberTypes[i].memberTypes continue @@ -2170,9 +2347,17 @@ class IDLUnionType(IDLType): return False return True + def hasDictionaryType(self): + return self._dictionaryType is not None + + def hasPossiblyEmptyDictionaryType(self): + return (self._dictionaryType is not None and + self._dictionaryType.inner.canBeEmpty()) + def _getDependentObjects(self): return set(self.memberTypes) + class IDLArrayType(IDLType): def __init__(self, location, parameterType): assert not parameterType.isVoid() @@ -2261,6 +2446,8 @@ class IDLArrayType(IDLType): return self.inner.unroll() def isDistinguishableFrom(self, other): + if other.isPromise(): + return False if other.isUnion(): # Just forward to the union; it'll deal return other.isDistinguishableFrom(self) @@ -2270,23 +2457,18 @@ class IDLArrayType(IDLType): def _getDependentObjects(self): return self.inner._getDependentObjects() -class IDLTypedefType(IDLType, IDLObjectWithIdentifier): + +class IDLTypedefType(IDLType): def __init__(self, location, innerType, name): - IDLType.__init__(self, location, innerType.name) - - identifier = IDLUnresolvedIdentifier(location, name) - - IDLObjectWithIdentifier.__init__(self, location, None, identifier) - + IDLType.__init__(self, location, name) self.inner = innerType - self.name = name self.builtin = False def __eq__(self, other): return isinstance(other, IDLTypedefType) and self.inner == other.inner def __str__(self): - return self.identifier.name + return self.name def nullable(self): return self.inner.nullable() @@ -2333,9 +2515,18 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier): def isArrayBufferView(self): return self.inner.isArrayBufferView() + def isSharedArrayBuffer(self): + return self.inner.isSharedArrayBuffer() + + def isSharedArrayBufferView(self): + return self.inner.isSharedArrayBufferView() + def isTypedArray(self): return self.inner.isTypedArray() + def isSharedTypedArray(self): + return self.inner.isSharedTypedArray() + def isInterface(self): return self.inner.isInterface() @@ -2354,16 +2545,6 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier): assert self.inner.isComplete() return self.inner - def finish(self, parentScope): - # Maybe the IDLObjectWithIdentifier for the typedef should be - # a separate thing from the type? If that happens, we can - # remove some hackery around avoiding isInterface() in - # Configuration.py. - self.complete(parentScope) - - def validate(self): - pass - # Do we need a resolveType impl? I don't think it's particularly useful.... def tag(self): @@ -2378,6 +2559,33 @@ class IDLTypedefType(IDLType, IDLObjectWithIdentifier): def _getDependentObjects(self): return self.inner._getDependentObjects() + +class IDLTypedef(IDLObjectWithIdentifier): + def __init__(self, location, parentScope, innerType, name): + identifier = IDLUnresolvedIdentifier(location, name) + IDLObjectWithIdentifier.__init__(self, location, parentScope, identifier) + self.innerType = innerType + + def __str__(self): + return "Typedef %s %s" % (self.identifier.name, self.innerType) + + def finish(self, parentScope): + if not self.innerType.isComplete(): + self.innerType = self.innerType.complete(parentScope) + + def validate(self): + pass + + def isTypedef(self): + return True + + def addExtendedAttributes(self, attrs): + assert len(attrs) == 0 + + def _getDependentObjects(self): + return self.innerType._getDependentObjects() + + class IDLWrapperType(IDLType): def __init__(self, location, inner, promiseInnerType=None): IDLType.__init__(self, location, inner.identifier.name) @@ -2388,9 +2596,9 @@ class IDLWrapperType(IDLType): self._promiseInnerType = promiseInnerType def __eq__(self, other): - return isinstance(other, IDLWrapperType) and \ - self._identifier == other._identifier and \ - self.builtin == other.builtin + return (isinstance(other, IDLWrapperType) and + self._identifier == other._identifier and + self.builtin == other.builtin) def __str__(self): return str(self.name) + " (Wrapper)" @@ -2426,8 +2634,8 @@ class IDLWrapperType(IDLType): return isinstance(self.inner, IDLDictionary) def isInterface(self): - return isinstance(self.inner, IDLInterface) or \ - isinstance(self.inner, IDLExternalInterface) + return (isinstance(self.inner, IDLInterface) or + isinstance(self.inner, IDLExternalInterface)) def isCallbackInterface(self): return self.isInterface() and self.inner.isCallback() @@ -2439,8 +2647,12 @@ class IDLWrapperType(IDLType): return isinstance(self.inner, IDLEnum) def isPromise(self): - return isinstance(self.inner, IDLInterface) and \ - self.inner.identifier.name == "Promise" + return (isinstance(self.inner, IDLInterface) and + self.inner.identifier.name == "Promise") + + def promiseInnerType(self): + assert self.isPromise() + return self._promiseInnerType def isSerializable(self): if self.isInterface(): @@ -2473,6 +2685,10 @@ class IDLWrapperType(IDLType): assert False def isDistinguishableFrom(self, other): + if self.isPromise(): + return False + if other.isPromise(): + return False if other.isUnion(): # Just forward to the union; it'll deal return other.isDistinguishableFrom(self) @@ -2518,9 +2734,9 @@ class IDLWrapperType(IDLType): # Let's say true, though ideally we'd only do this when # exposureSet contains the primary global's name. return True - if (iface.identifier.name == "Promise" and + if (self.isPromise() and # Check the internal type - not self._promiseInnerType.unroll().isExposedInAllOf(exposureSet)): + not self.promiseInnerType().unroll().isExposedInAllOf(exposureSet)): return False return iface.exposureSet.issuperset(exposureSet) @@ -2548,6 +2764,7 @@ class IDLWrapperType(IDLType): return set([self.inner]) return set() + class IDLBuiltinType(IDLType): Types = enum( @@ -2578,6 +2795,8 @@ class IDLBuiltinType(IDLType): # Funny stuff 'ArrayBuffer', 'ArrayBufferView', + 'SharedArrayBuffer', + 'SharedArrayBufferView', 'Int8Array', 'Uint8Array', 'Uint8ClampedArray', @@ -2586,42 +2805,62 @@ class IDLBuiltinType(IDLType): 'Int32Array', 'Uint32Array', 'Float32Array', - 'Float64Array' + 'Float64Array', + 'SharedInt8Array', + 'SharedUint8Array', + 'SharedUint8ClampedArray', + 'SharedInt16Array', + 'SharedUint16Array', + 'SharedInt32Array', + 'SharedUint32Array', + 'SharedFloat32Array', + 'SharedFloat64Array' ) TagLookup = { - Types.byte: IDLType.Tags.int8, - Types.octet: IDLType.Tags.uint8, - Types.short: IDLType.Tags.int16, - Types.unsigned_short: IDLType.Tags.uint16, - Types.long: IDLType.Tags.int32, - Types.unsigned_long: IDLType.Tags.uint32, - Types.long_long: IDLType.Tags.int64, - Types.unsigned_long_long: IDLType.Tags.uint64, - Types.boolean: IDLType.Tags.bool, - Types.unrestricted_float: IDLType.Tags.unrestricted_float, - Types.float: IDLType.Tags.float, - Types.unrestricted_double: IDLType.Tags.unrestricted_double, - Types.double: IDLType.Tags.double, - Types.any: IDLType.Tags.any, - Types.domstring: IDLType.Tags.domstring, - Types.bytestring: IDLType.Tags.bytestring, - Types.usvstring: IDLType.Tags.usvstring, - Types.object: IDLType.Tags.object, - Types.date: IDLType.Tags.date, - Types.void: IDLType.Tags.void, - Types.ArrayBuffer: IDLType.Tags.interface, - Types.ArrayBufferView: IDLType.Tags.interface, - Types.Int8Array: IDLType.Tags.interface, - Types.Uint8Array: IDLType.Tags.interface, - Types.Uint8ClampedArray: IDLType.Tags.interface, - Types.Int16Array: IDLType.Tags.interface, - Types.Uint16Array: IDLType.Tags.interface, - Types.Int32Array: IDLType.Tags.interface, - Types.Uint32Array: IDLType.Tags.interface, - Types.Float32Array: IDLType.Tags.interface, - Types.Float64Array: IDLType.Tags.interface - } + Types.byte: IDLType.Tags.int8, + Types.octet: IDLType.Tags.uint8, + Types.short: IDLType.Tags.int16, + Types.unsigned_short: IDLType.Tags.uint16, + Types.long: IDLType.Tags.int32, + Types.unsigned_long: IDLType.Tags.uint32, + Types.long_long: IDLType.Tags.int64, + Types.unsigned_long_long: IDLType.Tags.uint64, + Types.boolean: IDLType.Tags.bool, + Types.unrestricted_float: IDLType.Tags.unrestricted_float, + Types.float: IDLType.Tags.float, + Types.unrestricted_double: IDLType.Tags.unrestricted_double, + Types.double: IDLType.Tags.double, + Types.any: IDLType.Tags.any, + Types.domstring: IDLType.Tags.domstring, + Types.bytestring: IDLType.Tags.bytestring, + Types.usvstring: IDLType.Tags.usvstring, + Types.object: IDLType.Tags.object, + Types.date: IDLType.Tags.date, + Types.void: IDLType.Tags.void, + Types.ArrayBuffer: IDLType.Tags.interface, + Types.ArrayBufferView: IDLType.Tags.interface, + Types.SharedArrayBuffer: IDLType.Tags.interface, + Types.SharedArrayBufferView: IDLType.Tags.interface, + Types.Int8Array: IDLType.Tags.interface, + Types.Uint8Array: IDLType.Tags.interface, + Types.Uint8ClampedArray: IDLType.Tags.interface, + Types.Int16Array: IDLType.Tags.interface, + Types.Uint16Array: IDLType.Tags.interface, + Types.Int32Array: IDLType.Tags.interface, + Types.Uint32Array: IDLType.Tags.interface, + Types.Float32Array: IDLType.Tags.interface, + Types.Float64Array: IDLType.Tags.interface, + Types.SharedInt8Array: IDLType.Tags.interface, + Types.SharedUint8Array: IDLType.Tags.interface, + Types.SharedUint8ClampedArray: IDLType.Tags.interface, + Types.SharedInt16Array: IDLType.Tags.interface, + Types.SharedUint16Array: IDLType.Tags.interface, + Types.SharedInt32Array: IDLType.Tags.interface, + Types.SharedUint32Array: IDLType.Tags.interface, + Types.SharedFloat32Array: IDLType.Tags.interface, + Types.SharedFloat64Array: IDLType.Tags.interface + } def __init__(self, location, name, type): IDLType.__init__(self, location, name) @@ -2638,9 +2877,9 @@ class IDLBuiltinType(IDLType): return self.isPrimitive() and not self.isBoolean() def isString(self): - return self._typeTag == IDLBuiltinType.Types.domstring or \ - self._typeTag == IDLBuiltinType.Types.bytestring or \ - self._typeTag == IDLBuiltinType.Types.usvstring + return (self._typeTag == IDLBuiltinType.Types.domstring or + self._typeTag == IDLBuiltinType.Types.bytestring or + self._typeTag == IDLBuiltinType.Types.usvstring) def isByteString(self): return self._typeTag == IDLBuiltinType.Types.bytestring @@ -2660,35 +2899,48 @@ class IDLBuiltinType(IDLType): def isArrayBufferView(self): return self._typeTag == IDLBuiltinType.Types.ArrayBufferView + def isSharedArrayBuffer(self): + return self._typeTag == IDLBuiltinType.Types.SharedArrayBuffer + + def isSharedArrayBufferView(self): + return self._typeTag == IDLBuiltinType.Types.SharedArrayBufferView + def isTypedArray(self): - return self._typeTag >= IDLBuiltinType.Types.Int8Array and \ - self._typeTag <= IDLBuiltinType.Types.Float64Array + return (self._typeTag >= IDLBuiltinType.Types.Int8Array and + self._typeTag <= IDLBuiltinType.Types.Float64Array) + + def isSharedTypedArray(self): + return (self._typeTag >= IDLBuiltinType.Types.SharedInt8Array and + self._typeTag <= IDLBuiltinType.Types.SharedFloat64Array) def isInterface(self): # TypedArray things are interface types per the TypedArray spec, # but we handle them as builtins because SpiderMonkey implements # all of it internally. - return self.isArrayBuffer() or \ - self.isArrayBufferView() or \ - self.isTypedArray() + return (self.isArrayBuffer() or + self.isArrayBufferView() or + self.isSharedArrayBuffer() or + self.isSharedArrayBufferView() or + self.isTypedArray() or + self.isSharedTypedArray()) def isNonCallbackInterface(self): # All the interfaces we can be are non-callback return self.isInterface() def isFloat(self): - return self._typeTag == IDLBuiltinType.Types.float or \ - self._typeTag == IDLBuiltinType.Types.double or \ - self._typeTag == IDLBuiltinType.Types.unrestricted_float or \ - self._typeTag == IDLBuiltinType.Types.unrestricted_double + return (self._typeTag == IDLBuiltinType.Types.float or + self._typeTag == IDLBuiltinType.Types.double or + self._typeTag == IDLBuiltinType.Types.unrestricted_float or + self._typeTag == IDLBuiltinType.Types.unrestricted_double) def isUnrestricted(self): assert self.isFloat() - return self._typeTag == IDLBuiltinType.Types.unrestricted_float or \ - self._typeTag == IDLBuiltinType.Types.unrestricted_double + return (self._typeTag == IDLBuiltinType.Types.unrestricted_float or + self._typeTag == IDLBuiltinType.Types.unrestricted_double) def isSerializable(self): - return self.isPrimitive() or self.isDOMString() or self.isDate() + return self.isPrimitive() or self.isString() or self.isDate() def includesRestrictedFloat(self): return self.isFloat() and not self.isUnrestricted() @@ -2697,6 +2949,8 @@ class IDLBuiltinType(IDLType): return IDLBuiltinType.TagLookup[self._typeTag] def isDistinguishableFrom(self, other): + if other.isPromise(): + return False if other.isUnion(): # Just forward to the union; it'll deal return other.isDistinguishableFrom(self) @@ -2741,127 +2995,165 @@ class IDLBuiltinType(IDLType): # ArrayBuffer is distinguishable from everything # that's not an ArrayBuffer or a callback interface (self.isArrayBuffer() and not other.isArrayBuffer()) or + (self.isSharedArrayBuffer() and not other.isSharedArrayBuffer()) or # ArrayBufferView is distinguishable from everything # that's not an ArrayBufferView or typed array. (self.isArrayBufferView() and not other.isArrayBufferView() and not other.isTypedArray()) or + (self.isSharedArrayBufferView() and not other.isSharedArrayBufferView() and + not other.isSharedTypedArray()) or # Typed arrays are distinguishable from everything # except ArrayBufferView and the same type of typed # array (self.isTypedArray() and not other.isArrayBufferView() and not - (other.isTypedArray() and other.name == self.name))))) + (other.isTypedArray() and other.name == self.name)) or + (self.isSharedTypedArray() and not other.isSharedArrayBufferView() and not + (other.isSharedTypedArray() and other.name == self.name))))) def _getDependentObjects(self): return set() BuiltinTypes = { - IDLBuiltinType.Types.byte: - IDLBuiltinType(BuiltinLocation(""), "Byte", - IDLBuiltinType.Types.byte), - IDLBuiltinType.Types.octet: - IDLBuiltinType(BuiltinLocation(""), "Octet", - IDLBuiltinType.Types.octet), - IDLBuiltinType.Types.short: - IDLBuiltinType(BuiltinLocation(""), "Short", - IDLBuiltinType.Types.short), - IDLBuiltinType.Types.unsigned_short: - IDLBuiltinType(BuiltinLocation(""), "UnsignedShort", - IDLBuiltinType.Types.unsigned_short), - IDLBuiltinType.Types.long: - IDLBuiltinType(BuiltinLocation(""), "Long", - IDLBuiltinType.Types.long), - IDLBuiltinType.Types.unsigned_long: - IDLBuiltinType(BuiltinLocation(""), "UnsignedLong", - IDLBuiltinType.Types.unsigned_long), - IDLBuiltinType.Types.long_long: - IDLBuiltinType(BuiltinLocation(""), "LongLong", - IDLBuiltinType.Types.long_long), - IDLBuiltinType.Types.unsigned_long_long: - IDLBuiltinType(BuiltinLocation(""), "UnsignedLongLong", - IDLBuiltinType.Types.unsigned_long_long), - IDLBuiltinType.Types.boolean: - IDLBuiltinType(BuiltinLocation(""), "Boolean", - IDLBuiltinType.Types.boolean), - IDLBuiltinType.Types.float: - IDLBuiltinType(BuiltinLocation(""), "Float", - IDLBuiltinType.Types.float), - IDLBuiltinType.Types.unrestricted_float: - IDLBuiltinType(BuiltinLocation(""), "UnrestrictedFloat", - IDLBuiltinType.Types.unrestricted_float), - IDLBuiltinType.Types.double: - IDLBuiltinType(BuiltinLocation(""), "Double", - IDLBuiltinType.Types.double), - IDLBuiltinType.Types.unrestricted_double: - IDLBuiltinType(BuiltinLocation(""), "UnrestrictedDouble", - IDLBuiltinType.Types.unrestricted_double), - IDLBuiltinType.Types.any: - IDLBuiltinType(BuiltinLocation(""), "Any", - IDLBuiltinType.Types.any), - IDLBuiltinType.Types.domstring: - IDLBuiltinType(BuiltinLocation(""), "String", - IDLBuiltinType.Types.domstring), - IDLBuiltinType.Types.bytestring: - IDLBuiltinType(BuiltinLocation(""), "ByteString", - IDLBuiltinType.Types.bytestring), - IDLBuiltinType.Types.usvstring: - IDLBuiltinType(BuiltinLocation(""), "USVString", - IDLBuiltinType.Types.usvstring), - IDLBuiltinType.Types.object: - IDLBuiltinType(BuiltinLocation(""), "Object", - IDLBuiltinType.Types.object), - IDLBuiltinType.Types.date: - IDLBuiltinType(BuiltinLocation(""), "Date", - IDLBuiltinType.Types.date), - IDLBuiltinType.Types.void: - IDLBuiltinType(BuiltinLocation(""), "Void", - IDLBuiltinType.Types.void), - IDLBuiltinType.Types.ArrayBuffer: - IDLBuiltinType(BuiltinLocation(""), "ArrayBuffer", - IDLBuiltinType.Types.ArrayBuffer), - IDLBuiltinType.Types.ArrayBufferView: - IDLBuiltinType(BuiltinLocation(""), "ArrayBufferView", - IDLBuiltinType.Types.ArrayBufferView), - IDLBuiltinType.Types.Int8Array: - IDLBuiltinType(BuiltinLocation(""), "Int8Array", - IDLBuiltinType.Types.Int8Array), - IDLBuiltinType.Types.Uint8Array: - IDLBuiltinType(BuiltinLocation(""), "Uint8Array", - IDLBuiltinType.Types.Uint8Array), - IDLBuiltinType.Types.Uint8ClampedArray: - IDLBuiltinType(BuiltinLocation(""), "Uint8ClampedArray", - IDLBuiltinType.Types.Uint8ClampedArray), - IDLBuiltinType.Types.Int16Array: - IDLBuiltinType(BuiltinLocation(""), "Int16Array", - IDLBuiltinType.Types.Int16Array), - IDLBuiltinType.Types.Uint16Array: - IDLBuiltinType(BuiltinLocation(""), "Uint16Array", - IDLBuiltinType.Types.Uint16Array), - IDLBuiltinType.Types.Int32Array: - IDLBuiltinType(BuiltinLocation(""), "Int32Array", - IDLBuiltinType.Types.Int32Array), - IDLBuiltinType.Types.Uint32Array: - IDLBuiltinType(BuiltinLocation(""), "Uint32Array", - IDLBuiltinType.Types.Uint32Array), - IDLBuiltinType.Types.Float32Array: - IDLBuiltinType(BuiltinLocation(""), "Float32Array", - IDLBuiltinType.Types.Float32Array), - IDLBuiltinType.Types.Float64Array: - IDLBuiltinType(BuiltinLocation(""), "Float64Array", - IDLBuiltinType.Types.Float64Array) - } + IDLBuiltinType.Types.byte: + IDLBuiltinType(BuiltinLocation(""), "Byte", + IDLBuiltinType.Types.byte), + IDLBuiltinType.Types.octet: + IDLBuiltinType(BuiltinLocation(""), "Octet", + IDLBuiltinType.Types.octet), + IDLBuiltinType.Types.short: + IDLBuiltinType(BuiltinLocation(""), "Short", + IDLBuiltinType.Types.short), + IDLBuiltinType.Types.unsigned_short: + IDLBuiltinType(BuiltinLocation(""), "UnsignedShort", + IDLBuiltinType.Types.unsigned_short), + IDLBuiltinType.Types.long: + IDLBuiltinType(BuiltinLocation(""), "Long", + IDLBuiltinType.Types.long), + IDLBuiltinType.Types.unsigned_long: + IDLBuiltinType(BuiltinLocation(""), "UnsignedLong", + IDLBuiltinType.Types.unsigned_long), + IDLBuiltinType.Types.long_long: + IDLBuiltinType(BuiltinLocation(""), "LongLong", + IDLBuiltinType.Types.long_long), + IDLBuiltinType.Types.unsigned_long_long: + IDLBuiltinType(BuiltinLocation(""), "UnsignedLongLong", + IDLBuiltinType.Types.unsigned_long_long), + IDLBuiltinType.Types.boolean: + IDLBuiltinType(BuiltinLocation(""), "Boolean", + IDLBuiltinType.Types.boolean), + IDLBuiltinType.Types.float: + IDLBuiltinType(BuiltinLocation(""), "Float", + IDLBuiltinType.Types.float), + IDLBuiltinType.Types.unrestricted_float: + IDLBuiltinType(BuiltinLocation(""), "UnrestrictedFloat", + IDLBuiltinType.Types.unrestricted_float), + IDLBuiltinType.Types.double: + IDLBuiltinType(BuiltinLocation(""), "Double", + IDLBuiltinType.Types.double), + IDLBuiltinType.Types.unrestricted_double: + IDLBuiltinType(BuiltinLocation(""), "UnrestrictedDouble", + IDLBuiltinType.Types.unrestricted_double), + IDLBuiltinType.Types.any: + IDLBuiltinType(BuiltinLocation(""), "Any", + IDLBuiltinType.Types.any), + IDLBuiltinType.Types.domstring: + IDLBuiltinType(BuiltinLocation(""), "String", + IDLBuiltinType.Types.domstring), + IDLBuiltinType.Types.bytestring: + IDLBuiltinType(BuiltinLocation(""), "ByteString", + IDLBuiltinType.Types.bytestring), + IDLBuiltinType.Types.usvstring: + IDLBuiltinType(BuiltinLocation(""), "USVString", + IDLBuiltinType.Types.usvstring), + IDLBuiltinType.Types.object: + IDLBuiltinType(BuiltinLocation(""), "Object", + IDLBuiltinType.Types.object), + IDLBuiltinType.Types.date: + IDLBuiltinType(BuiltinLocation(""), "Date", + IDLBuiltinType.Types.date), + IDLBuiltinType.Types.void: + IDLBuiltinType(BuiltinLocation(""), "Void", + IDLBuiltinType.Types.void), + IDLBuiltinType.Types.ArrayBuffer: + IDLBuiltinType(BuiltinLocation(""), "ArrayBuffer", + IDLBuiltinType.Types.ArrayBuffer), + IDLBuiltinType.Types.ArrayBufferView: + IDLBuiltinType(BuiltinLocation(""), "ArrayBufferView", + IDLBuiltinType.Types.ArrayBufferView), + IDLBuiltinType.Types.SharedArrayBuffer: + IDLBuiltinType(BuiltinLocation(""), "SharedArrayBuffer", + IDLBuiltinType.Types.SharedArrayBuffer), + IDLBuiltinType.Types.SharedArrayBufferView: + IDLBuiltinType(BuiltinLocation(""), "SharedArrayBufferView", + IDLBuiltinType.Types.SharedArrayBufferView), + IDLBuiltinType.Types.Int8Array: + IDLBuiltinType(BuiltinLocation(""), "Int8Array", + IDLBuiltinType.Types.Int8Array), + IDLBuiltinType.Types.Uint8Array: + IDLBuiltinType(BuiltinLocation(""), "Uint8Array", + IDLBuiltinType.Types.Uint8Array), + IDLBuiltinType.Types.Uint8ClampedArray: + IDLBuiltinType(BuiltinLocation(""), "Uint8ClampedArray", + IDLBuiltinType.Types.Uint8ClampedArray), + IDLBuiltinType.Types.Int16Array: + IDLBuiltinType(BuiltinLocation(""), "Int16Array", + IDLBuiltinType.Types.Int16Array), + IDLBuiltinType.Types.Uint16Array: + IDLBuiltinType(BuiltinLocation(""), "Uint16Array", + IDLBuiltinType.Types.Uint16Array), + IDLBuiltinType.Types.Int32Array: + IDLBuiltinType(BuiltinLocation(""), "Int32Array", + IDLBuiltinType.Types.Int32Array), + IDLBuiltinType.Types.Uint32Array: + IDLBuiltinType(BuiltinLocation(""), "Uint32Array", + IDLBuiltinType.Types.Uint32Array), + IDLBuiltinType.Types.Float32Array: + IDLBuiltinType(BuiltinLocation(""), "Float32Array", + IDLBuiltinType.Types.Float32Array), + IDLBuiltinType.Types.Float64Array: + IDLBuiltinType(BuiltinLocation(""), "Float64Array", + IDLBuiltinType.Types.Float64Array), + IDLBuiltinType.Types.SharedInt8Array: + IDLBuiltinType(BuiltinLocation(""), "SharedInt8Array", + IDLBuiltinType.Types.SharedInt8Array), + IDLBuiltinType.Types.SharedUint8Array: + IDLBuiltinType(BuiltinLocation(""), "SharedUint8Array", + IDLBuiltinType.Types.SharedUint8Array), + IDLBuiltinType.Types.SharedUint8ClampedArray: + IDLBuiltinType(BuiltinLocation(""), "SharedUint8ClampedArray", + IDLBuiltinType.Types.SharedUint8ClampedArray), + IDLBuiltinType.Types.SharedInt16Array: + IDLBuiltinType(BuiltinLocation(""), "SharedInt16Array", + IDLBuiltinType.Types.SharedInt16Array), + IDLBuiltinType.Types.SharedUint16Array: + IDLBuiltinType(BuiltinLocation(""), "SharedUint16Array", + IDLBuiltinType.Types.SharedUint16Array), + IDLBuiltinType.Types.SharedInt32Array: + IDLBuiltinType(BuiltinLocation(""), "SharedInt32Array", + IDLBuiltinType.Types.SharedInt32Array), + IDLBuiltinType.Types.SharedUint32Array: + IDLBuiltinType(BuiltinLocation(""), "SharedUint32Array", + IDLBuiltinType.Types.SharedUint32Array), + IDLBuiltinType.Types.SharedFloat32Array: + IDLBuiltinType(BuiltinLocation(""), "SharedFloat32Array", + IDLBuiltinType.Types.SharedFloat32Array), + IDLBuiltinType.Types.SharedFloat64Array: + IDLBuiltinType(BuiltinLocation(""), "SharedFloat64Array", + IDLBuiltinType.Types.SharedFloat64Array) +} integerTypeSizes = { - IDLBuiltinType.Types.byte: (-128, 127), - IDLBuiltinType.Types.octet: (0, 255), - IDLBuiltinType.Types.short: (-32768, 32767), - IDLBuiltinType.Types.unsigned_short: (0, 65535), - IDLBuiltinType.Types.long: (-2147483648, 2147483647), - IDLBuiltinType.Types.unsigned_long: (0, 4294967295), - IDLBuiltinType.Types.long_long: (-9223372036854775808, - 9223372036854775807), - IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615) - } + IDLBuiltinType.Types.byte: (-128, 127), + IDLBuiltinType.Types.octet: (0, 255), + IDLBuiltinType.Types.short: (-32768, 32767), + IDLBuiltinType.Types.unsigned_short: (0, 65535), + IDLBuiltinType.Types.long: (-2147483648, 2147483647), + IDLBuiltinType.Types.unsigned_long: (0, 4294967295), + IDLBuiltinType.Types.long_long: (-9223372036854775808, 9223372036854775807), + IDLBuiltinType.Types.unsigned_long_long: (0, 18446744073709551615) +} + def matchIntegerValueToType(value): for type, extremes in integerTypeSizes.items(): @@ -2871,6 +3163,7 @@ def matchIntegerValueToType(value): return None + class IDLValue(IDLObject): def __init__(self, location, type, value): IDLObject.__init__(self, location) @@ -2881,7 +3174,7 @@ class IDLValue(IDLObject): def coerceToType(self, type, location): if type == self.type: - return self # Nothing to do + return self # Nothing to do # We first check for unions to ensure that even if the union is nullable # we end up with the right flat member type, not the union's type. @@ -2952,6 +3245,7 @@ class IDLValue(IDLObject): def _getDependentObjects(self): return set() + class IDLNullValue(IDLObject): def __init__(self, location): IDLObject.__init__(self, location) @@ -2961,14 +3255,14 @@ class IDLNullValue(IDLObject): def coerceToType(self, type, location): if (not isinstance(type, IDLNullableType) and not (type.isUnion() and type.hasNullableType) and - not (type.isUnion() and type.hasDictionaryType) and + not (type.isUnion() and type.hasDictionaryType()) and not type.isDictionary() and not type.isAny()): raise WebIDLError("Cannot coerce null value to type %s." % type, [location]) nullValue = IDLNullValue(self.location) - if type.isUnion() and not type.nullable() and type.hasDictionaryType: + if type.isUnion() and not type.nullable() and type.hasDictionaryType(): # We're actually a default value for the union's dictionary member. # Use its type. for t in type.flatMemberTypes: @@ -2981,6 +3275,7 @@ class IDLNullValue(IDLObject): def _getDependentObjects(self): return set() + class IDLEmptySequenceValue(IDLObject): def __init__(self, location): IDLObject.__init__(self, location) @@ -3009,6 +3304,7 @@ class IDLEmptySequenceValue(IDLObject): def _getDependentObjects(self): return set() + class IDLUndefinedValue(IDLObject): def __init__(self, location): IDLObject.__init__(self, location) @@ -3027,12 +3323,14 @@ class IDLUndefinedValue(IDLObject): def _getDependentObjects(self): return set() + class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): Tags = enum( 'Const', 'Attr', - 'Method' + 'Method', + 'MaplikeOrSetlike' ) Special = enum( @@ -3058,6 +3356,9 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): def isConst(self): return self.tag == IDLInterfaceMember.Tags.Const + def isMaplikeOrSetlike(self): + return self.tag == IDLInterfaceMember.Tags.MaplikeOrSetlike + def addExtendedAttributes(self, attrs): for attr in attrs: self.handleExtendedAttribute(attr) @@ -3084,12 +3385,13 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): "%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]) + for attribute in ["CheckAnyPermissions", "CheckAllPermissions"]: + if (self.getExtendedAttribute(attribute) and + self.exposureSet != set([self._globalScope.primaryGlobalName])): + raise WebIDLError("[%s] used on an interface member that is " + "not %s-only" % + (attribute, self.parentScope.primaryGlobalName), + [self.location]) if self.isAttr() or self.isMethod(): if self.affects == "Everything" and self.dependsOn != "Everything": @@ -3098,6 +3400,12 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): "That seems rather unlikely.", [self.location]) + if self.getExtendedAttribute("NewObject"): + if self.dependsOn == "Nothing" or self.dependsOn == "DOMState": + raise WebIDLError("A [NewObject] method is not idempotent, " + "so it has to depend on something other than DOM state.", + [self.location]) + def _setDependsOn(self, dependsOn): if self.dependsOn != "Everything": raise WebIDLError("Trying to specify multiple different DependsOn, " @@ -3118,6 +3426,262 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins): [self.location]) self.affects = affects + def _addAlias(self, alias): + if alias in self.aliases: + raise WebIDLError("Duplicate [Alias=%s] on attribute" % alias, + [self.location]) + self.aliases.append(alias) + + +# MaplikeOrSetlike adds a trait to an interface, like map or iteration +# functions. To handle them while still getting all of the generated binding +# code taken care of, we treat them as macros that are expanded into members +# based on parsed values. +class IDLMaplikeOrSetlike(IDLInterfaceMember): + + MaplikeOrSetlikeTypes = enum( + 'maplike', + 'setlike' + ) + + def __init__(self, location, identifier, maplikeOrSetlikeType, + readonly, keyType, valueType): + IDLInterfaceMember.__init__(self, location, identifier, + IDLInterfaceMember.Tags.MaplikeOrSetlike) + + assert isinstance(keyType, IDLType) + assert isinstance(valueType, IDLType) + self.maplikeOrSetlikeType = maplikeOrSetlikeType + self.readonly = readonly + self.keyType = keyType + self.valueType = valueType + self.slotIndex = None + self.disallowedMemberNames = [] + self.disallowedNonMethodNames = [] + + # When generating JSAPI access code, we need to know the backing object + # type prefix to create the correct function. Generate here for reuse. + if self.isMaplike(): + self.prefix = 'Map' + elif self.isSetlike(): + self.prefix = 'Set' + + def __str__(self): + return "declared '%s' with key '%s'" % (self.maplikeOrSetlikeType, self.keyType) + + def isMaplike(self): + return self.maplikeOrSetlikeType == "maplike" + + def isSetlike(self): + return self.maplikeOrSetlikeType == "setlike" + + def checkCollisions(self, members, isAncestor): + for member in members: + # Check that there are no disallowed members + if (member.identifier.name in self.disallowedMemberNames and + not ((member.isMethod() and member.isMaplikeOrSetlikeMethod()) or + (member.isAttr() and member.isMaplikeOrSetlikeAttr()))): + raise WebIDLError("Member '%s' conflicts " + "with reserved %s name." % + (member.identifier.name, + self.maplikeOrSetlikeType), + [self.location, member.location]) + # Check that there are no disallowed non-method members + if (isAncestor or (member.isAttr() or member.isConst()) and + member.identifier.name in self.disallowedNonMethodNames): + raise WebIDLError("Member '%s' conflicts " + "with reserved %s method." % + (member.identifier.name, + self.maplikeOrSetlikeType), + [self.location, member.location]) + + def expand(self, members, isJSImplemented): + """ + In order to take advantage of all of the method machinery in Codegen, + we generate our functions as if they were part of the interface + specification during parsing. + """ + def addMethod(name, allowExistingOperations, returnType, args=[], + chromeOnly=False, isPure=False, affectsNothing=False): + """ + Create an IDLMethod based on the parameters passed in. chromeOnly is only + True for read-only js implemented classes, to implement underscore + prefixed convenience functions would otherwise not be available, + unlike the case of C++ bindings. isPure is only True for + idempotent functions, so it is not valid for things like keys, + values, etc. that return a new object every time. + + """ + + # Only add name to lists for collision checks if it's not chrome + # only. + if chromeOnly: + name = "__" + name + else: + if not allowExistingOperations: + self.disallowedMemberNames.append(name) + else: + self.disallowedNonMethodNames.append(name) + + # If allowExistingOperations is True, and another operation exists + # with the same name as the one we're trying to add, don't add the + # maplike/setlike operation. However, if the operation is static, + # then fail by way of creating the function, which will cause a + # naming conflict, per the spec. + if allowExistingOperations: + for m in members: + if m.identifier.name == name and m.isMethod() and not m.isStatic(): + return + + method = IDLMethod(self.location, + IDLUnresolvedIdentifier(self.location, name, allowDoubleUnderscore=chromeOnly), + returnType, args, maplikeOrSetlike=self) + + # We need to be able to throw from declaration methods + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("Throws",))]) + if chromeOnly: + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("ChromeOnly",))]) + if isPure: + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("Pure",))]) + # Following attributes are used for keys/values/entries. Can't mark + # them pure, since they return a new object each time they are run. + if affectsNothing: + method.addExtendedAttributes( + [IDLExtendedAttribute(self.location, ("DependsOn", "Everything")), + IDLExtendedAttribute(self.location, ("Affects", "Nothing"))]) + members.append(method) + + # Both maplike and setlike have a size attribute + members.append(IDLAttribute(self.location, + IDLUnresolvedIdentifier(BuiltinLocation(""), "size"), + BuiltinTypes[IDLBuiltinType.Types.unsigned_long], + True, + maplikeOrSetlike=self)) + self.reserved_ro_names = ["size"] + + # object entries() + addMethod("entries", False, BuiltinTypes[IDLBuiltinType.Types.object], + affectsNothing=True) + # object keys() + addMethod("keys", False, BuiltinTypes[IDLBuiltinType.Types.object], + affectsNothing=True) + # object values() + addMethod("values", False, BuiltinTypes[IDLBuiltinType.Types.object], + affectsNothing=True) + + # void forEach(callback(valueType, keyType), thisVal) + foreachArguments = [IDLArgument(self.location, + IDLUnresolvedIdentifier(BuiltinLocation(""), + "callback"), + BuiltinTypes[IDLBuiltinType.Types.object]), + IDLArgument(self.location, + IDLUnresolvedIdentifier(BuiltinLocation(""), + "thisArg"), + BuiltinTypes[IDLBuiltinType.Types.any], + optional=True)] + addMethod("forEach", False, BuiltinTypes[IDLBuiltinType.Types.void], + foreachArguments) + + def getKeyArg(): + return IDLArgument(self.location, + IDLUnresolvedIdentifier(self.location, "key"), + self.keyType) + + # boolean has(keyType key) + addMethod("has", False, BuiltinTypes[IDLBuiltinType.Types.boolean], + [getKeyArg()], isPure=True) + + if not self.readonly: + # void clear() + addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void], + []) + # boolean delete(keyType key) + addMethod("delete", True, + BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()]) + + # Always generate underscored functions (e.g. __add, __clear) for js + # implemented interfaces as convenience functions. + if isJSImplemented: + # void clear() + addMethod("clear", True, BuiltinTypes[IDLBuiltinType.Types.void], + [], chromeOnly=True) + # boolean delete(keyType key) + addMethod("delete", True, + BuiltinTypes[IDLBuiltinType.Types.boolean], [getKeyArg()], + chromeOnly=True) + + if self.isSetlike(): + if not self.readonly: + # Add returns the set object it just added to. + # object add(keyType key) + + addMethod("add", True, + BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()]) + if isJSImplemented: + addMethod("add", True, + BuiltinTypes[IDLBuiltinType.Types.object], [getKeyArg()], + chromeOnly=True) + return + + # If we get this far, we're a maplike declaration. + + # valueType get(keyType key) + # + # Note that instead of the value type, we're using any here. The + # validity checks should happen as things are inserted into the map, + # and using any as the return type makes code generation much simpler. + # + # TODO: Bug 1155340 may change this to use specific type to provide + # more info to JIT. + addMethod("get", False, BuiltinTypes[IDLBuiltinType.Types.any], + [getKeyArg()], isPure=True) + + def getValueArg(): + return IDLArgument(self.location, + IDLUnresolvedIdentifier(self.location, "value"), + self.valueType) + + if not self.readonly: + addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object], + [getKeyArg(), getValueArg()]) + if isJSImplemented: + addMethod("set", True, BuiltinTypes[IDLBuiltinType.Types.object], + [getKeyArg(), getValueArg()], chromeOnly=True) + + def resolve(self, parentScope): + self.keyType.resolveType(parentScope) + self.valueType.resolveType(parentScope) + + def finish(self, scope): + IDLInterfaceMember.finish(self, scope) + if not self.keyType.isComplete(): + t = self.keyType.complete(scope) + + assert not isinstance(t, IDLUnresolvedType) + assert not isinstance(t, IDLTypedefType) + assert not isinstance(t.name, IDLUnresolvedIdentifier) + self.keyType = t + if not self.valueType.isComplete(): + t = self.valueType.complete(scope) + + assert not isinstance(t, IDLUnresolvedType) + assert not isinstance(t, IDLTypedefType) + assert not isinstance(t.name, IDLUnresolvedIdentifier) + self.valueType = t + + def validate(self): + IDLInterfaceMember.validate(self) + + def handleExtendedAttribute(self, attr): + IDLInterfaceMember.handleExtendedAttribute(self, attr) + + def _getDependentObjects(self): + return set([self.keyType, self.valueType]) + + class IDLConst(IDLInterfaceMember): def __init__(self, location, identifier, type, value): IDLInterfaceMember.__init__(self, location, identifier, @@ -3168,7 +3732,8 @@ class IDLConst(IDLInterfaceMember): identifier == "ChromeOnly" or identifier == "Func" or identifier == "AvailableIn" or - identifier == "CheckPermissions"): + identifier == "CheckAnyPermissions" or + identifier == "CheckAllPermissions"): # Known attributes that we don't need to do anything with here pass else: @@ -3179,9 +3744,10 @@ class IDLConst(IDLInterfaceMember): def _getDependentObjects(self): return set([self.type, self.value]) + class IDLAttribute(IDLInterfaceMember): def __init__(self, location, identifier, type, readonly, inherit=False, - static=False, stringifier=False): + static=False, stringifier=False, maplikeOrSetlike=None): IDLInterfaceMember.__init__(self, location, identifier, IDLInterfaceMember.Tags.Attr) @@ -3196,6 +3762,8 @@ class IDLAttribute(IDLInterfaceMember): self.enforceRange = False self.clamp = False self.slotIndex = None + assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike) + self.maplikeOrSetlike = maplikeOrSetlike self.dependsOn = "Everything" self.affects = "Everything" @@ -3423,6 +3991,7 @@ class IDLAttribute(IDLInterfaceMember): [attr.location, self.location]) self._setDependsOn(attr.value()) elif (identifier == "Pref" or + identifier == "Deprecated" or identifier == "SetterThrows" or identifier == "Throws" or identifier == "GetterThrows" or @@ -3432,7 +4001,8 @@ class IDLAttribute(IDLInterfaceMember): identifier == "AvailableIn" or identifier == "NewObject" or identifier == "UnsafeInPrerendering" or - identifier == "CheckPermissions" or + identifier == "CheckAnyPermissions" or + identifier == "CheckAllPermissions" or identifier == "BinaryName"): # Known attributes that we don't need to do anything with here pass @@ -3453,12 +4023,21 @@ class IDLAttribute(IDLInterfaceMember): def hasLenientThis(self): return self.lenientThis + def isMaplikeOrSetlikeAttr(self): + """ + True if this attribute was generated from an interface with + maplike/setlike (e.g. this is the size attribute for + maplike/setlike) + """ + return self.maplikeOrSetlike is not None + def isUnforgeable(self): return self._unforgeable def _getDependentObjects(self): return set([self.type]) + class IDLArgument(IDLObjectWithIdentifier): def __init__(self, location, identifier, type, optional=False, defaultValue=None, variadic=False, dictionaryMember=False): IDLObjectWithIdentifier.__init__(self, location, None, identifier) @@ -3491,7 +4070,7 @@ class IDLArgument(IDLObjectWithIdentifier): [attribute.location]) if self.enforceRange: raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", - [self.location]); + [self.location]) self.clamp = True elif identifier == "EnforceRange": if not attribute.noArguments(): @@ -3499,12 +4078,14 @@ class IDLArgument(IDLObjectWithIdentifier): [attribute.location]) if self.clamp: raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive", - [self.location]); + [self.location]) self.enforceRange = True elif identifier == "TreatNonCallableAsNull": self._allowTreatNonCallableAsNull = True else: - raise WebIDLError("Unhandled extended attribute on an argument", + raise WebIDLError("Unhandled extended attribute on %s" % + ("a dictionary member" if self.dictionaryMember else + "an argument"), [attribute.location]) def isComplete(self): @@ -3524,7 +4105,7 @@ class IDLArgument(IDLObjectWithIdentifier): self.type = type if ((self.type.isDictionary() or - self.type.isUnion() and self.type.unroll().hasDictionaryType) and + 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, # for simplicity, so the codegen doesn't have to special-case this. @@ -3557,12 +4138,11 @@ class IDLArgument(IDLObjectWithIdentifier): def canHaveMissingValue(self): return self.optional and not self.defaultValue -class IDLCallbackType(IDLType, IDLObjectWithScope): + +class IDLCallback(IDLObjectWithScope): def __init__(self, location, parentScope, identifier, returnType, arguments): assert isinstance(returnType, IDLType) - IDLType.__init__(self, location, identifier.name) - self._returnType = returnType # Clone the list self._arguments = list(arguments) @@ -3585,9 +4165,6 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): def signatures(self): return [(self._returnType, self._arguments)] - def tag(self): - return IDLType.Tags.callback - def finish(self, scope): if not self._returnType.isComplete(): type = self._returnType.complete(scope) @@ -3611,14 +4188,6 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): def validate(self): pass - def isDistinguishableFrom(self, other): - if other.isUnion(): - # 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() or - other.isSequence()) - def addExtendedAttributes(self, attrs): unhandledAttrs = [] for attr in attrs: @@ -3637,6 +4206,32 @@ class IDLCallbackType(IDLType, IDLObjectWithScope): def _getDependentObjects(self): return set([self._returnType] + self._arguments) + +class IDLCallbackType(IDLType): + def __init__(self, location, callback): + IDLType.__init__(self, location, callback.identifier.name) + self.callback = callback + + def isCallback(self): + return True + + def tag(self): + return IDLType.Tags.callback + + def isDistinguishableFrom(self, other): + if other.isPromise(): + return False + if other.isUnion(): + # 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() or + other.isSequence()) + + def _getDependentObjects(self): + return self.callback._getDependentObjects() + + class IDLMethodOverload: """ A class that represents a single overload of a WebIDL method. This is not @@ -3657,6 +4252,7 @@ class IDLMethodOverload: deps.add(self.returnType) return deps + class IDLMethod(IDLInterfaceMember, IDLScope): Special = enum( @@ -3683,7 +4279,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def __init__(self, location, identifier, returnType, arguments, static=False, getter=False, setter=False, creator=False, deleter=False, specialType=NamedOrIndexed.Neither, - legacycaller=False, stringifier=False, jsonifier=False): + legacycaller=False, stringifier=False, jsonifier=False, + maplikeOrSetlike=None): # REVIEW: specialType is NamedOrIndexed -- wow, this is messed up. IDLInterfaceMember.__init__(self, location, identifier, IDLInterfaceMember.Tags.Method) @@ -3711,10 +4308,13 @@ class IDLMethod(IDLInterfaceMember, IDLScope): self._stringifier = stringifier assert isinstance(jsonifier, bool) self._jsonifier = jsonifier + assert maplikeOrSetlike is None or isinstance(maplikeOrSetlike, IDLMaplikeOrSetlike) + self.maplikeOrSetlike = maplikeOrSetlike self._specialType = specialType self._unforgeable = False self.dependsOn = "Everything" self.affects = "Everything" + self.aliases = [] if static and identifier.name == "prototype": raise WebIDLError("The identifier of a static operation must not be 'prototype'", @@ -3729,10 +4329,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope): if self._getter or self._deleter: assert len(self._overloads) == 1 overload = self._overloads[0] - arguments = overload.arguments + arguments = overload.arguments assert len(arguments) == 1 - assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \ - arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long] + assert (arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or + arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]) assert not arguments[0].optional and not arguments[0].variadic assert not self._getter or not overload.returnType.isVoid() @@ -3740,8 +4340,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope): assert len(self._overloads) == 1 arguments = self._overloads[0].arguments assert len(arguments) == 2 - assert arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or \ - arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long] + assert (arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.domstring] or + arguments[0].type == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]) assert not arguments[0].optional and not arguments[0].variadic assert not arguments[1].optional and not arguments[1].variadic @@ -3773,13 +4373,13 @@ class IDLMethod(IDLInterfaceMember, IDLScope): return self._deleter def isNamed(self): - assert self._specialType == IDLMethod.NamedOrIndexed.Named or \ - self._specialType == IDLMethod.NamedOrIndexed.Indexed + assert (self._specialType == IDLMethod.NamedOrIndexed.Named or + self._specialType == IDLMethod.NamedOrIndexed.Indexed) return self._specialType == IDLMethod.NamedOrIndexed.Named def isIndexed(self): - assert self._specialType == IDLMethod.NamedOrIndexed.Named or \ - self._specialType == IDLMethod.NamedOrIndexed.Indexed + assert (self._specialType == IDLMethod.NamedOrIndexed.Named or + self._specialType == IDLMethod.NamedOrIndexed.Indexed) return self._specialType == IDLMethod.NamedOrIndexed.Indexed def isLegacycaller(self): @@ -3791,11 +4391,26 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def isJsonifier(self): return self._jsonifier + def isMaplikeOrSetlikeMethod(self): + """ + True if this method was generated as part of a + maplike/setlike/etc interface (e.g. has/get methods) + """ + return self.maplikeOrSetlike is not None + def hasOverloads(self): return self._hasOverloads def isIdentifierLess(self): - return self.identifier.name[:2] == "__" + """ + True if the method name started with __, and if the method is not a + maplike/setlike method. Interfaces with maplike/setlike will generate + methods starting with __ for chrome only backing object access in JS + implemented interfaces, so while these functions use what is considered + an non-identifier name, they actually DO have an identifier. + """ + return (self.identifier.name[:2] == "__" and + not self.isMaplikeOrSetlikeMethod()) def resolve(self, parentScope): assert isinstance(parentScope, IDLScope) @@ -3848,45 +4463,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope): def finish(self, scope): IDLInterfaceMember.finish(self, scope) - overloadWithPromiseReturnType = None - overloadWithoutPromiseReturnType = None for overload in self._overloads: - variadicArgument = None - - arguments = overload.arguments - for (idx, argument) in enumerate(arguments): - if not argument.isComplete(): - argument.complete(scope) - assert argument.type.isComplete() - - if (argument.type.isDictionary() or - (argument.type.isUnion() and - argument.type.unroll().hasDictionaryType)): - # Dictionaries and unions containing dictionaries at the - # end of the list or followed by optional arguments must be - # optional. - if (not argument.optional and - all(arg.optional for arg in arguments[idx+1:])): - raise WebIDLError("Dictionary argument or union " - "argument containing a dictionary " - "not followed by a required argument " - "must be optional", - [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]) - - # Only the last argument can be variadic - if variadicArgument: - raise WebIDLError("Variadic argument is not last argument", - [variadicArgument.location]) - if argument.variadic: - variadicArgument = argument - returnType = overload.returnType if not returnType.isComplete(): returnType = returnType.complete(scope) @@ -3895,28 +4472,16 @@ class IDLMethod(IDLInterfaceMember, IDLScope): assert not isinstance(returnType.name, IDLUnresolvedIdentifier) overload.returnType = returnType - if returnType.isPromise(): - overloadWithPromiseReturnType = overload - else: - overloadWithoutPromiseReturnType = overload - - # Make sure either all our overloads return Promises or none do - if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType: - raise WebIDLError("We have overloads with both Promise and " - "non-Promise return types", - [overloadWithPromiseReturnType.location, - overloadWithoutPromiseReturnType.location]) - - if overloadWithPromiseReturnType and self._legacycaller: - raise WebIDLError("May not have a Promise return type for a " - "legacycaller.", - [overloadWithPromiseReturnType.location]) + for argument in overload.arguments: + if not argument.isComplete(): + argument.complete(scope) + assert argument.type.isComplete() # Now compute various information that will be used by the # WebIDL overload resolution algorithm. self.maxArgCount = max(len(s[1]) for s in self.signatures()) - self.allowedArgCounts = [ i for i in range(self.maxArgCount+1) - if len(self.signaturesForArgCount(i)) != 0 ] + self.allowedArgCounts = [i for i in range(self.maxArgCount+1) + if len(self.signaturesForArgCount(i)) != 0] def validate(self): IDLInterfaceMember.validate(self) @@ -3940,12 +4505,73 @@ class IDLMethod(IDLInterfaceMember, IDLScope): distinguishingIndex), [self.location, overload.location]) + overloadWithPromiseReturnType = None + overloadWithoutPromiseReturnType = None for overload in self._overloads: - if not overload.returnType.unroll().isExposedInAllOf(self.exposureSet): + returnType = overload.returnType + if not returnType.unroll().isExposedInAllOf(self.exposureSet): raise WebIDLError("Overload returns a type that is not exposed " "everywhere where the method is exposed", [overload.location]) + variadicArgument = None + + arguments = overload.arguments + for (idx, argument) in enumerate(arguments): + assert argument.type.isComplete() + + if ((argument.type.isDictionary() and + argument.type.inner.canBeEmpty())or + (argument.type.isUnion() and + argument.type.unroll().hasPossiblyEmptyDictionaryType())): + # Optional dictionaries and unions containing optional + # dictionaries at the end of the list or followed by + # optional arguments must be optional. + if (not argument.optional and + all(arg.optional for arg in arguments[idx+1:])): + raise WebIDLError("Dictionary argument or union " + "argument containing a dictionary " + "not followed by a required argument " + "must be optional", + [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]) + + # Only the last argument can be variadic + if variadicArgument: + raise WebIDLError("Variadic argument is not last argument", + [variadicArgument.location]) + if argument.variadic: + variadicArgument = argument + + if returnType.isPromise(): + overloadWithPromiseReturnType = overload + else: + overloadWithoutPromiseReturnType = overload + + # Make sure either all our overloads return Promises or none do + if overloadWithPromiseReturnType and overloadWithoutPromiseReturnType: + raise WebIDLError("We have overloads with both Promise and " + "non-Promise return types", + [overloadWithPromiseReturnType.location, + overloadWithoutPromiseReturnType.location]) + + if overloadWithPromiseReturnType and self._legacycaller: + raise WebIDLError("May not have a Promise return type for a " + "legacycaller.", + [overloadWithPromiseReturnType.location]) + + if self.getExtendedAttribute("StaticClassOverride") and not \ + (self.identifier.scope.isJSImplemented() and self.isStatic()): + raise WebIDLError("StaticClassOverride can be applied to static" + " methods on JS-implemented classes only.", + [self.location]) + def overloadsForArgCount(self, argc): return [overload for overload in self._overloads if len(overload.arguments) == argc or @@ -4006,10 +4632,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope): self._unforgeable = True elif identifier == "SameObject": raise WebIDLError("Methods must not be flagged as [SameObject]", - [attr.location, self.location]); + [attr.location, self.location]) elif identifier == "Constant": raise WebIDLError("Methods must not be flagged as [Constant]", - [attr.location, self.location]); + [attr.location, self.location]) elif identifier == "PutForwards": raise WebIDLError("Only attributes support [PutForwards]", [attr.location, self.location]) @@ -4048,15 +4674,24 @@ class IDLMethod(IDLInterfaceMember, IDLScope): raise WebIDLError("[DependsOn] takes an identifier", [attr.location]) self._setDependsOn(attr.value()) + elif identifier == "Alias": + if not attr.hasValue(): + raise WebIDLError("[Alias] takes an identifier or string", + [attr.location]) + self._addAlias(attr.value()) elif (identifier == "Throws" or identifier == "NewObject" or identifier == "ChromeOnly" or identifier == "UnsafeInPrerendering" or identifier == "Pref" or + identifier == "Deprecated" or identifier == "Func" or identifier == "AvailableIn" or - identifier == "CheckPermissions" or - identifier == "BinaryName"): + identifier == "CheckAnyPermissions" or + identifier == "CheckAllPermissions" or + identifier == "BinaryName" or + identifier == "MethodIdentityTestable" or + identifier == "StaticClassOverride"): # Known attributes that we don't need to do anything with here pass else: @@ -4076,10 +4711,11 @@ class IDLMethod(IDLInterfaceMember, IDLScope): deps.update(overload._getDependentObjects()) return deps + class IDLImplementsStatement(IDLObject): def __init__(self, location, implementor, implementee): IDLObject.__init__(self, location) - self.implementor = implementor; + self.implementor = implementor self.implementee = implementee self._finished = False @@ -4119,6 +4755,7 @@ class IDLImplementsStatement(IDLObject): def addExtendedAttributes(self, attrs): assert len(attrs) == 0 + class IDLExtendedAttribute(IDLObject): """ A class to represent IDL extended attributes so we can give them locations @@ -4157,6 +4794,7 @@ class IDLExtendedAttribute(IDLObject): # Parser + class Tokenizer(object): tokens = [ "INTEGER", @@ -4272,17 +4910,20 @@ class Tokenizer(object): "<": "LT", ">": "GT", "ArrayBuffer": "ARRAYBUFFER", - "or": "OR" + "SharedArrayBuffer": "SHAREDARRAYBUFFER", + "or": "OR", + "maplike": "MAPLIKE", + "setlike": "SETLIKE" } tokens.extend(keywords.values()) def t_error(self, t): raise WebIDLError("Unrecognized Input", - [Location(lexer=self.lexer, - lineno=self.lexer.lineno, - lexpos=self.lexer.lexpos, - filename = self.filename)]) + [Location(lexer=self.lexer, + lineno=self.lexer.lineno, + lexpos=self.lexer.lexpos, + filename=self.filename)]) def __init__(self, outputdir, lexer=None): if lexer: @@ -4293,6 +4934,7 @@ class Tokenizer(object): lextab='webidllex', reflags=re.DOTALL) + class SqueakyCleanLogger(object): errorWhitelist = [ # Web IDL defines the WHITESPACE token, but doesn't actually @@ -4310,11 +4952,14 @@ class SqueakyCleanLogger(object): # Which means the Other symbol is unreachable. "Symbol 'Other' is unreachable", ] + def __init__(self): self.errors = [] + def debug(self, msg, *args, **kwargs): pass info = debug + def warning(self, msg, *args, **kwargs): if msg == "%s:%d: Rule '%s' defined, but not used": # Munge things so we don't have to hardcode filenames and @@ -4332,6 +4977,7 @@ class SqueakyCleanLogger(object): if self.errors: raise WebIDLError("\n".join(self.errors), []) + class Parser(Tokenizer): def getLocation(self, p, i): return Location(self.lexer, p.lineno(i), p.lexpos(i), self._filename) @@ -4371,7 +5017,7 @@ class Parser(Tokenizer): | ImplementsStatement """ p[0] = p[1] - assert p[1] # We might not have implemented something ... + assert p[1] # We might not have implemented something ... def p_CallbackOrInterfaceCallback(self, p): """ @@ -4508,7 +5154,7 @@ class Parser(Tokenizer): def p_InterfaceMember(self, p): """ InterfaceMember : Const - | AttributeOrOperation + | AttributeOrOperationOrMaplikeOrSetlike """ p[0] = p[1] @@ -4573,7 +5219,7 @@ class Parser(Tokenizer): if len(p) == 2: p[0] = p[1] else: - assert len(p) == 3 # Must be [] + assert len(p) == 3 # Must be [] p[0] = IDLEmptySequenceValue(self.getLocation(p, 1)) def p_Exception(self, p): @@ -4630,8 +5276,8 @@ class Parser(Tokenizer): CallbackRest : IDENTIFIER EQUALS ReturnType LPAREN ArgumentList RPAREN SEMICOLON """ identifier = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) - p[0] = IDLCallbackType(self.getLocation(p, 1), self.globalScope(), - identifier, p[3], p[5]) + p[0] = IDLCallback(self.getLocation(p, 1), self.globalScope(), + identifier, p[3], p[5]) def p_ExceptionMembers(self, p): """ @@ -4644,8 +5290,8 @@ class Parser(Tokenizer): """ Typedef : TYPEDEF Type IDENTIFIER SEMICOLON """ - typedef = IDLTypedefType(self.getLocation(p, 1), p[2], p[3]) - typedef.resolve(self.globalScope()) + typedef = IDLTypedef(self.getLocation(p, 1), self.globalScope(), + p[2], p[3]) p[0] = typedef def p_ImplementsStatement(self, p): @@ -4685,7 +5331,7 @@ class Parser(Tokenizer): # We don't know ahead of time what type the integer literal is. # Determine the smallest type it could possibly fit in and use that. integerType = matchIntegerValueToType(p[1]) - if integerType == None: + if integerType is None: raise WebIDLError("Integer literal out of range", [location]) p[0] = IDLValue(location, integerType, p[1]) @@ -4723,13 +5369,43 @@ class Parser(Tokenizer): """ p[0] = False - def p_AttributeOrOperation(self, p): + def p_AttributeOrOperationOrMaplikeOrSetlike(self, p): """ - AttributeOrOperation : Attribute - | Operation + AttributeOrOperationOrMaplikeOrSetlike : Attribute + | Maplike + | Setlike + | Operation """ p[0] = p[1] + def p_Setlike(self, p): + """ + Setlike : ReadOnly SETLIKE LT Type GT SEMICOLON + """ + readonly = p[1] + maplikeOrSetlikeType = p[2] + location = self.getLocation(p, 2) + identifier = IDLUnresolvedIdentifier(location, "__setlike", + allowDoubleUnderscore=True) + keyType = p[4] + valueType = keyType + p[0] = IDLMaplikeOrSetlike(location, identifier, maplikeOrSetlikeType, + readonly, keyType, valueType) + + def p_Maplike(self, p): + """ + Maplike : ReadOnly MAPLIKE LT Type COMMA Type GT SEMICOLON + """ + readonly = p[1] + maplikeOrSetlikeType = p[2] + location = self.getLocation(p, 2) + identifier = IDLUnresolvedIdentifier(location, "__maplike", + allowDoubleUnderscore=True) + keyType = p[4] + valueType = p[6] + p[0] = IDLMaplikeOrSetlike(location, identifier, maplikeOrSetlikeType, + readonly, keyType, valueType) + def p_AttributeWithQualifier(self, p): """ Attribute : Qualifier AttributeRest @@ -4737,15 +5413,22 @@ class Parser(Tokenizer): static = IDLInterfaceMember.Special.Static in p[1] stringifier = IDLInterfaceMember.Special.Stringifier in p[1] (location, identifier, type, readonly) = p[2] - p[0] = IDLAttribute(location, identifier, type, readonly, static=static, - stringifier=stringifier) + p[0] = IDLAttribute(location, identifier, type, readonly, + static=static, stringifier=stringifier) + + def p_AttributeInherited(self, p): + """ + Attribute : INHERIT AttributeRest + """ + (location, identifier, type, readonly) = p[2] + p[0] = IDLAttribute(location, identifier, type, readonly, inherit=True) def p_Attribute(self, p): """ - Attribute : Inherit AttributeRest + Attribute : AttributeRest """ - (location, identifier, type, readonly) = p[2] - p[0] = IDLAttribute(location, identifier, type, readonly, inherit=p[1]) + (location, identifier, type, readonly) = p[1] + p[0] = IDLAttribute(location, identifier, type, readonly, inherit=False) def p_AttributeRest(self, p): """ @@ -4769,18 +5452,6 @@ class Parser(Tokenizer): """ p[0] = False - def p_Inherit(self, p): - """ - Inherit : INHERIT - """ - p[0] = True - - def p_InheritEmpty(self, p): - """ - Inherit : - """ - p[0] = False - def p_Operation(self, p): """ Operation : Qualifiers OperationRest @@ -4837,7 +5508,7 @@ class Parser(Tokenizer): raise WebIDLError("%s cannot have %s argument" % ("getter" if getter else "deleter", "optional" if arguments[0].optional else "variadic"), - [arguments[0].location]) + [arguments[0].location]) if getter: if returnType.isVoid(): raise WebIDLError("getter cannot have void return type", @@ -4877,21 +5548,24 @@ 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 \ - not deleter and not legacycaller and not stringifier: + if (not getter and not setter and not creator and + not deleter and not legacycaller and not stringifier): raise WebIDLError("Identifier required for non-special methods", [self.getLocation(p, 2)]) location = BuiltinLocation("") - identifier = IDLUnresolvedIdentifier(location, "__%s%s%s%s%s%s%s" % - ("named" if specialType == IDLMethod.NamedOrIndexed.Named else \ + identifier = IDLUnresolvedIdentifier( + location, + "__%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) + "stringifier" if stringifier else ""), + allowDoubleUnderscore=True) method = IDLMethod(self.getLocation(p, 2), identifier, returnType, arguments, static=static, getter=getter, setter=setter, creator=creator, @@ -5077,9 +5751,11 @@ class Parser(Tokenizer): | INHERIT | INTERFACE | LEGACYCALLER + | MAPLIKE | PARTIAL | REQUIRED | SERIALIZER + | SETLIKE | SETTER | STATIC | STRINGIFIER @@ -5319,12 +5995,15 @@ class Parser(Tokenizer): """ NonAnyType : PrimitiveOrStringType TypeSuffix | ARRAYBUFFER TypeSuffix + | SHAREDARRAYBUFFER TypeSuffix | OBJECT TypeSuffix """ if p[1] == "object": type = BuiltinTypes[IDLBuiltinType.Types.object] elif p[1] == "ArrayBuffer": type = BuiltinTypes[IDLBuiltinType.Types.ArrayBuffer] + elif p[1] == "SharedArrayBuffer": + type = BuiltinTypes[IDLBuiltinType.Types.SharedArrayBuffer] else: type = BuiltinTypes[p[1]] @@ -5380,8 +6059,12 @@ class Parser(Tokenizer): try: if self.globalScope()._lookupIdentifier(p[1]): obj = self.globalScope()._lookupIdentifier(p[1]) - if obj.isType(): - type = obj + assert not obj.isType() + if obj.isTypedef(): + 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) else: type = IDLWrapperType(self.getLocation(p, 1), p[1]) p[0] = self.handleModifiers(type, p[2]) @@ -5489,8 +6172,8 @@ class Parser(Tokenizer): """ UnsignedIntegerType : UNSIGNED IntegerType """ - p[0] = p[2] + 1 # Adding one to a given signed integer type - # gets you the unsigned type. + # Adding one to a given signed integer type gets you the unsigned type: + p[0] = p[2] + 1 def p_UnsignedIntegerType(self, p): """ @@ -5598,7 +6281,7 @@ class Parser(Tokenizer): """ RelativeScopedName : IDENTIFIER ScopedNameParts """ - assert not p[2] # Not implemented! + assert not p[2] # Not implemented! p[0] = IDLUnresolvedIdentifier(self.getLocation(p, 1), p[1]) @@ -5689,11 +6372,13 @@ class Parser(Tokenizer): # We're not pickling for now, until it # becomes a speedup again. # , picklefile='WebIDLGrammar.pkl' - ) + ) logger.reportGrammarErrors() self._globalScope = IDLScope(BuiltinLocation(""), 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. + # 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") @@ -5708,24 +6393,22 @@ class Parser(Tokenizer): self.lexer.input(Parser._builtins) self._filename = None - self.parser.parse(lexer=self.lexer,tracking=True) + self.parser.parse(lexer=self.lexer, tracking=True) def _installBuiltins(self, scope): assert isinstance(scope, IDLScope) # xrange omits the last value. - for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.Float64Array + 1): + for x in xrange(IDLBuiltinType.Types.ArrayBuffer, IDLBuiltinType.Types.SharedFloat64Array + 1): builtin = BuiltinTypes[x] name = builtin.name - - typedef = IDLTypedefType(BuiltinLocation(""), builtin, name) - typedef.resolve(scope) + typedef = IDLTypedef(BuiltinLocation(""), scope, builtin, name) @ staticmethod def handleModifiers(type, modifiers): for (modifier, modifierLocation) in modifiers: - assert modifier == IDLMethod.TypeSuffixModifier.QMark or \ - modifier == IDLMethod.TypeSuffixModifier.Brackets + assert (modifier == IDLMethod.TypeSuffixModifier.QMark or + modifier == IDLMethod.TypeSuffixModifier.Brackets) if modifier == IDLMethod.TypeSuffixModifier.QMark: type = IDLNullableType(modifierLocation, type) @@ -5737,21 +6420,21 @@ class Parser(Tokenizer): def parse(self, t, filename=None): self.lexer.input(t) - #for tok in iter(self.lexer.token, None): + # for tok in iter(self.lexer.token, None): # print tok self._filename = filename - self._productions.extend(self.parser.parse(lexer=self.lexer,tracking=True)) + self._productions.extend(self.parser.parse(lexer=self.lexer, tracking=True)) self._filename = None def finish(self): # First, finish all the IDLImplementsStatements. In particular, we # have to make sure we do those before we do the IDLInterfaces. # XXX khuey hates this bit and wants to nuke it from orbit. - implementsStatements = [ p for p in self._productions if - isinstance(p, IDLImplementsStatement)] - otherStatements = [ p for p in self._productions if - not isinstance(p, IDLImplementsStatement)] + implementsStatements = [p for p in self._productions if + isinstance(p, IDLImplementsStatement)] + otherStatements = [p for p in self._productions if + not isinstance(p, IDLImplementsStatement)] for production in implementsStatements: production.finish(self.globalScope()) for production in otherStatements: @@ -5777,8 +6460,10 @@ class Parser(Tokenizer): _builtins = """ typedef unsigned long long DOMTimeStamp; typedef (ArrayBufferView or ArrayBuffer) BufferSource; + typedef (SharedArrayBufferView or SharedArrayBuffer) SharedBufferSource; """ + def main(): # Parse arguments. from optparse import OptionParser diff --git a/servo/components/script/dom/webidls/BrowserElement.webidl b/servo/components/script/dom/webidls/BrowserElement.webidl index ad748884f9ff..6b4e9a8cf04d 100644 --- a/servo/components/script/dom/webidls/BrowserElement.webidl +++ b/servo/components/script/dom/webidls/BrowserElement.webidl @@ -7,8 +7,17 @@ callback BrowserElementNextPaintEventCallback = void (); +//enum BrowserFindCaseSensitivity { "case-sensitive", "case-insensitive" }; +//enum BrowserFindDirection { "forward", "backward" }; + //dictionary BrowserElementDownloadOptions { // DOMString? filename; +// DOMString? referrer; +//}; + +//dictionary BrowserElementExecuteScriptOptions { +// DOMString? url; +// DOMString? origin; //}; [NoInterfaceObject] @@ -22,22 +31,32 @@ BrowserElement implements BrowserElementPrivileged; interface BrowserElementCommon { //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser embed-widgets"] + // CheckAnyPermissions="browser embed-widgets"] //void setVisible(boolean visible); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser embed-widgets"] + // CheckAnyPermissions="browser embed-widgets"] //DOMRequest getVisible(); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser embed-widgets"] + // CheckAnyPermissions="browser embed-widgets"] + //void setActive(boolean active); + + //[Throws, + // Pref="dom.mozBrowserFramesEnabled", + // CheckAnyPermissions="browser embed-widgets"] + //boolean getActive(); + + //[Throws, + // Pref="dom.mozBrowserFramesEnabled", + // CheckAnyPermissions="browser embed-widgets"] //void addNextPaintListener(BrowserElementNextPaintEventCallback listener); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser embed-widgets"] + // CheckAnyPermissions="browser embed-widgets"] //void removeNextPaintListener(BrowserElementNextPaintEventCallback listener); }; @@ -45,7 +64,7 @@ interface BrowserElementCommon { interface BrowserElementPrivileged { //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //void sendMouseEvent(DOMString type, // unsigned long x, // unsigned long y, @@ -56,7 +75,7 @@ interface BrowserElementPrivileged { //[Throws, // Pref="dom.mozBrowserFramesEnabled", // Func="TouchEvent::PrefEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //void sendTouchEvent(DOMString type, // sequence identifiers, // sequence x, @@ -70,70 +89,91 @@ interface BrowserElementPrivileged { [Throws, Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] + CheckAnyPermissions="browser"] void goBack(); [Throws, Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] + CheckAnyPermissions="browser"] void goForward(); [Throws, Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] + CheckAnyPermissions="browser"] void reload(optional boolean hardReload = false); [Throws, Pref="dom.mozBrowserFramesEnabled", - CheckPermissions="browser"] + CheckAnyPermissions="browser"] void stop(); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //DOMRequest download(DOMString url, // optional BrowserElementDownloadOptions options); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //DOMRequest purgeHistory(); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //DOMRequest getScreenshot([EnforceRange] unsigned long width, // [EnforceRange] unsigned long height, // optional DOMString mimeType=""); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //void zoom(float zoom); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //DOMRequest getCanGoBack(); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //DOMRequest getCanGoForward(); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAnyPermissions="browser"] //DOMRequest getContentDimensions(); //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAllPermissions="browser input-manage"] //DOMRequest setInputMethodActive(boolean isActive); - // Additional |nfc-manager| permission is required for setNFCFocus API //[Throws, // Pref="dom.mozBrowserFramesEnabled", - // CheckPermissions="browser"] + // CheckAllPermissions="browser nfc-manager"] //void setNFCFocus(boolean isFocus); + + //[Throws, + // Pref="dom.mozBrowserFramesEnabled", + // CheckAnyPermissions="browser"] + //void findAll(DOMString searchString, BrowserFindCaseSensitivity caseSensitivity); + + //[Throws, + // Pref="dom.mozBrowserFramesEnabled", + // CheckAnyPermissions="browser"] + //void findNext(BrowserFindDirection direction); + + //[Throws, + // Pref="dom.mozBrowserFramesEnabled", + // CheckAnyPermissions="browser"] + //void clearMatch(); + + //[Throws, + // Pref="dom.mozBrowserFramesEnabled", + // CheckAllPermissions="browser browser:universalxss"] + //DOMRequest executeScript(DOMString script, + // optional BrowserElementExecuteScriptOptions options); + }; diff --git a/servo/components/script/dom/webidls/TestBinding.webidl b/servo/components/script/dom/webidls/TestBinding.webidl index 68ac9bb8b303..08221f2ccc00 100644 --- a/servo/components/script/dom/webidls/TestBinding.webidl +++ b/servo/components/script/dom/webidls/TestBinding.webidl @@ -8,6 +8,7 @@ enum TestEnum { "", "foo", "bar" }; dictionary TestDictionary { + required boolean requiredValue; boolean booleanValue; byte byteValue; octet octetValue;