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:
Andrea Marchesini 2013-06-19 20:57:38 -04:00
Родитель a64eba0ec3
Коммит 476be46aaf
22 изменённых файлов: 792 добавлений и 792 удалений

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

@ -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