mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 1472342: Part 1 - Properly support iterator getters which need JSContexts. r=bz
The IterableIterator helper currently only supports iterator methods which return types which are supported by ToJSValue, but do not need a JSContext* to construct them. That means that getters which need to return native JS objects or values can't do so safely, or without resorting to hacks. This patch adds templated helpers which will call a JSContext-accepting, JS::Value-returning version of the getter methods if they exist, and fall back to the simpler versions if they don't. MozReview-Commit-ID: hedZOc3lqR --HG-- extra : rebase_source : b92cdc3900b3c9bee41836af4d4b9f4e65f3d5f6
This commit is contained in:
parent
99d822fb5f
commit
72ae1375d1
@ -16770,11 +16770,15 @@ class CGIterableMethodGenerator(CGGeneric):
|
||||
JS::AutoValueArray<3> callArgs(cx);
|
||||
callArgs[2].setObject(*obj);
|
||||
JS::Rooted<JS::Value> 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(
|
||||
"""
|
||||
|
@ -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 <typename T, typename U>
|
||||
bool
|
||||
CallIterableGetter(JSContext* aCx, U (T::* aMethod)(uint32_t),
|
||||
T* aInst, uint32_t aIndex,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
return ToJSValue(aCx, (aInst->*aMethod)(aIndex), aResult);
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
bool
|
||||
CallIterableGetter(JSContext* aCx, U (T::* aMethod)(uint32_t) const,
|
||||
const T* aInst, uint32_t aIndex,
|
||||
JS::MutableHandle<JS::Value> 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 <typename T>
|
||||
bool
|
||||
CallIterableGetter(JSContext* aCx,
|
||||
bool (T::* aMethod)(JSContext*, uint32_t, JS::MutableHandle<JS::Value>),
|
||||
T* aInst, uint32_t aIndex,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
return (aInst->*aMethod)(aCx, aIndex, aResult);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool
|
||||
CallIterableGetter(JSContext* aCx,
|
||||
bool (T::* aMethod)(JSContext*, uint32_t, JS::MutableHandle<JS::Value>) const,
|
||||
const T* aInst, uint32_t aIndex,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
return (aInst->*aMethod)(aCx, aIndex, aResult);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
class IterableIterator final : public IterableIteratorBase
|
||||
{
|
||||
@ -78,6 +125,24 @@ public:
|
||||
MOZ_ASSERT(mWrapFunc);
|
||||
}
|
||||
|
||||
bool
|
||||
GetKeyAtIndex(JSContext* aCx, uint32_t aIndex,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
return CallIterableGetter(aCx, &T::GetKeyAtIndex,
|
||||
mIterableObj.get(),
|
||||
aIndex, aResult);
|
||||
}
|
||||
|
||||
bool
|
||||
GetValueAtIndex(JSContext* aCx, uint32_t aIndex,
|
||||
JS::MutableHandle<JS::Value> aResult)
|
||||
{
|
||||
return CallIterableGetter(aCx, &T::GetValueAtIndex,
|
||||
mIterableObj.get(),
|
||||
aIndex, aResult);
|
||||
}
|
||||
|
||||
void
|
||||
Next(JSContext* aCx, JS::MutableHandle<JSObject*> 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<JS::Value> 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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user