Rename the MozMap C++ type to "record" and give it a template parameter for the key type

This commit is contained in:
JustOff 2019-03-13 20:04:13 +02:00 • committed by Roy Tam
commit 6196fdda47
7 changed files with 145 additions and 126 deletions

View file

@ -49,7 +49,7 @@ namespace mozilla {
enum UseCounter : int16_t; enum UseCounter : int16_t;
namespace dom { namespace dom {
template<typename DataType> class MozMap; template<typename KeyType, typename ValueType> class Record;
nsresult nsresult
UnwrapArgImpl(JS::Handle<JSObject*> src, const nsIID& iid, void** ppArg); UnwrapArgImpl(JS::Handle<JSObject*> src, const nsIID& iid, void** ppArg);
@ -2293,25 +2293,26 @@ public:
} }
}; };
template<typename T> template<typename K, typename V>
void TraceMozMap(JSTracer* trc, MozMap<T>& map) void TraceRecord(JSTracer* trc, Record<K, V>& record)
{ {
for (auto& entry : map.Entries()) { for (auto& entry : record.Entries()) {
// Act like it's a one-element sequence to leverage all that infrastructure. // Act like it's a one-element sequence to leverage all that infrastructure.
SequenceTracer<T>::TraceSequence(trc, &entry.mValue, &entry.mValue + 1); SequenceTracer<V>::TraceSequence(trc, &entry.mValue, &entry.mValue + 1);
} }
} }
// sequence<MozMap> // sequence<record>
template<typename T> template<typename K, typename V>
class SequenceTracer<MozMap<T>, false, false, false> class SequenceTracer<Record<K, V>, false, false, false>
{ {
explicit SequenceTracer() = delete; // Should never be instantiated explicit SequenceTracer() = delete; // Should never be instantiated
public: public:
static void TraceSequence(JSTracer* trc, MozMap<T>* seqp, MozMap<T>* end) { static void TraceSequence(JSTracer* trc, Record<K, V>* seqp,
Record<K, V>* end) {
for (; seqp != end; ++seqp) { for (; seqp != end; ++seqp) {
TraceMozMap(trc, *seqp); TraceRecord(trc, *seqp);
} }
} }
}; };
@ -2389,51 +2390,51 @@ public:
SequenceType mSequenceType; SequenceType mSequenceType;
}; };
// Rooter class for MozMap; this is what we mostly use in the codegen. // Rooter class for Record; this is what we mostly use in the codegen.
template<typename T> template<typename K, typename V>
class MOZ_RAII MozMapRooter final : private JS::CustomAutoRooter class MOZ_RAII RecordRooter final : private JS::CustomAutoRooter
{ {
public: public:
MozMapRooter(JSContext *aCx, MozMap<T>* aMozMap RecordRooter(JSContext *aCx, Record<K, V>* aRecord
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT), : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
mMozMap(aMozMap), mRecord(aRecord),
mMozMapType(eMozMap) mRecordType(eRecord)
{ {
} }
MozMapRooter(JSContext *aCx, Nullable<MozMap<T>>* aMozMap RecordRooter(JSContext *aCx, Nullable<Record<K, V>>* aRecord
MOZ_GUARD_OBJECT_NOTIFIER_PARAM) MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
: JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT), : JS::CustomAutoRooter(aCx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_TO_PARENT),
mNullableMozMap(aMozMap), mNullableRecord(aRecord),
mMozMapType(eNullableMozMap) mRecordType(eNullableRecord)
{ {
} }
private: private:
enum MozMapType { enum RecordType {
eMozMap, eRecord,
eNullableMozMap eNullableRecord
}; };
virtual void trace(JSTracer *trc) override virtual void trace(JSTracer *trc) override
{ {
if (mMozMapType == eMozMap) { if (mRecordType == eRecord) {
TraceMozMap(trc, *mMozMap); TraceRecord(trc, *mRecord);
} else { } else {
MOZ_ASSERT(mMozMapType == eNullableMozMap); MOZ_ASSERT(mRecordType == eNullableRecord);
if (!mNullableMozMap->IsNull()) { if (!mNullableRecord->IsNull()) {
TraceMozMap(trc, mNullableMozMap->Value()); TraceRecord(trc, mNullableRecord->Value());
} }
} }
} }
union { union {
MozMap<T>* mMozMap; Record<K, V>* mRecord;
Nullable<MozMap<T>>* mNullableMozMap; Nullable<Record<K, V>>* mNullableRecord;
}; };
MozMapType mMozMapType; RecordType mRecordType;
}; };
template<typename T> template<typename T>

View file

@ -996,6 +996,8 @@ class CGElseChain(CGThing):
class CGTemplatedType(CGWrapper): class CGTemplatedType(CGWrapper):
def __init__(self, templateName, child, isConst=False, isReference=False): def __init__(self, templateName, child, isConst=False, isReference=False):
if isinstance(child, list):
child = CGList(child, ", ")
const = "const " if isConst else "" const = "const " if isConst else ""
pre = "%s%s<" % (const, templateName) pre = "%s%s<" % (const, templateName)
ref = "&" if isReference else "" ref = "&" if isReference else ""
@ -1173,10 +1175,10 @@ class CGHeaders(CGWrapper):
bindingHeaders.add("mozilla/dom/PrimitiveConversions.h") bindingHeaders.add("mozilla/dom/PrimitiveConversions.h")
elif unrolled.isRecord(): elif unrolled.isRecord():
if dictionary or jsImplementedDescriptors: if dictionary or jsImplementedDescriptors:
declareIncludes.add("mozilla/dom/MozMap.h") declareIncludes.add("mozilla/dom/Record.h")
else: else:
bindingHeaders.add("mozilla/dom/MozMap.h") bindingHeaders.add("mozilla/dom/Record.h")
# Also add headers for the type the MozMap is # Also add headers for the type the record is
# parametrized over, if needed. # parametrized over, if needed.
addHeadersForType((t.inner, dictionary)) addHeadersForType((t.inner, dictionary))
@ -1389,7 +1391,7 @@ def UnionTypes(unionTypes, config):
# code. # code.
headers.add(CGHeaders.getDeclarationFilename(f.callback)) headers.add(CGHeaders.getDeclarationFilename(f.callback))
elif f.isRecord(): elif f.isRecord():
headers.add("mozilla/dom/MozMap.h") headers.add("mozilla/dom/Record.h")
# And add headers for the type we're parametrized over # And add headers for the type we're parametrized over
addHeadersForType(f.inner) addHeadersForType(f.inner)
@ -1449,8 +1451,8 @@ def UnionConversions(unionTypes, config):
elif f.isPrimitive(): elif f.isPrimitive():
headers.add("mozilla/dom/PrimitiveConversions.h") headers.add("mozilla/dom/PrimitiveConversions.h")
elif f.isRecord(): elif f.isRecord():
headers.add("mozilla/dom/MozMap.h") headers.add("mozilla/dom/Record.h")
# And the internal type of the MozMap # And the internal type of the record
addHeadersForType(f.inner) addHeadersForType(f.inner)
# We plan to include UnionTypes.h no matter what, so it's # We plan to include UnionTypes.h no matter what, so it's
@ -4370,6 +4372,13 @@ def handleDefaultStringValue(defaultValue, method):
} }
def recordKeyDeclType(recordType):
assert recordType.keyType.isString()
if recordType.keyType.isByteString():
return CGGeneric("nsCString")
return CGGeneric("nsString")
# If this function is modified, modify CGNativeMember.getArg and # If this function is modified, modify CGNativeMember.getArg and
# CGNativeMember.getRetvalInfo accordingly. The latter cares about the decltype # CGNativeMember.getRetvalInfo accordingly. The latter cares about the decltype
# and holdertype we end up using, because it needs to be able to return the code # and holdertype we end up using, because it needs to be able to return the code
@ -4564,7 +4573,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
declArgs = "cx" declArgs = "cx"
else: else:
assert (isMember in assert (isMember in
("Sequence", "Variadic", "Dictionary", "OwningUnion", "MozMap")) ("Sequence", "Variadic", "Dictionary", "OwningUnion", "Record"))
# We'll get traced by the sequence or dictionary or union tracer # We'll get traced by the sequence or dictionary or union tracer
declType = CGGeneric("JSObject*") declType = CGGeneric("JSObject*")
declArgs = None declArgs = None
@ -4733,36 +4742,38 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if type.isRecord(): if type.isRecord():
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
if failureCode is None: if failureCode is None:
notMozMap = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n' notRecord = ('ThrowErrorMessage(cx, MSG_NOT_OBJECT, "%s");\n'
"%s" % (firstCap(sourceDescription), exceptionCode)) "%s" % (firstCap(sourceDescription), exceptionCode))
else: else:
notMozMap = failureCode notRecord = failureCode
nullable = type.nullable() nullable = type.nullable()
# Be very careful not to change "type": we need it later # Be very careful not to change "type": we need it later
if nullable: if nullable:
valueType = type.inner.inner recordType = type.inner
else: else:
valueType = type.inner recordType = type
valueType = recordType.inner
valueInfo = getJSToNativeConversionInfo( valueInfo = getJSToNativeConversionInfo(
valueType, descriptorProvider, isMember="MozMap", valueType, descriptorProvider, isMember="Record",
exceptionCode=exceptionCode, lenientFloatCode=lenientFloatCode, exceptionCode=exceptionCode, lenientFloatCode=lenientFloatCode,
isCallbackReturnValue=isCallbackReturnValue, isCallbackReturnValue=isCallbackReturnValue,
sourceDescription="value in %s" % sourceDescription, sourceDescription="value in %s" % sourceDescription,
nestingLevel=incrementNestingLevel()) nestingLevel=incrementNestingLevel())
if valueInfo.dealWithOptional: if valueInfo.dealWithOptional:
raise TypeError("Shouldn't have optional things in MozMap") raise TypeError("Shouldn't have optional things in record")
if valueInfo.holderType is not None: if valueInfo.holderType is not None:
raise TypeError("Shouldn't need holders for MozMap") raise TypeError("Shouldn't need holders for record")
typeName = CGTemplatedType("MozMap", valueInfo.declType) declType = CGTemplatedType("Record", [recordKeyDeclType(recordType),
mozMapType = typeName.define() valueInfo.declType])
typeName = declType.define()
if nullable: if nullable:
typeName = CGTemplatedType("Nullable", typeName) declType = CGTemplatedType("Nullable", declType)
mozMapRef = "${declName}.SetValue()" recordRef = "${declName}.SetValue()"
else: else:
mozMapRef = "${declName}" recordRef = "${declName}"
valueConversion = string.Template(valueInfo.template).substitute({ valueConversion = string.Template(valueInfo.template).substitute({
"val": "temp", "val": "temp",
@ -4777,17 +4788,17 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
templateBody = fill( templateBody = fill(
""" """
auto& mozMapEntries = ${mozMapRef}.Entries(); auto& recordEntries = ${recordRef}.Entries();
JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject()); JS::Rooted<JSObject*> recordObj(cx, &$${val}.toObject());
JS::AutoIdVector ids(cx); JS::AutoIdVector ids(cx);
// Keep skipping symbols until // Keep skipping symbols until
// https://github.com/heycam/webidl/issues/294 is sorted out. // https://github.com/heycam/webidl/issues/294 is sorted out.
if (!js::GetPropertyKeys(cx, mozMapObj, if (!js::GetPropertyKeys(cx, recordObj,
JSITER_OWNONLY | JSITER_HIDDEN, &ids)) { JSITER_OWNONLY | JSITER_HIDDEN, &ids)) {
$*{exceptionCode} $*{exceptionCode}
} }
if (!mozMapEntries.SetCapacity(ids.length(), mozilla::fallible)) { if (!recordEntries.SetCapacity(ids.length(), mozilla::fallible)) {
JS_ReportOutOfMemory(cx); JS_ReportOutOfMemory(cx);
$*{exceptionCode} $*{exceptionCode}
} }
@ -4800,7 +4811,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
MOZ_ASSERT(!JSID_IS_SYMBOL(curId), "No symbols, we said!"); MOZ_ASSERT(!JSID_IS_SYMBOL(curId), "No symbols, we said!");
JS::Rooted<JS::PropertyDescriptor> desc(cx); JS::Rooted<JS::PropertyDescriptor> desc(cx);
if (!JS_GetOwnPropertyDescriptorById(cx, mozMapObj, curId, if (!JS_GetOwnPropertyDescriptorById(cx, recordObj, curId,
&desc)) { &desc)) {
$*{exceptionCode} $*{exceptionCode}
} }
@ -4817,44 +4828,45 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
} }
MOZ_ASSERT(!isSymbol, "We said, no symbols!"); MOZ_ASSERT(!isSymbol, "We said, no symbols!");
if (!JS_GetPropertyById(cx, mozMapObj, curId, &temp)) { if (!JS_GetPropertyById(cx, recordObj, curId, &temp)) {
$*{exceptionCode} $*{exceptionCode}
} }
// Safe to do an infallible append here, because we did a // Safe to do an infallible append here, because we did a
// SetCapacity above to the right capacity. // SetCapacity above to the right capacity.
${mozMapType}::EntryType* entry = mozMapEntries.AppendElement(); ${typeName}::EntryType* entry = recordEntries.AppendElement();
entry->mKey = propName; entry->mKey = propName;
${valueType}& slot = entry->mValue; ${valueType}& slot = entry->mValue;
$*{valueConversion} $*{valueConversion}
} }
""", """,
exceptionCode=exceptionCode, exceptionCode=exceptionCode,
mozMapRef=mozMapRef, recordRef=recordRef,
mozMapType=mozMapType, typeName=typeName,
valueType=valueInfo.declType.define(), valueType=valueInfo.declType.define(),
valueConversion=valueConversion) valueConversion=valueConversion)
templateBody = wrapObjectTemplate(templateBody, type, templateBody = wrapObjectTemplate(templateBody, type,
"${declName}.SetNull();\n", "${declName}.SetNull();\n",
notMozMap) notRecord)
declType = typeName
declArgs = None declArgs = None
holderType = None holderType = None
holderArgs = None holderArgs = None
# MozMap arguments that might contain traceable things need # record arguments that might contain traceable things need
# to get traced # to get traced
if not isMember and isCallbackReturnValue: if not isMember and isCallbackReturnValue:
# Go ahead and just convert directly into our actual return value # Go ahead and just convert directly into our actual return value
declType = CGWrapper(declType, post="&") declType = CGWrapper(declType, post="&")
declArgs = "aRetVal" declArgs = "aRetVal"
elif not isMember and typeNeedsRooting(valueType): elif not isMember and typeNeedsRooting(valueType):
holderType = CGTemplatedType("MozMapRooter", valueInfo.declType) holderType = CGTemplatedType("RecordRooter",
# If our MozMap is nullable, this will set the Nullable to be [recordKeyDeclType(recordType),
valueInfo.declType])
# If our record is nullable, this will set the Nullable to be
# not-null, but that's ok because we make an explicit SetNull() call # not-null, but that's ok because we make an explicit SetNull() call
# on it as needed if our JS value is actually null. # on it as needed if our JS value is actually null.
holderArgs = "cx, &%s" % mozMapRef holderArgs = "cx, &%s" % recordRef
return JSToNativeConversionInfo(templateBody, declType=declType, return JSToNativeConversionInfo(templateBody, declType=declType,
declArgs=declArgs, declArgs=declArgs,
@ -4937,16 +4949,16 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
else: else:
setDictionary = None setDictionary = None
mozMapMemberTypes = filter(lambda t: t.isRecord(), memberTypes) recordMemberTypes = filter(lambda t: t.isRecord(), memberTypes)
if len(mozMapMemberTypes) > 0: if len(recordMemberTypes) > 0:
assert len(mozMapMemberTypes) == 1 assert len(recordMemberTypes) == 1
name = getUnionMemberName(mozMapMemberTypes[0]) name = getUnionMemberName(recordMemberTypes[0])
mozMapObject = CGGeneric( recordObject = CGGeneric(
"done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" % "done = (failed = !%s.TrySetTo%s(cx, ${val}, tryNext, ${passedToJSImpl})) || !tryNext;\n" %
(unionArgumentObj, name)) (unionArgumentObj, name))
names.append(name) names.append(name)
else: else:
mozMapObject = None recordObject = None
objectMemberTypes = filter(lambda t: t.isObject(), memberTypes) objectMemberTypes = filter(lambda t: t.isObject(), memberTypes)
if len(objectMemberTypes) > 0: if len(objectMemberTypes) > 0:
@ -4962,10 +4974,10 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
else: else:
object = None object = None
hasObjectTypes = interfaceObject or sequenceObject or dateObject or callbackObject or object or mozMapObject hasObjectTypes = interfaceObject or sequenceObject or dateObject or callbackObject or object or recordObject
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 sequenceObject or dateObject or callbackObject or mozMapObject) assert not object or not (interfaceObject or sequenceObject or dateObject or callbackObject or recordObject)
if sequenceObject or dateObject or callbackObject: if sequenceObject or dateObject or callbackObject:
# An object can be both an sequence object and a callback or # An object can be both an sequence object and a callback or
# dictionary, but we shouldn't have both in the union's members # dictionary, but we shouldn't have both in the union's members
@ -4985,9 +4997,9 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
if dateObject: if dateObject:
templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());\n")) templateBody.prepend(CGGeneric("JS::Rooted<JSObject*> argObj(cx, &${val}.toObject());\n"))
if mozMapObject: if recordObject:
templateBody = CGList([templateBody, templateBody = CGList([templateBody,
CGIfWrapper(mozMapObject, "!done")]) CGIfWrapper(recordObject, "!done")])
templateBody = CGIfWrapper(templateBody, "${val}.isObject()") templateBody = CGIfWrapper(templateBody, "${val}.isObject()")
else: else:
@ -5747,7 +5759,7 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
assert not isEnforceRange and not isClamp assert not isEnforceRange and not isClamp
declArgs = None declArgs = None
if isMember in ("Variadic", "Sequence", "Dictionary", "MozMap"): if isMember in ("Variadic", "Sequence", "Dictionary", "Record"):
# Rooting is handled by the sequence and dictionary tracers. # Rooting is handled by the sequence and dictionary tracers.
declType = "JS::Value" declType = "JS::Value"
else: else:
@ -6280,7 +6292,7 @@ def getMaybeWrapValueFuncForType(type):
sequenceWrapLevel = 0 sequenceWrapLevel = 0
mozMapWrapLevel = 0 recordWrapLevel = 0
def getWrapTemplateForType(type, descriptorProvider, result, successCode, def getWrapTemplateForType(type, descriptorProvider, result, successCode,
@ -6459,13 +6471,13 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
return (code, False) return (code, False)
if type.isRecord(): if type.isRecord():
# Now do non-nullable MozMap. Our success code is just to break to # Now do non-nullable record. Our success code is just to break to
# where we define the property on the object. Note that we bump the # where we define the property on the object. Note that we bump the
# mozMapWrapLevel around this call so that nested MozMap conversions # recordWrapLevel around this call so that nested record conversions
# will use different temp value names. # will use different temp value names.
global mozMapWrapLevel global recordWrapLevel
valueName = "mozMapValue%d" % mozMapWrapLevel valueName = "recordValue%d" % recordWrapLevel
mozMapWrapLevel += 1 recordWrapLevel += 1
innerTemplate = wrapForType( innerTemplate = wrapForType(
type.inner, descriptorProvider, type.inner, descriptorProvider,
{ {
@ -6478,7 +6490,7 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
'obj': "returnObj", 'obj': "returnObj",
'typedArraysAreStructs': typedArraysAreStructs 'typedArraysAreStructs': typedArraysAreStructs
}) })
mozMapWrapLevel -= 1 recordWrapLevel -= 1
code = fill( code = fill(
""" """
@ -6895,14 +6907,15 @@ def getRetvalDeclarationForType(returnType, descriptorProvider,
returnType = returnType.inner returnType = returnType.inner
result, _, _, _, _ = getRetvalDeclarationForType(returnType.inner, result, _, _, _, _ = getRetvalDeclarationForType(returnType.inner,
descriptorProvider, descriptorProvider,
isMember="MozMap") isMember="Record")
# While we have our inner type, set up our rooter, if needed # While we have our inner type, set up our rooter, if needed
if not isMember and typeNeedsRooting(returnType): if not isMember and typeNeedsRooting(returnType):
rooter = CGGeneric("MozMapRooter<%s> resultRooter(cx, &result);\n" % rooter = CGGeneric("RecordRooter<%s> resultRooter(cx, &result);\n" %
result.define()) ("nsString, " + result.define()))
else: else:
rooter = None rooter = None
result = CGTemplatedType("MozMap", result) result = CGTemplatedType("Record", [recordKeyDeclType(returnType),
result])
if nullable: if nullable:
result = CGTemplatedType("Nullable", result) result = CGTemplatedType("Nullable", result)
return result, "ref", rooter, None, None return result, "ref", rooter, None, None
@ -7161,7 +7174,7 @@ class MethodNotNewObjectError(Exception):
# nested sequences we don't use the same variable name to iterate over # nested sequences we don't use the same variable name to iterate over
# different sequences. # different sequences.
sequenceWrapLevel = 0 sequenceWrapLevel = 0
mapWrapLevel = 0 recordWrapLevel = 0
def wrapTypeIntoCurrentCompartment(type, value, isMember=True): def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
@ -7226,20 +7239,20 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
origType = type origType = type
if type.nullable(): if type.nullable():
type = type.inner type = type.inner
mozMapRef = "%s.Value()" % value recordRef = "%s.Value()" % value
else: else:
mozMapRef = value recordRef = value
global mapWrapLevel global recordWrapLevel
entryRef = "mapEntry%d" % mapWrapLevel entryRef = "mapEntry%d" % recordWrapLevel
mapWrapLevel += 1 recordWrapLevel += 1
wrapElement = wrapTypeIntoCurrentCompartment(type.inner, wrapElement = wrapTypeIntoCurrentCompartment(type.inner,
"%s.mValue" % entryRef) "%s.mValue" % entryRef)
mapWrapLevel -= 1 recordWrapLevel -= 1
if not wrapElement: if not wrapElement:
return None return None
wrapCode = CGWrapper(CGIndenter(wrapElement), wrapCode = CGWrapper(CGIndenter(wrapElement),
pre=("for (auto& %s : %s.Entries()) {\n" % pre=("for (auto& %s : %s.Entries()) {\n" %
(entryRef, mozMapRef)), (entryRef, recordRef)),
post="}\n") post="}\n")
if origType.nullable(): if origType.nullable():
wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % value) wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % value)
@ -8131,7 +8144,7 @@ class CGMethodCall(CGThing):
if distinguishingType(s).isSequence()) if distinguishingType(s).isSequence())
# Now append all the overloads that take a dictionary or callback # Now append all the overloads that take a dictionary or callback
# interface or MozMap. There should be only one of these! # interface or record. There should be only one of these!
genericObjectSigs = [ genericObjectSigs = [
s for s in possibleSignatures s for s in possibleSignatures
if (distinguishingType(s).isDictionary() or if (distinguishingType(s).isDictionary() or
@ -9694,13 +9707,18 @@ def getUnionAccessorSignatureType(type, descriptorProvider):
if type.isSequence(): if type.isSequence():
wrapperType = "Sequence" wrapperType = "Sequence"
else: else:
wrapperType = "MozMap" wrapperType = "Record"
# We don't use the returned template here, so it's OK to just pass no # We don't use the returned template here, so it's OK to just pass no
# sourceDescription. # sourceDescription.
elementInfo = getJSToNativeConversionInfo(type.inner, elementInfo = getJSToNativeConversionInfo(type.inner,
descriptorProvider, descriptorProvider,
isMember=wrapperType) isMember=wrapperType)
return CGTemplatedType(wrapperType, elementInfo.declType, if wrapperType == "Sequence":
innerType = elementInfo.declType
else:
innerType = [recordKeyDeclType(type), elementInfo.declType]
return CGTemplatedType(wrapperType, innerType,
isConst=True, isReference=True) isConst=True, isReference=True)
# Nested unions are unwrapped automatically into our flatMemberTypes. # Nested unions are unwrapped automatically into our flatMemberTypes.
@ -10064,7 +10082,7 @@ class CGUnionStruct(CGThing):
elif t.isRecord(): elif t.isRecord():
traceCases.append( traceCases.append(
CGCase("e" + vars["name"], CGCase("e" + vars["name"],
CGGeneric("TraceMozMap(trc, mValue.m%s.Value());\n" % CGGeneric("TraceRecord(trc, mValue.m%s.Value());\n" %
vars["name"]))) vars["name"])))
else: else:
assert t.isSpiderMonkeyInterface() assert t.isSpiderMonkeyInterface()
@ -13194,7 +13212,7 @@ class CGDictionary(CGThing):
if type.nullable(): if type.nullable():
trace = CGIfWrapper(trace, "!%s.IsNull()" % memberNullable) trace = CGIfWrapper(trace, "!%s.IsNull()" % memberNullable)
elif type.isRecord(): elif type.isRecord():
# If you implement this, add a MozMap<object> to # If you implement this, add a record<DOMString, object> to
# TestInterfaceJSDictionary and test it in test_bug1036214.html # TestInterfaceJSDictionary and test it in test_bug1036214.html
# to make sure we end up with the correct security properties. # to make sure we end up with the correct security properties.
assert False assert False
@ -14111,8 +14129,8 @@ class CGNativeMember(ClassMethod):
returnCode = "aRetVal.SwapElements(${declName});\n" returnCode = "aRetVal.SwapElements(${declName});\n"
return "void", "", returnCode return "void", "", returnCode
if type.isRecord(): if type.isRecord():
# If we want to handle MozMap-of-MozMap return values, we're # If we want to handle record-of-record return values, we're
# going to need to fix example codegen to not produce MozMap<void> # going to need to fix example codegen to not produce record<void>
# for the relevant argument... # for the relevant argument...
assert not isMember assert not isMember
# In this case we convert directly into our outparam to start with # In this case we convert directly into our outparam to start with
@ -14166,7 +14184,8 @@ class CGNativeMember(ClassMethod):
returnType = returnType.inner returnType = returnType.inner
# And now the actual underlying type # And now the actual underlying type
elementDecl = self.getReturnType(returnType.inner, True) elementDecl = self.getReturnType(returnType.inner, True)
type = CGTemplatedType("MozMap", CGGeneric(elementDecl)) type = CGTemplatedType("Record", [recordKeyDeclType(returnType),
CGGeneric(elementDecl)])
if nullable: if nullable:
type = CGTemplatedType("Nullable", type) type = CGTemplatedType("Nullable", type)
args.append(Argument("%s&" % type.define(), "aRetVal")) args.append(Argument("%s&" % type.define(), "aRetVal"))
@ -14227,7 +14246,7 @@ class CGNativeMember(ClassMethod):
Nullable as needed. Nullable as needed.
isMember can be false or one of the strings "Sequence", "Variadic", isMember can be false or one of the strings "Sequence", "Variadic",
"MozMap" "Record"
""" """
if type.isSequence(): if type.isSequence():
nullable = type.nullable() nullable = type.nullable()
@ -14243,8 +14262,8 @@ class CGNativeMember(ClassMethod):
if nullable: if nullable:
type = type.inner type = type.inner
elementType = type.inner elementType = type.inner
argType = self.getArgType(elementType, False, "MozMap")[0] argType = self.getArgType(elementType, False, "Record")[0]
decl = CGTemplatedType("MozMap", argType) decl = CGTemplatedType("Record", [recordKeyDeclType(type), argType])
return decl.define(), True, True return decl.define(), True, True
if type.isUnion(): if type.isUnion():

View file

@ -5,11 +5,11 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/** /**
* Class for representing MozMap arguments. Basically an array under the hood. * Class for representing record arguments. Basically an array under the hood.
*/ */
#ifndef mozilla_dom_MozMap_h #ifndef mozilla_dom_Record_h
#define mozilla_dom_MozMap_h #define mozilla_dom_Record_h
#include "nsTHashtable.h" #include "nsTHashtable.h"
#include "nsHashKeys.h" #include "nsHashKeys.h"
@ -23,15 +23,15 @@ namespace dom {
namespace binding_detail { namespace binding_detail {
template<typename KeyType, typename ValueType> template<typename KeyType, typename ValueType>
class MozMapEntry class RecordEntry
{ {
public: public:
MozMapEntry() RecordEntry()
{ {
} }
// Move constructor so we can do MozMaps of MozMaps. // Move constructor so we can do Records of Records.
MozMapEntry(MozMapEntry<KeyType, ValueType>&& aOther) RecordEntry(RecordEntry<KeyType, ValueType>&& aOther)
: mKey(Move(aOther.mKey)), : mKey(Move(aOther.mKey)),
mValue(Move(aOther.mValue)) mValue(Move(aOther.mValue))
{ {
@ -43,20 +43,19 @@ public:
} // namespace binding_detail } // namespace binding_detail
template<typename ValueType> template<typename KeyType, typename ValueType>
class MozMap class Record
{ {
public: public:
typedef nsString KeyType; typedef typename binding_detail::RecordEntry<nsString, ValueType> EntryType;
typedef typename binding_detail::MozMapEntry<KeyType, ValueType> EntryType; typedef Record<KeyType, ValueType> SelfType;
typedef MozMap<ValueType> SelfType;
MozMap() Record()
{ {
} }
// Move constructor so we can do MozMap of MozMap. // Move constructor so we can do Record of Record.
MozMap(SelfType&& aOther) : Record(SelfType&& aOther) :
mEntries(Move(aOther.mEntries)) mEntries(Move(aOther.mEntries))
{ {
} }
@ -78,4 +77,4 @@ private:
} // namespace dom } // namespace dom
} // namespace mozilla } // namespace mozilla
#endif // mozilla_dom_MozMap_h #endif // mozilla_dom_Record_h

View file

@ -32,10 +32,10 @@ EXPORTS.mozilla.dom += [
'FakeString.h', 'FakeString.h',
'IterableIterator.h', 'IterableIterator.h',
'JSSlots.h', 'JSSlots.h',
'MozMap.h',
'NonRefcountedDOMObject.h', 'NonRefcountedDOMObject.h',
'Nullable.h', 'Nullable.h',
'PrimitiveConversions.h', 'PrimitiveConversions.h',
'Record.h',
'RootedDictionary.h', 'RootedDictionary.h',
'SimpleGlobalObject.h', 'SimpleGlobalObject.h',
'StructuredClone.h', 'StructuredClone.h',

View file

@ -20,7 +20,7 @@ class ErrorResult;
namespace dom { namespace dom {
template<typename T> class MozMap; template<typename K, typename V> class Record;
class HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord; class HeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord;
class OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord; class OwningHeadersOrByteStringSequenceSequenceOrByteStringByteStringRecord;

View file

@ -314,7 +314,7 @@ InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& a
} }
void void
InternalHeaders::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv) InternalHeaders::Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv)
{ {
for (auto& entry : aInit.Entries()) { for (auto& entry : aInit.Entries()) {
Append(NS_ConvertUTF16toUTF8(entry.mKey), entry.mValue, aRv); Append(NS_ConvertUTF16toUTF8(entry.mKey), entry.mValue, aRv);

View file

@ -20,7 +20,7 @@ class ErrorResult;
namespace dom { namespace dom {
template<typename T> class MozMap; template<typename K, typename V> class Record;
class HeadersEntry; class HeadersEntry;
class InternalHeaders final class InternalHeaders final
@ -113,7 +113,7 @@ public:
void Fill(const InternalHeaders& aInit, ErrorResult& aRv); void Fill(const InternalHeaders& aInit, ErrorResult& aRv);
void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv); void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv); void Fill(const Record<nsCString, nsCString>& aInit, ErrorResult& aRv);
bool HasOnlySimpleHeaders() const; bool HasOnlySimpleHeaders() const;