Backed out 3 changesets (bug 1409852) for build bustage and failing test_js_dev_error_interceptor.js. r=backout on a CLOSED TREE
authorCsoregi Natalia <ncsoregi@mozilla.com>
Thu, 21 Dec 2017 15:31:27 +0200
changeset 448904 e574f932b5a811a3fb50545a7f40f75a03bff5f2
parent 448903 3c1c19235a373f3f80ec685f2356824da4b40db1
child 448905 87289743490850225764cb0c0f65ea9ceb1e72b2
push id8527
push userCallek@gmail.com
push dateThu, 11 Jan 2018 21:05:50 +0000
treeherdermozilla-beta@95342d212a7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1409852
milestone59.0a1
backs out06368bf1a32c75852fe4fc940789b5d5af728805
46fce9a2622d691de05223d1c80d15bf2a564a51
649d7bdf80add985394854ff7829cc45e20dd571
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 3 changesets (bug 1409852) for build bustage and failing test_js_dev_error_interceptor.js. r=backout on a CLOSED TREE Backed out changeset 06368bf1a32c (bug 1409852) Backed out changeset 46fce9a2622d (bug 1409852) Backed out changeset 649d7bdf80ad (bug 1409852)
dom/base/ChromeUtils.cpp
dom/base/ChromeUtils.h
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/base/test/unit/test_js_dev_error_interceptor.js
dom/base/test/unit/xpcshell.ini
dom/webidl/ChromeUtils.webidl
dom/webidl/moz.build
js/src/jsapi-tests/moz.build
js/src/jsapi-tests/testErrorInterceptor.cpp
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxtinlines.h
js/src/vm/Runtime.h
xpcom/base/CycleCollectedJSRuntime.cpp
xpcom/base/CycleCollectedJSRuntime.h
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -6,17 +6,16 @@
 
 #include "ChromeUtils.h"
 
 #include "jsfriendapi.h"
 #include "WrapperFactory.h"
 
 #include "mozilla/Base64.h"
 #include "mozilla/BasePrincipal.h"
-#include "mozilla/CycleCollectedJSRuntime.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/dom/IdleDeadline.h"
 #include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/WindowBinding.h" // For IdleRequestCallback/Options
 #include "nsThreadUtils.h"
 
 namespace mozilla {
 namespace dom {
@@ -429,37 +428,10 @@ ChromeUtils::IsOriginAttributesEqual(con
                                      const dom::OriginAttributesDictionary& aB)
 {
   return aA.mAppId == aB.mAppId &&
          aA.mInIsolatedMozBrowser == aB.mInIsolatedMozBrowser &&
          aA.mUserContextId == aB.mUserContextId &&
          aA.mPrivateBrowsingId == aB.mPrivateBrowsingId;
 }
 
-#ifdef NIGHTLY_BUILD
-/* static */ void
-ChromeUtils::GetRecentJSDevError(GlobalObject& aGlobal,
-                                JS::MutableHandleValue aRetval,
-                                ErrorResult& aRv)
-{
-  aRetval.setUndefined();
-  auto runtime = CycleCollectedJSRuntime::Get();
-  MOZ_ASSERT(runtime);
-
-  auto cx = aGlobal.Context();
-  if (!runtime->GetRecentDevError(cx, aRetval)) {
-    aRv.NoteJSContextException(cx);
-    return;
-  }
-}
-
-/* static */ void
-ChromeUtils::ClearRecentJSDevError(GlobalObject&)
-{
-  auto runtime = CycleCollectedJSRuntime::Get();
-  MOZ_ASSERT(runtime);
-
-  runtime->ClearRecentDevError();
-}
-#endif // NIGHTLY_BUILD
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/ChromeUtils.h
+++ b/dom/base/ChromeUtils.h
@@ -143,20 +143,14 @@ public:
                            JS::HandleObject aTarget,
                            JS::MutableHandleObject aRetval,
                            ErrorResult& aRv);
 
   static void IdleDispatch(const GlobalObject& global,
                            IdleRequestCallback& callback,
                            const IdleRequestOptions& options,
                            ErrorResult& aRv);
-
-  static void GetRecentJSDevError(GlobalObject& aGlobal,
-                                  JS::MutableHandleValue aRetval,
-                                  ErrorResult& aRv);
-
-  static void ClearRecentJSDevError(GlobalObject& aGlobal);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_ChromeUtils__
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -10987,26 +10987,28 @@ nsContentUtils::IsOverridingWindowName(c
 #define EXTRACT_EXN_VALUES(T, ...)                                \
   ExtractExceptionValues<mozilla::dom::prototypes::id::T,         \
                          T##Binding::NativeType, T>(__VA_ARGS__).isOk()
 
 template <prototypes::ID PrototypeID, class NativeType, typename T>
 static Result<Ok, nsresult>
 ExtractExceptionValues(JSContext* aCx,
                        JS::HandleObject aObj,
-                       nsAString& aSourceSpecOut,
+                       nsACString& aSourceSpecOut,
                        uint32_t* aLineOut,
                        uint32_t* aColumnOut,
                        nsString& aMessageOut)
 {
   RefPtr<T> exn;
   MOZ_TRY((UnwrapObject<PrototypeID, NativeType>(aObj, exn)));
 
-  exn->GetFilename(aCx, aSourceSpecOut);
-  if (!aSourceSpecOut.IsEmpty()) {
+  nsAutoString filename;
+  exn->GetFilename(aCx, filename);
+  if (!filename.IsEmpty()) {
+    CopyUTF16toUTF8(filename, aSourceSpecOut);
     *aLineOut = exn->LineNumber(aCx);
     *aColumnOut = exn->ColumnNumber();
   }
 
   exn->GetName(aMessageOut);
   aMessageOut.AppendLiteral(": ");
 
   nsAutoString message;
@@ -11018,29 +11020,16 @@ ExtractExceptionValues(JSContext* aCx,
 /* static */ void
 nsContentUtils::ExtractErrorValues(JSContext* aCx,
                                    JS::Handle<JS::Value> aValue,
                                    nsACString& aSourceSpecOut,
                                    uint32_t* aLineOut,
                                    uint32_t* aColumnOut,
                                    nsString& aMessageOut)
 {
-  nsAutoString sourceSpec;
-  ExtractErrorValues(aCx, aValue, sourceSpec, aLineOut, aColumnOut, aMessageOut);
-  CopyUTF16toUTF8(sourceSpec, aSourceSpecOut);
-}
-
-/* static */ void
-nsContentUtils::ExtractErrorValues(JSContext* aCx,
-                                   JS::Handle<JS::Value> aValue,
-                                   nsAString& aSourceSpecOut,
-                                   uint32_t* aLineOut,
-                                   uint32_t* aColumnOut,
-                                   nsString& aMessageOut)
-{
   MOZ_ASSERT(aLineOut);
   MOZ_ASSERT(aColumnOut);
 
   if (aValue.isObject()) {
     JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
 
     // Try to process as an Error object.  Use the file/line/column values
     // from the Error as they will be more specific to the root cause of
@@ -11051,17 +11040,17 @@ nsContentUtils::ExtractErrorValues(JSCon
       // this report anywhere.
       RefPtr<xpc::ErrorReport> report = new xpc::ErrorReport();
       report->Init(err,
                    "<unknown>", // toString result
                    false,       // chrome
                    0);          // window ID
 
       if (!report->mFileName.IsEmpty()) {
-        aSourceSpecOut = report->mFileName;
+        CopyUTF16toUTF8(report->mFileName, aSourceSpecOut);
         *aLineOut = report->mLineNumber;
         *aColumnOut = report->mColumn;
       }
       aMessageOut.Assign(report->mErrorMsg);
     }
 
     // Next, try to unwrap the rejection value as a DOMException.
     else if (EXTRACT_EXN_VALUES(DOMException, aCx, obj, aSourceSpecOut,
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1131,24 +1131,16 @@ public:
    * Helper function that generates a UUID.
    */
   static nsresult GenerateUUIDInPlace(nsID& aUUID);
 
   static bool PrefetchPreloadEnabled(nsIDocShell* aDocShell);
 
   static void
   ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue,
-                     nsAString& aSourceSpecOut, uint32_t *aLineOut,
-                     uint32_t *aColumnOut, nsString& aMessageOut);
-
-  // Variant on `ExtractErrorValues` with a `nsACString`. This
-  // method is provided for backwards compatibility. Prefer the
-  // faster method above for your code.
-  static void
-  ExtractErrorValues(JSContext* aCx, JS::Handle<JS::Value> aValue,
                      nsACString& aSourceSpecOut, uint32_t *aLineOut,
                      uint32_t *aColumnOut, nsString& aMessageOut);
 
   /**
    * Helper function to tell if user ever enabled DevTools explicitely.
    * Allows making DevTools related API no-op until user do so.
    */
   static bool DevToolsEnabled(JSContext* aCx);
deleted file mode 100644
--- a/dom/base/test/unit/test_js_dev_error_interceptor.js
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-function errors() {
-    return [
-        // The following two errors MUST NOT be captured.
-        new Error("This is an error: " + Math.random()),
-        new RangeError("This is a RangeError: " + Math.random()),
-        "This is a string: " + Math.random(),
-        null,
-        undefined,
-        Math.random(),
-        {},
-
-        // The following errors MUST be captured.
-        new TypeError("This is a TypeError: " + Math.random()),
-        new SyntaxError("This is a SyntaxError: " + Math.random()),
-        new ReferenceError("This is a ReferenceError: " + Math.random())
-    ]
-}
-
-function isDeveloperError(e) {
-    if (e == null || typeof e != "object") {
-        return false;
-    }
-
-    return e.constructor == TypeError
-        || e.constructor == SyntaxError
-        || e.constructor == ReferenceError;
-}
-
-function run_test() {
-    ChromeUtils.clearRecentJSDevError();
-    Assert.equal(ChromeUtils.recentJSDevError, undefined);
-
-    for (let exn of errors()) {
-        ChromeUtils.clearRecentJSDevError();
-        try {
-            throw exn;
-        } catch (e) {
-            // Discard error.
-        }
-        do_print(`Threw "${exn}", logged "${ChromeUtils.recentJSDevError}`);
-        if (isDeveloperError(exn)) {
-            Assert.equal(ChromeUtils.recentJSDevError.message, "" + exn);
-        } else {
-            Assert.equal(ChromeUtils.recentJSDevError, undefined);
-        }
-        ChromeUtils.clearRecentJSDevError();
-        Assert.equal(ChromeUtils.recentJSDevError, undefined);
-    }
-};
-
--- a/dom/base/test/unit/xpcshell.ini
+++ b/dom/base/test/unit/xpcshell.ini
@@ -49,12 +49,9 @@ head = head_xml.js
 head = head_xml.js
 [test_xml_serializer.js]
 head = head_xml.js
 [test_xmlserializer.js]
 [test_cancelPrefetch.js]
 [test_chromeutils_base64.js]
 [test_generate_xpath.js]
 head = head_xml.js
-[test_js_dev_error_interceptor.js]
-# This feature is implemented only in NIGHTLY.
-run-if = nightly_build
 
--- a/dom/webidl/ChromeUtils.webidl
+++ b/dom/webidl/ChromeUtils.webidl
@@ -84,50 +84,16 @@ namespace ChromeUtils {
    * @param string The string to decode.
    * @param options Additional decoding options.
    * @returns The decoded buffer.
    */
   [Throws, NewObject]
   ArrayBuffer base64URLDecode(ByteString string,
                               Base64URLDecodeOptions options);
 
-#ifdef NIGHTLY_BUILD
-
-  /**
-   * If the chrome code has thrown a JavaScript Dev Error
-   * in the current JSRuntime. the first such error, or `undefined`
-   * otherwise.
-   *
-   * A JavaScript Dev Error is an exception thrown by JavaScript
-   * code that matches both conditions:
-   * - it was thrown by chrome code;
-   * - it is either a `ReferenceError`, a `TypeError` or a `SyntaxError`.
-   *
-   * Such errors are stored regardless of whether they have been
-   * caught.
-   *
-   * This mechanism is designed to help ensure that the code of
-   * Firefox is free from Dev Errors, even if they are accidentally
-   * caught by clients.
-   *
-   * The object returned is not an exception. It has fields:
-   * - DOMString stack
-   * - DOMString filename
-   * - DOMString lineNumber
-   * - DOMString message
-   */
-  [Throws]
-  readonly attribute any recentJSDevError;
-
-  /**
-   * Reset `recentJSDevError` to `undefined` for the current JSRuntime.
-   */
-  void clearRecentJSDevError();
-#endif // NIGHTLY_BUILD
-
   /**
    * IF YOU ADD NEW METHODS HERE, MAKE SURE THEY ARE THREAD-SAFE.
    */
 };
 
 /**
  * Additional ChromeUtils methods that are _not_ thread-safe, and hence not
  * exposed in workers.
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -358,17 +358,16 @@ with Files("WindowOrWorkerGlobalScope.we
 with Files("Worker*"):
     BUG_COMPONENT = ("Core", "DOM: Workers")
 
 GENERATED_WEBIDL_FILES = [
     'CSS2Properties.webidl',
 ]
 
 PREPROCESSED_WEBIDL_FILES = [
-    'ChromeUtils.webidl',
     'Navigator.webidl',
     'Node.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
     'AbortController.webidl',
     'AbortSignal.webidl',
@@ -421,16 +420,17 @@ WEBIDL_FILES = [
     'CDATASection.webidl',
     'ChannelMergerNode.webidl',
     'ChannelSplitterNode.webidl',
     'ChannelWrapper.webidl',
     'CharacterData.webidl',
     'CheckerboardReportService.webidl',
     'ChildNode.webidl',
     'ChromeNodeList.webidl',
+    'ChromeUtils.webidl',
     'Client.webidl',
     'Clients.webidl',
     'ClipboardEvent.webidl',
     'CommandEvent.webidl',
     'Comment.webidl',
     'CompositionEvent.webidl',
     'Console.webidl',
     'ConstantSourceNode.webidl',
--- a/js/src/jsapi-tests/moz.build
+++ b/js/src/jsapi-tests/moz.build
@@ -132,23 +132,16 @@ if CONFIG['ENABLE_ION']:
         'testJitRValueAlloc.cpp',
     ]
 
 if CONFIG['ENABLE_STREAMS']:
     UNIFIED_SOURCES += [
         'testReadableStream.cpp',
     ]
 
-
-if CONFIG['NIGHTLY_BUILD']:
-    # The Error interceptor only exists on Nightly.
-    UNIFIED_SOURCES += [
-        'testErrorInterceptor.cpp',
-    ]
-
 if CONFIG['JS_BUILD_BINAST'] and CONFIG['JS_STANDALONE']:
     # Standalone builds leave the source directory untouched,
     # which lets us run tests with the data files intact.
     # Otherwise, in the current state of the build system,
     # we can't have data files in js/src tests.
     UNIFIED_SOURCES += [
         'testBinASTReader.cpp',
         'testBinTokenReaderTester.cpp'
deleted file mode 100644
--- a/js/src/jsapi-tests/testErrorInterceptor.cpp
+++ /dev/null
@@ -1,143 +0,0 @@
-#include "jsapi.h"
-
-#include "jsapi-tests/tests.h"
-
-#include "vm/StringBuffer.h"
-
-// Tests for JS_GetErrorInterceptorCallback and JS_SetErrorInterceptorCallback.
-
-
-namespace {
-const double EXN_VALUE = 3.14;
-
-static JS::PersistentRootedString gLatestMessage;
-
-// An interceptor that stores the error in `gLatestMessage`.
-struct SimpleInterceptor: JSErrorInterceptor {
-    virtual void interceptError(JSContext* cx, const JS::Value& val) override {
-        js::StringBuffer buffer(cx);
-        if (!ValueToStringBuffer(cx, val, buffer))
-            MOZ_CRASH("Could not convert to string buffer");
-        gLatestMessage = buffer.finishString();
-        if (!gLatestMessage)
-            MOZ_CRASH("Could not convert to string");
-    }
-};
-
-bool equalStrings(JSContext* cx, JSString* a, JSString* b) {
-    int32_t result = 0;
-    if (!JS_CompareStrings(cx, a, b, &result))
-        MOZ_CRASH("Could not compare strings");
-    return result == 0;
-}
-}
-
-BEGIN_TEST(testErrorInterceptor)
-{
-    // Run the following snippets.
-    const char* SAMPLES[] = {
-        "throw new Error('I am an Error')\0",
-        "throw new TypeError('I am a TypeError')\0",
-        "throw new ReferenceError('I am a ReferenceError')\0",
-        "throw new SyntaxError('I am a SyntaxError')\0",
-        "throw 5\0",
-        "undefined[0]\0",
-        "foo[0]\0",
-        "b[\0",
-    };
-    // With the simpleInterceptor, we should end up with the following error:
-    const char* TO_STRING[] = {
-        "Error: I am an Error\0",
-        "TypeError: I am a TypeError\0",
-        "ReferenceError: I am a ReferenceError\0",
-        "SyntaxError: I am a SyntaxError\0",
-        "5\0",
-        "TypeError: undefined has no properties\0",
-        "ReferenceError: foo is not defined\0",
-        "SyntaxError: expected expression, got end of script\0",
-    };
-    MOZ_ASSERT(mozilla::ArrayLength(SAMPLES) == mozilla::ArrayLength(TO_STRING));
-
-
-    // Save original callback.
-    JSErrorInterceptor* original = JS_GetErrorInterceptorCallback(cx->runtime());
-    gLatestMessage.init(cx);
-
-    // Test without callback.
-    JS_SetErrorInterceptorCallback(cx->runtime(), nullptr);
-    CHECK(gLatestMessage == nullptr);
-
-    for (auto sample: SAMPLES) {
-        if (execDontReport(sample, __FILE__, __LINE__))
-            MOZ_CRASH("This sample should have failed");
-        CHECK(JS_IsExceptionPending(cx));
-        CHECK(gLatestMessage == nullptr);
-        JS_ClearPendingException(cx);
-    }
-
-    // Test with callback.
-    SimpleInterceptor simpleInterceptor;
-    JS_SetErrorInterceptorCallback(cx->runtime(), &simpleInterceptor);
-
-    // Test that we return the right callback.
-    CHECK_EQUAL(JS_GetErrorInterceptorCallback(cx->runtime()), &simpleInterceptor);
-
-    // This shouldn't cause any error.
-    EXEC("function bar() {}");
-    CHECK(gLatestMessage == nullptr);
-
-    // Test error throwing with a callback that succeeds.
-    for (size_t i = 0; i < mozilla::ArrayLength(SAMPLES); ++i) {
-        // This should cause the appropriate error.
-        if (execDontReport(SAMPLES[i], __FILE__, __LINE__))
-            MOZ_CRASH("This sample should have failed");
-        CHECK(JS_IsExceptionPending(cx));
-
-        // Check result of callback.
-        CHECK(gLatestMessage != nullptr);
-        CHECK(js::StringEqualsAscii(&gLatestMessage->asLinear(), TO_STRING[i]));
-
-        // Check the final error.
-        JS::RootedValue exn(cx);
-        CHECK(JS_GetPendingException(cx, &exn));
-        JS_ClearPendingException(cx);
-
-        js::StringBuffer buffer(cx);
-        CHECK(ValueToStringBuffer(cx, exn, buffer));
-        CHECK(equalStrings(cx, buffer.finishString(), gLatestMessage));
-
-        // Cleanup.
-        gLatestMessage = nullptr;
-    }
-
-    // Test again without callback.
-    JS_SetErrorInterceptorCallback(cx->runtime(), nullptr);
-    for (size_t i = 0; i < mozilla::ArrayLength(SAMPLES); ++i) {
-        if (execDontReport(SAMPLES[i], __FILE__, __LINE__))
-            MOZ_CRASH("This sample should have failed");
-        CHECK(JS_IsExceptionPending(cx));
-
-        // Check that the callback wasn't called.
-        CHECK(gLatestMessage == nullptr);
-
-        // Check the final error.
-        JS::RootedValue exn(cx);
-        CHECK(JS_GetPendingException(cx, &exn));
-        JS_ClearPendingException(cx);
-
-        js::StringBuffer buffer(cx);
-        CHECK(ValueToStringBuffer(cx, exn, buffer));
-        CHECK(js::StringEqualsAscii(buffer.finishString(), TO_STRING[i]));
-
-        // Cleanup.
-        gLatestMessage = nullptr;
-    }
-
-    // Cleanup
-    JS_SetErrorInterceptorCallback(cx->runtime(), original);
-    gLatestMessage = nullptr;
-    JS_ClearPendingException(cx);
-
-    return true;
-}
-END_TEST(testErrorInterceptor)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -648,50 +648,16 @@ JS_SetSizeOfIncludingThisCompartmentCall
 }
 
 JS_PUBLIC_API(void)
 JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback)
 {
     cx->runtime()->compartmentNameCallback = callback;
 }
 
-#if defined(NIGHTLY_BUILD)
-JS_PUBLIC_API(void)
-JS_SetErrorInterceptorCallback(JSRuntime* rt, JSErrorInterceptor* callback)
-{
-    rt->errorInterception.interceptor = callback;
-}
-
-JS_PUBLIC_API(JSErrorInterceptor*)
-JS_GetErrorInterceptorCallback(JSRuntime* rt)
-{
-    return rt->errorInterception.interceptor;
-}
-
-JS_PUBLIC_API(Maybe<JSExnType>)
-JS_GetErrorType(const JS::Value& val)
-{
-    // All errors are objects.
-    if (!val.isObject())
-        return mozilla::Nothing();
-
-    const JSObject& obj = val.toObject();
-
-    // All errors are `ErrorObject`.
-    if (!obj.is<js::ErrorObject>()) {
-        // Not one of the primitive errors.
-        return mozilla::Nothing();
-    }
-
-    const js::ErrorObject& err = obj.as<js::ErrorObject>();
-    return mozilla::Some(err.type());
-}
-
-#endif // defined(NIGHTLY_BUILD)
-
 JS_PUBLIC_API(void)
 JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks)
 {
     cx->runtime()->wrapObjectCallbacks = callbacks;
 }
 
 JS_PUBLIC_API(void)
 JS_SetExternalStringSizeofCallback(JSContext* cx, JSExternalStringSizeofCallback callback)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -675,28 +675,16 @@ typedef void
  * that corresponds to the size of the allocation that will be released by the
  * JSStringFinalizer passed to JS_NewExternalString for this string.
  *
  * Implementations of this callback MUST NOT do anything that can cause GC.
  */
 using JSExternalStringSizeofCallback =
     size_t (*)(JSString* str, mozilla::MallocSizeOf mallocSizeOf);
 
-/**
- * Callback used to intercept JavaScript errors.
- */
-struct JSErrorInterceptor {
-    /**
-     * This method is called whenever an error has been raised from JS code.
-     *
-     * This method MUST be infallible.
-     */
-    virtual void interceptError(JSContext* cx, const JS::Value& error) = 0;
-};
-
 /************************************************************************/
 
 static MOZ_ALWAYS_INLINE JS::Value
 JS_NumberValue(double d)
 {
     int32_t i;
     d = JS::CanonicalizeNaN(d);
     if (mozilla::NumberIsInt32(d, &i))
@@ -1334,43 +1322,16 @@ extern JS_PUBLIC_API(void)
 JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback);
 
 extern JS_PUBLIC_API(void)
 JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks);
 
 extern JS_PUBLIC_API(void)
 JS_SetExternalStringSizeofCallback(JSContext* cx, JSExternalStringSizeofCallback callback);
 
-#if defined(NIGHTLY_BUILD)
-
-// Set a callback that will be called whenever an error
-// is thrown in this runtime. This is designed as a mechanism
-// for logging errors. Note that the VM makes no attempt to sanitize
-// the contents of the error (so it may contain private data)
-// or to sort out among errors (so it may not be the error you
-// are interested in or for the component in which you are
-// interested).
-//
-// If the callback sets a new error, this new error
-// will replace the original error.
-//
-// May be `nullptr`.
-extern JS_PUBLIC_API(void)
-JS_SetErrorInterceptorCallback(JSRuntime*, JSErrorInterceptor* callback);
-
-extern JS_PUBLIC_API(JSErrorInterceptor*)
-JS_GetErrorInterceptorCallback(JSRuntime*);
-
-// Examine a value to determine if it is one of the built-in Error types.
-// If so, return the error type.
-extern JS_PUBLIC_API(mozilla::Maybe<JSExnType>)
-JS_GetErrorType(const JS::Value& val);
-
-#endif // defined(NIGHTLY_BUILD)
-
 extern JS_PUBLIC_API(void)
 JS_SetCompartmentPrivate(JSCompartment* compartment, void* data);
 
 extern JS_PUBLIC_API(void*)
 JS_GetCompartmentPrivate(JSCompartment* compartment);
 
 extern JS_PUBLIC_API(void)
 JS_SetZoneUserData(JS::Zone* zone, void* data);
--- a/js/src/jscntxtinlines.h
+++ b/js/src/jscntxtinlines.h
@@ -429,41 +429,16 @@ inline void
 JSContext::minorGC(JS::gcreason::Reason reason)
 {
     runtime()->gc.minorGC(reason);
 }
 
 inline void
 JSContext::setPendingException(const js::Value& v)
 {
-#if defined(NIGHTLY_BUILD)
-    do {
-        // Do not intercept exceptions if we are already
-        // in the exception interceptor. That would lead
-        // to infinite recursion.
-        if (this->runtime()->errorInterception.isExecuting)
-            break;
-
-        // Check whether we have an interceptor at all.
-        if (!this->runtime()->errorInterception.interceptor)
-            break;
-
-        // Make sure that we do not call the interceptor from within
-        // the interceptor.
-        this->runtime()->errorInterception.isExecuting = true;
-
-        // The interceptor must be infallible.
-        const mozilla::DebugOnly<bool> wasExceptionPending = this->isExceptionPending();
-        this->runtime()->errorInterception.interceptor->interceptError(this, v);
-        MOZ_ASSERT(wasExceptionPending == this->isExceptionPending());
-
-        this->runtime()->errorInterception.isExecuting = false;
-    } while (false);
-#endif // defined(NIGHTLY_BUILD)
-
     // overRecursed_ is set after the fact by ReportOverRecursed.
     this->overRecursed_ = false;
     this->throwing = true;
     this->unwrappedException() = v;
     // We don't use assertSameCompartment here to allow
     // js::SetPendingExceptionCrossContext to work.
     MOZ_ASSERT_IF(v.isObject(), v.toObject().compartment() == compartment());
 }
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1076,40 +1076,16 @@ struct JSRuntime : public js::MallocProv
         wasmUnwindPC_ = nullptr;
     }
     void* wasmResumePC() const {
         return wasmResumePC_;
     }
     void* wasmUnwindPC() const {
         return wasmUnwindPC_;
     }
-
-  public:
-#if defined(NIGHTLY_BUILD)
-    // Support for informing the embedding of any error thrown.
-    // This mechanism is designed to let the embedding
-    // log/report/fail in case certain errors are thrown
-    // (e.g. SyntaxError, ReferenceError or TypeError
-    // in critical code).
-    struct ErrorInterceptionSupport {
-        ErrorInterceptionSupport()
-          : isExecuting(false)
-          , interceptor(nullptr)
-        { }
-
-        // true if the error interceptor is currently executing,
-        // false otherwise. Used to avoid infinite loops.
-        bool isExecuting;
-
-        // if non-null, any call to `setPendingException`
-        // in this runtime will trigger the call to `interceptor`
-        JSErrorInterceptor* interceptor;
-    };
-    ErrorInterceptionSupport errorInterception;
-#endif // defined(NIGHTLY_BUILD)
 };
 
 namespace js {
 
 inline void
 FreeOp::free_(void* p)
 {
     js_free(p);
--- a/xpcom/base/CycleCollectedJSRuntime.cpp
+++ b/xpcom/base/CycleCollectedJSRuntime.cpp
@@ -92,21 +92,16 @@
 #endif
 
 #include "nsIException.h"
 #include "nsIPlatformInfo.h"
 #include "nsThread.h"
 #include "nsThreadUtils.h"
 #include "xpcpublic.h"
 
-#ifdef NIGHTLY_BUILD
-// For performance reasons, we make the JS Dev Error Interceptor a Nightly-only feature.
-#define MOZ_JS_DEV_ERROR_INTERCEPTOR = 1
-#endif // NIGHTLY_BUILD
-
 using namespace mozilla;
 using namespace mozilla::dom;
 
 namespace mozilla {
 
 struct DeferredFinalizeFunctionHolder
 {
   DeferredFinalizeFunction run;
@@ -556,40 +551,30 @@ CycleCollectedJSRuntime::CycleCollectedJ
 
   static js::DOMCallbacks DOMcallbacks = {
     InstanceClassHasProtoAtDepth
   };
   SetDOMCallbacks(aCx, &DOMcallbacks);
   js::SetScriptEnvironmentPreparer(aCx, &mEnvironmentPreparer);
 
   JS::dbg::SetDebuggerMallocSizeOf(aCx, moz_malloc_size_of);
-
-#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
-  JS_SetErrorInterceptorCallback(mJSRuntime, &mErrorInterceptor);
-#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
 }
 
 void
 CycleCollectedJSRuntime::Shutdown(JSContext* cx)
 {
-#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
-  mErrorInterceptor.Shutdown(mJSRuntime);
-#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
   JS_RemoveExtraGCRootsTracer(cx, TraceBlackJS, this);
   JS_RemoveExtraGCRootsTracer(cx, TraceGrayJS, this);
 #ifdef DEBUG
   mShutdownCalled = true;
 #endif
 }
 
 CycleCollectedJSRuntime::~CycleCollectedJSRuntime()
 {
-#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
-  mErrorInterceptor.Shutdown(mJSRuntime);
-#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
   MOZ_COUNT_DTOR(CycleCollectedJSRuntime);
   MOZ_ASSERT(!mDeferredFinalizerTable.Count());
   MOZ_ASSERT(mShutdownCalled);
 }
 
 void
 CycleCollectedJSRuntime::AddContext(CycleCollectedJSContext* aContext)
 {
@@ -1567,118 +1552,8 @@ CycleCollectedJSRuntime::EnvironmentPrep
 CycleCollectedJSRuntime::Get()
 {
   auto context = CycleCollectedJSContext::Get();
   if (context) {
     return context->Runtime();
   }
   return nullptr;
 }
-
-#ifdef MOZ_JS_DEV_ERROR_INTERCEPTOR
-
-namespace js {
-extern void DumpValue(const JS::Value& val);
-}
-
-void
-CycleCollectedJSRuntime::ErrorInterceptor::Shutdown(JSRuntime* rt)
-{
-  JS_SetErrorInterceptorCallback(rt, nullptr);
-  mThrownError.reset();
-}
-
-/* virtual */ void
-CycleCollectedJSRuntime::ErrorInterceptor::interceptError(JSContext* cx, const JS::Value& exn)
-{
-  if (mThrownError) {
-    // We already have an error, we don't need anything more.
-    return;
-  }
-
-  if (!nsContentUtils::ThreadsafeIsSystemCaller(cx)) {
-    // We are only interested in chrome code.
-    return;
-  }
-
-  const auto type = JS_GetErrorType(exn);
-  if (!type) {
-    // This is not one of the primitive error types.
-    return;
-  }
-
-  switch (*type) {
-    case JSExnType::JSEXN_REFERENCEERR:
-    case JSExnType::JSEXN_SYNTAXERR:
-    case JSExnType::JSEXN_TYPEERR:
-      break;
-    default:
-      // Not one of the errors we are interested in.
-      return;
-  }
-
-  // Now copy the details of the exception locally.
-  // While copying the details of an exception could be expensive, in most runs,
-  // this will be done at most once during the execution of the process, so the
-  // total cost should be reasonable.
-  JS::RootedValue value(cx, exn);
-
-  ErrorDetails details;
-  details.mType = *type;
-  // If `exn` isn't an exception object, `ExtractErrorValues` could end up calling
-  // `toString()`, which could in turn end up throwing an error. While this should
-  // work, we want to avoid that complex use case.
-  // Fortunately, we have already checked above that `exn` is an exception object,
-  // so nothing such should happen.
-  nsContentUtils::ExtractErrorValues(cx, value, details.mFilename, &details.mLine, &details.mColumn, details.mMessage);
-
-  nsAutoCString stack;
-  JS::UniqueChars buf = JS::FormatStackDump(cx, nullptr, /* showArgs = */ false, /* showLocals = */ false, /* showThisProps = */ false);
-  stack.Append(buf.get());
-  CopyUTF8toUTF16(buf.get(), details.mStack);
-
-  mThrownError.emplace(Move(details));
-}
-
-void
-CycleCollectedJSRuntime::ClearRecentDevError()
-{
-  mErrorInterceptor.mThrownError.reset();
-}
-
-bool
-CycleCollectedJSRuntime::GetRecentDevError(JSContext*cx, JS::MutableHandle<JS::Value> error)
-{
-  if (!mErrorInterceptor.mThrownError) {
-    return true;
-  }
-
-  // Create a copy of the exception.
-  JS::RootedObject obj(cx, JS_NewPlainObject(cx));
-  if (!obj) {
-    return false;
-  }
-
-  JS::RootedValue message(cx);
-  JS::RootedValue filename(cx);
-  JS::RootedValue stack(cx);
-  if (!ToJSValue(cx, mErrorInterceptor.mThrownError->mMessage, &message) ||
-      !ToJSValue(cx, mErrorInterceptor.mThrownError->mFilename, &filename) ||
-      !ToJSValue(cx, mErrorInterceptor.mThrownError->mStack, &stack)) {
-    return false;
-  }
-
-  // Build the object.
-  const auto FLAGS = JSPROP_READONLY | JSPROP_ENUMERATE | JSPROP_PERMANENT;
-  if (!JS_DefineProperty(cx, obj, "message", message, FLAGS) ||
-      !JS_DefineProperty(cx, obj, "fileName", filename, FLAGS) ||
-      !JS_DefineProperty(cx, obj, "lineNumber", mErrorInterceptor.mThrownError->mLine, FLAGS) ||
-      !JS_DefineProperty(cx, obj, "stack", stack, FLAGS)) {
-    return false;
-  }
-
-  // Pass the result.
-  error.setObject(*obj);
-  return true;
-}
-#endif // MOZ_JS_DEV_ERROR_INTERCEPTOR
-
-#undef MOZ_JS_DEV_ERROR_INTERCEPTOR
--- a/xpcom/base/CycleCollectedJSRuntime.h
+++ b/xpcom/base/CycleCollectedJSRuntime.h
@@ -323,21 +323,16 @@ public:
 
   // Get the current thread's CycleCollectedJSRuntime.  Returns null if there
   // isn't one.
   static CycleCollectedJSRuntime* Get();
 
   void AddContext(CycleCollectedJSContext* aContext);
   void RemoveContext(CycleCollectedJSContext* aContext);
 
-#ifdef NIGHTLY_BUILD
-  bool GetRecentDevError(JSContext* aContext, JS::MutableHandle<JS::Value> aError);
-  void ClearRecentDevError();
-#endif // defined(NIGHTLY_BUILD)
-
 private:
   LinkedList<CycleCollectedJSContext> mContexts;
 
   JSGCThingParticipant mGCThingCycleCollectorGlobal;
 
   JSZoneParticipant mJSZoneCycleCollectorGlobal;
 
   JSRuntime* mJSRuntime;
@@ -372,47 +367,16 @@ private:
   struct EnvironmentPreparer : public js::ScriptEnvironmentPreparer {
     void invoke(JS::HandleObject scope, Closure& closure) override;
   };
   EnvironmentPreparer mEnvironmentPreparer;
 
 #ifdef DEBUG
   bool mShutdownCalled;
 #endif
-
-#ifdef NIGHTLY_BUILD
-  // Implementation of the error interceptor.
-  // Built on nightly only to avoid any possible performance impact on release
-
-  struct ErrorInterceptor final : public JSErrorInterceptor {
-    virtual void interceptError(JSContext* cx, const JS::Value& val) override;
-    void Shutdown(JSRuntime* rt);
-
-    // Copy of the details of the exception.
-    // We store this rather than the exception itself to avoid dealing with complicated
-    // garbage-collection scenarios, e.g. a JSContext being killed while we still hold
-    // onto an exception thrown from it.
-    struct ErrorDetails {
-      nsString mFilename;
-      nsString mMessage;
-      nsString mStack;
-      JSExnType mType;
-      uint32_t mLine;
-      uint32_t mColumn;
-    };
-
-    // If we have encountered at least one developer error,
-    // the first error we have encountered. Otherwise, or
-    // if we have reset since the latest error, `None`.
-    Maybe<ErrorDetails> mThrownError;
-  };
-  ErrorInterceptor mErrorInterceptor;
-
-#endif // defined(NIGHTLY_BUILD)
-
 };
 
 void TraceScriptHolder(nsISupports* aHolder, JSTracer* aTracer);
 
 // Returns true if the JS::TraceKind is one the cycle collector cares about.
 inline bool AddToCCKind(JS::TraceKind aKind)
 {
   return aKind == JS::TraceKind::Object ||