mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Back out 2ccb9ec11a9f:d27ecea31590 (bug 856410) for b2g mochitest-3 failures
CLOSED TREE
This commit is contained in:
parent
311073b449
commit
f6f5e5401f
@ -309,12 +309,6 @@ public:
|
||||
Optional_base<JS::Handle<T>, JS::Rooted<T> >()
|
||||
{}
|
||||
|
||||
Optional(JSContext* cx) :
|
||||
Optional_base<JS::Handle<T>, JS::Rooted<T> >()
|
||||
{
|
||||
this->Construct(cx);
|
||||
}
|
||||
|
||||
Optional(JSContext* cx, const T& aValue) :
|
||||
Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
|
||||
{}
|
||||
|
@ -160,19 +160,6 @@ ErrorResult::ReportJSException(JSContext* cx)
|
||||
JS_RemoveValueRoot(cx, &mJSException);
|
||||
}
|
||||
|
||||
void
|
||||
ErrorResult::StealJSException(JSContext* cx,
|
||||
JS::MutableHandle<JS::Value> value)
|
||||
{
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException,
|
||||
"Must call WouldReportJSException unconditionally in all codepaths that might call StealJSException");
|
||||
MOZ_ASSERT(IsJSException(), "No exception to steal");
|
||||
|
||||
value.set(mJSException);
|
||||
JS_RemoveValueRoot(cx, &mJSException);
|
||||
mResult = NS_OK;
|
||||
}
|
||||
|
||||
namespace dom {
|
||||
|
||||
bool
|
||||
|
@ -404,10 +404,6 @@ DOMInterfaces = {
|
||||
'nativeType': 'nsDOMFocusEvent',
|
||||
},
|
||||
|
||||
'Future': {
|
||||
'implicitJSContext': [ 'constructor' ]
|
||||
},
|
||||
|
||||
'GainNode': {
|
||||
'resultNotAddRefed': [ 'gain' ],
|
||||
},
|
||||
|
@ -64,18 +64,11 @@ public:
|
||||
// Facilities for throwing a preexisting JS exception value via this
|
||||
// ErrorResult. The contract is that any code which might end up calling
|
||||
// ThrowJSException() must call MightThrowJSException() even if no exception
|
||||
// is being thrown. Code that would call ReportJSException or
|
||||
// StealJSException as needed must first call WouldReportJSException even if
|
||||
// this ErrorResult has not failed.
|
||||
// is being thrown. Code that would call ReportJSException as needed must
|
||||
// first call WouldReportJSException even if this ErrorResult has not failed.
|
||||
void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
|
||||
void ReportJSException(JSContext* cx);
|
||||
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
|
||||
|
||||
// StealJSException steals the JS Exception from the object. This method must
|
||||
// be called only if IsJSException() returns true. This method also resets the
|
||||
// ErrorCode() to NS_OK.
|
||||
void StealJSException(JSContext* cx, JS::MutableHandle<JS::Value> value);
|
||||
|
||||
void MOZ_ALWAYS_INLINE MightThrowJSException()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
|
@ -1,264 +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/Future.h"
|
||||
#include "mozilla/dom/FutureBinding.h"
|
||||
#include "mozilla/dom/FutureResolver.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "FutureCallback.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
// FutureTask
|
||||
|
||||
// This class processes the future's callbacks with future's result.
|
||||
class FutureTask MOZ_FINAL : public nsRunnable
|
||||
{
|
||||
public:
|
||||
FutureTask(Future* aFuture)
|
||||
: mFuture(aFuture)
|
||||
{
|
||||
MOZ_ASSERT(aFuture);
|
||||
MOZ_COUNT_CTOR(FutureTask);
|
||||
}
|
||||
|
||||
~FutureTask()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FutureTask);
|
||||
}
|
||||
|
||||
NS_IMETHOD Run()
|
||||
{
|
||||
mFuture->mTaskPending = false;
|
||||
mFuture->RunTask();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsRefPtr<Future> mFuture;
|
||||
};
|
||||
|
||||
// Future
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Future)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolver)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveCallbacks);
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectCallbacks);
|
||||
tmp->mResult = JSVAL_VOID;
|
||||
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(mWindow)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolver)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveCallbacks);
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectCallbacks);
|
||||
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_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_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Future)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
Future::Future(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
, mResult(JS::UndefinedValue())
|
||||
, mState(Pending)
|
||||
, mTaskPending(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(Future);
|
||||
NS_HOLD_JS_OBJECTS(this, Future);
|
||||
SetIsDOMBinding();
|
||||
|
||||
mResolver = new FutureResolver(this);
|
||||
}
|
||||
|
||||
Future::~Future()
|
||||
{
|
||||
mResult = JSVAL_VOID;
|
||||
NS_DROP_JS_OBJECTS(this, Future);
|
||||
MOZ_COUNT_DTOR(Future);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
Future::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope)
|
||||
{
|
||||
return FutureBinding::Wrap(aCx, aScope, this);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
Future::PrefEnabled()
|
||||
{
|
||||
return Preferences::GetBool("dom.future.enabled", false);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Future>
|
||||
Future::Constructor(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
FutureInit& aInit, ErrorResult& aRv)
|
||||
{
|
||||
MOZ_ASSERT(PrefEnabled());
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.Get());
|
||||
if (!window) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Future> future = new Future(window);
|
||||
|
||||
aInit.Call(future, *future->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);
|
||||
}
|
||||
|
||||
return future.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Future>
|
||||
Future::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<Future> future = new Future(window);
|
||||
|
||||
Optional<JS::Handle<JS::Value> > value(aCx, aValue);
|
||||
future->mResolver->Resolve(aCx, value);
|
||||
return future.forget();
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<Future>
|
||||
Future::Reject(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<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);
|
||||
|
||||
AppendCallbacks(resolveCb, rejectCb);
|
||||
|
||||
return future.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Future>
|
||||
Future::Catch(AnyCallback* aRejectCallback)
|
||||
{
|
||||
return Then(nullptr, aRejectCallback);
|
||||
}
|
||||
|
||||
void
|
||||
Future::Done(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback)
|
||||
{
|
||||
if (!aResolveCallback && !aRejectCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<FutureCallback> resolveCb;
|
||||
if (aResolveCallback) {
|
||||
resolveCb = new SimpleWrapperFutureCallback(this, aResolveCallback);
|
||||
}
|
||||
|
||||
nsRefPtr<FutureCallback> rejectCb;
|
||||
if (aRejectCallback) {
|
||||
rejectCb = new SimpleWrapperFutureCallback(this, aRejectCallback);
|
||||
}
|
||||
|
||||
AppendCallbacks(resolveCb, rejectCb);
|
||||
}
|
||||
|
||||
void
|
||||
Future::AppendCallbacks(FutureCallback* aResolveCallback,
|
||||
FutureCallback* aRejectCallback)
|
||||
{
|
||||
if (aResolveCallback) {
|
||||
mResolveCallbacks.AppendElement(aResolveCallback);
|
||||
}
|
||||
|
||||
if (aRejectCallback) {
|
||||
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 (mState != Pending && !mTaskPending) {
|
||||
nsRefPtr<FutureTask> task = new FutureTask(this);
|
||||
NS_DispatchToCurrentThread(task);
|
||||
mTaskPending = true;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Future::RunTask()
|
||||
{
|
||||
MOZ_ASSERT(mState != Pending);
|
||||
|
||||
nsTArray<nsRefPtr<FutureCallback> > callbacks;
|
||||
callbacks.SwapElements(mState == Resolved ? mResolveCallbacks
|
||||
: mRejectCallbacks);
|
||||
mResolveCallbacks.Clear();
|
||||
mRejectCallbacks.Clear();
|
||||
|
||||
Optional<JS::Handle<JS::Value> > value(nsContentUtils::GetSafeJSContext(),
|
||||
mResult);
|
||||
|
||||
for (uint32_t i = 0; i < callbacks.Length(); ++i) {
|
||||
callbacks[i]->Call(value);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
@ -1,118 +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_Future_h
|
||||
#define mozilla_dom_Future_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/dom/FutureBinding.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
struct JSContext;
|
||||
class nsPIDOMWindow;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FutureInit;
|
||||
class FutureCallback;
|
||||
class AnyCallback;
|
||||
class FutureResolver;
|
||||
|
||||
class Future MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class FutureTask;
|
||||
friend class FutureResolver;
|
||||
friend class FutureResolverTask;
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Future)
|
||||
|
||||
Future(nsPIDOMWindow* aWindow);
|
||||
~Future();
|
||||
|
||||
static bool PrefEnabled();
|
||||
|
||||
// WebIDL
|
||||
|
||||
nsPIDOMWindow* GetParentObject() const
|
||||
{
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aScope) MOZ_OVERRIDE;
|
||||
|
||||
static already_AddRefed<Future>
|
||||
Constructor(const GlobalObject& aGlobal, JSContext* aCx, FutureInit& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Future>
|
||||
Resolve(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Future>
|
||||
Reject(const GlobalObject& aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Future>
|
||||
Then(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
|
||||
|
||||
already_AddRefed<Future>
|
||||
Catch(AnyCallback* aRejectCallback);
|
||||
|
||||
void Done(AnyCallback* aResolveCallback, AnyCallback* aRejectCallback);
|
||||
|
||||
private:
|
||||
enum FutureState {
|
||||
Pending,
|
||||
Resolved,
|
||||
Rejected
|
||||
};
|
||||
|
||||
void SetState(FutureState aState)
|
||||
{
|
||||
MOZ_ASSERT(mState == Pending);
|
||||
MOZ_ASSERT(aState != Pending);
|
||||
mState = aState;
|
||||
}
|
||||
|
||||
void SetResult(JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
mResult = aValue;
|
||||
}
|
||||
|
||||
// This method processes future's resolve/reject callbacks with future'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
|
||||
// appended by then(), catch() or done().
|
||||
void RunTask();
|
||||
|
||||
void AppendCallbacks(FutureCallback* aResolveCallback,
|
||||
FutureCallback* aRejectCallback);
|
||||
|
||||
nsRefPtr<nsPIDOMWindow> mWindow;
|
||||
|
||||
nsRefPtr<FutureResolver> mResolver;
|
||||
|
||||
nsTArray<nsRefPtr<FutureCallback> > mResolveCallbacks;
|
||||
nsTArray<nsRefPtr<FutureCallback> > mRejectCallbacks;
|
||||
|
||||
JS::Value mResult;
|
||||
FutureState mState;
|
||||
bool mTaskPending;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_Future_h
|
@ -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
|
@ -1,75 +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_FutureResolver_h
|
||||
#define mozilla_dom_FutureResolver_h
|
||||
|
||||
#include "mozilla/dom/Future.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsWrapperCache.h"
|
||||
|
||||
struct JSContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class FutureResolver MOZ_FINAL : public nsISupports,
|
||||
public nsWrapperCache
|
||||
{
|
||||
friend class FutureResolverTask;
|
||||
friend class WrapperFutureCallback;
|
||||
friend class ResolveFutureCallback;
|
||||
friend class RejectFutureCallback;
|
||||
|
||||
private:
|
||||
enum FutureTaskSync {
|
||||
SyncTask,
|
||||
AsyncTask
|
||||
};
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(FutureResolver)
|
||||
|
||||
FutureResolver(Future* aFuture);
|
||||
|
||||
Future* GetParentObject() const
|
||||
{
|
||||
return mFuture;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
void Reject(JSContext* aCx, const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
|
||||
private:
|
||||
void ResolveInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
|
||||
void RejectInternal(JSContext* aCx,
|
||||
const Optional<JS::Handle<JS::Value> >& aValue,
|
||||
FutureTaskSync aSync = AsyncTask);
|
||||
|
||||
void RunTask(JS::Handle<JS::Value> aValue,
|
||||
Future::FutureState aState, FutureTaskSync aSync);
|
||||
|
||||
nsRefPtr<Future> mFuture;
|
||||
|
||||
bool mResolvePending;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_FutureResolver_h
|
@ -1,18 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = domfuture_s
|
||||
LIBXUL_LIBRARY = 1
|
||||
FORCE_STATIC_LIB = 1
|
||||
FAIL_ON_WARNINGS := 1
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -1,22 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
||||
TEST_DIRS += ['tests']
|
||||
|
||||
XPIDL_MODULE = 'dom_future'
|
||||
|
||||
MODULE = 'dom'
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'Future.h',
|
||||
'FutureResolver.h',
|
||||
]
|
||||
|
||||
CPP_SOURCES += [
|
||||
'Future.cpp',
|
||||
'FutureResolver.cpp',
|
||||
'FutureCallback.cpp',
|
||||
]
|
@ -1,19 +0,0 @@
|
||||
# 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/.
|
||||
|
||||
DEPTH = @DEPTH@
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
relativesrcdir = @relativesrcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MOCHITEST_FILES = \
|
||||
test_future.html \
|
||||
test_resolve.html \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
@ -1,6 +0,0 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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/.
|
||||
|
@ -1,412 +0,0 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Basic Future Test</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript"><!--
|
||||
|
||||
function futureResolve() {
|
||||
ok(Future, "Future 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");
|
||||
|
||||
resolver.resolve(42);
|
||||
}).done(function(what) {
|
||||
ok(true, "Done - resolveCb has been called");
|
||||
is(what, 42, "ResolveCb received 42");
|
||||
runTest();
|
||||
}, function() {
|
||||
ok(false, "Done - rejectCb has been called");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureReject() {
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.reject(42);
|
||||
}).done(function(what) {
|
||||
ok(false, "Done - resolveCb has been called");
|
||||
runTest();
|
||||
}, function(what) {
|
||||
ok(true, "Done - rejectCb has been called");
|
||||
is(what, 42, "RejectCb received 42");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureException() {
|
||||
var future = new Future(function(resolver) {
|
||||
throw 42;
|
||||
}).done(function(what) {
|
||||
ok(false, "Done - resolveCb has been called");
|
||||
runTest();
|
||||
}, function(what) {
|
||||
ok(true, "Done - rejectCb has been called");
|
||||
is(what, 42, "RejectCb received 42");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureGC() {
|
||||
var resolver;
|
||||
var future = new Future(function(r) {
|
||||
resolver = r;
|
||||
}).done(function(what) {
|
||||
ok(true, "Done - future is still alive");
|
||||
runTest();
|
||||
});
|
||||
|
||||
future = null;
|
||||
|
||||
SpecialPowers.gc();
|
||||
SpecialPowers.forceGC();
|
||||
SpecialPowers.forceCC();
|
||||
|
||||
resolver.resolve(42);
|
||||
}
|
||||
|
||||
function futureAsync() {
|
||||
var global = "foo";
|
||||
var f = new Future(function(r) {
|
||||
is(global, "foo", "Global should be foo");
|
||||
r.resolve(42);
|
||||
is(global, "foo", "Global should still be foo");
|
||||
setTimeout(function() {
|
||||
is(global, "bar", "Global should still be bar!");
|
||||
runTest();
|
||||
}, 0);
|
||||
}).done(function() {
|
||||
global = "bar";
|
||||
});
|
||||
is(global, "foo", "Global should still be foo (2)");
|
||||
}
|
||||
|
||||
function futureDoubleDone() {
|
||||
var steps = 0;
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.resolve(42);
|
||||
});
|
||||
|
||||
future.done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
steps++;
|
||||
}, function(what) {
|
||||
ok(false, "Done.reject has been called");
|
||||
});
|
||||
|
||||
future.done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
is(steps, 1, "Done.resolve - step == 1");
|
||||
is(what, 42, "Value == 42");
|
||||
runTest();
|
||||
}, function(what) {
|
||||
ok(false, "Done.reject has been called");
|
||||
});
|
||||
}
|
||||
|
||||
function futureDoneException() {
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.resolve(42);
|
||||
});
|
||||
|
||||
onErrorCb = window.onerror;
|
||||
window.onerror = function(e) {
|
||||
ok(true, "window.onerror has been called!");
|
||||
window.onerror = onErrorCb;
|
||||
runTest();
|
||||
};
|
||||
|
||||
future.done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
throw "booh";
|
||||
});
|
||||
}
|
||||
|
||||
function futureThenCatchDone() {
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.resolve(42);
|
||||
});
|
||||
|
||||
var future2 = future.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
return what + 1;
|
||||
}, function(what) {
|
||||
ok(false, "Then.reject has been called");
|
||||
});
|
||||
|
||||
isnot(future, future2, "These 2 future objs are different");
|
||||
|
||||
future2.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 43, "Value == 43");
|
||||
return what + 1;
|
||||
}, function(what) {
|
||||
ok(false, "Then.reject has been called");
|
||||
}).catch(function() {
|
||||
ok(false, "Catch has been called");
|
||||
}).done(function(what) {
|
||||
ok(true, "Done.resolve has been called");
|
||||
is(what, 44, "Value == 44");
|
||||
runTest();
|
||||
}, function(what) {
|
||||
ok(false, "Done.reject has been called");
|
||||
});
|
||||
}
|
||||
|
||||
function futureRejectThenCatchDone() {
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.reject(42);
|
||||
});
|
||||
|
||||
var future2 = future.then(function(what) {
|
||||
ok(false, "Then.resolve has been called");
|
||||
}, function(what) {
|
||||
ok(true, "Then.reject has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
return what + 1;
|
||||
});
|
||||
|
||||
isnot(future, future2, "These 2 future objs are different");
|
||||
|
||||
future2.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 43, "Value == 43");
|
||||
return what+1;
|
||||
}).catch(function(what) {
|
||||
ok(false, "Catch has been called");
|
||||
}).done(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 44, "Value == 44");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureRejectThenCatchDone2() {
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.reject(42);
|
||||
});
|
||||
|
||||
future.then(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
return what+1;
|
||||
}).catch(function(what) {
|
||||
is(what, 42, "Value == 42");
|
||||
ok(true, "Catch has been called");
|
||||
return what+1;
|
||||
}).done(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 43, "Value == 43");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureRejectThenCatchExceptionDone() {
|
||||
var future = new Future(function(resolver) {
|
||||
resolver.reject(42);
|
||||
});
|
||||
|
||||
future.then(function(what) {
|
||||
ok(false, "Then.resolve has been called");
|
||||
}, function(what) {
|
||||
ok(true, "Then.reject has been called");
|
||||
is(what, 42, "Value == 42");
|
||||
throw(what + 1);
|
||||
}).catch(function(what) {
|
||||
ok(true, "Catch has been called");
|
||||
is(what, 43, "Value == 43");
|
||||
return what + 1;
|
||||
}).done(function(what) {
|
||||
ok(true, "Then.resolve has been called");
|
||||
is(what, 44, "Value == 44");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureThenCatchOrderingResolve() {
|
||||
var global = 0;
|
||||
var f = new Future(function(r) {
|
||||
r.resolve(42);
|
||||
});
|
||||
|
||||
f.done(function() {
|
||||
f.then(function() {
|
||||
global++;
|
||||
});
|
||||
f.catch(function() {
|
||||
global++;
|
||||
});
|
||||
f.done(function() {
|
||||
global++;
|
||||
});
|
||||
setTimeout(function() {
|
||||
is(global, 2, "Many steps... should return 2");
|
||||
runTest();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function futureThenCatchOrderingReject() {
|
||||
var global = 0;
|
||||
var f = new Future(function(r) {
|
||||
r.reject(42);
|
||||
})
|
||||
|
||||
f.done(function() {}, function() {
|
||||
f.then(function() {
|
||||
global++;
|
||||
});
|
||||
f.catch(function() {
|
||||
global++;
|
||||
});
|
||||
f.done(function() {}, function() {
|
||||
global++;
|
||||
});
|
||||
setTimeout(function() {
|
||||
is(global, 2, "Many steps... should return 2");
|
||||
runTest();
|
||||
}, 0);
|
||||
});
|
||||
}
|
||||
|
||||
function futureNestedFuture() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
r.resolve(42);
|
||||
}));
|
||||
}).then(function(value) {
|
||||
is(value, 42, "Nested future is executed and then == 42");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureNestedNestedFuture() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
r.resolve(42);
|
||||
}).then(function(what) { return what+1; }));
|
||||
}).then(function(value) {
|
||||
is(value, 43, "Nested future is executed and then == 43");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureWrongNestedFuture() {
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
r.resolve(42);
|
||||
}));
|
||||
resolver.reject(42);
|
||||
}).then(function(value) {
|
||||
is(value, 42, "Nested future 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");
|
||||
r.resolve(42);
|
||||
}));
|
||||
}));
|
||||
}).then(function(value) {
|
||||
is(value, 42, "Nested nested future is executed and then == 42");
|
||||
runTest();
|
||||
}, function(value) {
|
||||
ok(false, "This is wrong");
|
||||
});
|
||||
}
|
||||
|
||||
function futureReject() {
|
||||
var future = Future.reject(42).done(function(what) {
|
||||
ok(false, "This should not be called");
|
||||
}, function(what) {
|
||||
is(what, 42, "Value == 42");
|
||||
runTest();
|
||||
});
|
||||
}
|
||||
|
||||
function futureResolve() {
|
||||
var future = Future.resolve(42).done(function(what) {
|
||||
is(what, 42, "Value == 42");
|
||||
runTest();
|
||||
}, function() {
|
||||
ok(false, "This should not be called");
|
||||
});
|
||||
}
|
||||
|
||||
function futureResolveNestedFuture() {
|
||||
var future = Future.resolve(new Future(function(r) {
|
||||
ok(true, "Nested future is executed");
|
||||
r.resolve(42);
|
||||
}, function() {
|
||||
ok(false, "This should not be called");
|
||||
})).done(function(what) {
|
||||
is(what, 42, "Value == 42");
|
||||
runTest();
|
||||
}, function() {
|
||||
ok(false, "This should not be called");
|
||||
});
|
||||
}
|
||||
|
||||
var tests = [ futureResolve, futureReject,
|
||||
futureException, futureGC, futureAsync,
|
||||
futureDoubleDone, futureDoneException,
|
||||
futureThenCatchDone, futureRejectThenCatchDone,
|
||||
futureRejectThenCatchDone2,
|
||||
futureRejectThenCatchExceptionDone,
|
||||
futureThenCatchOrderingResolve,
|
||||
futureThenCatchOrderingReject,
|
||||
futureNestedFuture, futureNestedNestedFuture,
|
||||
futureWrongNestedFuture, futureLoop,
|
||||
futureReject, futureResolve,
|
||||
futureResolveNestedFuture,
|
||||
];
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.shift();
|
||||
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);
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.future.enabled", true]]}, runTest);
|
||||
// -->
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,67 +0,0 @@
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Future.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>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript"><!--
|
||||
|
||||
var tests = [
|
||||
null,
|
||||
42,
|
||||
"hello world",
|
||||
true,
|
||||
false,
|
||||
{},
|
||||
{ a: 42 },
|
||||
[ 1, 2, 3, 4, null, true, "hello world" ],
|
||||
function() {},
|
||||
window,
|
||||
undefined,
|
||||
document.createElement('input'),
|
||||
new Date(),
|
||||
];
|
||||
|
||||
function cbError() {
|
||||
ok(false, "Nothing should arrive here!");
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
if (!tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
var test = tests.pop();
|
||||
|
||||
new Future(function(resolver) {
|
||||
resolver.resolve(test);
|
||||
}).then(function(what) {
|
||||
ok(test === what, "What is: " + what);
|
||||
}, cbError).done(function() {
|
||||
new Future(function(resolver) {
|
||||
resolver.reject(test)
|
||||
}).then(cbError, function(what) {
|
||||
ok(test === what, "What is: " + what);
|
||||
}).done(runTest, cbError);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SpecialPowers.pushPrefEnv({"set": [["dom.future.enabled", true]]}, runTest);
|
||||
// -->
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -71,7 +71,6 @@ PARALLEL_DIRS += [
|
||||
'workers',
|
||||
'camera',
|
||||
'audiochannel',
|
||||
'future',
|
||||
'wappush'
|
||||
]
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/.
|
||||
*
|
||||
* The origin of this IDL file is
|
||||
* http://dom.spec.whatwg.org/#futures
|
||||
*/
|
||||
|
||||
interface FutureResolver {
|
||||
void resolve(optional any value);
|
||||
void reject(optional any value);
|
||||
};
|
||||
|
||||
callback FutureInit = void (FutureResolver resolver);
|
||||
callback AnyCallback = any (optional any value);
|
||||
|
||||
[PrefControlled, Constructor(FutureInit init)]
|
||||
interface Future {
|
||||
// TODO: update this interface - bug 875289
|
||||
|
||||
[Creator, Throws]
|
||||
static Future resolve(any value); // same as any(value)
|
||||
[Creator, Throws]
|
||||
static Future reject(any value);
|
||||
|
||||
[Creator]
|
||||
Future then(optional AnyCallback? resolveCallback = null,
|
||||
optional AnyCallback? rejectCallback = null);
|
||||
|
||||
[Creator]
|
||||
Future 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 \
|
||||
|
@ -223,7 +223,7 @@ AutoJSContext::Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
|
||||
}
|
||||
}
|
||||
|
||||
AutoJSContext::operator JSContext*() const
|
||||
AutoJSContext::operator JSContext*()
|
||||
{
|
||||
return mCx;
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ namespace mozilla {
|
||||
class MOZ_STACK_CLASS AutoJSContext {
|
||||
public:
|
||||
AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
|
||||
operator JSContext*() const;
|
||||
operator JSContext*();
|
||||
|
||||
protected:
|
||||
AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
|
@ -71,7 +71,6 @@ 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/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) \
|
||||
|
@ -1822,13 +1822,6 @@ pref("dom.max_script_run_time", 10);
|
||||
// If true, ArchiveReader will be enabled
|
||||
pref("dom.archivereader.enabled", false);
|
||||
|
||||
// If true, Future will be enabled
|
||||
#ifdef RELEASE_BUILD
|
||||
pref("dom.future.enabled", false);
|
||||
#else
|
||||
pref("dom.future.enabled", true);
|
||||
#endif
|
||||
|
||||
// Hang monitor timeout after which we kill the browser, in seconds
|
||||
// (0 is disabled)
|
||||
// Disabled on all platforms per bug 705748 until the found issues are
|
||||
|
Loading…
Reference in New Issue
Block a user