Bug 829248. Implement basic support for [TreatUndefinedAs=Missing] in WebIDL. r=khuey

This does not add support for [TreatUndefinedAs=Missing] in overloaded
methods, since it's not clear what that should really look like.

This also does not require that [TreatUndefinedAs=Missing] on an
argument force it on all later arguments, since it's not clear that we
want that long-term.
This commit is contained in:
Boris Zbarsky 2013-06-05 20:51:21 -04:00
Родитель 29483ee344
Коммит c9eca87821
6 изменённых файлов: 66 добавлений и 29 удалений

Просмотреть файл

@ -2433,7 +2433,8 @@ class JSToNativeConversionInfo():
${declName} replaced by the declaration's name
${haveValue} replaced by an expression that evaluates to a boolean
for whether we have a JS::Value. Only used when
defaultValue is not None.
defaultValue is not None or when True is passed for
checkForValue to instantiateJSToNativeConversion.
declType: A CGThing representing the native C++ type we're converting
to. This is allowed to be None if the conversion code is
@ -3197,7 +3198,10 @@ for (uint32_t i = 0; i < length; ++i) {
treatAs = {
"Default": "eStringify",
"EmptyString": "eEmpty",
"Null": "eNull"
"Null": "eNull",
# For Missing it doesn't matter what we use here, since we'll never
# call ConvertJSValueToString on undefined in that case.
"Missing": "eStringify"
}
if type.nullable():
# For nullable strings null becomes a null string.
@ -3207,8 +3211,6 @@ for (uint32_t i = 0; i < length; ++i) {
if treatUndefinedAs == "Default":
treatUndefinedAs = "Null"
nullBehavior = treatAs[treatNullAs]
if treatUndefinedAs == "Missing":
raise TypeError("We don't support [TreatUndefinedAs=Missing]")
undefinedBehavior = treatAs[treatUndefinedAs]
def getConversionCode(varName):
@ -3559,22 +3561,21 @@ for (uint32_t i = 0; i < length; ++i) {
return JSToNativeConversionInfo(template, declType=declType,
dealWithOptional=isOptional)
def instantiateJSToNativeConversion(info, replacements, argcAndIndex=None):
def instantiateJSToNativeConversion(info, replacements, checkForValue=False):
"""
Take a JSToNativeConversionInfo as returned by getJSToNativeConversionInfo
and a set of replacements as required by the strings in such an object, and
generate code to convert into stack C++ types.
If argcAndIndex is not None it must be a dict that can be used to
replace ${argc} and ${index}, where ${index} is the index of this
argument (0-based) and ${argc} is the total number of arguments.
If checkForValue is True, then the conversion will get wrapped in
a check for ${haveValue}.
"""
(templateBody, declType, holderType, dealWithOptional) = (
info.template, info.declType, info.holderType, info.dealWithOptional)
if dealWithOptional and argcAndIndex is None:
if dealWithOptional and not checkForValue:
raise TypeError("Have to deal with optional things, but don't know how")
if argcAndIndex is not None and declType is None:
if checkForValue and declType is None:
raise TypeError("Need to predeclare optional things, so they will be "
"outside the check for big enough arg count!");
@ -3623,7 +3624,7 @@ def instantiateJSToNativeConversion(info, replacements, argcAndIndex=None):
string.Template(templateBody).substitute(replacements)
)
if argcAndIndex is not None:
if checkForValue:
if dealWithOptional:
declConstruct = CGIndenter(
CGGeneric("%s.Construct(%s);" %
@ -3644,8 +3645,8 @@ def instantiateJSToNativeConversion(info, replacements, argcAndIndex=None):
conversion = CGList(
[CGGeneric(
string.Template("if (${index} < ${argc}) {").substitute(
argcAndIndex
string.Template("if (${haveValue}) {").substitute(
replacements
)),
declConstruct,
holderConstruct,
@ -3710,9 +3711,12 @@ class CGArgumentConverter(CGThing):
self.replacementVariables["valMutableHandle"] = (
"JS::MutableHandle<JS::Value>::fromMarkedLocation(%s)" %
self.replacementVariables["valPtr"])
if argument.defaultValue:
self.replacementVariables["haveValue"] = string.Template(
"${index} < ${argc}").substitute(replacer)
haveValueCheck = string.Template("${index} < ${argc}").substitute(replacer)
if argument.treatUndefinedAs == "Missing":
haveValueCheck = (haveValueCheck +
(" && !%s.isUndefined()" %
self.replacementVariables["valHandle"]))
self.replacementVariables["haveValue"] = haveValueCheck
self.descriptorProvider = descriptorProvider
if self.argument.optional and not self.argument.defaultValue:
self.argcAndIndex = replacer
@ -3742,7 +3746,7 @@ class CGArgumentConverter(CGThing):
return instantiateJSToNativeConversion(
typeConversion,
self.replacementVariables,
self.argcAndIndex).define()
self.argcAndIndex is not None).define()
# Variadic arguments get turned into a sequence.
if typeConversion.dealWithOptional:
@ -4707,6 +4711,15 @@ class CGMethodCall(CGThing):
CGWrapper(CGIndenter(CGGeneric(code)), pre="\n", post="\n"))
return
# We don't handle [TreatUndefinedAs=Missing] arguments in overload
# resolution yet.
for (_, sigArgs) in signatures:
for arg in sigArgs:
if arg.treatUndefinedAs == "Missing":
raise TypeError("No support for [TreatUndefinedAs=Missing] "
"handling in overload resolution yet: %s" %
arg.location)
# Need to find the right overload
maxArgCount = method.maxArgCount
allowedArgCounts = method.allowedArgCounts

Просмотреть файл

@ -398,25 +398,33 @@ class IDLObjectWithIdentifier(IDLObject):
[self.location])
self.treatNullAs = value
elif identifier == "TreatUndefinedAs":
if not self.type.isString():
raise WebIDLError("[TreatUndefinedAs] is only allowed on "
"arguments or attributes whose type is "
"DOMString or DOMString?",
[self.location])
if isDictionaryMember:
raise WebIDLError("[TreatUndefinedAs] is not allowed for "
"dictionary members", [self.location])
if value == 'Null':
if not self.type.nullable():
raise WebIDLError("[TreatUndefinedAs=Null] is only "
"allowed on arguments whose type is "
"DOMString?", [self.location])
elif value == 'Missing':
if value == 'Missing':
if not isOptional:
raise WebIDLError("[TreatUndefinedAs=Missing] is only "
"allowed on optional arguments",
[self.location])
elif value != 'EmptyString':
elif value == 'Null':
if not self.type.isString():
raise WebIDLError("[TreatUndefinedAs=Null] is only "
"allowed on arguments or "
"attributes whose type is "
"DOMString or DOMString?",
[self.location])
if not self.type.nullable():
raise WebIDLError("[TreatUndefinedAs=Null] is only "
"allowed on arguments whose type "
"is DOMString?", [self.location])
elif value == 'EmptyString':
if not self.type.isString():
raise WebIDLError("[TreatUndefinedAs=EmptyString] "
"is only allowed on arguments or "
"attributes whose type is "
"DOMString or DOMString?",
[self.location])
else:
raise WebIDLError("[TreatUndefinedAs] must take the "
"identifiers EmptyString or Null or "
"Missing", [self.location])

Просмотреть файл

@ -156,7 +156,9 @@ public:
void PassByte(int8_t);
int8_t ReceiveByte();
void PassOptionalByte(const Optional<int8_t>&);
void PassOptionalUndefinedMissingByte(const Optional<int8_t>&);
void PassOptionalByteWithDefault(int8_t);
void PassOptionalUndefinedMissingByteWithDefault(int8_t);
void PassNullableByte(const Nullable<int8_t>&);
void PassOptionalNullableByte(const Optional< Nullable<int8_t> >&);
void PassVariadicByte(const Sequence<int8_t>&);
@ -400,7 +402,9 @@ public:
void PassString(const nsAString&);
void PassNullableString(const nsAString&);
void PassOptionalString(const Optional<nsAString>&);
void PassOptionalUndefinedMissingString(const Optional<nsAString>&);
void PassOptionalStringWithDefaultValue(const nsAString&);
void PassOptionalUndefinedMissingStringWithDefaultValue(const nsAString&);
void PassOptionalNullableString(const Optional<nsAString>&);
void PassOptionalNullableStringWithDefaultValue(const nsAString&);
void PassVariadicString(const Sequence<nsString>&);

Просмотреть файл

@ -118,7 +118,9 @@ interface TestInterface {
void passByte(byte arg);
byte receiveByte();
void passOptionalByte(optional byte arg);
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
void passOptionalByteWithDefault(optional byte arg = 0);
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
void passNullableByte(byte? arg);
void passOptionalNullableByte(optional byte? arg);
void passVariadicByte(byte... arg);
@ -368,7 +370,9 @@ interface TestInterface {
void passString(DOMString arg);
void passNullableString(DOMString? arg);
void passOptionalString(optional DOMString arg);
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
void passOptionalNullableString(optional DOMString? arg);
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
void passVariadicString(DOMString... arg);

Просмотреть файл

@ -23,7 +23,9 @@ interface TestExampleInterface {
void passByte(byte arg);
byte receiveByte();
void passOptionalByte(optional byte arg);
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
void passOptionalByteWithDefault(optional byte arg = 0);
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
void passNullableByte(byte? arg);
void passOptionalNullableByte(optional byte? arg);
void passVariadicByte(byte... arg);
@ -266,7 +268,9 @@ interface TestExampleInterface {
void passString(DOMString arg);
void passNullableString(DOMString? arg);
void passOptionalString(optional DOMString arg);
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
void passOptionalNullableString(optional DOMString? arg);
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
void passVariadicString(DOMString... arg);

Просмотреть файл

@ -35,7 +35,9 @@ interface TestJSImplInterface {
void passByte(byte arg);
byte receiveByte();
void passOptionalByte(optional byte arg);
void passOptionalUndefinedMissingByte([TreatUndefinedAs=Missing] optional byte arg);
void passOptionalByteWithDefault(optional byte arg = 0);
void passOptionalUndefinedMissingByteWithDefault([TreatUndefinedAs=Missing] optional byte arg = 0);
void passNullableByte(byte? arg);
void passOptionalNullableByte(optional byte? arg);
void passVariadicByte(byte... arg);
@ -289,7 +291,9 @@ interface TestJSImplInterface {
void passString(DOMString arg);
void passNullableString(DOMString? arg);
void passOptionalString(optional DOMString arg);
void passOptionalUndefinedMissingString([TreatUndefinedAs=Missing] optional DOMString arg);
void passOptionalStringWithDefaultValue(optional DOMString arg = "abc");
void passOptionalUndefinedMissingStringWithDefaultValue([TreatUndefinedAs=Missing] optional DOMString arg = "abc");
void passOptionalNullableString(optional DOMString? arg);
void passOptionalNullableStringWithDefaultValue(optional DOMString? arg = null);
void passVariadicString(DOMString... arg);