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_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(JSContext* cx, const T& aValue) :
|
||||||
Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
|
Optional_base<JS::Handle<T>, JS::Rooted<T> >(cx, aValue)
|
||||||
{}
|
{}
|
||||||
|
@ -160,19 +160,6 @@ ErrorResult::ReportJSException(JSContext* cx)
|
|||||||
JS_RemoveValueRoot(cx, &mJSException);
|
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 {
|
namespace dom {
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -404,10 +404,6 @@ DOMInterfaces = {
|
|||||||
'nativeType': 'nsDOMFocusEvent',
|
'nativeType': 'nsDOMFocusEvent',
|
||||||
},
|
},
|
||||||
|
|
||||||
'Future': {
|
|
||||||
'implicitJSContext': [ 'constructor' ]
|
|
||||||
},
|
|
||||||
|
|
||||||
'GainNode': {
|
'GainNode': {
|
||||||
'resultNotAddRefed': [ 'gain' ],
|
'resultNotAddRefed': [ 'gain' ],
|
||||||
},
|
},
|
||||||
|
@ -64,18 +64,11 @@ public:
|
|||||||
// Facilities for throwing a preexisting JS exception value via this
|
// Facilities for throwing a preexisting JS exception value via this
|
||||||
// ErrorResult. The contract is that any code which might end up calling
|
// ErrorResult. The contract is that any code which might end up calling
|
||||||
// ThrowJSException() must call MightThrowJSException() even if no exception
|
// ThrowJSException() must call MightThrowJSException() even if no exception
|
||||||
// is being thrown. Code that would call ReportJSException or
|
// is being thrown. Code that would call ReportJSException as needed must
|
||||||
// StealJSException as needed must first call WouldReportJSException even if
|
// first call WouldReportJSException even if this ErrorResult has not failed.
|
||||||
// this ErrorResult has not failed.
|
|
||||||
void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
|
void ThrowJSException(JSContext* cx, JS::Handle<JS::Value> exn);
|
||||||
void ReportJSException(JSContext* cx);
|
void ReportJSException(JSContext* cx);
|
||||||
bool IsJSException() const { return ErrorCode() == NS_ERROR_DOM_JS_EXCEPTION; }
|
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()
|
void MOZ_ALWAYS_INLINE MightThrowJSException()
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#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',
|
'workers',
|
||||||
'camera',
|
'camera',
|
||||||
'audiochannel',
|
'audiochannel',
|
||||||
'future',
|
|
||||||
'wappush'
|
'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 \
|
FocusEvent.webidl \
|
||||||
FormData.webidl \
|
FormData.webidl \
|
||||||
Function.webidl \
|
Function.webidl \
|
||||||
Future.webidl \
|
|
||||||
GainNode.webidl \
|
GainNode.webidl \
|
||||||
Geolocation.webidl \
|
Geolocation.webidl \
|
||||||
HTMLAnchorElement.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;
|
return mCx;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace mozilla {
|
|||||||
class MOZ_STACK_CLASS AutoJSContext {
|
class MOZ_STACK_CLASS AutoJSContext {
|
||||||
public:
|
public:
|
||||||
AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
|
AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM);
|
||||||
operator JSContext*() const;
|
operator JSContext*();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
AutoJSContext(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
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/offline/$(LIB_PREFIX)jsdomoffline_s.$(LIB_SUFFIX) \
|
||||||
$(DEPTH)/dom/src/geolocation/$(LIB_PREFIX)jsdomgeolocation_s.$(LIB_SUFFIX) \
|
$(DEPTH)/dom/src/geolocation/$(LIB_PREFIX)jsdomgeolocation_s.$(LIB_SUFFIX) \
|
||||||
$(DEPTH)/dom/audiochannel/$(LIB_PREFIX)domaudiochannel_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/src/notification/$(LIB_PREFIX)jsdomnotification_s.$(LIB_SUFFIX) \
|
||||||
$(DEPTH)/dom/system/$(LIB_PREFIX)domsystem_s.$(LIB_SUFFIX) \
|
$(DEPTH)/dom/system/$(LIB_PREFIX)domsystem_s.$(LIB_SUFFIX) \
|
||||||
$(DEPTH)/dom/workers/$(LIB_PREFIX)domworkers_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
|
// If true, ArchiveReader will be enabled
|
||||||
pref("dom.archivereader.enabled", false);
|
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
|
// Hang monitor timeout after which we kill the browser, in seconds
|
||||||
// (0 is disabled)
|
// (0 is disabled)
|
||||||
// Disabled on all platforms per bug 705748 until the found issues are
|
// Disabled on all platforms per bug 705748 until the found issues are
|
||||||
|
Loading…
Reference in New Issue
Block a user