зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1055925 - Refactor promise to merge main thread and worker thread tasks into a single task. r=nsm
This commit is contained in:
Родитель
5db5af6491
Коммит
6fda146273
|
@ -51,12 +51,15 @@ public:
|
|||
protected:
|
||||
~PromiseTask()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(PromiseTask);
|
||||
MOZ_COUNT_DTOR(PromiseTask);
|
||||
}
|
||||
|
||||
public:
|
||||
NS_IMETHOD Run()
|
||||
NS_IMETHOD
|
||||
Run() MOZ_OVERRIDE
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(PromiseTask);
|
||||
mPromise->mTaskPending = false;
|
||||
mPromise->RunTask();
|
||||
return NS_OK;
|
||||
|
@ -64,67 +67,40 @@ public:
|
|||
|
||||
private:
|
||||
nsRefPtr<Promise> mPromise;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
class WorkerPromiseTask MOZ_FINAL : public WorkerSameThreadRunnable
|
||||
// This class processes the promise's callbacks with promise's result.
|
||||
class PromiseResolverTask MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
WorkerPromiseTask(WorkerPrivate* aWorkerPrivate, Promise* aPromise)
|
||||
: WorkerSameThreadRunnable(aWorkerPrivate)
|
||||
, mPromise(aPromise)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_COUNT_CTOR(WorkerPromiseTask);
|
||||
}
|
||||
|
||||
protected:
|
||||
~WorkerPromiseTask()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WorkerPromiseTask);
|
||||
}
|
||||
|
||||
public:
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
mPromise->mTaskPending = false;
|
||||
mPromise->RunTask();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
class PromiseResolverMixin
|
||||
{
|
||||
public:
|
||||
PromiseResolverMixin(Promise* aPromise,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
Promise::PromiseState aState)
|
||||
PromiseResolverTask(Promise* aPromise,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
Promise::PromiseState aState)
|
||||
: mPromise(aPromise)
|
||||
, mValue(CycleCollectedJSRuntime::Get()->Runtime(), aValue)
|
||||
, mState(aState)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(mState != Promise::Pending);
|
||||
MOZ_COUNT_CTOR(PromiseResolverMixin);
|
||||
MOZ_COUNT_CTOR(PromiseResolverTask);
|
||||
}
|
||||
|
||||
virtual ~PromiseResolverMixin()
|
||||
virtual
|
||||
~PromiseResolverTask()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
|
||||
MOZ_COUNT_DTOR(PromiseResolverMixin);
|
||||
NS_ASSERT_OWNINGTHREAD(PromiseResolverTask);
|
||||
MOZ_COUNT_DTOR(PromiseResolverTask);
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
RunInternal()
|
||||
NS_IMETHOD
|
||||
Run() MOZ_OVERRIDE
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
|
||||
NS_ASSERT_OWNINGTHREAD(PromiseResolverTask);
|
||||
mPromise->RunResolveTask(
|
||||
JS::Handle<JS::Value>::fromMarkedLocation(mValue.address()),
|
||||
mState, Promise::SyncTask);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -134,50 +110,6 @@ private:
|
|||
NS_DECL_OWNINGTHREAD;
|
||||
};
|
||||
|
||||
// This class processes the promise's callbacks with promise's result.
|
||||
class PromiseResolverTask MOZ_FINAL : public nsRunnable,
|
||||
public PromiseResolverMixin
|
||||
{
|
||||
public:
|
||||
PromiseResolverTask(Promise* aPromise,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
Promise::PromiseState aState)
|
||||
: PromiseResolverMixin(aPromise, aValue, aState)
|
||||
{}
|
||||
|
||||
~PromiseResolverTask()
|
||||
{}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
RunInternal();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
class WorkerPromiseResolverTask MOZ_FINAL : public WorkerSameThreadRunnable,
|
||||
public PromiseResolverMixin
|
||||
{
|
||||
public:
|
||||
WorkerPromiseResolverTask(WorkerPrivate* aWorkerPrivate,
|
||||
Promise* aPromise,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
Promise::PromiseState aState)
|
||||
: WorkerSameThreadRunnable(aWorkerPrivate),
|
||||
PromiseResolverMixin(aPromise, aValue, aState)
|
||||
{}
|
||||
|
||||
~WorkerPromiseResolverTask()
|
||||
{}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
RunInternal();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
enum {
|
||||
SLOT_PROMISE = 0,
|
||||
SLOT_DATA
|
||||
|
@ -239,11 +171,12 @@ GetPromise(JSContext* aCx, JS::Handle<JSObject*> aFunc)
|
|||
}
|
||||
};
|
||||
|
||||
// Main thread runnable to resolve thenables.
|
||||
// Equivalent to the specification's ResolvePromiseViaThenableTask.
|
||||
class ThenableResolverMixin
|
||||
class ThenableResolverTask MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ThenableResolverMixin(Promise* aPromise,
|
||||
ThenableResolverTask(Promise* aPromise,
|
||||
JS::Handle<JSObject*> aThenable,
|
||||
PromiseInit* aThen)
|
||||
: mPromise(aPromise)
|
||||
|
@ -251,25 +184,26 @@ public:
|
|||
, mThen(aThen)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_COUNT_CTOR(ThenableResolverMixin);
|
||||
MOZ_COUNT_CTOR(ThenableResolverTask);
|
||||
}
|
||||
|
||||
virtual ~ThenableResolverMixin()
|
||||
virtual
|
||||
~ThenableResolverTask()
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
|
||||
MOZ_COUNT_DTOR(ThenableResolverMixin);
|
||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverTask);
|
||||
MOZ_COUNT_DTOR(ThenableResolverTask);
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
RunInternal()
|
||||
NS_IMETHOD
|
||||
Run() MOZ_OVERRIDE
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
|
||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverTask);
|
||||
ThreadsafeAutoJSContext cx;
|
||||
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
|
||||
MOZ_ASSERT(wrapper); // It was preserved!
|
||||
if (!wrapper) {
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
JSAutoCompartment ac(cx, wrapper);
|
||||
|
||||
|
@ -278,14 +212,14 @@ protected:
|
|||
|
||||
if (!resolveFunc) {
|
||||
mPromise->HandleException(cx);
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> rejectFunc(cx,
|
||||
mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Reject));
|
||||
if (!rejectFunc) {
|
||||
mPromise->HandleException(cx);
|
||||
return;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
LinkThenableCallables(cx, resolveFunc, rejectFunc);
|
||||
|
@ -319,6 +253,8 @@ protected:
|
|||
// the exception. FIXME(nsm): This should be reported to the error
|
||||
// console though, for debugging.
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -328,60 +264,6 @@ private:
|
|||
NS_DECL_OWNINGTHREAD;
|
||||
};
|
||||
|
||||
// Main thread runnable to resolve thenables.
|
||||
class ThenableResolverTask MOZ_FINAL : public nsRunnable,
|
||||
public ThenableResolverMixin
|
||||
{
|
||||
public:
|
||||
ThenableResolverTask(Promise* aPromise,
|
||||
JS::Handle<JSObject*> aThenable,
|
||||
PromiseInit* aThen)
|
||||
: ThenableResolverMixin(aPromise, aThenable, aThen)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
~ThenableResolverTask()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
RunInternal();
|
||||
return NS_OK;
|
||||
}
|
||||
};
|
||||
|
||||
// Worker thread runnable to resolve thenables.
|
||||
class WorkerThenableResolverTask MOZ_FINAL : public WorkerSameThreadRunnable,
|
||||
public ThenableResolverMixin
|
||||
{
|
||||
public:
|
||||
WorkerThenableResolverTask(WorkerPrivate* aWorkerPrivate,
|
||||
Promise* aPromise,
|
||||
JS::Handle<JSObject*> aThenable,
|
||||
PromiseInit* aThen)
|
||||
: WorkerSameThreadRunnable(aWorkerPrivate),
|
||||
ThenableResolverMixin(aPromise, aThenable, aThen)
|
||||
{
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
}
|
||||
|
||||
~WorkerThenableResolverTask()
|
||||
{}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
RunInternal();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// Promise
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Promise)
|
||||
|
@ -1017,19 +899,57 @@ Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
|
|||
// callbacks with promise's result. If promise's state is rejected, queue a
|
||||
// task to process our reject callbacks with promise's result.
|
||||
if (mState != Pending && !mTaskPending) {
|
||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
||||
nsRefPtr<PromiseTask> task = new PromiseTask(this);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
} else {
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
nsRefPtr<WorkerPromiseTask> task = new WorkerPromiseTask(worker, this);
|
||||
task->Dispatch(worker->GetJSContext());
|
||||
}
|
||||
nsRefPtr<PromiseTask> task = new PromiseTask(this);
|
||||
DispatchToMainOrWorkerThread(task);
|
||||
mTaskPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
class WrappedWorkerRunnable MOZ_FINAL : public WorkerSameThreadRunnable
|
||||
{
|
||||
public:
|
||||
WrappedWorkerRunnable(WorkerPrivate* aWorkerPrivate, nsIRunnable* aRunnable)
|
||||
: WorkerSameThreadRunnable(aWorkerPrivate)
|
||||
, mRunnable(aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(aRunnable);
|
||||
MOZ_COUNT_CTOR(WrappedWorkerRunnable);
|
||||
}
|
||||
|
||||
bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) MOZ_OVERRIDE
|
||||
{
|
||||
NS_ASSERT_OWNINGTHREAD(WrappedWorkerRunnable);
|
||||
mRunnable->Run();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual
|
||||
~WrappedWorkerRunnable()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WrappedWorkerRunnable);
|
||||
NS_ASSERT_OWNINGTHREAD(WrappedWorkerRunnable);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIRunnable> mRunnable;
|
||||
NS_DECL_OWNINGTHREAD
|
||||
};
|
||||
|
||||
/* static */ void
|
||||
Promise::DispatchToMainOrWorkerThread(nsIRunnable* aRunnable)
|
||||
{
|
||||
MOZ_ASSERT(aRunnable);
|
||||
if (NS_IsMainThread()) {
|
||||
NS_DispatchToCurrentThread(aRunnable);
|
||||
return;
|
||||
}
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
nsRefPtr<WrappedWorkerRunnable> task = new WrappedWorkerRunnable(worker, aRunnable);
|
||||
task->Dispatch(worker->GetJSContext());
|
||||
}
|
||||
|
||||
void
|
||||
Promise::RunTask()
|
||||
{
|
||||
|
@ -1170,18 +1090,9 @@ Promise::ResolveInternal(JSContext* aCx,
|
|||
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
||||
nsRefPtr<PromiseInit> thenCallback =
|
||||
new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
|
||||
if (NS_IsMainThread()) {
|
||||
nsRefPtr<ThenableResolverTask> task =
|
||||
new ThenableResolverTask(this, valueObj, thenCallback);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
} else {
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
nsRefPtr<WorkerThenableResolverTask> task =
|
||||
new WorkerThenableResolverTask(worker, this, valueObj, thenCallback);
|
||||
task->Dispatch(worker->GetJSContext());
|
||||
}
|
||||
|
||||
nsRefPtr<ThenableResolverTask> task =
|
||||
new ThenableResolverTask(this, valueObj, thenCallback);
|
||||
DispatchToMainOrWorkerThread(task);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -1214,17 +1125,9 @@ Promise::RunResolveTask(JS::Handle<JS::Value> aValue,
|
|||
// If the synchronous flag is unset, queue a task to process our
|
||||
// accept callbacks with value.
|
||||
if (aAsynchronous == AsyncTask) {
|
||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
||||
nsRefPtr<PromiseResolverTask> task =
|
||||
new PromiseResolverTask(this, aValue, aState);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
} else {
|
||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
||||
MOZ_ASSERT(worker);
|
||||
nsRefPtr<WorkerPromiseResolverTask> task =
|
||||
new WorkerPromiseResolverTask(worker, this, aValue, aState);
|
||||
task->Dispatch(worker->GetJSContext());
|
||||
}
|
||||
nsRefPtr<PromiseResolverTask> task =
|
||||
new PromiseResolverTask(this, aValue, aState);
|
||||
DispatchToMainOrWorkerThread(task);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,7 +55,6 @@ class Promise MOZ_FINAL : public nsISupports,
|
|||
public SupportsWeakPtr<Promise>
|
||||
{
|
||||
friend class NativePromiseCallback;
|
||||
friend class PromiseResolverMixin;
|
||||
friend class PromiseResolverTask;
|
||||
friend class PromiseTask;
|
||||
friend class PromiseReportRejectFeature;
|
||||
|
@ -63,9 +62,7 @@ class Promise MOZ_FINAL : public nsISupports,
|
|||
friend class PromiseWorkerProxyRunnable;
|
||||
friend class RejectPromiseCallback;
|
||||
friend class ResolvePromiseCallback;
|
||||
friend class ThenableResolverMixin;
|
||||
friend class WorkerPromiseResolverTask;
|
||||
friend class WorkerPromiseTask;
|
||||
friend class ThenableResolverTask;
|
||||
friend class WrapperPromiseCallback;
|
||||
|
||||
~Promise();
|
||||
|
@ -192,6 +189,10 @@ private:
|
|||
mResult = aValue;
|
||||
}
|
||||
|
||||
// Queue an async task to current main or worker thread.
|
||||
static void
|
||||
DispatchToMainOrWorkerThread(nsIRunnable* aRunnable);
|
||||
|
||||
// This method processes promise's resolve/reject callbacks with promise's
|
||||
// result. It's executed when the resolver.resolve() or resolver.reject() is
|
||||
// called or when the promise already has a result and new callbacks are
|
||||
|
|
Загрузка…
Ссылка в новой задаче