Backed out changeset c839f283bf28 (bug 1058695) for bustage.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 27 Apr 2015 14:04:24 -0400
changeset 241334 d02374f93b37167b58a34a8f78ee785089027c3c
parent 241333 600207b620204b60e41164b70e552cf764a80b7c
child 241335 4f898b4ffd633ed3dc2c75cd5e38e8016b2e3ea6
push id28658
push usercbook@mozilla.com
push dateTue, 28 Apr 2015 10:01:27 +0000
treeherdermozilla-central@e0299ad29b85 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1058695
milestone40.0a1
backs outc839f283bf289e73bbfb66995b5e9f31ba48d204
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
Backed out changeset c839f283bf28 (bug 1058695) for bustage. CLOSED TREE
dom/base/nsGlobalWindow.cpp
dom/base/nsIGlobalObject.h
dom/promise/Promise.cpp
dom/promise/PromiseCallback.cpp
dom/promise/PromiseCallback.h
js/src/jsapi.cpp
js/src/jsapi.h
js/xpconnect/src/XPCJSRuntime.cpp
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -1434,18 +1434,16 @@ nsGlobalWindow::DropOuterWindowDocs()
 void
 nsGlobalWindow::CleanUp()
 {
   // Guarantee idempotence.
   if (mCleanedUp)
     return;
   mCleanedUp = true;
 
-  StartDying();
-
   mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nullptr);
   mEventTargetObjects.Clear();
 
   if (mObserver) {
     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     if (os) {
       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
       os->RemoveObserver(mObserver, "dom-storage2-changed");
--- a/dom/base/nsIGlobalObject.h
+++ b/dom/base/nsIGlobalObject.h
@@ -12,55 +12,21 @@
 #define NS_IGLOBALOBJECT_IID \
 { 0xe2538ded, 0x13ef, 0x4f4d, \
 { 0x94, 0x6b, 0x65, 0xd3, 0x33, 0xb4, 0xf0, 0x3c } }
 
 class nsIPrincipal;
 
 class nsIGlobalObject : public nsISupports
 {
-  bool mIsDying;
-
-protected:
-  nsIGlobalObject()
-   : mIsDying(false)
-  {}
-
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IGLOBALOBJECT_IID)
 
-  /**
-   * This check is added to deal with Promise microtask queues. On the main
-   * thread, we do not impose restrictions about when script stops running or
-   * when runnables can no longer be dispatched to the main thread. This means
-   * it is possible for a Promise chain to keep resolving an infinite chain of
-   * promises, preventing the browser from shutting down. See Bug 1058695. To
-   * prevent this, the nsGlobalWindow subclass sets this flag when it is
-   * closed. The Promise implementation checks this and prohibits new runnables
-   * from being dispatched.
-   *
-   * We pair this with checks during processing the promise microtask queue
-   * that pops up the slow script dialog when the Promise queue is preventing
-   * a window from going away.
-   */
-  bool
-  IsDying() const
-  {
-    return mIsDying;
-  }
-
   virtual JSObject* GetGlobalJSObject() = 0;
 
   // This method is not meant to be overridden.
   nsIPrincipal* PrincipalOrNull();
-
-protected:
-  void
-  StartDying()
-  {
-    mIsDying = true;
-  }
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIGlobalObject,
                               NS_IGLOBALOBJECT_IID)
 
 #endif // nsIGlobalObject_h__
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -258,17 +258,17 @@ protected:
 
         mPromise->RejectInternal(cx, exn);
       }
       // At least one of resolveFunc or rejectFunc have been called, so ignore
       // the exception. FIXME(nsm): This should be reported to the error
       // console though, for debugging.
     }
 
-    return rv.ErrorCode();
+    return NS_OK;
   }
 
 private:
   nsRefPtr<Promise> mPromise;
   JS::PersistentRooted<JSObject*> mThenable;
   nsRefPtr<PromiseInit> mThen;
   NS_DECL_OWNINGTHREAD;
 };
@@ -484,34 +484,23 @@ Promise::PerformMicroTaskCheckpoint()
   CycleCollectedJSRuntime* runtime = CycleCollectedJSRuntime::Get();
   nsTArray<nsCOMPtr<nsIRunnable>>& microtaskQueue =
     runtime->GetPromiseMicroTaskQueue();
 
   if (microtaskQueue.IsEmpty()) {
     return false;
   }
 
-  Maybe<AutoSafeJSContext> cx;
-  if (NS_IsMainThread()) {
-    cx.emplace();
-  }
-
   do {
     nsCOMPtr<nsIRunnable> runnable = microtaskQueue.ElementAt(0);
     MOZ_ASSERT(runnable);
 
     // This function can re-enter, so we remove the element before calling.
     microtaskQueue.RemoveElementAt(0);
-    nsresult rv = runnable->Run();
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return false;
-    }
-    if (cx.isSome()) {
-      JS_CheckForInterrupt(cx.ref());
-    }
+    runnable->Run();
   } while (!microtaskQueue.IsEmpty());
 
   return true;
 }
 
 /* static */ bool
 Promise::JSCallback(JSContext* aCx, unsigned aArgc, JS::Value* aVp)
 {
@@ -1077,20 +1066,16 @@ Promise::Compartment() const
 {
   return js::GetObjectCompartment(GlobalJSObject());
 }
 
 void
 Promise::AppendCallbacks(PromiseCallback* aResolveCallback,
                          PromiseCallback* aRejectCallback)
 {
-  if (mGlobal->IsDying()) {
-    return;
-  }
-
   MOZ_ASSERT(aResolveCallback);
   MOZ_ASSERT(aRejectCallback);
 
   if (mIsLastInChain && mState == PromiseState::Rejected) {
     // This rejection is now consumed.
     PromiseDebugging::AddConsumedRejection(*this);
     // Note that we may not have had the opportunity to call
     // RunResolveTask() yet, so we may never have called
@@ -1307,22 +1292,17 @@ Promise::RejectInternal(JSContext* aCx,
   mResolvePending = true;
 
   MaybeSettle(aValue, Rejected);
 }
 
 void
 Promise::Settle(JS::Handle<JS::Value> aValue, PromiseState aState)
 {
-  if (mGlobal->IsDying()) {
-    return;
-  }
-
   mSettlementTimestamp = TimeStamp::Now();
-
   SetResult(aValue);
   SetState(aState);
 
   AutoJSAPI jsapi;
   jsapi.Init();
   JSContext* cx = jsapi.cx();
   JS::RootedObject wrapper(cx, GetWrapper());
   MOZ_ASSERT(wrapper); // We preserved it
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -66,31 +66,30 @@ ResolvePromiseCallback::ResolvePromiseCa
   HoldJSObjects(this);
 }
 
 ResolvePromiseCallback::~ResolvePromiseCallback()
 {
   DropJSObjects(this);
 }
 
-nsresult
+void
 ResolvePromiseCallback::Call(JSContext* aCx,
                              JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
   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;
+    return;
   }
 
   mPromise->ResolveInternal(aCx, value);
-  return NS_OK;
 }
 
 // RejectPromiseCallback
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(RejectPromiseCallback)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(RejectPromiseCallback,
                                                 PromiseCallback)
@@ -125,32 +124,31 @@ RejectPromiseCallback::RejectPromiseCall
   HoldJSObjects(this);
 }
 
 RejectPromiseCallback::~RejectPromiseCallback()
 {
   DropJSObjects(this);
 }
 
-nsresult
+void
 RejectPromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
 {
   // Run resolver's algorithm with value and the synchronous flag set.
 
   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;
+    return;
   }
 
 
   mPromise->RejectInternal(aCx, value);
-  return NS_OK;
 }
 
 // WrapperPromiseCallback
 NS_IMPL_CYCLE_COLLECTION_CLASS(WrapperPromiseCallback)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(WrapperPromiseCallback,
                                                 PromiseCallback)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mNextPromise)
@@ -187,25 +185,25 @@ WrapperPromiseCallback::WrapperPromiseCa
   HoldJSObjects(this);
 }
 
 WrapperPromiseCallback::~WrapperPromiseCallback()
 {
   DropJSObjects(this);
 }
 
-nsresult
+void
 WrapperPromiseCallback::Call(JSContext* aCx,
                              JS::Handle<JS::Value> 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;
+    return;
   }
 
   ErrorResult rv;
 
   // PromiseReactionTask step 6
   JS::Rooted<JS::Value> retValue(aCx);
   mCallback->Call(value, &retValue, rv, "promise callback",
                   CallbackObject::eRethrowExceptions,
@@ -216,30 +214,30 @@ WrapperPromiseCallback::Call(JSContext* 
   // PromiseReactionTask step 7
   if (rv.Failed()) {
     JS::Rooted<JS::Value> value(aCx);
     if (rv.IsJSException()) {
       rv.StealJSException(aCx, &value);
 
       if (!JS_WrapValue(aCx, &value)) {
         NS_WARNING("Failed to wrap value into the right compartment.");
-        return NS_ERROR_FAILURE;
+        return;
       }
     } else {
       // 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.
       JSAutoCompartment ac(aCx, mNextPromise->GlobalJSObject());
       DebugOnly<bool> conversionResult = ToJSValue(aCx, rv, &value);
       MOZ_ASSERT(conversionResult);
     }
 
     mNextPromise->RejectInternal(aCx, value);
-    return NS_OK;
+    return;
   }
 
   // If the return value is the same as the promise itself, throw TypeError.
   if (retValue.isObject()) {
     JS::Rooted<JSObject*> valueObj(aCx, &retValue.toObject());
     Promise* returnedPromise;
     nsresult r = UNWRAP_OBJECT(Promise, valueObj, returnedPromise);
 
@@ -267,49 +265,48 @@ WrapperPromiseCallback::Call(JSContext* 
         }
       }
 
       // 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;
+        return;
       }
 
       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;
+        return;
       }
 
       JS::Rooted<JS::Value> typeError(aCx);
       if (!JS::CreateError(aCx, JSEXN_TYPEERR, JS::NullPtr(), fn, lineNumber, 0,
                            nullptr, message, &typeError)) {
         // Out of memory. Promise will stay unresolved.
         JS_ClearPendingException(aCx);
-        return NS_ERROR_OUT_OF_MEMORY;
+        return;
       }
 
       mNextPromise->RejectInternal(aCx, typeError);
-      return NS_OK;
+      return;
     }
   }
 
   // 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;
+    return;
   }
 
   mNextPromise->ResolveInternal(aCx, retValue);
-  return NS_OK;
 }
 
 // NativePromiseCallback
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(NativePromiseCallback,
                                    PromiseCallback, mHandler)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(NativePromiseCallback)
@@ -325,32 +322,31 @@ NativePromiseCallback::NativePromiseCall
 {
   MOZ_ASSERT(aHandler);
 }
 
 NativePromiseCallback::~NativePromiseCallback()
 {
 }
 
-nsresult
+void
 NativePromiseCallback::Call(JSContext* aCx,
                             JS::Handle<JS::Value> aValue)
 {
   if (mState == Promise::Resolved) {
     mHandler->ResolvedCallback(aCx, aValue);
-    return NS_OK;
+    return;
   }
 
   if (mState == Promise::Rejected) {
     mHandler->RejectedCallback(aCx, aValue);
-    return NS_OK;
+    return;
   }
 
   NS_NOTREACHED("huh?");
-  return NS_ERROR_FAILURE;
 }
 
 /* static */ PromiseCallback*
 PromiseCallback::Factory(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
                          AnyCallback* aCallback, Task aTask)
 {
   MOZ_ASSERT(aNextPromise);
 
--- a/dom/promise/PromiseCallback.h
+++ b/dom/promise/PromiseCallback.h
@@ -21,18 +21,18 @@ 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;
+  virtual void 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
@@ -49,18 +49,18 @@ public:
 // aNextPromise->RejectFunction() if the JS Callback throws.
 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;
+  void Call(JSContext* aCx,
+            JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return mNextPromise;
   }
 
   WrapperPromiseCallback(Promise* aNextPromise, JS::Handle<JSObject*> aGlobal,
                          AnyCallback* aCallback);
@@ -77,18 +77,18 @@ private:
 // 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;
+  void Call(JSContext* aCx,
+            JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return mPromise;
   }
 
   ResolvePromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
 
@@ -103,18 +103,18 @@ private:
 // 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;
+  void Call(JSContext* aCx,
+            JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return mPromise;
   }
 
   RejectPromiseCallback(Promise* aPromise, JS::Handle<JSObject*> aGlobal);
 
@@ -128,18 +128,18 @@ private:
 // 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;
+  void Call(JSContext* aCx,
+            JS::Handle<JS::Value> aValue) override;
 
   Promise* GetDependentPromise() override
   {
     return nullptr;
   }
 
   NativePromiseCallback(PromiseNativeHandler* aHandler,
                         Promise::PromiseState aState);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4457,22 +4457,16 @@ JS_New(JSContext* cx, HandleObject ctor,
     RootedObject obj(cx);
     {
         AutoLastFrameCheck lfc(cx);
         obj = JS_NewHelper(cx, ctor, inputArgs);
     }
     return obj;
 }
 
-JS_PUBLIC_API(bool)
-JS_CheckForInterrupt(JSContext* cx)
-{
-    return js::CheckForInterrupt(cx);
-}
-
 JS_PUBLIC_API(JSInterruptCallback)
 JS_SetInterruptCallback(JSRuntime* rt, JSInterruptCallback callback)
 {
     JSInterruptCallback old = rt->interruptCallback;
     rt->interruptCallback = callback;
     return old;
 }
 
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3943,21 +3943,19 @@ Call(JSContext* cx, JS::HandleValue this
     JS::RootedValue fun(cx, JS::ObjectValue(*funObj));
     return Call(cx, thisv, fun, args, rval);
 }
 
 extern JS_PUBLIC_API(bool)
 Construct(JSContext* cx, JS::HandleValue fun,
           const JS::HandleValueArray& args,
           MutableHandleValue rval);
+
 } /* namespace JS */
 
-extern JS_PUBLIC_API(bool)
-JS_CheckForInterrupt(JSContext* cx);
-
 /*
  * These functions allow setting an interrupt callback that will be called
  * from the JS thread some time after any thread triggered the callback using
  * JS_RequestInterruptCallback(rt).
  *
  * To schedule the GC and for other activities the engine internally triggers
  * interrupt callbacks. The embedding should thus not rely on callbacks being
  * triggered through the external API only.
--- a/js/xpconnect/src/XPCJSRuntime.cpp
+++ b/js/xpconnect/src/XPCJSRuntime.cpp
@@ -1456,23 +1456,18 @@ XPCJSRuntime::InterruptCallback(JSContex
         if (!JS_GetPrototype(cx, global, &proto))
             return false;
         if (proto && IsSandboxPrototypeProxy(proto) &&
             (proto = js::CheckedUnwrap(proto, /* stopAtOuter = */ false)))
         {
             win = WindowGlobalOrNull(proto);
         }
     }
-
-    if (!win) {
-        NS_WARNING("No active window");
+    if (!win)
         return true;
-    }
-
-    MOZ_ASSERT(!win->IsDying());
 
     if (win->GetIsPrerendered()) {
         // We cannot display a dialog if the page is being prerendered, so
         // just kill the page.
         mozilla::dom::HandlePrerenderingViolation(win);
         return false;
     }