diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index a4844f8747c1..4694ed9bdc75 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -16770,11 +16770,15 @@ class CGIterableMethodGenerator(CGGeneric): JS::AutoValueArray<3> callArgs(cx); callArgs[2].setObject(*obj); JS::Rooted ignoredReturnVal(cx); + auto GetKeyAtIndex = &${selfType}::GetKeyAtIndex; + auto GetValueAtIndex = &${selfType}::GetValueAtIndex; for (size_t i = 0; i < self->GetIterableLength(); ++i) { - if (!ToJSValue(cx, self->GetValueAtIndex(i), callArgs[0])) { + if (!CallIterableGetter(cx, GetValueAtIndex, self, i, + callArgs[0])) { return false; } - if (!ToJSValue(cx, self->GetKeyAtIndex(i), callArgs[1])) { + if (!CallIterableGetter(cx, GetKeyAtIndex, self, i, + callArgs[1])) { return false; } if (!JS::Call(cx, arg1, arg0, JS::HandleValueArray(callArgs), @@ -16783,7 +16787,8 @@ class CGIterableMethodGenerator(CGGeneric): } } """, - ifaceName=descriptor.interface.identifier.name)) + ifaceName=descriptor.interface.identifier.name, + selfType=descriptor.nativeType)) return CGGeneric.__init__(self, fill( """ diff --git a/dom/bindings/IterableIterator.h b/dom/bindings/IterableIterator.h index f8c9cb0b6bc3..46ec6d3a68a5 100644 --- a/dom/bindings/IterableIterator.h +++ b/dom/bindings/IterableIterator.h @@ -57,6 +57,53 @@ protected: virtual void TraverseHelper(nsCycleCollectionTraversalCallback& cb) = 0; }; +// Helpers to call iterator getter methods with the correct arguments, depending +// on the types they return, and convert the result to JS::Values. + +// Helper for Get[Key,Value]AtIndex(uint32_t) methods, which accept an index and +// return a type supported by ToJSValue. +template +bool +CallIterableGetter(JSContext* aCx, U (T::* aMethod)(uint32_t), + T* aInst, uint32_t aIndex, + JS::MutableHandle aResult) +{ + return ToJSValue(aCx, (aInst->*aMethod)(aIndex), aResult); +} + +template +bool +CallIterableGetter(JSContext* aCx, U (T::* aMethod)(uint32_t) const, + const T* aInst, uint32_t aIndex, + JS::MutableHandle aResult) +{ + return ToJSValue(aCx, (aInst->*aMethod)(aIndex), aResult); +} + + +// Helper for Get[Key,Value]AtIndex(JSContext*, uint32_t, MutableHandleValue) +// methods, which accept a JS context, index, and mutable result value handle, +// and return true on success or false on failure. +template +bool +CallIterableGetter(JSContext* aCx, + bool (T::* aMethod)(JSContext*, uint32_t, JS::MutableHandle), + T* aInst, uint32_t aIndex, + JS::MutableHandle aResult) +{ + return (aInst->*aMethod)(aCx, aIndex, aResult); +} + +template +bool +CallIterableGetter(JSContext* aCx, + bool (T::* aMethod)(JSContext*, uint32_t, JS::MutableHandle) const, + const T* aInst, uint32_t aIndex, + JS::MutableHandle aResult) +{ + return (aInst->*aMethod)(aCx, aIndex, aResult); +} + template class IterableIterator final : public IterableIteratorBase { @@ -78,6 +125,24 @@ public: MOZ_ASSERT(mWrapFunc); } + bool + GetKeyAtIndex(JSContext* aCx, uint32_t aIndex, + JS::MutableHandle aResult) + { + return CallIterableGetter(aCx, &T::GetKeyAtIndex, + mIterableObj.get(), + aIndex, aResult); + } + + bool + GetValueAtIndex(JSContext* aCx, uint32_t aIndex, + JS::MutableHandle aResult) + { + return CallIterableGetter(aCx, &T::GetValueAtIndex, + mIterableObj.get(), + aIndex, aResult); + } + void Next(JSContext* aCx, JS::MutableHandle aResult, ErrorResult& aRv) { @@ -89,7 +154,7 @@ public: switch (mIteratorType) { case IterableIteratorType::Keys: { - if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &value)) { + if (!GetKeyAtIndex(aCx, mIndex, &value)) { aRv.Throw(NS_ERROR_FAILURE); return; } @@ -98,7 +163,7 @@ public: } case IterableIteratorType::Values: { - if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) { + if (!GetValueAtIndex(aCx, mIndex, &value)) { aRv.Throw(NS_ERROR_FAILURE); return; } @@ -108,11 +173,11 @@ public: case IterableIteratorType::Entries: { JS::Rooted key(aCx); - if (!ToJSValue(aCx, this->mIterableObj->GetKeyAtIndex(mIndex), &key)) { + if (!GetKeyAtIndex(aCx, mIndex, &key)) { aRv.Throw(NS_ERROR_FAILURE); return; } - if (!ToJSValue(aCx, this->mIterableObj->GetValueAtIndex(mIndex), &value)) { + if (!GetValueAtIndex(aCx, mIndex, &value)) { aRv.Throw(NS_ERROR_FAILURE); return; }