mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 911216 - Part 24: Use promise rejection tracking to report unhandled rejections to the console. r=bz,Paolo
This commit is contained in:
parent
0f6f35176e
commit
b0d2250794
@ -940,6 +940,35 @@ Promise::MaybeRejectWithNull()
|
|||||||
MaybeSomething(JS::NullHandleValue, &Promise::MaybeReject);
|
MaybeSomething(JS::NullHandleValue, &Promise::MaybeReject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
|
void
|
||||||
|
Promise::ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(!js::IsWrapper(aPromise));
|
||||||
|
|
||||||
|
MOZ_ASSERT(JS::GetPromiseState(aPromise) == JS::PromiseState::Rejected);
|
||||||
|
|
||||||
|
JS::Rooted<JS::Value> result(aCx, JS::GetPromiseResult(aPromise));
|
||||||
|
|
||||||
|
js::ErrorReport report(aCx);
|
||||||
|
if (!report.init(aCx, result, js::ErrorReport::NoSideEffects)) {
|
||||||
|
JS_ClearPendingException(aCx);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||||
|
bool isMainThread = MOZ_LIKELY(NS_IsMainThread());
|
||||||
|
bool isChrome = isMainThread ? nsContentUtils::IsSystemPrincipal(nsContentUtils::ObjectPrincipal(aPromise))
|
||||||
|
: GetCurrentThreadWorkerPrivate()->IsChromeWorker();
|
||||||
|
nsGlobalWindow* win = isMainThread ? xpc::WindowGlobalOrNull(aPromise) : nullptr;
|
||||||
|
xpcReport->Init(report.report(), report.message(), isChrome, win ? win->AsInner()->WindowID() : 0);
|
||||||
|
|
||||||
|
// Now post an event to do the real reporting async
|
||||||
|
NS_DispatchToMainThread(new AsyncErrorReporter(xpcReport));
|
||||||
|
}
|
||||||
|
#endif // defined(SPIDERMONKEY_PROMISE)
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Promise::PerformMicroTaskCheckpoint()
|
Promise::PerformMicroTaskCheckpoint()
|
||||||
{
|
{
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
// that need to be removed once clients have been put together
|
// that need to be removed once clients have been put together
|
||||||
// to take advantage of the new mechanism. New code should not
|
// to take advantage of the new mechanism. New code should not
|
||||||
// depend on code #ifdefed to this #define.
|
// depend on code #ifdefed to this #define.
|
||||||
#define DOM_PROMISE_DEPRECATED_REPORTING 1
|
#define DOM_PROMISE_DEPRECATED_REPORTING !SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
#if defined(DOM_PROMISE_DEPRECATED_REPORTING)
|
||||||
#include "mozilla/dom/workers/bindings/WorkerFeature.h"
|
#include "mozilla/dom/workers/bindings/WorkerFeature.h"
|
||||||
@ -112,6 +112,9 @@ public:
|
|||||||
#ifdef SPIDERMONKEY_PROMISE
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
static already_AddRefed<Promise>
|
static already_AddRefed<Promise>
|
||||||
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
|
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv);
|
||||||
|
|
||||||
|
// Reports a rejected Promise by sending an error report.
|
||||||
|
static void ReportRejectedPromise(JSContext* aCx, JS::HandleObject aPromise);
|
||||||
#else
|
#else
|
||||||
static already_AddRefed<Promise>
|
static already_AddRefed<Promise>
|
||||||
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
|
Create(nsIGlobalObject* aGlobal, ErrorResult& aRv,
|
||||||
|
@ -230,11 +230,8 @@ PromiseDebugging::Shutdown()
|
|||||||
/* static */ void
|
/* static */ void
|
||||||
PromiseDebugging::FlushUncaughtRejections()
|
PromiseDebugging::FlushUncaughtRejections()
|
||||||
{
|
{
|
||||||
// XXXbz figure out the plan
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
FlushRejections::FlushSync();
|
FlushRejections::FlushSync();
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
#ifndef SPIDERMONKEY_PROMISE
|
||||||
@ -342,7 +339,90 @@ PromiseDebugging::RemoveUncaughtRejectionObserver(GlobalObject&,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PromiseDebugging::AddUncaughtRejection(JS::HandleObject aPromise)
|
||||||
|
{
|
||||||
|
// This might OOM, but won't set a pending exception, so we'll just ignore it.
|
||||||
|
if (CycleCollectedJSRuntime::Get()->mUncaughtRejections.append(aPromise)) {
|
||||||
|
FlushRejections::DispatchNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* void */ void
|
||||||
|
PromiseDebugging::AddConsumedRejection(JS::HandleObject aPromise)
|
||||||
|
{
|
||||||
|
// If the promise is in our list of uncaught rejections, we haven't yet
|
||||||
|
// reported it as unhandled. In that case, just remove it from the list
|
||||||
|
// and don't add it to the list of consumed rejections.
|
||||||
|
auto& uncaughtRejections = CycleCollectedJSRuntime::Get()->mUncaughtRejections;
|
||||||
|
for (size_t i = 0; i < uncaughtRejections.length(); i++) {
|
||||||
|
if (uncaughtRejections[i] == aPromise) {
|
||||||
|
// To avoid large amounts of memmoves, we don't shrink the vector here.
|
||||||
|
// Instead, we filter out nullptrs when iterating over the vector later.
|
||||||
|
uncaughtRejections[i].set(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// This might OOM, but won't set a pending exception, so we'll just ignore it.
|
||||||
|
if (CycleCollectedJSRuntime::Get()->mConsumedRejections.append(aPromise)) {
|
||||||
|
FlushRejections::DispatchNeeded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
PromiseDebugging::FlushUncaughtRejectionsInternal()
|
||||||
|
{
|
||||||
|
CycleCollectedJSRuntime* storage = CycleCollectedJSRuntime::Get();
|
||||||
|
|
||||||
|
auto& uncaught = storage->mUncaughtRejections;
|
||||||
|
auto& consumed = storage->mConsumedRejections;
|
||||||
|
|
||||||
|
AutoJSAPI jsapi;
|
||||||
|
jsapi.Init();
|
||||||
|
JSContext* cx = jsapi.cx();
|
||||||
|
|
||||||
|
// Notify observers of uncaught Promise.
|
||||||
|
auto& observers = storage->mUncaughtRejectionObservers;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < uncaught.length(); i++) {
|
||||||
|
JS::RootedObject promise(cx, uncaught[i]);
|
||||||
|
// Filter out nullptrs which might've been added by
|
||||||
|
// PromiseDebugging::AddConsumedRejection.
|
||||||
|
if (!promise) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < observers.Length(); ++j) {
|
||||||
|
RefPtr<UncaughtRejectionObserver> obs =
|
||||||
|
static_cast<UncaughtRejectionObserver*>(observers[j].get());
|
||||||
|
|
||||||
|
IgnoredErrorResult err;
|
||||||
|
obs->OnLeftUncaught(promise, err);
|
||||||
|
}
|
||||||
|
JSAutoCompartment ac(cx, promise);
|
||||||
|
Promise::ReportRejectedPromise(cx, promise);
|
||||||
|
}
|
||||||
|
storage->mUncaughtRejections.clear();
|
||||||
|
|
||||||
|
// Notify observers of consumed Promise.
|
||||||
|
|
||||||
|
for (size_t i = 0; i < consumed.length(); i++) {
|
||||||
|
JS::RootedObject promise(cx, consumed[i]);
|
||||||
|
|
||||||
|
for (size_t j = 0; j < observers.Length(); ++j) {
|
||||||
|
RefPtr<UncaughtRejectionObserver> obs =
|
||||||
|
static_cast<UncaughtRejectionObserver*>(observers[j].get());
|
||||||
|
|
||||||
|
IgnoredErrorResult err;
|
||||||
|
obs->OnConsumed(promise, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
storage->mConsumedRejections.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PromiseDebugging::AddUncaughtRejection(Promise& aPromise)
|
PromiseDebugging::AddUncaughtRejection(Promise& aPromise)
|
||||||
@ -372,13 +452,10 @@ PromiseDebugging::GetPromiseID(GlobalObject&,
|
|||||||
aID = sIDPrefix;
|
aID = sIDPrefix;
|
||||||
aID.AppendInt(promiseID);
|
aID.AppendInt(promiseID);
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
|
|
||||||
/* static */ void
|
/* static */ void
|
||||||
PromiseDebugging::FlushUncaughtRejectionsInternal()
|
PromiseDebugging::FlushUncaughtRejectionsInternal()
|
||||||
{
|
{
|
||||||
// XXXbz talk to till about replacement for this stuff.
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
|
||||||
CycleCollectedJSRuntime* storage = CycleCollectedJSRuntime::Get();
|
CycleCollectedJSRuntime* storage = CycleCollectedJSRuntime::Get();
|
||||||
|
|
||||||
// The Promise that have been left uncaught (rejected and last in
|
// The Promise that have been left uncaught (rejected and last in
|
||||||
@ -439,8 +516,8 @@ PromiseDebugging::FlushUncaughtRejectionsInternal()
|
|||||||
obs->OnConsumed(*promise, err); // Ignore errors
|
obs->OnConsumed(*promise, err); // Ignore errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
|
||||||
}
|
}
|
||||||
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -26,6 +26,8 @@ class GlobalObject;
|
|||||||
class UncaughtRejectionObserver;
|
class UncaughtRejectionObserver;
|
||||||
class FlushRejections;
|
class FlushRejections;
|
||||||
|
|
||||||
|
void TriggerFlushRejections();
|
||||||
|
|
||||||
class PromiseDebugging
|
class PromiseDebugging
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -63,13 +65,18 @@ public:
|
|||||||
#endif // SPIDERMONKEY_PROMISE
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
// Mechanism for watching uncaught instances of Promise.
|
// Mechanism for watching uncaught instances of Promise.
|
||||||
// XXXbz figure out the plan
|
|
||||||
static void AddUncaughtRejectionObserver(GlobalObject&,
|
static void AddUncaughtRejectionObserver(GlobalObject&,
|
||||||
UncaughtRejectionObserver& aObserver);
|
UncaughtRejectionObserver& aObserver);
|
||||||
static bool RemoveUncaughtRejectionObserver(GlobalObject&,
|
static bool RemoveUncaughtRejectionObserver(GlobalObject&,
|
||||||
UncaughtRejectionObserver& aObserver);
|
UncaughtRejectionObserver& aObserver);
|
||||||
|
|
||||||
#ifndef SPIDERMONKEY_PROMISE
|
#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.
|
// Mark a Promise as having been left uncaught at script completion.
|
||||||
static void AddUncaughtRejection(Promise&);
|
static void AddUncaughtRejection(Promise&);
|
||||||
// Mark a Promise previously added with `AddUncaughtRejection` as
|
// Mark a Promise previously added with `AddUncaughtRejection` as
|
||||||
@ -78,7 +85,6 @@ public:
|
|||||||
#endif // SPIDERMONKEY_PROMISE
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
// Propagate the informations from AddUncaughtRejection
|
// Propagate the informations from AddUncaughtRejection
|
||||||
// and AddConsumedRejection to observers.
|
// and AddConsumedRejection to observers.
|
||||||
// XXXbz figure out the plan.
|
|
||||||
static void FlushUncaughtRejections();
|
static void FlushUncaughtRejections();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -38,7 +38,11 @@ callback interface UncaughtRejectionObserver {
|
|||||||
* caught, i.e. if its `then` callback is called, `onConsumed` will
|
* caught, i.e. if its `then` callback is called, `onConsumed` will
|
||||||
* be called.
|
* be called.
|
||||||
*/
|
*/
|
||||||
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
|
void onLeftUncaught(object p);
|
||||||
|
#else
|
||||||
void onLeftUncaught(Promise<any> p);
|
void onLeftUncaught(Promise<any> p);
|
||||||
|
#endif SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Promise previously left uncaught is not the last in its
|
* A Promise previously left uncaught is not the last in its
|
||||||
@ -47,7 +51,11 @@ callback interface UncaughtRejectionObserver {
|
|||||||
* @param p A Promise that was previously left in uncaught state is
|
* @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.
|
* 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);
|
void onConsumed(Promise<any> p);
|
||||||
|
#endif SPIDERMONKEY_PROMISE
|
||||||
};
|
};
|
||||||
|
|
||||||
[ChromeOnly, Exposed=(Window,System)]
|
[ChromeOnly, Exposed=(Window,System)]
|
||||||
|
@ -857,6 +857,9 @@ add_test({
|
|||||||
self.writeManifest(["test_simple_uncaught_rejection.js"])
|
self.writeManifest(["test_simple_uncaught_rejection.js"])
|
||||||
|
|
||||||
self.assertTestResult(False)
|
self.assertTestResult(False)
|
||||||
|
self.assertInLog(TEST_FAIL_STRING)
|
||||||
|
self.assertInLog("test_simple_uncaught_rejection.js:3:3")
|
||||||
|
self.assertInLog("Test rejection.")
|
||||||
self.assertEquals(1, self.x.testCount)
|
self.assertEquals(1, self.x.testCount)
|
||||||
self.assertEquals(0, self.x.passCount)
|
self.assertEquals(0, self.x.passCount)
|
||||||
self.assertEquals(1, self.x.failCount)
|
self.assertEquals(1, self.x.failCount)
|
||||||
@ -869,6 +872,9 @@ add_test({
|
|||||||
self.writeManifest(["test_simple_uncaught_rejection_jsm.js"])
|
self.writeManifest(["test_simple_uncaught_rejection_jsm.js"])
|
||||||
|
|
||||||
self.assertTestResult(False)
|
self.assertTestResult(False)
|
||||||
|
self.assertInLog(TEST_FAIL_STRING)
|
||||||
|
self.assertInLog("test_simple_uncaught_rejection_jsm.js:4:16")
|
||||||
|
self.assertInLog("Test rejection.")
|
||||||
self.assertEquals(1, self.x.testCount)
|
self.assertEquals(1, self.x.testCount)
|
||||||
self.assertEquals(0, self.x.passCount)
|
self.assertEquals(0, self.x.passCount)
|
||||||
self.assertEquals(1, self.x.failCount)
|
self.assertEquals(1, self.x.failCount)
|
||||||
|
@ -69,6 +69,7 @@
|
|||||||
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
#include "mozilla/dom/ProfileTimelineMarkerBinding.h"
|
||||||
#include "mozilla/dom/Promise.h"
|
#include "mozilla/dom/Promise.h"
|
||||||
#include "mozilla/dom/PromiseBinding.h"
|
#include "mozilla/dom/PromiseBinding.h"
|
||||||
|
#include "mozilla/dom/PromiseDebugging.h"
|
||||||
#include "mozilla/dom/ScriptSettings.h"
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "jsprf.h"
|
#include "jsprf.h"
|
||||||
#include "js/Debug.h"
|
#include "js/Debug.h"
|
||||||
@ -471,6 +472,11 @@ CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
|
|||||||
MOZ_ASSERT(mDebuggerPromiseMicroTaskQueue.empty());
|
MOZ_ASSERT(mDebuggerPromiseMicroTaskQueue.empty());
|
||||||
MOZ_ASSERT(mPromiseMicroTaskQueue.empty());
|
MOZ_ASSERT(mPromiseMicroTaskQueue.empty());
|
||||||
|
|
||||||
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
|
mUncaughtRejections.reset();
|
||||||
|
mConsumedRejections.reset();
|
||||||
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
JS_DestroyRuntime(mJSRuntime);
|
JS_DestroyRuntime(mJSRuntime);
|
||||||
mJSRuntime = nullptr;
|
mJSRuntime = nullptr;
|
||||||
nsCycleCollector_forgetJSRuntime();
|
nsCycleCollector_forgetJSRuntime();
|
||||||
@ -540,6 +546,9 @@ CycleCollectedJSRuntime::Initialize(JSRuntime* aParentRuntime,
|
|||||||
|
|
||||||
#ifdef SPIDERMONKEY_PROMISE
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
JS::SetEnqueuePromiseJobCallback(mJSRuntime, EnqueuePromiseJobCallback, this);
|
JS::SetEnqueuePromiseJobCallback(mJSRuntime, EnqueuePromiseJobCallback, this);
|
||||||
|
JS::SetPromiseRejectionTrackerCallback(mJSRuntime, PromiseRejectionTrackerCallback, this);
|
||||||
|
mUncaughtRejections.init(mJSRuntime, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
||||||
|
mConsumedRejections.init(mJSRuntime, JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>(js::SystemAllocPolicy()));
|
||||||
#endif // SPIDERMONKEY_PROMISE
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
JS::dbg::SetDebuggerMallocSizeOf(mJSRuntime, moz_malloc_size_of);
|
JS::dbg::SetDebuggerMallocSizeOf(mJSRuntime, moz_malloc_size_of);
|
||||||
@ -948,6 +957,28 @@ CycleCollectedJSRuntime::EnqueuePromiseJobCallback(JSContext* aCx,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef SPIDERMONKEY_PROMISE
|
||||||
|
/* static */
|
||||||
|
void
|
||||||
|
CycleCollectedJSRuntime::PromiseRejectionTrackerCallback(JSContext* aCx,
|
||||||
|
JS::HandleObject aPromise,
|
||||||
|
PromiseRejectionHandlingState state,
|
||||||
|
void* aData)
|
||||||
|
{
|
||||||
|
#ifdef DEBUG
|
||||||
|
CycleCollectedJSRuntime* self = static_cast<CycleCollectedJSRuntime*>(aData);
|
||||||
|
#endif // DEBUG
|
||||||
|
MOZ_ASSERT(JS_GetRuntime(aCx) == self->Runtime());
|
||||||
|
MOZ_ASSERT(Get() == self);
|
||||||
|
|
||||||
|
if (state == PromiseRejectionHandlingState::Unhandled) {
|
||||||
|
PromiseDebugging::AddUncaughtRejection(aPromise);
|
||||||
|
} else {
|
||||||
|
PromiseDebugging::AddConsumedRejection(aPromise);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
|
|
||||||
struct JsGcTracer : public TraceCallbacks
|
struct JsGcTracer : public TraceCallbacks
|
||||||
{
|
{
|
||||||
virtual void Trace(JS::Heap<JS::Value>* aPtr, const char* aName,
|
virtual void Trace(JS::Heap<JS::Value>* aPtr, const char* aName,
|
||||||
|
@ -221,6 +221,12 @@ private:
|
|||||||
JS::HandleObject aJob,
|
JS::HandleObject aJob,
|
||||||
JS::HandleObject aAllocationSite,
|
JS::HandleObject aAllocationSite,
|
||||||
void* aData);
|
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) { };
|
virtual void TraceNativeBlackRoots(JSTracer* aTracer) { };
|
||||||
void TraceNativeGrayRoots(JSTracer* aTracer);
|
void TraceNativeGrayRoots(JSTracer* aTracer);
|
||||||
@ -362,11 +368,24 @@ public:
|
|||||||
|
|
||||||
// Storage for watching rejected promises waiting for some client to
|
// Storage for watching rejected promises waiting for some client to
|
||||||
// consume their rejection.
|
// 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
|
||||||
|
// they're consumed before it'd be reported.
|
||||||
|
JS::PersistentRooted<JS::GCVector<JSObject*, 0, js::SystemAllocPolicy>> mUncaughtRejections;
|
||||||
|
|
||||||
|
// Promises in this list have previously been reported as rejected
|
||||||
|
// (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
|
// 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
|
// from xpcom to dom/promise, but they can really only have a single concrete
|
||||||
// type.
|
// type.
|
||||||
nsTArray<nsCOMPtr<nsISupports /* Promise */>> mUncaughtRejections;
|
nsTArray<nsCOMPtr<nsISupports /* Promise */>> mUncaughtRejections;
|
||||||
nsTArray<nsCOMPtr<nsISupports /* Promise */ >> mConsumedRejections;
|
nsTArray<nsCOMPtr<nsISupports /* Promise */ >> mConsumedRejections;
|
||||||
|
#endif // SPIDERMONKEY_PROMISE
|
||||||
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
|
nsTArray<nsCOMPtr<nsISupports /* UncaughtRejectionObserver */ >> mUncaughtRejectionObservers;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user