mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
auto merge of #3941 : mukilan/servo/timeout-arguments, r=Ms2ger
This commit is contained in:
commit
43b452f3b8
15 changed files with 186 additions and 376 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():
|
||||||
|
declType = CGWrapper(declType, pre="Option<", post=">")
|
||||||
|
template = wrapObjectTemplate("Some(%s)" % template, isDefinitelyObject, type,
|
||||||
|
failureCode)
|
||||||
|
|
||||||
template = wrapObjectTemplate(conversion, isDefinitelyObject, type,
|
|
||||||
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,8 +4801,8 @@ 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
|
||||||
self.needThisHandling = needThisHandling
|
self.needThisHandling = needThisHandling
|
||||||
|
@ -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):
|
||||||
|
|
|
@ -146,7 +146,7 @@ impl DedicatedWorkerGlobalScope {
|
||||||
Worker::handle_release(addr)
|
Worker::handle_release(addr)
|
||||||
},
|
},
|
||||||
Ok(FireTimerMsg(FromWorker, timer_id)) => {
|
Ok(FireTimerMsg(FromWorker, timer_id)) => {
|
||||||
scope.handle_fire_timer(timer_id, js_context.ptr);
|
scope.handle_fire_timer(timer_id);
|
||||||
}
|
}
|
||||||
Ok(_) => panic!("Unexpected message"),
|
Ok(_) => panic!("Unexpected message"),
|
||||||
Err(_) => break,
|
Err(_) => break,
|
||||||
|
|
|
@ -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>) {}
|
||||||
|
|
14
components/script/dom/webidls/Function.webidl
Normal file
14
components/script/dom/webidls/Function.webidl
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* The origin of this IDL file is
|
||||||
|
* http://www.whatwg.org/specs/web-apps/current-work/#functiocn
|
||||||
|
*
|
||||||
|
* © Copyright 2004-2011 Apple Computer, Inc., Mozilla Foundation, and
|
||||||
|
* Opera Software ASA. You are granted a license to use, reproduce
|
||||||
|
* and create derivative works of this document.
|
||||||
|
*/
|
||||||
|
|
||||||
|
callback Function = any(any... arguments);
|
|
@ -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);
|
||||||
|
|
|
@ -64,13 +64,11 @@ Window implements WindowEventHandlers;
|
||||||
// http://www.whatwg.org/html/#windowtimers
|
// http://www.whatwg.org/html/#windowtimers
|
||||||
[NoInterfaceObject/*, Exposed=Window,Worker*/]
|
[NoInterfaceObject/*, Exposed=Window,Worker*/]
|
||||||
interface WindowTimers {
|
interface WindowTimers {
|
||||||
//long setTimeout(Function handler, optional long timeout = 0, any... arguments);
|
long setTimeout(Function handler, optional long timeout = 0, any... arguments);
|
||||||
//long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
|
//long setTimeout(DOMString handler, optional long timeout = 0, any... arguments);
|
||||||
long setTimeout(any handler, optional long timeout = 0);
|
|
||||||
void clearTimeout(optional long handle = 0);
|
void clearTimeout(optional long handle = 0);
|
||||||
//long setInterval(Function handler, optional long timeout = 0, any... arguments);
|
long setInterval(Function handler, optional long timeout = 0, any... arguments);
|
||||||
//long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
|
//long setInterval(DOMString handler, optional long timeout = 0, any... arguments);
|
||||||
long setInterval(any handler, optional long timeout = 0);
|
|
||||||
void clearInterval(optional long handle = 0);
|
void clearInterval(optional long handle = 0);
|
||||||
};
|
};
|
||||||
Window implements WindowTimers;
|
Window implements WindowTimers;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
|
use dom::bindings::codegen::Bindings::EventHandlerBinding::{OnErrorEventHandlerNonNull, EventHandlerNonNull};
|
||||||
|
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding;
|
use dom::bindings::codegen::Bindings::WindowBinding;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
use dom::bindings::codegen::InheritTypes::EventTargetCast;
|
||||||
|
@ -223,8 +224,9 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
|
||||||
self.navigator.get().unwrap()
|
self.navigator.get().unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetTimeout(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
|
fn SetTimeout(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
|
||||||
self.timers.set_timeout_or_interval(callback,
|
self.timers.set_timeout_or_interval(callback,
|
||||||
|
args,
|
||||||
timeout,
|
timeout,
|
||||||
false, // is_interval
|
false, // is_interval
|
||||||
FromWindow(self.page.id.clone()),
|
FromWindow(self.page.id.clone()),
|
||||||
|
@ -235,8 +237,9 @@ impl<'a> WindowMethods for JSRef<'a, Window> {
|
||||||
self.timers.clear_timeout_or_interval(handle);
|
self.timers.clear_timeout_or_interval(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetInterval(self, _cx: *mut JSContext, callback: JSVal, timeout: i32) -> i32 {
|
fn SetInterval(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
|
||||||
self.timers.set_timeout_or_interval(callback,
|
self.timers.set_timeout_or_interval(callback,
|
||||||
|
args,
|
||||||
timeout,
|
timeout,
|
||||||
true, // is_interval
|
true, // is_interval
|
||||||
FromWindow(self.page.id.clone()),
|
FromWindow(self.page.id.clone()),
|
||||||
|
@ -317,7 +320,7 @@ pub trait WindowHelpers {
|
||||||
fn wait_until_safe_to_modify_dom(self);
|
fn wait_until_safe_to_modify_dom(self);
|
||||||
fn init_browser_context(self, doc: JSRef<Document>);
|
fn init_browser_context(self, doc: JSRef<Document>);
|
||||||
fn load_url(self, href: DOMString);
|
fn load_url(self, href: DOMString);
|
||||||
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext);
|
fn handle_fire_timer(self, timer_id: TimerId);
|
||||||
fn evaluate_js_with_result(self, code: &str) -> JSVal;
|
fn evaluate_js_with_result(self, code: &str) -> JSVal;
|
||||||
fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal;
|
fn evaluate_script_with_result(self, code: &str, filename: &str) -> JSVal;
|
||||||
}
|
}
|
||||||
|
@ -380,9 +383,8 @@ impl<'a> WindowHelpers for JSRef<'a, Window> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
|
fn handle_fire_timer(self, timer_id: TimerId) {
|
||||||
let this_value = self.reflector().get_jsobject();
|
self.timers.fire_timer(timer_id, self.clone());
|
||||||
self.timers.fire_timer(timer_id, this_value, cx);
|
|
||||||
self.flush_layout();
|
self.flush_layout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
use dom::bindings::codegen::Bindings::WorkerGlobalScopeBinding::WorkerGlobalScopeMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown};
|
use dom::bindings::error::{ErrorResult, Fallible, Syntax, Network, FailureUnknown};
|
||||||
use dom::bindings::global;
|
use dom::bindings::global;
|
||||||
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
|
use dom::bindings::js::{MutNullableJS, JSRef, Temporary, OptionalSettable};
|
||||||
|
@ -155,8 +156,9 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
|
||||||
base64_atob(atob)
|
base64_atob(atob)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetTimeout(self, _cx: *mut JSContext, handler: JSVal, timeout: i32) -> i32 {
|
fn SetTimeout(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
|
||||||
self.timers.set_timeout_or_interval(handler,
|
self.timers.set_timeout_or_interval(callback,
|
||||||
|
args,
|
||||||
timeout,
|
timeout,
|
||||||
false, // is_interval
|
false, // is_interval
|
||||||
FromWorker,
|
FromWorker,
|
||||||
|
@ -167,8 +169,9 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
|
||||||
self.timers.clear_timeout_or_interval(handle);
|
self.timers.clear_timeout_or_interval(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn SetInterval(self, _cx: *mut JSContext, handler: JSVal, timeout: i32) -> i32 {
|
fn SetInterval(self, _cx: *mut JSContext, callback: Function, timeout: i32, args: Vec<JSVal>) -> i32 {
|
||||||
self.timers.set_timeout_or_interval(handler,
|
self.timers.set_timeout_or_interval(callback,
|
||||||
|
args,
|
||||||
timeout,
|
timeout,
|
||||||
true, // is_interval
|
true, // is_interval
|
||||||
FromWorker,
|
FromWorker,
|
||||||
|
@ -181,14 +184,13 @@ impl<'a> WorkerGlobalScopeMethods for JSRef<'a, WorkerGlobalScope> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait WorkerGlobalScopeHelpers {
|
pub trait WorkerGlobalScopeHelpers {
|
||||||
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext);
|
fn handle_fire_timer(self, timer_id: TimerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> WorkerGlobalScopeHelpers for JSRef<'a, WorkerGlobalScope> {
|
impl<'a> WorkerGlobalScopeHelpers for JSRef<'a, WorkerGlobalScope> {
|
||||||
|
|
||||||
fn handle_fire_timer(self, timer_id: TimerId, cx: *mut JSContext) {
|
fn handle_fire_timer(self, timer_id: TimerId) {
|
||||||
let this_value = self.reflector().get_jsobject();
|
self.timers.fire_timer(timer_id, self.clone());
|
||||||
self.timers.fire_timer(timer_id, this_value, cx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -665,7 +665,7 @@ impl ScriptTask {
|
||||||
pipeline ID not associated with this script task. This is a bug.");
|
pipeline ID not associated with this script task. This is a bug.");
|
||||||
let frame = page.frame();
|
let frame = page.frame();
|
||||||
let window = frame.as_ref().unwrap().window.root();
|
let window = frame.as_ref().unwrap().window.root();
|
||||||
window.handle_fire_timer(timer_id, self.get_cx());
|
window.handle_fire_timer(timer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handles a notification that reflow completed.
|
/// Handles a notification that reflow completed.
|
||||||
|
|
|
@ -3,16 +3,17 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use dom::bindings::cell::DOMRefCell;
|
use dom::bindings::cell::DOMRefCell;
|
||||||
|
use dom::bindings::callback::ReportExceptions;
|
||||||
|
use dom::bindings::codegen::Bindings::FunctionBinding::Function;
|
||||||
|
use dom::bindings::js::JSRef;
|
||||||
|
use dom::bindings::utils::Reflectable;
|
||||||
|
|
||||||
use script_task::{FireTimerMsg, ScriptChan};
|
use script_task::{FireTimerMsg, ScriptChan};
|
||||||
use script_task::{TimerSource, FromWindow, FromWorker};
|
use script_task::{TimerSource, FromWindow, FromWorker};
|
||||||
|
|
||||||
use servo_util::task::spawn_named;
|
use servo_util::task::spawn_named;
|
||||||
|
|
||||||
use js::jsapi::JS_CallFunctionValue;
|
use js::jsval::JSVal;
|
||||||
use js::jsapi::{JSContext, JSObject};
|
|
||||||
use js::jsval::{JSVal, NullValue};
|
|
||||||
use js::rust::with_compartment;
|
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -21,7 +22,6 @@ use std::comm::{channel, Sender};
|
||||||
use std::comm::Select;
|
use std::comm::Select;
|
||||||
use std::hash::{Hash, sip};
|
use std::hash::{Hash, sip};
|
||||||
use std::io::timer::Timer;
|
use std::io::timer::Timer;
|
||||||
use std::ptr;
|
|
||||||
use std::time::duration::Duration;
|
use std::time::duration::Duration;
|
||||||
|
|
||||||
#[deriving(PartialEq, Eq)]
|
#[deriving(PartialEq, Eq)]
|
||||||
|
@ -69,11 +69,14 @@ impl Drop for TimerManager {
|
||||||
// Holder for the various JS values associated with setTimeout
|
// Holder for the various JS values associated with setTimeout
|
||||||
// (ie. function value to invoke and all arguments to pass
|
// (ie. function value to invoke and all arguments to pass
|
||||||
// to the function when calling it)
|
// to the function when calling it)
|
||||||
|
// TODO: Handle rooting during fire_timer when movable GC is turned on
|
||||||
#[jstraceable]
|
#[jstraceable]
|
||||||
#[privatize]
|
#[privatize]
|
||||||
|
#[deriving(Clone)]
|
||||||
struct TimerData {
|
struct TimerData {
|
||||||
is_interval: bool,
|
is_interval: bool,
|
||||||
funval: JSVal,
|
funval: Function,
|
||||||
|
args: Vec<JSVal>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TimerManager {
|
impl TimerManager {
|
||||||
|
@ -85,7 +88,8 @@ impl TimerManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_timeout_or_interval(&self,
|
pub fn set_timeout_or_interval(&self,
|
||||||
callback: JSVal,
|
callback: Function,
|
||||||
|
arguments: Vec<JSVal>,
|
||||||
timeout: i32,
|
timeout: i32,
|
||||||
is_interval: bool,
|
is_interval: bool,
|
||||||
source: TimerSource,
|
source: TimerSource,
|
||||||
|
@ -142,6 +146,7 @@ impl TimerManager {
|
||||||
data: TimerData {
|
data: TimerData {
|
||||||
is_interval: is_interval,
|
is_interval: is_interval,
|
||||||
funval: callback,
|
funval: callback,
|
||||||
|
args: arguments
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.active_timers.borrow_mut().insert(timer_id, timer);
|
self.active_timers.borrow_mut().insert(timer_id, timer);
|
||||||
|
@ -156,21 +161,15 @@ impl TimerManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fire_timer(&self, timer_id: TimerId, this: *mut JSObject, cx: *mut JSContext) {
|
pub fn fire_timer<T: Reflectable>(&self, timer_id: TimerId, this: JSRef<T>) {
|
||||||
|
|
||||||
let data = match self.active_timers.borrow().get(&timer_id) {
|
let data = match self.active_timers.borrow().get(&timer_id) {
|
||||||
None => return,
|
None => return,
|
||||||
Some(timer_handle) => timer_handle.data,
|
Some(timer_handle) => timer_handle.data.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: Support extra arguments. This requires passing a `*JSVal` array as `argv`.
|
// TODO: Must handle rooting of funval and args when movable GC is turned on
|
||||||
with_compartment(cx, this, || {
|
let _ = data.funval.Call_(this, data.args, ReportExceptions);
|
||||||
let mut rval = NullValue();
|
|
||||||
unsafe {
|
|
||||||
JS_CallFunctionValue(cx, this, data.funval,
|
|
||||||
0, ptr::null_mut(), &mut rval);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if !data.is_interval {
|
if !data.is_interval {
|
||||||
self.active_timers.borrow_mut().remove(&timer_id);
|
self.active_timers.borrow_mut().remove(&timer_id);
|
||||||
|
|
|
@ -9948,3 +9948,27 @@
|
||||||
[HTMLFontElement interface: document.createElement("font") must inherit property "size" with the proper type (2)]
|
[HTMLFontElement interface: document.createElement("font") must inherit property "size" with the proper type (2)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
[Window interface: operation setTimeout(Function,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Window interface: operation setTimeout(DOMString,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Window interface: operation setInterval(Function,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[Window interface: operation setInterval(DOMString,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WorkerGlobalScope interface: operation setTimeout(Function,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WorkerGlobalScope interface: operation setTimeout(DOMString,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WorkerGlobalScope interface: operation setInterval(Function,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[WorkerGlobalScope interface: operation setInterval(DOMString,long,any)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
[compile-error-in-setInterval.html]
|
[compile-error-in-setInterval.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[window.onerror - compile error in setInterval]
|
[window.onerror - compile error in setInterval]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[window.onerror - compile error in setInterval (column)]
|
[window.onerror - compile error in setInterval (column)]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
[compile-error-in-setTimeout.html]
|
[compile-error-in-setTimeout.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[window.onerror - compile error in setTimeout]
|
[window.onerror - compile error in setTimeout]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[window.onerror - compile error in setTimeout (column)]
|
[window.onerror - compile error in setTimeout (column)]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
[runtime-error-in-setInterval.html]
|
[runtime-error-in-setInterval.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[window.onerror - runtime error in setInterval]
|
[window.onerror - runtime error in setInterval]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[window.onerror - runtime error in setInterval (column)]
|
[window.onerror - runtime error in setInterval (column)]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
[runtime-error-in-setTimeout.html]
|
[runtime-error-in-setTimeout.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
|
expected: TIMEOUT
|
||||||
[window.onerror - runtime error in setTimeout]
|
[window.onerror - runtime error in setTimeout]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
[window.onerror - runtime error in setTimeout (column)]
|
[window.onerror - runtime error in setTimeout (column)]
|
||||||
expected: FAIL
|
expected: NOTRUN
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue