Bug 1007878 part 3. Add JS-to-C++ conversion for MozMap. r=khuey

This commit is contained in:
Boris Zbarsky 2014-05-23 17:32:38 -04:00
parent 72c13f6d06
commit 2e69c899dd
3 changed files with 207 additions and 18 deletions

View File

@ -3648,8 +3648,8 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
declType = CGGeneric("JS::Rooted<JSObject*>")
declArgs = "cx"
else:
assert (isMember == "Sequence" or isMember == "Variadic" or
isMember == "Dictionary" or isMember == "OwningUnion")
assert (isMember in
("Sequence", "Variadic", "Dictionary", "OwningUnion", "MozMap"))
# We'll get traced by the sequence or dictionary or union tracer
declType = CGGeneric("JSObject*")
declArgs = None
@ -3702,7 +3702,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
else:
sequenceClass = "binding_detail::AutoSequence"
# XXXbz we can't include the index in the the sourceDescription, because
# XXXbz we can't include the index in the sourceDescription, because
# we don't really have a way to pass one in dynamically at runtime...
elementInfo = getJSToNativeConversionInfo(
elementType, descriptorProvider, isMember="Sequence",
@ -3722,6 +3722,16 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
else:
arrayRef = "${declName}"
elementConversion = string.Template(elementInfo.template).substitute({
"val": "temp",
"mutableVal": "&temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder"
})
# NOTE: Keep this in sync with variadic conversions as needed
templateBody = fill(
"""
@ -3748,25 +3758,16 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
$*{exceptionCode}
}
${elementType}& slot = *slotPtr;
$*{elementConversion}
}
""",
exceptionCode=exceptionCode,
notSequence=notSequence,
sequenceType=sequenceType,
arrayRef=arrayRef,
elementType=elementInfo.declType.define())
elementType=elementInfo.declType.define(),
elementConversion=elementConversion)
templateBody += indent(
string.Template(elementInfo.template).substitute({
"val": "temp",
"mutableVal": "&temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder"
}))
templateBody += "}\n"
templateBody = wrapObjectTemplate(templateBody, type,
"${declName}.SetNull();\n", notSequence)
# Sequence arguments that might contain traceable things need
@ -3786,6 +3787,110 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
dealWithOptional=isOptional,
holderArgs=holderArgs)
if type.isMozMap():
assert not isEnforceRange and not isClamp
if failureCode is None:
notMozMap = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
"%s" % (firstCap(sourceDescription), exceptionCode))
else:
notMozMap = failureCode
nullable = type.nullable()
# Be very careful not to change "type": we need it later
if nullable:
valueType = type.inner.inner
else:
valueType = type.inner
valueInfo = getJSToNativeConversionInfo(
valueType, descriptorProvider, isMember="MozMap",
exceptionCode=exceptionCode, lenientFloatCode=lenientFloatCode,
isCallbackReturnValue=isCallbackReturnValue,
sourceDescription="value in %s" % sourceDescription)
if valueInfo.dealWithOptional:
raise TypeError("Shouldn't have optional things in MozMap")
if valueInfo.holderType is not None:
raise TypeError("Shouldn't need holders for MozMap")
typeName = CGTemplatedType("MozMap", valueInfo.declType)
mozMapType = typeName.define()
if nullable:
typeName = CGTemplatedType("Nullable", typeName)
mozMapRef = "${declName}.SetValue()"
else:
mozMapRef = "${declName}"
valueConversion = string.Template(valueInfo.template).substitute({
"val": "temp",
"mutableVal": "&temp",
"declName": "slot",
# We only need holderName here to handle isExternal()
# interfaces, which use an internal holder for the
# conversion even when forceOwningType ends up true.
"holderName": "tempHolder"
})
templateBody = fill(
"""
${mozMapType} &mozMap = ${mozMapRef};
JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject());
JS::AutoIdArray ids(cx, JS_Enumerate(cx, mozMapObj));
if (!ids) {
$*{exceptionCode}
}
JS::Rooted<JS::Value> propNameValue(cx);
JS::Rooted<JS::Value> temp(cx);
JS::Rooted<jsid> curId(cx);
for (size_t i = 0; i < ids.length(); ++i) {
// Make sure we get the value before converting the name, since
// getting the value can trigger GC but our name is a dependent
// string.
curId = ids[i];
binding_detail::FakeDependentString propName;
if (!JS_GetPropertyById(cx, mozMapObj, curId, &temp) ||
!JS_IdToValue(cx, curId, &propNameValue) ||
!ConvertJSValueToString(cx, propNameValue, &propNameValue,
eStringify, eStringify, propName)) {
$*{exceptionCode}
}
${valueType}* slotPtr = mozMap.AddEntry(propName);
if (!slotPtr) {
JS_ReportOutOfMemory(cx);
$*{exceptionCode}
}
${valueType}& slot = *slotPtr;
$*{valueConversion}
}
""",
exceptionCode=exceptionCode,
mozMapType=mozMapType,
mozMapRef=mozMapRef,
valueType=valueInfo.declType.define(),
valueConversion=valueConversion)
templateBody = wrapObjectTemplate(templateBody, type,
"${declName}.SetNull();\n",
notMozMap)
# MozMap arguments that might contain traceable things need
# to get traced
if not isMember and typeNeedsRooting(valueType):
holderType = CGTemplatedType("MozMapRooter", valueInfo.declType)
# If our MozMap is nullable, this will set the Nullable to be
# not-null, but that's ok because we make an explicit SetNull() call
# on it as needed if our JS value is actually null.
holderArgs = "cx, &%s" % mozMapRef
else:
holderType = None
holderArgs = None
return JSToNativeConversionInfo(templateBody, declType=typeName,
holderType=holderType,
dealWithOptional=isOptional,
holderArgs=holderArgs)
if type.isUnion():
nullable = type.nullable()
if nullable:
@ -3858,6 +3963,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
else:
setDictionary = None
mozMapMemberTypes = filter(lambda t: t.isMozMap(), memberTypes)
if len(mozMapMemberTypes) > 0:
raise TypeError("We don't support MozMap in unions yet")
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
if len(objectMemberTypes) > 0:
assert len(objectMemberTypes) == 1
@ -4491,7 +4600,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not isEnforceRange and not isClamp
declArgs = None
if isMember in ("Variadic", "Sequence", "Dictionary"):
if isMember in ("Variadic", "Sequence", "Dictionary", "MozMap"):
# Rooting is handled by the sequence and dictionary tracers.
declType = "JS::Value"
else:
@ -5403,7 +5512,7 @@ def typeMatchesLambda(type, func):
return False
if type.nullable():
return typeMatchesLambda(type.inner, func)
if type.isSequence() or type.isArray():
if type.isSequence() or type.isMozMap() or type.isArray():
return typeMatchesLambda(type.inner, func)
if type.isUnion():
return any(typeMatchesLambda(t, func) for t in
@ -5586,6 +5695,8 @@ class CGCallGenerator(CGThing):
return True
if a.type.isSequence():
return True
if a.type.isMozMap():
return True
# isObject() types are always a JS::Rooted, whether
# nullable or not, and it turns out a const JS::Rooted
# is not very helpful at all (in particular, it won't

View File

@ -9,6 +9,7 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Date.h"
#include "mozilla/dom/MozMap.h"
#include "mozilla/dom/TypedArray.h"
#include "mozilla/dom/UnionTypes.h"
#include "mozilla/ErrorResult.h"
@ -401,6 +402,26 @@ public:
void PassSequenceOfSequences(const Sequence< Sequence<int32_t> >&);
void ReceiveSequenceOfSequences(nsTArray< nsTArray<int32_t> >&);
// MozMap types
void PassMozMap(const MozMap<int32_t> &);
void PassNullableMozMap(const Nullable< MozMap<int32_t> >&);
void PassMozMapOfNullableInts(const MozMap<Nullable<int32_t> >&);
void PassOptionalMozMapOfNullableInts(const Optional<MozMap<Nullable<int32_t> > > &);
void PassOptionalNullableMozMapOfNullableInts(const Optional<Nullable<MozMap<Nullable<int32_t> > > > &);
void PassCastableObjectMozMap(const MozMap< OwningNonNull<TestInterface> >&);
void PassNullableCastableObjectMozMap(const MozMap< nsRefPtr<TestInterface> > &);
void PassCastableObjectNullableMozMap(const Nullable< MozMap< OwningNonNull<TestInterface> > >&);
void PassNullableCastableObjectNullableMozMap(const Nullable< MozMap< nsRefPtr<TestInterface> > >&);
void PassOptionalMozMap(const Optional<MozMap<int32_t> >&);
void PassOptionalNullableMozMap(const Optional<Nullable<MozMap<int32_t> > >&);
void PassOptionalNullableMozMapWithDefaultValue(const Nullable< MozMap<int32_t> >&);
void PassOptionalObjectMozMap(const Optional<MozMap<OwningNonNull<TestInterface> > >&);
void PassExternalInterfaceMozMap(const MozMap<nsRefPtr<TestExternalInterface> >&);
void PassNullableExternalInterfaceMozMap(const MozMap<nsRefPtr<TestExternalInterface> >&);
void PassStringMozMap(const MozMap<nsString>&);
void PassByteStringMozMap(const MozMap<nsCString>&);
void PassMozMapOfMozMaps(const MozMap< MozMap<int32_t> >&);
// Typed array types
void PassArrayBuffer(const ArrayBuffer&);
void PassNullableArrayBuffer(const Nullable<ArrayBuffer>&);
@ -419,6 +440,8 @@ public:
void PassFloat64Array(const Float64Array&);
void PassSequenceOfArrayBuffers(const Sequence<ArrayBuffer>&);
void PassSequenceOfNullableArrayBuffers(const Sequence<Nullable<ArrayBuffer> >&);
void PassMozMapOfArrayBuffers(const MozMap<ArrayBuffer>&);
void PassMozMapOfNullableArrayBuffers(const MozMap<Nullable<ArrayBuffer> >&);
void PassVariadicTypedArray(const Sequence<Float32Array>&);
void PassVariadicNullableTypedArray(const Sequence<Nullable<Float32Array> >&);
JSObject* ReceiveUint8Array(JSContext*);
@ -483,6 +506,17 @@ public:
void PassSequenceOfNullableSequenceOfAny(JSContext*, const Sequence<Nullable<Sequence<JS::Value> > >&);
void PassNullableSequenceOfNullableSequenceOfAny(JSContext*, const Nullable<Sequence<Nullable<Sequence<JS::Value> > > >&);
void PassOptionalNullableSequenceOfNullableSequenceOfAny(JSContext*, const Optional<Nullable<Sequence<Nullable<Sequence<JS::Value> > > > >&);
void PassMozMapOfAny(JSContext*, const MozMap<JS::Value>&);
void PassNullableMozMapOfAny(JSContext*, const Nullable<MozMap<JS::Value> >&);
void PassOptionalMozMapOfAny(JSContext*, const Optional<MozMap<JS::Value> >&);
void PassOptionalNullableMozMapOfAny(JSContext*, const Optional<Nullable<MozMap<JS::Value> > >&);
void PassOptionalMozMapOfAnyWithDefaultValue(JSContext*, const Nullable<MozMap<JS::Value> >&);
void PassMozMapOfMozMapOfAny(JSContext*, const MozMap<MozMap<JS::Value> >&);
void PassMozMapOfNullableMozMapOfAny(JSContext*, const MozMap<Nullable<MozMap<JS::Value> > >&);
void PassNullableMozMapOfNullableMozMapOfAny(JSContext*, const Nullable<MozMap<Nullable<MozMap<JS::Value> > > >&);
void PassOptionalNullableMozMapOfNullableMozMapOfAny(JSContext*, const Optional<Nullable<MozMap<Nullable<MozMap<JS::Value>>>>>&);
void PassOptionalNullableMozMapOfNullableSequenceOfAny(JSContext*, const Optional<Nullable<MozMap<Nullable<Sequence<JS::Value>>>>>&);
void PassOptionalNullableSequenceOfNullableMozMapOfAny(JSContext*, const Optional<Nullable<Sequence<Nullable<MozMap<JS::Value>>>>>&);
JS::Value ReceiveAny(JSContext*);
// object types
@ -498,6 +532,7 @@ public:
void PassNullableSequenceOfObject(JSContext*, const Nullable<Sequence<JSObject*> >&);
void PassOptionalNullableSequenceOfNullableSequenceOfObject(JSContext*, const Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&);
void PassOptionalNullableSequenceOfNullableSequenceOfNullableObject(JSContext*, const Optional<Nullable<Sequence<Nullable<Sequence<JSObject*> > > > >&);
void PassMozMapOfObject(JSContext*, const MozMap<JSObject*>&);
JSObject* ReceiveObject(JSContext*);
JSObject* ReceiveNullableObject(JSContext*);
@ -579,6 +614,8 @@ public:
void PassSequenceOfNullableUnions(const Sequence<Nullable<OwningCanvasPatternOrCanvasGradient>>&);
void PassVariadicNullableUnion(const Sequence<Nullable<OwningCanvasPatternOrCanvasGradient>>&);
void PassMozMapOfUnions(const MozMap<OwningCanvasPatternOrCanvasGradient>&);
void PassMozMapOfUnions2(JSContext*, const MozMap<OwningObjectOrLong>&);
void ReceiveUnion(OwningCanvasPatternOrCanvasGradient&);
void ReceiveUnion2(JSContext*, OwningObjectOrLong&);
@ -599,6 +636,7 @@ public:
void PassOptionalNullableDate(const Optional<Nullable<Date> >&);
void PassOptionalNullableDateWithDefaultValue(const Nullable<Date>&);
void PassDateSequence(const Sequence<Date>&);
void PassDateMozMap(const MozMap<Date>&);
void PassNullableDateSequence(const Sequence<Nullable<Date> >&);
Date ReceiveDate();
Nullable<Date> ReceiveNullableDate();
@ -624,6 +662,7 @@ public:
void ReceiveNullableDictionary(JSContext*, Nullable<Dict>&);
void PassOtherDictionary(const GrandparentDict&);
void PassSequenceOfDictionaries(JSContext*, const Sequence<Dict>&);
void PassMozMapOfDictionaries(const MozMap<GrandparentDict>&);
void PassDictionaryOrLong(JSContext*, const Dict&);
void PassDictionaryOrLong(int32_t);
void PassDictContainingDict(JSContext*, const DictContainingDict&);

View File

@ -360,6 +360,26 @@ interface TestInterface {
void passSequenceOfSequences(sequence<sequence<long>> arg);
sequence<sequence<long>> receiveSequenceOfSequences();
// MozMap types
void passMozMap(MozMap<long> arg);
void passNullableMozMap(MozMap<long>? arg);
void passMozMapOfNullableInts(MozMap<long?> arg);
void passOptionalMozMapOfNullableInts(optional MozMap<long?> arg);
void passOptionalNullableMozMapOfNullableInts(optional MozMap<long?>? arg);
void passCastableObjectMozMap(MozMap<TestInterface> arg);
void passNullableCastableObjectMozMap(MozMap<TestInterface?> arg);
void passCastableObjectNullableMozMap(MozMap<TestInterface>? arg);
void passNullableCastableObjectNullableMozMap(MozMap<TestInterface?>? arg);
void passOptionalMozMap(optional MozMap<long> arg);
void passOptionalNullableMozMap(optional MozMap<long>? arg);
void passOptionalNullableMozMapWithDefaultValue(optional MozMap<long>? arg = null);
void passOptionalObjectMozMap(optional MozMap<TestInterface> arg);
void passExternalInterfaceMozMap(MozMap<TestExternalInterface> arg);
void passNullableExternalInterfaceMozMap(MozMap<TestExternalInterface?> arg);
void passStringMozMap(MozMap<DOMString> arg);
void passByteStringMozMap(MozMap<ByteString> arg);
void passMozMapOfMozMaps(MozMap<MozMap<long>> arg);
// Typed array types
void passArrayBuffer(ArrayBuffer arg);
void passNullableArrayBuffer(ArrayBuffer? arg);
@ -378,6 +398,8 @@ interface TestInterface {
void passFloat64Array(Float64Array arg);
void passSequenceOfArrayBuffers(sequence<ArrayBuffer> arg);
void passSequenceOfNullableArrayBuffers(sequence<ArrayBuffer?> arg);
void passMozMapOfArrayBuffers(MozMap<ArrayBuffer> arg);
void passMozMapOfNullableArrayBuffers(MozMap<ArrayBuffer?> arg);
void passVariadicTypedArray(Float32Array... arg);
void passVariadicNullableTypedArray(Float32Array?... arg);
Uint8Array receiveUint8Array();
@ -439,6 +461,17 @@ interface TestInterface {
void passSequenceOfNullableSequenceOfAny(sequence<sequence<any>?> arg);
void passNullableSequenceOfNullableSequenceOfAny(sequence<sequence<any>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfAny(optional sequence<sequence<any>?>? arg);
void passMozMapOfAny(MozMap<any> arg);
void passNullableMozMapOfAny(MozMap<any>? arg);
void passOptionalMozMapOfAny(optional MozMap<any> arg);
void passOptionalNullableMozMapOfAny(optional MozMap<any>? arg);
void passOptionalMozMapOfAnyWithDefaultValue(optional MozMap<any>? arg = null);
void passMozMapOfMozMapOfAny(MozMap<MozMap<any>> arg);
void passMozMapOfNullableMozMapOfAny(MozMap<MozMap<any>?> arg);
void passNullableMozMapOfNullableMozMapOfAny(MozMap<MozMap<any>?>? arg);
void passOptionalNullableMozMapOfNullableMozMapOfAny(optional MozMap<MozMap<any>?>? arg);
void passOptionalNullableMozMapOfNullableSequenceOfAny(optional MozMap<sequence<any>?>? arg);
void passOptionalNullableSequenceOfNullableMozMapOfAny(optional sequence<MozMap<any>?>? arg);
any receiveAny();
// object types
@ -454,6 +487,7 @@ interface TestInterface {
void passNullableSequenceOfObject(sequence<object>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfObject(optional sequence<sequence<object>?>? arg);
void passOptionalNullableSequenceOfNullableSequenceOfNullableObject(optional sequence<sequence<object?>?>? arg);
void passMozMapOfObject(MozMap<object> arg);
object receiveObject();
object? receiveNullableObject();
@ -527,6 +561,9 @@ interface TestInterface {
void passSequenceOfNullableUnions(sequence<(CanvasPattern or CanvasGradient)?> arg);
void passVariadicNullableUnion((CanvasPattern or CanvasGradient)?... arg);
void passMozMapOfUnions(MozMap<(CanvasPattern or CanvasGradient)> arg);
// XXXbz no move constructor on some unions
// void passMozMapOfUnions2(MozMap<(object or long)> arg);
(CanvasPattern or CanvasGradient) receiveUnion();
(object or long) receiveUnion2();
@ -546,6 +583,7 @@ interface TestInterface {
void passOptionalNullableDateWithDefaultValue(optional Date? arg = null);
void passDateSequence(sequence<Date> arg);
void passNullableDateSequence(sequence<Date?> arg);
void passDateMozMap(MozMap<Date> arg);
Date receiveDate();
Date? receiveNullableDate();
@ -572,6 +610,7 @@ interface TestInterface {
Dict? receiveNullableDictionary();
void passOtherDictionary(optional GrandparentDict x);
void passSequenceOfDictionaries(sequence<Dict> x);
void passMozMapOfDictionaries(MozMap<GrandparentDict> x);
// No support for nullable dictionaries inside a sequence (nor should there be)
// void passSequenceOfNullableDictionaries(sequence<Dict?> x);
void passDictionaryOrLong(optional Dict x);