author | Csoregi Natalia <ncsoregi@mozilla.com> |
Thu, 21 Dec 2017 15:31:27 +0200 | |
changeset 448904 | e574f932b5a811a3fb50545a7f40f75a03bff5f2 |
parent 448903 | 3c1c19235a373f3f80ec685f2356824da4b40db1 |
child 448905 | 87289743490850225764cb0c0f65ea9ceb1e72b2 |
push id | 8527 |
push user | Callek@gmail.com |
push date | Thu, 11 Jan 2018 21:05:50 +0000 |
treeherder | mozilla-beta@95342d212a7a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | backout |
bugs | 1409852 |
milestone | 59.0a1 |
backs out | 06368bf1a32c75852fe4fc940789b5d5af728805 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
|
--- 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 ||