Bug 1549351 - Promise rejection event should not be sent for cross-origin scripts; r=smaug,till
authorEdgar Chen <echen@mozilla.com>
Sun, 19 May 2019 01:18:04 +0000
changeset 474481 0e88a0a379f37595e17d7b516c90d8d2962798d0
parent 474480 ab585bce1f5bee00fa4dcad39f7701359ceba6a0
child 474482 bba4ef388cc0906abaa9bab96c0e9c3bfec5490a
push id36040
push userrgurzau@mozilla.com
push dateMon, 20 May 2019 13:43:21 +0000
treeherdermozilla-central@319a369ccde4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug, till
bugs1549351
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1549351 - Promise rejection event should not be sent for cross-origin scripts; r=smaug,till Differential Revision: https://phabricator.services.mozilla.com/D31565
js/public/Promise.h
js/src/shell/js.cpp
js/src/vm/Runtime.cpp
testing/web-platform/meta/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/disallow-crossorigin.html.ini
xpcom/base/CycleCollectedJSContext.cpp
xpcom/base/CycleCollectedJSContext.h
--- a/js/public/Promise.h
+++ b/js/public/Promise.h
@@ -255,17 +255,17 @@ class MOZ_RAII JS_PUBLIC_API AutoDebugge
   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER;
   JSContext* cx;
   js::UniquePtr<JobQueue::SavedJobQueue> saved;
 };
 
 enum class PromiseRejectionHandlingState { Unhandled, Handled };
 
 typedef void (*PromiseRejectionTrackerCallback)(
-    JSContext* cx, JS::HandleObject promise,
+    JSContext* cx, bool mutedErrors, JS::HandleObject promise,
     JS::PromiseRejectionHandlingState state, void* data);
 
 /**
  * Sets the callback that's invoked whenever a Promise is rejected without
  * a rejection handler, and when a Promise that was previously rejected
  * without a handler gets a handler attached.
  */
 extern JS_PUBLIC_API void SetPromiseRejectionTrackerCallback(
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -1132,17 +1132,17 @@ static bool TrackUnhandledRejections(JSC
       // add the promise in the first place, due to OOM.
       break;
   }
 
   return true;
 }
 
 static void ForwardingPromiseRejectionTrackerCallback(
-    JSContext* cx, JS::HandleObject promise,
+    JSContext* cx, bool mutedErrors, JS::HandleObject promise,
     JS::PromiseRejectionHandlingState state, void* data) {
   AutoReportException are(cx);
 
   if (!TrackUnhandledRejections(cx, promise, state)) {
     return;
   }
 
   RootedValue callback(cx,
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -632,31 +632,43 @@ bool JSRuntime::enqueuePromiseJob(JSCont
 
 void JSRuntime::addUnhandledRejectedPromise(JSContext* cx,
                                             js::HandleObject promise) {
   MOZ_ASSERT(promise->is<PromiseObject>());
   if (!cx->promiseRejectionTrackerCallback) {
     return;
   }
 
+  bool mutedErrors = false;
+  if (JSScript* script = cx->currentScript()) {
+    mutedErrors = script->mutedErrors();
+  }
+
   void* data = cx->promiseRejectionTrackerCallbackData;
   cx->promiseRejectionTrackerCallback(
-      cx, promise, JS::PromiseRejectionHandlingState::Unhandled, data);
+      cx, mutedErrors, promise, JS::PromiseRejectionHandlingState::Unhandled,
+      data);
 }
 
 void JSRuntime::removeUnhandledRejectedPromise(JSContext* cx,
                                                js::HandleObject promise) {
   MOZ_ASSERT(promise->is<PromiseObject>());
   if (!cx->promiseRejectionTrackerCallback) {
     return;
   }
 
+  bool mutedErrors = false;
+  if (JSScript* script = cx->currentScript()) {
+    mutedErrors = script->mutedErrors();
+  }
+
   void* data = cx->promiseRejectionTrackerCallbackData;
   cx->promiseRejectionTrackerCallback(
-      cx, promise, JS::PromiseRejectionHandlingState::Handled, data);
+      cx, mutedErrors, promise, JS::PromiseRejectionHandlingState::Handled,
+      data);
 }
 
 mozilla::non_crypto::XorShift128PlusRNG& JSRuntime::randomKeyGenerator() {
   MOZ_ASSERT(CurrentThreadCanAccessRuntime(this));
   if (randomKeyGenerator_.isNothing()) {
     mozilla::Array<uint64_t, 2> seed;
     GenerateXorShift128PlusSeed(seed);
     randomKeyGenerator_.emplace(seed[0], seed[1]);
deleted file mode 100644
--- a/testing/web-platform/meta/html/webappapis/scripting/processing-model-2/unhandled-promise-rejections/disallow-crossorigin.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[disallow-crossorigin.html]
-  expected: ERROR
-  [Promise rejection event should be muted for cross-origin non-CORS script]
-    expected: FAIL
-
--- a/xpcom/base/CycleCollectedJSContext.cpp
+++ b/xpcom/base/CycleCollectedJSContext.cpp
@@ -327,41 +327,43 @@ CycleCollectedJSContext::saveJobQueue(JS
     return nullptr;
   }
 
   return saved;
 }
 
 /* static */
 void CycleCollectedJSContext::PromiseRejectionTrackerCallback(
-    JSContext* aCx, JS::HandleObject aPromise,
+    JSContext* aCx, bool aMutedErrors, JS::HandleObject aPromise,
     JS::PromiseRejectionHandlingState state, void* aData) {
   CycleCollectedJSContext* self = static_cast<CycleCollectedJSContext*>(aData);
 
   MOZ_ASSERT(aCx == self->Context());
   MOZ_ASSERT(Get() == self);
 
   // TODO: Bug 1549351 - Promise rejection event should not be sent for
   // cross-origin scripts
 
   PromiseArray& aboutToBeNotified = self->mAboutToBeNotifiedRejectedPromises;
   PromiseHashtable& unhandled = self->mPendingUnhandledRejections;
   uint64_t promiseID = JS::GetPromiseID(aPromise);
 
   if (state == JS::PromiseRejectionHandlingState::Unhandled) {
     PromiseDebugging::AddUncaughtRejection(aPromise);
-    if (mozilla::StaticPrefs::dom_promise_rejection_events_enabled()) {
+    if (mozilla::StaticPrefs::dom_promise_rejection_events_enabled() &&
+        !aMutedErrors) {
       RefPtr<Promise> promise =
           Promise::CreateFromExisting(xpc::NativeGlobal(aPromise), aPromise);
       aboutToBeNotified.AppendElement(promise);
       unhandled.Put(promiseID, promise);
     }
   } else {
     PromiseDebugging::AddConsumedRejection(aPromise);
-    if (mozilla::StaticPrefs::dom_promise_rejection_events_enabled()) {
+    if (mozilla::StaticPrefs::dom_promise_rejection_events_enabled() &&
+        !aMutedErrors) {
       for (size_t i = 0; i < aboutToBeNotified.Length(); i++) {
         if (aboutToBeNotified[i] &&
             aboutToBeNotified[i]->PromiseObj() == 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.
           aboutToBeNotified[i] = nullptr;
           DebugOnly<bool> isFound = unhandled.Remove(promiseID);
--- a/xpcom/base/CycleCollectedJSContext.h
+++ b/xpcom/base/CycleCollectedJSContext.h
@@ -113,17 +113,17 @@ class CycleCollectedJSContext
   static JSObject* GetIncumbentGlobalCallback(JSContext* aCx);
   static bool EnqueuePromiseJobCallback(JSContext* aCx,
                                         JS::HandleObject aPromise,
                                         JS::HandleObject aJob,
                                         JS::HandleObject aAllocationSite,
                                         JS::HandleObject aIncumbentGlobal,
                                         void* aData);
   static void PromiseRejectionTrackerCallback(
-      JSContext* aCx, JS::HandleObject aPromise,
+      JSContext* aCx, bool aMutedErrors, JS::HandleObject aPromise,
       JS::PromiseRejectionHandlingState state, void* aData);
 
   void AfterProcessMicrotasks();
 
  public:
   void ProcessStableStateQueue();
 
  private: