mirror of
https://github.com/servo/servo.git
synced 2025-07-25 08:10:21 +01:00
Fix binding generation for Callback Functions and Callback Interfaces
This commit is contained in:
parent
443b1b98e1
commit
05bd182538
3 changed files with 98 additions and 331 deletions
|
@ -601,11 +601,13 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||||
|
|
||||||
if descriptor.interface.isCallback():
|
if descriptor.interface.isCallback():
|
||||||
name = descriptor.nativeType
|
name = descriptor.nativeType
|
||||||
declType = CGGeneric("Option<%s>" % name);
|
declType = CGGeneric(name)
|
||||||
conversion = ("Some(%s::new((${val}).to_object()))" % name)
|
template = "%s::new((${val}).to_object())" % name
|
||||||
|
if type.nullable():
|
||||||
template = wrapObjectTemplate(conversion, isDefinitelyObject, type,
|
declType = CGWrapper(declType, pre="Option<", post=">")
|
||||||
|
template = wrapObjectTemplate("Some(%s)" % template, isDefinitelyObject, type,
|
||||||
failureCode)
|
failureCode)
|
||||||
|
|
||||||
return handleOptional(template, declType, handleDefaultNull("None"))
|
return handleOptional(template, declType, handleDefaultNull("None"))
|
||||||
|
|
||||||
if isMember:
|
if isMember:
|
||||||
|
@ -983,15 +985,14 @@ class CGArgumentConverter(CGThing):
|
||||||
needsRooting)
|
needsRooting)
|
||||||
|
|
||||||
seqType = CGTemplatedType("Vec", declType)
|
seqType = CGTemplatedType("Vec", declType)
|
||||||
|
|
||||||
variadicConversion = string.Template(
|
variadicConversion = string.Template(
|
||||||
"{\n"
|
"let mut vector: ${seqType} = Vec::with_capacity((${argc} - ${index}) as uint);\n"
|
||||||
" let mut vector: ${seqType} = Vec::with_capacity((${argc} - ${index}) as uint);\n"
|
"for variadicArg in range(${index}, ${argc}) {\n"
|
||||||
" for variadicArg in range(${index}, ${argc}) {\n"
|
|
||||||
"${inner}\n"
|
"${inner}\n"
|
||||||
" vector.push(slot);\n"
|
" vector.push(slot);\n"
|
||||||
" }\n"
|
"}\n"
|
||||||
" vector\n"
|
"vector"
|
||||||
"}"
|
|
||||||
).substitute({
|
).substitute({
|
||||||
"index": index,
|
"index": index,
|
||||||
"argc": argc,
|
"argc": argc,
|
||||||
|
@ -999,6 +1000,10 @@ class CGArgumentConverter(CGThing):
|
||||||
"inner": CGIndenter(innerConverter, 4).define(),
|
"inner": CGIndenter(innerConverter, 4).define(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
variadicConversion = CGIfElseWrapper(condition,
|
||||||
|
CGGeneric(variadicConversion),
|
||||||
|
CGGeneric("Vec::new()")).define()
|
||||||
|
|
||||||
self.converter = instantiateJSToNativeConversionTemplate(
|
self.converter = instantiateJSToNativeConversionTemplate(
|
||||||
variadicConversion, replacementVariables, seqType, "arg%d" % index,
|
variadicConversion, replacementVariables, seqType, "arg%d" % index,
|
||||||
False)
|
False)
|
||||||
|
@ -3993,44 +3998,14 @@ class CGInterfaceTrait(CGThing):
|
||||||
def __init__(self, descriptor):
|
def __init__(self, descriptor):
|
||||||
CGThing.__init__(self)
|
CGThing.__init__(self)
|
||||||
|
|
||||||
def argument_type(ty, optional=False, defaultValue=None, variadic=False):
|
|
||||||
_, _, declType, _ = getJSToNativeConversionTemplate(
|
|
||||||
ty, descriptor, isArgument=True)
|
|
||||||
|
|
||||||
if variadic:
|
|
||||||
declType = CGWrapper(declType, pre="Vec<", post=">")
|
|
||||||
elif optional and not defaultValue:
|
|
||||||
declType = CGWrapper(declType, pre="Option<", post=">")
|
|
||||||
|
|
||||||
if ty.isDictionary():
|
|
||||||
declType = CGWrapper(declType, pre="&")
|
|
||||||
|
|
||||||
return declType.define()
|
|
||||||
|
|
||||||
def attribute_arguments(needCx, argument=None):
|
def attribute_arguments(needCx, argument=None):
|
||||||
if needCx:
|
if needCx:
|
||||||
yield "cx", "*mut JSContext"
|
yield "cx", "*mut JSContext"
|
||||||
|
|
||||||
if argument:
|
if argument:
|
||||||
yield "value", argument_type(argument)
|
yield "value", argument_type(descriptor, argument)
|
||||||
|
|
||||||
def method_arguments(returnType, arguments, trailing=None):
|
|
||||||
if needCx(returnType, arguments, True):
|
|
||||||
yield "cx", "*mut JSContext"
|
|
||||||
|
|
||||||
for argument in arguments:
|
|
||||||
ty = argument_type(argument.type, argument.optional,
|
|
||||||
argument.defaultValue, argument.variadic)
|
|
||||||
yield CGDictionary.makeMemberName(argument.identifier.name), ty
|
|
||||||
|
|
||||||
if trailing:
|
|
||||||
yield trailing
|
|
||||||
|
|
||||||
def return_type(rettype, infallible):
|
|
||||||
result = getRetvalDeclarationForType(rettype, descriptor)
|
|
||||||
if not infallible:
|
|
||||||
result = CGWrapper(result, pre="Fallible<", post=">")
|
|
||||||
return result.define()
|
|
||||||
|
|
||||||
def members():
|
def members():
|
||||||
for m in descriptor.interface.members:
|
for m in descriptor.interface.members:
|
||||||
|
@ -4039,14 +4014,14 @@ class CGInterfaceTrait(CGThing):
|
||||||
name = CGSpecializedMethod.makeNativeName(descriptor, m)
|
name = CGSpecializedMethod.makeNativeName(descriptor, m)
|
||||||
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
|
infallible = 'infallible' in descriptor.getExtendedAttributes(m)
|
||||||
for idx, (rettype, arguments) in enumerate(m.signatures()):
|
for idx, (rettype, arguments) in enumerate(m.signatures()):
|
||||||
arguments = method_arguments(rettype, arguments)
|
arguments = method_arguments(descriptor, rettype, arguments)
|
||||||
rettype = return_type(rettype, infallible)
|
rettype = return_type(descriptor, rettype, infallible)
|
||||||
yield name + ('_' * idx), arguments, rettype
|
yield name + ('_' * idx), arguments, rettype
|
||||||
elif m.isAttr() and not m.isStatic():
|
elif m.isAttr() and not m.isStatic():
|
||||||
name = CGSpecializedGetter.makeNativeName(descriptor, m)
|
name = CGSpecializedGetter.makeNativeName(descriptor, m)
|
||||||
infallible = 'infallible' in descriptor.getExtendedAttributes(m, getter=True)
|
infallible = 'infallible' in descriptor.getExtendedAttributes(m, getter=True)
|
||||||
needCx = typeNeedsCx(m.type)
|
needCx = typeNeedsCx(m.type)
|
||||||
yield name, attribute_arguments(needCx), return_type(m.type, infallible)
|
yield name, attribute_arguments(needCx), return_type(descriptor, m.type, infallible)
|
||||||
|
|
||||||
if not m.readonly:
|
if not m.readonly:
|
||||||
name = CGSpecializedSetter.makeNativeName(descriptor, m)
|
name = CGSpecializedSetter.makeNativeName(descriptor, m)
|
||||||
|
@ -4067,10 +4042,10 @@ class CGInterfaceTrait(CGThing):
|
||||||
|
|
||||||
infallible = 'infallible' in descriptor.getExtendedAttributes(operation)
|
infallible = 'infallible' in descriptor.getExtendedAttributes(operation)
|
||||||
if operation.isGetter():
|
if operation.isGetter():
|
||||||
arguments = method_arguments(rettype, arguments, ("found", "&mut bool"))
|
arguments = method_arguments(descriptor, rettype, arguments, trailing=("found", "&mut bool"))
|
||||||
else:
|
else:
|
||||||
arguments = method_arguments(rettype, arguments)
|
arguments = method_arguments(descriptor, rettype, arguments)
|
||||||
rettype = return_type(rettype, infallible)
|
rettype = return_type(descriptor, rettype, infallible)
|
||||||
yield name, arguments, rettype
|
yield name, arguments, rettype
|
||||||
|
|
||||||
def fmt(arguments):
|
def fmt(arguments):
|
||||||
|
@ -4573,6 +4548,38 @@ class CGBindingRoot(CGThing):
|
||||||
def define(self):
|
def define(self):
|
||||||
return stripTrailingWhitespace(self.root.define())
|
return stripTrailingWhitespace(self.root.define())
|
||||||
|
|
||||||
|
def argument_type(descriptorProvdider, ty, optional=False, defaultValue=None, variadic=False):
|
||||||
|
_, _, declType, _ = getJSToNativeConversionTemplate(
|
||||||
|
ty, descriptorProvdider, isArgument=True)
|
||||||
|
|
||||||
|
if variadic:
|
||||||
|
declType = CGWrapper(declType, pre="Vec<", post=">")
|
||||||
|
elif optional and not defaultValue:
|
||||||
|
declType = CGWrapper(declType, pre="Option<", post=">")
|
||||||
|
|
||||||
|
if ty.isDictionary():
|
||||||
|
declType = CGWrapper(declType, pre="&")
|
||||||
|
|
||||||
|
return declType.define()
|
||||||
|
|
||||||
|
def method_arguments(descriptorProvider, returnType, arguments, passJSBits=True, trailing=None):
|
||||||
|
if needCx(returnType, arguments, passJSBits):
|
||||||
|
yield "cx", "*mut JSContext"
|
||||||
|
|
||||||
|
for argument in arguments:
|
||||||
|
ty = argument_type(descriptorProvider, argument.type, argument.optional,
|
||||||
|
argument.defaultValue, argument.variadic)
|
||||||
|
yield CGDictionary.makeMemberName(argument.identifier.name), ty
|
||||||
|
|
||||||
|
if trailing:
|
||||||
|
yield trailing
|
||||||
|
|
||||||
|
def return_type(descriptorProvider, rettype, infallible):
|
||||||
|
result = getRetvalDeclarationForType(rettype, descriptorProvider)
|
||||||
|
if not infallible:
|
||||||
|
result = CGWrapper(result, pre="Fallible<", post=">")
|
||||||
|
return result.define()
|
||||||
|
|
||||||
class CGNativeMember(ClassMethod):
|
class CGNativeMember(ClassMethod):
|
||||||
def __init__(self, descriptorProvider, member, name, signature, extendedAttrs,
|
def __init__(self, descriptorProvider, member, name, signature, extendedAttrs,
|
||||||
breakAfter=True, passJSBitsAsNeeded=True, visibility="public",
|
breakAfter=True, passJSBitsAsNeeded=True, visibility="public",
|
||||||
|
@ -4592,7 +4599,7 @@ class CGNativeMember(ClassMethod):
|
||||||
self.variadicIsSequence = variadicIsSequence
|
self.variadicIsSequence = variadicIsSequence
|
||||||
breakAfterSelf = "\n" if breakAfter else ""
|
breakAfterSelf = "\n" if breakAfter else ""
|
||||||
ClassMethod.__init__(self, name,
|
ClassMethod.__init__(self, name,
|
||||||
self.getReturnType(signature[0], False),
|
self.getReturnType(signature[0]),
|
||||||
self.getArgs(signature[0], signature[1]),
|
self.getArgs(signature[0], signature[1]),
|
||||||
static=member.isStatic(),
|
static=member.isStatic(),
|
||||||
# Mark our getters, which are attrs that
|
# Mark our getters, which are attrs that
|
||||||
|
@ -4603,274 +4610,16 @@ class CGNativeMember(ClassMethod):
|
||||||
breakAfterSelf=breakAfterSelf,
|
breakAfterSelf=breakAfterSelf,
|
||||||
visibility=visibility)
|
visibility=visibility)
|
||||||
|
|
||||||
def getReturnType(self, type, isMember):
|
def getReturnType(self, type):
|
||||||
return self.getRetvalInfo(type, isMember)[0]
|
infallible = 'infallible' in self.extendedAttrs
|
||||||
|
typeDecl = return_type(self.descriptorProvider, type, infallible)
|
||||||
def getRetvalInfo(self, type, isMember):
|
return typeDecl
|
||||||
"""
|
|
||||||
Returns a tuple:
|
|
||||||
|
|
||||||
The first element is the type declaration for the retval
|
|
||||||
|
|
||||||
The second element is a template for actually returning a value stored in
|
|
||||||
"${declName}". This means actually returning it if
|
|
||||||
we're not outparam, else assigning to the "retval" outparam. If
|
|
||||||
isMember is true, this can be None, since in that case the caller will
|
|
||||||
never examine this value.
|
|
||||||
"""
|
|
||||||
if type.isVoid():
|
|
||||||
typeDecl, template = "", ""
|
|
||||||
elif type.isPrimitive() and type.tag() in builtinNames:
|
|
||||||
result = CGGeneric(builtinNames[type.tag()])
|
|
||||||
if type.nullable():
|
|
||||||
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
|
|
||||||
typeDecl, template = "nsString", None
|
|
||||||
# Outparam
|
|
||||||
else:
|
|
||||||
typeDecl, template = "void", "retval = ${declName};"
|
|
||||||
elif type.isByteString():
|
|
||||||
if isMember:
|
|
||||||
# No need for a third element in the isMember case
|
|
||||||
typeDecl, template = "nsCString", None
|
|
||||||
# Outparam
|
|
||||||
typeDecl, template = "void", "retval = ${declName};"
|
|
||||||
elif type.isEnum():
|
|
||||||
enumName = type.unroll().inner.identifier.name
|
|
||||||
if type.nullable():
|
|
||||||
enumName = CGTemplatedType("Nullable",
|
|
||||||
CGGeneric(enumName)).define()
|
|
||||||
typeDecl, template = enumName, "return ${declName};"
|
|
||||||
elif type.isGeckoInterface():
|
|
||||||
iface = type.unroll().inner;
|
|
||||||
nativeType = self.descriptorProvider.getDescriptor(
|
|
||||||
iface.identifier.name).nativeType
|
|
||||||
# Now trim off unnecessary namespaces
|
|
||||||
nativeType = nativeType.split("::")
|
|
||||||
if nativeType[0] == "mozilla":
|
|
||||||
nativeType.pop(0)
|
|
||||||
if nativeType[0] == "dom":
|
|
||||||
nativeType.pop(0)
|
|
||||||
result = CGWrapper(CGGeneric("::".join(nativeType)), post="*")
|
|
||||||
# Since we always force an owning type for callback return values,
|
|
||||||
# our ${declName} is an OwningNonNull or nsRefPtr. So we can just
|
|
||||||
# .forget() to get our already_AddRefed.
|
|
||||||
typeDecl, template = result.define(), "return ${declName}.forget();"
|
|
||||||
elif type.isCallback():
|
|
||||||
typeDecl, template = \
|
|
||||||
("already_AddRefed<%s>" % type.unroll().identifier.name,
|
|
||||||
"return ${declName}.forget();")
|
|
||||||
elif type.isAny():
|
|
||||||
typeDecl, template = "JSVal", "return Ok(${declName});"
|
|
||||||
elif type.isObject():
|
|
||||||
typeDecl, template = "JSObject*", "return ${declName};"
|
|
||||||
elif type.isSpiderMonkeyInterface():
|
|
||||||
if type.nullable():
|
|
||||||
returnCode = "return ${declName}.IsNull() ? nullptr : ${declName}.Value().Obj();"
|
|
||||||
else:
|
|
||||||
returnCode = "return ${declName}.Obj();"
|
|
||||||
typeDecl, template = "JSObject*", returnCode
|
|
||||||
elif type.isSequence():
|
|
||||||
# If we want to handle sequence-of-sequences return values, we're
|
|
||||||
# going to need to fix example codegen to not produce nsTArray<void>
|
|
||||||
# for the relevant argument...
|
|
||||||
assert not isMember
|
|
||||||
# Outparam.
|
|
||||||
if type.nullable():
|
|
||||||
returnCode = ("if (${declName}.IsNull()) {\n"
|
|
||||||
" retval.SetNull();\n"
|
|
||||||
"} else {\n"
|
|
||||||
" retval.SetValue().SwapElements(${declName}.Value());\n"
|
|
||||||
"}")
|
|
||||||
else:
|
|
||||||
returnCode = "retval.SwapElements(${declName});"
|
|
||||||
typeDecl, template = "void", returnCode
|
|
||||||
elif type.isDate():
|
|
||||||
result = CGGeneric("Date")
|
|
||||||
if type.nullable():
|
|
||||||
result = CGTemplatedType("Nullable", result)
|
|
||||||
typeDecl, template = result.define(), "return ${declName};"
|
|
||||||
else:
|
|
||||||
raise TypeError("Don't know how to declare return value for %s" % type)
|
|
||||||
|
|
||||||
if not 'infallible' in self.extendedAttrs:
|
|
||||||
if typeDecl:
|
|
||||||
typeDecl = "Fallible<%s>" % typeDecl
|
|
||||||
else:
|
|
||||||
typeDecl = "ErrorResult"
|
|
||||||
if not template:
|
|
||||||
template = "return Ok(());"
|
|
||||||
return typeDecl, template
|
|
||||||
|
|
||||||
def getArgs(self, returnType, argList):
|
def getArgs(self, returnType, argList):
|
||||||
args = [self.getArg(arg) for arg in argList]
|
return [Argument(arg[1], arg[0]) for arg in method_arguments(self.descriptorProvider,
|
||||||
# Now the outparams
|
returnType,
|
||||||
if returnType.isDOMString():
|
argList,
|
||||||
args.append(Argument("nsString&", "retval"))
|
self.passJSBitsAsNeeded)]
|
||||||
if returnType.isByteString():
|
|
||||||
args.append(Argument("nsCString&", "retval"))
|
|
||||||
elif returnType.isSequence():
|
|
||||||
nullable = returnType.nullable()
|
|
||||||
if nullable:
|
|
||||||
returnType = returnType.inner
|
|
||||||
# And now the actual underlying type
|
|
||||||
elementDecl = self.getReturnType(returnType.inner, True)
|
|
||||||
type = CGTemplatedType("nsTArray", CGGeneric(elementDecl))
|
|
||||||
if nullable:
|
|
||||||
type = CGTemplatedType("Nullable", type)
|
|
||||||
args.append(Argument("%s&" % type.define(), "retval"))
|
|
||||||
# The legacycaller thisval
|
|
||||||
if self.member.isMethod() and self.member.isLegacycaller():
|
|
||||||
# If it has an identifier, we can't deal with it yet
|
|
||||||
assert self.member.isIdentifierLess()
|
|
||||||
args.insert(0, Argument("JS::Value", "aThisVal"))
|
|
||||||
# And jscontext bits.
|
|
||||||
if needCx(returnType, argList, self.passJSBitsAsNeeded):
|
|
||||||
args.insert(0, Argument("JSContext*", "cx"))
|
|
||||||
# And if we're static, a global
|
|
||||||
if self.member.isStatic():
|
|
||||||
args.insert(0, Argument("const GlobalObject&", "global"))
|
|
||||||
return args
|
|
||||||
|
|
||||||
def doGetArgType(self, type, optional, isMember):
|
|
||||||
"""
|
|
||||||
The main work of getArgType. Returns a string type decl, whether this
|
|
||||||
is a const ref, as well as whether the type should be wrapped in
|
|
||||||
Nullable as needed.
|
|
||||||
|
|
||||||
isMember can be false or one of the strings "Sequence" or "Variadic"
|
|
||||||
"""
|
|
||||||
if type.isArray():
|
|
||||||
raise TypeError("Can't handle array arguments yet")
|
|
||||||
|
|
||||||
if type.isSequence():
|
|
||||||
nullable = type.nullable()
|
|
||||||
if nullable:
|
|
||||||
type = type.inner
|
|
||||||
elementType = type.inner
|
|
||||||
argType = self.getArgType(elementType, False, "Sequence")[0]
|
|
||||||
decl = CGTemplatedType("Sequence", argType)
|
|
||||||
return decl.define(), True, True
|
|
||||||
|
|
||||||
if type.isUnion():
|
|
||||||
return union_native_type(type), False, True
|
|
||||||
|
|
||||||
if type.isGeckoInterface() and not type.isCallbackInterface():
|
|
||||||
iface = type.unroll().inner
|
|
||||||
argIsPointer = type.nullable()
|
|
||||||
forceOwningType = iface.isCallback() or isMember
|
|
||||||
if argIsPointer:
|
|
||||||
if (optional or isMember) and forceOwningType:
|
|
||||||
typeDecl = "nsRefPtr<%s>"
|
|
||||||
else:
|
|
||||||
typeDecl = "*%s"
|
|
||||||
else:
|
|
||||||
if optional or isMember:
|
|
||||||
if forceOwningType:
|
|
||||||
typeDecl = "OwningNonNull<%s>"
|
|
||||||
else:
|
|
||||||
typeDecl = "NonNull<%s>"
|
|
||||||
else:
|
|
||||||
typeDecl = "%s"
|
|
||||||
descriptor = self.descriptorProvider.getDescriptor(iface.identifier.name)
|
|
||||||
return (typeDecl % descriptor.argumentType,
|
|
||||||
False, False)
|
|
||||||
|
|
||||||
if type.isSpiderMonkeyInterface():
|
|
||||||
if self.jsObjectsArePtr:
|
|
||||||
return "JSObject*", False, False
|
|
||||||
|
|
||||||
return type.name, True, True
|
|
||||||
|
|
||||||
if type.isDOMString():
|
|
||||||
declType = "DOMString"
|
|
||||||
return declType, True, False
|
|
||||||
|
|
||||||
if type.isByteString():
|
|
||||||
declType = "nsCString"
|
|
||||||
return declType, True, False
|
|
||||||
|
|
||||||
if type.isEnum():
|
|
||||||
return type.unroll().inner.identifier.name, False, True
|
|
||||||
|
|
||||||
if type.isCallback() or type.isCallbackInterface():
|
|
||||||
forceOwningType = optional or isMember
|
|
||||||
if type.nullable():
|
|
||||||
if forceOwningType:
|
|
||||||
declType = "nsRefPtr<%s>"
|
|
||||||
else:
|
|
||||||
declType = "%s*"
|
|
||||||
else:
|
|
||||||
if forceOwningType:
|
|
||||||
declType = "OwningNonNull<%s>"
|
|
||||||
else:
|
|
||||||
declType = "%s&"
|
|
||||||
if type.isCallback():
|
|
||||||
name = type.unroll().identifier.name
|
|
||||||
else:
|
|
||||||
name = type.unroll().inner.identifier.name
|
|
||||||
return declType % name, False, False
|
|
||||||
|
|
||||||
if type.isAny():
|
|
||||||
# Don't do the rooting stuff for variadics for now
|
|
||||||
if isMember:
|
|
||||||
declType = "JS::Value"
|
|
||||||
else:
|
|
||||||
declType = "JSVal"
|
|
||||||
return declType, False, False
|
|
||||||
|
|
||||||
if type.isObject():
|
|
||||||
if isMember:
|
|
||||||
declType = "JSObject*"
|
|
||||||
else:
|
|
||||||
declType = "JS::Handle<JSObject*>"
|
|
||||||
return declType, False, False
|
|
||||||
|
|
||||||
if type.isDictionary():
|
|
||||||
typeName = CGDictionary.makeDictionaryName(type.inner)
|
|
||||||
return typeName, True, True
|
|
||||||
|
|
||||||
if type.isDate():
|
|
||||||
return "Date", False, True
|
|
||||||
|
|
||||||
assert type.isPrimitive()
|
|
||||||
|
|
||||||
return builtinNames[type.tag()], False, True
|
|
||||||
|
|
||||||
def getArgType(self, type, optional, isMember):
|
|
||||||
"""
|
|
||||||
Get the type of an argument declaration. Returns the type CGThing, and
|
|
||||||
whether this should be a const ref.
|
|
||||||
|
|
||||||
isMember can be False, "Sequence", or "Variadic"
|
|
||||||
"""
|
|
||||||
(decl, ref, handleNullable) = self.doGetArgType(type, optional,
|
|
||||||
isMember)
|
|
||||||
decl = CGGeneric(decl)
|
|
||||||
if handleNullable and type.nullable():
|
|
||||||
decl = CGTemplatedType("Nullable", decl)
|
|
||||||
if isMember == "Variadic":
|
|
||||||
arrayType = "Sequence" if self.variadicIsSequence else "nsTArray"
|
|
||||||
decl = CGTemplatedType(arrayType, decl)
|
|
||||||
elif optional:
|
|
||||||
# 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)
|
|
||||||
return decl
|
|
||||||
|
|
||||||
def getArg(self, arg):
|
|
||||||
"""
|
|
||||||
Get the full argument declaration for an argument
|
|
||||||
"""
|
|
||||||
decl = self.getArgType(arg.type,
|
|
||||||
arg.optional and not arg.defaultValue,
|
|
||||||
"Variadic" if arg.variadic else False)
|
|
||||||
|
|
||||||
return Argument(decl.define(), arg.identifier.name)
|
|
||||||
|
|
||||||
class CGCallback(CGClass):
|
class CGCallback(CGClass):
|
||||||
def __init__(self, idlObject, descriptorProvider, baseName, methods,
|
def __init__(self, idlObject, descriptorProvider, baseName, methods,
|
||||||
|
@ -5052,7 +4801,7 @@ class CallbackMember(CGNativeMember):
|
||||||
lastArg = args[self.argCount-1]
|
lastArg = args[self.argCount-1]
|
||||||
if lastArg.variadic:
|
if lastArg.variadic:
|
||||||
self.argCountStr = (
|
self.argCountStr = (
|
||||||
"(%d - 1) + %s.Length()" % (self.argCount,
|
"(%d - 1) + %s.len()" % (self.argCount,
|
||||||
lastArg.identifier.name))
|
lastArg.identifier.name))
|
||||||
else:
|
else:
|
||||||
self.argCountStr = "%d" % self.argCount
|
self.argCountStr = "%d" % self.argCount
|
||||||
|
@ -5111,7 +4860,6 @@ class CallbackMember(CGNativeMember):
|
||||||
def getResultConversion(self):
|
def getResultConversion(self):
|
||||||
replacements = {
|
replacements = {
|
||||||
"val": "rval",
|
"val": "rval",
|
||||||
"declName": "rvalDecl",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template, _, declType, needsRooting = getJSToNativeConversionTemplate(
|
template, _, declType, needsRooting = getJSToNativeConversionTemplate(
|
||||||
|
@ -5125,10 +4873,12 @@ class CallbackMember(CGNativeMember):
|
||||||
convertType = instantiateJSToNativeConversionTemplate(
|
convertType = instantiateJSToNativeConversionTemplate(
|
||||||
template, replacements, declType, "rvalDecl", needsRooting)
|
template, replacements, declType, "rvalDecl", needsRooting)
|
||||||
|
|
||||||
assignRetval = string.Template(
|
if self.retvalType is None or self.retvalType.isVoid():
|
||||||
self.getRetvalInfo(self.retvalType,
|
retval = "()"
|
||||||
False)[1]).substitute(replacements)
|
else:
|
||||||
return convertType.define() + "\n" + assignRetval + "\n"
|
retval = "rvalDecl"
|
||||||
|
|
||||||
|
return "%s\nOk(%s)\n" % (convertType.define(), retval)
|
||||||
|
|
||||||
def getArgConversions(self):
|
def getArgConversions(self):
|
||||||
# Just reget the arglist from self.originalSig, because our superclasses
|
# Just reget the arglist from self.originalSig, because our superclasses
|
||||||
|
@ -5139,12 +4889,7 @@ class CallbackMember(CGNativeMember):
|
||||||
# Do them back to front, so our argc modifications will work
|
# Do them back to front, so our argc modifications will work
|
||||||
# correctly, because we examine trailing arguments first.
|
# correctly, because we examine trailing arguments first.
|
||||||
argConversions.reverse();
|
argConversions.reverse();
|
||||||
# Wrap each one in a scope so that any locals it has don't leak out, and
|
argConversions = [CGGeneric(c) for c in argConversions]
|
||||||
# also so that we can just "break;" for our successCode.
|
|
||||||
argConversions = [CGWrapper(CGIndenter(CGGeneric(c)),
|
|
||||||
pre="loop {\n",
|
|
||||||
post="\nbreak;}\n")
|
|
||||||
for c in argConversions]
|
|
||||||
if self.argCount > 0:
|
if self.argCount > 0:
|
||||||
argConversions.insert(0, self.getArgcDecl())
|
argConversions.insert(0, self.getArgcDecl())
|
||||||
# And slap them together.
|
# And slap them together.
|
||||||
|
@ -5163,13 +4908,13 @@ class CallbackMember(CGNativeMember):
|
||||||
|
|
||||||
conversion = wrapForType("argv[%s]" % jsvalIndex,
|
conversion = wrapForType("argv[%s]" % jsvalIndex,
|
||||||
result=argval,
|
result=argval,
|
||||||
successCode="continue;" if arg.variadic else "break;")
|
successCode="")
|
||||||
if arg.variadic:
|
if arg.variadic:
|
||||||
conversion = string.Template(
|
conversion = string.Template(
|
||||||
"for (uint32_t idx = 0; idx < ${arg}.Length(); ++idx) {\n" +
|
"for idx in range(0, ${arg}.len()) {\n" +
|
||||||
CGIndenter(CGGeneric(conversion)).define() + "\n"
|
CGIndenter(CGGeneric(conversion)).define() + "\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"break;").substitute({ "arg": arg.identifier.name })
|
).substitute({ "arg": arg.identifier.name })
|
||||||
elif arg.optional and not arg.defaultValue:
|
elif arg.optional and not arg.defaultValue:
|
||||||
conversion = (
|
conversion = (
|
||||||
CGIfWrapper(CGGeneric(conversion),
|
CGIfWrapper(CGGeneric(conversion),
|
||||||
|
@ -5220,7 +4965,7 @@ class CallbackMember(CGNativeMember):
|
||||||
})
|
})
|
||||||
|
|
||||||
def getArgcDecl(self):
|
def getArgcDecl(self):
|
||||||
return CGGeneric("let mut argc = %su32;" % self.argCountStr);
|
return CGGeneric("let mut argc = %s as u32;" % self.argCountStr);
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def ensureASCIIName(idlObject):
|
def ensureASCIIName(idlObject):
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
use dom::bindings::codegen::Bindings::TestBindingBinding::TestBindingMethods;
|
use dom::bindings::codegen::Bindings::TestBindingBinding::TestBindingMethods;
|
||||||
use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnum;
|
use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnum;
|
||||||
use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnumValues::_empty;
|
use dom::bindings::codegen::Bindings::TestBindingBinding::TestEnumValues::_empty;
|
||||||
|
use dom::bindings::codegen::Bindings::EventListenerBinding::EventListener;
|
||||||
|
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use dom::bindings::codegen::UnionTypes::BlobOrString::BlobOrString;
|
use dom::bindings::codegen::UnionTypes::BlobOrString::BlobOrString;
|
||||||
use dom::bindings::codegen::UnionTypes::EventOrString::{EventOrString, eString};
|
use dom::bindings::codegen::UnionTypes::EventOrString::{EventOrString, eString};
|
||||||
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::{HTMLElementOrLong, eLong};
|
use dom::bindings::codegen::UnionTypes::HTMLElementOrLong::{HTMLElementOrLong, eLong};
|
||||||
|
@ -164,6 +166,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
|
||||||
fn PassUnion2(self, _: EventOrString) {}
|
fn PassUnion2(self, _: EventOrString) {}
|
||||||
fn PassUnion3(self, _: BlobOrString) {}
|
fn PassUnion3(self, _: BlobOrString) {}
|
||||||
fn PassAny(self, _: *mut JSContext, _: JSVal) {}
|
fn PassAny(self, _: *mut JSContext, _: JSVal) {}
|
||||||
|
fn PassCallbackFunction(self, _: Function) {}
|
||||||
|
fn PassCallbackInterface(self, _: EventListener) {}
|
||||||
|
|
||||||
fn PassNullableBoolean(self, _: Option<bool>) {}
|
fn PassNullableBoolean(self, _: Option<bool>) {}
|
||||||
fn PassNullableByte(self, _: Option<i8>) {}
|
fn PassNullableByte(self, _: Option<i8>) {}
|
||||||
|
@ -182,6 +186,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
|
||||||
fn PassNullableInterface(self, _: Option<JSRef<Blob>>) {}
|
fn PassNullableInterface(self, _: Option<JSRef<Blob>>) {}
|
||||||
fn PassNullableUnion(self, _: Option<HTMLElementOrLong>) {}
|
fn PassNullableUnion(self, _: Option<HTMLElementOrLong>) {}
|
||||||
fn PassNullableUnion2(self, _: Option<EventOrString>) {}
|
fn PassNullableUnion2(self, _: Option<EventOrString>) {}
|
||||||
|
fn PassNullableCallbackFunction(self, _: Option<Function>) {}
|
||||||
|
fn PassNullableCallbackInterface(self, _: Option<EventListener>) {}
|
||||||
|
|
||||||
fn PassOptionalBoolean(self, _: Option<bool>) {}
|
fn PassOptionalBoolean(self, _: Option<bool>) {}
|
||||||
fn PassOptionalByte(self, _: Option<i8>) {}
|
fn PassOptionalByte(self, _: Option<i8>) {}
|
||||||
|
@ -201,6 +207,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
|
||||||
fn PassOptionalUnion(self, _: Option<HTMLElementOrLong>) {}
|
fn PassOptionalUnion(self, _: Option<HTMLElementOrLong>) {}
|
||||||
fn PassOptionalUnion2(self, _: Option<EventOrString>) {}
|
fn PassOptionalUnion2(self, _: Option<EventOrString>) {}
|
||||||
fn PassOptionalAny(self, _: *mut JSContext, _: JSVal) {}
|
fn PassOptionalAny(self, _: *mut JSContext, _: JSVal) {}
|
||||||
|
fn PassOptionalCallbackFunction(self, _: Option<Function>) {}
|
||||||
|
fn PassOptionalCallbackInterface(self, _: Option<EventListener>) {}
|
||||||
|
|
||||||
fn PassOptionalNullableBoolean(self, _: Option<Option<bool>>) {}
|
fn PassOptionalNullableBoolean(self, _: Option<Option<bool>>) {}
|
||||||
fn PassOptionalNullableByte(self, _: Option<Option<i8>>) {}
|
fn PassOptionalNullableByte(self, _: Option<Option<i8>>) {}
|
||||||
|
@ -219,6 +227,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
|
||||||
fn PassOptionalNullableInterface(self, _: Option<Option<JSRef<Blob>>>) {}
|
fn PassOptionalNullableInterface(self, _: Option<Option<JSRef<Blob>>>) {}
|
||||||
fn PassOptionalNullableUnion(self, _: Option<Option<HTMLElementOrLong>>) {}
|
fn PassOptionalNullableUnion(self, _: Option<Option<HTMLElementOrLong>>) {}
|
||||||
fn PassOptionalNullableUnion2(self, _: Option<Option<EventOrString>>) {}
|
fn PassOptionalNullableUnion2(self, _: Option<Option<EventOrString>>) {}
|
||||||
|
fn PassOptionalNullableCallbackFunction(self, _: Option<Option<Function>>) {}
|
||||||
|
fn PassOptionalNullableCallbackInterface(self, _: Option<Option<EventListener>>) {}
|
||||||
|
|
||||||
fn PassOptionalBooleanWithDefault(self, _: bool) {}
|
fn PassOptionalBooleanWithDefault(self, _: bool) {}
|
||||||
fn PassOptionalByteWithDefault(self, _: i8) {}
|
fn PassOptionalByteWithDefault(self, _: i8) {}
|
||||||
|
@ -249,6 +259,8 @@ impl<'a> TestBindingMethods for JSRef<'a, TestBinding> {
|
||||||
fn PassOptionalNullableInterfaceWithDefault(self, _: Option<JSRef<Blob>>) {}
|
fn PassOptionalNullableInterfaceWithDefault(self, _: Option<JSRef<Blob>>) {}
|
||||||
fn PassOptionalNullableUnionWithDefault(self, _: Option<HTMLElementOrLong>) {}
|
fn PassOptionalNullableUnionWithDefault(self, _: Option<HTMLElementOrLong>) {}
|
||||||
fn PassOptionalNullableUnion2WithDefault(self, _: Option<EventOrString>) {}
|
fn PassOptionalNullableUnion2WithDefault(self, _: Option<EventOrString>) {}
|
||||||
|
// fn PassOptionalNullableCallbackFunctionWithDefault(self, _: Option<Function>) {}
|
||||||
|
fn PassOptionalNullableCallbackInterfaceWithDefault(self, _: Option<EventListener>) {}
|
||||||
fn PassOptionalAnyWithDefault(self, _: *mut JSContext, _: JSVal) {}
|
fn PassOptionalAnyWithDefault(self, _: *mut JSContext, _: JSVal) {}
|
||||||
|
|
||||||
fn PassOptionalNullableBooleanWithNonNullDefault(self, _: Option<bool>) {}
|
fn PassOptionalNullableBooleanWithNonNullDefault(self, _: Option<bool>) {}
|
||||||
|
|
|
@ -148,6 +148,8 @@ interface TestBinding {
|
||||||
void passUnion2((Event or DOMString) data);
|
void passUnion2((Event or DOMString) data);
|
||||||
void passUnion3((Blob or DOMString) data);
|
void passUnion3((Blob or DOMString) data);
|
||||||
void passAny(any arg);
|
void passAny(any arg);
|
||||||
|
void passCallbackFunction(Function fun);
|
||||||
|
void passCallbackInterface(EventListener listener);
|
||||||
|
|
||||||
void passNullableBoolean(boolean? arg);
|
void passNullableBoolean(boolean? arg);
|
||||||
void passNullableByte(byte? arg);
|
void passNullableByte(byte? arg);
|
||||||
|
@ -166,6 +168,8 @@ interface TestBinding {
|
||||||
void passNullableInterface(Blob? arg);
|
void passNullableInterface(Blob? arg);
|
||||||
void passNullableUnion((HTMLElement or long)? arg);
|
void passNullableUnion((HTMLElement or long)? arg);
|
||||||
void passNullableUnion2((Event or DOMString)? data);
|
void passNullableUnion2((Event or DOMString)? data);
|
||||||
|
void passNullableCallbackFunction(Function? fun);
|
||||||
|
void passNullableCallbackInterface(EventListener? listener);
|
||||||
|
|
||||||
void passOptionalBoolean(optional boolean arg);
|
void passOptionalBoolean(optional boolean arg);
|
||||||
void passOptionalByte(optional byte arg);
|
void passOptionalByte(optional byte arg);
|
||||||
|
@ -185,6 +189,8 @@ interface TestBinding {
|
||||||
void passOptionalUnion(optional (HTMLElement or long) arg);
|
void passOptionalUnion(optional (HTMLElement or long) arg);
|
||||||
void passOptionalUnion2(optional (Event or DOMString) data);
|
void passOptionalUnion2(optional (Event or DOMString) data);
|
||||||
void passOptionalAny(optional any arg);
|
void passOptionalAny(optional any arg);
|
||||||
|
void passOptionalCallbackFunction(optional Function fun);
|
||||||
|
void passOptionalCallbackInterface(optional EventListener listener);
|
||||||
|
|
||||||
void passOptionalNullableBoolean(optional boolean? arg);
|
void passOptionalNullableBoolean(optional boolean? arg);
|
||||||
void passOptionalNullableByte(optional byte? arg);
|
void passOptionalNullableByte(optional byte? arg);
|
||||||
|
@ -203,6 +209,8 @@ interface TestBinding {
|
||||||
void passOptionalNullableInterface(optional Blob? arg);
|
void passOptionalNullableInterface(optional Blob? arg);
|
||||||
void passOptionalNullableUnion(optional (HTMLElement or long)? arg);
|
void passOptionalNullableUnion(optional (HTMLElement or long)? arg);
|
||||||
void passOptionalNullableUnion2(optional (Event or DOMString)? data);
|
void passOptionalNullableUnion2(optional (Event or DOMString)? data);
|
||||||
|
void passOptionalNullableCallbackFunction(optional Function? fun);
|
||||||
|
void passOptionalNullableCallbackInterface(optional EventListener? listener);
|
||||||
|
|
||||||
void passOptionalBooleanWithDefault(optional boolean arg = false);
|
void passOptionalBooleanWithDefault(optional boolean arg = false);
|
||||||
void passOptionalByteWithDefault(optional byte arg = 0);
|
void passOptionalByteWithDefault(optional byte arg = 0);
|
||||||
|
@ -233,6 +241,8 @@ interface TestBinding {
|
||||||
void passOptionalNullableInterfaceWithDefault(optional Blob? arg = null);
|
void passOptionalNullableInterfaceWithDefault(optional Blob? arg = null);
|
||||||
void passOptionalNullableUnionWithDefault(optional (HTMLElement or long)? arg = null);
|
void passOptionalNullableUnionWithDefault(optional (HTMLElement or long)? arg = null);
|
||||||
void passOptionalNullableUnion2WithDefault(optional (Event or DOMString)? data = null);
|
void passOptionalNullableUnion2WithDefault(optional (Event or DOMString)? data = null);
|
||||||
|
// void passOptionalNullableCallbackFunctionWithDefault(optional Function? fun = null);
|
||||||
|
void passOptionalNullableCallbackInterfaceWithDefault(optional EventListener? listener = null);
|
||||||
void passOptionalAnyWithDefault(optional any arg = null);
|
void passOptionalAnyWithDefault(optional any arg = null);
|
||||||
|
|
||||||
void passOptionalNullableBooleanWithNonNullDefault(optional boolean? arg = false);
|
void passOptionalNullableBooleanWithNonNullDefault(optional boolean? arg = false);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue