summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dom/bindings/BindingUtils.h16
-rw-r--r--dom/bindings/Codegen.py51
-rw-r--r--dom/bindings/MozMap.h82
-rw-r--r--dom/fetch/InternalHeaders.cpp9
4 files changed, 55 insertions, 103 deletions
diff --git a/dom/bindings/BindingUtils.h b/dom/bindings/BindingUtils.h
index 24b47a545d..23bbbea5a0 100644
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -2294,18 +2294,12 @@ public:
};
template<typename T>
-static void
-TraceMozMapValue(T* aValue, void* aClosure)
-{
- JSTracer* trc = static_cast<JSTracer*>(aClosure);
- // Act like it's a one-element sequence to leverage all that infrastructure.
- SequenceTracer<T>::TraceSequence(trc, aValue, aValue + 1);
-}
-
-template<typename T>
void TraceMozMap(JSTracer* trc, MozMap<T>& map)
{
- map.EnumerateValues(TraceMozMapValue<T>, trc);
+ for (auto& entry : map.Entries()) {
+ // Act like it's a one-element sequence to leverage all that infrastructure.
+ SequenceTracer<T>::TraceSequence(trc, &entry.mValue, &entry.mValue + 1);
+ }
}
// sequence<MozMap>
@@ -2317,7 +2311,7 @@ class SequenceTracer<MozMap<T>, false, false, false>
public:
static void TraceSequence(JSTracer* trc, MozMap<T>* seqp, MozMap<T>* end) {
for (; seqp != end; ++seqp) {
- seqp->EnumerateValues(TraceMozMapValue<T>, trc);
+ TraceMozMap(trc, *seqp);
}
}
};
diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py
index 5c4aa746d5..fd811bb3a3 100644
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -4774,20 +4774,21 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
templateBody = fill(
"""
- ${mozMapType} &mozMap = ${mozMapRef};
+ auto& mozMapEntries = ${mozMapRef}.Entries();
JS::Rooted<JSObject*> mozMapObj(cx, &$${val}.toObject());
JS::Rooted<JS::IdVector> ids(cx, JS::IdVector(cx));
if (!JS_Enumerate(cx, mozMapObj, &ids)) {
$*{exceptionCode}
}
+ if (!mozMapEntries.SetCapacity(ids.length(), mozilla::fallible)) {
+ JS_ReportOutOfMemory(cx);
+ $*{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::FakeString propName;
bool isSymbol;
@@ -4799,18 +4800,17 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
continue;
}
- ${valueType}* slotPtr = mozMap.AddEntry(propName);
- if (!slotPtr) {
- JS_ReportOutOfMemory(cx);
- $*{exceptionCode}
- }
- ${valueType}& slot = *slotPtr;
+ // Safe to do an infallible append here, because we did a
+ // SetCapacity above to the right capacity.
+ ${mozMapType}::EntryType* entry = mozMapEntries.AppendElement();
+ entry->mKey = propName;
+ ${valueType}& slot = entry->mValue;
$*{valueConversion}
}
""",
exceptionCode=exceptionCode,
- mozMapType=mozMapType,
mozMapRef=mozMapRef,
+ mozMapType=mozMapType,
valueType=valueInfo.declType.define(),
valueConversion=valueConversion)
@@ -6460,8 +6460,6 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
code = fill(
"""
- nsTArray<nsString> keys;
- ${result}.GetKeys(keys);
JS::Rooted<JSObject*> returnObj(cx, JS_NewPlainObject(cx));
if (!returnObj) {
$*{exceptionCode}
@@ -6469,15 +6467,16 @@ def getWrapTemplateForType(type, descriptorProvider, result, successCode,
// Scope for 'tmp'
{
JS::Rooted<JS::Value> tmp(cx);
- for (size_t idx = 0; idx < keys.Length(); ++idx) {
- auto& ${valueName} = ${result}.Get(keys[idx]);
+ for (auto& entry : ${result}.Entries()) {
+ auto& ${valueName} = entry.mValue;
// Control block to let us common up the JS_DefineUCProperty calls when there
// are different ways to succeed at wrapping the value.
do {
$*{innerTemplate}
} while (0);
- if (!JS_DefineUCProperty(cx, returnObj, keys[idx].get(),
- keys[idx].Length(), tmp,
+ if (!JS_DefineUCProperty(cx, returnObj,
+ entry.mKey.BeginReading(),
+ entry.mKey.Length(), tmp,
JSPROP_ENUMERATE)) {
$*{exceptionCode}
}
@@ -7202,28 +7201,26 @@ def wrapTypeIntoCurrentCompartment(type, value, isMember=True):
return wrapCode
if type.isMozMap():
- origValue = value
origType = type
if type.nullable():
type = type.inner
- value = "%s.Value()" % value
+ mozMapRef = "%s.Value()" % value
+ else:
+ mozMapRef = value
global mapWrapLevel
- key = "mapName%d" % mapWrapLevel
+ entryRef = "mapEntry%d" % mapWrapLevel
mapWrapLevel += 1
wrapElement = wrapTypeIntoCurrentCompartment(type.inner,
- "%s.Get(%sKeys[%sIndex])" % (value, key, key))
+ "%s.mValue" % entryRef)
mapWrapLevel -= 1
if not wrapElement:
return None
wrapCode = CGWrapper(CGIndenter(wrapElement),
- pre=("""
- nsTArray<nsString> %sKeys;
- %s.GetKeys(%sKeys);
- for (uint32_t %sIndex = 0; %sIndex < %sKeys.Length(); ++%sIndex) {
- """ % (key, value, key, key, key, key, key)),
+ pre=("for (auto& %s : %s.Entries()) {\n" %
+ (entryRef, mozMapRef)),
post="}\n")
if origType.nullable():
- wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % origValue)
+ wrapCode = CGIfWrapper(wrapCode, "!%s.IsNull()" % value)
return wrapCode
if type.isDictionary():
diff --git a/dom/bindings/MozMap.h b/dom/bindings/MozMap.h
index 1e920c098e..2725c74ffd 100644
--- a/dom/bindings/MozMap.h
+++ b/dom/bindings/MozMap.h
@@ -5,9 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
- * Class for representing MozMap arguments. This is an nsTHashtable
- * under the hood, but we don't want to leak that implementation
- * detail.
+ * Class for representing MozMap arguments. Basically an array under the hood.
*/
#ifndef mozilla_dom_MozMap_h
@@ -24,34 +22,34 @@ namespace mozilla {
namespace dom {
namespace binding_detail {
-template<typename DataType>
-class MozMapEntry : public nsStringHashKey
+template<typename KeyType, typename ValueType>
+class MozMapEntry
{
public:
- explicit MozMapEntry(const nsAString* aKeyTypePointer)
- : nsStringHashKey(aKeyTypePointer)
+ MozMapEntry()
{
}
// Move constructor so we can do MozMaps of MozMaps.
- MozMapEntry(MozMapEntry<DataType>&& aOther)
- : nsStringHashKey(aOther),
- mData(Move(aOther.mData))
+ MozMapEntry(MozMapEntry<KeyType, ValueType>&& aOther)
+ : mKey(Move(aOther.mKey)),
+ mValue(Move(aOther.mValue))
{
}
- DataType mData;
+ KeyType mKey;
+ ValueType mValue;
};
} // namespace binding_detail
-template<typename DataType>
-class MozMap : protected nsTHashtable<binding_detail::MozMapEntry<DataType>>
+template<typename ValueType>
+class MozMap
{
public:
- typedef typename binding_detail::MozMapEntry<DataType> EntryType;
- typedef nsTHashtable<EntryType> Base;
- typedef MozMap<DataType> SelfType;
+ typedef nsString KeyType;
+ typedef typename binding_detail::MozMapEntry<KeyType, ValueType> EntryType;
+ typedef MozMap<ValueType> SelfType;
MozMap()
{
@@ -59,60 +57,22 @@ public:
// Move constructor so we can do MozMap of MozMap.
MozMap(SelfType&& aOther) :
- Base(Move(aOther))
+ mEntries(Move(aOther.mEntries))
{
}
- // The return value is only safe to use until an AddEntry call.
- const DataType& Get(const nsAString& aKey) const
+ const nsTArray<EntryType>& Entries() const
{
- const EntryType* ent = this->GetEntry(aKey);
- MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?");
- return ent->mData;
+ return mEntries;
}
- DataType& Get(const nsAString& aKey)
+ nsTArray<EntryType>& Entries()
{
- EntryType* ent = this->GetEntry(aKey);
- MOZ_ASSERT(ent, "Why are you using a key we didn't claim to have?");
- return ent->mData;
+ return mEntries;
}
- // The return value is only safe to use until an AddEntry call.
- const DataType* GetIfExists(const nsAString& aKey) const
- {
- const EntryType* ent = this->GetEntry(aKey);
- if (!ent) {
- return nullptr;
- }
- return &ent->mData;
- }
-
- void GetKeys(nsTArray<nsString>& aKeys) const {
- for (auto iter = this->ConstIter(); !iter.Done(); iter.Next()) {
- aKeys.AppendElement(iter.Get()->GetKey());
- }
- }
-
- // XXXbz we expose this generic enumerator for tracing. Otherwise we'd end up
- // with a dependency on BindingUtils.h here for the SequenceTracer bits.
- typedef void (* Enumerator)(DataType* aValue, void* aClosure);
- void EnumerateValues(Enumerator aEnumerator, void *aClosure)
- {
- for (auto iter = this->Iter(); !iter.Done(); iter.Next()) {
- aEnumerator(&iter.Get()->mData, aClosure);
- }
- }
-
- MOZ_MUST_USE
- DataType* AddEntry(const nsAString& aKey)
- {
- EntryType* ent = this->PutEntry(aKey, fallible);
- if (!ent) {
- return nullptr;
- }
- return &ent->mData;
- }
+private:
+ nsTArray<EntryType> mEntries;
};
} // namespace dom
diff --git a/dom/fetch/InternalHeaders.cpp b/dom/fetch/InternalHeaders.cpp
index 11585615ea..83a6867851 100644
--- a/dom/fetch/InternalHeaders.cpp
+++ b/dom/fetch/InternalHeaders.cpp
@@ -316,10 +316,11 @@ InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& a
void
InternalHeaders::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv)
{
- nsTArray<nsString> keys;
- aInit.GetKeys(keys);
- for (uint32_t i = 0; i < keys.Length() && !aRv.Failed(); ++i) {
- Append(NS_ConvertUTF16toUTF8(keys[i]), aInit.Get(keys[i]), aRv);
+ for (auto& entry : aInit.Entries()) {
+ Append(NS_ConvertUTF16toUTF8(entry.mKey), entry.mValue, aRv);
+ if (aRv.Failed()) {
+ return;
+ }
}
}