зеркало из https://github.com/mozilla/gecko-dev.git
Bug 884279 - Rename Future to Promise. r=mounir
--HG-- rename : dom/future/Makefile.in => dom/promise/Makefile.in rename : dom/future/Future.cpp => dom/promise/Promise.cpp rename : dom/future/Future.h => dom/promise/Promise.h rename : dom/future/FutureCallback.cpp => dom/promise/PromiseCallback.cpp rename : dom/future/FutureCallback.h => dom/promise/PromiseCallback.h rename : dom/future/FutureResolver.cpp => dom/promise/PromiseResolver.cpp rename : dom/future/FutureResolver.h => dom/promise/PromiseResolver.h rename : dom/future/moz.build => dom/promise/moz.build rename : dom/future/tests/Makefile.in => dom/promise/tests/Makefile.in rename : dom/future/tests/moz.build => dom/promise/tests/moz.build rename : dom/future/tests/test_future.html => dom/promise/tests/test_promise.html rename : dom/future/tests/test_resolve.html => dom/promise/tests/test_resolve.html rename : dom/webidl/Future.webidl => dom/webidl/Promise.webidl
This commit is contained in:
Родитель
a64eba0ec3
Коммит
476be46aaf
|
@ -733,6 +733,6 @@ pref("ping.manifestURL", "https://marketplace.firefox.com/packaged.webapp");
|
|||
// Enable the disk space watcher
|
||||
pref("disk_space_watcher.enabled", true);
|
||||
|
||||
// Enable future
|
||||
pref("dom.future.enabled", false);
|
||||
// Enable promise
|
||||
pref("dom.promise.enabled", false);
|
||||
|
||||
|
|
|
@ -403,10 +403,6 @@ DOMInterfaces = {
|
|||
'nativeType': 'nsDOMFocusEvent',
|
||||
},
|
||||
|
||||
'Future': {
|
||||
'implicitJSContext': [ 'constructor' ]
|
||||
},
|
||||
|
||||
'GainNode': {
|
||||
'resultNotAddRefed': [ 'gain' ],
|
||||
},
|
||||
|
@ -770,6 +766,10 @@ DOMInterfaces = {
|
|||
'headerFile': 'nsGeolocation.h'
|
||||
},
|
||||
|
||||
'Promise': {
|
||||
'implicitJSContext': [ 'constructor' ]
|
||||
},
|
||||
|
||||
'PropertyNodeList': {
|
||||
'headerFile': 'HTMLPropertiesCollection.h',
|
||||
'resultNotAddRefed': [ 'item' ]
|
||||
|
|
|
@ -1,232 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "FutureCallback.h"
|
||||
#include "mozilla/dom/Future.h"
|
||||
#include "mozilla/dom/FutureResolver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FutureCallback)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FutureCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FutureCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(FutureCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(FutureCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
FutureCallback::FutureCallback()
|
||||
{
|
||||
MOZ_COUNT_CTOR(FutureCallback);
|
||||
}
|
||||
|
||||
FutureCallback::~FutureCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FutureCallback);
|
||||
}
|
||||
|
||||
// ResolveFutureCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolveFutureCallback,
|
||||
FutureCallback,
|
||||
mResolver)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ResolveFutureCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(FutureCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ResolveFutureCallback, FutureCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(ResolveFutureCallback, FutureCallback)
|
||||
|
||||
ResolveFutureCallback::ResolveFutureCallback(FutureResolver* aResolver)
|
||||
: mResolver(aResolver)
|
||||
{
|
||||
MOZ_ASSERT(aResolver);
|
||||
MOZ_COUNT_CTOR(ResolveFutureCallback);
|
||||
}
|
||||
|
||||
ResolveFutureCallback::~ResolveFutureCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ResolveFutureCallback);
|
||||
}
|
||||
|
||||
void
|
||||
ResolveFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
AutoJSContext cx;
|
||||
// FIXME Bug 878849
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
||||
ac.construct(cx, rooted);
|
||||
}
|
||||
|
||||
mResolver->ResolveInternal(cx, aValue, FutureResolver::SyncTask);
|
||||
}
|
||||
|
||||
// RejectFutureCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(RejectFutureCallback,
|
||||
FutureCallback,
|
||||
mResolver)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectFutureCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(FutureCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(RejectFutureCallback, FutureCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(RejectFutureCallback, FutureCallback)
|
||||
|
||||
RejectFutureCallback::RejectFutureCallback(FutureResolver* aResolver)
|
||||
: mResolver(aResolver)
|
||||
{
|
||||
MOZ_ASSERT(aResolver);
|
||||
MOZ_COUNT_CTOR(RejectFutureCallback);
|
||||
}
|
||||
|
||||
RejectFutureCallback::~RejectFutureCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RejectFutureCallback);
|
||||
}
|
||||
|
||||
void
|
||||
RejectFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
AutoJSContext cx;
|
||||
// FIXME Bug 878849
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
||||
ac.construct(cx, rooted);
|
||||
}
|
||||
|
||||
mResolver->RejectInternal(cx, aValue, FutureResolver::SyncTask);
|
||||
}
|
||||
|
||||
// WrapperFutureCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(WrapperFutureCallback,
|
||||
FutureCallback,
|
||||
mNextResolver, mCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WrapperFutureCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(FutureCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(WrapperFutureCallback, FutureCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(WrapperFutureCallback, FutureCallback)
|
||||
|
||||
WrapperFutureCallback::WrapperFutureCallback(FutureResolver* aNextResolver,
|
||||
AnyCallback* aCallback)
|
||||
: mNextResolver(aNextResolver)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aNextResolver);
|
||||
MOZ_COUNT_CTOR(WrapperFutureCallback);
|
||||
}
|
||||
|
||||
WrapperFutureCallback::~WrapperFutureCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WrapperFutureCallback);
|
||||
}
|
||||
|
||||
void
|
||||
WrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
AutoJSContext cx;
|
||||
// FIXME Bug 878849
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
||||
ac.construct(cx, rooted);
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
// If invoking callback threw an exception, run resolver's reject with the
|
||||
// thrown exception as argument and the synchronous flag set.
|
||||
Optional<JS::Handle<JS::Value> > value(cx,
|
||||
mCallback->Call(mNextResolver->GetParentObject(), aValue, rv,
|
||||
CallbackObject::eRethrowExceptions));
|
||||
|
||||
rv.WouldReportJSException();
|
||||
|
||||
if (rv.Failed() && rv.IsJSException()) {
|
||||
Optional<JS::Handle<JS::Value> > value(cx);
|
||||
rv.StealJSException(cx, &value.Value());
|
||||
mNextResolver->RejectInternal(cx, value, FutureResolver::SyncTask);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, run resolver's resolve with value and the synchronous flag
|
||||
// set.
|
||||
mNextResolver->ResolveInternal(cx, value, FutureResolver::SyncTask);
|
||||
}
|
||||
|
||||
// SimpleWrapperFutureCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(SimpleWrapperFutureCallback,
|
||||
FutureCallback,
|
||||
mFuture, mCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SimpleWrapperFutureCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(FutureCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SimpleWrapperFutureCallback, FutureCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(SimpleWrapperFutureCallback, FutureCallback)
|
||||
|
||||
SimpleWrapperFutureCallback::SimpleWrapperFutureCallback(Future* aFuture,
|
||||
AnyCallback* aCallback)
|
||||
: mFuture(aFuture)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aFuture);
|
||||
MOZ_COUNT_CTOR(SimpleWrapperFutureCallback);
|
||||
}
|
||||
|
||||
SimpleWrapperFutureCallback::~SimpleWrapperFutureCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(SimpleWrapperFutureCallback);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleWrapperFutureCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
ErrorResult rv;
|
||||
mCallback->Call(mFuture, aValue, rv);
|
||||
}
|
||||
|
||||
/* static */ FutureCallback*
|
||||
FutureCallback::Factory(FutureResolver* aNextResolver,
|
||||
AnyCallback* aCallback, Task aTask)
|
||||
{
|
||||
MOZ_ASSERT(aNextResolver);
|
||||
|
||||
// If we have a callback and a next resolver, we have to exec the callback and
|
||||
// then propagate the return value to the next resolver->resolve().
|
||||
if (aCallback) {
|
||||
return new WrapperFutureCallback(aNextResolver, aCallback);
|
||||
}
|
||||
|
||||
if (aTask == Resolve) {
|
||||
return new ResolveFutureCallback(aNextResolver);
|
||||
}
|
||||
|
||||
if (aTask == Reject) {
|
||||
return new RejectFutureCallback(aNextResolver);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "This should not happen");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,121 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_FutureCallback_h
|
||||
#define mozilla_dom_FutureCallback_h
|
||||
|
||||
#include "mozilla/dom/Future.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FutureResolver;
|
||||
|
||||
// This is the base class for any FutureCallback.
|
||||
// It's a logical step in the future chain of callbacks.
|
||||
class FutureCallback : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(FutureCallback)
|
||||
|
||||
FutureCallback();
|
||||
virtual ~FutureCallback();
|
||||
|
||||
virtual void Call(const Optional<JS::Handle<JS::Value> >& aValue) = 0;
|
||||
|
||||
enum Task {
|
||||
Resolve,
|
||||
Reject
|
||||
};
|
||||
|
||||
// This factory returns a FutureCallback object with refcount of 0.
|
||||
static FutureCallback*
|
||||
Factory(FutureResolver* aNextResolver, AnyCallback* aCallback,
|
||||
Task aTask);
|
||||
};
|
||||
|
||||
// WrapperFutureCallback execs a JS Callback with a value, and then the return
|
||||
// value is sent to the aNextResolver->resolve() or to aNextResolver->Reject()
|
||||
// if the JS Callback throws.
|
||||
class WrapperFutureCallback MOZ_FINAL : public FutureCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WrapperFutureCallback,
|
||||
FutureCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
WrapperFutureCallback(FutureResolver* aNextResolver,
|
||||
AnyCallback* aCallback);
|
||||
~WrapperFutureCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<FutureResolver> mNextResolver;
|
||||
nsRefPtr<AnyCallback> mCallback;
|
||||
};
|
||||
|
||||
// SimpleWrapperFutureCallback execs a JS Callback with a value.
|
||||
class SimpleWrapperFutureCallback MOZ_FINAL : public FutureCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SimpleWrapperFutureCallback,
|
||||
FutureCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
SimpleWrapperFutureCallback(Future* aFuture,
|
||||
AnyCallback* aCallback);
|
||||
~SimpleWrapperFutureCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<Future> mFuture;
|
||||
nsRefPtr<AnyCallback> mCallback;
|
||||
};
|
||||
|
||||
// ResolveFutureCallback calls aResolver->Resolve() with the value received by
|
||||
// Call().
|
||||
class ResolveFutureCallback MOZ_FINAL : public FutureCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ResolveFutureCallback,
|
||||
FutureCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
ResolveFutureCallback(FutureResolver* aResolver);
|
||||
~ResolveFutureCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<FutureResolver> mResolver;
|
||||
};
|
||||
|
||||
// RejectFutureCallback calls aResolver->Reject() with the value received by
|
||||
// Call().
|
||||
class RejectFutureCallback MOZ_FINAL : public FutureCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RejectFutureCallback,
|
||||
FutureCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
RejectFutureCallback(FutureResolver* aResolver);
|
||||
~RejectFutureCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<FutureResolver> mResolver;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_FutureCallback_h
|
|
@ -1,171 +0,0 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/FutureResolver.h"
|
||||
#include "mozilla/dom/FutureBinding.h"
|
||||
#include "mozilla/dom/Future.h"
|
||||
#include "FutureCallback.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// FutureResolverTask
|
||||
|
||||
// This class processes the future's callbacks with future's result.
|
||||
class FutureResolverTask MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
FutureResolverTask(FutureResolver* aResolver,
|
||||
const JS::Handle<JS::Value> aValue,
|
||||
Future::FutureState aState)
|
||||
: mResolver(aResolver)
|
||||
, mValue(aValue)
|
||||
, mState(aState)
|
||||
{
|
||||
MOZ_ASSERT(aResolver);
|
||||
MOZ_ASSERT(mState != Future::Pending);
|
||||
MOZ_COUNT_CTOR(FutureResolverTask);
|
||||
|
||||
JSContext* cx = nsContentUtils::GetSafeJSContext();
|
||||
JS_AddNamedValueRootRT(JS_GetRuntime(cx), &mValue,
|
||||
"FutureResolverTask.mValue");
|
||||
}
|
||||
|
||||
~FutureResolverTask()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FutureResolverTask);
|
||||
|
||||
JSContext* cx = nsContentUtils::GetSafeJSContext();
|
||||
JS_RemoveValueRootRT(JS_GetRuntime(cx), &mValue);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mResolver->RunTask(JS::Handle<JS::Value>::fromMarkedLocation(&mValue),
|
||||
mState, FutureResolver::SyncTask);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<FutureResolver> mResolver;
|
||||
JS::Value mValue;
|
||||
Future::FutureState mState;
|
||||
};
|
||||
|
||||
// FutureResolver
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(FutureResolver, mFuture)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(FutureResolver)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(FutureResolver)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(FutureResolver)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
FutureResolver::FutureResolver(Future* aFuture)
|
||||
: mFuture(aFuture)
|
||||
, mResolvePending(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
FutureResolver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return FutureResolverBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
void
|
||||
FutureResolver::Resolve(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aAsynchronous)
|
||||
{
|
||||
if (mResolvePending) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResolveInternal(aCx, aValue, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
FutureResolver::ResolveInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aAsynchronous)
|
||||
{
|
||||
mResolvePending = true;
|
||||
|
||||
// TODO: Bug 879245 - Then-able objects
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> valueObj(aCx, &aValue.Value().toObject());
|
||||
Future* nextFuture;
|
||||
nsresult rv = UnwrapObject<Future>(aCx, valueObj, nextFuture);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsRefPtr<FutureCallback> resolveCb = new ResolveFutureCallback(this);
|
||||
nsRefPtr<FutureCallback> rejectCb = new RejectFutureCallback(this);
|
||||
nextFuture->AppendCallbacks(resolveCb, rejectCb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the synchronous flag is set, process future's resolve callbacks with
|
||||
// value. Otherwise, the synchronous flag is unset, queue a task to process
|
||||
// future's resolve callbacks with value. Otherwise, the synchronous flag is
|
||||
// unset, queue a task to process future's resolve callbacks with value.
|
||||
RunTask(aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
|
||||
Future::Resolved, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
FutureResolver::Reject(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aAsynchronous)
|
||||
{
|
||||
if (mResolvePending) {
|
||||
return;
|
||||
}
|
||||
|
||||
RejectInternal(aCx, aValue, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
FutureResolver::RejectInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aAsynchronous)
|
||||
{
|
||||
mResolvePending = true;
|
||||
|
||||
// If the synchronous flag is set, process future's reject callbacks with
|
||||
// value. Otherwise, the synchronous flag is unset, queue a task to process
|
||||
// future's reject callbacks with value.
|
||||
RunTask(aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
|
||||
Future::Rejected, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
FutureResolver::RunTask(JS::Handle<JS::Value> aValue,
|
||||
Future::FutureState aState,
|
||||
FutureTaskSync aAsynchronous)
|
||||
{
|
||||
// If the synchronous flag is unset, queue a task to process future's
|
||||
// accept callbacks with value.
|
||||
if (aAsynchronous == AsyncTask) {
|
||||
nsRefPtr<FutureResolverTask> task =
|
||||
new FutureResolverTask(this, aValue, aState);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
return;
|
||||
}
|
||||
|
||||
mFuture->SetResult(aValue);
|
||||
mFuture->SetState(aState);
|
||||
mFuture->RunTask();
|
||||
mFuture = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -71,7 +71,7 @@ PARALLEL_DIRS += [
|
|||
'workers',
|
||||
'camera',
|
||||
'audiochannel',
|
||||
'future',
|
||||
'promise',
|
||||
'wappush'
|
||||
]
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ VPATH = @srcdir@
|
|||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = domfuture_s
|
||||
LIBRARY_NAME = dompromise_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
FAIL_ON_WARNINGS := 1
|
|
@ -4,49 +4,49 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/Future.h"
|
||||
#include "mozilla/dom/FutureBinding.h"
|
||||
#include "mozilla/dom/FutureResolver.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseBinding.h"
|
||||
#include "mozilla/dom/PromiseResolver.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "FutureCallback.h"
|
||||
#include "PromiseCallback.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// FutureTask
|
||||
// PromiseTask
|
||||
|
||||
// This class processes the future's callbacks with future's result.
|
||||
class FutureTask MOZ_FINAL : public nsRunnable
|
||||
// This class processes the promise's callbacks with promise's result.
|
||||
class PromiseTask MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
FutureTask(Future* aFuture)
|
||||
: mFuture(aFuture)
|
||||
PromiseTask(Promise* aPromise)
|
||||
: mPromise(aPromise)
|
||||
{
|
||||
MOZ_ASSERT(aFuture);
|
||||
MOZ_COUNT_CTOR(FutureTask);
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_COUNT_CTOR(PromiseTask);
|
||||
}
|
||||
|
||||
~FutureTask()
|
||||
~PromiseTask()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FutureTask);
|
||||
MOZ_COUNT_DTOR(PromiseTask);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mFuture->mTaskPending = false;
|
||||
mFuture->RunTask();
|
||||
mPromise->mTaskPending = false;
|
||||
mPromise->RunTask();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<Future> mFuture;
|
||||
nsRefPtr<Promise> mPromise;
|
||||
};
|
||||
|
||||
// Future
|
||||
// Promise
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Future)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Promise)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveCallbacks);
|
||||
|
@ -55,7 +55,7 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Future)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Future)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Promise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveCallbacks);
|
||||
|
@ -63,54 +63,54 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(Future)
|
|||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Future)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(Promise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JSVAL_MEMBER_CALLBACK(mResult)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Future)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Future)
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(Promise)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(Promise)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Future)
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Promise)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
Future::Future(nsPIDOMWindow* aWindow)
|
||||
Promise::Promise(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
, mResult(JS::UndefinedValue())
|
||||
, mState(Pending)
|
||||
, mTaskPending(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(Future);
|
||||
NS_HOLD_JS_OBJECTS(this, Future);
|
||||
MOZ_COUNT_CTOR(Promise);
|
||||
NS_HOLD_JS_OBJECTS(this, Promise);
|
||||
SetIsDOMBinding();
|
||||
|
||||
mResolver = new FutureResolver(this);
|
||||
mResolver = new PromiseResolver(this);
|
||||
}
|
||||
|
||||
Future::~Future()
|
||||
Promise::~Promise()
|
||||
{
|
||||
mResult = JSVAL_VOID;
|
||||
NS_DROP_JS_OBJECTS(this, Future);
|
||||
MOZ_COUNT_DTOR(Future);
|
||||
NS_DROP_JS_OBJECTS(this, Promise);
|
||||
MOZ_COUNT_DTOR(Promise);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Future::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
Promise::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return FutureBinding::Wrap(aCx, aScope, this);
|
||||
return PromiseBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Future::PrefEnabled()
|
||||
Promise::PrefEnabled()
|
||||
{
|
||||
return Preferences::GetBool("dom.future.enabled", false);
|
||||
return Preferences::GetBool("dom.promise.enabled", false);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Future>
|
||||
Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
FutureInit& aInit, ErrorResult& aRv)
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Promise::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
PromiseInit& aInit, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(PrefEnabled());
|
||||
|
||||
|
@ -120,23 +120,42 @@ Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Future> future = new Future(window);
|
||||
nsRefPtr<Promise> promise = new Promise(window);
|
||||
|
||||
aInit.Call(future, *future->mResolver, aRv,
|
||||
aInit.Call(promise, *promise->mResolver, aRv,
|
||||
CallbackObject::eRethrowExceptions);
|
||||
aRv.WouldReportJSException();
|
||||
|
||||
if (aRv.IsJSException()) {
|
||||
Optional<JS::Handle<JS::Value> > value(aCx);
|
||||
aRv.StealJSException(aCx, &value.Value());
|
||||
future->mResolver->Reject(aCx, value);
|
||||
promise->mResolver->Reject(aCx, value);
|
||||
}
|
||||
|
||||
return future.forget();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Future>
|
||||
Future::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Promise::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(PrefEnabled());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> promise = new Promise(window);
|
||||
|
||||
Optional<JS::Handle<JS::Value> > value(aCx, aValue);
|
||||
promise->mResolver->Resolve(aCx, value);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Promise>
|
||||
Promise::Reject(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(PrefEnabled());
|
||||
|
@ -147,81 +166,62 @@ Future::Resolve(const GlobalObject& aGlobal, JSContext* aCx,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Future> future = new Future(window);
|
||||
nsRefPtr<Promise> promise = new Promise(window);
|
||||
|
||||
Optional<JS::Handle<JS::Value> > value(aCx, aValue);
|
||||
future->mResolver->Resolve(aCx, value);
|
||||
return future.forget();
|
||||
promise->mResolver->Reject(aCx, value);
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Future>
|
||||
Future::Reject(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv)
|
||||
already_AddRefed<Promise>
|
||||
Promise::Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback)
|
||||
{
|
||||
MOZ_ASSERT(PrefEnabled());
|
||||
nsRefPtr<Promise> promise = new Promise(GetParentObject());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
nsRefPtr<PromiseCallback> resolveCb =
|
||||
PromiseCallback::Factory(promise->mResolver,
|
||||
aResolveCallback,
|
||||
PromiseCallback::Resolve);
|
||||
|
||||
nsRefPtr<Future> future = new Future(window);
|
||||
|
||||
Optional<JS::Handle<JS::Value> > value(aCx, aValue);
|
||||
future->mResolver->Reject(aCx, value);
|
||||
return future.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Future>
|
||||
Future::Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback)
|
||||
{
|
||||
nsRefPtr<Future> future = new Future(GetParentObject());
|
||||
|
||||
nsRefPtr<FutureCallback> resolveCb =
|
||||
FutureCallback::Factory(future->mResolver,
|
||||
aResolveCallback,
|
||||
FutureCallback::Resolve);
|
||||
|
||||
nsRefPtr<FutureCallback> rejectCb =
|
||||
FutureCallback::Factory(future->mResolver,
|
||||
aRejectCallback,
|
||||
FutureCallback::Reject);
|
||||
nsRefPtr<PromiseCallback> rejectCb =
|
||||
PromiseCallback::Factory(promise->mResolver,
|
||||
aRejectCallback,
|
||||
PromiseCallback::Reject);
|
||||
|
||||
AppendCallbacks(resolveCb, rejectCb);
|
||||
|
||||
return future.forget();
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Future>
|
||||
Future::Catch(AnyCallback* aRejectCallback)
|
||||
already_AddRefed<Promise>
|
||||
Promise::Catch(AnyCallback* aRejectCallback)
|
||||
{
|
||||
return Then(nullptr, aRejectCallback);
|
||||
}
|
||||
|
||||
void
|
||||
Future::Done(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback)
|
||||
Promise::Done(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback)
|
||||
{
|
||||
if (!aResolveCallback && !aRejectCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<FutureCallback> resolveCb;
|
||||
nsRefPtr<PromiseCallback> resolveCb;
|
||||
if (aResolveCallback) {
|
||||
resolveCb = new SimpleWrapperFutureCallback(this, aResolveCallback);
|
||||
resolveCb = new SimpleWrapperPromiseCallback(this, aResolveCallback);
|
||||
}
|
||||
|
||||
nsRefPtr<FutureCallback> rejectCb;
|
||||
nsRefPtr<PromiseCallback> rejectCb;
|
||||
if (aRejectCallback) {
|
||||
rejectCb = new SimpleWrapperFutureCallback(this, aRejectCallback);
|
||||
rejectCb = new SimpleWrapperPromiseCallback(this, aRejectCallback);
|
||||
}
|
||||
|
||||
AppendCallbacks(resolveCb, rejectCb);
|
||||
}
|
||||
|
||||
void
|
||||
Future::AppendCallbacks(FutureCallback* aResolveCallback,
|
||||
FutureCallback* aRejectCallback)
|
||||
Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
|
||||
PromiseCallback* aRejectCallback)
|
||||
{
|
||||
if (aResolveCallback) {
|
||||
mResolveCallbacks.AppendElement(aResolveCallback);
|
||||
|
@ -231,22 +231,22 @@ Future::AppendCallbacks(FutureCallback* aResolveCallback,
|
|||
mRejectCallbacks.AppendElement(aRejectCallback);
|
||||
}
|
||||
|
||||
// If future's state is resolved, queue a task to process future's resolve
|
||||
// callbacks with future's result. If future's state is rejected, queue a task
|
||||
// to process future's reject callbacks with future's result.
|
||||
// If promise's state is resolved, queue a task to process promise's resolve
|
||||
// callbacks with promise's result. If promise's state is rejected, queue a task
|
||||
// to process promise's reject callbacks with promise's result.
|
||||
if (mState != Pending && !mTaskPending) {
|
||||
nsRefPtr<FutureTask> task = new FutureTask(this);
|
||||
nsRefPtr<PromiseTask> task = new PromiseTask(this);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
mTaskPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Future::RunTask()
|
||||
Promise::RunTask()
|
||||
{
|
||||
MOZ_ASSERT(mState != Pending);
|
||||
|
||||
nsTArray<nsRefPtr<FutureCallback> > callbacks;
|
||||
nsTArray<nsRefPtr<PromiseCallback> > callbacks;
|
||||
callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
|
||||
: mRejectCallbacks);
|
||||
mResolveCallbacks.Clear();
|
|
@ -4,14 +4,14 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_Future_h
|
||||
#define mozilla_dom_Future_h
|
||||
#ifndef mozilla_dom_Promise_h
|
||||
#define mozilla_dom_Promise_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/dom/FutureBinding.h"
|
||||
#include "mozilla/dom/PromiseBinding.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
|
@ -21,24 +21,24 @@ class nsPIDOMWindow;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FutureInit;
|
||||
class FutureCallback;
|
||||
class PromiseInit;
|
||||
class PromiseCallback;
|
||||
class AnyCallback;
|
||||
class FutureResolver;
|
||||
class PromiseResolver;
|
||||
|
||||
class Future MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class Promise MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class FutureTask;
|
||||
friend class FutureResolver;
|
||||
friend class FutureResolverTask;
|
||||
friend class PromiseTask;
|
||||
friend class PromiseResolver;
|
||||
friend class PromiseResolverTask;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Future)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
|
||||
|
||||
Future(nsPIDOMWindow* aWindow);
|
||||
~Future();
|
||||
Promise(nsPIDOMWindow* aWindow);
|
||||
~Promise();
|
||||
|
||||
static bool PrefEnabled();
|
||||
|
||||
|
@ -52,34 +52,34 @@ public:
|
|||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<Future>
|
||||
Constructor(const GlobalObject& aGlobal, JSContext* aCx, FutureInit& aInit,
|
||||
static already_AddRefed<Promise>
|
||||
Constructor(const GlobalObject& aGlobal, JSContext* aCx, PromiseInit& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Future>
|
||||
static already_AddRefed<Promise>
|
||||
Resolve(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Future>
|
||||
static already_AddRefed<Promise>
|
||||
Reject(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Future>
|
||||
already_AddRefed<Promise>
|
||||
Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
|
||||
|
||||
already_AddRefed<Future>
|
||||
already_AddRefed<Promise>
|
||||
Catch(AnyCallback* aRejectCallback);
|
||||
|
||||
void Done(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
|
||||
|
||||
private:
|
||||
enum FutureState {
|
||||
enum PromiseState {
|
||||
Pending,
|
||||
Resolved,
|
||||
Rejected
|
||||
};
|
||||
|
||||
void SetState(FutureState aState)
|
||||
void SetState(PromiseState aState)
|
||||
{
|
||||
MOZ_ASSERT(mState == Pending);
|
||||
MOZ_ASSERT(aState != Pending);
|
||||
|
@ -91,28 +91,28 @@ private:
|
|||
mResult = aValue;
|
||||
}
|
||||
|
||||
// This method processes future's resolve/reject callbacks with future's
|
||||
// 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 future already has a result and new callbacks are
|
||||
// called or when the promise already has a result and new callbacks are
|
||||
// appended by then(), catch() or done().
|
||||
void RunTask();
|
||||
|
||||
void AppendCallbacks(FutureCallback* aResolveCallback,
|
||||
FutureCallback* aRejectCallback);
|
||||
void AppendCallbacks(PromiseCallback* aResolveCallback,
|
||||
PromiseCallback* aRejectCallback);
|
||||
|
||||
nsRefPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
nsRefPtr<FutureResolver> mResolver;
|
||||
nsRefPtr<PromiseResolver> mResolver;
|
||||
|
||||
nsTArray<nsRefPtr<FutureCallback> > mResolveCallbacks;
|
||||
nsTArray<nsRefPtr<FutureCallback> > mRejectCallbacks;
|
||||
nsTArray<nsRefPtr<PromiseCallback> > mResolveCallbacks;
|
||||
nsTArray<nsRefPtr<PromiseCallback> > mRejectCallbacks;
|
||||
|
||||
JS::Heap<JS::Value> mResult;
|
||||
FutureState mState;
|
||||
PromiseState mState;
|
||||
bool mTaskPending;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_Future_h
|
||||
#endif // mozilla_dom_Promise_h
|
|
@ -0,0 +1,232 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PromiseCallback.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseResolver.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
PromiseCallback::PromiseCallback()
|
||||
{
|
||||
MOZ_COUNT_CTOR(PromiseCallback);
|
||||
}
|
||||
|
||||
PromiseCallback::~PromiseCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PromiseCallback);
|
||||
}
|
||||
|
||||
// ResolvePromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(ResolvePromiseCallback,
|
||||
PromiseCallback,
|
||||
mResolver)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ResolvePromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ResolvePromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(ResolvePromiseCallback, PromiseCallback)
|
||||
|
||||
ResolvePromiseCallback::ResolvePromiseCallback(PromiseResolver* aResolver)
|
||||
: mResolver(aResolver)
|
||||
{
|
||||
MOZ_ASSERT(aResolver);
|
||||
MOZ_COUNT_CTOR(ResolvePromiseCallback);
|
||||
}
|
||||
|
||||
ResolvePromiseCallback::~ResolvePromiseCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(ResolvePromiseCallback);
|
||||
}
|
||||
|
||||
void
|
||||
ResolvePromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
AutoJSContext cx;
|
||||
// FIXME Bug 878849
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
||||
ac.construct(cx, rooted);
|
||||
}
|
||||
|
||||
mResolver->ResolveInternal(cx, aValue, PromiseResolver::SyncTask);
|
||||
}
|
||||
|
||||
// RejectPromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_1(RejectPromiseCallback,
|
||||
PromiseCallback,
|
||||
mResolver)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectPromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(RejectPromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(RejectPromiseCallback, PromiseCallback)
|
||||
|
||||
RejectPromiseCallback::RejectPromiseCallback(PromiseResolver* aResolver)
|
||||
: mResolver(aResolver)
|
||||
{
|
||||
MOZ_ASSERT(aResolver);
|
||||
MOZ_COUNT_CTOR(RejectPromiseCallback);
|
||||
}
|
||||
|
||||
RejectPromiseCallback::~RejectPromiseCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(RejectPromiseCallback);
|
||||
}
|
||||
|
||||
void
|
||||
RejectPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
AutoJSContext cx;
|
||||
// FIXME Bug 878849
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
||||
ac.construct(cx, rooted);
|
||||
}
|
||||
|
||||
mResolver->RejectInternal(cx, aValue, PromiseResolver::SyncTask);
|
||||
}
|
||||
|
||||
// WrapperPromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(WrapperPromiseCallback,
|
||||
PromiseCallback,
|
||||
mNextResolver, mCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WrapperPromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(WrapperPromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(WrapperPromiseCallback, PromiseCallback)
|
||||
|
||||
WrapperPromiseCallback::WrapperPromiseCallback(PromiseResolver* aNextResolver,
|
||||
AnyCallback* aCallback)
|
||||
: mNextResolver(aNextResolver)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aNextResolver);
|
||||
MOZ_COUNT_CTOR(WrapperPromiseCallback);
|
||||
}
|
||||
|
||||
WrapperPromiseCallback::~WrapperPromiseCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(WrapperPromiseCallback);
|
||||
}
|
||||
|
||||
void
|
||||
WrapperPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
AutoJSContext cx;
|
||||
// FIXME Bug 878849
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> rooted(cx, &aValue.Value().toObject());
|
||||
ac.construct(cx, rooted);
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
// If invoking callback threw an exception, run resolver's reject with the
|
||||
// thrown exception as argument and the synchronous flag set.
|
||||
Optional<JS::Handle<JS::Value> > value(cx,
|
||||
mCallback->Call(mNextResolver->GetParentObject(), aValue, rv,
|
||||
CallbackObject::eRethrowExceptions));
|
||||
|
||||
rv.WouldReportJSException();
|
||||
|
||||
if (rv.Failed() && rv.IsJSException()) {
|
||||
Optional<JS::Handle<JS::Value> > value(cx);
|
||||
rv.StealJSException(cx, &value.Value());
|
||||
mNextResolver->RejectInternal(cx, value, PromiseResolver::SyncTask);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, run resolver's resolve with value and the synchronous flag
|
||||
// set.
|
||||
mNextResolver->ResolveInternal(cx, value, PromiseResolver::SyncTask);
|
||||
}
|
||||
|
||||
// SimpleWrapperPromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED_2(SimpleWrapperPromiseCallback,
|
||||
PromiseCallback,
|
||||
mPromise, mCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SimpleWrapperPromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(SimpleWrapperPromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(SimpleWrapperPromiseCallback, PromiseCallback)
|
||||
|
||||
SimpleWrapperPromiseCallback::SimpleWrapperPromiseCallback(Promise* aPromise,
|
||||
AnyCallback* aCallback)
|
||||
: mPromise(aPromise)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_COUNT_CTOR(SimpleWrapperPromiseCallback);
|
||||
}
|
||||
|
||||
SimpleWrapperPromiseCallback::~SimpleWrapperPromiseCallback()
|
||||
{
|
||||
MOZ_COUNT_DTOR(SimpleWrapperPromiseCallback);
|
||||
}
|
||||
|
||||
void
|
||||
SimpleWrapperPromiseCallback::Call(const Optional<JS::Handle<JS::Value> >& aValue)
|
||||
{
|
||||
ErrorResult rv;
|
||||
mCallback->Call(mPromise, aValue, rv);
|
||||
}
|
||||
|
||||
/* static */ PromiseCallback*
|
||||
PromiseCallback::Factory(PromiseResolver* aNextResolver,
|
||||
AnyCallback* aCallback, Task aTask)
|
||||
{
|
||||
MOZ_ASSERT(aNextResolver);
|
||||
|
||||
// If we have a callback and a next resolver, we have to exec the callback and
|
||||
// then propagate the return value to the next resolver->resolve().
|
||||
if (aCallback) {
|
||||
return new WrapperPromiseCallback(aNextResolver, aCallback);
|
||||
}
|
||||
|
||||
if (aTask == Resolve) {
|
||||
return new ResolvePromiseCallback(aNextResolver);
|
||||
}
|
||||
|
||||
if (aTask == Reject) {
|
||||
return new RejectPromiseCallback(aNextResolver);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "This should not happen");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,121 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PromiseCallback_h
|
||||
#define mozilla_dom_PromiseCallback_h
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class PromiseResolver;
|
||||
|
||||
// This is the base class for any PromiseCallback.
|
||||
// It's a logical step in the promise chain of callbacks.
|
||||
class PromiseCallback : public nsISupports
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(PromiseCallback)
|
||||
|
||||
PromiseCallback();
|
||||
virtual ~PromiseCallback();
|
||||
|
||||
virtual void Call(const Optional<JS::Handle<JS::Value> >& aValue) = 0;
|
||||
|
||||
enum Task {
|
||||
Resolve,
|
||||
Reject
|
||||
};
|
||||
|
||||
// This factory returns a PromiseCallback object with refcount of 0.
|
||||
static PromiseCallback*
|
||||
Factory(PromiseResolver* aNextResolver, AnyCallback* aCallback,
|
||||
Task aTask);
|
||||
};
|
||||
|
||||
// WrapperPromiseCallback execs a JS Callback with a value, and then the return
|
||||
// value is sent to the aNextResolver->resolve() or to aNextResolver->Reject()
|
||||
// if the JS Callback throws.
|
||||
class WrapperPromiseCallback MOZ_FINAL : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(WrapperPromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
WrapperPromiseCallback(PromiseResolver* aNextResolver,
|
||||
AnyCallback* aCallback);
|
||||
~WrapperPromiseCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<PromiseResolver> mNextResolver;
|
||||
nsRefPtr<AnyCallback> mCallback;
|
||||
};
|
||||
|
||||
// SimpleWrapperPromiseCallback execs a JS Callback with a value.
|
||||
class SimpleWrapperPromiseCallback MOZ_FINAL : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SimpleWrapperPromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
SimpleWrapperPromiseCallback(Promise* aPromise,
|
||||
AnyCallback* aCallback);
|
||||
~SimpleWrapperPromiseCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<Promise> mPromise;
|
||||
nsRefPtr<AnyCallback> mCallback;
|
||||
};
|
||||
|
||||
// ResolvePromiseCallback calls aResolver->Resolve() with the value received by
|
||||
// Call().
|
||||
class ResolvePromiseCallback MOZ_FINAL : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ResolvePromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
ResolvePromiseCallback(PromiseResolver* aResolver);
|
||||
~ResolvePromiseCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<PromiseResolver> mResolver;
|
||||
};
|
||||
|
||||
// RejectPromiseCallback calls aResolver->Reject() with the value received by
|
||||
// Call().
|
||||
class RejectPromiseCallback MOZ_FINAL : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(RejectPromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
void Call(const Optional<JS::Handle<JS::Value> >& aValue) MOZ_OVERRIDE;
|
||||
|
||||
RejectPromiseCallback(PromiseResolver* aResolver);
|
||||
~RejectPromiseCallback();
|
||||
|
||||
private:
|
||||
nsRefPtr<PromiseResolver> mResolver;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PromiseCallback_h
|
|
@ -0,0 +1,171 @@
|
|||
/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/PromiseResolver.h"
|
||||
#include "mozilla/dom/PromiseBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "PromiseCallback.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// PromiseResolverTask
|
||||
|
||||
// This class processes the promise's callbacks with promise's result.
|
||||
class PromiseResolverTask MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
PromiseResolverTask(PromiseResolver* aResolver,
|
||||
const JS::Handle<JS::Value> aValue,
|
||||
Promise::PromiseState aState)
|
||||
: mResolver(aResolver)
|
||||
, mValue(aValue)
|
||||
, mState(aState)
|
||||
{
|
||||
MOZ_ASSERT(aResolver);
|
||||
MOZ_ASSERT(mState != Promise::Pending);
|
||||
MOZ_COUNT_CTOR(PromiseResolverTask);
|
||||
|
||||
JSContext* cx = nsContentUtils::GetSafeJSContext();
|
||||
JS_AddNamedValueRootRT(JS_GetRuntime(cx), &mValue,
|
||||
"PromiseResolverTask.mValue");
|
||||
}
|
||||
|
||||
~PromiseResolverTask()
|
||||
{
|
||||
MOZ_COUNT_DTOR(PromiseResolverTask);
|
||||
|
||||
JSContext* cx = nsContentUtils::GetSafeJSContext();
|
||||
JS_RemoveValueRootRT(JS_GetRuntime(cx), &mValue);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mResolver->RunTask(JS::Handle<JS::Value>::fromMarkedLocation(&mValue),
|
||||
mState, PromiseResolver::SyncTask);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<PromiseResolver> mResolver;
|
||||
JS::Value mValue;
|
||||
Promise::PromiseState mState;
|
||||
};
|
||||
|
||||
// PromiseResolver
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(PromiseResolver, mPromise)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseResolver)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseResolver)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseResolver)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
PromiseResolver::PromiseResolver(Promise* aPromise)
|
||||
: mPromise(aPromise)
|
||||
, mResolvePending(false)
|
||||
{
|
||||
SetIsDOMBinding();
|
||||
}
|
||||
|
||||
JSObject*
|
||||
PromiseResolver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return PromiseResolverBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseResolver::Resolve(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
PromiseTaskSync aAsynchronous)
|
||||
{
|
||||
if (mResolvePending) {
|
||||
return;
|
||||
}
|
||||
|
||||
ResolveInternal(aCx, aValue, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseResolver::ResolveInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
PromiseTaskSync aAsynchronous)
|
||||
{
|
||||
mResolvePending = true;
|
||||
|
||||
// TODO: Bug 879245 - Then-able objects
|
||||
if (aValue.WasPassed() && aValue.Value().isObject()) {
|
||||
JS::Rooted<JSObject*> valueObj(aCx, &aValue.Value().toObject());
|
||||
Promise* nextPromise;
|
||||
nsresult rv = UnwrapObject<Promise>(aCx, valueObj, nextPromise);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
nsRefPtr<PromiseCallback> resolveCb = new ResolvePromiseCallback(this);
|
||||
nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this);
|
||||
nextPromise->AppendCallbacks(resolveCb, rejectCb);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If the synchronous flag is set, process promise's resolve callbacks with
|
||||
// value. Otherwise, the synchronous flag is unset, queue a task to process
|
||||
// promise's resolve callbacks with value. Otherwise, the synchronous flag is
|
||||
// unset, queue a task to process promise's resolve callbacks with value.
|
||||
RunTask(aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
|
||||
Promise::Resolved, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseResolver::Reject(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
PromiseTaskSync aAsynchronous)
|
||||
{
|
||||
if (mResolvePending) {
|
||||
return;
|
||||
}
|
||||
|
||||
RejectInternal(aCx, aValue, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseResolver::RejectInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
PromiseTaskSync aAsynchronous)
|
||||
{
|
||||
mResolvePending = true;
|
||||
|
||||
// If the synchronous flag is set, process promise's reject callbacks with
|
||||
// value. Otherwise, the synchronous flag is unset, queue a task to process
|
||||
// promise's reject callbacks with value.
|
||||
RunTask(aValue.WasPassed() ? aValue.Value() : JS::UndefinedHandleValue,
|
||||
Promise::Rejected, aAsynchronous);
|
||||
}
|
||||
|
||||
void
|
||||
PromiseResolver::RunTask(JS::Handle<JS::Value> aValue,
|
||||
Promise::PromiseState aState,
|
||||
PromiseTaskSync aAsynchronous)
|
||||
{
|
||||
// If the synchronous flag is unset, queue a task to process promise's
|
||||
// accept callbacks with value.
|
||||
if (aAsynchronous == AsyncTask) {
|
||||
nsRefPtr<PromiseResolverTask> task =
|
||||
new PromiseResolverTask(this, aValue, aState);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
return;
|
||||
}
|
||||
|
||||
mPromise->SetResult(aValue);
|
||||
mPromise->SetState(aState);
|
||||
mPromise->RunTask();
|
||||
mPromise = nullptr;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -4,10 +4,10 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_FutureResolver_h
|
||||
#define mozilla_dom_FutureResolver_h
|
||||
#ifndef mozilla_dom_PromiseResolver_h
|
||||
#define mozilla_dom_PromiseResolver_h
|
||||
|
||||
#include "mozilla/dom/Future.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
@ -18,53 +18,53 @@ struct JSContext;
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FutureResolver MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
class PromiseResolver MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class FutureResolverTask;
|
||||
friend class WrapperFutureCallback;
|
||||
friend class ResolveFutureCallback;
|
||||
friend class RejectFutureCallback;
|
||||
friend class PromiseResolverTask;
|
||||
friend class WrapperPromiseCallback;
|
||||
friend class ResolvePromiseCallback;
|
||||
friend class RejectPromiseCallback;
|
||||
|
||||
private:
|
||||
enum FutureTaskSync {
|
||||
enum PromiseTaskSync {
|
||||
SyncTask,
|
||||
AsyncTask
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FutureResolver)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PromiseResolver)
|
||||
|
||||
FutureResolver(Future* aFuture);
|
||||
PromiseResolver(Promise* aPromise);
|
||||
|
||||
Future* GetParentObject() const
|
||||
Promise* GetParentObject() const
|
||||
{
|
||||
return mFuture;
|
||||
return mPromise;
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
void Resolve(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
PromiseTaskSync aSync = AsyncTask);
|
||||
|
||||
void Reject(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
PromiseTaskSync aSync = AsyncTask);
|
||||
|
||||
private:
|
||||
void ResolveInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
PromiseTaskSync aSync = AsyncTask);
|
||||
|
||||
void RejectInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
PromiseTaskSync aSync = AsyncTask);
|
||||
|
||||
void RunTask(JS::Handle<JS::Value> aValue,
|
||||
Future::FutureState aState, FutureTaskSync aSync);
|
||||
Promise::PromiseState aState, PromiseTaskSync aSync);
|
||||
|
||||
nsRefPtr<Future> mFuture;
|
||||
nsRefPtr<Promise> mPromise;
|
||||
|
||||
bool mResolvePending;
|
||||
};
|
||||
|
@ -72,4 +72,4 @@ private:
|
|||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_FutureResolver_h
|
||||
#endif // mozilla_dom_PromiseResolver_h
|
|
@ -6,17 +6,17 @@
|
|||
|
||||
TEST_DIRS += ['tests']
|
||||
|
||||
XPIDL_MODULE = 'dom_future'
|
||||
XPIDL_MODULE = 'dom_promise'
|
||||
|
||||
MODULE = 'dom'
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Future.h',
|
||||
'FutureResolver.h',
|
||||
'Promise.h',
|
||||
'PromiseResolver.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'Future.cpp',
|
||||
'FutureResolver.cpp',
|
||||
'FutureCallback.cpp',
|
||||
'Promise.cpp',
|
||||
'PromiseResolver.cpp',
|
||||
'PromiseCallback.cpp',
|
||||
]
|
|
@ -12,7 +12,7 @@ relativesrcdir = @relativesrcdir@
|
|||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
test_future.html \
|
||||
test_promise.html \
|
||||
test_resolve.html \
|
||||
$(NULL)
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Basic Future Test</title>
|
||||
<title>Basic Promise Test</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
@ -16,13 +16,13 @@
|
|||
<pre id="test">
|
||||
<script type="application/javascript"><!--
|
||||
|
||||
function futureResolve() {
|
||||
ok(Future, "Future object should exist");
|
||||
function promiseResolve() {
|
||||
ok(Promise, "Promise object should exist");
|
||||
|
||||
var future = new Future(function(resolver) {
|
||||
ok(resolver, "FutureResolver exists");
|
||||
ok("reject" in resolver, "FutureResolver.reject exists");
|
||||
ok("resolve" in resolver, "FutureResolver.resolve exists");
|
||||
var promise = new Promise(function(resolver) {
|
||||
ok(resolver, "PromiseResolver exists");
|
||||
ok("reject" in resolver, "PromiseResolver.reject exists");
|
||||
ok("resolve" in resolver, "PromiseResolver.resolve exists");
|
||||
|
||||
resolver.resolve(42);
|
||||
}).done(function(what) {
|
||||
|
@ -35,8 +35,8 @@ function futureResolve() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureReject() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseReject() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.reject(42);
|
||||
}).done(function(what) {
|
||||
ok(false, "Done - resolveCb has been called");
|
||||
|
@ -48,8 +48,8 @@ function futureReject() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureException() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseException() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
throw 42;
|
||||
}).done(function(what) {
|
||||
ok(false, "Done - resolveCb has been called");
|
||||
|
@ -61,16 +61,16 @@ function futureException() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureGC() {
|
||||
function promiseGC() {
|
||||
var resolver;
|
||||
var future = new Future(function(r) {
|
||||
var promise = new Promise(function(r) {
|
||||
resolver = r;
|
||||
}).done(function(what) {
|
||||
ok(true, "Done - future is still alive");
|
||||
ok(true, "Done - promise is still alive");
|
||||
runTest();
|
||||
});
|
||||
|
||||
future = null;
|
||||
promise = null;
|
||||
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.forceGC();
|
||||
|
@ -79,9 +79,9 @@ function futureGC() {
|
|||
resolver.resolve(42);
|
||||
}
|
||||
|
||||
function futureAsync() {
|
||||
function promiseAsync() {
|
||||
var global = "foo";
|
||||
var f = new Future(function(r) {
|
||||
var f = new Promise(function(r) {
|
||||
is(global, "foo", "Global should be foo");
|
||||
r.resolve(42);
|
||||
is(global, "foo", "Global should still be foo");
|
||||
|
@ -95,13 +95,13 @@ function futureAsync() {
|
|||
is(global, "foo", "Global should still be foo (2)");
|
||||
}
|
||||
|
||||
function futureDoubleDone() {
|
||||
function promiseDoubleDone() {
|
||||
var steps = 0;
|
||||
var future = new Future(function(resolver) {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.resolve(42);
|
||||
});
|
||||
|
||||
future.done(function(what) {
|
||||
promise.done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
steps++;
|
||||
|
@ -109,7 +109,7 @@ function futureDoubleDone() {
|
|||
ok(false, "Done.reject has been called");
|
||||
});
|
||||
|
||||
future.done(function(what) {
|
||||
promise.done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
is(steps, 1, "Done.resolve - step == 1");
|
||||
is(what, 42, "Value == 42");
|
||||
|
@ -119,8 +119,8 @@ function futureDoubleDone() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureDoneException() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseDoneException() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.resolve(42);
|
||||
});
|
||||
|
||||
|
@ -131,18 +131,18 @@ function futureDoneException() {
|
|||
runTest();
|
||||
};
|
||||
|
||||
future.done(function(what) {
|
||||
promise.done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
throw "booh";
|
||||
});
|
||||
}
|
||||
|
||||
function futureThenCatchDone() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseThenCatchDone() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.resolve(42);
|
||||
});
|
||||
|
||||
var future2 = future.then(function(what) {
|
||||
var promise2 = promise.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
return what + 1;
|
||||
|
@ -150,9 +150,9 @@ function futureThenCatchDone() {
|
|||
ok(false, "Then.reject has been called");
|
||||
});
|
||||
|
||||
isnot(future, future2, "These 2 future objs are different");
|
||||
isnot(promise, promise2, "These 2 promise objs are different");
|
||||
|
||||
future2.then(function(what) {
|
||||
promise2.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 43, "Value == 43");
|
||||
return what + 1;
|
||||
|
@ -169,12 +169,12 @@ function futureThenCatchDone() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureRejectThenCatchDone() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseRejectThenCatchDone() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.reject(42);
|
||||
});
|
||||
|
||||
var future2 = future.then(function(what) {
|
||||
var promise2 = promise.then(function(what) {
|
||||
ok(false, "Then.resolve has been called");
|
||||
}, function(what) {
|
||||
ok(true, "Then.reject has been called");
|
||||
|
@ -182,9 +182,9 @@ function futureRejectThenCatchDone() {
|
|||
return what + 1;
|
||||
});
|
||||
|
||||
isnot(future, future2, "These 2 future objs are different");
|
||||
isnot(promise, promise2, "These 2 promise objs are different");
|
||||
|
||||
future2.then(function(what) {
|
||||
promise2.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 43, "Value == 43");
|
||||
return what+1;
|
||||
|
@ -197,12 +197,12 @@ function futureRejectThenCatchDone() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureRejectThenCatchDone2() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseRejectThenCatchDone2() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.reject(42);
|
||||
});
|
||||
|
||||
future.then(function(what) {
|
||||
promise.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
return what+1;
|
||||
|
@ -217,12 +217,12 @@ function futureRejectThenCatchDone2() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureRejectThenCatchExceptionDone() {
|
||||
var future = new Future(function(resolver) {
|
||||
function promiseRejectThenCatchExceptionDone() {
|
||||
var promise = new Promise(function(resolver) {
|
||||
resolver.reject(42);
|
||||
});
|
||||
|
||||
future.then(function(what) {
|
||||
promise.then(function(what) {
|
||||
ok(false, "Then.resolve has been called");
|
||||
}, function(what) {
|
||||
ok(true, "Then.reject has been called");
|
||||
|
@ -239,9 +239,9 @@ function futureRejectThenCatchExceptionDone() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureThenCatchOrderingResolve() {
|
||||
function promiseThenCatchOrderingResolve() {
|
||||
var global = 0;
|
||||
var f = new Future(function(r) {
|
||||
var f = new Promise(function(r) {
|
||||
r.resolve(42);
|
||||
});
|
||||
|
||||
|
@ -262,9 +262,9 @@ function futureThenCatchOrderingResolve() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureThenCatchOrderingReject() {
|
||||
function promiseThenCatchOrderingReject() {
|
||||
var global = 0;
|
||||
var f = new Future(function(r) {
|
||||
var f = new Promise(function(r) {
|
||||
r.reject(42);
|
||||
})
|
||||
|
||||
|
@ -285,64 +285,64 @@ function futureThenCatchOrderingReject() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureNestedFuture() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
function promiseNestedPromise() {
|
||||
new Promise(function(resolver) {
|
||||
resolver.resolve(new Promise(function(r) {
|
||||
ok(true, "Nested promise is executed");
|
||||
r.resolve(42);
|
||||
}));
|
||||
}).then(function(value) {
|
||||
is(value, 42, "Nested future is executed and then == 42");
|
||||
is(value, 42, "Nested promise is executed and then == 42");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureNestedNestedFuture() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
function promiseNestedNestedPromise() {
|
||||
new Promise(function(resolver) {
|
||||
resolver.resolve(new Promise(function(r) {
|
||||
ok(true, "Nested promise is executed");
|
||||
r.resolve(42);
|
||||
}).then(function(what) { return what+1; }));
|
||||
}).then(function(value) {
|
||||
is(value, 43, "Nested future is executed and then == 43");
|
||||
is(value, 43, "Nested promise is executed and then == 43");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureWrongNestedFuture() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
function promiseWrongNestedPromise() {
|
||||
new Promise(function(resolver) {
|
||||
resolver.resolve(new Promise(function(r) {
|
||||
ok(true, "Nested promise is executed");
|
||||
r.resolve(42);
|
||||
}));
|
||||
resolver.reject(42);
|
||||
}).then(function(value) {
|
||||
is(value, 42, "Nested future is executed and then == 42");
|
||||
is(value, 42, "Nested promise is executed and then == 42");
|
||||
runTest();
|
||||
}, function(value) {
|
||||
ok(false, "This is wrong");
|
||||
});
|
||||
}
|
||||
|
||||
function futureLoop() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
r.resolve(new Future(function(r) {
|
||||
ok(true, "Nested nested future is executed");
|
||||
function promiseLoop() {
|
||||
new Promise(function(resolver) {
|
||||
resolver.resolve(new Promise(function(r) {
|
||||
ok(true, "Nested promise is executed");
|
||||
r.resolve(new Promise(function(r) {
|
||||
ok(true, "Nested nested promise is executed");
|
||||
r.resolve(42);
|
||||
}));
|
||||
}));
|
||||
}).then(function(value) {
|
||||
is(value, 42, "Nested nested future is executed and then == 42");
|
||||
is(value, 42, "Nested nested promise is executed and then == 42");
|
||||
runTest();
|
||||
}, function(value) {
|
||||
ok(false, "This is wrong");
|
||||
});
|
||||
}
|
||||
|
||||
function futureReject() {
|
||||
var future = Future.reject(42).done(function(what) {
|
||||
function promiseReject() {
|
||||
var promise = Promise.reject(42).done(function(what) {
|
||||
ok(false, "This should not be called");
|
||||
}, function(what) {
|
||||
is(what, 42, "Value == 42");
|
||||
|
@ -350,8 +350,8 @@ function futureReject() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureResolve() {
|
||||
var future = Future.resolve(42).done(function(what) {
|
||||
function promiseResolve() {
|
||||
var promise = Promise.resolve(42).done(function(what) {
|
||||
is(what, 42, "Value == 42");
|
||||
runTest();
|
||||
}, function() {
|
||||
|
@ -359,9 +359,9 @@ function futureResolve() {
|
|||
});
|
||||
}
|
||||
|
||||
function futureResolveNestedFuture() {
|
||||
var future = Future.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
function promiseResolveNestedPromise() {
|
||||
var promise = Promise.resolve(new Promise(function(r) {
|
||||
ok(true, "Nested promise is executed");
|
||||
r.resolve(42);
|
||||
}, function() {
|
||||
ok(false, "This should not be called");
|
||||
|
@ -373,18 +373,18 @@ function futureResolveNestedFuture() {
|
|||
});
|
||||
}
|
||||
|
||||
var tests = [ futureResolve, futureReject,
|
||||
futureException, futureGC, futureAsync,
|
||||
futureDoubleDone, futureDoneException,
|
||||
futureThenCatchDone, futureRejectThenCatchDone,
|
||||
futureRejectThenCatchDone2,
|
||||
futureRejectThenCatchExceptionDone,
|
||||
futureThenCatchOrderingResolve,
|
||||
futureThenCatchOrderingReject,
|
||||
futureNestedFuture, futureNestedNestedFuture,
|
||||
futureWrongNestedFuture, futureLoop,
|
||||
futureReject, futureResolve,
|
||||
futureResolveNestedFuture,
|
||||
var tests = [ promiseResolve, promiseReject,
|
||||
promiseException, promiseGC, promiseAsync,
|
||||
promiseDoubleDone, promiseDoneException,
|
||||
promiseThenCatchDone, promiseRejectThenCatchDone,
|
||||
promiseRejectThenCatchDone2,
|
||||
promiseRejectThenCatchExceptionDone,
|
||||
promiseThenCatchOrderingResolve,
|
||||
promiseThenCatchOrderingReject,
|
||||
promiseNestedPromise, promiseNestedNestedPromise,
|
||||
promiseWrongNestedPromise, promiseLoop,
|
||||
promiseReject, promiseResolve,
|
||||
promiseResolveNestedPromise,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
|
@ -397,13 +397,13 @@ function runTest() {
|
|||
test();
|
||||
}
|
||||
|
||||
var p = SpecialPowers.getBoolPref("dom.future.enabled");
|
||||
SpecialPowers.setBoolPref("dom.future.enabled", false);
|
||||
ok(!("Future" in window), "Future object should not exist if disabled by pref");
|
||||
SpecialPowers.setBoolPref("dom.future.enabled", p);
|
||||
var p = SpecialPowers.getBoolPref("dom.promise.enabled");
|
||||
SpecialPowers.setBoolPref("dom.promise.enabled", false);
|
||||
ok(!("Promise" in window), "Promise object should not exist if disabled by pref");
|
||||
SpecialPowers.setBoolPref("dom.promise.enabled", p);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.future.enabled", true]]}, runTest);
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
|
||||
// -->
|
||||
</script>
|
||||
</pre>
|
|
@ -4,7 +4,7 @@
|
|||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Future.resolve(anything) Test</title>
|
||||
<title>Promise.resolve(anything) Test</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
@ -44,12 +44,12 @@ function runTest() {
|
|||
|
||||
var test = tests.pop();
|
||||
|
||||
new Future(function(resolver) {
|
||||
new Promise(function(resolver) {
|
||||
resolver.resolve(test);
|
||||
}).then(function(what) {
|
||||
ok(test === what, "What is: " + what);
|
||||
}, cbError).done(function() {
|
||||
new Future(function(resolver) {
|
||||
new Promise(function(resolver) {
|
||||
resolver.reject(test)
|
||||
}).then(cbError, function(what) {
|
||||
ok(test === what, "What is: " + what);
|
||||
|
@ -58,7 +58,7 @@ function runTest() {
|
|||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.future.enabled", true]]}, runTest);
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.promise.enabled", true]]}, runTest);
|
||||
// -->
|
||||
</script>
|
||||
</pre>
|
|
@ -4,32 +4,32 @@
|
|||
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dom.spec.whatwg.org/#futures
|
||||
* http://dom.spec.whatwg.org/#promises
|
||||
*/
|
||||
|
||||
interface FutureResolver {
|
||||
interface PromiseResolver {
|
||||
void resolve(optional any value);
|
||||
void reject(optional any value);
|
||||
};
|
||||
|
||||
callback FutureInit = void (FutureResolver resolver);
|
||||
callback PromiseInit = void (PromiseResolver resolver);
|
||||
callback AnyCallback = any (optional any value);
|
||||
|
||||
[PrefControlled, Constructor(FutureInit init)]
|
||||
interface Future {
|
||||
[PrefControlled, Constructor(PromiseInit init)]
|
||||
interface Promise {
|
||||
// TODO: update this interface - bug 875289
|
||||
|
||||
[Creator, Throws]
|
||||
static Future resolve(any value); // same as any(value)
|
||||
static Promise resolve(any value); // same as any(value)
|
||||
[Creator, Throws]
|
||||
static Future reject(any value);
|
||||
static Promise reject(any value);
|
||||
|
||||
[Creator]
|
||||
Future then(optional AnyCallback? resolveCallback = null,
|
||||
optional AnyCallback? rejectCallback = null);
|
||||
Promise then(optional AnyCallback? resolveCallback = null,
|
||||
optional AnyCallback? rejectCallback = null);
|
||||
|
||||
[Creator]
|
||||
Future catch(optional AnyCallback? rejectCallback = null);
|
||||
Promise catch(optional AnyCallback? rejectCallback = null);
|
||||
|
||||
void done(optional AnyCallback? resolveCallback = null,
|
||||
optional AnyCallback? rejectCallback = null);
|
|
@ -86,7 +86,6 @@ webidl_files = \
|
|||
FocusEvent.webidl \
|
||||
FormData.webidl \
|
||||
Function.webidl \
|
||||
Future.webidl \
|
||||
GainNode.webidl \
|
||||
Geolocation.webidl \
|
||||
HTMLAnchorElement.webidl \
|
||||
|
@ -207,6 +206,7 @@ webidl_files = \
|
|||
Position.webidl \
|
||||
PositionError.webidl \
|
||||
ProcessingInstruction.webidl \
|
||||
Promise.webidl \
|
||||
Range.webidl \
|
||||
Rect.webidl \
|
||||
RGBColor.webidl \
|
||||
|
|
|
@ -71,7 +71,7 @@ SHARED_LIBRARY_LIBS = \
|
|||
$(DEPTH)/dom/src/offline/$(LIB_PREFIX)jsdomoffline_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/src/geolocation/$(LIB_PREFIX)jsdomgeolocation_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/audiochannel/$(LIB_PREFIX)domaudiochannel_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/future/$(LIB_PREFIX)domfuture_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/promise/$(LIB_PREFIX)dompromise_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/src/notification/$(LIB_PREFIX)jsdomnotification_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/system/$(LIB_PREFIX)domsystem_s.$(LIB_SUFFIX) \
|
||||
$(DEPTH)/dom/workers/$(LIB_PREFIX)domworkers_s.$(LIB_SUFFIX) \
|
||||
|
|
|
@ -1832,11 +1832,11 @@ pref("dom.max_script_run_time", 10);
|
|||
// If true, ArchiveReader will be enabled
|
||||
pref("dom.archivereader.enabled", false);
|
||||
|
||||
// If true, Future will be enabled
|
||||
// If true, Promise will be enabled
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("dom.future.enabled", false);
|
||||
pref("dom.promise.enabled", false);
|
||||
#else
|
||||
pref("dom.future.enabled", true);
|
||||
pref("dom.promise.enabled", true);
|
||||
#endif
|
||||
|
||||
// Hang monitor timeout after which we kill the browser, in seconds
|
||||
|
|
Загрузка…
Ссылка в новой задаче