Bug 1322964 - MozPromise.Then() taking only one resolve+reject function - r=jwwang

Then and ThenPromise can now be given only one function object, which takes a
`const MozPromise::ResolveOrRejectValue&`.

MozReview-Commit-ID: BEtc3spK9Yh

--HG--
extra : rebase_source : 1b16ad15ebfcdfb653d8d98073adee0f8b27b46e
This commit is contained in:
Gerald Squelart 2017-01-03 16:15:14 +11:00
Родитель 9a05a0446d
Коммит b3e89a3af9
2 изменённых файлов: 95 добавлений и 0 удалений

Просмотреть файл

@ -112,6 +112,40 @@ TEST(MozPromise, BasicReject)
});
}
TEST(MozPromise, BasicResolveOrRejectResolved)
{
AutoTaskQueue atq;
RefPtr<TaskQueue> queue = atq.Queue();
RunOnTaskQueue(queue, [queue] () -> void {
TestPromise::CreateAndResolve(42, __func__)->Then(queue, __func__,
[queue] (const TestPromise::ResolveOrRejectValue& aValue) -> void
{
EXPECT_TRUE(aValue.IsResolve());
EXPECT_FALSE(aValue.IsReject());
EXPECT_FALSE(aValue.IsNothing());
EXPECT_EQ(aValue.ResolveValue(), 42);
queue->BeginShutdown();
});
});
}
TEST(MozPromise, BasicResolveOrRejectRejected)
{
AutoTaskQueue atq;
RefPtr<TaskQueue> queue = atq.Queue();
RunOnTaskQueue(queue, [queue] () -> void {
TestPromise::CreateAndReject(42.0, __func__)->Then(queue, __func__,
[queue] (const TestPromise::ResolveOrRejectValue& aValue) -> void
{
EXPECT_TRUE(aValue.IsReject());
EXPECT_FALSE(aValue.IsResolve());
EXPECT_FALSE(aValue.IsNothing());
EXPECT_EQ(aValue.RejectValue(), 42.0);
queue->BeginShutdown();
});
});
}
TEST(MozPromise, AsyncResolve)
{
AutoTaskQueue atq;

Просмотреть файл

@ -578,6 +578,57 @@ protected:
Maybe<RejectFunction> mRejectFunction; // Only accessed and deleted on dispatch thread.
};
// Specialization of FunctionThenValue (with 2nd template arg being 'void')
// that only takes one function, to be called with a ResolveOrRejectValue.
template<typename ResolveRejectFunction>
class FunctionThenValue<ResolveRejectFunction, void> : public ThenValueBase
{
public:
FunctionThenValue(AbstractThread* aResponseTarget,
ResolveRejectFunction&& aResolveRejectFunction,
const char* aCallSite)
: ThenValueBase(aResponseTarget, aCallSite)
{
mResolveRejectFunction.emplace(Move(aResolveRejectFunction));
}
void Disconnect() override
{
ThenValueBase::Disconnect();
// If a Request has been disconnected, we don't guarantee that the
// resolve/reject runnable will be dispatched. Destroy our callbacks
// now so that any references in closures are released predictable on
// the dispatch thread.
mResolveRejectFunction.reset();
}
protected:
already_AddRefed<MozPromise> DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override
{
// Note: The usage of InvokeCallbackMethod here requires that
// ResolveRejectFunction is capture-lambdas (i.e. anonymous
// classes with ::operator()), since it allows us to share code more easily.
// We could fix this if need be, though it's quite easy to work around by
// just capturing something.
RefPtr<MozPromise> completion =
InvokeCallbackMethod(mResolveRejectFunction.ptr(),
&ResolveRejectFunction::operator(),
aValue);
// Destroy callbacks after invocation so that any references in closures are
// released predictably on the dispatch thread. Otherwise, they would be
// released on whatever thread last drops its reference to the ThenValue,
// which may or may not be ok.
mResolveRejectFunction.reset();
return completion.forget();
}
private:
Maybe<ResolveRejectFunction> mResolveRejectFunction; // Only accessed and deleted on dispatch thread.
};
public:
void ThenInternal(AbstractThread* aResponseThread, ThenValueBase* aThenValue,
const char* aCallSite)
@ -688,6 +739,16 @@ public:
return ThenCommand(aResponseThread, aCallSite, thenValue.forget(), this);
}
template<typename ResolveRejectFunction>
ThenCommand Then(AbstractThread* aResponseThread, const char* aCallSite,
ResolveRejectFunction&& aResolveRejectFunction)
{
using ThenType = FunctionThenValue<ResolveRejectFunction, void>;
RefPtr<ThenValueBase> thenValue = new ThenType(aResponseThread,
Move(aResolveRejectFunction), aCallSite);
return ThenCommand(aResponseThread, aCallSite, thenValue.forget(), this);
}
void ChainTo(already_AddRefed<Private> aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);