Backed out changesets fa9fe193778f and 3eaf867930dd (bug 1148593) for test_async_setTimeout_stack.html and test_async_setTimeout_stack_across_globals.html failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 17 Jul 2015 12:37:24 -0400
changeset 253515 7d05fa306c73ede66e055d629f0ec166f03e1cfc
parent 253514 498153aa50a7c5473d784b244fc9018f34c612b2
child 253516 5ba62c1cf6056016486208358d9dbb8a16d41d01
push id29067
push userkwierso@gmail.com
push dateSat, 18 Jul 2015 00:57:04 +0000
treeherdermozilla-central@e2f2eb9ecca0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1148593
milestone42.0a1
backs outfa9fe193778fd56ae95d88484814541989b16f9e
3eaf867930dd72d65eb4d1beebe0c1b38a401063
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 changesets fa9fe193778f and 3eaf867930dd (bug 1148593) for test_async_setTimeout_stack.html and test_async_setTimeout_stack_across_globals.html failures.
browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js
browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js
docshell/test/browser/browser_timelineMarkers-frame-05.js
dom/base/nsGlobalWindow.cpp
dom/base/test/mochitest.ini
dom/base/test/test_async_setTimeout_stack.html
dom/base/test/test_async_setTimeout_stack_across_globals.html
dom/bindings/CallbackFunction.h
dom/bindings/CallbackInterface.h
dom/bindings/CallbackObject.cpp
dom/bindings/CallbackObject.h
dom/bindings/Codegen.py
dom/bindings/test/mochitest.ini
dom/bindings/test/test_async_stacks.html
dom/bindings/test/test_exception_options_from_jsimplemented.html
dom/bindings/test/test_promise_rejections_from_jsimplemented.html
dom/events/DOMEventTargetHelper.cpp
dom/events/EventListenerManager.cpp
dom/promise/Promise.cpp
dom/xbl/nsXBLPrototypeHandler.cpp
js/src/builtin/TestingFunctions.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/vm/Runtime.cpp
js/src/vm/Runtime.h
js/src/vm/SavedStacks.cpp
js/src/vm/Stack-inl.h
js/src/vm/Stack.h
js/xpconnect/src/XPCComponents.cpp
toolkit/modules/Promise-backend.js
--- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-01.js
@@ -23,20 +23,18 @@ function* ifTestingSupported() {
     "There should be no stack container available yet for the draw call.");
 
   let callStackDisplayed = once(window, EVENTS.CALL_STACK_DISPLAYED);
   EventUtils.sendMouseEvent({ type: "mousedown" }, locationLink, window);
   yield callStackDisplayed;
 
   isnot($(".call-item-stack", callItem.target), null,
     "There should be a stack container available now for the draw call.");
-  // We may have more than 4 functions, depending on whether async
-  // stacks are available.
-  ok($all(".call-item-stack-fn", callItem.target).length >= 4,
-     "There should be at least 4 functions on the stack for the draw call.");
+  is($all(".call-item-stack-fn", callItem.target).length, 4,
+    "There should be 4 functions on the stack for the draw call.");
 
   ok($all(".call-item-stack-fn-name", callItem.target)[0].getAttribute("value")
     .includes("C()"),
     "The first function on the stack has the correct name.");
   ok($all(".call-item-stack-fn-name", callItem.target)[1].getAttribute("value")
     .includes("B()"),
     "The second function on the stack has the correct name.");
   ok($all(".call-item-stack-fn-name", callItem.target)[2].getAttribute("value")
--- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-02.js
@@ -24,20 +24,18 @@ function* ifTestingSupported() {
     "There should be no stack container available yet for the draw call.");
 
   let callStackDisplayed = once(window, EVENTS.CALL_STACK_DISPLAYED);
   EventUtils.sendMouseEvent({ type: "mousedown" }, locationLink, window);
   yield callStackDisplayed;
 
   isnot($(".call-item-stack", callItem.target), null,
     "There should be a stack container available now for the draw call.");
-  // We may have more than 4 functions, depending on whether async
-  // stacks are available.
-  ok($all(".call-item-stack-fn", callItem.target).length >= 4,
-     "There should be at least 4 functions on the stack for the draw call.");
+  is($all(".call-item-stack-fn", callItem.target).length, 4,
+    "There should be 4 functions on the stack for the draw call.");
 
   let jumpedToSource = once(window, EVENTS.SOURCE_SHOWN_IN_JS_DEBUGGER);
   EventUtils.sendMouseEvent({ type: "mousedown" }, $(".call-item-location", callItem.target));
   yield jumpedToSource;
 
   let toolbox = yield gDevTools.getToolbox(target);
   let { panelWin: { DebuggerView: view } } = toolbox.getPanel("jsdebugger");
 
--- a/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js
+++ b/browser/devtools/canvasdebugger/test/browser_canvas-frontend-call-stack-03.js
@@ -35,31 +35,27 @@ function* ifTestingSupported() {
   is(view.hasAttribute("call-stack-populated"), true,
     "The call item's view should have the stack populated now.");
   is(view.getAttribute("call-stack-expanded"), "true",
     "The call item's view should have the stack expanded now.");
   isnot($(".call-item-stack", callItem.target), null,
     "There should be a stack container available now for the draw call.");
   is($(".call-item-stack", callItem.target).hidden, false,
     "The stack container should now be visible.");
-  // We may have more than 4 functions, depending on whether async
-  // stacks are available.
-  ok($all(".call-item-stack-fn", callItem.target).length >= 4,
-     "There should be at least 4 functions on the stack for the draw call.");
+  is($all(".call-item-stack-fn", callItem.target).length, 4,
+    "There should be 4 functions on the stack for the draw call.");
 
   EventUtils.sendMouseEvent({ type: "dblclick" }, contents, window);
 
   is(view.hasAttribute("call-stack-populated"), true,
     "The call item's view should still have the stack populated.");
   is(view.getAttribute("call-stack-expanded"), "false",
     "The call item's view should not have the stack expanded anymore.");
   isnot($(".call-item-stack", callItem.target), null,
     "There should still be a stack container available for the draw call.");
   is($(".call-item-stack", callItem.target).hidden, true,
     "The stack container should now be hidden.");
-  // We may have more than 4 functions, depending on whether async
-  // stacks are available.
-  ok($all(".call-item-stack-fn", callItem.target).length >= 4,
-     "There should still be at least 4 functions on the stack for the draw call.");
+  is($all(".call-item-stack-fn", callItem.target).length, 4,
+    "There should still be 4 functions on the stack for the draw call.");
 
   yield teardown(panel);
   finish();
 }
--- a/docshell/test/browser/browser_timelineMarkers-frame-05.js
+++ b/docshell/test/browser/browser_timelineMarkers-frame-05.js
@@ -89,17 +89,17 @@ if (Services.prefs.getBoolPref("javascri
       resolvePromise(resolver);
     },
     check: function(markers) {
       markers = markers.filter(m => m.name == "ConsoleTime");
       ok(markers.length > 0, "Promise marker includes stack");
 
       let frame = markers[0].endStack;
       ok(frame.parent.asyncParent !== null, "Parent frame has async parent");
-      is(frame.parent.asyncParent.asyncCause, "promise callback",
+      is(frame.parent.asyncParent.asyncCause, "Promise",
          "Async parent has correct cause");
       is(frame.parent.asyncParent.functionDisplayName, "makePromise",
          "Async parent has correct function name");
     }
   });
 }
 
 timelineContentTest(TESTS);
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -5550,17 +5550,17 @@ nsGlobalWindow::RequestAnimationFrame(JS
 {
   FORWARD_TO_INNER(RequestAnimationFrame, (aCallback, cx, aHandle), NS_ERROR_UNEXPECTED);
   if (!aCallback.isObject() || !JS::IsCallable(&aCallback.toObject())) {
     return NS_ERROR_INVALID_ARG;
   }
 
   JS::Rooted<JSObject*> callbackObj(cx, &aCallback.toObject());
   nsRefPtr<FrameRequestCallback> callback =
-    new FrameRequestCallback(cx, callbackObj, GetIncumbentGlobal());
+    new FrameRequestCallback(callbackObj, GetIncumbentGlobal());
 
   ErrorResult rv;
   *aHandle = RequestAnimationFrame(*callback, rv);
 
   return rv.StealNSResult();
 }
 
 NS_IMETHODIMP
--- a/dom/base/test/mochitest.ini
+++ b/dom/base/test/mochitest.ini
@@ -241,18 +241,16 @@ support-files =
   file_webaudioLoop.html
   file_webaudioLoop2.html
 
 [test_anonymousContent_api.html]
 [test_anonymousContent_append_after_reflow.html]
 [test_anonymousContent_insert.html]
 [test_anonymousContent_manipulate_content.html]
 [test_appname_override.html]
-[test_async_setTimeout_stack.html]
-[test_async_setTimeout_stack_across_globals.html]
 [test_audioWindowUtils.html]
 [test_audioNotification.html]
 skip-if = buildapp == 'mulet'
 [test_audioNotificationStopOnNavigation.html]
 skip-if = buildapp == 'mulet'
 [test_bug1091883.html]
 [test_bug116083.html]
 [test_bug793311.html]
deleted file mode 100644
--- a/dom/base/test/test_async_setTimeout_stack.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1142577
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1142577 - Async stacks for setTimeout</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1142577">Mozilla Bug 1142577</a>
-  <pre id="stack"></pre>
-  <script type="application/javascript">
-  SimpleTest.waitForExplicitFinish();
-  SimpleTest.requestFlakyTimeout("Testing async stacks across setTimeout");
-
-  function getFunctionName(frame) {
-    return frame.slice(0, frame.indexOf("@"));
-  }
-
-  function a() { b() }
-  function b() { c() }
-  function c() { setTimeout(d, 1) }
-  function d() { e() }
-  function e() { f() }
-  function f() { setTimeout(g, 1) }
-  function g() { h() }
-  function h() { i() }
-  function i() {
-    var stackString = Error().stack;
-    document.getElementById("stack").textContent = stackString;
-
-    var frames = stackString
-            .split("\n")
-            .map(getFunctionName)
-            .filter(function (name) { return !!name; });
-
-    is(frames[0], "i");
-    is(frames[1], "h");
-    is(frames[2], "g");
-    is(frames[3], "setTimeout handler*SimpleTest_setTimeoutShim");
-    is(frames[4], "f");
-    is(frames[5], "e");
-    is(frames[6], "d");
-    is(frames[7], "setTimeout handler*SimpleTest_setTimeoutShim");
-    is(frames[8], "c");
-    is(frames[9], "b");
-    is(frames[10], "a");
-    // One extra frame due to pushPrefEnv.
-    is(frames.length, 12);
-
-    SimpleTest.finish();
-  }
-
-  SpecialPowers.pushPrefEnv(
-    {"set": [['javascript.options.asyncstack', true]]},
-    a);
-  </script>
-</body>
-</html>
deleted file mode 100644
--- a/dom/base/test/test_async_setTimeout_stack_across_globals.html
+++ /dev/null
@@ -1,62 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1142577
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1142577 - Async stacks for setTimeout</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-</head>
-<body>
-  <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1142577">Mozilla Bug 1142577</a>
-  <pre id="stack"></pre>
-  <iframe id="iframe"></iframe>
-  <script type="application/javascript">
-  SimpleTest.waitForExplicitFinish();
-
-  var otherGlobal = document.getElementById("iframe").contentWindow;
-
-  function getFunctionName(frame) {
-    return frame.slice(0, frame.indexOf("@"));
-  }
-
-  function a() { b() }
-  function b() { c() }
-  function c() { otherGlobal.setTimeout(d, 1) }
-  function d() { e() }
-  function e() { f() }
-  function f() { otherGlobal.setTimeout(g, 1) }
-  function g() { h() }
-  function h() { i() }
-  function i() {
-    var stackString = Error().stack;
-    document.getElementById("stack").textContent = stackString;
-
-    var frames = stackString
-            .split("\n")
-            .map(getFunctionName)
-            .filter(function (name) { return !!name; });
-
-    is(frames[0], "i");
-    is(frames[1], "h");
-    is(frames[2], "g");
-    is(frames[3], "setTimeout handler*f");
-    is(frames[4], "e");
-    is(frames[5], "d");
-    is(frames[6], "setTimeout handler*c");
-    is(frames[7], "b");
-    is(frames[8], "a");
-    // One extra frame due to pushPrefEnv.
-    is(frames.length, 10);
-
-    SimpleTest.finish();
-  }
-
-  SpecialPowers.pushPrefEnv(
-    {"set": [['javascript.options.asyncstack', true]]},
-    a);
-  </script>
-</body>
-</html>
--- a/dom/bindings/CallbackFunction.h
+++ b/dom/bindings/CallbackFunction.h
@@ -20,20 +20,19 @@
 #include "mozilla/dom/CallbackObject.h"
 
 namespace mozilla {
 namespace dom {
 
 class CallbackFunction : public CallbackObject
 {
 public:
-  // See CallbackObject for an explanation of the arguments.
-  explicit CallbackFunction(JSContext* aCx, JS::Handle<JSObject*> aCallable,
+  explicit CallbackFunction(JS::Handle<JSObject*> aCallable,
                             nsIGlobalObject* aIncumbentGlobal)
-    : CallbackObject(aCx, aCallable, aIncumbentGlobal)
+    : CallbackObject(aCallable, aIncumbentGlobal)
   {
   }
 
   JS::Handle<JSObject*> Callable() const
   {
     return Callback();
   }
 
--- a/dom/bindings/CallbackInterface.h
+++ b/dom/bindings/CallbackInterface.h
@@ -19,20 +19,19 @@
 #include "mozilla/dom/CallbackObject.h"
 
 namespace mozilla {
 namespace dom {
 
 class CallbackInterface : public CallbackObject
 {
 public:
-  // See CallbackObject for an explanation of the arguments.
-  explicit CallbackInterface(JSContext* aCx, JS::Handle<JSObject*> aCallback,
+  explicit CallbackInterface(JS::Handle<JSObject*> aCallback,
                              nsIGlobalObject *aIncumbentGlobal)
-    : CallbackObject(aCx, aCallback, aIncumbentGlobal)
+    : CallbackObject(aCallback, aIncumbentGlobal)
   {
   }
 
 protected:
   bool GetCallableProperty(JSContext* cx, JS::Handle<jsid> aPropId,
                            JS::MutableHandle<JS::Value> aCallable);
 
 };
--- a/dom/bindings/CallbackObject.cpp
+++ b/dom/bindings/CallbackObject.cpp
@@ -38,17 +38,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(Ca
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mIncumbentGlobal)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIncumbentGlobal)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
-  NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCreationStack)
   NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mIncumbentJSGlobal)
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
 CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
                                      ErrorResult& aRv,
                                      const char* aExecutionReason,
                                      ExceptionHandling aExceptionHandling,
                                      JSCompartment* aCompartment,
@@ -165,26 +164,16 @@ CallbackObject::CallSetup::CallSetup(Cal
     bool allowed = nsContentUtils::GetSecurityManager()->
       ScriptAllowed(js::GetGlobalForObjectCrossCompartment(realCallback));
 
     if (!allowed) {
       return;
     }
   }
 
-  mAsyncStack.emplace(cx, aCallback->GetCreationStack());
-  if (*mAsyncStack) {
-    mAsyncCause.emplace(cx, JS_NewStringCopyZ(cx, aExecutionReason));
-    if (*mAsyncCause) {
-      mAsyncStackSetter.emplace(cx, *mAsyncStack, *mAsyncCause);
-    } else {
-      JS_ClearPendingException(cx);
-    }
-  }
-
   // Enter the compartment of our callback, so we can actually work with it.
   //
   // Note that if the callback is a wrapper, this will not be the same
   // compartment that we ended up in with mAutoEntryScript above, because the
   // entry point is based off of the unwrapped callback (realCallback).
   mAc.emplace(cx, *mRootedCallable);
 
   // And now we're ready to go.
--- a/dom/bindings/CallbackObject.h
+++ b/dom/bindings/CallbackObject.h
@@ -25,17 +25,16 @@
 #include "mozilla/ErrorResult.h"
 #include "mozilla/HoldDropJSObjects.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/dom/ScriptSettings.h"
 #include "nsContentUtils.h"
 #include "nsWrapperCache.h"
 #include "nsJSEnvironment.h"
 #include "xpcpublic.h"
-#include "jsapi.h"
 
 namespace mozilla {
 namespace dom {
 
 #define DOM_CALLBACKOBJECT_IID \
 { 0xbe74c190, 0x6d76, 0x4991, \
  { 0x84, 0xb9, 0x65, 0x06, 0x99, 0xe6, 0x93, 0x2b } }
 
@@ -45,49 +44,28 @@ public:
   NS_DECLARE_STATIC_IID_ACCESSOR(DOM_CALLBACKOBJECT_IID)
 
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(CallbackObject)
 
   // The caller may pass a global object which will act as an override for the
   // incumbent script settings object when the callback is invoked (overriding
   // the entry point computed from aCallback). If no override is required, the
-  // caller should pass null.  |aCx| is used to capture the current
-  // stack, which is later used as an async parent when the callback
-  // is invoked.  aCx can be nullptr, in which case no stack is
-  // captured.
-  explicit CallbackObject(JSContext* aCx, JS::Handle<JSObject*> aCallback,
-                          nsIGlobalObject *aIncumbentGlobal)
+  // caller should pass null.
+  explicit CallbackObject(JS::Handle<JSObject*> aCallback, nsIGlobalObject *aIncumbentGlobal)
   {
-    if (aCx && JS::RuntimeOptionsRef(aCx).asyncStack()) {
-      JS::RootedObject stack(aCx);
-      if (!JS::CaptureCurrentStack(aCx, &stack)) {
-        JS_ClearPendingException(aCx);
-      }
-      Init(aCallback, stack, aIncumbentGlobal);
-    } else {
-      Init(aCallback, nullptr, aIncumbentGlobal);
-    }
+    Init(aCallback, aIncumbentGlobal);
   }
 
   JS::Handle<JSObject*> Callback() const
   {
     JS::ExposeObjectToActiveJS(mCallback);
     return CallbackPreserveColor();
   }
 
-  JSObject* GetCreationStack() const
-  {
-    JSObject* result = mCreationStack;
-    if (result) {
-      JS::ExposeObjectToActiveJS(result);
-    }
-    return result;
-  }
-
   /*
    * This getter does not change the color of the JSObject meaning that the
    * object returned is not guaranteed to be kept alive past the next CC.
    *
    * This should only be called if you are certain that the return value won't
    * be passed into a JS API function and that it won't be stored without being
    * rooted (or otherwise signaling the stored value to the CC).
    */
@@ -125,62 +103,57 @@ public:
 protected:
   virtual ~CallbackObject()
   {
     DropJSObjects();
   }
 
   explicit CallbackObject(CallbackObject* aCallbackObject)
   {
-    Init(aCallbackObject->mCallback, aCallbackObject->mCreationStack,
-         aCallbackObject->mIncumbentGlobal);
+    Init(aCallbackObject->mCallback, aCallbackObject->mIncumbentGlobal);
   }
 
   bool operator==(const CallbackObject& aOther) const
   {
     JSObject* thisObj =
       js::UncheckedUnwrap(CallbackPreserveColor());
     JSObject* otherObj =
       js::UncheckedUnwrap(aOther.CallbackPreserveColor());
     return thisObj == otherObj;
   }
 
 private:
-  inline void Init(JSObject* aCallback, JSObject* aCreationStack,
-                   nsIGlobalObject* aIncumbentGlobal)
+  inline void Init(JSObject* aCallback, nsIGlobalObject* aIncumbentGlobal)
   {
     MOZ_ASSERT(aCallback && !mCallback);
     // Set script objects before we hold, on the off chance that a GC could
     // somehow happen in there... (which would be pretty odd, granted).
     mCallback = aCallback;
-    mCreationStack = aCreationStack;
     if (aIncumbentGlobal) {
       mIncumbentGlobal = aIncumbentGlobal;
       mIncumbentJSGlobal = aIncumbentGlobal->GetGlobalJSObject();
     }
     mozilla::HoldJSObjects(this);
   }
 
   CallbackObject(const CallbackObject&) = delete;
   CallbackObject& operator =(const CallbackObject&) = delete;
 
 protected:
   void DropJSObjects()
   {
     MOZ_ASSERT_IF(mIncumbentJSGlobal, mCallback);
     if (mCallback) {
       mCallback = nullptr;
-      mCreationStack = nullptr;
       mIncumbentJSGlobal = nullptr;
       mozilla::DropJSObjects(this);
     }
   }
 
   JS::Heap<JSObject*> mCallback;
-  JS::Heap<JSObject*> mCreationStack;
   // Ideally, we'd just hold a reference to the nsIGlobalObject, since that's
   // what we need to pass to AutoIncumbentScript. Unfortunately, that doesn't
   // hold the actual JS global alive. So we maintain an additional pointer to
   // the JS global itself so that we can trace it.
   //
   // At some point we should consider trying to make native globals hold their
   // scripted global alive, at which point we can get rid of the duplication
   // here.
@@ -231,21 +204,16 @@ protected:
     // And now members whose construction/destruction order we need to control.
     Maybe<AutoEntryScript> mAutoEntryScript;
     Maybe<AutoIncumbentScript> mAutoIncumbentScript;
 
     // Constructed the rooter within the scope of mCxPusher above, so that it's
     // always within a request during its lifetime.
     Maybe<JS::Rooted<JSObject*> > mRootedCallable;
 
-    // Members which are used to set the async stack.
-    Maybe<JS::Rooted<JSObject*>> mAsyncStack;
-    Maybe<JS::Rooted<JSString*>> mAsyncCause;
-    Maybe<JS::AutoSetAsyncStackForNewCalls> mAsyncStackSetter;
-
     // Can't construct a JSAutoCompartment without a JSContext either.  Also,
     // Put mAc after mAutoEntryScript so that we exit the compartment before
     // we pop the JSContext. Though in practice we'll often manually order
     // those two things.
     Maybe<JSAutoCompartment> mAc;
 
     // An ErrorResult to possibly re-throw exceptions on and whether
     // we should re-throw them.
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3971,17 +3971,17 @@ class FailureFatalCastableObjectUnwrappe
             isCallbackReturnValue)
 
 
 class CGCallbackTempRoot(CGGeneric):
     def __init__(self, name):
         define = dedent("""
             { // Scope for tempRoot
               JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());
-              ${declName} = new %s(cx, tempRoot, mozilla::dom::GetIncumbentGlobal());
+              ${declName} = new %s(tempRoot, mozilla::dom::GetIncumbentGlobal());
             }
             """) % name
         CGGeneric.__init__(self, define=define)
 
 
 class JSToNativeConversionInfo():
     """
     An object representing information about a JS-to-native conversion.
@@ -13903,17 +13903,17 @@ class CGJSImplClass(CGBindingImplClass):
             decorators = ""
             # We need a protected virtual destructor our subclasses can use
             destructor = ClassDestructor(virtual=True, visibility="protected")
         else:
             decorators = "final"
             destructor = ClassDestructor(virtual=False, visibility="private")
 
         baseConstructors = [
-            ("mImpl(new %s(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr))" %
+            ("mImpl(new %s(aJSImplObject, /* aIncumbentGlobal = */ nullptr))" %
              jsImplName(descriptor.name)),
             "mParent(aParent)"]
         parentInterface = descriptor.interface.parent
         while parentInterface:
             if parentInterface.isJSImplemented():
                 baseConstructors.insert(
                     0, "%s(aJSImplObject, aParent)" % parentClass)
                 break
@@ -14048,24 +14048,23 @@ class CGCallback(CGClass):
         if (not self.idlObject.isInterface() and
             not self.idlObject._treatNonObjectAsNull):
             body = "MOZ_ASSERT(JS::IsCallable(mCallback));\n"
         else:
             # Not much we can assert about it, other than not being null, and
             # CallbackObject does that already.
             body = ""
         return [ClassConstructor(
-            [Argument("JSContext*", "aCx"),
-             Argument("JS::Handle<JSObject*>", "aCallback"),
+            [Argument("JS::Handle<JSObject*>", "aCallback"),
              Argument("nsIGlobalObject*", "aIncumbentGlobal")],
             bodyInHeader=True,
             visibility="public",
             explicit=True,
             baseConstructors=[
-                "%s(aCx, aCallback, aIncumbentGlobal)" % self.baseName,
+                "%s(aCallback, aIncumbentGlobal)" % self.baseName,
             ],
             body=body)]
 
     def getMethodImpls(self, method):
         assert method.needThisHandling
         args = list(method.args)
         # Strip out the JSContext*/JSObject* args
         # that got added.
--- a/dom/bindings/test/mochitest.ini
+++ b/dom/bindings/test/mochitest.ini
@@ -3,17 +3,16 @@ support-files =
   file_InstanceOf.html
   file_bug707564.html
   file_bug775543.html
   file_document_location_set_via_xray.html
   file_dom_xrays.html
   file_proxies_via_xray.html
   forOf_iframe.html
 
-[test_async_stacks.html]
 [test_ByteString.html]
 [test_InstanceOf.html]
 [test_bug560072.html]
 [test_bug707564.html]
 [test_bug742191.html]
 [test_bug759621.html]
 [test_bug773326.html]
 [test_bug788369.html]
deleted file mode 100644
--- a/dom/bindings/test/test_async_stacks.html
+++ /dev/null
@@ -1,108 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1148593
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1148593</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script type="application/javascript">
-
-  /** Test for Bug 1148593 **/
-
-  SimpleTest.waitForExplicitFinish();
-
-  var TESTS;
-
-  function nextTest() {
-    var t = TESTS.pop();
-    if (t) {
-      t();
-    } else {
-      SimpleTest.finish();
-    }
-  }
-
-  function checkStack(functionName) {
-    try {
-      noSuchFunction();
-    } catch (e) {
-      ok(e.stack.indexOf(functionName) >= 0, "stack includes " + functionName);
-    }
-    nextTest();
-  }
-
-  function eventListener() {
-    checkStack("registerEventListener");
-  }
-  function registerEventListener(link) {
-    link.onload = eventListener;
-  }
-  function eventTest() {
-    var link = document.createElement("link");
-    link.rel = "stylesheet";
-    link.href = "data:text/css,";
-    registerEventListener(link);
-    document.body.appendChild(link);
-  }
-
-  function xhrListener() {
-    checkStack("xhrTest");
-  }
-  function xhrTest() {
-    var ourFile = location.href;
-    var x = new XMLHttpRequest();
-    x.onload = xhrListener;
-    x.open("get", ourFile, true);
-    x.send();
-  }
-
-  function rafListener() {
-    checkStack("rafTest");
-  }
-  function rafTest() {
-    requestAnimationFrame(rafListener);
-  }
-
-  var intervalId;
-  function intervalHandler() {
-    clearInterval(intervalId);
-    checkStack("intervalTest");
-  }
-  function intervalTest() {
-    intervalId = setInterval(intervalHandler, 5);
-  }
-
-  function postMessageHandler(ev) {
-    ev.stopPropagation();
-    checkStack("postMessageTest");
-  }
-  function postMessageTest() {
-    window.addEventListener("message", postMessageHandler, true);
-    window.postMessage("whatever", "*");
-  }
-
-  function runTests() {
-    TESTS = [postMessageTest, intervalTest, rafTest, xhrTest, eventTest];
-    nextTest();
-  }
-
-  addLoadEvent(function() {
-    SpecialPowers.pushPrefEnv(
-      {"set": [['javascript.options.asyncstack', true]]},
-      runTests);
-  });
-  </script>
-</head>
-<body>
-<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1148593">Mozilla Bug 1148593</a>
-<p id="display"></p>
-<div id="content" style="display: none">
-
-</div>
-<pre id="test">
-</pre>
-</body>
-</html>
--- a/dom/bindings/test/test_exception_options_from_jsimplemented.html
+++ b/dom/bindings/test/test_exception_options_from_jsimplemented.html
@@ -10,127 +10,127 @@ https://bugzilla.mozilla.org/show_bug.cg
   <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
   <script type="application/javascript">
 
   /** Test for Bug 1107592 **/
 
   SimpleTest.waitForExplicitFinish();
 
   function doTest() {
-    var file = location.href;
-
     var t = new TestInterfaceJS();
     try {
       t.testThrowError();
     } catch (e) {
       ok(e instanceof Error, "Should have an Error here");
       ok(!(e instanceof DOMException), "Should not have DOMException here");
       ok(!("code" in e), "Should not have a 'code' property");
       is(e.name, "Error", "Should not have an interesting name here");
       is(e.message, "We are an Error", "Should have the right message");
       is(e.stack,
-         `doTest@${file}:22:7\nAsync*@${file}:137:1\n`,
+         "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:20:7\n",
          "Exception stack should still only show our code");
       is(e.fileName,
-         file,
+         "http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
          "Should have the right file name");
-      is(e.lineNumber, 22, "Should have the right line number");
+      is(e.lineNumber, 20, "Should have the right line number");
       is(e.columnNumber, 7, "Should have the right column number");
     }
 
     try {
       t.testThrowDOMException();
     } catch (e) {
       ok(e instanceof Error, "Should also have an Error here");
       ok(e instanceof DOMException, "Should have DOMException here");
       is(e.name, "NotSupportedError", "Should have the right name here");
       is(e.message, "We are a DOMException",
          "Should also have the right message");
       is(e.code, DOMException.NOT_SUPPORTED_ERR,
          "Should have the right 'code'");
       is(e.stack,
-         `doTest@${file}:40:7\nAsync*@${file}:137:1\n`,
+         "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:38:7\n",
          "Exception stack should still only show our code");
       is(e.filename,
-         file,
+         "http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
          "Should still have the right file name");
-      is(e.lineNumber, 40, "Should still have the right line number");
+      is(e.lineNumber, 38, "Should still have the right line number");
       todo_isnot(e.columnNumber, 0,
                  "No column number support for DOMException yet");
     }
 
     try {
       t.testThrowTypeError();
     } catch (e) {
       ok(e instanceof TypeError, "Should have a TypeError here");
       ok(!(e instanceof DOMException), "Should not have DOMException here (2)");
       ok(!("code" in e), "Should not have a 'code' property (2)");
       is(e.name, "TypeError", "Should be named TypeError");
       is(e.message, "We are a TypeError",
          "Should also have the right message (2)");
       is(e.stack,
-         `doTest@${file}:61:7\nAsync*@${file}:137:1\n`,
+         "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:59:7\n",
          "Exception stack for TypeError should only show our code");
       is(e.fileName,
-         file,
+         "http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
          "Should still have the right file name for TypeError");
-      is(e.lineNumber, 61, "Should still have the right line number for TypeError");
+      is(e.lineNumber, 59, "Should still have the right line number for TypeError");
       is(e.columnNumber, 7, "Should have the right column number for TypeError");
     }
 
     try {
       t.testThrowCallbackError(function() { Array.indexOf() });
     } catch (e) {
       ok(e instanceof TypeError, "Should have a TypeError here (3)");
       ok(!(e instanceof DOMException), "Should not have DOMException here (3)");
       ok(!("code" in e), "Should not have a 'code' property (3)");
       is(e.name, "TypeError", "Should be named TypeError (3)");
       is(e.message, "missing argument 0 when calling function Array.indexOf",
          "Should also have the right message (3)");
       is(e.stack,
-         `doTest/<@${file}:80:45\ndoTest@${file}:80:7\nAsync*@${file}:137:1\n`,
+         "doTest/<@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:78:45\n" +
+         "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:78:7\n"
+  ,
          "Exception stack for TypeError should only show our code (3)");
       is(e.fileName,
-         file,
+         "http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
          "Should still have the right file name for TypeError (3)");
-      is(e.lineNumber, 80, "Should still have the right line number for TypeError (3)");
+      is(e.lineNumber, 78, "Should still have the right line number for TypeError (3)");
       is(e.columnNumber, 45, "Should have the right column number for TypeError (3)");
     }
 
     try {
       t.testThrowXraySelfHosted();
     } catch (e) {
       ok(!(e instanceof Error), "Should have an Exception here (4)");
       ok(!(e instanceof DOMException), "Should not have DOMException here (4)");
       ok(!("code" in e), "Should not have a 'code' property (4)");
       is(e.name, "NS_ERROR_UNEXPECTED", "Name should be sanitized (4)");
       is(e.message, "", "Message should be sanitized (5)");
       is(e.stack,
-         `doTest@${file}:99:7\nAsync*@${file}:137:1\n`,
+         "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:99:7\n",
          "Exception stack for sanitized exception should only show our code (4)");
       is(e.filename,
-         file,
+         "http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
          "Should still have the right file name for sanitized exception (4)");
       is(e.lineNumber, 99, "Should still have the right line number for sanitized exception (4)");
       todo_isnot(e.columnNumber, 0, "Should have the right column number for sanitized exception (4)");
     }
 
     try {
       t.testThrowSelfHosted();
     } catch (e) {
       ok(!(e instanceof Error), "Should have an Exception here (5)");
       ok(!(e instanceof DOMException), "Should not have DOMException here (5)");
       ok(!("code" in e), "Should not have a 'code' property (5)");
       is(e.name, "NS_ERROR_UNEXPECTED", "Name should be sanitized (5)");
       is(e.message, "", "Message should be sanitized (5)");
       is(e.stack,
-         `doTest@${file}:117:7\nAsync*@${file}:137:1\n`,
+         "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html:117:7\n",
          "Exception stack for sanitized exception should only show our code (5)");
       is(e.filename,
-         file,
+         "http://mochi.test:8888/tests/dom/bindings/test/test_exception_options_from_jsimplemented.html",
          "Should still have the right file name for sanitized exception (5)");
       is(e.lineNumber, 117, "Should still have the right line number for sanitized exception (5)");
       todo_isnot(e.columnNumber, 0, "Should have the right column number for sanitized exception (5)");
     }
 
     SimpleTest.finish();
   }
 
--- a/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
+++ b/dom/bindings/test/test_promise_rejections_from_jsimplemented.html
@@ -34,72 +34,65 @@ https://bugzilla.mozilla.org/show_bug.cg
   function ensurePromiseFail(testNumber, value) {
     ok(false, "Test " + testNumber + " should not have a fulfilled promise");
   }
 
   function doTest() {
     var t = new TestInterfaceJS();
     var asyncStack = SpecialPowers.getBoolPref("javascript.options.asyncstack");
     var ourFile = "http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html";
-    var parentFrame = asyncStack ? "Async*@" + ourFile + ":110:1\n" : "";
 
     Promise.all([
       t.testPromiseWithThrowingChromePromiseInit().then(
           ensurePromiseFail.bind(null, 1),
-          checkExn.bind(null, 45, "NS_ERROR_UNEXPECTED", "", undefined,
+          checkExn.bind(null, 44, "NS_ERROR_UNEXPECTED", "", undefined,
                         ourFile, 1,
-                        "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:45:7\n" +
-                        parentFrame)),
+                        "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:44:7\n")),
       t.testPromiseWithThrowingContentPromiseInit(function() {
           thereIsNoSuchContentFunction1();
         }).then(
           ensurePromiseFail.bind(null, 2),
-          checkExn.bind(null, 52, "ReferenceError",
+          checkExn.bind(null, 50, "ReferenceError",
                         "thereIsNoSuchContentFunction1 is not defined",
                         undefined, ourFile, 2,
-                        "doTest/<@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:52:11\ndoTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:51:7\n" +
-                        parentFrame)),
+                        "doTest/<@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:50:11\ndoTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:49:7\n")),
       t.testPromiseWithThrowingChromeThenFunction().then(
           ensurePromiseFail.bind(null, 3),
           checkExn.bind(null, 0, "NS_ERROR_UNEXPECTED", "", undefined, "", 3, "")),
       t.testPromiseWithThrowingContentThenFunction(function() {
           thereIsNoSuchContentFunction2();
         }).then(
           ensurePromiseFail.bind(null, 4),
-          checkExn.bind(null, 64, "ReferenceError",
+          checkExn.bind(null, 61, "ReferenceError",
                         "thereIsNoSuchContentFunction2 is not defined",
                         undefined, ourFile, 4,
-                        "doTest/<@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:64:11\n" +
-                        "Async*doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:63:7\n" +
-                        parentFrame)),
+                        "doTest/<@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:61:11\n" + (asyncStack ? "Async*doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:60:7\n" : ""))),
       t.testPromiseWithThrowingChromeThenable().then(
           ensurePromiseFail.bind(null, 5),
           checkExn.bind(null, 0, "NS_ERROR_UNEXPECTED", "", undefined, "", 5, "")),
       t.testPromiseWithThrowingContentThenable({
             then: function() { thereIsNoSuchContentFunction3(); }
         }).then(
           ensurePromiseFail.bind(null, 6),
-          checkExn.bind(null, 77, "ReferenceError",
+          checkExn.bind(null, 72, "ReferenceError",
                         "thereIsNoSuchContentFunction3 is not defined",
                         undefined, ourFile, 6,
-                        "doTest/<.then@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:77:32\n")),
+                        "doTest/<.then@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:72:32\n")),
       t.testPromiseWithDOMExceptionThrowingPromiseInit().then(
           ensurePromiseFail.bind(null, 7),
-          checkExn.bind(null, 84, "NotFoundError",
+          checkExn.bind(null, 79, "NotFoundError",
                         "We are a second DOMException",
                         DOMException.NOT_FOUND_ERR, ourFile, 7,
-                        "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:84:7\n" +
-                        parentFrame)),
+                        "doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:79:7\n")),
       t.testPromiseWithDOMExceptionThrowingThenFunction().then(
           ensurePromiseFail.bind(null, 8),
-          checkExn.bind(null, asyncStack ? 91 : 0, "NetworkError",
+          checkExn.bind(null, asyncStack ? 85 : 0, "NetworkError",
                          "We are a third DOMException",
                         DOMException.NETWORK_ERR, asyncStack ? ourFile : "", 8,
-                        (asyncStack ? "Async*doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:91:7\n" +
-                         parentFrame : ""))),
+                        asyncStack ? "Async*doTest@http://mochi.test:8888/tests/dom/bindings/test/test_promise_rejections_from_jsimplemented.html:85:7\n" : "")),
       t.testPromiseWithDOMExceptionThrowingThenable().then(
           ensurePromiseFail.bind(null, 9),
           checkExn.bind(null, 0, "TypeMismatchError",
                         "We are a fourth DOMException",
                          DOMException.TYPE_MISMATCH_ERR, "", 9, "")),
     ]).then(SimpleTest.finish,
             function() {
               ok(false, "One of our catch statements totally failed");
--- a/dom/events/DOMEventTargetHelper.cpp
+++ b/dom/events/DOMEventTargetHelper.cpp
@@ -282,17 +282,17 @@ DOMEventTargetHelper::DispatchTrustedEve
 nsresult
 DOMEventTargetHelper::SetEventHandler(nsIAtom* aType,
                                       JSContext* aCx,
                                       const JS::Value& aValue)
 {
   nsRefPtr<EventHandlerNonNull> handler;
   JS::Rooted<JSObject*> callable(aCx);
   if (aValue.isObject() && JS::IsCallable(callable = &aValue.toObject())) {
-    handler = new EventHandlerNonNull(aCx, callable, dom::GetIncumbentGlobal());
+    handler = new EventHandlerNonNull(callable, dom::GetIncumbentGlobal());
   }
   SetEventHandler(aType, EmptyString(), handler);
   return NS_OK;
 }
 
 void
 DOMEventTargetHelper::GetEventHandler(nsIAtom* aType,
                                       JSContext* aCx,
--- a/dom/events/EventListenerManager.cpp
+++ b/dom/events/EventListenerManager.cpp
@@ -945,25 +945,25 @@ EventListenerManager::CompileEventHandle
   result = nsJSUtils::CompileFunction(jsapi, scopeChain, options,
                                       nsAtomCString(typeAtom),
                                       argCount, argNames, *body, handler.address());
   NS_ENSURE_SUCCESS(result, result);
   NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
 
   if (jsEventHandler->EventName() == nsGkAtoms::onerror && win) {
     nsRefPtr<OnErrorEventHandlerNonNull> handlerCallback =
-      new OnErrorEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
+      new OnErrorEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
     jsEventHandler->SetHandler(handlerCallback);
   } else if (jsEventHandler->EventName() == nsGkAtoms::onbeforeunload && win) {
     nsRefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
-      new OnBeforeUnloadEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
+      new OnBeforeUnloadEventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
     jsEventHandler->SetHandler(handlerCallback);
   } else {
     nsRefPtr<EventHandlerNonNull> handlerCallback =
-      new EventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
+      new EventHandlerNonNull(handler, /* aIncumbentGlobal = */ nullptr);
     jsEventHandler->SetHandler(handlerCallback);
   }
 
   return result;
 }
 
 nsresult
 EventListenerManager::HandleEventSubType(Listener* aListener,
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -1307,17 +1307,17 @@ Promise::ResolveInternal(JSContext* aCx,
         nsRefPtr<PromiseCallback> rejectCb = new RejectPromiseCallback(this, glob);
         nsRefPtr<FastThenableResolverTask> task =
           new FastThenableResolverTask(resolveCb, rejectCb, nextPromise);
         DispatchToMicroTask(task);
         return;
       }
 
       nsRefPtr<PromiseInit> thenCallback =
-        new PromiseInit(nullptr, thenObj, mozilla::dom::GetIncumbentGlobal());
+        new PromiseInit(thenObj, mozilla::dom::GetIncumbentGlobal());
       nsRefPtr<ThenableResolverTask> task =
         new ThenableResolverTask(this, valueObj, thenCallback);
       DispatchToMicroTask(task);
       return;
     }
   }
 
   MaybeSettle(aValue, Resolved);
--- a/dom/xbl/nsXBLPrototypeHandler.cpp
+++ b/dom/xbl/nsXBLPrototypeHandler.cpp
@@ -311,17 +311,17 @@ nsXBLPrototypeHandler::ExecuteHandler(Ev
   NS_ENSURE_TRUE(ok, NS_ERROR_OUT_OF_MEMORY);
 
   // Next, clone the generic handler with our desired scope chain.
   JS::Rooted<JSObject*> bound(cx, JS::CloneFunctionObject(cx, genericHandler,
                                                           scopeChain));
   NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
 
   nsRefPtr<EventHandlerNonNull> handlerCallback =
-    new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr);
+    new EventHandlerNonNull(bound, /* aIncumbentGlobal = */ nullptr);
 
   TypedEventHandler typedHandler(handlerCallback);
 
   // Execute it.
   nsCOMPtr<JSEventHandler> jsEventHandler;
   rv = NS_NewJSEventHandler(scriptTarget, onEventAtom,
                             typedHandler,
                             getter_AddRefs(jsEventHandler));
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -938,18 +938,17 @@ CallFunctionWithAsyncStack(JSContext* cx
         JS_ReportError(cx, "The third argument should be a non-empty string.");
         return false;
     }
 
     RootedObject function(cx, &args[0].toObject());
     RootedObject stack(cx, &args[1].toObject());
     RootedString asyncCause(cx, args[2].toString());
 
-    JS::AutoSetAsyncStackForNewCalls sas(cx, stack, asyncCause,
-                                         JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
+    JS::AutoSetAsyncStackForNewCalls sas(cx, stack, asyncCause);
     return Call(cx, UndefinedHandleValue, function,
                 JS::HandleValueArray::empty(), args.rval());
 }
 
 static bool
 EnableTrackAllocations(JSContext* cx, unsigned argc, jsval* vp)
 {
     SetObjectMetadataCallback(cx, SavedStacksMetadataCallback);
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -4725,45 +4725,41 @@ JS_PUBLIC_API(void)
 JS_RestoreFrameChain(JSContext* cx)
 {
     AssertHeapIsIdleOrIterating(cx);
     CHECK_REQUEST(cx);
     cx->restoreFrameChain();
 }
 
 JS::AutoSetAsyncStackForNewCalls::AutoSetAsyncStackForNewCalls(
-  JSContext* cx, HandleObject stack, HandleString asyncCause,
-  JS::AutoSetAsyncStackForNewCalls::AsyncCallKind kind)
+  JSContext* cx, HandleObject stack, HandleString asyncCause)
   : cx(cx),
     oldAsyncStack(cx, cx->runtime()->asyncStackForNewActivations),
-    oldAsyncCause(cx, cx->runtime()->asyncCauseForNewActivations),
-    oldAsyncCallIsExplicit(cx->runtime()->asyncCallIsExplicit)
+    oldAsyncCause(cx, cx->runtime()->asyncCauseForNewActivations)
 {
     CHECK_REQUEST(cx);
 
     // The option determines whether we actually use the new values at this
     // point. It will not affect restoring the previous values when the object
     // is destroyed, so if the option changes it won't cause consistency issues.
     if (!cx->runtime()->options().asyncStack())
         return;
 
     SavedFrame* asyncStack = &stack->as<SavedFrame>();
     MOZ_ASSERT(!asyncCause->empty());
 
     cx->runtime()->asyncStackForNewActivations = asyncStack;
     cx->runtime()->asyncCauseForNewActivations = asyncCause;
-    cx->runtime()->asyncCallIsExplicit = kind == AsyncCallKind::EXPLICIT;
 }
 
 JS::AutoSetAsyncStackForNewCalls::~AutoSetAsyncStackForNewCalls()
 {
     cx->runtime()->asyncCauseForNewActivations = oldAsyncCause;
     cx->runtime()->asyncStackForNewActivations =
       oldAsyncStack ? &oldAsyncStack->as<SavedFrame>() : nullptr;
-    cx->runtime()->asyncCallIsExplicit = oldAsyncCallIsExplicit;
 }
 
 /************************************************************************/
 JS_PUBLIC_API(JSString*)
 JS_NewStringCopyN(JSContext* cx, const char* s, size_t n)
 {
     AssertHeapIsIdle(cx);
     CHECK_REQUEST(cx);
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -4028,35 +4028,24 @@ namespace JS {
  * See also `js/src/doc/SavedFrame/SavedFrame.md` for documentation on async
  * stack frames.
  */
 class MOZ_STACK_CLASS JS_PUBLIC_API(AutoSetAsyncStackForNewCalls)
 {
     JSContext* cx;
     RootedObject oldAsyncStack;
     RootedString oldAsyncCause;
-    bool oldAsyncCallIsExplicit;
 
   public:
-    enum class AsyncCallKind {
-        // The ordinary kind of call, where we may apply an async
-        // parent if there is no ordinary parent.
-        IMPLICIT,
-        // An explicit async parent, e.g., callFunctionWithAsyncStack,
-        // where we always want to override any ordinary parent.
-        EXPLICIT
-    };
-
     // The stack parameter cannot be null by design, because it would be
     // ambiguous whether that would clear any scheduled async stack and make the
     // normal stack reappear in the new call, or just keep the async stack
     // already scheduled for the new call, if any.
     AutoSetAsyncStackForNewCalls(JSContext* cx, HandleObject stack,
-                                 HandleString asyncCause,
-                                 AsyncCallKind kind = AsyncCallKind::IMPLICIT);
+                                 HandleString asyncCause);
     ~AutoSetAsyncStackForNewCalls();
 };
 
 } // namespace JS
 
 /************************************************************************/
 
 /*
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -123,17 +123,16 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
     jitStackLimit_(0xbad),
     activation_(nullptr),
     profilingActivation_(nullptr),
     profilerSampleBufferGen_(0),
     profilerSampleBufferLapCount_(1),
     asmJSActivationStack_(nullptr),
     asyncStackForNewActivations(nullptr),
     asyncCauseForNewActivations(nullptr),
-    asyncCallIsExplicit(false),
     entryMonitor(nullptr),
     parentRuntime(parentRuntime),
     interrupt_(false),
     telemetryCallback(nullptr),
     handlingSignal(false),
     interruptCallback(nullptr),
     exclusiveAccessLock(nullptr),
     exclusiveAccessOwner(nullptr),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -692,22 +692,16 @@ struct JSRuntime : public JS::shadow::Ru
      */
     js::SavedFrame* asyncStackForNewActivations;
 
     /*
      * Value of asyncCause to be attached to asyncStackForNewActivations.
      */
     JSString* asyncCauseForNewActivations;
 
-    /*
-     * True if the async call was explicitly requested, e.g. via
-     * callFunctionWithAsyncStack.
-     */
-    bool asyncCallIsExplicit;
-
     /* If non-null, report JavaScript entry points to this monitor. */
     JS::dbg::AutoEntryMonitor* entryMonitor;
 
     js::Activation* const* addressOfActivation() const {
         return &activation_;
     }
     static unsigned offsetOfActivation() {
         return offsetof(JSRuntime, activation_);
--- a/js/src/vm/SavedStacks.cpp
+++ b/js/src/vm/SavedStacks.cpp
@@ -907,38 +907,31 @@ SavedStacks::insertFrames(JSContext* cx,
     RootedSavedFrame asyncStack(cx, nullptr);
     RootedString asyncCause(cx, nullptr);
 
     // Accumulate the vector of Lookup objects in |stackChain|.
     SavedFrame::AutoLookupVector stackChain(cx);
     while (!iter.done()) {
         Activation& activation = *iter.activation();
 
-        if (asyncActivation && asyncActivation != &activation) {
-            // We found an async stack in the previous activation, and we
-            // walked past the oldest frame of that activation, we're done.
-            // However, we only want to use the async parent if it was
-            // explicitly requested; if we got here otherwise, we have
-            // a direct parent, which we prefer.
-            if (asyncActivation->asyncCallIsExplicit())
-                break;
-            asyncActivation = nullptr;
-        }
-
         if (!asyncActivation) {
             asyncStack = activation.asyncStack();
             if (asyncStack) {
                 // While walking from the youngest to the oldest frame, we found
                 // an activation that has an async stack set. We will use the
                 // youngest frame of the async stack as the parent of the oldest
                 // frame of this activation. We still need to iterate over other
                 // frames in this activation before reaching the oldest frame.
                 asyncCause = activation.asyncCause();
                 asyncActivation = &activation;
             }
+        } else if (asyncActivation != &activation) {
+            // We found an async stack in the previous activation, and we
+            // walked past the oldest frame of that activation, we're done.
+            break;
         }
 
         AutoLocationValueRooter location(cx);
 
         {
             AutoCompartment ac(cx, iter.compartment());
             if (!cx->compartment()->savedStacks().getLocation(cx, iter, &location))
                 return false;
--- a/js/src/vm/Stack-inl.h
+++ b/js/src/vm/Stack-inl.h
@@ -863,37 +863,34 @@ Activation::Activation(JSContext* cx, Ki
   : cx_(cx),
     compartment_(cx->compartment()),
     prev_(cx->runtime_->activation_),
     prevProfiling_(prev_ ? prev_->mostRecentProfiling() : nullptr),
     savedFrameChain_(0),
     hideScriptedCallerCount_(0),
     asyncStack_(cx, cx->runtime_->asyncStackForNewActivations),
     asyncCause_(cx, cx->runtime_->asyncCauseForNewActivations),
-    asyncCallIsExplicit_(cx->runtime_->asyncCallIsExplicit),
     entryMonitor_(cx->runtime_->entryMonitor),
     kind_(kind)
 {
     cx->runtime_->asyncStackForNewActivations = nullptr;
     cx->runtime_->asyncCauseForNewActivations = nullptr;
-    cx->runtime_->asyncCallIsExplicit = false;
     cx->runtime_->entryMonitor = nullptr;
     cx->runtime_->activation_ = this;
 }
 
 Activation::~Activation()
 {
     MOZ_ASSERT_IF(isProfiling(), this != cx_->runtime()->profilingActivation_);
     MOZ_ASSERT(cx_->runtime_->activation_ == this);
     MOZ_ASSERT(hideScriptedCallerCount_ == 0);
     cx_->runtime_->activation_ = prev_;
     cx_->runtime_->entryMonitor = entryMonitor_;
     cx_->runtime_->asyncCauseForNewActivations = asyncCause_;
     cx_->runtime_->asyncStackForNewActivations = asyncStack_;
-    cx_->runtime_->asyncCallIsExplicit = asyncCallIsExplicit_;
 }
 
 bool
 Activation::isProfiling() const
 {
     if (isInterpreter())
         return asInterpreter()->isProfiling();
 
--- a/js/src/vm/Stack.h
+++ b/js/src/vm/Stack.h
@@ -1125,20 +1125,16 @@ class Activation
     //
     // Usually this is nullptr, meaning that normal stack capture will occur.
     // When this is set, the stack of any previous activation is ignored.
     Rooted<SavedFrame*> asyncStack_;
 
     // Value of asyncCause to be attached to asyncStack_.
     RootedString asyncCause_;
 
-    // True if the async call was explicitly requested, e.g. via
-    // callFunctionWithAsyncStack.
-    bool asyncCallIsExplicit_;
-
     // The entry point monitor that was set on cx_->runtime() when this
     // Activation was created. Subclasses should report their entry frame's
     // function or script here.
     JS::dbg::AutoEntryMonitor* entryMonitor_;
 
     enum Kind { Interpreter, Jit, AsmJS };
     Kind kind_;
 
@@ -1214,20 +1210,16 @@ class Activation
     SavedFrame* asyncStack() {
         return asyncStack_;
     }
 
     JSString* asyncCause() {
         return asyncCause_;
     }
 
-    bool asyncCallIsExplicit() const {
-        return asyncCallIsExplicit_;
-    }
-
   private:
     Activation(const Activation& other) = delete;
     void operator=(const Activation& other) = delete;
 };
 
 // This variable holds a special opcode value which is greater than all normal
 // opcodes, and is chosen such that the bitwise or of this value with any
 // opcode is this value.
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2819,18 +2819,17 @@ nsXPCComponents_Utils::CallFunctionWithA
     }
 
     JS::Rooted<JSObject*> asyncStackObj(cx, &asyncStack.toObject());
     JS::Rooted<JSString*> asyncCauseString(cx, JS_NewUCStringCopyN(cx, asyncCause.BeginReading(),
                                                                        asyncCause.Length()));
     if (!asyncCauseString)
         return NS_ERROR_OUT_OF_MEMORY;
 
-    JS::AutoSetAsyncStackForNewCalls sas(cx, asyncStackObj, asyncCauseString,
-                                         JS::AutoSetAsyncStackForNewCalls::AsyncCallKind::EXPLICIT);
+    JS::AutoSetAsyncStackForNewCalls sas(cx, asyncStackObj, asyncCauseString);
 
     if (!JS_CallFunctionValue(cx, nullptr, function,
                               JS::HandleValueArray::empty(), retval))
     {
         return NS_ERROR_XPC_JAVASCRIPT_ERROR;
     }
 
     return NS_OK;
--- a/toolkit/modules/Promise-backend.js
+++ b/toolkit/modules/Promise-backend.js
@@ -38,20 +38,16 @@
 // If the file is loaded as a CommonJS module on a worker thread, the instance
 // of Cu obtained from the chrome module will be null. The reason for this is
 // that Components is not defined in worker threads, so no instance of Cu can
 // be obtained.
 
 let Cu = this.require ? require("chrome").Cu : Components.utils;
 let Cc = this.require ? require("chrome").Cc : Components.classes;
 let Ci = this.require ? require("chrome").Ci : Components.interfaces;
-// If we can access Components, then we use it to capture an async
-// parent stack trace; see scheduleWalkerLoop.  However, as it might
-// not be available (see above), users of this must check it first.
-let Components_ = this.require ? require("chrome").components : Components;
 
 // If Cu is defined, use it to lazily define the FinalizationWitnessService.
 if (Cu) {
   Cu.import("resource://gre/modules/Services.jsm");
   Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 
   XPCOMUtils.defineLazyServiceGetter(this, "FinalizationWitnessService",
                                      "@mozilla.org/toolkit/finalizationwitness;1",
@@ -736,25 +732,17 @@ this.PromiseWalker = {
     // server should be avoided when it is running on a worker thread. Because
     // it is still necessary to be able to schedule runnables on the event
     // queue, the worker loader defines the function setImmediate as a
     // per-module global for this purpose.
     //
     // If Cu is defined, this file is loaded on the main thread. Otherwise, it
     // is loaded on the worker thread.
     if (Cu) {
-      let stack = Components_ ? Components_.stack : null;
-      if (stack) {
-        DOMPromise.resolve().then(() => {
-          Cu.callFunctionWithAsyncStack(this.walkerLoop.bind(this), stack,
-                                        "Promise")
-        });
-      } else {
-        DOMPromise.resolve().then(() => this.walkerLoop());
-      }
+      DOMPromise.resolve().then(() => this.walkerLoop());
     } else {
       setImmediate(this.walkerLoop);
     }
   },
 
   /**
    * Schedules the resolution or rejection handlers registered on the provided
    * promise for processing.