зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1322920 - Remove DOM Promise implementation. r=bz
MozReview-Commit-ID: 1zzd0x2LNNb
This commit is contained in:
Родитель
398a43804b
Коммит
95b8398292
|
@ -136,14 +136,6 @@ release_or_beta
|
|||
|
||||
Always defined.
|
||||
|
||||
sm_promise
|
||||
Whether spidermonkey promises have been enabled or not. This is set
|
||||
by adding --enable-sm-promise to the mozconfig file.
|
||||
|
||||
Values are ``true`` and ``false``.
|
||||
|
||||
Always defined.
|
||||
|
||||
stylo
|
||||
Whether the Stylo styling system is being used.
|
||||
|
||||
|
|
|
@ -2961,42 +2961,6 @@ ConvertExceptionToPromise(JSContext* cx,
|
|||
JSObject* promiseScope,
|
||||
JS::MutableHandle<JS::Value> rval)
|
||||
{
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
GlobalObject global(cx, promiseScope);
|
||||
if (global.Failed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> exn(cx);
|
||||
if (!JS_GetPendingException(cx, &exn)) {
|
||||
// This is very important: if there is no pending exception here but we're
|
||||
// ending up in this code, that means the callee threw an uncatchable
|
||||
// exception. Just propagate that out as-is.
|
||||
return false;
|
||||
}
|
||||
|
||||
JS_ClearPendingException(cx);
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> globalObj =
|
||||
do_QueryInterface(global.GetAsSupports());
|
||||
if (!globalObj) {
|
||||
ErrorResult rv;
|
||||
rv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return !rv.MaybeSetPendingException(cx);
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
RefPtr<Promise> promise = Promise::Reject(globalObj, cx, exn, rv);
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
// We just give up. We put the exception from the ErrorResult on
|
||||
// the JSContext just to make sure to not leak memory on the
|
||||
// ErrorResult, but now just put the original exception back.
|
||||
JS_SetPendingException(cx, exn);
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetOrCreateDOMReflector(cx, promise, rval);
|
||||
#else // SPIDERMONKEY_PROMISE
|
||||
{
|
||||
JSAutoCompartment ac(cx, promiseScope);
|
||||
|
||||
|
@ -3022,7 +2986,6 @@ ConvertExceptionToPromise(JSContext* cx,
|
|||
|
||||
// Now make sure we rewrap promise back into the compartment we want
|
||||
return JS_WrapValue(cx, rval);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
}
|
||||
|
||||
/* static */
|
||||
|
|
|
@ -3038,23 +3038,6 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
else:
|
||||
unforgeableHolderSetup = None
|
||||
|
||||
if self.descriptor.name == "Promise":
|
||||
speciesSetup = CGGeneric(fill(
|
||||
"""
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
JS::Rooted<JSObject*> promiseConstructor(aCx, *interfaceCache);
|
||||
JS::Rooted<jsid> species(aCx,
|
||||
SYMBOL_TO_JSID(JS::GetWellKnownSymbol(aCx, JS::SymbolCode::species)));
|
||||
if (!JS_DefinePropertyById(aCx, promiseConstructor, species, JS::UndefinedHandleValue,
|
||||
JSPROP_SHARED, Promise::PromiseSpecies, nullptr)) {
|
||||
$*{failureCode}
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
""",
|
||||
failureCode=failureCode))
|
||||
else:
|
||||
speciesSetup = None
|
||||
|
||||
if (self.descriptor.interface.isOnGlobalProtoChain() and
|
||||
needInterfacePrototypeObject):
|
||||
makeProtoPrototypeImmutable = CGGeneric(fill(
|
||||
|
@ -3080,7 +3063,7 @@ class CGCreateInterfaceObjectsMethod(CGAbstractMethod):
|
|||
return CGList(
|
||||
[getParentProto, getConstructorProto, initIds,
|
||||
prefCache, CGGeneric(call), defineAliases, unforgeableHolderSetup,
|
||||
speciesSetup, makeProtoPrototypeImmutable],
|
||||
makeProtoPrototypeImmutable],
|
||||
"\n").define()
|
||||
|
||||
|
||||
|
@ -5319,7 +5302,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
$*{exceptionCode}
|
||||
}
|
||||
binding_detail::FastErrorResult promiseRv;
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
nsCOMPtr<nsIGlobalObject> global =
|
||||
do_QueryInterface(promiseGlobal.GetAsSupports());
|
||||
if (!global) {
|
||||
|
@ -5332,26 +5314,6 @@ def getJSToNativeConversionInfo(type, descriptorProvider, failureCode=None,
|
|||
if (promiseRv.MaybeSetPendingException(cx)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
#else
|
||||
JS::Handle<JSObject*> promiseCtor =
|
||||
PromiseBinding::GetConstructorObjectHandle(cx);
|
||||
if (!promiseCtor) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
JS::Rooted<JS::Value> resolveThisv(cx, JS::ObjectValue(*promiseCtor));
|
||||
JS::Rooted<JS::Value> resolveResult(cx);
|
||||
Promise::Resolve(promiseGlobal, resolveThisv, valueToResolve,
|
||||
&resolveResult, promiseRv);
|
||||
if (promiseRv.MaybeSetPendingException(cx)) {
|
||||
$*{exceptionCode}
|
||||
}
|
||||
nsresult unwrapRv = UNWRAP_OBJECT(Promise, &resolveResult.toObject(), $${declName});
|
||||
if (NS_FAILED(unwrapRv)) { // Quite odd
|
||||
promiseRv.Throw(unwrapRv);
|
||||
promiseRv.MaybeSetPendingException(cx);
|
||||
$*{exceptionCode}
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
}
|
||||
""",
|
||||
getPromiseGlobal=getPromiseGlobal,
|
||||
|
|
|
@ -7,9 +7,7 @@
|
|||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/dom/DOMException.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
#include "nsAString.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsStringBuffer.h"
|
||||
|
@ -66,7 +64,6 @@ ToJSValue(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
bool
|
||||
ToJSValue(JSContext* aCx, Promise& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
|
@ -74,7 +71,6 @@ ToJSValue(JSContext* aCx, Promise& aArgument,
|
|||
aValue.setObject(*aArgument.PromiseObj());
|
||||
return true;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -306,13 +306,11 @@ ToJSValue(JSContext* aCx,
|
|||
return ToJSValue(aCx, *aArgument, aValue);
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
// Accept Promise objects, which need special handling.
|
||||
MOZ_MUST_USE bool
|
||||
ToJSValue(JSContext* aCx,
|
||||
Promise& aArgument,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
// Accept arrays of other things we accept
|
||||
template <typename T>
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -21,17 +21,6 @@
|
|||
#include "js/TypeDecls.h"
|
||||
#include "jspubtd.h"
|
||||
|
||||
// Bug 1083361 introduces a new mechanism for tracking uncaught
|
||||
// rejections. This #define serves to track down the parts of code
|
||||
// that need to be removed once clients have been put together
|
||||
// to take advantage of the new mechanism. New code should not
|
||||
// depend on code #ifdefed to this #define.
|
||||
#define DOM_PROMISE_DEPRECATED_REPORTING !SPIDERMONKEY_PROMISE
|
||||
|
||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
#include "mozilla/dom/workers/bindings/WorkerHolder.h"
|
||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
|
||||
class nsIGlobalObject;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -40,88 +29,36 @@ namespace dom {
|
|||
class AnyCallback;
|
||||
class DOMError;
|
||||
class MediaStreamError;
|
||||
class PromiseCallback;
|
||||
class PromiseInit;
|
||||
class PromiseNativeHandler;
|
||||
class PromiseDebugging;
|
||||
|
||||
class Promise;
|
||||
|
||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
class PromiseReportRejectWorkerHolder : public workers::WorkerHolder
|
||||
{
|
||||
// PromiseReportRejectWorkerHolder is held by an nsAutoPtr on the Promise
|
||||
// which means that this object will be destroyed before the Promise is
|
||||
// destroyed.
|
||||
Promise* MOZ_NON_OWNING_REF mPromise;
|
||||
|
||||
public:
|
||||
explicit PromiseReportRejectWorkerHolder(Promise* aPromise)
|
||||
: mPromise(aPromise)
|
||||
{
|
||||
MOZ_ASSERT(mPromise);
|
||||
}
|
||||
|
||||
virtual bool
|
||||
Notify(workers::Status aStatus) override;
|
||||
};
|
||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
|
||||
#define NS_PROMISE_IID \
|
||||
{ 0x1b8d6215, 0x3e67, 0x43ba, \
|
||||
{ 0x8a, 0xf9, 0x31, 0x5e, 0x8f, 0xce, 0x75, 0x65 } }
|
||||
|
||||
class Promise : public nsISupports,
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
// Only wrappercached when we're not using SpiderMonkey
|
||||
// promises, because those don't have a useful object moved
|
||||
// hook, which wrappercache needs.
|
||||
public nsWrapperCache,
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
public SupportsWeakPtr<Promise>
|
||||
{
|
||||
friend class NativePromiseCallback;
|
||||
friend class PromiseReactionJob;
|
||||
friend class PromiseResolverTask;
|
||||
friend class PromiseTask;
|
||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
friend class PromiseReportRejectWorkerHolder;
|
||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
friend class PromiseWorkerProxy;
|
||||
friend class PromiseWorkerProxyRunnable;
|
||||
friend class RejectPromiseCallback;
|
||||
friend class ResolvePromiseCallback;
|
||||
friend class PromiseResolveThenableJob;
|
||||
friend class FastPromiseResolveThenableJob;
|
||||
friend class WrapperPromiseCallback;
|
||||
|
||||
public:
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_PROMISE_IID)
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
// We're not skippable, since we're not owned from JS to start with.
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
|
||||
#else // SPIDERMONKEY_PROMISE
|
||||
NS_DECL_CYCLE_COLLECTION_SKIPPABLE_SCRIPT_HOLDER_CLASS(Promise)
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
MOZ_DECLARE_WEAKREFERENCE_TYPENAME(Promise)
|
||||
|
||||
// Promise creation tries to create a JS reflector for the Promise, so is
|
||||
// fallible. Furthermore, we don't want to do JS-wrapping on a 0-refcount
|
||||
// object, so we addref before doing that and return the addrefed pointer
|
||||
// here.
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static already_AddRefed<Promise>
|
||||
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
|
||||
|
||||
// Reports a rejected Promise by sending an error report.
|
||||
static void ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise);
|
||||
#else
|
||||
static already_AddRefed<Promise>
|
||||
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
|
||||
// Passing null for aDesiredProto will use Promise.prototype.
|
||||
JS::Handle<JSObject*> aDesiredProto = nullptr);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
typedef void (Promise::*MaybeFunc)(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
|
@ -183,7 +120,6 @@ public:
|
|||
return mGlobal;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
bool
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto,
|
||||
JS::MutableHandle<JSObject*> aWrapper);
|
||||
|
@ -220,95 +156,17 @@ public:
|
|||
return mPromiseObj;
|
||||
}
|
||||
|
||||
#else // SPIDERMONKEY_PROMISE
|
||||
JSObject* PromiseObj()
|
||||
{
|
||||
return GetWrapper();
|
||||
}
|
||||
|
||||
virtual JSObject*
|
||||
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
|
||||
ErrorResult& aRv, JS::Handle<JSObject*> aDesiredProto);
|
||||
|
||||
static void
|
||||
Resolve(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
Resolve(nsIGlobalObject* aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
Reject(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::MutableHandle<JS::Value> aRetval, ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
Reject(nsIGlobalObject* aGlobal, JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue, ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Then(JSContext* aCx,
|
||||
// aCalleeGlobal may not be in the compartment of aCx, when called over
|
||||
// Xrays.
|
||||
JS::Handle<JSObject*> aCalleeGlobal,
|
||||
AnyCallback* aResolveCallback, AnyCallback* aRejectCallback,
|
||||
JS::MutableHandle<JS::Value> aRetval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
void
|
||||
Catch(JSContext* aCx,
|
||||
AnyCallback* aRejectCallback,
|
||||
JS::MutableHandle<JS::Value> aRetval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
All(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
||||
JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static already_AddRefed<Promise>
|
||||
All(const GlobalObject& aGlobal,
|
||||
const nsTArray<RefPtr<Promise>>& aPromiseList, ErrorResult& aRv);
|
||||
|
||||
static void
|
||||
Race(const GlobalObject& aGlobal, JS::Handle<JS::Value> aThisv,
|
||||
JS::Handle<JS::Value> aIterable, JS::MutableHandle<JS::Value> aRetval,
|
||||
ErrorResult& aRv);
|
||||
|
||||
static bool
|
||||
PromiseSpecies(JSContext* aCx, unsigned aArgc, JS::Value* aVp);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
void AppendNativeHandler(PromiseNativeHandler* aRunnable);
|
||||
|
||||
JSObject* GlobalJSObject() const;
|
||||
|
||||
JSCompartment* Compartment() const;
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
// Return a unique-to-the-process identifier for this Promise.
|
||||
uint64_t GetID();
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
enum JSCallbackSlots {
|
||||
SLOT_PROMISE = 0,
|
||||
SLOT_DATA
|
||||
};
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
// Create a dom::Promise from a given SpiderMonkey Promise object.
|
||||
// aPromiseObj MUST be in the compartment of aGlobal's global JS object.
|
||||
static already_AddRefed<Promise>
|
||||
CreateFromExisting(nsIGlobalObject* aGlobal,
|
||||
JS::Handle<JSObject*> aPromiseObj);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
enum class PromiseState {
|
||||
Pending,
|
||||
|
@ -332,99 +190,7 @@ protected:
|
|||
// use the default prototype for the sort of Promise we have.
|
||||
void CreateWrapper(JS::Handle<JSObject*> aDesiredProto, ErrorResult& aRv);
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
// Create the JS resolving functions of resolve() and reject(). And provide
|
||||
// references to the two functions by calling PromiseInit passed from Promise
|
||||
// constructor.
|
||||
void CallInitFunction(const GlobalObject& aGlobal, PromiseInit& aInit,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// The NewPromiseCapability function from
|
||||
// <http://www.ecma-international.org/ecma-262/6.0/#sec-newpromisecapability>.
|
||||
// Errors are communicated via aRv. If aForceCallbackCreation is
|
||||
// true, then this function will ensure that aCapability has a
|
||||
// useful mResolve/mReject even if mNativePromise is non-null.
|
||||
static void NewPromiseCapability(JSContext* aCx, nsIGlobalObject* aGlobal,
|
||||
JS::Handle<JS::Value> aConstructor,
|
||||
bool aForceCallbackCreation,
|
||||
PromiseCapability& aCapability,
|
||||
ErrorResult& aRv);
|
||||
|
||||
bool IsPending()
|
||||
{
|
||||
return mResolvePending;
|
||||
}
|
||||
|
||||
void GetDependentPromises(nsTArray<RefPtr<Promise>>& aPromises);
|
||||
|
||||
bool IsLastInChain() const
|
||||
{
|
||||
return mIsLastInChain;
|
||||
}
|
||||
|
||||
void SetNotifiedAsUncaught()
|
||||
{
|
||||
mWasNotifiedAsUncaught = true;
|
||||
}
|
||||
|
||||
bool WasNotifiedAsUncaught() const
|
||||
{
|
||||
return mWasNotifiedAsUncaught;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
private:
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
friend class PromiseDebugging;
|
||||
|
||||
void SetState(PromiseState aState)
|
||||
{
|
||||
MOZ_ASSERT(mState == Pending);
|
||||
MOZ_ASSERT(aState != Pending);
|
||||
mState = aState;
|
||||
}
|
||||
|
||||
void SetResult(JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
mResult = aValue;
|
||||
}
|
||||
|
||||
// This method enqueues promise's resolve/reject callbacks with promise's
|
||||
// result. It's executed when the resolver.resolve() or resolver.reject() is
|
||||
// called or when the promise already has a result and new callbacks are
|
||||
// appended by then() or catch().
|
||||
void TriggerPromiseReactions();
|
||||
|
||||
void Settle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
|
||||
void MaybeSettle(JS::Handle<JS::Value> aValue, Promise::PromiseState aState);
|
||||
|
||||
void AppendCallbacks(PromiseCallback* aResolveCallback,
|
||||
PromiseCallback* aRejectCallback);
|
||||
|
||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
// If we have been rejected and our mResult is a JS exception,
|
||||
// report it to the error console.
|
||||
// Use MaybeReportRejectedOnce() for actual calls.
|
||||
void MaybeReportRejected();
|
||||
|
||||
void MaybeReportRejectedOnce() {
|
||||
MaybeReportRejected();
|
||||
RemoveWorkerHolder();
|
||||
mResult.setUndefined();
|
||||
}
|
||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
|
||||
void MaybeResolveInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
void MaybeRejectInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
|
||||
void ResolveInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
void RejectInternal(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
template <typename T>
|
||||
void MaybeSomething(T& aArgument, MaybeFunc aFunc) {
|
||||
MOZ_ASSERT(PromiseObj()); // It was preserved!
|
||||
|
@ -441,92 +207,11 @@ private:
|
|||
(this->*aFunc)(cx, val);
|
||||
}
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
// Static methods for the PromiseInit functions.
|
||||
static bool
|
||||
JSCallback(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
|
||||
|
||||
static bool
|
||||
ThenableResolverCommon(JSContext* aCx, uint32_t /* PromiseCallback::Task */ aTask,
|
||||
unsigned aArgc, JS::Value* aVp);
|
||||
static bool
|
||||
JSCallbackThenableResolver(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
|
||||
static bool
|
||||
JSCallbackThenableRejecter(JSContext *aCx, unsigned aArgc, JS::Value *aVp);
|
||||
|
||||
static JSObject*
|
||||
CreateFunction(JSContext* aCx, Promise* aPromise, int32_t aTask);
|
||||
|
||||
static JSObject*
|
||||
CreateThenableFunction(JSContext* aCx, Promise* aPromise, uint32_t aTask);
|
||||
|
||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
void RemoveWorkerHolder();
|
||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
|
||||
// Capture the current stack and store it in aTarget. If false is
|
||||
// returned, an exception is presumably pending on aCx.
|
||||
bool CaptureStack(JSContext* aCx, JS::Heap<JSObject*>& aTarget);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
void HandleException(JSContext* aCx);
|
||||
|
||||
RefPtr<nsIGlobalObject> mGlobal;
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
nsTArray<RefPtr<PromiseCallback> > mResolveCallbacks;
|
||||
nsTArray<RefPtr<PromiseCallback> > mRejectCallbacks;
|
||||
|
||||
JS::Heap<JS::Value> mResult;
|
||||
// A stack that shows where this promise was allocated, if there was
|
||||
// JS running at the time. Otherwise null.
|
||||
JS::Heap<JSObject*> mAllocationStack;
|
||||
// mRejectionStack is only set when the promise is rejected directly from
|
||||
// script, by calling Promise.reject() or the rejection callback we pass to
|
||||
// the PromiseInit function. Promises that are rejected internally do not
|
||||
// have a rejection stack.
|
||||
JS::Heap<JSObject*> mRejectionStack;
|
||||
// mFullfillmentStack is only set when the promise is fulfilled directly from
|
||||
// script, by calling Promise.resolve() or the fulfillment callback we pass to
|
||||
// the PromiseInit function. Promises that are fulfilled internally do not
|
||||
// have a fulfillment stack.
|
||||
JS::Heap<JSObject*> mFullfillmentStack;
|
||||
PromiseState mState;
|
||||
|
||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
bool mHadRejectCallback;
|
||||
|
||||
// If a rejected promise on a worker has no reject callbacks attached, it
|
||||
// needs to know when the worker is shutting down, to report the error on the
|
||||
// console before the worker's context is deleted. This feature is used for
|
||||
// that purpose.
|
||||
nsAutoPtr<PromiseReportRejectWorkerHolder> mWorkerHolder;
|
||||
#endif // defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||
|
||||
bool mTaskPending;
|
||||
bool mResolvePending;
|
||||
|
||||
// `true` if this Promise is the last in the chain, or `false` if
|
||||
// another Promise has been created from this one by a call to
|
||||
// `then`, `all`, `race`, etc.
|
||||
bool mIsLastInChain;
|
||||
|
||||
// `true` if PromiseDebugging has already notified at least one observer that
|
||||
// this promise was left uncaught, `false` otherwise.
|
||||
bool mWasNotifiedAsUncaught;
|
||||
|
||||
// The time when this promise was created.
|
||||
TimeStamp mCreationTimestamp;
|
||||
|
||||
// The time when this promise transitioned out of the pending state.
|
||||
TimeStamp mSettlementTimestamp;
|
||||
|
||||
// Once `GetID()` has been called, a unique-to-the-process identifier for this
|
||||
// promise. Until then, `0`.
|
||||
uint64_t mID;
|
||||
#else // SPIDERMONKEY_PROMISE
|
||||
JS::Heap<JSObject*> mPromiseObj;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
};
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(Promise, NS_PROMISE_IID)
|
||||
|
|
|
@ -1,575 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "PromiseCallback.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/PromiseNativeHandler.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jswrapper.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
|
||||
|
||||
PromiseCallback::PromiseCallback()
|
||||
{
|
||||
}
|
||||
|
||||
PromiseCallback::~PromiseCallback()
|
||||
{
|
||||
}
|
||||
|
||||
// ResolvePromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(ResolvePromiseCallback)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ResolvePromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
||||
tmp->mGlobal = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ResolvePromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(ResolvePromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ResolvePromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ResolvePromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(ResolvePromiseCallback, PromiseCallback)
|
||||
|
||||
ResolvePromiseCallback::ResolvePromiseCallback(Promise* aPromise,
|
||||
JS::Handle<JSObject*> aGlobal)
|
||||
: mPromise(aPromise)
|
||||
, mGlobal(aGlobal)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(aGlobal);
|
||||
HoldJSObjects(this);
|
||||
}
|
||||
|
||||
ResolvePromiseCallback::~ResolvePromiseCallback()
|
||||
{
|
||||
DropJSObjects(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolvePromiseCallback::Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
|
||||
JS::ExposeValueToActiveJS(aValue);
|
||||
|
||||
JSAutoCompartment ac(aCx, mGlobal);
|
||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
||||
if (!JS_WrapValue(aCx, &value)) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mPromise->ResolveInternal(aCx, value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// RejectPromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(RejectPromiseCallback)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RejectPromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromise)
|
||||
tmp->mGlobal = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(RejectPromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(RejectPromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(RejectPromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(RejectPromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(RejectPromiseCallback, PromiseCallback)
|
||||
|
||||
RejectPromiseCallback::RejectPromiseCallback(Promise* aPromise,
|
||||
JS::Handle<JSObject*> aGlobal)
|
||||
: mPromise(aPromise)
|
||||
, mGlobal(aGlobal)
|
||||
{
|
||||
MOZ_ASSERT(aPromise);
|
||||
MOZ_ASSERT(mGlobal);
|
||||
HoldJSObjects(this);
|
||||
}
|
||||
|
||||
RejectPromiseCallback::~RejectPromiseCallback()
|
||||
{
|
||||
DropJSObjects(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RejectPromiseCallback::Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
|
||||
JS::ExposeValueToActiveJS(aValue);
|
||||
|
||||
JSAutoCompartment ac(aCx, mGlobal);
|
||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
||||
if (!JS_WrapValue(aCx, &value)) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
mPromise->RejectInternal(aCx, value);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// InvokePromiseFuncCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(InvokePromiseFuncCallback)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(InvokePromiseFuncCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPromiseFunc)
|
||||
tmp->mGlobal = nullptr;
|
||||
tmp->mNextPromiseObj = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(InvokePromiseFuncCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromiseFunc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(InvokePromiseFuncCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(InvokePromiseFuncCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(InvokePromiseFuncCallback, PromiseCallback)
|
||||
|
||||
InvokePromiseFuncCallback::InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
|
||||
JS::Handle<JSObject*> aNextPromiseObj,
|
||||
AnyCallback* aPromiseFunc)
|
||||
: mGlobal(aGlobal)
|
||||
, mNextPromiseObj(aNextPromiseObj)
|
||||
, mPromiseFunc(aPromiseFunc)
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(aNextPromiseObj);
|
||||
MOZ_ASSERT(aPromiseFunc);
|
||||
HoldJSObjects(this);
|
||||
}
|
||||
|
||||
InvokePromiseFuncCallback::~InvokePromiseFuncCallback()
|
||||
{
|
||||
DropJSObjects(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
InvokePromiseFuncCallback::Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
// Run resolver's algorithm with value and the synchronous flag set.
|
||||
|
||||
JS::ExposeValueToActiveJS(aValue);
|
||||
|
||||
JSAutoCompartment ac(aCx, mGlobal);
|
||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
||||
if (!JS_WrapValue(aCx, &value)) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
JS::Rooted<JS::Value> ignored(aCx);
|
||||
mPromiseFunc->Call(value, &ignored, rv);
|
||||
// Useful exceptions already got reported.
|
||||
rv.SuppressException();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Promise*
|
||||
InvokePromiseFuncCallback::GetDependentPromise()
|
||||
{
|
||||
Promise* promise;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Oh, well.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// WrapperPromiseCallback
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(WrapperPromiseCallback)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WrapperPromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mResolveFunc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mRejectFunc)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
|
||||
tmp->mGlobal = nullptr;
|
||||
tmp->mNextPromiseObj = nullptr;
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(WrapperPromiseCallback,
|
||||
PromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mNextPromise)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mResolveFunc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRejectFunc)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(WrapperPromiseCallback)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mGlobal)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mNextPromiseObj)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(WrapperPromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(WrapperPromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(WrapperPromiseCallback, PromiseCallback)
|
||||
|
||||
WrapperPromiseCallback::WrapperPromiseCallback(Promise* aNextPromise,
|
||||
JS::Handle<JSObject*> aGlobal,
|
||||
AnyCallback* aCallback)
|
||||
: mNextPromise(aNextPromise)
|
||||
, mGlobal(aGlobal)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(aNextPromise);
|
||||
MOZ_ASSERT(aGlobal);
|
||||
HoldJSObjects(this);
|
||||
}
|
||||
|
||||
WrapperPromiseCallback::WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
|
||||
AnyCallback* aCallback,
|
||||
JS::Handle<JSObject*> aNextPromiseObj,
|
||||
AnyCallback* aResolveFunc,
|
||||
AnyCallback* aRejectFunc)
|
||||
: mNextPromiseObj(aNextPromiseObj)
|
||||
, mResolveFunc(aResolveFunc)
|
||||
, mRejectFunc(aRejectFunc)
|
||||
, mGlobal(aGlobal)
|
||||
, mCallback(aCallback)
|
||||
{
|
||||
MOZ_ASSERT(mNextPromiseObj);
|
||||
MOZ_ASSERT(aResolveFunc);
|
||||
MOZ_ASSERT(aRejectFunc);
|
||||
MOZ_ASSERT(aGlobal);
|
||||
HoldJSObjects(this);
|
||||
}
|
||||
|
||||
WrapperPromiseCallback::~WrapperPromiseCallback()
|
||||
{
|
||||
DropJSObjects(this);
|
||||
}
|
||||
|
||||
nsresult
|
||||
WrapperPromiseCallback::Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
JS::ExposeValueToActiveJS(aValue);
|
||||
|
||||
JSAutoCompartment ac(aCx, mGlobal);
|
||||
JS::Rooted<JS::Value> value(aCx, aValue);
|
||||
if (!JS_WrapValue(aCx, &value)) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult rv;
|
||||
|
||||
// PromiseReactionTask step 6
|
||||
JS::Rooted<JS::Value> retValue(aCx);
|
||||
JSCompartment* compartment;
|
||||
if (mNextPromise) {
|
||||
compartment = mNextPromise->Compartment();
|
||||
} else {
|
||||
MOZ_ASSERT(mNextPromiseObj);
|
||||
compartment = js::GetObjectCompartment(mNextPromiseObj);
|
||||
}
|
||||
mCallback->Call(value, &retValue, rv, "promise callback",
|
||||
CallbackObject::eRethrowExceptions,
|
||||
compartment);
|
||||
|
||||
rv.WouldReportJSException();
|
||||
|
||||
// PromiseReactionTask step 7
|
||||
if (rv.Failed()) {
|
||||
if (rv.IsUncatchableException()) {
|
||||
// We have nothing to resolve/reject the promise with.
|
||||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx);
|
||||
{ // Scope for JSAutoCompartment
|
||||
// Convert the ErrorResult to a JS exception object that we can reject
|
||||
// ourselves with. This will be exactly the exception that would get
|
||||
// thrown from a binding method whose ErrorResult ended up with whatever
|
||||
// is on "rv" right now. Do this in the promise reflector compartment.
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (mNextPromise) {
|
||||
ac.emplace(aCx, mNextPromise->GlobalJSObject());
|
||||
} else {
|
||||
ac.emplace(aCx, mNextPromiseObj);
|
||||
}
|
||||
DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value);
|
||||
MOZ_ASSERT(conversionResult);
|
||||
}
|
||||
|
||||
if (mNextPromise) {
|
||||
mNextPromise->RejectInternal(aCx, value);
|
||||
} else {
|
||||
JS::Rooted<JS::Value> ignored(aCx);
|
||||
ErrorResult rejectRv;
|
||||
mRejectFunc->Call(value, &ignored, rejectRv);
|
||||
// This reported any JS exceptions; we just have a pointless exception on
|
||||
// there now.
|
||||
rejectRv.SuppressException();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// If the return value is the same as the promise itself, throw TypeError.
|
||||
if (retValue.isObject()) {
|
||||
JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
|
||||
valueObj = js::CheckedUnwrap(valueObj);
|
||||
JS::Rooted<JSObject*> nextPromiseObj(aCx);
|
||||
if (mNextPromise) {
|
||||
nextPromiseObj = mNextPromise->GetWrapper();
|
||||
} else {
|
||||
MOZ_ASSERT(mNextPromiseObj);
|
||||
nextPromiseObj = mNextPromiseObj;
|
||||
}
|
||||
// XXXbz shouldn't this check be over in ResolveInternal anyway?
|
||||
if (valueObj == nextPromiseObj) {
|
||||
const char* fileName = nullptr;
|
||||
uint32_t lineNumber = 0;
|
||||
|
||||
// Try to get some information about the callback to report a sane error,
|
||||
// but don't try too hard (only deals with scripted functions).
|
||||
JS::Rooted<JSObject*> unwrapped(aCx,
|
||||
js::CheckedUnwrap(mCallback->Callback()));
|
||||
|
||||
if (unwrapped) {
|
||||
JSAutoCompartment ac(aCx, unwrapped);
|
||||
if (JS_ObjectIsFunction(aCx, unwrapped)) {
|
||||
JS::Rooted<JS::Value> asValue(aCx, JS::ObjectValue(*unwrapped));
|
||||
JS::Rooted<JSFunction*> func(aCx, JS_ValueToFunction(aCx, asValue));
|
||||
|
||||
MOZ_ASSERT(func);
|
||||
JSScript* script = JS_GetFunctionScript(aCx, func);
|
||||
if (script) {
|
||||
fileName = JS_GetScriptFilename(script);
|
||||
lineNumber = JS_GetScriptBaseLineNumber(aCx, script);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We're back in aValue's compartment here.
|
||||
JS::Rooted<JSString*> fn(aCx, JS_NewStringCopyZ(aCx, fileName));
|
||||
if (!fn) {
|
||||
// Out of memory. Promise will stay unresolved.
|
||||
JS_ClearPendingException(aCx);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> message(aCx,
|
||||
JS_NewStringCopyZ(aCx,
|
||||
"then() cannot return same Promise that it resolves."));
|
||||
if (!message) {
|
||||
// Out of memory. Promise will stay unresolved.
|
||||
JS_ClearPendingException(aCx);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> typeError(aCx);
|
||||
if (!JS::CreateError(aCx, JSEXN_TYPEERR, nullptr, fn, lineNumber, 0,
|
||||
nullptr, message, &typeError)) {
|
||||
// Out of memory. Promise will stay unresolved.
|
||||
JS_ClearPendingException(aCx);
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (mNextPromise) {
|
||||
mNextPromise->RejectInternal(aCx, typeError);
|
||||
} else {
|
||||
JS::Rooted<JS::Value> ignored(aCx);
|
||||
ErrorResult rejectRv;
|
||||
mRejectFunc->Call(typeError, &ignored, rejectRv);
|
||||
// This reported any JS exceptions; we just have a pointless exception
|
||||
// on there now.
|
||||
rejectRv.SuppressException();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, run resolver's resolve with value.
|
||||
if (!JS_WrapValue(aCx, &retValue)) {
|
||||
NS_WARNING("Failed to wrap value into the right compartment.");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mNextPromise) {
|
||||
mNextPromise->ResolveInternal(aCx, retValue);
|
||||
} else {
|
||||
JS::Rooted<JS::Value> ignored(aCx);
|
||||
ErrorResult resolveRv;
|
||||
mResolveFunc->Call(retValue, &ignored, resolveRv);
|
||||
// This reported any JS exceptions; we just have a pointless exception
|
||||
// on there now.
|
||||
resolveRv.SuppressException();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
Promise*
|
||||
WrapperPromiseCallback::GetDependentPromise()
|
||||
{
|
||||
// Per spec, various algorithms like all() and race() are actually implemented
|
||||
// in terms of calling then() but passing it the resolve/reject functions that
|
||||
// are passed as arguments to function passed to the Promise constructor.
|
||||
// That will cause the promise in question to hold on to a
|
||||
// WrapperPromiseCallback, but the dependent promise should really be the one
|
||||
// whose constructor those functions came from, not the about-to-be-ignored
|
||||
// return value of "then". So try to determine whether we're in that case and
|
||||
// if so go ahead and dig the dependent promise out of the function we have.
|
||||
JSObject* callable = mCallback->Callable();
|
||||
// Unwrap it, in case it's a cross-compartment wrapper. Our caller here is
|
||||
// system, so it's really ok to just go and unwrap.
|
||||
callable = js::UncheckedUnwrap(callable);
|
||||
if (JS_IsNativeFunction(callable, Promise::JSCallback)) {
|
||||
JS::Value promiseVal =
|
||||
js::GetFunctionNativeReserved(callable, Promise::SLOT_PROMISE);
|
||||
Promise* promise;
|
||||
UNWRAP_OBJECT(Promise, &promiseVal.toObject(), promise);
|
||||
return promise;
|
||||
}
|
||||
|
||||
if (mNextPromise) {
|
||||
return mNextPromise;
|
||||
}
|
||||
|
||||
Promise* promise;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Promise, mNextPromiseObj, promise))) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Oh, well.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// NativePromiseCallback
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(NativePromiseCallback,
|
||||
PromiseCallback, mHandler)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
|
||||
NS_INTERFACE_MAP_END_INHERITING(PromiseCallback)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(NativePromiseCallback, PromiseCallback)
|
||||
NS_IMPL_RELEASE_INHERITED(NativePromiseCallback, PromiseCallback)
|
||||
|
||||
NativePromiseCallback::NativePromiseCallback(PromiseNativeHandler* aHandler,
|
||||
Promise::PromiseState aState)
|
||||
: mHandler(aHandler)
|
||||
, mState(aState)
|
||||
{
|
||||
MOZ_ASSERT(aHandler);
|
||||
}
|
||||
|
||||
NativePromiseCallback::~NativePromiseCallback()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
NativePromiseCallback::Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
JS::ExposeValueToActiveJS(aValue);
|
||||
|
||||
if (mState == Promise::Resolved) {
|
||||
mHandler->ResolvedCallback(aCx, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (mState == Promise::Rejected) {
|
||||
mHandler->RejectedCallback(aCx, aValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_NOTREACHED("huh?");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
/* static */ PromiseCallback*
|
||||
PromiseCallback::Factory(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
|
||||
AnyCallback* aCallback, Task aTask)
|
||||
{
|
||||
MOZ_ASSERT(aNextPromise);
|
||||
|
||||
// If we have a callback and a next resolver, we have to exec the callback and
|
||||
// then propagate the return value to the next resolver->resolve().
|
||||
if (aCallback) {
|
||||
return new WrapperPromiseCallback(aNextPromise, aGlobal, aCallback);
|
||||
}
|
||||
|
||||
if (aTask == Resolve) {
|
||||
return new ResolvePromiseCallback(aNextPromise, aGlobal);
|
||||
}
|
||||
|
||||
if (aTask == Reject) {
|
||||
return new RejectPromiseCallback(aNextPromise, aGlobal);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(false, "This should not happen");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -1,203 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_PromiseCallback_h
|
||||
#define mozilla_dom_PromiseCallback_h
|
||||
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
// This is the base class for any PromiseCallback.
|
||||
// It's a logical step in the promise chain of callbacks.
|
||||
class PromiseCallback : public nsISupports
|
||||
{
|
||||
protected:
|
||||
virtual ~PromiseCallback();
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(PromiseCallback)
|
||||
|
||||
PromiseCallback();
|
||||
|
||||
virtual nsresult Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) = 0;
|
||||
|
||||
// Return the Promise that this callback will end up resolving or
|
||||
// rejecting, if any.
|
||||
virtual Promise* GetDependentPromise() = 0;
|
||||
|
||||
enum Task {
|
||||
Resolve,
|
||||
Reject
|
||||
};
|
||||
|
||||
// This factory returns a PromiseCallback object with refcount of 0.
|
||||
static PromiseCallback*
|
||||
Factory(Promise* aNextPromise, JS::Handle<JSObject*> aObject,
|
||||
AnyCallback* aCallback, Task aTask);
|
||||
};
|
||||
|
||||
// WrapperPromiseCallback execs a JS Callback with a value, and then the return
|
||||
// value is sent to either:
|
||||
// a) If aNextPromise is non-null, the aNextPromise->ResolveFunction() or to
|
||||
// aNextPromise->RejectFunction() if the JS Callback throws.
|
||||
// or
|
||||
// b) If aNextPromise is null, in which case aResolveFunc and aRejectFunc must
|
||||
// be non-null, then to aResolveFunc, unless aCallback threw, in which case
|
||||
// aRejectFunc.
|
||||
class WrapperPromiseCallback final : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WrapperPromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
nsresult Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
Promise* GetDependentPromise() override;
|
||||
|
||||
// Constructor for when we know we have a vanilla Promise.
|
||||
WrapperPromiseCallback(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
|
||||
AnyCallback* aCallback);
|
||||
|
||||
// Constructor for when all we have to work with are resolve/reject functions.
|
||||
WrapperPromiseCallback(JS::Handle<JSObject*> aGlobal,
|
||||
AnyCallback* aCallback,
|
||||
JS::Handle<JSObject*> mNextPromiseObj,
|
||||
AnyCallback* aResolveFunc,
|
||||
AnyCallback* aRejectFunc);
|
||||
|
||||
private:
|
||||
~WrapperPromiseCallback();
|
||||
|
||||
// Either mNextPromise is non-null or all three of mNextPromiseObj,
|
||||
// mResolveFund and mRejectFunc must are non-null.
|
||||
RefPtr<Promise> mNextPromise;
|
||||
// mNextPromiseObj is the reflector itself; it may not be in the
|
||||
// same compartment as anything else we have.
|
||||
JS::Heap<JSObject*> mNextPromiseObj;
|
||||
RefPtr<AnyCallback> mResolveFunc;
|
||||
RefPtr<AnyCallback> mRejectFunc;
|
||||
JS::Heap<JSObject*> mGlobal;
|
||||
RefPtr<AnyCallback> mCallback;
|
||||
};
|
||||
|
||||
// ResolvePromiseCallback calls aPromise->ResolveFunction() with the value
|
||||
// received by Call().
|
||||
class ResolvePromiseCallback final : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(ResolvePromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
nsresult Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
Promise* GetDependentPromise() override
|
||||
{
|
||||
return mPromise;
|
||||
}
|
||||
|
||||
ResolvePromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
|
||||
|
||||
private:
|
||||
~ResolvePromiseCallback();
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
JS::Heap<JSObject*> mGlobal;
|
||||
};
|
||||
|
||||
// RejectPromiseCallback calls aPromise->RejectFunction() with the value
|
||||
// received by Call().
|
||||
class RejectPromiseCallback final : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(RejectPromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
nsresult Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
Promise* GetDependentPromise() override
|
||||
{
|
||||
return mPromise;
|
||||
}
|
||||
|
||||
RejectPromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
|
||||
|
||||
private:
|
||||
~RejectPromiseCallback();
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
JS::Heap<JSObject*> mGlobal;
|
||||
};
|
||||
|
||||
// InvokePromiseFuncCallback calls the given function with the value
|
||||
// received by Call().
|
||||
class InvokePromiseFuncCallback final : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(InvokePromiseFuncCallback,
|
||||
PromiseCallback)
|
||||
|
||||
nsresult Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
Promise* GetDependentPromise() override;
|
||||
|
||||
InvokePromiseFuncCallback(JS::Handle<JSObject*> aGlobal,
|
||||
JS::Handle<JSObject*> aNextPromiseObj,
|
||||
AnyCallback* aPromiseFunc);
|
||||
|
||||
private:
|
||||
~InvokePromiseFuncCallback();
|
||||
|
||||
JS::Heap<JSObject*> mGlobal;
|
||||
JS::Heap<JSObject*> mNextPromiseObj;
|
||||
RefPtr<AnyCallback> mPromiseFunc;
|
||||
};
|
||||
|
||||
// NativePromiseCallback wraps a PromiseNativeHandler.
|
||||
class NativePromiseCallback final : public PromiseCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(NativePromiseCallback,
|
||||
PromiseCallback)
|
||||
|
||||
nsresult Call(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue) override;
|
||||
|
||||
Promise* GetDependentPromise() override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
NativePromiseCallback(PromiseNativeHandler* aHandler,
|
||||
Promise::PromiseState aState);
|
||||
|
||||
private:
|
||||
~NativePromiseCallback();
|
||||
|
||||
RefPtr<PromiseNativeHandler> mHandler;
|
||||
Promise::PromiseState mState;
|
||||
};
|
||||
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_PromiseCallback_h
|
|
@ -66,20 +66,6 @@ private:
|
|||
/* static */ MOZ_THREAD_LOCAL(bool)
|
||||
FlushRejections::sDispatched;
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
static Promise*
|
||||
UnwrapPromise(JS::Handle<JSObject*> aPromise, ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise;
|
||||
if (NS_WARN_IF(NS_FAILED(UNWRAP_OBJECT(Promise, aPromise, promise)))) {
|
||||
aRv.ThrowTypeError<MSG_IS_NOT_PROMISE>(NS_LITERAL_STRING("Argument"));
|
||||
return nullptr;
|
||||
}
|
||||
return promise;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
/* static */ void
|
||||
PromiseDebugging::GetState(GlobalObject& aGlobal, JS::Handle<JSObject*> aPromise,
|
||||
PromiseDebuggingStateHolder& aState,
|
||||
|
@ -173,34 +159,6 @@ PromiseDebugging::GetFullfillmentStack(GlobalObject& aGlobal,
|
|||
aStack.set(JS::GetPromiseResolutionSite(obj));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetState(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
PromiseDebuggingStateHolder& aState,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
switch (promise->mState) {
|
||||
case Promise::Pending:
|
||||
aState.mState = PromiseDebuggingState::Pending;
|
||||
break;
|
||||
case Promise::Resolved:
|
||||
aState.mState = PromiseDebuggingState::Fulfilled;
|
||||
aState.mValue = promise->mResult;
|
||||
break;
|
||||
case Promise::Rejected:
|
||||
aState.mState = PromiseDebuggingState::Rejected;
|
||||
aState.mReason = promise->mResult;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/*static */ nsString
|
||||
PromiseDebugging::sIDPrefix;
|
||||
|
||||
|
@ -232,86 +190,6 @@ PromiseDebugging::FlushUncaughtRejections()
|
|||
FlushRejections::FlushSync();
|
||||
}
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetAllocationStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
aStack.set(promise->mAllocationStack);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetRejectionStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
aStack.set(promise->mRejectionStack);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetFullfillmentStack(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
aStack.set(promise->mFullfillmentStack);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetDependentPromises(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
nsTArray<RefPtr<Promise>>& aPromises,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
promise->GetDependentPromises(aPromises);
|
||||
}
|
||||
|
||||
/* static */ double
|
||||
PromiseDebugging::GetPromiseLifetime(GlobalObject&,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return 0;
|
||||
}
|
||||
return (TimeStamp::Now() - promise->mCreationTimestamp).ToMilliseconds();
|
||||
}
|
||||
|
||||
/* static */ double
|
||||
PromiseDebugging::GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return 0;
|
||||
}
|
||||
if (promise->mState == Promise::Pending) {
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return 0;
|
||||
}
|
||||
return (promise->mSettlementTimestamp -
|
||||
promise->mCreationTimestamp).ToMilliseconds();
|
||||
}
|
||||
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::AddUncaughtRejectionObserver(GlobalObject&,
|
||||
UncaughtRejectionObserver& aObserver)
|
||||
|
@ -337,8 +215,6 @@ PromiseDebugging::RemoveUncaughtRejectionObserver(GlobalObject&,
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::AddUncaughtRejection(JS::HandleObject aPromise)
|
||||
{
|
||||
|
@ -420,102 +296,5 @@ PromiseDebugging::FlushUncaughtRejectionsInternal()
|
|||
storage->mConsumedRejections.clear();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::AddUncaughtRejection(Promise& aPromise)
|
||||
{
|
||||
CycleCollectedJSContext::Get()->mUncaughtRejections.AppendElement(&aPromise);
|
||||
FlushRejections::DispatchNeeded();
|
||||
}
|
||||
|
||||
/* void */ void
|
||||
PromiseDebugging::AddConsumedRejection(Promise& aPromise)
|
||||
{
|
||||
CycleCollectedJSContext::Get()->mConsumedRejections.AppendElement(&aPromise);
|
||||
FlushRejections::DispatchNeeded();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::GetPromiseID(GlobalObject&,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
nsString& aID,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
Promise* promise = UnwrapPromise(aPromise, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return;
|
||||
}
|
||||
uint64_t promiseID = promise->GetID();
|
||||
aID = sIDPrefix;
|
||||
aID.AppendInt(promiseID);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PromiseDebugging::FlushUncaughtRejectionsInternal()
|
||||
{
|
||||
CycleCollectedJSContext* storage = CycleCollectedJSContext::Get();
|
||||
|
||||
// The Promise that have been left uncaught (rejected and last in
|
||||
// their chain) since the last call to this function.
|
||||
nsTArray<nsCOMPtr<nsISupports>> uncaught;
|
||||
storage->mUncaughtRejections.SwapElements(uncaught);
|
||||
|
||||
// The Promise that have been left uncaught at some point, but that
|
||||
// have eventually had their `then` method called.
|
||||
nsTArray<nsCOMPtr<nsISupports>> consumed;
|
||||
storage->mConsumedRejections.SwapElements(consumed);
|
||||
|
||||
nsTArray<nsCOMPtr<nsISupports>>& observers = storage->mUncaughtRejectionObservers;
|
||||
|
||||
nsresult rv;
|
||||
// Notify observers of uncaught Promise.
|
||||
|
||||
for (size_t i = 0; i < uncaught.Length(); ++i) {
|
||||
nsCOMPtr<Promise> promise = do_QueryInterface(uncaught[i], &rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
if (!promise->IsLastInChain()) {
|
||||
// This promise is not the last in the chain anymore,
|
||||
// so the error has been caught at some point.
|
||||
continue;
|
||||
}
|
||||
|
||||
// For the moment, the Promise is still at the end of the
|
||||
// chain. Let's inform observers, so that they may decide whether
|
||||
// to report it.
|
||||
for (size_t j = 0; j < observers.Length(); ++j) {
|
||||
ErrorResult err;
|
||||
RefPtr<UncaughtRejectionObserver> obs =
|
||||
static_cast<UncaughtRejectionObserver*>(observers[j].get());
|
||||
|
||||
obs->OnLeftUncaught(*promise, err); // Ignore errors
|
||||
}
|
||||
|
||||
promise->SetNotifiedAsUncaught();
|
||||
}
|
||||
|
||||
// Notify observers of consumed Promise.
|
||||
|
||||
for (size_t i = 0; i < consumed.Length(); ++i) {
|
||||
nsCOMPtr<Promise> promise = do_QueryInterface(consumed[i], &rv);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
if (!promise->WasNotifiedAsUncaught()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!promise->IsLastInChain());
|
||||
for (size_t j = 0; j < observers.Length(); ++j) {
|
||||
ErrorResult err;
|
||||
RefPtr<UncaughtRejectionObserver> obs =
|
||||
static_cast<UncaughtRejectionObserver*>(observers[j].get());
|
||||
|
||||
obs->OnConsumed(*promise, err); // Ignore errors
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -52,37 +52,17 @@ public:
|
|||
JS::MutableHandle<JSObject*> aStack,
|
||||
ErrorResult& aRv);
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
static void GetDependentPromises(GlobalObject&,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
nsTArray<RefPtr<Promise>>& aPromises,
|
||||
ErrorResult& aRv);
|
||||
static double GetPromiseLifetime(GlobalObject&,
|
||||
JS::Handle<JSObject*> aPromise,
|
||||
ErrorResult& aRv);
|
||||
static double GetTimeToSettle(GlobalObject&, JS::Handle<JSObject*> aPromise,
|
||||
ErrorResult& aRv);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
// Mechanism for watching uncaught instances of Promise.
|
||||
static void AddUncaughtRejectionObserver(GlobalObject&,
|
||||
UncaughtRejectionObserver& aObserver);
|
||||
static bool RemoveUncaughtRejectionObserver(GlobalObject&,
|
||||
UncaughtRejectionObserver& aObserver);
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
// Mark a Promise as having been left uncaught at script completion.
|
||||
static void AddUncaughtRejection(JS::HandleObject);
|
||||
// Mark a Promise previously added with `AddUncaughtRejection` as
|
||||
// eventually consumed.
|
||||
static void AddConsumedRejection(JS::HandleObject);
|
||||
#else
|
||||
// Mark a Promise as having been left uncaught at script completion.
|
||||
static void AddUncaughtRejection(Promise&);
|
||||
// Mark a Promise previously added with `AddUncaughtRejection` as
|
||||
// eventually consumed.
|
||||
static void AddConsumedRejection(Promise&);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
// Propagate the informations from AddUncaughtRejection
|
||||
// and AddConsumedRejection to observers.
|
||||
static void FlushUncaughtRejections();
|
||||
|
|
|
@ -13,7 +13,6 @@ EXPORTS.mozilla.dom += [
|
|||
|
||||
UNIFIED_SOURCES += [
|
||||
'Promise.cpp',
|
||||
'PromiseCallback.cpp',
|
||||
'PromiseDebugging.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -17,51 +17,8 @@ callback PromiseJobCallback = void();
|
|||
[TreatNonCallableAsNull]
|
||||
callback AnyCallback = any (any value);
|
||||
|
||||
// When using SpiderMonkey promises, we don't want to define all this stuff;
|
||||
// just define a tiny interface to make codegen of Promise arguments and return
|
||||
// values work.
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
[Constructor(PromiseInit init),
|
||||
Exposed=(Window,Worker,WorkerDebugger,System)]
|
||||
// Need to escape "Promise" so it's treated as an identifier.
|
||||
interface _Promise {
|
||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
||||
// support the subclassing behavior, since nothing actually requires the
|
||||
// return value of PromiseSubclass.resolve/reject to be a Promise object.
|
||||
[NewObject, Throws]
|
||||
static any resolve(optional any value);
|
||||
[NewObject, Throws]
|
||||
static any reject(optional any value);
|
||||
|
||||
// The [TreatNonCallableAsNull] annotation is required since then() should do
|
||||
// nothing instead of throwing errors when non-callable arguments are passed.
|
||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
||||
// support the subclassing behavior, since nothing actually requires the
|
||||
// return value of PromiseSubclass.then/catch to be a Promise object.
|
||||
[NewObject, Throws]
|
||||
any then([TreatNonCallableAsNull] optional AnyCallback? fulfillCallback = null,
|
||||
[TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
||||
|
||||
[NewObject, Throws]
|
||||
any catch([TreatNonCallableAsNull] optional AnyCallback? rejectCallback = null);
|
||||
|
||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
||||
// support the subclassing behavior, since nothing actually requires the
|
||||
// return value of PromiseSubclass.all to be a Promise object. As a result,
|
||||
// we also have to do our argument conversion manually, because we want to
|
||||
// convert its exceptions into rejections.
|
||||
[NewObject, Throws]
|
||||
static any all(optional any iterable);
|
||||
|
||||
// Have to use "any" (or "object", but "any" is simpler) as the type to
|
||||
// support the subclassing behavior, since nothing actually requires the
|
||||
// return value of PromiseSubclass.race to be a Promise object. As a result,
|
||||
// we also have to do our argument conversion manually, because we want to
|
||||
// convert its exceptions into rejections.
|
||||
[NewObject, Throws]
|
||||
static any race(optional any iterable);
|
||||
};
|
||||
#else // SPIDERMONKEY_PROMISE
|
||||
// Promises are implemented in SpiderMonkey; just define a tiny interface to make
|
||||
// codegen of Promise arguments and return values work.
|
||||
[NoInterfaceObject,
|
||||
Exposed=(Window,Worker,WorkerDebugger,System)]
|
||||
// Need to escape "Promise" so it's treated as an identifier.
|
||||
|
@ -74,4 +31,3 @@ interface _Promise {
|
|||
Exposed=(Window,Worker,System)]
|
||||
interface PromiseNativeHandler {
|
||||
};
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
|
|
@ -38,11 +38,7 @@ callback interface UncaughtRejectionObserver {
|
|||
* caught, i.e. if its `then` callback is called, `onConsumed` will
|
||||
* be called.
|
||||
*/
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
void onLeftUncaught(object p);
|
||||
#else
|
||||
void onLeftUncaught(Promise<any> p);
|
||||
#endif SPIDERMONKEY_PROMISE
|
||||
|
||||
/**
|
||||
* A Promise previously left uncaught is not the last in its
|
||||
|
@ -51,11 +47,7 @@ callback interface UncaughtRejectionObserver {
|
|||
* @param p A Promise that was previously left in uncaught state is
|
||||
* now caught, i.e. it is not the last in its chain anymore.
|
||||
*/
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
void onConsumed(object p);
|
||||
#else
|
||||
void onConsumed(Promise<any> p);
|
||||
#endif SPIDERMONKEY_PROMISE
|
||||
};
|
||||
|
||||
[ChromeOnly, Exposed=(Window,System)]
|
||||
|
@ -105,42 +97,6 @@ interface PromiseDebugging {
|
|||
[Throws]
|
||||
static object? getFullfillmentStack(object p);
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
/**
|
||||
* Get the promises directly depending on a given promise. These are:
|
||||
*
|
||||
* 1) Return values of then() calls on the promise
|
||||
* 2) Return values of Promise.all() if the given promise was passed in as one
|
||||
* of the arguments.
|
||||
* 3) Return values of Promise.race() if the given promise was passed in as
|
||||
* one of the arguments.
|
||||
*
|
||||
* Once a promise is settled, it will generally notify its dependent promises
|
||||
* and forget about them, so this is most useful on unsettled promises.
|
||||
*
|
||||
* Note that this function only returns the promises that directly depend on
|
||||
* p. It does not recursively return promises that depend on promises that
|
||||
* depend on p.
|
||||
*/
|
||||
[Throws]
|
||||
static sequence<Promise<any>> getDependentPromises(object p);
|
||||
|
||||
/**
|
||||
* Get the number of milliseconds elapsed since the given promise was created.
|
||||
*/
|
||||
[Throws]
|
||||
static DOMHighResTimeStamp getPromiseLifetime(object p);
|
||||
|
||||
/*
|
||||
* Get the number of milliseconds elapsed between the promise being created
|
||||
* and being settled. Throws NS_ERROR_UNEXPECTED if the promise has not
|
||||
* settled.
|
||||
*/
|
||||
[Throws]
|
||||
static DOMHighResTimeStamp getTimeToSettle(object p);
|
||||
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/**
|
||||
* Watching uncaught rejections on the current thread.
|
||||
*
|
||||
|
|
|
@ -11,8 +11,6 @@ GENERATED_WEBIDL_FILES = [
|
|||
PREPROCESSED_WEBIDL_FILES = [
|
||||
'Navigator.webidl',
|
||||
'Node.webidl',
|
||||
'Promise.webidl',
|
||||
'PromiseDebugging.webidl',
|
||||
'Window.webidl',
|
||||
]
|
||||
|
||||
|
@ -372,6 +370,8 @@ WEBIDL_FILES = [
|
|||
'PresentationRequest.webidl',
|
||||
'ProcessingInstruction.webidl',
|
||||
'ProfileTimelineMarker.webidl',
|
||||
'Promise.webidl',
|
||||
'PromiseDebugging.webidl',
|
||||
'PushEvent.webidl',
|
||||
'PushManager.webidl',
|
||||
'PushManager.webidl',
|
||||
|
|
|
@ -37,19 +37,6 @@ def js_disable_shell(value):
|
|||
set_config('JS_DISABLE_SHELL', js_disable_shell)
|
||||
|
||||
|
||||
# Use SpiderMonkey Promise implementation if it's enabled
|
||||
# =======================================================
|
||||
js_option('--enable-sm-promise', default=True,
|
||||
help='Enable SpiderMonkey promises')
|
||||
|
||||
@depends('--enable-sm-promise')
|
||||
def sm_promise(value):
|
||||
if value:
|
||||
return True
|
||||
|
||||
set_config('SPIDERMONKEY_PROMISE', sm_promise)
|
||||
set_define('SPIDERMONKEY_PROMISE', sm_promise)
|
||||
|
||||
# SpiderMonkey as a shared library, and how its symbols are exported
|
||||
# ==================================================================
|
||||
js_option('--disable-shared-js', default=building_js,
|
||||
|
|
|
@ -1438,7 +1438,6 @@ OOMTest(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static bool
|
||||
SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -1547,43 +1546,6 @@ RejectPromise(JSContext* cx, unsigned argc, Value* vp)
|
|||
return result;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static const js::Class FakePromiseClass = {
|
||||
"Promise", JSCLASS_IS_ANONYMOUS
|
||||
};
|
||||
|
||||
static bool
|
||||
MakeFakePromise(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
RootedObject obj(cx, NewObjectWithGivenProto(cx, &FakePromiseClass, nullptr));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
JS::dbg::onNewPromise(cx, obj);
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
SettleFakePromise(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (!args.requireAtLeast(cx, "settleFakePromise", 1))
|
||||
return false;
|
||||
if (!args[0].isObject() || args[0].toObject().getClass() != &FakePromiseClass) {
|
||||
JS_ReportErrorASCII(cx, "first argument must be a (fake) Promise object");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject promise(cx, &args[0].toObject());
|
||||
JS::dbg::onPromiseSettled(cx, promise);
|
||||
return true;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
static unsigned finalizeCount = 0;
|
||||
|
||||
static void
|
||||
|
@ -4214,7 +4176,6 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
|
|||
" This is also disabled when --fuzzing-safe is specified."),
|
||||
#endif
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS_FN_HELP("settlePromiseNow", SettlePromiseNow, 1, 0,
|
||||
"settlePromiseNow(promise)",
|
||||
" 'Settle' a 'promise' immediately. This just marks the promise as resolved\n"
|
||||
|
@ -4231,20 +4192,6 @@ JS_FN_HELP("resolvePromise", ResolvePromise, 2, 0,
|
|||
JS_FN_HELP("rejectPromise", RejectPromise, 2, 0,
|
||||
"rejectPromise(promise, reason)",
|
||||
" Reject a Promise by calling the JSAPI function JS::RejectPromise."),
|
||||
#else
|
||||
JS_FN_HELP("makeFakePromise", MakeFakePromise, 0, 0,
|
||||
"makeFakePromise()",
|
||||
" Create an object whose [[Class]] name is 'Promise' and call\n"
|
||||
" JS::dbg::onNewPromise on it before returning it. It doesn't actually have\n"
|
||||
" any of the other behavior associated with promises."),
|
||||
|
||||
JS_FN_HELP("settleFakePromise", SettleFakePromise, 1, 0,
|
||||
"settleFakePromise(promise)",
|
||||
" 'Settle' a 'promise' created by makeFakePromise(). This doesn't have any\n"
|
||||
" observable effects outside of firing any onPromiseSettled hooks set on\n"
|
||||
" Debugger instances that are observing the given promise's global as a\n"
|
||||
" debuggee."),
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
JS_FN_HELP("makeFinalizeObserver", MakeFinalizeObserver, 0, 0,
|
||||
"makeFinalizeObserver()",
|
||||
|
|
|
@ -77,6 +77,7 @@ UNIFIED_SOURCES += [
|
|||
'testPrintf.cpp',
|
||||
'testPrivateGCThingValue.cpp',
|
||||
'testProfileStrings.cpp',
|
||||
'testPromise.cpp',
|
||||
'testPropCache.cpp',
|
||||
'testRegExp.cpp',
|
||||
'testResolveRecursion.cpp',
|
||||
|
@ -124,11 +125,6 @@ if CONFIG['ENABLE_ION']:
|
|||
'testJitRValueAlloc.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['SPIDERMONKEY_PROMISE']:
|
||||
UNIFIED_SOURCES += [
|
||||
'testPromise.cpp',
|
||||
]
|
||||
|
||||
DEFINES['EXPORT_JS_API'] = True
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
|
|
|
@ -61,12 +61,6 @@
|
|||
#define IF_SAB(real,imaginary) imaginary
|
||||
#endif
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
#define IF_PROMISE(real,imaginary) real
|
||||
#else
|
||||
#define IF_PROMISE(real,imaginary) imaginary
|
||||
#endif
|
||||
|
||||
#define JS_FOR_PROTOTYPES(real,imaginary) \
|
||||
imaginary(Null, 0, InitNullClass, dummy) \
|
||||
real(Object, 1, InitViaClassSpec, OCLASP(Plain)) \
|
||||
|
@ -122,7 +116,7 @@ IF_SAB(real,imaginary)(Atomics, 47, InitAtomicsClass, OCLASP(Atomics)) \
|
|||
imaginary(WasmInstance, 51, dummy, dummy) \
|
||||
imaginary(WasmMemory, 52, dummy, dummy) \
|
||||
imaginary(WasmTable, 53, dummy, dummy) \
|
||||
IF_PROMISE(real,imaginary)(Promise, 54, InitViaClassSpec, OCLASP(Promise)) \
|
||||
real(Promise, 54, InitViaClassSpec, OCLASP(Promise)) \
|
||||
|
||||
#define JS_FOR_EACH_PROTOTYPE(macro) JS_FOR_PROTOTYPES(macro,macro)
|
||||
|
||||
|
|
|
@ -766,6 +766,7 @@ selfhosted.inputs = [
|
|||
'builtin/Module.js',
|
||||
'builtin/Number.js',
|
||||
'builtin/Object.js',
|
||||
'builtin/Promise.js',
|
||||
'builtin/Reflect.js',
|
||||
'builtin/RegExp.js',
|
||||
'builtin/RegExpGlobalReplaceOpt.h.js',
|
||||
|
@ -779,9 +780,6 @@ selfhosted.inputs = [
|
|||
'builtin/WeakSet.js'
|
||||
]
|
||||
|
||||
if CONFIG['SPIDERMONKEY_PROMISE']:
|
||||
selfhosted.inputs += ['builtin/Promise.js']
|
||||
|
||||
if CONFIG['JS_HAS_CTYPES']:
|
||||
if CONFIG['MOZ_SYSTEM_FFI']:
|
||||
CXXFLAGS += CONFIG['MOZ_FFI_CFLAGS']
|
||||
|
|
|
@ -151,7 +151,6 @@ static const TimeDuration MAX_TIMEOUT_INTERVAL = TimeDuration::FromSeconds(1800.
|
|||
# define SHARED_MEMORY_DEFAULT 0
|
||||
#endif
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
using JobQueue = GCVector<JSObject*, 0, SystemAllocPolicy>;
|
||||
|
||||
struct ShellAsyncTasks
|
||||
|
@ -164,7 +163,6 @@ struct ShellAsyncTasks
|
|||
size_t outstanding;
|
||||
Vector<JS::AsyncTask*> finished;
|
||||
};
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
enum class ScriptKind
|
||||
{
|
||||
|
@ -269,12 +267,10 @@ struct ShellContext
|
|||
JS::PersistentRootedValue interruptFunc;
|
||||
bool lastWarningEnabled;
|
||||
JS::PersistentRootedValue lastWarning;
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS::PersistentRootedValue promiseRejectionTrackerCallback;
|
||||
JS::PersistentRooted<JobQueue> jobQueue;
|
||||
ExclusiveData<ShellAsyncTasks> asyncTasks;
|
||||
bool drainingJobQueue;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/*
|
||||
* Watchdog thread state.
|
||||
|
@ -436,11 +432,9 @@ ShellContext::ShellContext(JSContext* cx)
|
|||
interruptFunc(cx, NullValue()),
|
||||
lastWarningEnabled(false),
|
||||
lastWarning(cx, NullValue()),
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
promiseRejectionTrackerCallback(cx, NullValue()),
|
||||
asyncTasks(mutexid::ShellAsyncTasks, cx),
|
||||
drainingJobQueue(false),
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
watchdogLock(mutexid::ShellContextWatchdog),
|
||||
exitCode(0),
|
||||
quitting(false),
|
||||
|
@ -740,7 +734,6 @@ RunModule(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
|
|||
return JS_CallFunction(cx, loaderObj, importFun, args, &value);
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static JSObject*
|
||||
ShellGetIncumbentGlobalCallback(JSContext* cx)
|
||||
{
|
||||
|
@ -777,12 +770,10 @@ ShellFinishAsyncTaskCallback(JS::AsyncTask* task)
|
|||
asyncTasks->outstanding--;
|
||||
return asyncTasks->finished.append(task);
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
static bool
|
||||
DrainJobQueue(JSContext* cx)
|
||||
{
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
ShellContext* sc = GetShellContext(cx);
|
||||
if (sc->quitting || sc->drainingJobQueue)
|
||||
return true;
|
||||
|
@ -833,7 +824,6 @@ DrainJobQueue(JSContext* cx)
|
|||
}
|
||||
sc->jobQueue.clear();
|
||||
sc->drainingJobQueue = false;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -848,7 +838,6 @@ DrainJobQueue(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static void
|
||||
ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promise,
|
||||
PromiseRejectionHandlingState state, void* data)
|
||||
|
@ -871,14 +860,12 @@ ForwardingPromiseRejectionTrackerCallback(JSContext* cx, JS::HandleObject promis
|
|||
if (!Call(cx, callback, UndefinedHandleValue, args, &rval))
|
||||
JS_ClearPendingException(cx);
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
static bool
|
||||
SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
if (!IsCallable(args.get(0))) {
|
||||
JS_ReportErrorASCII(cx,
|
||||
"setPromiseRejectionTrackerCallback expects a function as its sole "
|
||||
|
@ -889,7 +876,6 @@ SetPromiseRejectionTrackerCallback(JSContext* cx, unsigned argc, Value* vp)
|
|||
GetShellContext(cx)->promiseRejectionTrackerCallback = args[0];
|
||||
JS::SetPromiseRejectionTrackerCallback(cx, ForwardingPromiseRejectionTrackerCallback);
|
||||
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
args.rval().setUndefined();
|
||||
return true;
|
||||
}
|
||||
|
@ -3324,12 +3310,10 @@ WorkerMain(void* arg)
|
|||
return;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
|
||||
JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
|
||||
JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
|
||||
JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
EnvironmentPreparer environmentPreparer(cx);
|
||||
|
||||
|
@ -3360,11 +3344,9 @@ WorkerMain(void* arg)
|
|||
|
||||
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS::SetGetIncumbentGlobalCallback(cx, nullptr);
|
||||
JS::SetEnqueuePromiseJobCallback(cx, nullptr);
|
||||
sc->jobQueue.reset();
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
KillWatchdog(cx);
|
||||
|
||||
|
@ -7915,12 +7897,10 @@ main(int argc, char** argv, char** envp)
|
|||
if (!JS::InitSelfHostedCode(cx))
|
||||
return 1;
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
sc->jobQueue.init(cx, JobQueue(SystemAllocPolicy()));
|
||||
JS::SetEnqueuePromiseJobCallback(cx, ShellEnqueuePromiseJobCallback);
|
||||
JS::SetGetIncumbentGlobalCallback(cx, ShellGetIncumbentGlobalCallback);
|
||||
JS::SetAsyncTaskCallbacks(cx, ShellStartAsyncTaskCallback, ShellFinishAsyncTaskCallback);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
EnvironmentPreparer environmentPreparer(cx);
|
||||
|
||||
|
@ -7950,11 +7930,9 @@ main(int argc, char** argv, char** envp)
|
|||
|
||||
JS::SetLargeAllocationFailureCallback(cx, nullptr, nullptr);
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS::SetGetIncumbentGlobalCallback(cx, nullptr);
|
||||
JS::SetEnqueuePromiseJobCallback(cx, nullptr);
|
||||
sc->jobQueue.reset();
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
KillWatchdog(cx);
|
||||
|
||||
|
|
|
@ -8885,7 +8885,6 @@ DebuggerObject::proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
/* static */ bool
|
||||
DebuggerObject::isPromiseGetter(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -9054,7 +9053,6 @@ DebuggerObject::promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Val
|
|||
args.rval().setObject(*promises);
|
||||
return true;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
@ -9492,7 +9490,6 @@ const JSPropertySpec DebuggerObject::properties_[] = {
|
|||
JS_PS_END
|
||||
};
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
const JSPropertySpec DebuggerObject::promiseProperties_[] = {
|
||||
JS_PSG("isPromise", DebuggerObject::isPromiseGetter, 0),
|
||||
JS_PSG("promiseState", DebuggerObject::promiseStateGetter, 0),
|
||||
|
@ -9506,7 +9503,6 @@ const JSPropertySpec DebuggerObject::promiseProperties_[] = {
|
|||
JS_PSG("promiseDependentPromises", DebuggerObject::promiseDependentPromisesGetter, 0),
|
||||
JS_PS_END
|
||||
};
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
const JSFunctionSpec DebuggerObject::methods_[] = {
|
||||
JS_FN("isExtensible", DebuggerObject::isExtensibleMethod, 0, 0),
|
||||
|
@ -9546,10 +9542,8 @@ DebuggerObject::initClass(JSContext* cx, HandleObject obj, HandleObject debugCto
|
|||
if (!objectProto)
|
||||
return nullptr;
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
if (!DefinePropertiesAndFunctions(cx, objectProto, promiseProperties_, nullptr))
|
||||
return nullptr;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
return objectProto;
|
||||
}
|
||||
|
@ -9617,7 +9611,6 @@ DebuggerObject::isScriptedProxy() const
|
|||
return js::IsScriptedProxy(referent());
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
bool
|
||||
DebuggerObject::isPromise() const
|
||||
{
|
||||
|
@ -9631,7 +9624,6 @@ DebuggerObject::isPromise() const
|
|||
|
||||
return referent->is<PromiseObject>();
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::getClassName(JSContext* cx, HandleDebuggerObject object,
|
||||
|
@ -9890,7 +9882,6 @@ DebuggerObject::getErrorColumnNumber(JSContext* cx, HandleDebuggerObject object,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
/* static */ bool
|
||||
DebuggerObject::getPromiseValue(JSContext* cx, HandleDebuggerObject object,
|
||||
MutableHandleValue result)
|
||||
|
@ -9910,7 +9901,6 @@ DebuggerObject::getPromiseReason(JSContext* cx, HandleDebuggerObject object,
|
|||
result.set(object->promise()->reason());
|
||||
return object->owner()->wrapDebuggeeValue(cx, result);
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::isExtensible(JSContext* cx, HandleDebuggerObject object, bool& result)
|
||||
|
@ -10378,7 +10368,6 @@ DebuggerObject::requireGlobal(JSContext* cx, HandleDebuggerObject object)
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
/* static */ bool
|
||||
DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
|
||||
{
|
||||
|
@ -10400,7 +10389,6 @@ DebuggerObject::requirePromise(JSContext* cx, HandleDebuggerObject object)
|
|||
|
||||
return true;
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
/* static */ bool
|
||||
DebuggerObject::getScriptedProxyTarget(JSContext* cx, HandleDebuggerObject object,
|
||||
|
|
|
@ -1365,12 +1365,10 @@ class DebuggerObject : public NativeObject
|
|||
MutableHandleDebuggerObject result);
|
||||
static MOZ_MUST_USE bool getScriptedProxyHandler(JSContext* cx, HandleDebuggerObject object,
|
||||
MutableHandleDebuggerObject result);
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static MOZ_MUST_USE bool getPromiseValue(JSContext* cx, HandleDebuggerObject object,
|
||||
MutableHandleValue result);
|
||||
static MOZ_MUST_USE bool getPromiseReason(JSContext* cx, HandleDebuggerObject object,
|
||||
MutableHandleValue result);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
// Methods
|
||||
static MOZ_MUST_USE bool isExtensible(JSContext* cx, HandleDebuggerObject object,
|
||||
|
@ -1420,16 +1418,12 @@ class DebuggerObject : public NativeObject
|
|||
bool isArrowFunction() const;
|
||||
bool isGlobal() const;
|
||||
bool isScriptedProxy() const;
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
bool isPromise() const;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
JSAtom* name() const;
|
||||
JSAtom* displayName() const;
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS::PromiseState promiseState() const;
|
||||
double promiseLifetime() const;
|
||||
double promiseTimeToResolution() const;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
private:
|
||||
enum {
|
||||
|
@ -1441,9 +1435,7 @@ class DebuggerObject : public NativeObject
|
|||
static const ClassOps classOps_;
|
||||
|
||||
static const JSPropertySpec properties_[];
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static const JSPropertySpec promiseProperties_[];
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
static const JSFunctionSpec methods_[];
|
||||
|
||||
JSObject* referent() const {
|
||||
|
@ -1453,16 +1445,10 @@ class DebuggerObject : public NativeObject
|
|||
}
|
||||
|
||||
Debugger* owner() const;
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
PromiseObject* promise() const;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
static MOZ_MUST_USE bool requireGlobal(JSContext* cx, HandleDebuggerObject object);
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static MOZ_MUST_USE bool requirePromise(JSContext* cx, HandleDebuggerObject object);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
// JSNative properties
|
||||
|
@ -1487,7 +1473,6 @@ class DebuggerObject : public NativeObject
|
|||
static MOZ_MUST_USE bool isProxyGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool proxyTargetGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool proxyHandlerGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static MOZ_MUST_USE bool isPromiseGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool promiseStateGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool promiseValueGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
@ -1498,7 +1483,6 @@ class DebuggerObject : public NativeObject
|
|||
static MOZ_MUST_USE bool promiseResolutionSiteGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool promiseIDGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
static MOZ_MUST_USE bool promiseDependentPromisesGetter(JSContext* cx, unsigned argc, Value* vp);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
// JSNative methods
|
||||
static MOZ_MUST_USE bool isExtensibleMethod(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
|
|
@ -23,9 +23,7 @@
|
|||
#include "builtin/MapObject.h"
|
||||
#include "builtin/ModuleObject.h"
|
||||
#include "builtin/Object.h"
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
#include "builtin/Promise.h"
|
||||
#endif
|
||||
#include "builtin/RegExp.h"
|
||||
#include "builtin/SelfHostingDefines.h"
|
||||
#include "builtin/SymbolObject.h"
|
||||
|
|
|
@ -1621,7 +1621,6 @@ WebAssembly_toSource(JSContext* cx, unsigned argc, Value* vp)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static bool
|
||||
Nop(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
@ -1895,7 +1894,6 @@ WebAssembly_instantiate(JSContext* cx, unsigned argc, Value* vp)
|
|||
callArgs.rval().setObject(*promise);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool
|
||||
WebAssembly_validate(JSContext* cx, unsigned argc, Value* vp)
|
||||
|
@ -1926,10 +1924,8 @@ static const JSFunctionSpec WebAssembly_static_methods[] =
|
|||
#if JS_HAS_TOSOURCE
|
||||
JS_FN(js_toSource_str, WebAssembly_toSource, 0, 0),
|
||||
#endif
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS_FN("compile", WebAssembly_compile, 1, 0),
|
||||
JS_FN("instantiate", WebAssembly_instantiate, 2, 0),
|
||||
#endif
|
||||
JS_FN("validate", WebAssembly_validate, 1, 0),
|
||||
JS_FS_END
|
||||
};
|
||||
|
|
|
@ -1206,13 +1206,6 @@ xpc::CreateSandboxObject(JSContext* cx, MutableHandleValue vp, nsISupports* prin
|
|||
|
||||
if (!options.globalProperties.DefineInSandbox(cx, sandbox))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
|
||||
#ifndef SPIDERMONKEY_PROMISE
|
||||
// Promise is supposed to be part of ES, and therefore should appear on
|
||||
// every global.
|
||||
if (!dom::PromiseBinding::GetConstructorObject(cx))
|
||||
return NS_ERROR_XPC_UNEXPECTED;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
}
|
||||
|
||||
// We handle the case where the context isn't in a compartment for the
|
||||
|
|
|
@ -791,7 +791,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
|||
return CreateHolderIfNeeded(flat, d, dest);
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
||||
// Check for a Promise being returned via nsISupports. In that
|
||||
// situation, we want to dig out its underlying JS object and return
|
||||
|
@ -804,7 +803,6 @@ XPCConvert::NativeInterface2JSObject(MutableHandleValue d,
|
|||
return CreateHolderIfNeeded(flat, d, dest);
|
||||
}
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
// Don't double wrap CPOWs. This is a temporary measure for compatibility
|
||||
// with objects that don't provide necessary QIs (such as objects under
|
||||
|
@ -943,7 +941,6 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
// Deal with Promises being passed as nsISupports. In that situation we
|
||||
// want to create a dom::Promise and use that.
|
||||
if (iid->Equals(NS_GET_IID(nsISupports))) {
|
||||
|
@ -954,7 +951,6 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
|
|||
return p && NS_SUCCEEDED(p->QueryInterface(*iid, dest));
|
||||
}
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
}
|
||||
|
||||
RefPtr<nsXPCWrappedJS> wrapper;
|
||||
|
|
|
@ -95,7 +95,6 @@ def build_dict(config, env=os.environ):
|
|||
d['addon_signing'] = substs.get('MOZ_ADDON_SIGNING') == '1'
|
||||
d['require_signing'] = substs.get('MOZ_REQUIRE_SIGNING') == '1'
|
||||
d['official'] = bool(substs.get('MOZILLA_OFFICIAL'))
|
||||
d['sm_promise'] = bool(substs.get('SPIDERMONKEY_PROMISE'))
|
||||
|
||||
def guess_platform():
|
||||
if d['buildapp'] in ('browser', 'mulet'):
|
||||
|
|
|
@ -470,10 +470,8 @@ CycleCollectedJSContext::~CycleCollectedJSContext()
|
|||
MOZ_ASSERT(mDebuggerPromiseMicroTaskQueue.empty());
|
||||
MOZ_ASSERT(mPromiseMicroTaskQueue.empty());
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
mUncaughtRejections.reset();
|
||||
mConsumedRejections.reset();
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
JS_DestroyContext(mJSContext);
|
||||
mJSContext = nullptr;
|
||||
|
@ -550,12 +548,10 @@ CycleCollectedJSContext::Initialize(JSContext* aParentContext,
|
|||
|
||||
JS::SetGetIncumbentGlobalCallback(mJSContext, GetIncumbentGlobalCallback);
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
JS::SetEnqueuePromiseJobCallback(mJSContext, EnqueuePromiseJobCallback, this);
|
||||
JS::SetPromiseRejectionTrackerCallback(mJSContext, PromiseRejectionTrackerCallback, this);
|
||||
mUncaughtRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
||||
mConsumedRejections.init(mJSContext, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
JS::dbg::SetDebuggerMallocSizeOf(mJSContext, moz_malloc_size_of);
|
||||
|
||||
|
@ -981,7 +977,6 @@ CycleCollectedJSContext::EnqueuePromiseJobCallback(JSContext* aCx,
|
|||
return true;
|
||||
}
|
||||
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
/* static */
|
||||
void
|
||||
CycleCollectedJSContext::PromiseRejectionTrackerCallback(JSContext* aCx,
|
||||
|
@ -1001,7 +996,6 @@ CycleCollectedJSContext::PromiseRejectionTrackerCallback(JSContext* aCx,
|
|||
PromiseDebugging::AddConsumedRejection(aPromise);
|
||||
}
|
||||
}
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
struct JsGcTracer : public TraceCallbacks
|
||||
{
|
||||
|
|
|
@ -224,12 +224,10 @@ private:
|
|||
JS::HandleObject aAllocationSite,
|
||||
JS::HandleObject aIncumbentGlobal,
|
||||
void* aData);
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
static void PromiseRejectionTrackerCallback(JSContext* aCx,
|
||||
JS::HandleObject aPromise,
|
||||
PromiseRejectionHandlingState state,
|
||||
void* aData);
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
|
||||
virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
|
||||
void TraceNativeGrayRoots(JSTracer* aTracer);
|
||||
|
@ -406,7 +404,6 @@ public:
|
|||
|
||||
// Storage for watching rejected promises waiting for some client to
|
||||
// consume their rejection.
|
||||
#ifdef SPIDERMONKEY_PROMISE
|
||||
// Promises in this list have been rejected in the last turn of the
|
||||
// event loop without the rejection being handled.
|
||||
// Note that this can contain nullptrs in place of promises removed because
|
||||
|
@ -417,13 +414,6 @@ public:
|
|||
// (because they were in the above list), but the rejection was handled
|
||||
// in the last turn of the event loop.
|
||||
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mConsumedRejections;
|
||||
#else
|
||||
// We store values as `nsISupports` to avoid adding compile-time dependencies
|
||||
// from xpcom to dom/promise, but they can really only have a single concrete
|
||||
// type.
|
||||
nsTArray<nsCOMPtr<nsISupports /* Promise */>> mUncaughtRejections;
|
||||
nsTArray<nsCOMPtr<nsISupports /* Promise */ >> mConsumedRejections;
|
||||
#endif // SPIDERMONKEY_PROMISE
|
||||
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
|
||||
|
||||
private:
|
||||
|
|
Загрузка…
Ссылка в новой задаче