mirror of
https://github.com/servo/servo.git
synced 2025-06-09 09:03:23 +00:00
Port modern callback handling code from Gecko, and copy related WebIDL parser bits too.
This commit is contained in:
parent
04931adf70
commit
003e5bcd46
18 changed files with 442 additions and 223 deletions
|
@ -7,9 +7,10 @@
|
|||
import os
|
||||
import string
|
||||
import operator
|
||||
import itertools
|
||||
|
||||
from WebIDL import *
|
||||
from Configuration import Descriptor
|
||||
from Configuration import getTypesFromDescriptor, getTypesFromDictionary, getTypesFromCallback, Descriptor
|
||||
|
||||
AUTOGENERATED_WARNING_COMMENT = \
|
||||
"/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n\n"
|
||||
|
@ -406,6 +407,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
isEnforceRange=False,
|
||||
isClamp=False,
|
||||
exceptionCode=None,
|
||||
allowTreatNonObjectAsNull=False,
|
||||
isCallbackReturnValue=False,
|
||||
sourceDescription="value"):
|
||||
"""
|
||||
|
@ -439,6 +441,9 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
If isClamp is true, we're converting an integer and clamping if the
|
||||
value is out of range.
|
||||
|
||||
If allowTreatNonObjectAsNull is true, then [TreatNonObjectAsNull]
|
||||
extended attributes on nullable callback functions will be honored.
|
||||
|
||||
The return value from this function is a tuple consisting of four things:
|
||||
|
||||
1) A string representing the conversion code. This will have template
|
||||
|
@ -500,6 +505,14 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
'%s' % (firstCap(sourceDescription), typeName,
|
||||
exceptionCode))),
|
||||
post="\n")
|
||||
def onFailureNotCallable(failureCode):
|
||||
return CGWrapper(
|
||||
CGGeneric(
|
||||
failureCode or
|
||||
('//XXXjdm ThrowErrorMessage(cx, MSG_NOT_CALLABLE, "%s");\n'
|
||||
'%s' % (firstCap(sourceDescription), exceptionCode))),
|
||||
post="\n")
|
||||
|
||||
|
||||
# A helper function for handling null default values. Checks that the
|
||||
# default value, if it exists, is null.
|
||||
|
@ -699,23 +712,39 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
|||
|
||||
if type.isCallback():
|
||||
assert not isEnforceRange and not isClamp
|
||||
assert not type.treatNonCallableAsNull()
|
||||
assert not type.treatNonObjectAsNull() or type.nullable()
|
||||
assert not type.treatNonObjectAsNull() or not type.treatNonCallableAsNull()
|
||||
|
||||
if isMember:
|
||||
raise TypeError("Can't handle member callbacks; need to sort out "
|
||||
"rooting issues")
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable and always have [TreatNonCallableAsNull] for now.
|
||||
haveCallable = "${val}.is_object() && JS_ObjectIsCallable(cx, ${val}.to_object()) != 0"
|
||||
if defaultValue is not None:
|
||||
assert(isinstance(defaultValue, IDLNullValue))
|
||||
haveCallable = "${haveValue} && " + haveCallable
|
||||
return (
|
||||
"if (%s) {\n"
|
||||
" ${val}.to_object()\n"
|
||||
"} else {\n"
|
||||
" ptr::mut_null()\n"
|
||||
"}" % haveCallable,
|
||||
CGGeneric("*mut JSObject"), needsRooting)
|
||||
declType = CGGeneric('%s::%s' % (type.unroll().module(), type.unroll().identifier.name))
|
||||
|
||||
conversion = CGCallbackTempRoot(declType.define())
|
||||
|
||||
if type.nullable():
|
||||
declType = CGTemplatedType("Option", declType)
|
||||
conversion = CGWrapper(conversion, pre="Some(", post=")")
|
||||
|
||||
if allowTreatNonObjectAsNull and type.treatNonObjectAsNull():
|
||||
if not isDefinitelyObject:
|
||||
haveObject = "${val}.is_object()"
|
||||
if defaultValue is not None:
|
||||
assert isinstance(defaultValue, IDLNullValue)
|
||||
haveObject = "${haveValue} && " + haveObject
|
||||
template = CGIfElseWrapper(haveObject,
|
||||
conversion,
|
||||
CGGeneric("None")).define()
|
||||
else:
|
||||
template = conversion
|
||||
else:
|
||||
template = CGIfElseWrapper("JS_ObjectIsCallable(cx, ${val}.to_object()) != 0",
|
||||
conversion,
|
||||
onFailureNotCallable(failureCode)).define()
|
||||
template = wrapObjectTemplate(
|
||||
template,
|
||||
isDefinitelyObject,
|
||||
type,
|
||||
failureCode)
|
||||
return (template, declType, needsRooting)
|
||||
|
||||
if type.isAny():
|
||||
assert not isEnforceRange and not isClamp
|
||||
|
@ -874,7 +903,8 @@ class CGArgumentConverter(CGThing):
|
|||
defaultValue=argument.defaultValue,
|
||||
treatNullAs=argument.treatNullAs,
|
||||
isEnforceRange=argument.enforceRange,
|
||||
isClamp=argument.clamp)
|
||||
isClamp=argument.clamp,
|
||||
allowTreatNonObjectAsNull=argument.allowTreatNonCallableAsNull())
|
||||
|
||||
if argument.optional and not argument.defaultValue:
|
||||
declType = CGWrapper(declType, pre="Option<", post=">")
|
||||
|
@ -913,7 +943,7 @@ def typeNeedsCx(type, retVal=False):
|
|||
return any(typeNeedsCx(t) for t in type.unroll().flatMemberTypes)
|
||||
if retVal and type.isSpiderMonkeyInterface():
|
||||
return True
|
||||
return type.isCallback() or type.isAny() or type.isObject()
|
||||
return type.isAny() or type.isObject()
|
||||
|
||||
def typeRetValNeedsRooting(type):
|
||||
if type is None:
|
||||
|
@ -958,9 +988,11 @@ def getRetvalDeclarationForType(returnType, descriptorProvider):
|
|||
result = CGWrapper(result, pre="Option<", post=">")
|
||||
return result
|
||||
if returnType.isCallback():
|
||||
# XXXbz we're going to assume that callback types are always
|
||||
# nullable for now.
|
||||
return CGGeneric("*mut JSObject")
|
||||
result = CGGeneric('%s::%s' % (returnType.unroll().module(),
|
||||
returnType.unroll().identifier.name))
|
||||
if returnType.nullable():
|
||||
result = CGWrapper(result, pre="Option<", post=">")
|
||||
return result
|
||||
if returnType.isAny():
|
||||
return CGGeneric("JSVal")
|
||||
if returnType.isObject() or returnType.isSpiderMonkeyInterface():
|
||||
|
@ -1347,12 +1379,8 @@ class CGIfWrapper(CGWrapper):
|
|||
post="\n}")
|
||||
|
||||
class CGTemplatedType(CGWrapper):
|
||||
def __init__(self, templateName, child, isConst=False, isReference=False):
|
||||
const = "const " if isConst else ""
|
||||
pre = "%s%s<" % (const, templateName)
|
||||
ref = "&" if isReference else ""
|
||||
post = ">%s" % ref
|
||||
CGWrapper.__init__(self, child, pre=pre, post=post)
|
||||
def __init__(self, templateName, child):
|
||||
CGWrapper.__init__(self, child, pre=templateName + "<", post=">")
|
||||
|
||||
class CGNamespace(CGWrapper):
|
||||
def __init__(self, namespace, child, public=False):
|
||||
|
@ -1573,23 +1601,32 @@ class CGGeneric(CGThing):
|
|||
def define(self):
|
||||
return self.text
|
||||
|
||||
def getTypes(descriptor):
|
||||
"""
|
||||
Get all argument and return types for all members of the descriptor
|
||||
"""
|
||||
members = [m for m in descriptor.interface.members]
|
||||
if descriptor.interface.ctor():
|
||||
members.append(descriptor.interface.ctor())
|
||||
signatures = [s for m in members if m.isMethod() for s in m.signatures()]
|
||||
types = []
|
||||
for s in signatures:
|
||||
assert len(s) == 2
|
||||
(returnType, arguments) = s
|
||||
types.append(returnType)
|
||||
types.extend([a.type for a in arguments])
|
||||
class CGCallbackTempRoot(CGGeneric):
|
||||
def __init__(self, name):
|
||||
val = "%s::new(tempRoot)" % name
|
||||
define = """{
|
||||
let tempRoot = ${val}.to_object();
|
||||
%s
|
||||
}""" % val
|
||||
CGGeneric.__init__(self, define)
|
||||
|
||||
types.extend(a.type for a in members if a.isAttr())
|
||||
return types
|
||||
|
||||
def getAllTypes(descriptors, dictionaries, callbacks):
|
||||
"""
|
||||
Generate all the types we're dealing with. For each type, a tuple
|
||||
containing type, descriptor, dictionary is yielded. The
|
||||
descriptor and dictionary can be None if the type does not come
|
||||
from a descriptor or dictionary; they will never both be non-None.
|
||||
"""
|
||||
for d in descriptors:
|
||||
for t in getTypesFromDescriptor(d):
|
||||
yield (t, d, None)
|
||||
for dictionary in dictionaries:
|
||||
for t in getTypesFromDictionary(dictionary):
|
||||
yield (t, None, dictionary)
|
||||
for callback in callbacks:
|
||||
for t in getTypesFromCallback(callback):
|
||||
yield (t, None, None)
|
||||
|
||||
def SortedTuples(l):
|
||||
"""
|
||||
|
@ -1606,24 +1643,23 @@ def SortedDictValues(d):
|
|||
# We're only interested in the values.
|
||||
return (i[1] for i in d)
|
||||
|
||||
def UnionTypes(descriptors):
|
||||
def UnionTypes(descriptors, dictionaries, callbacks, config):
|
||||
"""
|
||||
Returns a tuple containing a set of header filenames to include, a set of
|
||||
tuples containing a type declaration and a boolean if the type is a struct
|
||||
for member types of the unions and a CGList containing CGUnionStructs for
|
||||
every union.
|
||||
Returns a CGList containing CGUnionStructs for every union.
|
||||
"""
|
||||
|
||||
# Now find all the things we'll need as arguments and return values because
|
||||
# we need to wrap or unwrap them.
|
||||
unionStructs = dict()
|
||||
for d in descriptors:
|
||||
for t in getTypes(d):
|
||||
t = t.unroll()
|
||||
if t.isUnion():
|
||||
name = str(t)
|
||||
if not name in unionStructs:
|
||||
unionStructs[name] = CGList([CGUnionStruct(t, d), CGUnionConversionStruct(t, d)])
|
||||
for (t, descriptor, dictionary) in getAllTypes(descriptors, dictionaries, callbacks):
|
||||
assert not descriptor or not dictionary
|
||||
t = t.unroll()
|
||||
if not t.isUnion():
|
||||
continue
|
||||
name = str(t)
|
||||
if not name in unionStructs:
|
||||
provider = descriptor or config.getDescriptorProvider()
|
||||
unionStructs[name] = CGList([CGUnionStruct(t, provider), CGUnionConversionStruct(t, provider)])
|
||||
|
||||
return CGList(SortedDictValues(unionStructs), "\n\n")
|
||||
|
||||
|
@ -2309,15 +2345,19 @@ class FakeArgument():
|
|||
A class that quacks like an IDLArgument. This is used to make
|
||||
setters look like method calls or for special operations.
|
||||
"""
|
||||
def __init__(self, type, interfaceMember):
|
||||
def __init__(self, type, interfaceMember, allowTreatNonObjectAsNull=False):
|
||||
self.type = type
|
||||
self.optional = False
|
||||
self.variadic = False
|
||||
self.defaultValue = None
|
||||
self._allowTreatNonObjectAsNull = allowTreatNonObjectAsNull
|
||||
self.treatNullAs = interfaceMember.treatNullAs
|
||||
self.enforceRange = False
|
||||
self.clamp = False
|
||||
|
||||
def allowTreatNonCallableAsNull(self):
|
||||
return self._allowTreatNonObjectAsNull
|
||||
|
||||
class CGSetterCall(CGPerSignatureCall):
|
||||
"""
|
||||
A class to generate a native object setter call for a particular IDL
|
||||
|
@ -2325,7 +2365,7 @@ class CGSetterCall(CGPerSignatureCall):
|
|||
"""
|
||||
def __init__(self, argsPre, argType, nativeMethodName, descriptor, attr):
|
||||
CGPerSignatureCall.__init__(self, None, argsPre,
|
||||
[FakeArgument(argType, attr)],
|
||||
[FakeArgument(argType, attr, allowTreatNonObjectAsNull=True)],
|
||||
nativeMethodName, False, descriptor, attr,
|
||||
setter=True)
|
||||
def wrap_return_value(self):
|
||||
|
@ -2710,9 +2750,22 @@ class CGUnionStruct(CGThing):
|
|||
enumValues = [
|
||||
" e%s(%s)," % (v["name"], v["typeName"]) for v in templateVars
|
||||
]
|
||||
return ("pub enum %s {\n"
|
||||
"%s\n"
|
||||
"}\n") % (self.type, "\n".join(enumValues))
|
||||
enumConversions = [
|
||||
" e%s(ref inner) => inner.to_jsval(cx)," % v["name"] for v in templateVars
|
||||
]
|
||||
return ("""pub enum %s {
|
||||
%s
|
||||
}
|
||||
|
||||
impl ToJSValConvertible for %s {
|
||||
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
|
||||
match *self {
|
||||
%s
|
||||
}
|
||||
}
|
||||
}
|
||||
""") % (self.type, "\n".join(enumValues),
|
||||
self.type, "\n".join(enumConversions))
|
||||
|
||||
|
||||
class CGUnionConversionStruct(CGThing):
|
||||
|
@ -4170,14 +4223,17 @@ class CGBindingRoot(CGThing):
|
|||
for d in dictionaries])
|
||||
|
||||
# Do codegen for all the callbacks.
|
||||
cgthings.extend(CGCallbackFunction(c, config.getDescriptorProvider())
|
||||
cgthings.extend(CGList([CGCallbackFunction(c, config.getDescriptorProvider()),
|
||||
CGCallbackFunctionImpl(c)], "\n")
|
||||
for c in mainCallbacks)
|
||||
|
||||
# Do codegen for all the descriptors
|
||||
cgthings.extend([CGDescriptor(x) for x in descriptors])
|
||||
|
||||
# Do codegen for all the callback interfaces.
|
||||
cgthings.extend([CGCallbackInterface(x) for x in callbackDescriptors])
|
||||
cgthings.extend(CGList([CGCallbackInterface(x),
|
||||
CGCallbackFunctionImpl(x)], "\n")
|
||||
for x in callbackDescriptors)
|
||||
|
||||
# And make sure we have the right number of newlines at the end
|
||||
curr = CGWrapper(CGList(cgthings, "\n\n"), post="\n\n")
|
||||
|
@ -4236,7 +4292,7 @@ class CGBindingRoot(CGThing):
|
|||
'dom::bindings::utils::VoidVal',
|
||||
'dom::bindings::utils::get_dictionary_property',
|
||||
'dom::bindings::trace::JSTraceable',
|
||||
'dom::bindings::callback::{CallbackContainer,CallbackInterface}',
|
||||
'dom::bindings::callback::{CallbackContainer,CallbackInterface,CallbackFunction}',
|
||||
'dom::bindings::callback::{CallSetup,ExceptionHandling}',
|
||||
'dom::bindings::callback::{WrapCallThisObject}',
|
||||
'dom::bindings::conversions::{FromJSValConvertible, ToJSValConvertible}',
|
||||
|
@ -4322,8 +4378,9 @@ class CGNativeMember(ClassMethod):
|
|||
elif type.isPrimitive() and type.tag() in builtinNames:
|
||||
result = CGGeneric(builtinNames[type.tag()])
|
||||
if type.nullable():
|
||||
result = CGTemplatedType("Nullable", result)
|
||||
typeDecl, template = result.define(), "return ${declName};"
|
||||
raise TypeError("Nullable primitives are not supported here.")
|
||||
|
||||
typeDecl, template = result.define(), "return Ok(${declName});"
|
||||
elif type.isDOMString():
|
||||
if isMember:
|
||||
# No need for a third element in the isMember case
|
||||
|
@ -4363,9 +4420,9 @@ class CGNativeMember(ClassMethod):
|
|||
("already_AddRefed<%s>" % type.unroll().identifier.name,
|
||||
"return ${declName}.forget();")
|
||||
elif type.isAny():
|
||||
typeDecl, template = "JS::Value", "return ${declName};"
|
||||
typeDecl, template = "JSVal", "return Ok(${declName});"
|
||||
elif type.isObject():
|
||||
typeDecl, template = "*JSObject", "return ${declName};"
|
||||
typeDecl, template = "JSObject*", "return ${declName};"
|
||||
elif type.isSpiderMonkeyInterface():
|
||||
if type.nullable():
|
||||
returnCode = "return ${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();"
|
||||
|
@ -4462,7 +4519,7 @@ class CGNativeMember(ClassMethod):
|
|||
if type.isUnion():
|
||||
if type.nullable():
|
||||
type = type.inner
|
||||
return str(type), True, True
|
||||
return str(type), False, True
|
||||
|
||||
if type.isGeckoInterface() and not type.isCallbackInterface():
|
||||
iface = type.unroll().inner
|
||||
|
@ -4492,10 +4549,7 @@ class CGNativeMember(ClassMethod):
|
|||
return type.name, True, True
|
||||
|
||||
if type.isDOMString():
|
||||
if isMember:
|
||||
declType = "nsString"
|
||||
else:
|
||||
declType = "nsAString"
|
||||
declType = "DOMString"
|
||||
return declType, True, False
|
||||
|
||||
if type.isByteString():
|
||||
|
@ -4528,7 +4582,7 @@ class CGNativeMember(ClassMethod):
|
|||
if isMember:
|
||||
declType = "JS::Value"
|
||||
else:
|
||||
declType = "JS::Handle<JS::Value>"
|
||||
declType = "JSVal"
|
||||
return declType, False, False
|
||||
|
||||
if type.isObject():
|
||||
|
@ -4570,7 +4624,7 @@ class CGNativeMember(ClassMethod):
|
|||
# Note: All variadic args claim to be optional, but we can just use
|
||||
# empty arrays to represent them not being present.
|
||||
decl = CGTemplatedType("Option", decl)
|
||||
ref = True
|
||||
ref = False
|
||||
return (decl, ref)
|
||||
|
||||
def getArg(self, arg):
|
||||
|
@ -4581,7 +4635,7 @@ class CGNativeMember(ClassMethod):
|
|||
arg.optional and not arg.defaultValue,
|
||||
"Variadic" if arg.variadic else False)
|
||||
if ref:
|
||||
decl = CGWrapper(decl, pre="const ", post="&")
|
||||
decl = CGWrapper(decl, pre="&")
|
||||
|
||||
return Argument(decl.define(), arg.identifier.name)
|
||||
|
||||
|
@ -4649,39 +4703,37 @@ class CGCallback(CGClass):
|
|||
|
||||
# And now insert our template argument.
|
||||
argsWithoutThis = list(args)
|
||||
args.insert(0, Argument("Box<T>", "thisObj"))
|
||||
args.insert(0, Argument("&JSRef<T>", "thisObj"))
|
||||
|
||||
# And the self argument
|
||||
method.args.insert(0, Argument(None, "&self"))
|
||||
args.insert(0, Argument(None, "&self"))
|
||||
argsWithoutThis.insert(0, Argument(None, "&self"))
|
||||
|
||||
setupCall = ("let s = CallSetup::new(cx_for_dom_object(${cxProvider}), aExceptionHandling);\n"
|
||||
setupCall = ("let s = CallSetup::new(self, aExceptionHandling);\n"
|
||||
"if s.GetContext().is_null() {\n"
|
||||
" return Err(FailureUnknown);\n"
|
||||
"}\n")
|
||||
|
||||
bodyWithThis = string.Template(
|
||||
setupCall+
|
||||
"let thisObjJS = WrapCallThisObject(s.GetContext(), ptr::mut_null() /*XXXjdm proper scope*/, thisObj);\n"
|
||||
"let thisObjJS = WrapCallThisObject(s.GetContext(), thisObj);\n"
|
||||
"if thisObjJS.is_null() {\n"
|
||||
" return Err(FailureUnknown);\n"
|
||||
"}\n"
|
||||
"return ${methodName}(${callArgs});").substitute({
|
||||
"callArgs" : ", ".join(argnamesWithThis),
|
||||
"methodName": 'self.' + method.name,
|
||||
"cxProvider": 'thisObj'
|
||||
})
|
||||
bodyWithoutThis = string.Template(
|
||||
setupCall +
|
||||
"return ${methodName}(${callArgs});").substitute({
|
||||
"callArgs" : ", ".join(argnamesWithoutThis),
|
||||
"methodName": 'self.' + method.name,
|
||||
"cxProvider": args[2].name #XXXjdm There's no guarantee that this is a DOM object
|
||||
})
|
||||
return [ClassMethod(method.name+'_', method.returnType, args,
|
||||
bodyInHeader=True,
|
||||
templateArgs=["T: 'static+CallbackContainer+Reflectable"],
|
||||
templateArgs=["T: Reflectable"],
|
||||
body=bodyWithThis,
|
||||
visibility='pub'),
|
||||
ClassMethod(method.name+'__', method.returnType, argsWithoutThis,
|
||||
|
@ -4707,15 +4759,27 @@ class CGCallbackFunction(CGCallback):
|
|||
methods=[CallCallback(callback, descriptorProvider)])
|
||||
|
||||
def getConstructors(self):
|
||||
return CGCallback.getConstructors(self) + [
|
||||
ClassConstructor(
|
||||
[Argument("CallbackFunction*", "aOther")],
|
||||
bodyInHeader=True,
|
||||
visibility="pub",
|
||||
explicit=True,
|
||||
baseConstructors=[
|
||||
"CallbackFunction(aOther)"
|
||||
])]
|
||||
return CGCallback.getConstructors(self)
|
||||
|
||||
class CGCallbackFunctionImpl(CGGeneric):
|
||||
def __init__(self, callback):
|
||||
impl = string.Template("""impl CallbackContainer for ${type} {
|
||||
fn new(callback: *mut JSObject) -> ${type} {
|
||||
${type}::new(callback)
|
||||
}
|
||||
|
||||
fn callback(&self) -> *mut JSObject {
|
||||
self.parent.callback()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToJSValConvertible for ${type} {
|
||||
fn to_jsval(&self, cx: *mut JSContext) -> JSVal {
|
||||
self.callback().to_jsval(cx)
|
||||
}
|
||||
}
|
||||
""").substitute({"type": callback.name})
|
||||
CGGeneric.__init__(self, impl)
|
||||
|
||||
class CGCallbackInterface(CGCallback):
|
||||
def __init__(self, descriptor):
|
||||
|
@ -4817,7 +4881,7 @@ class CallbackMember(CGNativeMember):
|
|||
return CGList([
|
||||
CGGeneric(pre),
|
||||
CGWrapper(CGIndenter(CGGeneric(body)),
|
||||
pre="with_compartment(cx, self.parent.callback, || {\n",
|
||||
pre="with_compartment(cx, self.parent.callback(), || {\n",
|
||||
post="})")
|
||||
], "\n").define()
|
||||
|
||||
|
@ -4876,19 +4940,10 @@ class CallbackMember(CGNativeMember):
|
|||
else:
|
||||
jsvalIndex = "%d" % i
|
||||
if arg.optional and not arg.defaultValue:
|
||||
argval += ".Value()"
|
||||
if arg.type.isDOMString():
|
||||
# XPConnect string-to-JS conversion wants to mutate the string. So
|
||||
# let's give it a string it can mutate
|
||||
# XXXbz if we try to do a sequence of strings, this will kinda fail.
|
||||
result = "mutableStr"
|
||||
prepend = "nsString mutableStr(%s);\n" % argval
|
||||
else:
|
||||
result = argval
|
||||
prepend = ""
|
||||
argval += ".clone().unwrap()"
|
||||
|
||||
conversion = prepend + wrapForType("*argv.get_mut(%s)" % jsvalIndex,
|
||||
result=result,
|
||||
conversion = wrapForType("*argv.get_mut(%s)" % jsvalIndex,
|
||||
result=argval,
|
||||
successCode="continue;" if arg.variadic else "break;")
|
||||
if arg.variadic:
|
||||
conversion = string.Template(
|
||||
|
@ -4899,12 +4954,12 @@ class CallbackMember(CGNativeMember):
|
|||
elif arg.optional and not arg.defaultValue:
|
||||
conversion = (
|
||||
CGIfWrapper(CGGeneric(conversion),
|
||||
"%s.WasPassed()" % arg.identifier.name).define() +
|
||||
"%s.is_some()" % arg.identifier.name).define() +
|
||||
" else if (argc == %d) {\n"
|
||||
" // This is our current trailing argument; reduce argc\n"
|
||||
" --argc;\n"
|
||||
" argc -= 1;\n"
|
||||
"} else {\n"
|
||||
" argv[%d] = JS::UndefinedValue();\n"
|
||||
" *argv.get_mut(%d) = UndefinedValue();\n"
|
||||
"}" % (i+1, i))
|
||||
return conversion
|
||||
|
||||
|
@ -4946,7 +5001,7 @@ class CallbackMember(CGNativeMember):
|
|||
})
|
||||
|
||||
def getArgcDecl(self):
|
||||
return CGGeneric("let argc = %su32;" % self.argCountStr);
|
||||
return CGGeneric("let mut argc = %su32;" % self.argCountStr);
|
||||
|
||||
@staticmethod
|
||||
def ensureASCIIName(idlObject):
|
||||
|
@ -4999,7 +5054,7 @@ class CallCallback(CallbackMethod):
|
|||
return "aThisObj"
|
||||
|
||||
def getCallableDecl(self):
|
||||
return "JS::Rooted<JS::Value> callable(cx, JS::ObjectValue(*mCallback));\n"
|
||||
return "let callable = ObjectValue(unsafe {&*self.parent.callback()});\n";
|
||||
|
||||
class CallbackOperationBase(CallbackMethod):
|
||||
"""
|
||||
|
@ -5012,11 +5067,11 @@ class CallbackOperationBase(CallbackMethod):
|
|||
|
||||
def getThisObj(self):
|
||||
if not self.singleOperation:
|
||||
return "self.parent.callback"
|
||||
return "self.parent.callback()"
|
||||
# This relies on getCallableDecl declaring a boolean
|
||||
# isCallable in the case when we're a single-operation
|
||||
# interface.
|
||||
return "if isCallable { aThisObj } else { self.parent.callback }"
|
||||
return "if isCallable { aThisObj } else { self.parent.callback() }"
|
||||
|
||||
def getCallableDecl(self):
|
||||
replacements = {
|
||||
|
@ -5030,11 +5085,11 @@ class CallbackOperationBase(CallbackMethod):
|
|||
if not self.singleOperation:
|
||||
return 'JS::Rooted<JS::Value> callable(cx);\n' + getCallableFromProp
|
||||
return (
|
||||
'let isCallable = unsafe { JS_ObjectIsCallable(cx, self.parent.callback) != 0 };\n'
|
||||
'let isCallable = unsafe { JS_ObjectIsCallable(cx, self.parent.callback()) != 0 };\n'
|
||||
'let callable =\n' +
|
||||
CGIndenter(
|
||||
CGIfElseWrapper('isCallable',
|
||||
CGGeneric('unsafe { ObjectValue(&*self.parent.callback) }'),
|
||||
CGGeneric('unsafe { ObjectValue(&*self.parent.callback()) }'),
|
||||
CGGeneric(getCallableFromProp))).define() + ';\n')
|
||||
|
||||
class CallbackOperation(CallbackOperationBase):
|
||||
|
@ -5242,12 +5297,16 @@ class GlobalGenRoots():
|
|||
@staticmethod
|
||||
def UnionTypes(config):
|
||||
|
||||
curr = UnionTypes(config.getDescriptors())
|
||||
curr = UnionTypes(config.getDescriptors(),
|
||||
config.getDictionaries(),
|
||||
config.getCallbacks(),
|
||||
config)
|
||||
|
||||
curr = CGImports(curr, [], [
|
||||
'dom::bindings::utils::unwrap_jsmanaged',
|
||||
'dom::bindings::codegen::PrototypeList',
|
||||
'dom::bindings::conversions::FromJSValConvertible',
|
||||
'dom::bindings::conversions::ToJSValConvertible',
|
||||
'dom::bindings::conversions::Default',
|
||||
'dom::bindings::error::throw_not_in_union',
|
||||
'dom::bindings::js::JS',
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue