Support dictionaries in unions.

Fixes #11612.
This commit is contained in:
Ms2ger 2017-01-20 15:51:13 +01:00
parent 1f76aa6ef7
commit 6a6f339b29
3 changed files with 39 additions and 12 deletions

View file

@ -758,7 +758,26 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
" _ => { %s },\n" " _ => { %s },\n"
"}" % (indent(failOrPropagate, 8), exceptionCode)) "}" % (indent(failOrPropagate, 8), exceptionCode))
return handleOptional(templateBody, declType, handleDefaultNull("None")) dictionaries = [
memberType
for memberType in type.unroll().flatMemberTypes
if memberType.isDictionary()
]
if dictionaries:
if defaultValue:
assert isinstance(defaultValue, IDLNullValue)
dictionary, = dictionaries
default = "%s::%s(%s::%s::empty(cx))" % (
union_native_type(type),
dictionary.name,
CGDictionary.makeModuleName(dictionary.inner),
CGDictionary.makeDictionaryName(dictionary.inner))
else:
default = None
else:
default = handleDefaultNull("None")
return handleOptional(templateBody, declType, default)
if type.isGeckoInterface(): if type.isGeckoInterface():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
@ -1076,8 +1095,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
handleDefaultNull("ptr::null_mut()")) handleDefaultNull("ptr::null_mut()"))
if type.isDictionary(): if type.isDictionary():
if failureCode is not None:
raise TypeError("Can't handle dictionaries when failureCode is not None")
# There are no nullable dictionaries # There are no nullable dictionaries
assert not type.nullable() assert not type.nullable()
@ -2217,6 +2234,7 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
""" """
imports = [ imports = [
'dom',
'dom::bindings::codegen::PrototypeList', 'dom::bindings::codegen::PrototypeList',
'dom::bindings::conversions::ConversionResult', 'dom::bindings::conversions::ConversionResult',
'dom::bindings::conversions::FromJSValConvertible', 'dom::bindings::conversions::FromJSValConvertible',
@ -2243,7 +2261,9 @@ def UnionTypes(descriptors, dictionaries, callbacks, typedefs, config):
# we need to wrap or unwrap them. # we need to wrap or unwrap them.
unionStructs = dict() unionStructs = dict()
for (t, descriptor, dictionary) in getAllTypes(descriptors, dictionaries, callbacks, typedefs): for (t, descriptor, dictionary) in getAllTypes(descriptors, dictionaries, callbacks, typedefs):
assert not descriptor or not dictionary if dictionary:
imports.append("%s::%s" % (CGDictionary.makeModuleName(dictionary),
CGDictionary.makeDictionaryName(dictionary)))
t = t.unroll() t = t.unroll()
if not t.isUnion(): if not t.isUnion():
continue continue
@ -4028,6 +4048,9 @@ def getUnionTypeTemplateVars(type, descriptorProvider):
elif type.isEnum(): elif type.isEnum():
name = type.inner.identifier.name name = type.inner.identifier.name
typeName = name typeName = name
elif type.isDictionary():
name = type.name
typeName = name
elif type.isSequence() or type.isMozMap(): elif type.isSequence() or type.isMozMap():
name = type.name name = type.name
inner = getUnionTypeTemplateVars(innerContainerType(type), descriptorProvider) inner = getUnionTypeTemplateVars(innerContainerType(type), descriptorProvider)
@ -4163,16 +4186,13 @@ class CGUnionConversionStruct(CGThing):
dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes) dictionaryMemberTypes = filter(lambda t: t.isDictionary(), memberTypes)
if len(dictionaryMemberTypes) > 0: if len(dictionaryMemberTypes) > 0:
raise TypeError("No support for unwrapping dictionaries as member " assert len(dictionaryMemberTypes) == 1
"of a union") typeName = dictionaryMemberTypes[0].name
dictionaryObject = CGGeneric(get_match(typeName))
names.append(typeName)
else: else:
dictionaryObject = None dictionaryObject = None
if callbackObject or dictionaryObject:
assert False, "Not currently supported"
else:
nonPlatformObject = None
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
if len(objectMemberTypes) > 0: if len(objectMemberTypes) > 0:
assert len(objectMemberTypes) == 1 assert len(objectMemberTypes) == 1
@ -4191,7 +4211,7 @@ class CGUnionConversionStruct(CGThing):
else: else:
mozMapObject = None mozMapObject = None
hasObjectTypes = interfaceObject or arrayObject or dateObject or nonPlatformObject or object or mozMapObject hasObjectTypes = interfaceObject or arrayObject or dateObject or object or mozMapObject
if hasObjectTypes: if hasObjectTypes:
# "object" is not distinguishable from other types # "object" is not distinguishable from other types
assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject) assert not object or not (interfaceObject or arrayObject or dateObject or callbackObject or mozMapObject)
@ -4203,6 +4223,11 @@ class CGUnionConversionStruct(CGThing):
if mozMapObject: if mozMapObject:
templateBody.append(mozMapObject) templateBody.append(mozMapObject)
conversions.append(CGIfWrapper("value.get().is_object()", templateBody)) conversions.append(CGIfWrapper("value.get().is_object()", templateBody))
if dictionaryObject:
assert not hasObjectTypes
conversions.append(dictionaryObject)
stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()] stringTypes = [t for t in memberTypes if t.isString() or t.isEnum()]
numericTypes = [t for t in memberTypes if t.isNumeric()] numericTypes = [t for t in memberTypes if t.isNumeric()]
booleanTypes = [t for t in memberTypes if t.isBoolean()] booleanTypes = [t for t in memberTypes if t.isBoolean()]

View file

@ -434,6 +434,7 @@ impl TestBindingMethods for TestBinding {
fn PassUnion6(&self, _: UnsignedLongOrBoolean) {} fn PassUnion6(&self, _: UnsignedLongOrBoolean) {}
fn PassUnion7(&self, _: StringSequenceOrUnsignedLong) {} fn PassUnion7(&self, _: StringSequenceOrUnsignedLong) {}
fn PassUnion8(&self, _: ByteStringSequenceOrLong) {} fn PassUnion8(&self, _: ByteStringSequenceOrLong) {}
fn PassUnion9(&self, _: UnionTypes::TestDictionaryOrLong) {}
fn PassUnionWithTypedef(&self, _: DocumentOrTestTypedef) {} fn PassUnionWithTypedef(&self, _: DocumentOrTestTypedef) {}
fn PassUnionWithTypedef2(&self, _: LongSequenceOrTestTypedef) {} fn PassUnionWithTypedef2(&self, _: LongSequenceOrTestTypedef) {}
#[allow(unsafe_code)] #[allow(unsafe_code)]

View file

@ -242,6 +242,7 @@ interface TestBinding {
void passUnion6((unsigned long or boolean) bool); void passUnion6((unsigned long or boolean) bool);
void passUnion7((sequence<DOMString> or unsigned long) arg); void passUnion7((sequence<DOMString> or unsigned long) arg);
void passUnion8((sequence<ByteString> or long) arg); void passUnion8((sequence<ByteString> or long) arg);
void passUnion9((TestDictionary or long) arg);
void passUnionWithTypedef((Document or TestTypedef) arg); void passUnionWithTypedef((Document or TestTypedef) arg);
void passUnionWithTypedef2((sequence<long> or TestTypedef) arg); void passUnionWithTypedef2((sequence<long> or TestTypedef) arg);
void passAny(any arg); void passAny(any arg);