Port modern callback handling code from Gecko, and copy related WebIDL parser bits too.

This commit is contained in:
Josh Matthews 2014-04-22 17:14:48 -04:00 committed by Ms2ger
parent 04931adf70
commit 003e5bcd46
18 changed files with 442 additions and 223 deletions

View file

@ -464,6 +464,10 @@ class IDLInterface(IDLObjectWithScope):
self._callback = False
self._finished = False
self.members = []
# namedConstructors needs deterministic ordering because bindings code
# outputs the constructs in the order that namedConstructors enumerates
# them.
self.namedConstructors = list()
self.implementedInterfaces = set()
self._consequential = False
self._isPartial = True
@ -696,6 +700,9 @@ class IDLInterface(IDLObjectWithScope):
if identifier == "TreatNonCallableAsNull":
raise WebIDLError("TreatNonCallableAsNull cannot be specified on interfaces",
[attr.location, self.location])
if identifier == "TreatNonObjectAsNull":
raise WebIDLError("TreatNonObjectAsNull cannot be specified on interfaces",
[attr.location, self.location])
elif identifier == "NoInterfaceObject":
if not attr.noArguments():
raise WebIDLError("[NoInterfaceObject] must take no arguments",
@ -1049,11 +1056,12 @@ class IDLType(IDLObject):
assert False # Override me!
def treatNonCallableAsNull(self):
if not (self.nullable() and self.tag() == IDLType.Tags.callback):
raise WebIDLError("Type %s cannot be TreatNonCallableAsNull" % self,
[self.location])
assert self.tag() == IDLType.Tags.callback
return self.nullable() and self.inner._treatNonCallableAsNull
return hasattr(self, "_treatNonCallableAsNull")
def treatNonObjectAsNull(self):
assert self.tag() == IDLType.Tags.callback
return self.nullable() and self.inner._treatNonObjectAsNull
def markTreatNonCallableAsNull(self):
assert not self.treatNonCallableAsNull()
@ -2189,6 +2197,7 @@ class IDLArgument(IDLObjectWithIdentifier):
self._isComplete = False
self.enforceRange = False
self.clamp = False
self._allowTreatNonCallableAsNull = False
assert not variadic or optional
@ -2215,6 +2224,8 @@ class IDLArgument(IDLObjectWithIdentifier):
raise WebIDLError("[EnforceRange] and [Clamp] are mutually exclusive",
[self.location]);
self.enforceRange = True
elif identifier == "TreatNonCallableAsNull":
self._allowTreatNonCallableAsNull = True
else:
raise WebIDLError("Unhandled extended attribute on an argument",
[attribute.location])
@ -2247,6 +2258,9 @@ class IDLArgument(IDLObjectWithIdentifier):
self.location)
assert self.defaultValue
def allowTreatNonCallableAsNull(self):
return self._allowTreatNonCallableAsNull
def _getDependentObjects(self):
deps = set([self.type])
if self.defaultValue:
@ -2269,6 +2283,12 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
for argument in arguments:
argument.resolve(self)
self._treatNonCallableAsNull = False
self._treatNonObjectAsNull = False
def module(self):
return self.location.filename().split('/')[-1].split('.webidl')[0] + 'Binding'
def isCallback(self):
return True
@ -2308,6 +2328,21 @@ class IDLCallbackType(IDLType, IDLObjectWithScope):
return (other.isPrimitive() or other.isString() or other.isEnum() or
other.isNonCallbackInterface() or other.isDate())
def addExtendedAttributes(self, attrs):
unhandledAttrs = []
for attr in attrs:
if attr.identifier() == "TreatNonCallableAsNull":
self._treatNonCallableAsNull = True
elif attr.identifier() == "TreatNonObjectAsNull":
self._treatNonObjectAsNull = True
else:
unhandledAttrs.append(attr)
if self._treatNonCallableAsNull and self._treatNonObjectAsNull:
raise WebIDLError("Cannot specify both [TreatNonCallableAsNull] "
"and [TreatNonObjectAsNull]", [self.location])
if len(unhandledAttrs) != 0:
IDLType.addExtendedAttributes(self, unhandledAttrs)
def _getDependentObjects(self):
return set([self._returnType] + self._arguments)