mirror of
https://github.com/servo/servo.git
synced 2025-06-19 14:48:59 +01:00
Implement WebIDL method overloads. Fixes #540.
This commit is contained in:
parent
213d9a011a
commit
eb95d82fe6
11 changed files with 281 additions and 74 deletions
|
@ -92,9 +92,10 @@ DOMInterfaces = {
|
||||||
{
|
{
|
||||||
'headerFile': 'nsIDOMFile.h',
|
'headerFile': 'nsIDOMFile.h',
|
||||||
},
|
},
|
||||||
{
|
#{
|
||||||
'workers': True,
|
# 'workers': True,
|
||||||
}],
|
#}
|
||||||
|
],
|
||||||
|
|
||||||
'CanvasRenderingContext2D': [
|
'CanvasRenderingContext2D': [
|
||||||
{
|
{
|
||||||
|
@ -199,9 +200,10 @@ DOMInterfaces = {
|
||||||
'FormData': [
|
'FormData': [
|
||||||
{
|
{
|
||||||
},
|
},
|
||||||
{
|
#{
|
||||||
'workers': True,
|
# 'workers': True,
|
||||||
}],
|
#}
|
||||||
|
],
|
||||||
|
|
||||||
'HTMLCollection': [
|
'HTMLCollection': [
|
||||||
{
|
{
|
||||||
|
|
2
src/components/script/dom/bindings/codegen/Blob.webidl
Normal file
2
src/components/script/dom/bindings/codegen/Blob.webidl
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
interface Blob {
|
||||||
|
};
|
|
@ -122,6 +122,15 @@ class CastableObjectUnwrapper():
|
||||||
# }
|
# }
|
||||||
#}""").substitute(self.substitution)
|
#}""").substitute(self.substitution)
|
||||||
|
|
||||||
|
class FailureFatalCastableObjectUnwrapper(CastableObjectUnwrapper):
|
||||||
|
"""
|
||||||
|
As CastableObjectUnwrapper, but defaulting to throwing if unwrapping fails
|
||||||
|
"""
|
||||||
|
def __init__(self, descriptor, source, target):
|
||||||
|
CastableObjectUnwrapper.__init__(self, descriptor, source, target,
|
||||||
|
"return Throw<%s>(cx, rv);" %
|
||||||
|
toStringBool(not descriptor.workers))
|
||||||
|
|
||||||
class CGThing():
|
class CGThing():
|
||||||
"""
|
"""
|
||||||
Abstract base class for things that spit out code.
|
Abstract base class for things that spit out code.
|
||||||
|
@ -154,9 +163,10 @@ class CGMethodCall(CGThing):
|
||||||
requiredArgs -= 1
|
requiredArgs -= 1
|
||||||
return requiredArgs
|
return requiredArgs
|
||||||
|
|
||||||
def getPerSignatureCall(signature, argConversionStartsAt=0):
|
def getPerSignatureCall(signature, argConversionStartsAt=0, signatureIndex=0):
|
||||||
return CGPerSignatureCall(signature[0], argsPre, signature[1],
|
return CGPerSignatureCall(signature[0], argsPre, signature[1],
|
||||||
nativeMethodName, static, descriptor,
|
nativeMethodName + '_'*signatureIndex,
|
||||||
|
static, descriptor,
|
||||||
method, argConversionStartsAt)
|
method, argConversionStartsAt)
|
||||||
|
|
||||||
|
|
||||||
|
@ -201,15 +211,12 @@ class CGMethodCall(CGThing):
|
||||||
signature[1][argCount].optional and
|
signature[1][argCount].optional and
|
||||||
(argCount+1) in allowedArgCounts and
|
(argCount+1) in allowedArgCounts and
|
||||||
len(method.signaturesForArgCount(argCount+1)) == 1):
|
len(method.signaturesForArgCount(argCount+1)) == 1):
|
||||||
#XXXjdm unfinished
|
argCountCases.append(
|
||||||
pass
|
CGCase(str(argCount), None, True))
|
||||||
#argCountCases.append(
|
|
||||||
# CGCase(str(argCount), None, True))
|
|
||||||
else:
|
else:
|
||||||
pass
|
pass
|
||||||
#XXXjdm unfinished
|
argCountCases.append(
|
||||||
#argCountCases.append(
|
CGCase(str(argCount), getPerSignatureCall(signature)))
|
||||||
# CGCase(str(argCount), getPerSignatureCall(signature)))
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
distinguishingIndex = method.distinguishingIndexForArgCount(argCount)
|
distinguishingIndex = method.distinguishingIndexForArgCount(argCount)
|
||||||
|
@ -225,14 +232,14 @@ class CGMethodCall(CGThing):
|
||||||
# Doesn't matter which of the possible signatures we use, since
|
# Doesn't matter which of the possible signatures we use, since
|
||||||
# they all have the same types up to that point; just use
|
# they all have the same types up to that point; just use
|
||||||
# possibleSignatures[0]
|
# possibleSignatures[0]
|
||||||
caseBody = [CGGeneric("JS::Value* argv_start = JS_ARGV(cx, vp);")]
|
caseBody = [CGGeneric("let argv_start = JS_ARGV(cx, cast::transmute(vp));")]
|
||||||
caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
|
caseBody.extend([ CGArgumentConverter(possibleSignatures[0][1][i],
|
||||||
i, "argv_start", "argc",
|
i, "argv_start", "argc",
|
||||||
descriptor) for i in
|
descriptor) for i in
|
||||||
range(0, distinguishingIndex) ])
|
range(0, distinguishingIndex) ])
|
||||||
|
|
||||||
# Select the right overload from our set.
|
# Select the right overload from our set.
|
||||||
distinguishingArg = "argv_start[%d]" % distinguishingIndex
|
distinguishingArg = "(*argv_start.offset(%d))" % distinguishingIndex
|
||||||
|
|
||||||
def pickFirstSignature(condition, filterLambda):
|
def pickFirstSignature(condition, filterLambda):
|
||||||
sigs = filter(filterLambda, possibleSignatures)
|
sigs = filter(filterLambda, possibleSignatures)
|
||||||
|
@ -240,11 +247,13 @@ class CGMethodCall(CGThing):
|
||||||
if len(sigs) > 0:
|
if len(sigs) > 0:
|
||||||
if condition is None:
|
if condition is None:
|
||||||
caseBody.append(
|
caseBody.append(
|
||||||
getPerSignatureCall(sigs[0], distinguishingIndex))
|
getPerSignatureCall(sigs[0], distinguishingIndex,
|
||||||
|
possibleSignatures.index(sigs[0])))
|
||||||
else:
|
else:
|
||||||
caseBody.append(CGGeneric("if (" + condition + ") {"))
|
caseBody.append(CGGeneric("if " + condition + " {"))
|
||||||
caseBody.append(CGIndenter(
|
caseBody.append(CGIndenter(
|
||||||
getPerSignatureCall(sigs[0], distinguishingIndex)))
|
getPerSignatureCall(sigs[0], distinguishingIndex,
|
||||||
|
possibleSignatures.index(sigs[0]))))
|
||||||
caseBody.append(CGGeneric("}"))
|
caseBody.append(CGGeneric("}"))
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -276,10 +285,10 @@ class CGMethodCall(CGThing):
|
||||||
# also allow the unwrapping test to skip having to do codegen
|
# also allow the unwrapping test to skip having to do codegen
|
||||||
# for the null-or-undefined case, which we already handled
|
# for the null-or-undefined case, which we already handled
|
||||||
# above.
|
# above.
|
||||||
caseBody.append(CGGeneric("if (%s.isObject()) {" %
|
caseBody.append(CGGeneric("if JSVAL_IS_OBJECT(%s) {" %
|
||||||
(distinguishingArg)))
|
(distinguishingArg)))
|
||||||
for sig in interfacesSigs:
|
for sig in interfacesSigs:
|
||||||
caseBody.append(CGIndenter(CGGeneric("do {")));
|
caseBody.append(CGIndenter(CGGeneric("loop {")));
|
||||||
type = sig[1][distinguishingIndex].type
|
type = sig[1][distinguishingIndex].type
|
||||||
|
|
||||||
# The argument at index distinguishingIndex can't possibly
|
# The argument at index distinguishingIndex can't possibly
|
||||||
|
@ -303,7 +312,7 @@ class CGMethodCall(CGThing):
|
||||||
# distinguishingIndex.
|
# distinguishingIndex.
|
||||||
caseBody.append(CGIndenter(
|
caseBody.append(CGIndenter(
|
||||||
getPerSignatureCall(sig, distinguishingIndex + 1), 4))
|
getPerSignatureCall(sig, distinguishingIndex + 1), 4))
|
||||||
caseBody.append(CGIndenter(CGGeneric("} while (0);")))
|
caseBody.append(CGIndenter(CGGeneric("}")))
|
||||||
|
|
||||||
caseBody.append(CGGeneric("}"))
|
caseBody.append(CGGeneric("}"))
|
||||||
|
|
||||||
|
@ -354,22 +363,21 @@ class CGMethodCall(CGThing):
|
||||||
caseBody.append(CGGeneric("return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);" %
|
caseBody.append(CGGeneric("return Throw<%s>(cx, NS_ERROR_XPC_BAD_CONVERT_JS);" %
|
||||||
toStringBool(not descriptor.workers)))
|
toStringBool(not descriptor.workers)))
|
||||||
|
|
||||||
#XXXjdm unfinished
|
argCountCases.append(CGCase(str(argCount),
|
||||||
#argCountCases.append(CGCase(str(argCount),
|
CGList(caseBody, "\n")))
|
||||||
# CGList(caseBody, "\n")))
|
|
||||||
|
|
||||||
overloadCGThings = []
|
overloadCGThings = []
|
||||||
overloadCGThings.append(
|
overloadCGThings.append(
|
||||||
CGGeneric("unsigned argcount = NS_MIN(argc, %du);" %
|
CGGeneric("let argcount = argc.min(&%d);" %
|
||||||
maxArgCount))
|
maxArgCount))
|
||||||
#XXXjdm unfinished
|
|
||||||
#overloadCGThings.append(
|
|
||||||
# CGSwitch("argcount",
|
|
||||||
# argCountCases,
|
|
||||||
# CGGeneric("return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName)))
|
|
||||||
overloadCGThings.append(
|
overloadCGThings.append(
|
||||||
CGGeneric('MOZ_NOT_REACHED("We have an always-returning default case");\n'
|
CGSwitch("argcount",
|
||||||
'return false;'))
|
argCountCases,
|
||||||
|
CGGeneric("return 0; //XXXjdm throw stuff\n//return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, %s);\n" % methodName)))
|
||||||
|
#XXXjdm Avoid unreachable statement warnings
|
||||||
|
#overloadCGThings.append(
|
||||||
|
# CGGeneric('fail!("We have an always-returning default case");\n'
|
||||||
|
# 'return 0;'))
|
||||||
self.cgRoot = CGWrapper(CGIndenter(CGList(overloadCGThings, "\n")),
|
self.cgRoot = CGWrapper(CGIndenter(CGList(overloadCGThings, "\n")),
|
||||||
pre="\n")
|
pre="\n")
|
||||||
|
|
||||||
|
@ -492,11 +500,11 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||||
def onFailureNotAnObject(failureCode):
|
def onFailureNotAnObject(failureCode):
|
||||||
return CGWrapper(CGGeneric(
|
return CGWrapper(CGGeneric(
|
||||||
failureCode or
|
failureCode or
|
||||||
'return ThrowErrorMessage(cx, MSG_NOT_OBJECT);'), post="\n")
|
'return 0; //XXXjdm return ThrowErrorMessage(cx, MSG_NOT_OBJECT);'), post="\n")
|
||||||
def onFailureBadType(failureCode, typeName):
|
def onFailureBadType(failureCode, typeName):
|
||||||
return CGWrapper(CGGeneric(
|
return CGWrapper(CGGeneric(
|
||||||
failureCode or
|
failureCode or
|
||||||
'return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s");' % typeName), post="\n")
|
'return 0; //XXXjdm return ThrowErrorMessage(cx, MSG_DOES_NOT_IMPLEMENT_INTERFACE, "%s");' % typeName), post="\n")
|
||||||
|
|
||||||
# A helper function for handling default values. Takes a template
|
# A helper function for handling default values. Takes a template
|
||||||
# body and the C++ code to set the default value and wraps the
|
# body and the C++ code to set the default value and wraps the
|
||||||
|
@ -529,7 +537,7 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||||
# Handle the non-object cases by wrapping up the whole
|
# Handle the non-object cases by wrapping up the whole
|
||||||
# thing in an if cascade.
|
# thing in an if cascade.
|
||||||
templateBody = (
|
templateBody = (
|
||||||
"if (${val}.isObject()) {\n" +
|
"if JSVAL_IS_OBJECT(${val}) {\n" +
|
||||||
CGIndenter(CGGeneric(templateBody)).define() + "\n")
|
CGIndenter(CGGeneric(templateBody)).define() + "\n")
|
||||||
if type.nullable():
|
if type.nullable():
|
||||||
templateBody += (
|
templateBody += (
|
||||||
|
@ -580,7 +588,8 @@ def getJSToNativeConversionTemplate(type, descriptorProvider, failureCode=None,
|
||||||
str(type.location))
|
str(type.location))
|
||||||
|
|
||||||
(elementTemplate, elementDeclType,
|
(elementTemplate, elementDeclType,
|
||||||
elementHolderType, dealWithOptional) = getJSToNativeConversionTemplate(
|
elementHolderType, dealWithOptional,
|
||||||
|
initialValue) = getJSToNativeConversionTemplate(
|
||||||
elementType, descriptorProvider, isMember=True)
|
elementType, descriptorProvider, isMember=True)
|
||||||
if dealWithOptional:
|
if dealWithOptional:
|
||||||
raise TypeError("Shouldn't have optional things in sequences")
|
raise TypeError("Shouldn't have optional things in sequences")
|
||||||
|
@ -635,7 +644,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
|
templateBody = wrapObjectTemplate(templateBody, isDefinitelyObject,
|
||||||
type,
|
type,
|
||||||
"const_cast< %s & >(${declName}).SetNull()" % mutableTypeName.define())
|
"const_cast< %s & >(${declName}).SetNull()" % mutableTypeName.define())
|
||||||
return (templateBody, typeName, None, isOptional)
|
return (templateBody, typeName, None, isOptional, None)
|
||||||
|
|
||||||
if type.isUnion():
|
if type.isUnion():
|
||||||
if isMember:
|
if isMember:
|
||||||
|
@ -848,7 +857,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
extraConditionForNull=valueMissing)
|
extraConditionForNull=valueMissing)
|
||||||
templateBody = CGList([constructDecl, templateBody], "\n")
|
templateBody = CGList([constructDecl, templateBody], "\n")
|
||||||
|
|
||||||
return templateBody.define(), declType, holderType, False
|
return templateBody.define(), declType, holderType, False, None
|
||||||
|
|
||||||
if type.isGeckoInterface():
|
if type.isGeckoInterface():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -886,7 +895,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
if forceOwningType:
|
if forceOwningType:
|
||||||
declType = "OwningNonNull<" + typeName + ">"
|
declType = "OwningNonNull<" + typeName + ">"
|
||||||
else:
|
else:
|
||||||
declType = "NonNull<" + typeName + ">"
|
declType = descriptor.pointerType + typeName
|
||||||
|
|
||||||
templateBody = ""
|
templateBody = ""
|
||||||
if descriptor.castable:
|
if descriptor.castable:
|
||||||
|
@ -902,16 +911,14 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
if failureCode is not None:
|
if failureCode is not None:
|
||||||
templateBody += str(CastableObjectUnwrapper(
|
templateBody += str(CastableObjectUnwrapper(
|
||||||
descriptor,
|
descriptor,
|
||||||
"&${val}.toObject()",
|
"JSVAL_TO_OBJECT(${val})",
|
||||||
"${declName}",
|
"${declName}",
|
||||||
failureCode))
|
failureCode))
|
||||||
else:
|
else:
|
||||||
pass
|
templateBody += str(FailureFatalCastableObjectUnwrapper(
|
||||||
#XXXjdm unfinished
|
descriptor,
|
||||||
#templateBody += str(FailureFatalCastableObjectUnwrapper(
|
"JSVAL_TO_OBJECT(${val})",
|
||||||
# descriptor,
|
"${declName}"))
|
||||||
# "&${val}.toObject()",
|
|
||||||
# "${declName}"))
|
|
||||||
elif descriptor.interface.isCallback() and False:
|
elif descriptor.interface.isCallback() and False:
|
||||||
#XXXjdm unfinished
|
#XXXjdm unfinished
|
||||||
templateBody += str(CallbackObjectUnwrapper(
|
templateBody += str(CallbackObjectUnwrapper(
|
||||||
|
@ -962,7 +969,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
declType = CGGeneric(declType)
|
declType = CGGeneric(declType)
|
||||||
if holderType is not None:
|
if holderType is not None:
|
||||||
holderType = CGGeneric(holderType)
|
holderType = CGGeneric(holderType)
|
||||||
return (templateBody, declType, holderType, isOptional)
|
return (templateBody, declType, holderType, isOptional, None)
|
||||||
|
|
||||||
if type.isSpiderMonkeyInterface():
|
if type.isSpiderMonkeyInterface():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1018,7 +1025,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
if holderType is not None:
|
if holderType is not None:
|
||||||
holderType = CGGeneric(holderType)
|
holderType = CGGeneric(holderType)
|
||||||
# We handle all the optional stuff ourselves; no need for caller to do it.
|
# We handle all the optional stuff ourselves; no need for caller to do it.
|
||||||
return (template, CGGeneric(declType), holderType, False)
|
return (template, CGGeneric(declType), holderType, False, None)
|
||||||
|
|
||||||
if type.isString():
|
if type.isString():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1040,17 +1047,21 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
raise TypeError("We don't support [TreatUndefinedAs=Missing]")
|
raise TypeError("We don't support [TreatUndefinedAs=Missing]")
|
||||||
undefinedBehavior = treatAs[treatUndefinedAs]
|
undefinedBehavior = treatAs[treatUndefinedAs]
|
||||||
|
|
||||||
def getConversionCode(varName):
|
def getConversionCode(varName, isOptional=False):
|
||||||
|
#XXXjdm support nullBehavior and undefinedBehavior
|
||||||
#conversionCode = (
|
#conversionCode = (
|
||||||
# "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
# "if (!ConvertJSValueToString(cx, ${val}, ${valPtr}, %s, %s, %s)) {\n"
|
||||||
# " return false;\n"
|
# " return false;\n"
|
||||||
# "}" % (nullBehavior, undefinedBehavior, varName))
|
# "}" % (nullBehavior, undefinedBehavior, varName))
|
||||||
|
strval = "str(strval.get())"
|
||||||
|
if isOptional:
|
||||||
|
strval = "Some(%s)" % strval
|
||||||
conversionCode = (
|
conversionCode = (
|
||||||
"let strval = jsval_to_str(cx, ${val});\n"
|
"let strval = jsval_to_str(cx, ${val});\n"
|
||||||
"if strval.is_err() {\n"
|
"if strval.is_err() {\n"
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"%s = str(strval.get());" % varName)
|
"%s = %s;" % (varName, strval))
|
||||||
if defaultValue is None:
|
if defaultValue is None:
|
||||||
return conversionCode
|
return conversionCode
|
||||||
|
|
||||||
|
@ -1075,20 +1086,22 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
"%s\n"
|
"%s\n"
|
||||||
" ${declName} = str;\n"
|
" ${declName} = str;\n"
|
||||||
"}\n" % CGIndenter(CGGeneric(getConversionCode("str"))).define(),
|
"}\n" % CGIndenter(CGGeneric(getConversionCode("str"))).define(),
|
||||||
declType, None, isOptional)
|
declType, None, isOptional, None)
|
||||||
|
|
||||||
if isOptional:
|
if isOptional:
|
||||||
declType = "Option<DOMString>"
|
declType = "Option<DOMString>"
|
||||||
|
initialValue = "None"
|
||||||
else:
|
else:
|
||||||
declType = "DOMString"
|
declType = "DOMString"
|
||||||
|
initialValue = None
|
||||||
|
|
||||||
return (
|
return (
|
||||||
"%s\n" %
|
"%s\n" %
|
||||||
#"const_cast<%s&>(${declName}) = &${holderName};" %
|
#"const_cast<%s&>(${declName}) = &${holderName};" %
|
||||||
(getConversionCode("${declName}")),
|
(getConversionCode("${declName}", isOptional)),
|
||||||
CGGeneric(declType), None, #CGGeneric("FakeDependentString"),
|
CGGeneric(declType), None, #CGGeneric("FakeDependentString"),
|
||||||
# No need to deal with Optional here; we have handled it already
|
False,
|
||||||
False)
|
initialValue)
|
||||||
|
|
||||||
if type.isEnum():
|
if type.isEnum():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1123,7 +1136,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
# ("${declName} = %sValues::%s" %
|
# ("${declName} = %sValues::%s" %
|
||||||
# (enum,
|
# (enum,
|
||||||
# getEnumValueName(defaultValue.value))))
|
# getEnumValueName(defaultValue.value))))
|
||||||
return (template, CGGeneric(enum), None, isOptional)
|
return (template, CGGeneric(enum), None, isOptional, None)
|
||||||
|
|
||||||
if type.isCallback():
|
if type.isCallback():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1143,7 +1156,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
"} else {\n"
|
"} else {\n"
|
||||||
" ${declName} = NULL;\n"
|
" ${declName} = NULL;\n"
|
||||||
"}" % haveCallable,
|
"}" % haveCallable,
|
||||||
CGGeneric("JSObject*"), None, isOptional)
|
CGGeneric("JSObject*"), None, isOptional, None)
|
||||||
|
|
||||||
if type.isAny():
|
if type.isAny():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1154,7 +1167,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
templateBody = "${declName} = ${val};"
|
templateBody = "${declName} = ${val};"
|
||||||
templateBody = handleDefaultNull(templateBody,
|
templateBody = handleDefaultNull(templateBody,
|
||||||
"${declName} = JS::NullValue()")
|
"${declName} = JS::NullValue()")
|
||||||
return (templateBody, CGGeneric("JS::Value"), None, isOptional)
|
return (templateBody, CGGeneric("JS::Value"), None, isOptional, None)
|
||||||
|
|
||||||
if type.isObject():
|
if type.isObject():
|
||||||
assert not isEnforceRange and not isClamp
|
assert not isEnforceRange and not isClamp
|
||||||
|
@ -1170,7 +1183,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
declType = CGGeneric("JSObject*")
|
declType = CGGeneric("JSObject*")
|
||||||
else:
|
else:
|
||||||
declType = CGGeneric("NonNull<JSObject>")
|
declType = CGGeneric("NonNull<JSObject>")
|
||||||
return (template, declType, None, isOptional)
|
return (template, declType, None, isOptional, None)
|
||||||
|
|
||||||
if type.isDictionary():
|
if type.isDictionary():
|
||||||
if failureCode is not None:
|
if failureCode is not None:
|
||||||
|
@ -1206,7 +1219,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
" return 0;\n"
|
" return 0;\n"
|
||||||
"}" % (selfRef, actualTypeName, selfRef, val))
|
"}" % (selfRef, actualTypeName, selfRef, val))
|
||||||
|
|
||||||
return (template, declType, None, False)
|
return (template, declType, None, False, None)
|
||||||
|
|
||||||
if not type.isPrimitive():
|
if not type.isPrimitive():
|
||||||
raise TypeError("Need conversion for argument type '%s'" % str(type))
|
raise TypeError("Need conversion for argument type '%s'" % str(type))
|
||||||
|
@ -1258,7 +1271,7 @@ for (uint32_t i = 0; i < length; ++i) {
|
||||||
" %s = %s;\n"
|
" %s = %s;\n"
|
||||||
"}" % (dataLoc, defaultStr))).define()
|
"}" % (dataLoc, defaultStr))).define()
|
||||||
|
|
||||||
return (template, declType, None, isOptional)
|
return (template, declType, None, isOptional, None)
|
||||||
|
|
||||||
def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
|
def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
|
||||||
argcAndIndex=None):
|
argcAndIndex=None):
|
||||||
|
@ -1271,7 +1284,7 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
|
||||||
replace ${argc} and ${index}, where ${index} is the index of this
|
replace ${argc} and ${index}, where ${index} is the index of this
|
||||||
argument (0-based) and ${argc} is the total number of arguments.
|
argument (0-based) and ${argc} is the total number of arguments.
|
||||||
"""
|
"""
|
||||||
(templateBody, declType, holderType, dealWithOptional) = templateTuple
|
(templateBody, declType, holderType, dealWithOptional, initialValue) = templateTuple
|
||||||
|
|
||||||
if dealWithOptional and argcAndIndex is None:
|
if dealWithOptional and argcAndIndex is None:
|
||||||
raise TypeError("Have to deal with optional things, but don't know how")
|
raise TypeError("Have to deal with optional things, but don't know how")
|
||||||
|
@ -1303,12 +1316,14 @@ def instantiateJSToNativeConversionTemplate(templateTuple, replacements,
|
||||||
(declType.define(), originalDeclName))
|
(declType.define(), originalDeclName))
|
||||||
mutableDeclType = CGWrapper(declType, pre="Optional< ", post=" >")
|
mutableDeclType = CGWrapper(declType, pre="Optional< ", post=" >")
|
||||||
declType = CGWrapper(mutableDeclType, pre="const ")
|
declType = CGWrapper(mutableDeclType, pre="const ")
|
||||||
result.append(
|
newDecl = [CGGeneric("let mut "),
|
||||||
CGList([CGGeneric("let mut "),
|
CGGeneric(originalDeclName),
|
||||||
CGGeneric(originalDeclName),
|
CGGeneric(": "),
|
||||||
CGGeneric(": "),
|
declType]
|
||||||
declType,
|
if initialValue:
|
||||||
CGGeneric(";")]))
|
newDecl.append(CGGeneric(" = " + initialValue))
|
||||||
|
newDecl.append(CGGeneric(";"))
|
||||||
|
result.append(CGList(newDecl))
|
||||||
|
|
||||||
conversion = CGGeneric(
|
conversion = CGGeneric(
|
||||||
string.Template(templateBody).substitute(replacements)
|
string.Template(templateBody).substitute(replacements)
|
||||||
|
@ -3020,6 +3035,51 @@ class CGPerSignatureCall(CGThing):
|
||||||
def define(self):
|
def define(self):
|
||||||
return (self.cgRoot.define() + "\n" + self.wrap_return_value())
|
return (self.cgRoot.define() + "\n" + self.wrap_return_value())
|
||||||
|
|
||||||
|
class CGSwitch(CGList):
|
||||||
|
"""
|
||||||
|
A class to generate code for a switch statement.
|
||||||
|
|
||||||
|
Takes three constructor arguments: an expression, a list of cases,
|
||||||
|
and an optional default.
|
||||||
|
|
||||||
|
Each case is a CGCase. The default is a CGThing for the body of
|
||||||
|
the default case, if any.
|
||||||
|
"""
|
||||||
|
def __init__(self, expression, cases, default=None):
|
||||||
|
CGList.__init__(self, [CGIndenter(c) for c in cases], "\n")
|
||||||
|
self.prepend(CGWrapper(CGGeneric(expression),
|
||||||
|
pre="match ", post=" {"));
|
||||||
|
if default is not None:
|
||||||
|
self.append(
|
||||||
|
CGIndenter(
|
||||||
|
CGWrapper(
|
||||||
|
CGIndenter(default),
|
||||||
|
pre="_ => {\n",
|
||||||
|
post="\n}"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.append(CGGeneric("}"))
|
||||||
|
|
||||||
|
class CGCase(CGList):
|
||||||
|
"""
|
||||||
|
A class to generate code for a case statement.
|
||||||
|
|
||||||
|
Takes three constructor arguments: an expression, a CGThing for
|
||||||
|
the body (allowed to be None if there is no body), and an optional
|
||||||
|
argument (defaulting to False) for whether to fall through.
|
||||||
|
"""
|
||||||
|
def __init__(self, expression, body, fallThrough=False):
|
||||||
|
CGList.__init__(self, [], "\n")
|
||||||
|
self.append(CGWrapper(CGGeneric(expression), post=" => {"))
|
||||||
|
bodyList = CGList([body], "\n")
|
||||||
|
if fallThrough:
|
||||||
|
raise TypeError("fall through required but unsupported")
|
||||||
|
#bodyList.append(CGGeneric('fail!("fall through unsupported"); /* Fall through */'))
|
||||||
|
self.append(CGIndenter(bodyList));
|
||||||
|
self.append(CGGeneric("}"))
|
||||||
|
|
||||||
class CGGetterCall(CGPerSignatureCall):
|
class CGGetterCall(CGPerSignatureCall):
|
||||||
"""
|
"""
|
||||||
A class to generate a native object getter call for a particular IDL
|
A class to generate a native object getter call for a particular IDL
|
||||||
|
@ -3976,7 +4036,7 @@ class CGDictionary(CGThing):
|
||||||
|
|
||||||
def getMemberType(self, memberInfo):
|
def getMemberType(self, memberInfo):
|
||||||
(member, (templateBody, declType,
|
(member, (templateBody, declType,
|
||||||
holderType, dealWithOptional)) = memberInfo
|
holderType, dealWithOptional, initialValue)) = memberInfo
|
||||||
# We can't handle having a holderType here
|
# We can't handle having a holderType here
|
||||||
assert holderType is None
|
assert holderType is None
|
||||||
if dealWithOptional:
|
if dealWithOptional:
|
||||||
|
@ -3985,7 +4045,7 @@ class CGDictionary(CGThing):
|
||||||
|
|
||||||
def getMemberConversion(self, memberInfo):
|
def getMemberConversion(self, memberInfo):
|
||||||
(member, (templateBody, declType,
|
(member, (templateBody, declType,
|
||||||
holderType, dealWithOptional)) = memberInfo
|
holderType, dealWithOptional, initialValue)) = memberInfo
|
||||||
replacements = { "val": "temp",
|
replacements = { "val": "temp",
|
||||||
"valPtr": "&temp",
|
"valPtr": "&temp",
|
||||||
"declName": ("self.%s" % member.identifier.name),
|
"declName": ("self.%s" % member.identifier.name),
|
||||||
|
@ -4138,6 +4198,7 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::document::Document', #XXXjdm
|
'dom::document::Document', #XXXjdm
|
||||||
'dom::bindings::utils::*',
|
'dom::bindings::utils::*',
|
||||||
'dom::bindings::conversions::*',
|
'dom::bindings::conversions::*',
|
||||||
|
'dom::blob::*', #XXXjdm
|
||||||
'dom::clientrect::*', #XXXjdm
|
'dom::clientrect::*', #XXXjdm
|
||||||
'dom::clientrectlist::*', #XXXjdm
|
'dom::clientrectlist::*', #XXXjdm
|
||||||
'dom::htmlcollection::*', #XXXjdm
|
'dom::htmlcollection::*', #XXXjdm
|
||||||
|
@ -4145,6 +4206,7 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::domparser::*', #XXXjdm
|
'dom::domparser::*', #XXXjdm
|
||||||
'dom::event::*', #XXXjdm
|
'dom::event::*', #XXXjdm
|
||||||
'dom::eventtarget::*', #XXXjdm
|
'dom::eventtarget::*', #XXXjdm
|
||||||
|
'dom::formdata::*', #XXXjdm
|
||||||
'script_task::task_from_context',
|
'script_task::task_from_context',
|
||||||
'dom::bindings::utils::EnumEntry',
|
'dom::bindings::utils::EnumEntry',
|
||||||
'dom::node::ScriptView',
|
'dom::node::ScriptView',
|
||||||
|
@ -4152,7 +4214,8 @@ class CGBindingRoot(CGThing):
|
||||||
'std::libc',
|
'std::libc',
|
||||||
'std::ptr',
|
'std::ptr',
|
||||||
'std::vec',
|
'std::vec',
|
||||||
'std::str'
|
'std::str',
|
||||||
|
'std::num',
|
||||||
],
|
],
|
||||||
[],
|
[],
|
||||||
curr)
|
curr)
|
||||||
|
|
14
src/components/script/dom/bindings/codegen/FormData.webidl
Normal file
14
src/components/script/dom/bindings/codegen/FormData.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://xhr.spec.whatwg.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*[Constructor(optional HTMLFormElement form)]*/
|
||||||
|
interface FormData {
|
||||||
|
void append(DOMString name, Blob value, optional DOMString filename);
|
||||||
|
void append(DOMString name, DOMString value);
|
||||||
|
};
|
|
@ -1,8 +1,10 @@
|
||||||
|
#include "BlobBinding.h"
|
||||||
#include "ClientRectBinding.h"
|
#include "ClientRectBinding.h"
|
||||||
#include "ClientRectListBinding.h"
|
#include "ClientRectListBinding.h"
|
||||||
#include "DOMParserBinding.h"
|
#include "DOMParserBinding.h"
|
||||||
#include "EventBinding.h"
|
#include "EventBinding.h"
|
||||||
#include "EventTargetBinding.h"
|
#include "EventTargetBinding.h"
|
||||||
|
#include "FormDataBinding.h"
|
||||||
#include "HTMLCollectionBinding.h"
|
#include "HTMLCollectionBinding.h"
|
||||||
#include "nsScriptNameSpaceManager.h"
|
#include "nsScriptNameSpaceManager.h"
|
||||||
|
|
||||||
|
@ -15,11 +17,13 @@ Register(nsScriptNameSpaceManager* aNameSpaceManager)
|
||||||
#define REGISTER_PROTO(_dom_class, _pref_check) \
|
#define REGISTER_PROTO(_dom_class, _pref_check) \
|
||||||
aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface, _pref_check);
|
aNameSpaceManager->RegisterDefineDOMInterface(NS_LITERAL_STRING(#_dom_class), _dom_class##Binding::DefineDOMInterface, _pref_check);
|
||||||
|
|
||||||
|
REGISTER_PROTO(Blob, nullptr);
|
||||||
REGISTER_PROTO(ClientRect, nullptr);
|
REGISTER_PROTO(ClientRect, nullptr);
|
||||||
REGISTER_PROTO(ClientRectList, nullptr);
|
REGISTER_PROTO(ClientRectList, nullptr);
|
||||||
REGISTER_PROTO(DOMParser, nullptr);
|
REGISTER_PROTO(DOMParser, nullptr);
|
||||||
REGISTER_PROTO(Event, nullptr);
|
REGISTER_PROTO(Event, nullptr);
|
||||||
REGISTER_PROTO(EventTarget, nullptr);
|
REGISTER_PROTO(EventTarget, nullptr);
|
||||||
|
REGISTER_PROTO(FormData, nullptr);
|
||||||
REGISTER_PROTO(HTMLCollection, nullptr);
|
REGISTER_PROTO(HTMLCollection, nullptr);
|
||||||
|
|
||||||
#undef REGISTER_PROTO
|
#undef REGISTER_PROTO
|
||||||
|
|
62
src/components/script/dom/bindings/formdata.rs
Normal file
62
src/components/script/dom/bindings/formdata.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
use dom::bindings::utils::{CacheableWrapper, WrapperCache, BindingObject, DerivedWrapper};
|
||||||
|
use dom::bindings::codegen::FormDataBinding;
|
||||||
|
use dom::formdata::FormData;
|
||||||
|
use script_task::{task_from_context, global_script_context};
|
||||||
|
|
||||||
|
use js::jsapi::{JSObject, JSContext, JSVal};
|
||||||
|
use js::glue::RUST_OBJECT_TO_JSVAL;
|
||||||
|
|
||||||
|
use std::cast;
|
||||||
|
|
||||||
|
impl FormData {
|
||||||
|
pub fn init_wrapper(@mut self) {
|
||||||
|
let script_context = global_script_context();
|
||||||
|
let cx = script_context.js_compartment.cx.ptr;
|
||||||
|
let owner = script_context.root_frame.get_ref().window;
|
||||||
|
let cache = owner.get_wrappercache();
|
||||||
|
let scope = cache.get_wrapper();
|
||||||
|
self.wrap_object_shared(cx, scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CacheableWrapper for FormData {
|
||||||
|
fn get_wrappercache(&mut self) -> &mut WrapperCache {
|
||||||
|
unsafe {
|
||||||
|
cast::transmute(&self.wrapper)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_object_shared(@mut self, cx: *JSContext, scope: *JSObject) -> *JSObject {
|
||||||
|
let mut unused = false;
|
||||||
|
FormDataBinding::Wrap(cx, scope, self, &mut unused)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BindingObject for FormData {
|
||||||
|
fn GetParentObject(&self, cx: *JSContext) -> @mut CacheableWrapper {
|
||||||
|
let script_context = task_from_context(cx);
|
||||||
|
unsafe {
|
||||||
|
(*script_context).root_frame.get_ref().window as @mut CacheableWrapper
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerivedWrapper for FormData {
|
||||||
|
fn wrap(&mut self, _cx: *JSContext, _scope: *JSObject, _vp: *mut JSVal) -> i32 {
|
||||||
|
fail!(~"nyi")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn wrap_shared(@mut self, cx: *JSContext, scope: *JSObject, vp: *mut JSVal) -> i32 {
|
||||||
|
let obj = self.wrap_object_shared(cx, scope);
|
||||||
|
if obj.is_null() {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
unsafe { *vp = RUST_OBJECT_TO_JSVAL(obj) };
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -380,6 +380,7 @@ pub mod prototypes {
|
||||||
HTMLCollection,
|
HTMLCollection,
|
||||||
Event,
|
Event,
|
||||||
EventTarget,
|
EventTarget,
|
||||||
|
FormData,
|
||||||
_ID_Count
|
_ID_Count
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,7 +583,7 @@ pub extern fn ThrowingConstructor(_cx: *JSContext, _argc: uint, _vp: *JSVal) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn initialize_global(global: *JSObject) {
|
pub fn initialize_global(global: *JSObject) {
|
||||||
let protoArray = @mut ([0 as *JSObject, ..6]); //XXXjdm prototypes::_ID_COUNT
|
let protoArray = @mut ([0 as *JSObject, ..7]); //XXXjdm prototypes::_ID_COUNT
|
||||||
unsafe {
|
unsafe {
|
||||||
//XXXjdm we should be storing the box pointer instead of the inner
|
//XXXjdm we should be storing the box pointer instead of the inner
|
||||||
let box = squirrel_away(protoArray);
|
let box = squirrel_away(protoArray);
|
||||||
|
|
17
src/components/script/dom/blob.rs
Normal file
17
src/components/script/dom/blob.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
use dom::bindings::utils::{WrapperCache};
|
||||||
|
|
||||||
|
pub struct Blob {
|
||||||
|
wrapper: WrapperCache
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Blob {
|
||||||
|
pub fn new() -> @mut Blob {
|
||||||
|
@mut Blob {
|
||||||
|
wrapper: WrapperCache::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
src/components/script/dom/formdata.rs
Normal file
38
src/components/script/dom/formdata.rs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
use dom::bindings::utils::{WrapperCache, DOMString, str};
|
||||||
|
use dom::blob::Blob;
|
||||||
|
use std::hashmap::HashMap;
|
||||||
|
|
||||||
|
enum FormDatum {
|
||||||
|
StringData(DOMString),
|
||||||
|
BlobData { blob: @mut Blob, name: DOMString }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct FormData {
|
||||||
|
data: HashMap<~str, FormDatum>,
|
||||||
|
wrapper: WrapperCache
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FormData {
|
||||||
|
pub fn new() -> @mut FormData {
|
||||||
|
@mut FormData {
|
||||||
|
data: HashMap::new(),
|
||||||
|
wrapper: WrapperCache::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Append(&mut self, name: DOMString, value: @mut Blob, filename: Option<DOMString>) {
|
||||||
|
let blob = BlobData {
|
||||||
|
blob: value,
|
||||||
|
name: filename.get_or_default(str(~"default"))
|
||||||
|
};
|
||||||
|
self.data.insert(name.to_str(), blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn Append_(&mut self, name: DOMString, value: DOMString) {
|
||||||
|
self.data.insert(name.to_str(), StringData(value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,6 +38,7 @@ pub mod dom {
|
||||||
pub mod clientrectlist;
|
pub mod clientrectlist;
|
||||||
pub mod domparser;
|
pub mod domparser;
|
||||||
pub mod htmlcollection;
|
pub mod htmlcollection;
|
||||||
|
pub mod formdata;
|
||||||
pub mod codegen {
|
pub mod codegen {
|
||||||
pub mod ClientRectBinding;
|
pub mod ClientRectBinding;
|
||||||
pub mod ClientRectListBinding;
|
pub mod ClientRectListBinding;
|
||||||
|
@ -45,8 +46,10 @@ pub mod dom {
|
||||||
pub mod EventBinding;
|
pub mod EventBinding;
|
||||||
pub mod EventTargetBinding;
|
pub mod EventTargetBinding;
|
||||||
pub mod HTMLCollectionBinding;
|
pub mod HTMLCollectionBinding;
|
||||||
|
pub mod FormDataBinding;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub mod blob;
|
||||||
pub mod characterdata;
|
pub mod characterdata;
|
||||||
pub mod clientrect;
|
pub mod clientrect;
|
||||||
pub mod clientrectlist;
|
pub mod clientrectlist;
|
||||||
|
@ -55,6 +58,7 @@ pub mod dom {
|
||||||
pub mod element;
|
pub mod element;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod eventtarget;
|
pub mod eventtarget;
|
||||||
|
pub mod formdata;
|
||||||
pub mod htmlcollection;
|
pub mod htmlcollection;
|
||||||
pub mod node;
|
pub mod node;
|
||||||
pub mod window;
|
pub mod window;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9e623124ee5508faac2666fae20c025ff6c52472
|
Subproject commit af080e2ab3ca871a6e77339eb752e59b3903b068
|
Loading…
Add table
Add a link
Reference in a new issue