mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Allow undefined
variants in IDL unions (#37042)
Testing: Includes a test which ensures that unions with a `undefined` variant compile Fixes https://github.com/servo/servo/issues/28679 Part of https://github.com/servo/servo/issues/30287 --------- Signed-off-by: Simon Wülker <simon.wuelker@arcor.de>
This commit is contained in:
parent
9c0c1cf30f
commit
fcc391d852
2 changed files with 37 additions and 10 deletions
|
@ -39,6 +39,7 @@ from WebIDL import (
|
|||
from Configuration import (
|
||||
Configuration,
|
||||
Descriptor,
|
||||
DescriptorProvider,
|
||||
MakeNativeName,
|
||||
MemberIsLegacyUnforgeable,
|
||||
getModuleFromObject,
|
||||
|
@ -617,16 +618,16 @@ class JSToNativeConversionInfo():
|
|||
|
||||
|
||||
def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
||||
isDefinitelyObject=False,
|
||||
isMember=False,
|
||||
isDefinitelyObject: bool = False,
|
||||
isMember: bool | str = False,
|
||||
isArgument=False,
|
||||
isAutoRooted=False,
|
||||
invalidEnumValueFatal=True,
|
||||
defaultValue=None,
|
||||
exceptionCode=None,
|
||||
allowTreatNonObjectAsNull=False,
|
||||
allowTreatNonObjectAsNull: bool = False,
|
||||
isCallbackReturnValue=False,
|
||||
sourceDescription="value"):
|
||||
sourceDescription="value") -> JSToNativeConversionInfo:
|
||||
"""
|
||||
Get a template for converting a JS value to a native object based on the
|
||||
given type and descriptor. If failureCode is given, then we're actually
|
||||
|
@ -5071,7 +5072,7 @@ class CGConstant(CGThing):
|
|||
return f"pub const {name}: {const_type} = {value};\n"
|
||||
|
||||
|
||||
def getUnionTypeTemplateVars(type, descriptorProvider):
|
||||
def getUnionTypeTemplateVars(type, descriptorProvider: DescriptorProvider):
|
||||
if type.isGeckoInterface():
|
||||
name = type.inner.identifier.name
|
||||
typeName = descriptorProvider.getDescriptor(name).returnType
|
||||
|
@ -5108,6 +5109,12 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
|
|||
elif type.isCallback():
|
||||
name = type.name
|
||||
typeName = f"{name}<D>"
|
||||
elif type.isUndefined():
|
||||
return {
|
||||
"name": type.name,
|
||||
"typeName": "()",
|
||||
"jsConversion": CGGeneric("if value.is_undefined() { Ok(Some(())) } else { Ok(None) }")
|
||||
}
|
||||
else:
|
||||
raise TypeError(f"Can't handle {type} in unions yet")
|
||||
|
||||
|
@ -5173,7 +5180,7 @@ impl{self.generic} Clone for {self.type}{self.genericSuffix} {{
|
|||
def manualImpl(self, t, templateVars):
|
||||
if t == "Clone":
|
||||
return self.manualImplClone(templateVars)
|
||||
raise f"Don't know how to impl {t} for union"
|
||||
raise ValueError(f"Don't know how to impl {t} for union")
|
||||
|
||||
def define(self):
|
||||
def getTypeWrapper(t):
|
||||
|
@ -5330,31 +5337,44 @@ class CGUnionConversionStruct(CGThing):
|
|||
stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()]
|
||||
numericTypes = [t for t in memberTypes if t.isNumeric()]
|
||||
booleanTypes = [t for t in memberTypes if t.isBoolean()]
|
||||
if stringTypes or numericTypes or booleanTypes:
|
||||
numUndefinedVariants = [t.isUndefined() for t in memberTypes].count(True)
|
||||
if stringTypes or numericTypes or booleanTypes or numUndefinedVariants != 0:
|
||||
assert len(stringTypes) <= 1
|
||||
assert len(numericTypes) <= 1
|
||||
assert len(booleanTypes) <= 1
|
||||
assert numUndefinedVariants <= 1
|
||||
|
||||
def getStringOrPrimitiveConversion(memberType):
|
||||
typename = get_name(memberType)
|
||||
return CGGeneric(get_match(typename))
|
||||
|
||||
other = []
|
||||
stringConversion = list(map(getStringOrPrimitiveConversion, stringTypes))
|
||||
numericConversion = list(map(getStringOrPrimitiveConversion, numericTypes))
|
||||
booleanConversion = list(map(getStringOrPrimitiveConversion, booleanTypes))
|
||||
undefinedConversion = CGGeneric("return Ok(ConversionResult::Success(Self::Undefined(())));")
|
||||
|
||||
if stringConversion:
|
||||
if booleanConversion:
|
||||
other.append(CGIfWrapper("value.get().is_boolean()", booleanConversion[0]))
|
||||
if numericConversion:
|
||||
other.append(CGIfWrapper("value.get().is_number()", numericConversion[0]))
|
||||
if numUndefinedVariants != 0:
|
||||
other.append(CGIfWrapper("value.get().is_undefined()", undefinedConversion))
|
||||
other.append(stringConversion[0])
|
||||
elif numericConversion:
|
||||
if booleanConversion:
|
||||
other.append(CGIfWrapper("value.get().is_boolean()", booleanConversion[0]))
|
||||
if numUndefinedVariants != 0:
|
||||
other.append(CGIfWrapper("value.get().is_undefined()", undefinedConversion))
|
||||
other.append(numericConversion[0])
|
||||
else:
|
||||
assert booleanConversion
|
||||
elif booleanConversion:
|
||||
if numUndefinedVariants != 0:
|
||||
other.append(CGIfWrapper("value.get().is_undefined()", undefinedConversion))
|
||||
other.append(booleanConversion[0])
|
||||
else:
|
||||
assert numUndefinedVariants != 0
|
||||
other.append(undefinedConversion)
|
||||
conversions.append(CGList(other, "\n\n"))
|
||||
conversions.append(CGGeneric(
|
||||
f'Ok(ConversionResult::Failure("argument could not be converted to any of: {", ".join(names)}".into()))'
|
||||
|
@ -5376,6 +5396,10 @@ class CGUnionConversionStruct(CGThing):
|
|||
post="\n}")
|
||||
|
||||
def try_method(self, t):
|
||||
if t.isUndefined():
|
||||
# undefined does not require a conversion method, so we don't generate one
|
||||
return CGGeneric("")
|
||||
|
||||
templateVars = getUnionTypeTemplateVars(t, self.descriptorProvider)
|
||||
actualType = templateVars["typeName"]
|
||||
if type_needs_tracing(t):
|
||||
|
@ -7151,7 +7175,7 @@ impl{self.generic} Clone for {self.makeClassName(self.dictionary)}{self.genericS
|
|||
def manualImpl(self, t):
|
||||
if t == "Clone":
|
||||
return self.manualImplClone()
|
||||
raise f"Don't know how to impl {t} for dicts."
|
||||
raise ValueError(f"Don't know how to impl {t} for dicts.")
|
||||
|
||||
def struct(self):
|
||||
d = self.dictionary
|
||||
|
|
|
@ -627,3 +627,6 @@ dictionary NotUsedAnyWhereElse {};
|
|||
dictionary RecordFieldWithUnionInside {
|
||||
record<USVString, (USVString or NotUsedAnyWhereElse)> recordWithUnionField;
|
||||
};
|
||||
|
||||
// https://github.com/servo/servo/issues/28679
|
||||
typedef (USVString or undefined) UnionWithUndefinedVariant;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue