aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/codegen
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-06-12 07:37:49 -0700
committerGitHub <noreply@github.com>2017-06-12 07:37:49 -0700
commit0c929ad3fd902f4314844787868fe891033d3b01 (patch)
tree23e72087649bef2076bcdf2ed45e69c5889418f4 /components/script/dom/bindings/codegen
parentd7dff8e6d118bf82f837b3e6387cf96647007cdd (diff)
parente566bc7b1c65e54601f5420bfa071bab9c1b83a3 (diff)
downloadservo-0c929ad3fd902f4314844787868fe891033d3b01.tar.gz
servo-0c929ad3fd902f4314844787868fe891033d3b01.zip
Auto merge of #17254 - servo:webidl, r=jdm
Update the WebIDL parser <!-- Reviewable:start --> This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/17254) <!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/bindings/codegen')
-rw-r--r--components/script/dom/bindings/codegen/CodegenRust.py175
-rw-r--r--components/script/dom/bindings/codegen/parser/WebIDL.py455
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_cereactions.py162
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_constructor.py166
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py33
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py35
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_identifier_conflict.py39
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_interface_maplikesetlikeiterable.py111
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_newobject.py70
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_promise.py102
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_record.py (renamed from components/script/dom/bindings/codegen/parser/tests/test_mozmap.py)26
-rw-r--r--components/script/dom/bindings/codegen/parser/tests/test_special_methods.py41
12 files changed, 1142 insertions, 273 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py
index 102c1a17d57..bf6ca70e6c0 100644
--- a/components/script/dom/bindings/codegen/CodegenRust.py
+++ b/components/script/dom/bindings/codegen/CodegenRust.py
@@ -17,11 +17,12 @@ import functools
from WebIDL import (
BuiltinTypes,
IDLBuiltinType,
- IDLNullValue,
+ IDLInterfaceMember,
IDLNullableType,
+ IDLNullValue,
IDLObject,
+ IDLPromiseType,
IDLType,
- IDLInterfaceMember,
IDLUndefinedValue,
IDLWrapperType,
)
@@ -94,14 +95,14 @@ def stripTrailingWhitespace(text):
def innerContainerType(type):
- assert type.isSequence() or type.isMozMap()
+ assert type.isSequence() or type.isRecord()
return type.inner.inner if type.nullable() else type.inner
def wrapInNativeContainerType(type, inner):
if type.isSequence():
containerType = "Vec"
- elif type.isMozMap():
+ elif type.isRecord():
containerType = "MozMap"
else:
raise TypeError("Unexpected container type %s", type)
@@ -697,7 +698,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not (isEnforceRange and isClamp) # These are mutually exclusive
- if type.isSequence() or type.isMozMap():
+ if type.isSequence() or type.isRecord():
innerInfo = getJSToNativeConversionInfo(innerContainerType(type),
descriptorProvider,
isMember=isMember)
@@ -754,6 +755,56 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
return handleOptional(templateBody, declType, default)
+ if type.isPromise():
+ assert not type.nullable()
+ # Per spec, what we're supposed to do is take the original
+ # Promise.resolve and call it with the original Promise as this
+ # value to make a Promise out of whatever value we actually have
+ # here. The question is which global we should use. There are
+ # a couple cases to consider:
+ #
+ # 1) Normal call to API with a Promise argument. This is a case the
+ # spec covers, and we should be using the current Realm's
+ # Promise. That means the current compartment.
+ # 2) Promise return value from a callback or callback interface.
+ # This is in theory a case the spec covers but in practice it
+ # really doesn't define behavior here because it doesn't define
+ # what Realm we're in after the callback returns, which is when
+ # the argument conversion happens. We will use the current
+ # compartment, which is the compartment of the callable (which
+ # may itself be a cross-compartment wrapper itself), which makes
+ # as much sense as anything else. In practice, such an API would
+ # once again be providing a Promise to signal completion of an
+ # operation, which would then not be exposed to anyone other than
+ # our own implementation code.
+ templateBody = fill(
+ """
+ { // Scope for our JSAutoCompartment.
+
+ rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
+ let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get());
+
+ rooted!(in(cx) let mut valueToResolve = $${val}.get());
+ if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
+ $*{exceptionCode}
+ }
+ match Promise::Resolve(&promiseGlobal, cx, valueToResolve.handle()) {
+ Ok(value) => value,
+ Err(error) => {
+ throw_dom_exception(cx, &promiseGlobal, error);
+ $*{exceptionCode}
+ }
+ }
+ }
+ """,
+ exceptionCode=exceptionCode)
+
+ if isArgument:
+ declType = CGGeneric("&Promise")
+ else:
+ declType = CGGeneric("Rc<Promise>")
+ return handleOptional(templateBody, declType, handleDefaultNull("None"))
+
if type.isGeckoInterface():
assert not isEnforceRange and not isClamp
@@ -780,79 +831,34 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
elif isArgument:
descriptorType = descriptor.argumentType
- templateBody = ""
- isPromise = descriptor.interface.identifier.name == "Promise"
- if isPromise:
- # Per spec, what we're supposed to do is take the original
- # Promise.resolve and call it with the original Promise as this
- # value to make a Promise out of whatever value we actually have
- # here. The question is which global we should use. There are
- # a couple cases to consider:
- #
- # 1) Normal call to API with a Promise argument. This is a case the
- # spec covers, and we should be using the current Realm's
- # Promise. That means the current compartment.
- # 2) Promise return value from a callback or callback interface.
- # This is in theory a case the spec covers but in practice it
- # really doesn't define behavior here because it doesn't define
- # what Realm we're in after the callback returns, which is when
- # the argument conversion happens. We will use the current
- # compartment, which is the compartment of the callable (which
- # may itself be a cross-compartment wrapper itself), which makes
- # as much sense as anything else. In practice, such an API would
- # once again be providing a Promise to signal completion of an
- # operation, which would then not be exposed to anyone other than
- # our own implementation code.
- templateBody = fill(
- """
- { // Scope for our JSAutoCompartment.
-
- rooted!(in(cx) let globalObj = CurrentGlobalOrNull(cx));
- let promiseGlobal = GlobalScope::from_object_maybe_wrapped(globalObj.handle().get());
+ if descriptor.interface.isConsequential():
+ raise TypeError("Consequential interface %s being used as an "
+ "argument" % descriptor.interface.identifier.name)
- rooted!(in(cx) let mut valueToResolve = $${val}.get());
- if !JS_WrapValue(cx, valueToResolve.handle_mut()) {
- $*{exceptionCode}
- }
- match Promise::Resolve(&promiseGlobal, cx, valueToResolve.handle()) {
- Ok(value) => value,
- Err(error) => {
- throw_dom_exception(cx, &promiseGlobal, error);
- $*{exceptionCode}
- }
- }
- }
- """,
- exceptionCode=exceptionCode)
+ if failureCode is None:
+ substitutions = {
+ "sourceDescription": sourceDescription,
+ "interface": descriptor.interface.identifier.name,
+ "exceptionCode": exceptionCode,
+ }
+ unwrapFailureCode = string.Template(
+ 'throw_type_error(cx, "${sourceDescription} does not '
+ 'implement interface ${interface}.");\n'
+ '${exceptionCode}').substitute(substitutions)
else:
- if descriptor.interface.isConsequential():
- raise TypeError("Consequential interface %s being used as an "
- "argument" % descriptor.interface.identifier.name)
-
- if failureCode is None:
- substitutions = {
- "sourceDescription": sourceDescription,
- "interface": descriptor.interface.identifier.name,
- "exceptionCode": exceptionCode,
- }
- unwrapFailureCode = string.Template(
- 'throw_type_error(cx, "${sourceDescription} does not '
- 'implement interface ${interface}.");\n'
- '${exceptionCode}').substitute(substitutions)
- else:
- unwrapFailureCode = failureCode
+ unwrapFailureCode = failureCode
- templateBody = fill(
- """
- match ${function}($${val}) {
- Ok(val) => val,
- Err(()) => {
- $*{failureCode}
- }
+ templateBody = fill(
+ """
+ match ${function}($${val}) {
+ Ok(val) => val,
+ Err(()) => {
+ $*{failureCode}
}
- """,
- failureCode=unwrapFailureCode + "\n",
- function=conversionFunction)
+ }
+ """,
+ failureCode=unwrapFailureCode + "\n",
+ function=conversionFunction)
declType = CGGeneric(descriptorType)
if type.nullable():
@@ -1323,7 +1329,7 @@ def typeNeedsCx(type, retVal=False):
# Returns a conversion behavior suitable for a type
def getConversionConfigForType(type, isEnforceRange, isClamp, treatNullAs):
- if type.isSequence() or type.isMozMap():
+ if type.isSequence() or type.isRecord():
return getConversionConfigForType(innerContainerType(type), isEnforceRange, isClamp, treatNullAs)
if type.isDOMString():
assert not isEnforceRange and not isClamp
@@ -1381,6 +1387,9 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
if returnType.nullable():
result = CGWrapper(result, pre="Option<", post=">")
return result
+ if returnType.isPromise():
+ assert not returnType.nullable()
+ return CGGeneric("Rc<Promise>")
if returnType.isGeckoInterface():
descriptor = descriptorProvider.getDescriptor(
returnType.unroll().inner.identifier.name)
@@ -1408,7 +1417,7 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
if returnType.nullable():
result = CGWrapper(result, pre="Option<", post=">")
return result
- if returnType.isSequence() or returnType.isMozMap():
+ if returnType.isSequence() or returnType.isRecord():
result = getRetvalDeclarationForType(innerContainerType(returnType), descriptorProvider)
result = wrapInNativeContainerType(returnType, result)
if returnType.nullable():
@@ -1946,8 +1955,10 @@ class CGImports(CGWrapper):
if parentName:
descriptor = descriptorProvider.getDescriptor(parentName)
extras += [descriptor.path, descriptor.bindingPath]
- elif t.isType() and t.isMozMap():
+ elif t.isType() and t.isRecord():
extras += ['dom::bindings::mozmap::MozMap']
+ elif isinstance(t, IDLPromiseType):
+ extras += ["dom::promise::Promise"]
else:
if t.isEnum():
extras += [getModuleFromObject(t) + '::' + getIdentifier(t).name + 'Values']
@@ -3819,7 +3830,9 @@ class CGMemberJITInfo(CGThing):
return "JSVAL_TYPE_UNDEFINED"
if t.isSequence():
return "JSVAL_TYPE_OBJECT"
- if t.isMozMap():
+ if t.isRecord():
+ return "JSVAL_TYPE_OBJECT"
+ if t.isPromise():
return "JSVAL_TYPE_OBJECT"
if t.isGeckoInterface():
return "JSVAL_TYPE_OBJECT"
@@ -4055,7 +4068,7 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
elif type.isDictionary():
name = type.name
typeName = name
- elif type.isSequence() or type.isMozMap():
+ elif type.isSequence() or type.isRecord():
name = type.name
inner = getUnionTypeTemplateVars(innerContainerType(type), descriptorProvider)
typeName = wrapInNativeContainerType(type, CGGeneric(inner["typeName"])).define()
@@ -4208,7 +4221,7 @@ class CGUnionConversionStruct(CGThing):
else:
object = None
- mozMapMemberTypes = filter(lambda t: t.isMozMap(), memberTypes)
+ mozMapMemberTypes = filter(lambda t: t.isRecord(), memberTypes)
if len(mozMapMemberTypes) > 0:
assert len(mozMapMemberTypes) == 1
typeName = mozMapMemberTypes[0].name
@@ -6870,6 +6883,8 @@ def process_arg(expr, arg):
expr += ".r()"
else:
expr = "&" + expr
+ elif isinstance(arg.type, IDLPromiseType):
+ expr = "&" + expr
return expr
diff --git a/components/script/dom/bindings/codegen/parser/WebIDL.py b/components/script/dom/bindings/codegen/parser/WebIDL.py
index dc9fa036141..820dc108fbf 100644
--- a/components/script/dom/bindings/codegen/parser/WebIDL.py
+++ b/components/script/dom/bindings/codegen/parser/WebIDL.py
@@ -305,8 +305,8 @@ 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 (isinstance(originalObject, IDLMethod) and
+ isinstance(newObject, IDLMethod)):
return originalObject.addOverload(newObject)
# Default to throwing, derived classes can override.
@@ -367,8 +367,6 @@ class IDLUnresolvedIdentifier(IDLObject):
[location])
if name[0] == '_' and not allowDoubleUnderscore:
name = name[1:]
- # TODO: Bug 872377, Restore "toJSON" to below list.
- # We sometimes need custom serialization, so allow toJSON for now.
if (name in ["constructor", "toString"] and
not allowForbidden):
raise WebIDLError("Cannot use reserved identifier '%s'" % (name),
@@ -515,6 +513,9 @@ class IDLExposureMixins():
def isExposedInWorkerDebugger(self):
return len(self.getWorkerDebuggerExposureSet()) > 0
+ def isExposedInAnyWorklet(self):
+ return len(self.getWorkletExposureSet()) > 0
+
def isExposedInSystemGlobals(self):
return 'BackstagePass' in self.exposureSet
@@ -534,6 +535,10 @@ class IDLExposureMixins():
workerScopes = self._globalScope.globalNameMapping["Worker"]
return workerScopes.intersection(self.exposureSet)
+ def getWorkletExposureSet(self):
+ workletScopes = self._globalScope.globalNameMapping["Worklet"]
+ return workletScopes.intersection(self.exposureSet)
+
def getWorkerDebuggerExposureSet(self):
workerDebuggerScopes = self._globalScope.globalNameMapping["WorkerDebugger"]
return workerDebuggerScopes.intersection(self.exposureSet)
@@ -568,7 +573,10 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
return False
def addExtendedAttributes(self, attrs):
- assert len(attrs) == 0
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on external interfaces",
+ [attrs[0].location, self.location])
def resolve(self, parentScope):
pass
@@ -579,7 +587,7 @@ class IDLExternalInterface(IDLObjectWithIdentifier, IDLExposureMixins):
def isJSImplemented(self):
return False
- def isProbablyShortLivingObject(self):
+ def hasProbablyShortLivingWrapper(self):
return False
def isNavigatorProperty(self):
@@ -1090,7 +1098,10 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
# {getter,setter,creator,deleter}, at most one stringifier,
# and at most one legacycaller. Note that this last is not
# quite per spec, but in practice no one overloads
- # legacycallers.
+ # legacycallers. Also note that in practice we disallow
+ # indexed deleters, but it simplifies some other code to
+ # treat deleter analogously to getter/setter/creator by
+ # prefixing it with "named".
specialMembersSeen = {}
for member in self.members:
if not member.isMethod():
@@ -1192,6 +1203,12 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
self.identifier.name,
locations)
+ ctor = self.ctor()
+ if ctor is not None:
+ ctor.validate()
+ for namedCtor in self.namedConstructors:
+ namedCtor.validate()
+
indexedGetter = None
hasLengthAttribute = False
for member in self.members:
@@ -1308,7 +1325,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
if not indexedGetter:
raise WebIDLError("Interface with value iterator does not "
"support indexed properties",
- [self.location])
+ [self.location, iterableDecl.location])
if iterableDecl.valueType != indexedGetter.signatures()[0][0]:
raise WebIDLError("Iterable type does not match indexed "
@@ -1319,7 +1336,7 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
if not hasLengthAttribute:
raise WebIDLError('Interface with value iterator does not '
'have an integer-typed "length" attribute',
- [self.location])
+ [self.location, iterableDecl.location])
else:
assert iterableDecl.isPairIterator()
if indexedGetter:
@@ -1328,6 +1345,11 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
[self.location, iterableDecl.location,
indexedGetter.location])
+ if indexedGetter and not hasLengthAttribute:
+ raise WebIDLError('Interface with an indexed getter does not have '
+ 'an integer-typed "length" attribute',
+ [self.location, indexedGetter.location])
+
def isExternal(self):
return False
@@ -1458,6 +1480,10 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
assert self.identifier.name == partial.identifier.name
self._partialInterfaces.append(partial)
+ def getPartialInterfaces(self):
+ # Don't let people mutate our guts.
+ return list(self._partialInterfaces)
+
def getJSImplementation(self):
classId = self.getExtendedAttribute("JSImplementation")
if not classId:
@@ -1469,10 +1495,10 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
def isJSImplemented(self):
return bool(self.getJSImplementation())
- def isProbablyShortLivingObject(self):
+ def hasProbablyShortLivingWrapper(self):
current = self
while current:
- if current.getExtendedAttribute("ProbablyShortLivingObject"):
+ if current.getExtendedAttribute("ProbablyShortLivingWrapper"):
return True
current = current.parent
return False
@@ -1526,10 +1552,8 @@ class IDLInterfaceOrNamespace(IDLObjectWithScope, IDLExposureMixins):
def hasMembersInSlots(self):
return self._ownMembersInSlots != 0
- conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func", "AvailableIn",
- "SecureContext",
- "CheckAnyPermissions",
- "CheckAllPermissions" ]
+ conditionExtendedAttributes = [ "Pref", "ChromeOnly", "Func",
+ "SecureContext" ]
def isExposedConditionally(self, exclusions=[]):
return any(((not a in exclusions) and self.getExtendedAttribute(a)) for a in self.conditionExtendedAttributes)
@@ -1566,7 +1590,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
[self.location])
self._noInterfaceObject = True
- elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor":
+ elif identifier == "Constructor" or identifier == "NamedConstructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
if identifier == "Constructor" and not self.hasInterfaceObject():
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
@@ -1579,15 +1603,20 @@ class IDLInterface(IDLInterfaceOrNamespace):
raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
[self.location])
+ if identifier == "HTMLConstructor":
+ if not self.hasInterfaceObject():
+ raise WebIDLError(str(identifier) + " and NoInterfaceObject are incompatible",
+ [self.location])
+
+ if not attr.noArguments():
+ raise WebIDLError(str(identifier) + " must take no arguments",
+ [attr.location])
+
args = attr.args() if attr.hasArgs() else []
- if self.identifier.name == "Promise":
- promiseType = BuiltinTypes[IDLBuiltinType.Types.any]
- else:
- promiseType = None
- retType = IDLWrapperType(self.location, self, promiseType)
+ retType = IDLWrapperType(self.location, self)
- if identifier == "Constructor" or identifier == "ChromeConstructor":
+ if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
name = "constructor"
allowForbidden = True
else:
@@ -1598,7 +1627,8 @@ class IDLInterface(IDLInterfaceOrNamespace):
allowForbidden=allowForbidden)
method = IDLMethod(self.location, methodIdentifier, retType,
- args, static=True)
+ args, static=True,
+ htmlConstructor=(identifier == "HTMLConstructor"))
# Constructors are always NewObject and are always
# assumed to be able to throw (since there's no way to
# indicate otherwise) and never have any other
@@ -1610,7 +1640,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
method.addExtendedAttributes(
[IDLExtendedAttribute(self.location, ("ChromeOnly",))])
- if identifier == "Constructor" or identifier == "ChromeConstructor":
+ if identifier == "Constructor" or identifier == "ChromeConstructor" or identifier == "HTMLConstructor":
method.resolve(self)
else:
# We need to detect conflicts for NamedConstructors across
@@ -1692,7 +1722,7 @@ class IDLInterface(IDLInterfaceOrNamespace):
identifier == "Unforgeable" or
identifier == "UnsafeInPrerendering" or
identifier == "LegacyEventInit" or
- identifier == "ProbablyShortLivingObject" or
+ identifier == "ProbablyShortLivingWrapper" or
identifier == "LegacyUnenumerableNamedProperties" or
identifier == "NonOrdinaryGetPrototypeOf" or
identifier == "Abstract" or
@@ -1853,7 +1883,7 @@ class IDLDictionary(IDLObjectWithScope):
if (memberType.nullable() or
memberType.isSequence() or
- memberType.isMozMap()):
+ memberType.isRecord()):
return typeContainsDictionary(memberType.inner, dictionary)
if memberType.isDictionary():
@@ -1901,7 +1931,10 @@ class IDLDictionary(IDLObjectWithScope):
[member.location] + locations)
def addExtendedAttributes(self, attrs):
- assert len(attrs) == 0
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on dictionaries",
+ [attrs[0].location, self.location])
def _getDependentObjects(self):
deps = set(self.members)
@@ -1935,7 +1968,10 @@ class IDLEnum(IDLObjectWithIdentifier):
return True
def addExtendedAttributes(self, attrs):
- assert len(attrs) == 0
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on enums",
+ [attrs[0].location, self.location])
def _getDependentObjects(self):
return set()
@@ -1974,7 +2010,8 @@ class IDLType(IDLObject):
'callback',
'union',
'sequence',
- 'mozmap'
+ 'record',
+ 'promise',
)
def __init__(self, location, name):
@@ -2024,7 +2061,7 @@ class IDLType(IDLObject):
def isSequence(self):
return False
- def isMozMap(self):
+ def isRecord(self):
return False
def isArrayBuffer(self):
@@ -2107,7 +2144,11 @@ class IDLType(IDLObject):
return self.nullable() and self.inner.callback._treatNonObjectAsNull
def addExtendedAttributes(self, attrs):
- assert len(attrs) == 0
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on types, for now (but this is "
+ "changing; see bug 1359269)",
+ [attrs[0].location, self.location])
def resolveType(self, parentScope):
pass
@@ -2128,9 +2169,8 @@ class IDLUnresolvedType(IDLType):
Unresolved types are interface types
"""
- def __init__(self, location, name, promiseInnerType=None):
+ def __init__(self, location, name):
IDLType.__init__(self, location, name)
- self._promiseInnerType = promiseInnerType
def isComplete(self):
return False
@@ -2157,18 +2197,15 @@ class IDLUnresolvedType(IDLType):
assert self.name.name == obj.identifier.name
return IDLCallbackType(obj.location, obj)
- if self._promiseInnerType and not self._promiseInnerType.isComplete():
- self._promiseInnerType = self._promiseInnerType.complete(scope)
-
name = self.name.resolve(scope, None)
- return IDLWrapperType(self.location, obj, self._promiseInnerType)
+ return IDLWrapperType(self.location, obj)
def isDistinguishableFrom(self, other):
raise TypeError("Can't tell whether an unresolved type is or is not "
"distinguishable from other things")
-class IDLParameterizedType(IDLType):
+class IDLParametrizedType(IDLType):
def __init__(self, location, name, innerType):
IDLType.__init__(self, location, name)
self.builtin = False
@@ -2191,7 +2228,7 @@ class IDLParameterizedType(IDLType):
return self.inner._getDependentObjects()
-class IDLNullableType(IDLParameterizedType):
+class IDLNullableType(IDLParametrizedType):
def __init__(self, location, innerType):
assert not innerType.isVoid()
assert not innerType == BuiltinTypes[IDLBuiltinType.Types.any]
@@ -2199,7 +2236,7 @@ class IDLNullableType(IDLParameterizedType):
name = innerType.name
if innerType.isComplete():
name += "OrNull"
- IDLParameterizedType.__init__(self, location, name, innerType)
+ IDLParametrizedType.__init__(self, location, name, innerType)
def __eq__(self, other):
return isinstance(other, IDLNullableType) and self.inner == other.inner
@@ -2249,8 +2286,8 @@ class IDLNullableType(IDLParameterizedType):
def isSequence(self):
return self.inner.isSequence()
- def isMozMap(self):
- return self.inner.isMozMap()
+ def isRecord(self):
+ return self.inner.isRecord()
def isArrayBuffer(self):
return self.inner.isArrayBuffer()
@@ -2271,7 +2308,9 @@ class IDLNullableType(IDLParameterizedType):
return self.inner.isInterface()
def isPromise(self):
- return self.inner.isPromise()
+ # There is no such thing as a nullable Promise.
+ assert not self.inner.isPromise()
+ return False
def isCallbackInterface(self):
return self.inner.isCallbackInterface()
@@ -2307,18 +2346,20 @@ class IDLNullableType(IDLParameterizedType):
return self
def isDistinguishableFrom(self, other):
- if (other.nullable() or (other.isUnion() and other.hasNullableType) or
- other.isDictionary()):
+ if (other.nullable() or
+ other.isDictionary() or
+ (other.isUnion() and
+ (other.hasNullableType or other.hasDictionaryType()))):
# Can't tell which type null should become
return False
return self.inner.isDistinguishableFrom(other)
-class IDLSequenceType(IDLParameterizedType):
+class IDLSequenceType(IDLParametrizedType):
def __init__(self, location, parameterType):
assert not parameterType.isVoid()
- IDLParameterizedType.__init__(self, location, parameterType.name, parameterType)
+ IDLParametrizedType.__init__(self, location, parameterType.name, parameterType)
# Need to set self.name up front if our inner type is already complete,
# since in that case our .complete() won't be called.
if self.inner.isComplete():
@@ -2383,34 +2424,38 @@ class IDLSequenceType(IDLParameterizedType):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isDate() or other.isInterface() or
other.isDictionary() or
- other.isCallback() or other.isMozMap())
+ other.isCallback() or other.isRecord())
-class IDLMozMapType(IDLParameterizedType):
- def __init__(self, location, parameterType):
- assert not parameterType.isVoid()
+class IDLRecordType(IDLParametrizedType):
+ def __init__(self, location, keyType, valueType):
+ assert keyType.isString()
+ assert keyType.isComplete()
+ assert not valueType.isVoid()
+
+ IDLParametrizedType.__init__(self, location, valueType.name, valueType)
+ self.keyType = keyType
- IDLParameterizedType.__init__(self, location, parameterType.name, parameterType)
# Need to set self.name up front if our inner type is already complete,
# since in that case our .complete() won't be called.
if self.inner.isComplete():
- self.name = self.inner.name + "MozMap"
+ self.name = self.keyType.name + self.inner.name + "Record"
def __eq__(self, other):
- return isinstance(other, IDLMozMapType) and self.inner == other.inner
+ return isinstance(other, IDLRecordType) and self.inner == other.inner
def __str__(self):
- return self.inner.__str__() + "MozMap"
+ return self.keyType.__str__() + self.inner.__str__() + "Record"
- def isMozMap(self):
+ def isRecord(self):
return True
def tag(self):
- return IDLType.Tags.mozmap
+ return IDLType.Tags.record
def complete(self, scope):
self.inner = self.inner.complete(scope)
- self.name = self.inner.name + "MozMap"
+ self.name = self.keyType.name + self.inner.name + "Record"
return self
def unroll(self):
@@ -2608,8 +2653,8 @@ class IDLTypedefType(IDLType):
def isSequence(self):
return self.inner.isSequence()
- def isMozMap(self):
- return self.inner.isMozMap()
+ def isRecord(self):
+ return self.inner.isRecord()
def isDictionary(self):
return self.inner.isDictionary()
@@ -2679,20 +2724,21 @@ class IDLTypedef(IDLObjectWithIdentifier):
return True
def addExtendedAttributes(self, attrs):
- assert len(attrs) == 0
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on typedefs",
+ [attrs[0].location, self.location])
def _getDependentObjects(self):
return self.innerType._getDependentObjects()
class IDLWrapperType(IDLType):
- def __init__(self, location, inner, promiseInnerType=None):
+ def __init__(self, location, inner):
IDLType.__init__(self, location, inner.identifier.name)
self.inner = inner
self._identifier = inner.identifier
self.builtin = False
- assert not promiseInnerType or inner.identifier.name == "Promise"
- self._promiseInnerType = promiseInnerType
def __eq__(self, other):
return (isinstance(other, IDLWrapperType) and
@@ -2742,14 +2788,6 @@ class IDLWrapperType(IDLType):
def isEnum(self):
return isinstance(self.inner, IDLEnum)
- def isPromise(self):
- 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():
if self.inner.isExternal():
@@ -2781,8 +2819,6 @@ class IDLWrapperType(IDLType):
assert False
def isDistinguishableFrom(self, other):
- if self.isPromise():
- return False
if other.isPromise():
return False
if other.isUnion():
@@ -2792,7 +2828,7 @@ class IDLWrapperType(IDLType):
if self.isEnum():
return (other.isPrimitive() or other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or
- other.isSequence() or other.isMozMap() or other.isDate())
+ other.isSequence() or other.isRecord() or other.isDate())
if self.isDictionary() and other.nullable():
return False
if (other.isPrimitive() or other.isString() or other.isEnum() or
@@ -2814,7 +2850,7 @@ class IDLWrapperType(IDLType):
(self.isNonCallbackInterface() or
other.isNonCallbackInterface()))
if (other.isDictionary() or other.isCallback() or
- other.isMozMap()):
+ other.isRecord()):
return self.isNonCallbackInterface()
# Not much else |other| can be
@@ -2829,10 +2865,6 @@ 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 (self.isPromise() and
- # Check the internal type
- not self.promiseInnerType().unroll().isExposedInAllOf(exposureSet)):
- return False
return iface.exposureSet.issuperset(exposureSet)
def _getDependentObjects(self):
@@ -2860,6 +2892,45 @@ class IDLWrapperType(IDLType):
return set()
+class IDLPromiseType(IDLParametrizedType):
+ def __init__(self, location, innerType):
+ IDLParametrizedType.__init__(self, location, "Promise", innerType)
+
+ def __eq__(self, other):
+ return (isinstance(other, IDLPromiseType) and
+ self.promiseInnerType() == other.promiseInnerType())
+
+ def __str__(self):
+ return self.inner.__str__() + "Promise"
+
+ def isPromise(self):
+ return True
+
+ def promiseInnerType(self):
+ return self.inner
+
+ def tag(self):
+ return IDLType.Tags.promise
+
+ def complete(self, scope):
+ self.inner = self.promiseInnerType().complete(scope)
+ return self
+
+ def unroll(self):
+ # We do not unroll our inner. Just stop at ourselves. That
+ # lets us add headers for both ourselves and our inner as
+ # needed.
+ return self
+
+ def isDistinguishableFrom(self, other):
+ # Promises are not distinguishable from anything.
+ return False
+
+ def isExposedInAllOf(self, exposureSet):
+ # Check the internal type
+ return self.promiseInnerType().unroll().isExposedInAllOf(exposureSet)
+
+
class IDLBuiltinType(IDLType):
Types = enum(
@@ -3024,17 +3095,17 @@ class IDLBuiltinType(IDLType):
return (other.isNumeric() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or
- other.isSequence() or other.isMozMap() or other.isDate())
+ other.isSequence() or other.isRecord() or other.isDate())
if self.isNumeric():
return (other.isBoolean() or other.isString() or other.isEnum() or
other.isInterface() or other.isObject() or
other.isCallback() or other.isDictionary() or
- other.isSequence() or other.isMozMap() or other.isDate())
+ other.isSequence() or other.isRecord() or other.isDate())
if self.isString():
return (other.isPrimitive() or other.isInterface() or
other.isObject() or
other.isCallback() or other.isDictionary() or
- other.isSequence() or other.isMozMap() or other.isDate())
+ other.isSequence() or other.isRecord() or other.isDate())
if self.isAny():
# Can't tell "any" apart from anything
return False
@@ -3044,7 +3115,7 @@ class IDLBuiltinType(IDLType):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isInterface() or other.isCallback() or
other.isDictionary() or other.isSequence() or
- other.isMozMap())
+ other.isRecord())
if self.isVoid():
return not other.isVoid()
# Not much else we could be!
@@ -3052,7 +3123,7 @@ class IDLBuiltinType(IDLType):
# Like interfaces, but we know we're not a callback
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isCallback() or other.isDictionary() or
- other.isSequence() or other.isMozMap() or other.isDate() or
+ other.isSequence() or other.isRecord() or other.isDate() or
(other.isInterface() and (
# ArrayBuffer is distinguishable from everything
# that's not an ArrayBuffer or a callback interface
@@ -3456,6 +3527,14 @@ class IDLInterfaceMember(IDLObjectWithIdentifier, IDLExposureMixins):
raise WebIDLError("A [NewObject] method is not idempotent, "
"so it has to depend on something other than DOM state.",
[self.location])
+ if (self.getExtendedAttribute("Cached") or
+ self.getExtendedAttribute("StoreInSlot")):
+ raise WebIDLError("A [NewObject] attribute shouldnt be "
+ "[Cached] or [StoreInSlot], since the point "
+ "of those is to keep returning the same "
+ "thing across multiple calls, which is not "
+ "what [NewObject] does.",
+ [self.location])
def _setDependsOn(self, dependsOn):
if self.dependsOn != "Everything":
@@ -3527,8 +3606,10 @@ class IDLMaplikeOrSetlikeOrIterableBase(IDLInterfaceMember):
(member.identifier.name,
self.maplikeOrSetlikeOrIterableType),
[self.location, member.location])
- # Check that there are no disallowed non-method members
- if (isAncestor or (member.isAttr() or member.isConst()) and
+ # Check that there are no disallowed non-method members.
+ # Ancestor members are always disallowed here; own members
+ # are disallowed only if they're non-methods.
+ if ((isAncestor or member.isAttr() or member.isConst()) and
member.identifier.name in self.disallowedNonMethodNames):
raise WebIDLError("Member '%s' conflicts "
"with reserved %s method." %
@@ -3730,6 +3811,7 @@ class IDLMaplikeOrSetlike(IDLMaplikeOrSetlikeOrIterableBase):
True,
maplikeOrSetlike=self))
self.reserved_ro_names = ["size"]
+ self.disallowedMemberNames.append("size")
# object entries()
self.addMethod("entries", members, False, BuiltinTypes[IDLBuiltinType.Types.object],
@@ -3820,6 +3902,9 @@ class IDLConst(IDLInterfaceMember):
if type.isDictionary():
raise WebIDLError("A constant cannot be of a dictionary type",
[self.location])
+ if type.isRecord():
+ raise WebIDLError("A constant cannot be of a record type",
+ [self.location])
self.type = type
self.value = value
@@ -3931,8 +4016,8 @@ class IDLAttribute(IDLInterfaceMember):
if self.type.isSequence() and not self.getExtendedAttribute("Cached"):
raise WebIDLError("A non-cached attribute cannot be of a sequence "
"type", [self.location])
- if self.type.isMozMap() and not self.getExtendedAttribute("Cached"):
- raise WebIDLError("A non-cached attribute cannot be of a MozMap "
+ if self.type.isRecord() and not self.getExtendedAttribute("Cached"):
+ raise WebIDLError("A non-cached attribute cannot be of a record "
"type", [self.location])
if self.type.isUnion():
for f in self.type.unroll().flatMemberTypes:
@@ -3948,25 +4033,30 @@ class IDLAttribute(IDLInterfaceMember):
"one of its member types's member "
"types, and so on) is a sequence "
"type", [self.location, f.location])
- if f.isMozMap():
+ if f.isRecord():
raise WebIDLError("An attribute cannot be of a union "
"type if one of its member types (or "
"one of its member types's member "
- "types, and so on) is a MozMap "
+ "types, and so on) is a record "
"type", [self.location, f.location])
if not self.type.isInterface() and self.getExtendedAttribute("PutForwards"):
raise WebIDLError("An attribute with [PutForwards] must have an "
"interface type as its type", [self.location])
- if not self.type.isInterface() and self.getExtendedAttribute("SameObject"):
+ if (not self.type.isInterface() and
+ self.getExtendedAttribute("SameObject")):
raise WebIDLError("An attribute with [SameObject] must have an "
"interface type as its type", [self.location])
+ if self.type.isPromise() and not self.readonly:
+ raise WebIDLError("Promise-returning attributes must be readonly",
+ [self.location])
+
def validate(self):
def typeContainsChromeOnlyDictionaryMember(type):
if (type.nullable() or
type.isSequence() or
- type.isMozMap()):
+ type.isRecord()):
return typeContainsChromeOnlyDictionaryMember(type.inner)
if type.isUnion():
@@ -4012,27 +4102,36 @@ class IDLAttribute(IDLInterfaceMember):
[self.location, location])
if self.getExtendedAttribute("Frozen"):
if (not self.type.isSequence() and not self.type.isDictionary() and
- not self.type.isMozMap()):
+ not self.type.isRecord()):
raise WebIDLError("[Frozen] is only allowed on "
"sequence-valued, dictionary-valued, and "
- "MozMap-valued attributes",
+ "record-valued attributes",
[self.location])
if not self.type.unroll().isExposedInAllOf(self.exposureSet):
raise WebIDLError("Attribute returns a type that is not exposed "
"everywhere where the attribute is exposed",
[self.location])
+ if self.getExtendedAttribute("CEReactions"):
+ if self.readonly:
+ raise WebIDLError("[CEReactions] is not allowed on "
+ "readonly attributes",
+ [self.location])
def handleExtendedAttribute(self, attr):
identifier = attr.identifier()
- if identifier == "SetterThrows" and self.readonly:
+ if ((identifier == "SetterThrows" or identifier == "SetterCanOOM")
+ and self.readonly):
raise WebIDLError("Readonly attributes must not be flagged as "
- "[SetterThrows]",
+ "[%s]" % identifier,
[self.location])
- elif (((identifier == "Throws" or identifier == "GetterThrows") and
+ elif (((identifier == "Throws" or identifier == "GetterThrows" or
+ identifier == "CanOOM" or identifier == "GetterCanOOM") and
self.getExtendedAttribute("StoreInSlot")) or
(identifier == "StoreInSlot" and
(self.getExtendedAttribute("Throws") or
- self.getExtendedAttribute("GetterThrows")))):
+ self.getExtendedAttribute("GetterThrows") or
+ self.getExtendedAttribute("CanOOM") or
+ self.getExtendedAttribute("GetterCanOOM")))):
raise WebIDLError("Throwing things can't be [StoreInSlot]",
[attr.location])
elif identifier == "LenientThis":
@@ -4066,6 +4165,10 @@ class IDLAttribute(IDLInterfaceMember):
if not self.readonly:
raise WebIDLError("[PutForwards] is only allowed on readonly "
"attributes", [attr.location, self.location])
+ if self.type.isPromise():
+ raise WebIDLError("[PutForwards] is not allowed on "
+ "Promise-typed attributes",
+ [attr.location, self.location])
if self.isStatic():
raise WebIDLError("[PutForwards] is only allowed on non-static "
"attributes", [attr.location, self.location])
@@ -4083,6 +4186,10 @@ class IDLAttribute(IDLInterfaceMember):
if not self.readonly:
raise WebIDLError("[Replaceable] is only allowed on readonly "
"attributes", [attr.location, self.location])
+ if self.type.isPromise():
+ raise WebIDLError("[Replaceable] is not allowed on "
+ "Promise-typed attributes",
+ [attr.location, self.location])
if self.isStatic():
raise WebIDLError("[Replaceable] is only allowed on non-static "
"attributes", [attr.location, self.location])
@@ -4097,6 +4204,10 @@ class IDLAttribute(IDLInterfaceMember):
if not self.readonly:
raise WebIDLError("[LenientSetter] is only allowed on readonly "
"attributes", [attr.location, self.location])
+ if self.type.isPromise():
+ raise WebIDLError("[LenientSetter] is not allowed on "
+ "Promise-typed attributes",
+ [attr.location, self.location])
if self.isStatic():
raise WebIDLError("[LenientSetter] is only allowed on non-static "
"attributes", [attr.location, self.location])
@@ -4191,17 +4302,27 @@ class IDLAttribute(IDLInterfaceMember):
raise WebIDLError("[Unscopable] is only allowed on non-static "
"attributes and operations",
[attr.location, self.location])
+ elif identifier == "CEReactions":
+ if not attr.noArguments():
+ raise WebIDLError("[CEReactions] must take no arguments",
+ [attr.location])
elif (identifier == "Pref" or
identifier == "Deprecated" or
identifier == "SetterThrows" or
identifier == "Throws" or
identifier == "GetterThrows" or
+ identifier == "SetterCanOOM" or
+ identifier == "CanOOM" or
+ identifier == "GetterCanOOM" or
identifier == "ChromeOnly" or
identifier == "Func" or
identifier == "SecureContext" or
identifier == "Frozen" or
identifier == "NewObject" or
identifier == "UnsafeInPrerendering" or
+ identifier == "NeedsSubjectPrincipal" or
+ identifier == "NeedsCallerType" or
+ identifier == "ReturnValueNeedsContainsHack" or
identifier == "BinaryName"):
# Known attributes that we don't need to do anything with here
pass
@@ -4482,7 +4603,7 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
static=False, getter=False, setter=False, creator=False,
deleter=False, specialType=NamedOrIndexed.Neither,
legacycaller=False, stringifier=False, jsonifier=False,
- maplikeOrSetlikeOrIterable=None):
+ maplikeOrSetlikeOrIterable=None, htmlConstructor=False):
# REVIEW: specialType is NamedOrIndexed -- wow, this is messed up.
IDLInterfaceMember.__init__(self, location, identifier,
IDLInterfaceMember.Tags.Method)
@@ -4512,6 +4633,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self._jsonifier = jsonifier
assert maplikeOrSetlikeOrIterable is None or isinstance(maplikeOrSetlikeOrIterable, IDLMaplikeOrSetlikeOrIterableBase)
self.maplikeOrSetlikeOrIterable = maplikeOrSetlikeOrIterable
+ assert isinstance(htmlConstructor, bool)
+ # The identifier of a HTMLConstructor must be 'constructor'.
+ assert not htmlConstructor or identifier.name == "constructor"
+ self._htmlConstructor = htmlConstructor
self._specialType = specialType
self._unforgeable = False
self.dependsOn = "Everything"
@@ -4612,6 +4737,9 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
self.isStringifier() or
self.isJsonifier())
+ def isHTMLConstructor(self):
+ return self._htmlConstructor
+
def hasOverloads(self):
return self._hasOverloads
@@ -4667,6 +4795,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
assert not method.isStringifier()
assert not self.isJsonifier()
assert not method.isJsonifier()
+ assert not self.isHTMLConstructor()
+ assert not method.isHTMLConstructor()
return self
@@ -4743,9 +4873,10 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
# 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 "
+ raise WebIDLError("Dictionary argument without any "
+ "required fields or union argument "
+ "containing such dictionary not "
+ "followed by a required argument "
"must be optional",
[argument.location])
@@ -4831,13 +4962,12 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
def handleExtendedAttribute(self, attr):
identifier = attr.identifier()
- if identifier == "GetterThrows":
- raise WebIDLError("Methods must not be flagged as "
- "[GetterThrows]",
- [attr.location, self.location])
- elif identifier == "SetterThrows":
+ if (identifier == "GetterThrows" or
+ identifier == "SetterThrows" or
+ identifier == "GetterCanOOM" or
+ identifier == "SetterCanOOM"):
raise WebIDLError("Methods must not be flagged as "
- "[SetterThrows]",
+ "[%s]" % identifier,
[attr.location, self.location])
elif identifier == "Unforgeable":
if self.isStatic():
@@ -4909,7 +5039,17 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
raise WebIDLError("[Unscopable] is only allowed on non-static "
"attributes and operations",
[attr.location, self.location])
+ elif identifier == "CEReactions":
+ if not attr.noArguments():
+ raise WebIDLError("[CEReactions] must take no arguments",
+ [attr.location])
+
+ if self.isSpecial() and not self.isSetter() and not self.isDeleter():
+ raise WebIDLError("[CEReactions] is only allowed on operation, "
+ "attribute, setter, and deleter",
+ [attr.location, self.location])
elif (identifier == "Throws" or
+ identifier == "CanOOM" or
identifier == "NewObject" or
identifier == "ChromeOnly" or
identifier == "UnsafeInPrerendering" or
@@ -4918,6 +5058,8 @@ class IDLMethod(IDLInterfaceMember, IDLScope):
identifier == "Func" or
identifier == "SecureContext" or
identifier == "BinaryName" or
+ identifier == "NeedsSubjectPrincipal" or
+ identifier == "NeedsCallerType" or
identifier == "StaticClassOverride"):
# Known attributes that we don't need to do anything with here
pass
@@ -4980,7 +5122,10 @@ class IDLImplementsStatement(IDLObject):
pass
def addExtendedAttributes(self, attrs):
- assert len(attrs) == 0
+ if len(attrs) != 0:
+ raise WebIDLError("There are no extended attributes that are "
+ "allowed on implements statements",
+ [attrs[0].location, self.location])
class IDLExtendedAttribute(IDLObject):
@@ -5119,7 +5264,7 @@ class Tokenizer(object):
"Promise": "PROMISE",
"required": "REQUIRED",
"sequence": "SEQUENCE",
- "MozMap": "MOZMAP",
+ "record": "RECORD",
"short": "SHORT",
"unsigned": "UNSIGNED",
"void": "VOID",
@@ -5837,6 +5982,9 @@ class Parser(Tokenizer):
specialType = IDLMethod.NamedOrIndexed.Named
elif argType == BuiltinTypes[IDLBuiltinType.Types.unsigned_long]:
specialType = IDLMethod.NamedOrIndexed.Indexed
+ if deleter:
+ raise WebIDLError("There is no such thing as an indexed deleter.",
+ [self.getLocation(p, 1)])
else:
raise WebIDLError("%s has wrong argument type (must be DOMString or UnsignedLong)" %
("getter" if getter else "deleter"),
@@ -6245,7 +6393,7 @@ class Parser(Tokenizer):
| OCTET
| OPTIONAL
| SEQUENCE
- | MOZMAP
+ | RECORD
| SETTER
| SHORT
| STATIC
@@ -6324,7 +6472,7 @@ class Parser(Tokenizer):
def p_NonAnyType(self, p):
"""
- NonAnyType : PrimitiveOrStringType Null
+ NonAnyType : PrimitiveType Null
| ARRAYBUFFER Null
| SHAREDARRAYBUFFER Null
| OBJECT Null
@@ -6340,6 +6488,12 @@ class Parser(Tokenizer):
p[0] = self.handleNullable(type, p[2])
+ def p_NonAnyTypeStringType(self, p):
+ """
+ NonAnyType : StringType Null
+ """
+ p[0] = self.handleNullable(p[1], p[2])
+
def p_NonAnyTypeSequenceType(self, p):
"""
NonAnyType : SEQUENCE LT Type GT Null
@@ -6348,25 +6502,22 @@ class Parser(Tokenizer):
type = IDLSequenceType(self.getLocation(p, 1), innerType)
p[0] = self.handleNullable(type, p[5])
- # Note: Promise<void> is allowed, so we want to parametrize on
- # ReturnType, not Type. Also, we want this to end up picking up
- # the Promise interface for now, hence the games with IDLUnresolvedType.
+ # Note: Promise<void> is allowed, so we want to parametrize on ReturnType,
+ # not Type. Promise types can't be null, hence no "Null" in there.
def p_NonAnyTypePromiseType(self, p):
"""
- NonAnyType : PROMISE LT ReturnType GT Null
+ NonAnyType : PROMISE LT ReturnType GT
"""
- innerType = p[3]
- promiseIdent = IDLUnresolvedIdentifier(self.getLocation(p, 1), "Promise")
- type = IDLUnresolvedType(self.getLocation(p, 1), promiseIdent, p[3])
- p[0] = self.handleNullable(type, p[5])
+ p[0] = IDLPromiseType(self.getLocation(p, 1), p[3])
- def p_NonAnyTypeMozMapType(self, p):
+ def p_NonAnyTypeRecordType(self, p):
"""
- NonAnyType : MOZMAP LT Type GT Null
+ NonAnyType : RECORD LT StringType COMMA Type GT Null
"""
- innerType = p[3]
- type = IDLMozMapType(self.getLocation(p, 1), innerType)
- p[0] = self.handleNullable(type, p[5])
+ keyType = p[3]
+ valueType = p[5]
+ type = IDLRecordType(self.getLocation(p, 1), keyType, valueType)
+ p[0] = self.handleNullable(type, p[7])
def p_NonAnyTypeScopedName(self, p):
"""
@@ -6409,7 +6560,7 @@ class Parser(Tokenizer):
def p_ConstType(self, p):
"""
- ConstType : PrimitiveOrStringType Null
+ ConstType : PrimitiveType Null
"""
type = BuiltinTypes[p[1]]
p[0] = self.handleNullable(type, p[2])
@@ -6423,69 +6574,75 @@ class Parser(Tokenizer):
type = IDLUnresolvedType(self.getLocation(p, 1), identifier)
p[0] = self.handleNullable(type, p[2])
- def p_PrimitiveOrStringTypeUint(self, p):
+ def p_PrimitiveTypeUint(self, p):
"""
- PrimitiveOrStringType : UnsignedIntegerType
+ PrimitiveType : UnsignedIntegerType
"""
p[0] = p[1]
- def p_PrimitiveOrStringTypeBoolean(self, p):
+ def p_PrimitiveTypeBoolean(self, p):
"""
- PrimitiveOrStringType : BOOLEAN
+ PrimitiveType : BOOLEAN
"""
p[0] = IDLBuiltinType.Types.boolean
- def p_PrimitiveOrStringTypeByte(self, p):
+ def p_PrimitiveTypeByte(self, p):
"""
- PrimitiveOrStringType : BYTE
+ PrimitiveType : BYTE
"""
p[0] = IDLBuiltinType.Types.byte
- def p_PrimitiveOrStringTypeOctet(self, p):
+ def p_PrimitiveTypeOctet(self, p):
"""
- PrimitiveOrStringType : OCTET
+ PrimitiveType : OCTET
"""
p[0] = IDLBuiltinType.Types.octet
- def p_PrimitiveOrStringTypeFloat(self, p):
+ def p_PrimitiveTypeFloat(self, p):
"""
- PrimitiveOrStringType : FLOAT
+ PrimitiveType : FLOAT
"""
p[0] = IDLBuiltinType.Types.float
- def p_PrimitiveOrStringTypeUnrestictedFloat(self, p):
+ def p_PrimitiveTypeUnrestictedFloat(self, p):
"""
- PrimitiveOrStringType : UNRESTRICTED FLOAT
+ PrimitiveType : UNRESTRICTED FLOAT
"""
p[0] = IDLBuiltinType.Types.unrestricted_float
- def p_PrimitiveOrStringTypeDouble(self, p):
+ def p_PrimitiveTypeDouble(self, p):
"""
- PrimitiveOrStringType : DOUBLE
+ PrimitiveType : DOUBLE
"""
p[0] = IDLBuiltinType.Types.double
- def p_PrimitiveOrStringTypeUnrestictedDouble(self, p):
+ def p_PrimitiveTypeUnrestictedDouble(self, p):
"""
- PrimitiveOrStringType : UNRESTRICTED DOUBLE
+ PrimitiveType : UNRESTRICTED DOUBLE
"""
p[0] = IDLBuiltinType.Types.unrestricted_double
- def p_PrimitiveOrStringTypeDOMString(self, p):
+ def p_StringType(self, p):
+ """
+ StringType : BuiltinStringType
+ """
+ p[0] = BuiltinTypes[p[1]]
+
+ def p_BuiltinStringTypeDOMString(self, p):
"""
- PrimitiveOrStringType : DOMSTRING
+ BuiltinStringType : DOMSTRING
"""
p[0] = IDLBuiltinType.Types.domstring
- def p_PrimitiveOrStringTypeBytestring(self, p):
+ def p_BuiltinStringTypeBytestring(self, p):
"""
- PrimitiveOrStringType : BYTESTRING
+ BuiltinStringType : BYTESTRING
"""
p[0] = IDLBuiltinType.Types.bytestring
- def p_PrimitiveOrStringTypeUSVString(self, p):
+ def p_BuiltinStringTypeUSVString(self, p):
"""
- PrimitiveOrStringType : USVSTRING
+ BuiltinStringType : USVSTRING
"""
p[0] = IDLBuiltinType.Types.usvstring
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_cereactions.py b/components/script/dom/bindings/codegen/parser/tests/test_cereactions.py
new file mode 100644
index 00000000000..2f9397d903e
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_cereactions.py
@@ -0,0 +1,162 @@
+def WebIDLTest(parser, harness):
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions(DOMString a)] void foo(boolean arg2);
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions(DOMString b)] readonly attribute boolean bar;
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] with an argument")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] attribute boolean bar;
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, e:
+ harness.ok(False, "Shouldn't have thrown for [CEReactions] used on writable attribute. %s" % e)
+ threw = True
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] void foo(boolean arg2);
+ };
+ """)
+
+ results = parser.finish()
+ except Exception, e:
+ harness.ok(False, "Shouldn't have thrown for [CEReactions] used on regular operations. %s" % e)
+ threw = True
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] readonly attribute boolean A;
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] used on a readonly attribute")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [CEReactions]
+ interface Foo {
+ }
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] used on a interface")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] getter any(DOMString name);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a named getter")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] creator boolean (DOMString name, boolean value);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a named creator")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] legacycaller double compute(double x);
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a legacycaller")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] stringifier DOMString ();
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw,
+ "Should have thrown for [CEReactions] used on a stringifier")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface Foo {
+ [CEReactions] jsonifier;
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown for [CEReactions] used on a jsonifier")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_constructor.py b/components/script/dom/bindings/codegen/parser/tests/test_constructor.py
index 348204c7dc1..6c68a6c79cf 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_constructor.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_constructor.py
@@ -13,7 +13,7 @@ def WebIDLTest(parser, harness):
def checkMethod(method, QName, name, signatures,
static=True, getter=False, setter=False, creator=False,
deleter=False, legacycaller=False, stringifier=False,
- chromeOnly=False):
+ chromeOnly=False, htmlConstructor=False):
harness.ok(isinstance(method, WebIDL.IDLMethod),
"Should be an IDLMethod")
harness.ok(method.isMethod(), "Method is a method")
@@ -29,6 +29,7 @@ def WebIDLTest(parser, harness):
harness.check(method.isLegacycaller(), legacycaller, "Method has the correct legacycaller value")
harness.check(method.isStringifier(), stringifier, "Method has the correct stringifier value")
harness.check(method.getExtendedAttribute("ChromeOnly") is not None, chromeOnly, "Method has the correct value for ChromeOnly")
+ harness.check(method.isHTMLConstructor(), htmlConstructor, "Method has the correct htmlConstructor value")
harness.check(len(method.signatures()), len(signatures), "Method has the correct number of signatures")
sigpairs = zip(method.signatures(), signatures)
@@ -94,6 +95,21 @@ def WebIDLTest(parser, harness):
chromeOnly=True)
parser = parser.reset()
+ parser.parse("""
+ [HTMLConstructor]
+ interface TestHTMLConstructor {
+ };
+ """)
+ results = parser.finish()
+ harness.check(len(results), 1, "Should be one production")
+ harness.ok(isinstance(results[0], WebIDL.IDLInterface),
+ "Should be an IDLInterface")
+
+ checkMethod(results[0].ctor(), "::TestHTMLConstructor::constructor",
+ "constructor", [("TestHTMLConstructor (Wrapper)", [])],
+ htmlConstructor=True)
+
+ parser = parser.reset()
threw = False
try:
parser.parse("""
@@ -107,3 +123,151 @@ def WebIDLTest(parser, harness):
threw = True
harness.ok(threw, "Can't have both a Constructor and a ChromeConstructor")
+
+ # Test HTMLConstructor with argument
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor(DOMString a)]
+ interface TestHTMLConstructorWithArgs {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "HTMLConstructor should take no argument")
+
+ # Test HTMLConstructor on a callback interface
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor]
+ callback interface TestHTMLConstructorOnCallbackInterface {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "HTMLConstructor can't be used on a callback interface")
+
+ # Test HTMLConstructor and Constructor
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [Constructor,
+ HTMLConstructor]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a Constructor and a HTMLConstructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ Constructor]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ Constructor(DOMString a)]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [Constructor(DOMString a),
+ HTMLConstructor]
+ interface TestHTMLConstructorAndConstructor {
+ };
+ """)
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a Constructor")
+
+ # Test HTMLConstructor and ChromeConstructor
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [ChromeConstructor,
+ HTMLConstructor]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ ChromeConstructor]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [ChromeConstructor(DOMString a),
+ HTMLConstructor]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor,
+ ChromeConstructor(DOMString a)]
+ interface TestHTMLConstructorAndChromeConstructor {
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Can't have both a HTMLConstructor and a ChromeConstructor")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py b/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py
index 2b09ae71e69..40708e7870e 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_constructor_no_interface_object.py
@@ -34,3 +34,36 @@ def WebIDLTest(parser, harness):
interface TestNamedConstructorNoInterfaceObject {
};
""")
+
+ # Test HTMLConstructor and NoInterfaceObject
+ parser = parser.reset()
+
+ threw = False
+ try:
+ parser.parse("""
+ [NoInterfaceObject, HTMLConstructor]
+ interface TestHTMLConstructorNoInterfaceObject {
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown.")
+
+ parser = parser.reset()
+
+ threw = False
+ try:
+ parser.parse("""
+ [HTMLConstructor, NoInterfaceObject]
+ interface TestHTMLConstructorNoInterfaceObject {
+ };
+ """)
+
+ results = parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "Should have thrown.")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py b/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py
index d7780c1ffa1..73a32b0acfb 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_distinguishability.py
@@ -158,21 +158,27 @@ def WebIDLTest(parser, harness):
"CallbackInterface?", "CallbackInterface2",
"object", "Callback", "Callback2", "optional Dict",
"optional Dict2", "sequence<long>", "sequence<short>",
- "MozMap<object>", "MozMap<Dict>", "MozMap<long>",
+ "record<DOMString, object>",
+ "record<USVString, Dict>",
+ "record<ByteString, long>",
"Date", "Date?", "any",
"Promise<any>", "Promise<any>?",
"USVString", "ArrayBuffer", "ArrayBufferView", "SharedArrayBuffer",
- "Uint8Array", "Uint16Array" ]
- # When we can parse Date and RegExp, we need to add them here.
+ "Uint8Array", "Uint16Array",
+ "(long or Callback)", "optional (long or Dict)",
+ ]
+ # When we can parse Date, we need to add it here.
+ # XXXbz we can, and should really do that...
# Try to categorize things a bit to keep list lengths down
def allBut(list1, list2):
return [a for a in list1 if a not in list2 and
(a != "any" and a != "Promise<any>" and a != "Promise<any>?")]
+ unions = [ "(long or Callback)", "optional (long or Dict)" ]
numerics = [ "long", "short", "long?", "short?" ]
booleans = [ "boolean", "boolean?" ]
primitives = numerics + booleans
- nonNumerics = allBut(argTypes, numerics)
+ nonNumerics = allBut(argTypes, numerics + unions)
nonBooleans = allBut(argTypes, booleans)
strings = [ "DOMString", "ByteString", "Enum", "Enum2", "USVString" ]
nonStrings = allBut(argTypes, strings)
@@ -182,16 +188,18 @@ def WebIDLTest(parser, harness):
sharedBufferSourceTypes = ["SharedArrayBuffer"]
interfaces = [ "Interface", "Interface?", "AncestorInterface",
"UnrelatedInterface", "ImplementedInterface" ] + bufferSourceTypes + sharedBufferSourceTypes
- nullables = ["long?", "short?", "boolean?", "Interface?",
- "CallbackInterface?", "optional Dict", "optional Dict2",
- "Date?", "any", "Promise<any>?"]
+ nullables = (["long?", "short?", "boolean?", "Interface?",
+ "CallbackInterface?", "optional Dict", "optional Dict2",
+ "Date?", "any", "Promise<any>?"] +
+ allBut(unions, [ "(long or Callback)" ]))
dates = [ "Date", "Date?" ]
sequences = [ "sequence<long>", "sequence<short>" ]
nonUserObjects = nonObjects + interfaces + dates + sequences
otherObjects = allBut(argTypes, nonUserObjects + ["object"])
notRelatedInterfaces = (nonObjects + ["UnrelatedInterface"] +
otherObjects + dates + sequences + bufferSourceTypes + sharedBufferSourceTypes)
- mozMaps = [ "MozMap<object>", "MozMap<Dict>", "MozMap<long>" ]
+ records = [ "record<DOMString, object>", "record<USVString, Dict>",
+ "record<ByteString, long>" ]
# Build a representation of the distinguishability table as a dict
# of dicts, holding True values where needed, holes elsewhere.
@@ -231,9 +239,9 @@ def WebIDLTest(parser, harness):
allBut(argTypes, sequences + ["object"]))
setDistinguishable("sequence<short>",
allBut(argTypes, sequences + ["object"]))
- setDistinguishable("MozMap<object>", nonUserObjects)
- setDistinguishable("MozMap<Dict>", nonUserObjects)
- setDistinguishable("MozMap<long>", nonUserObjects)
+ setDistinguishable("record<DOMString, object>", nonUserObjects)
+ setDistinguishable("record<USVString, Dict>", nonUserObjects)
+ setDistinguishable("record<ByteString, long>", nonUserObjects)
setDistinguishable("Date", allBut(argTypes, dates + ["object"]))
setDistinguishable("Date?", allBut(argTypes, dates + nullables + ["object"]))
setDistinguishable("any", [])
@@ -244,6 +252,10 @@ def WebIDLTest(parser, harness):
setDistinguishable("Uint8Array", allBut(argTypes, ["ArrayBufferView", "Uint8Array", "object"]))
setDistinguishable("Uint16Array", allBut(argTypes, ["ArrayBufferView", "Uint16Array", "object"]))
setDistinguishable("SharedArrayBuffer", allBut(argTypes, ["SharedArrayBuffer", "object"]))
+ setDistinguishable("(long or Callback)",
+ allBut(nonUserObjects, numerics))
+ setDistinguishable("optional (long or Dict)",
+ allBut(nonUserObjects, numerics + nullables))
def areDistinguishable(type1, type2):
return data[type1].get(type2, False)
@@ -263,7 +275,6 @@ def WebIDLTest(parser, harness):
callback Callback2 = long(short arg);
dictionary Dict {};
dictionary Dict2 {};
- interface _Promise {};
interface TestInterface {%s
};
"""
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_identifier_conflict.py b/components/script/dom/bindings/codegen/parser/tests/test_identifier_conflict.py
new file mode 100644
index 00000000000..b510a30c044
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_identifier_conflict.py
@@ -0,0 +1,39 @@
+# Import the WebIDL module, so we can do isinstance checks and whatnot
+import WebIDL
+
+def WebIDLTest(parser, harness):
+ try:
+ parser.parse("""
+ enum Foo { "a" };
+ interface Foo;
+ """)
+ results = parser.finish()
+ harness.ok(False, "Should fail to parse")
+ except Exception, e:
+ harness.ok("Name collision" in e.message,
+ "Should have name collision for interface")
+
+ parser = parser.reset()
+ try:
+ parser.parse("""
+ dictionary Foo { long x; };
+ enum Foo { "a" };
+ """)
+ results = parser.finish()
+ harness.ok(False, "Should fail to parse")
+ except Exception, e:
+ harness.ok("Name collision" in e.message,
+ "Should have name collision for dictionary")
+
+ parser = parser.reset()
+ try:
+ parser.parse("""
+ enum Foo { "a" };
+ enum Foo { "b" };
+ """)
+ results = parser.finish()
+ harness.ok(False, "Should fail to parse")
+ except Exception, e:
+ harness.ok("Multiple unresolvable definitions" in e.message,
+ "Should have name collision for dictionary")
+
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_interface_maplikesetlikeiterable.py b/components/script/dom/bindings/codegen/parser/tests/test_interface_maplikesetlikeiterable.py
index 159b50f84ff..ee5d870c200 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_interface_maplikesetlikeiterable.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_interface_maplikesetlikeiterable.py
@@ -88,6 +88,8 @@ def WebIDLTest(parser, harness):
disallowedNonMethodNames = ["clear", "delete"]
mapDisallowedNonMethodNames = ["set"] + disallowedNonMethodNames
setDisallowedNonMethodNames = ["add"] + disallowedNonMethodNames
+ unrelatedMembers = [("unrelatedAttribute", WebIDL.IDLAttribute),
+ ("unrelatedMethod", WebIDL.IDLMethod)]
#
# Simple Usage Tests
@@ -99,52 +101,147 @@ def WebIDLTest(parser, harness):
iterable<long>;
readonly attribute unsigned long length;
getter long(unsigned long index);
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
};
- """, valueIterableMembers)
+ """, valueIterableMembers + unrelatedMembers)
+
+ shouldPass("Iterable (key only) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ iterable<long>;
+ readonly attribute unsigned long length;
+ getter long(unsigned long index);
+ };
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, valueIterableMembers, numProductions=2)
shouldPass("Iterable (key and value)",
"""
interface Foo1 {
iterable<long, long>;
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
};
- """, iterableMembers,
+ """, iterableMembers + unrelatedMembers,
# numProductions == 2 because of the generated iterator iface,
numProductions=2)
+ shouldPass("Iterable (key and value) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ iterable<long, long>;
+ };
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, iterableMembers,
+ # numProductions == 3 because of the generated iterator iface,
+ numProductions=3)
+
shouldPass("Maplike (readwrite)",
"""
interface Foo1 {
maplike<long, long>;
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, mapRWMembers + unrelatedMembers)
+
+ shouldPass("Maplike (readwrite) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ maplike<long, long>;
+ };
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
};
- """, mapRWMembers)
+ """, mapRWMembers, numProductions=2)
shouldPass("Maplike (readwrite)",
"""
interface Foo1 {
maplike<long, long>;
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, mapRWMembers + unrelatedMembers)
+
+ shouldPass("Maplike (readwrite) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ maplike<long, long>;
};
- """, mapRWMembers)
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, mapRWMembers, numProductions=2)
shouldPass("Maplike (readonly)",
"""
interface Foo1 {
readonly maplike<long, long>;
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, mapROMembers + unrelatedMembers)
+
+ shouldPass("Maplike (readonly) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ readonly maplike<long, long>;
+ };
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
};
- """, mapROMembers)
+ """, mapROMembers, numProductions=2)
shouldPass("Setlike (readwrite)",
"""
interface Foo1 {
setlike<long>;
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
};
- """, setRWMembers)
+ """, setRWMembers + unrelatedMembers)
+
+ shouldPass("Setlike (readwrite) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ setlike<long>;
+ };
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, setRWMembers, numProductions=2)
shouldPass("Setlike (readonly)",
"""
interface Foo1 {
readonly setlike<long>;
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
+ };
+ """, setROMembers + unrelatedMembers)
+
+ shouldPass("Setlike (readonly) inheriting from parent",
+ """
+ interface Foo1 : Foo2 {
+ readonly setlike<long>;
+ };
+ interface Foo2 {
+ attribute long unrelatedAttribute;
+ long unrelatedMethod();
};
- """, setROMembers)
+ """, setROMembers, numProductions=2)
shouldPass("Inheritance of maplike/setlike",
"""
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_newobject.py b/components/script/dom/bindings/codegen/parser/tests/test_newobject.py
new file mode 100644
index 00000000000..26785c6a270
--- /dev/null
+++ b/components/script/dom/bindings/codegen/parser/tests/test_newobject.py
@@ -0,0 +1,70 @@
+# Import the WebIDL module, so we can do isinstance checks and whatnot
+import WebIDL
+
+def WebIDLTest(parser, harness):
+ # Basic functionality
+ parser.parse(
+ """
+ interface Iface {
+ [NewObject] readonly attribute Iface attr;
+ [NewObject] Iface method();
+ };
+ """)
+ results = parser.finish()
+ harness.ok(results, "Should not have thrown on basic [NewObject] usage")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface Iface {
+ [Pure, NewObject] readonly attribute Iface attr;
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[NewObject] attributes must depend on something")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface Iface {
+ [Pure, NewObject] Iface method();
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[NewObject] methods must depend on something")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface Iface {
+ [Cached, NewObject, Affects=Nothing] readonly attribute Iface attr;
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[NewObject] attributes must not be [Cached]")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface Iface {
+ [StoreInSlot, NewObject, Affects=Nothing] readonly attribute Iface attr;
+ };
+ """)
+ results = parser.finish()
+ except:
+ threw = True
+ harness.ok(threw, "[NewObject] attributes must not be [StoreInSlot]")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_promise.py b/components/script/dom/bindings/codegen/parser/tests/test_promise.py
index 55bc0768092..43c74029dc5 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_promise.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_promise.py
@@ -2,7 +2,6 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
- interface _Promise {};
interface A {
legacycaller Promise<any> foo();
};
@@ -18,7 +17,6 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
- interface _Promise {};
interface A {
Promise<any> foo();
long foo(long arg);
@@ -35,7 +33,6 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
- interface _Promise {};
interface A {
long foo(long arg);
Promise<any> foo();
@@ -49,8 +46,35 @@ def WebIDLTest(parser, harness):
"non-Promise return types.")
parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ Promise<any>? foo();
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow nullable Promise return values.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ void foo(Promise<any>? arg);
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow nullable Promise arguments.")
+
+ parser = parser.reset()
parser.parse("""
- interface _Promise {};
interface A {
Promise<any> foo();
Promise<any> foo(long arg);
@@ -61,3 +85,73 @@ def WebIDLTest(parser, harness):
harness.ok(True,
"Should allow overloads which only have Promise and return "
"types.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ attribute Promise<any> attr;
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow writable Promise-typed attributes.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ [LenientSetter] readonly attribute Promise<any> attr;
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow [LenientSetter] Promise-typed attributes.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ [PutForwards=bar] readonly attribute Promise<any> attr;
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow [PutForwards] Promise-typed attributes.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ [Replaceable] readonly attribute Promise<any> attr;
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow [Replaceable] Promise-typed attributes.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ interface A {
+ [SameObject] readonly attribute Promise<any> attr;
+ };
+ """)
+ results = parser.finish();
+ except:
+ threw = True
+ harness.ok(threw,
+ "Should not allow [SameObject] Promise-typed attributes.")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_mozmap.py b/components/script/dom/bindings/codegen/parser/tests/test_record.py
index 1a36fdd62c4..c3fe29fa060 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_mozmap.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_record.py
@@ -3,8 +3,8 @@ import WebIDL
def WebIDLTest(parser, harness):
parser.parse("""
dictionary Dict {};
- interface MozMapArg {
- void foo(MozMap<Dict> arg);
+ interface RecordArg {
+ void foo(record<DOMString, Dict> arg);
};
""")
@@ -19,7 +19,7 @@ def WebIDLTest(parser, harness):
signature = members[0].signatures()[0]
args = signature[1]
harness.check(len(args), 1, "Should have one arg")
- harness.ok(args[0].type.isMozMap(), "Should have a MozMap type here")
+ harness.ok(args[0].type.isRecord(), "Should have a record type here")
harness.ok(args[0].type.inner.isDictionary(),
"Should have a dictionary inner type")
@@ -27,13 +27,27 @@ def WebIDLTest(parser, harness):
threw = False
try:
parser.parse("""
- interface MozMapVoidArg {
- void foo(MozMap<void> arg);
+ interface RecordVoidArg {
+ void foo(record<DOMString, void> arg);
};
""")
results = parser.finish()
except Exception,x:
threw = True
+ harness.ok(threw, "Should have thrown because record can't have void as value type.")
+
+ parser = parser.reset()
+ threw = False
+ try:
+ parser.parse("""
+ dictionary Dict {
+ record<DOMString, Dict> val;
+ };
+ """)
- harness.ok(threw, "Should have thrown.")
+ results = parser.finish()
+ except Exception,x:
+ threw = True
+ harness.ok(threw,
+ "Should have thrown on dictionary containing itself via record.")
diff --git a/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py b/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py
index 695cfe4f250..1e3a95b9bc2 100644
--- a/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py
+++ b/components/script/dom/bindings/codegen/parser/tests/test_special_methods.py
@@ -6,15 +6,14 @@ def WebIDLTest(parser, harness):
getter long long (unsigned long index);
setter long long (unsigned long index, long long value);
creator long long (unsigned long index, long long value);
- deleter long long (unsigned long index);
getter boolean (DOMString name);
setter boolean (DOMString name, boolean value);
creator boolean (DOMString name, boolean value);
deleter boolean (DOMString name);
+ readonly attribute unsigned long length;
};
interface SpecialMethodsCombination {
- getter deleter long long (unsigned long index);
setter creator long long (unsigned long index, long long value);
getter deleter boolean (DOMString name);
setter creator boolean (DOMString name, boolean value);
@@ -49,25 +48,39 @@ def WebIDLTest(parser, harness):
setter=True)
checkMethod(iface.members[2], "::SpecialMethods::__indexedcreator", "__indexedcreator",
creator=True)
- checkMethod(iface.members[3], "::SpecialMethods::__indexeddeleter", "__indexeddeleter",
- deleter=True)
- checkMethod(iface.members[4], "::SpecialMethods::__namedgetter", "__namedgetter",
+ checkMethod(iface.members[3], "::SpecialMethods::__namedgetter", "__namedgetter",
getter=True)
- checkMethod(iface.members[5], "::SpecialMethods::__namedsetter", "__namedsetter",
+ checkMethod(iface.members[4], "::SpecialMethods::__namedsetter", "__namedsetter",
setter=True)
- checkMethod(iface.members[6], "::SpecialMethods::__namedcreator", "__namedcreator",
+ checkMethod(iface.members[5], "::SpecialMethods::__namedcreator", "__namedcreator",
creator=True)
- checkMethod(iface.members[7], "::SpecialMethods::__nameddeleter", "__nameddeleter",
+ checkMethod(iface.members[6], "::SpecialMethods::__nameddeleter", "__nameddeleter",
deleter=True)
iface = results[1]
- harness.check(len(iface.members), 4, "Expect 4 members")
+ harness.check(len(iface.members), 3, "Expect 3 members")
- checkMethod(iface.members[0], "::SpecialMethodsCombination::__indexedgetterdeleter",
- "__indexedgetterdeleter", getter=True, deleter=True)
- checkMethod(iface.members[1], "::SpecialMethodsCombination::__indexedsettercreator",
+ checkMethod(iface.members[0], "::SpecialMethodsCombination::__indexedsettercreator",
"__indexedsettercreator", setter=True, creator=True)
- checkMethod(iface.members[2], "::SpecialMethodsCombination::__namedgetterdeleter",
+ checkMethod(iface.members[1], "::SpecialMethodsCombination::__namedgetterdeleter",
"__namedgetterdeleter", getter=True, deleter=True)
- checkMethod(iface.members[3], "::SpecialMethodsCombination::__namedsettercreator",
+ checkMethod(iface.members[2], "::SpecialMethodsCombination::__namedsettercreator",
"__namedsettercreator", setter=True, creator=True)
+
+ parser = parser.reset();
+
+ threw = False
+ try:
+ parser.parse(
+ """
+ interface IndexedDeleter {
+ deleter void(unsigned long index);
+ };
+ """)
+ parser.finish()
+ except:
+ threw = True
+
+ harness.ok(threw, "There are no indexed deleters")
+
+