mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1055925 - Refactor promise to merge main thread and worker thread tasks into a single task. r=nsm
This commit is contained in:
parent
e0bcb0e461
commit
3baf570af3
@ -51,12 +51,15 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
~PromiseTask()
|
~PromiseTask()
|
||||||
{
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(PromiseTask);
|
||||||
MOZ_COUNT_DTOR(PromiseTask);
|
MOZ_COUNT_DTOR(PromiseTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NS_IMETHOD Run()
|
NS_IMETHOD
|
||||||
|
Run() MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
|
NS_ASSERT_OWNINGTHREAD(PromiseTask);
|
||||||
mPromise->mTaskPending = false;
|
mPromise->mTaskPending = false;
|
||||||
mPromise->RunTask();
|
mPromise->RunTask();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
@ -64,67 +67,40 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
nsRefPtr<Promise> mPromise;
|
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:
|
public:
|
||||||
WorkerPromiseTask(WorkerPrivate* aWorkerPrivate, Promise* aPromise)
|
PromiseResolverTask(Promise* aPromise,
|
||||||
: WorkerSameThreadRunnable(aWorkerPrivate)
|
JS::Handle<JS::Value> aValue,
|
||||||
, mPromise(aPromise)
|
Promise::PromiseState aState)
|
||||||
{
|
|
||||||
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)
|
|
||||||
: mPromise(aPromise)
|
: mPromise(aPromise)
|
||||||
, mValue(CycleCollectedJSRuntime::Get()->Runtime(), aValue)
|
, mValue(CycleCollectedJSRuntime::Get()->Runtime(), aValue)
|
||||||
, mState(aState)
|
, mState(aState)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPromise);
|
MOZ_ASSERT(aPromise);
|
||||||
MOZ_ASSERT(mState != Promise::Pending);
|
MOZ_ASSERT(mState != Promise::Pending);
|
||||||
MOZ_COUNT_CTOR(PromiseResolverMixin);
|
MOZ_COUNT_CTOR(PromiseResolverTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~PromiseResolverMixin()
|
virtual
|
||||||
|
~PromiseResolverTask()
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
|
NS_ASSERT_OWNINGTHREAD(PromiseResolverTask);
|
||||||
MOZ_COUNT_DTOR(PromiseResolverMixin);
|
MOZ_COUNT_DTOR(PromiseResolverTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
NS_IMETHOD
|
||||||
void
|
Run() MOZ_OVERRIDE
|
||||||
RunInternal()
|
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(PromiseResolverMixin);
|
NS_ASSERT_OWNINGTHREAD(PromiseResolverTask);
|
||||||
mPromise->RunResolveTask(
|
mPromise->RunResolveTask(
|
||||||
JS::Handle<JS::Value>::fromMarkedLocation(mValue.address()),
|
JS::Handle<JS::Value>::fromMarkedLocation(mValue.address()),
|
||||||
mState, Promise::SyncTask);
|
mState, Promise::SyncTask);
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -134,50 +110,6 @@ private:
|
|||||||
NS_DECL_OWNINGTHREAD;
|
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 {
|
enum {
|
||||||
SLOT_PROMISE = 0,
|
SLOT_PROMISE = 0,
|
||||||
SLOT_DATA
|
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.
|
// Equivalent to the specification's ResolvePromiseViaThenableTask.
|
||||||
class ThenableResolverMixin
|
class ThenableResolverTask MOZ_FINAL : public nsRunnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ThenableResolverMixin(Promise* aPromise,
|
ThenableResolverTask(Promise* aPromise,
|
||||||
JS::Handle<JSObject*> aThenable,
|
JS::Handle<JSObject*> aThenable,
|
||||||
PromiseInit* aThen)
|
PromiseInit* aThen)
|
||||||
: mPromise(aPromise)
|
: mPromise(aPromise)
|
||||||
@ -251,25 +184,26 @@ public:
|
|||||||
, mThen(aThen)
|
, mThen(aThen)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aPromise);
|
MOZ_ASSERT(aPromise);
|
||||||
MOZ_COUNT_CTOR(ThenableResolverMixin);
|
MOZ_COUNT_CTOR(ThenableResolverTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ThenableResolverMixin()
|
virtual
|
||||||
|
~ThenableResolverTask()
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
|
NS_ASSERT_OWNINGTHREAD(ThenableResolverTask);
|
||||||
MOZ_COUNT_DTOR(ThenableResolverMixin);
|
MOZ_COUNT_DTOR(ThenableResolverTask);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void
|
NS_IMETHOD
|
||||||
RunInternal()
|
Run() MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
NS_ASSERT_OWNINGTHREAD(ThenableResolverMixin);
|
NS_ASSERT_OWNINGTHREAD(ThenableResolverTask);
|
||||||
ThreadsafeAutoJSContext cx;
|
ThreadsafeAutoJSContext cx;
|
||||||
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
|
JS::Rooted<JSObject*> wrapper(cx, mPromise->GetWrapper());
|
||||||
MOZ_ASSERT(wrapper); // It was preserved!
|
MOZ_ASSERT(wrapper); // It was preserved!
|
||||||
if (!wrapper) {
|
if (!wrapper) {
|
||||||
return;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
JSAutoCompartment ac(cx, wrapper);
|
JSAutoCompartment ac(cx, wrapper);
|
||||||
|
|
||||||
@ -278,14 +212,14 @@ protected:
|
|||||||
|
|
||||||
if (!resolveFunc) {
|
if (!resolveFunc) {
|
||||||
mPromise->HandleException(cx);
|
mPromise->HandleException(cx);
|
||||||
return;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS::Rooted<JSObject*> rejectFunc(cx,
|
JS::Rooted<JSObject*> rejectFunc(cx,
|
||||||
mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Reject));
|
mPromise->CreateThenableFunction(cx, mPromise, PromiseCallback::Reject));
|
||||||
if (!rejectFunc) {
|
if (!rejectFunc) {
|
||||||
mPromise->HandleException(cx);
|
mPromise->HandleException(cx);
|
||||||
return;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkThenableCallables(cx, resolveFunc, rejectFunc);
|
LinkThenableCallables(cx, resolveFunc, rejectFunc);
|
||||||
@ -319,6 +253,8 @@ protected:
|
|||||||
// the exception. FIXME(nsm): This should be reported to the error
|
// the exception. FIXME(nsm): This should be reported to the error
|
||||||
// console though, for debugging.
|
// console though, for debugging.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -328,60 +264,6 @@ private:
|
|||||||
NS_DECL_OWNINGTHREAD;
|
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
|
// Promise
|
||||||
|
|
||||||
NS_IMPL_CYCLE_COLLECTION_CLASS(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
|
// callbacks with promise's result. If promise's state is rejected, queue a
|
||||||
// task to process our reject callbacks with promise's result.
|
// task to process our reject callbacks with promise's result.
|
||||||
if (mState != Pending && !mTaskPending) {
|
if (mState != Pending && !mTaskPending) {
|
||||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
nsRefPtr<PromiseTask> task = new PromiseTask(this);
|
||||||
nsRefPtr<PromiseTask> task = new PromiseTask(this);
|
DispatchToMainOrWorkerThread(task);
|
||||||
NS_DispatchToCurrentThread(task);
|
|
||||||
} else {
|
|
||||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
|
||||||
MOZ_ASSERT(worker);
|
|
||||||
nsRefPtr<WorkerPromiseTask> task = new WorkerPromiseTask(worker, this);
|
|
||||||
task->Dispatch(worker->GetJSContext());
|
|
||||||
}
|
|
||||||
mTaskPending = true;
|
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
|
void
|
||||||
Promise::RunTask()
|
Promise::RunTask()
|
||||||
{
|
{
|
||||||
@ -1170,18 +1090,9 @@ Promise::ResolveInternal(JSContext* aCx,
|
|||||||
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
JS::Rooted<JSObject*> thenObj(aCx, &then.toObject());
|
||||||
nsRefPtr<PromiseInit> thenCallback =
|
nsRefPtr<PromiseInit> thenCallback =
|
||||||
new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
|
new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
|
||||||
if (NS_IsMainThread()) {
|
nsRefPtr<ThenableResolverTask> task =
|
||||||
nsRefPtr<ThenableResolverTask> task =
|
new ThenableResolverTask(this, valueObj, thenCallback);
|
||||||
new ThenableResolverTask(this, valueObj, thenCallback);
|
DispatchToMainOrWorkerThread(task);
|
||||||
NS_DispatchToCurrentThread(task);
|
|
||||||
} else {
|
|
||||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
|
||||||
MOZ_ASSERT(worker);
|
|
||||||
nsRefPtr<WorkerThenableResolverTask> task =
|
|
||||||
new WorkerThenableResolverTask(worker, this, valueObj, thenCallback);
|
|
||||||
task->Dispatch(worker->GetJSContext());
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1214,17 +1125,9 @@ Promise::RunResolveTask(JS::Handle<JS::Value> aValue,
|
|||||||
// If the synchronous flag is unset, queue a task to process our
|
// If the synchronous flag is unset, queue a task to process our
|
||||||
// accept callbacks with value.
|
// accept callbacks with value.
|
||||||
if (aAsynchronous == AsyncTask) {
|
if (aAsynchronous == AsyncTask) {
|
||||||
if (MOZ_LIKELY(NS_IsMainThread())) {
|
nsRefPtr<PromiseResolverTask> task =
|
||||||
nsRefPtr<PromiseResolverTask> task =
|
new PromiseResolverTask(this, aValue, aState);
|
||||||
new PromiseResolverTask(this, aValue, aState);
|
DispatchToMainOrWorkerThread(task);
|
||||||
NS_DispatchToCurrentThread(task);
|
|
||||||
} else {
|
|
||||||
WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
|
|
||||||
MOZ_ASSERT(worker);
|
|
||||||
nsRefPtr<WorkerPromiseResolverTask> task =
|
|
||||||
new WorkerPromiseResolverTask(worker, this, aValue, aState);
|
|
||||||
task->Dispatch(worker->GetJSContext());
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,7 +55,6 @@ class Promise MOZ_FINAL : public nsISupports,
|
|||||||
public SupportsWeakPtr<Promise>
|
public SupportsWeakPtr<Promise>
|
||||||
{
|
{
|
||||||
friend class NativePromiseCallback;
|
friend class NativePromiseCallback;
|
||||||
friend class PromiseResolverMixin;
|
|
||||||
friend class PromiseResolverTask;
|
friend class PromiseResolverTask;
|
||||||
friend class PromiseTask;
|
friend class PromiseTask;
|
||||||
friend class PromiseReportRejectFeature;
|
friend class PromiseReportRejectFeature;
|
||||||
@ -63,9 +62,7 @@ class Promise MOZ_FINAL : public nsISupports,
|
|||||||
friend class PromiseWorkerProxyRunnable;
|
friend class PromiseWorkerProxyRunnable;
|
||||||
friend class RejectPromiseCallback;
|
friend class RejectPromiseCallback;
|
||||||
friend class ResolvePromiseCallback;
|
friend class ResolvePromiseCallback;
|
||||||
friend class ThenableResolverMixin;
|
friend class ThenableResolverTask;
|
||||||
friend class WorkerPromiseResolverTask;
|
|
||||||
friend class WorkerPromiseTask;
|
|
||||||
friend class WrapperPromiseCallback;
|
friend class WrapperPromiseCallback;
|
||||||
|
|
||||||
~Promise();
|
~Promise();
|
||||||
@ -192,6 +189,10 @@ private:
|
|||||||
mResult = aValue;
|
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
|
// This method processes promise's resolve/reject callbacks with promise's
|
||||||
// result. It's executed when the resolver.resolve() or resolver.reject() is
|
// 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
|
// called or when the promise already has a result and new callbacks are
|
||||||
|
Loading…
Reference in New Issue
Block a user