From 2aaffc99ec56d6966855696dd012552a65b5ba6e Mon Sep 17 00:00:00 2001 From: Bob Owen Date: Thu, 19 Jun 2014 08:21:14 +0100 Subject: [PATCH] Bug 1025476 - Part 1: Add compulsory Init functions to AutoJSAPI. r=bholley --- content/base/src/EventSource.cpp | 8 +- content/base/src/WebSocket.cpp | 7 +- content/base/src/nsContentUtils.cpp | 9 +- content/base/src/nsDOMDataChannel.cpp | 7 +- content/base/src/nsScriptLoader.cpp | 7 +- content/media/webaudio/AudioContext.cpp | 1 + .../media/webaudio/AudioDestinationNode.cpp | 8 +- .../media/webaudio/AudioProcessingEvent.cpp | 8 +- content/media/webaudio/MediaBufferDecoder.cpp | 8 +- .../media/webaudio/ScriptProcessorNode.cpp | 8 +- dom/archivereader/ArchiveRequest.cpp | 11 +-- dom/base/Console.cpp | 22 +++-- dom/base/MessagePort.cpp | 7 +- dom/base/ScriptSettings.cpp | 95 +++++++++++++++---- dom/base/ScriptSettings.h | 78 ++++++++++----- dom/base/nsGlobalWindow.cpp | 2 + dom/base/nsJSEnvironment.cpp | 1 + dom/devicestorage/nsDeviceStorage.cpp | 8 +- dom/events/EventListenerManager.cpp | 10 +- dom/icc/src/Icc.cpp | 10 +- dom/workers/WorkerPrivate.cpp | 7 +- js/src/jsapi.cpp | 11 ++- js/src/jsapi.h | 6 +- 23 files changed, 193 insertions(+), 146 deletions(-) diff --git a/content/base/src/EventSource.cpp b/content/base/src/EventSource.cpp index dcb24f3b815..110afd05614 100644 --- a/content/base/src/EventSource.cpp +++ b/content/base/src/EventSource.cpp @@ -1236,15 +1236,11 @@ EventSource::DispatchAllMessageEvents() return; } - // We need a parent object so that we can enter its compartment. - nsCOMPtr parentObject = do_QueryInterface(GetParentObject()); - if (NS_WARN_IF(!parentObject)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) { return; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, parentObject->GetGlobalJSObject()); while (mMessagesToDispatch.GetSize() > 0) { nsAutoPtr diff --git a/content/base/src/WebSocket.cpp b/content/base/src/WebSocket.cpp index 44d554306ae..1a126d01000 100644 --- a/content/base/src/WebSocket.cpp +++ b/content/base/src/WebSocket.cpp @@ -865,14 +865,11 @@ WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData, if (NS_FAILED(rv)) return NS_OK; - nsCOMPtr globalObject = do_QueryInterface(GetOwner()); - if (NS_WARN_IF(!globalObject)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) { return NS_ERROR_FAILURE; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject()); // Create appropriate JS object for message JS::Rooted jsData(cx); diff --git a/content/base/src/nsContentUtils.cpp b/content/base/src/nsContentUtils.cpp index 2b245181e47..fcd67d40718 100644 --- a/content/base/src/nsContentUtils.cpp +++ b/content/base/src/nsContentUtils.cpp @@ -6411,15 +6411,12 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern, nsIDocument* aDocument) { NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)"); - nsCOMPtr globalObject = - do_QueryInterface(aDocument->GetWindow()); - if (NS_WARN_IF(!globalObject)) { - return true; - } AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(aDocument->GetWindow()))) { + return true; + } JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject()); // The pattern has to match the entire value. aPattern.Insert(NS_LITERAL_STRING("^(?:"), 0); diff --git a/content/base/src/nsDOMDataChannel.cpp b/content/base/src/nsDOMDataChannel.cpp index fa15f591c66..8d250ab706b 100644 --- a/content/base/src/nsDOMDataChannel.cpp +++ b/content/base/src/nsDOMDataChannel.cpp @@ -383,14 +383,11 @@ nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData, return NS_OK; } - nsCOMPtr globalObject = do_QueryInterface(GetOwner()); - if (NS_WARN_IF(!globalObject)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) { return NS_ERROR_FAILURE; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject()); JS::Rooted jsData(cx); diff --git a/content/base/src/nsScriptLoader.cpp b/content/base/src/nsScriptLoader.cpp index 2b539e759a3..02ca15ddb2f 100644 --- a/content/base/src/nsScriptLoader.cpp +++ b/content/base/src/nsScriptLoader.cpp @@ -887,16 +887,13 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest) return NS_ERROR_FAILURE; } - nsCOMPtr context = globalObject->GetScriptContext(); - if (!context) { + AutoJSAPI jsapi; + if (!jsapi.InitWithLegacyErrorReporting(globalObject)) { return NS_ERROR_FAILURE; } - AutoJSAPIWithErrorsReportedToWindow jsapi(context); JSContext* cx = jsapi.cx(); JS::Rooted global(cx, globalObject->GetGlobalJSObject()); - JSAutoCompartment ac(cx, global); - JS::CompileOptions options(cx); FillCompileOptionsForRequest(aRequest, global, &options); diff --git a/content/media/webaudio/AudioContext.cpp b/content/media/webaudio/AudioContext.cpp index 1616c49ad7c..a00e80a5989 100644 --- a/content/media/webaudio/AudioContext.cpp +++ b/content/media/webaudio/AudioContext.cpp @@ -437,6 +437,7 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer, const Optional >& aFailureCallback) { AutoJSAPI jsapi; + jsapi.Init(); JSContext* cx = jsapi.cx(); JSAutoCompartment ac(cx, aBuffer.Obj()); diff --git a/content/media/webaudio/AudioDestinationNode.cpp b/content/media/webaudio/AudioDestinationNode.cpp index aa2d4eb97ae..870b6ab38ad 100644 --- a/content/media/webaudio/AudioDestinationNode.cpp +++ b/content/media/webaudio/AudioDestinationNode.cpp @@ -126,15 +126,11 @@ public: // which is strongly referenced by the runnable that called // AudioDestinationNode::FireOfflineCompletionEvent. - // We need the global for the context so that we can enter its compartment. - JSObject* global = context->GetGlobalJSObject(); - if (NS_WARN_IF(!global)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(aNode->GetOwner()))) { return; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, global); // Create the input buffer ErrorResult rv; diff --git a/content/media/webaudio/AudioProcessingEvent.cpp b/content/media/webaudio/AudioProcessingEvent.cpp index 9139713d011..1901b7e4802 100644 --- a/content/media/webaudio/AudioProcessingEvent.cpp +++ b/content/media/webaudio/AudioProcessingEvent.cpp @@ -41,16 +41,12 @@ already_AddRefed AudioProcessingEvent::LazilyCreateBuffer(uint32_t aNumberOfChannels, ErrorResult& aRv) { - // We need the global for the context so that we can enter its compartment. - JSObject* global = mNode->Context()->GetGlobalJSObject(); - if (NS_WARN_IF(!global)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(mNode->GetOwner()))) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, global); nsRefPtr buffer = AudioBuffer::Create(mNode->Context(), aNumberOfChannels, diff --git a/content/media/webaudio/MediaBufferDecoder.cpp b/content/media/webaudio/MediaBufferDecoder.cpp index b46fc854191..340b8a82ff9 100644 --- a/content/media/webaudio/MediaBufferDecoder.cpp +++ b/content/media/webaudio/MediaBufferDecoder.cpp @@ -413,15 +413,11 @@ WebAudioDecodeJob::AllocateBuffer() MOZ_ASSERT(!mOutput); MOZ_ASSERT(NS_IsMainThread()); - // We need the global for the context so that we can enter its compartment. - JSObject* global = mContext->GetGlobalJSObject(); - if (NS_WARN_IF(!global)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(mContext->GetOwner()))) { return false; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, global); // Now create the AudioBuffer ErrorResult rv; diff --git a/content/media/webaudio/ScriptProcessorNode.cpp b/content/media/webaudio/ScriptProcessorNode.cpp index 51b287c335e..d3e90837849 100644 --- a/content/media/webaudio/ScriptProcessorNode.cpp +++ b/content/media/webaudio/ScriptProcessorNode.cpp @@ -402,15 +402,11 @@ private: return NS_OK; } - // Get the global for the context so that we can enter its compartment. - JSObject* global = node->Context()->GetGlobalJSObject(); - if (NS_WARN_IF(!global)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(node->GetOwner()))) { return NS_OK; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, global); // Create the input buffer nsRefPtr inputBuffer; diff --git a/dom/archivereader/ArchiveRequest.cpp b/dom/archivereader/ArchiveRequest.cpp index 0c0389eeb6a..6065e8a03eb 100644 --- a/dom/archivereader/ArchiveRequest.cpp +++ b/dom/archivereader/ArchiveRequest.cpp @@ -131,19 +131,12 @@ ArchiveRequest::ReaderReady(nsTArray >& aFileList, nsresult rv; - nsCOMPtr globalObject = do_QueryInterface(GetOwner()); - if (NS_WARN_IF(!globalObject)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(GetOwner()))) { return NS_ERROR_UNEXPECTED; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JS::Rooted global(cx, globalObject->GetGlobalJSObject()); - NS_ASSERTION(global, "Failed to get global object!"); - - JSAutoCompartment ac(cx, global); - JS::Rooted result(cx); switch (mOperation) { case GetFilenames: diff --git a/dom/base/Console.cpp b/dom/base/Console.cpp index c70b62faa32..0a248c51942 100644 --- a/dom/base/Console.cpp +++ b/dom/base/Console.cpp @@ -324,17 +324,18 @@ private: wp = wp->GetParent(); } - AutoJSAPI jsapi; - JSContext* cx = jsapi.cx(); - ClearException ce(cx); - nsPIDOMWindow* window = wp->GetWindow(); NS_ENSURE_TRUE_VOID(window); nsRefPtr win = static_cast(window); NS_ENSURE_TRUE_VOID(win); - JSAutoCompartment ac(cx, win->GetWrapperPreserveColor()); + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(win))) { + return; + } + JSContext* cx = jsapi.cx(); + ClearException ce(cx); ErrorResult error; nsRefPtr console = win->GetConsole(error); @@ -436,17 +437,18 @@ private: wp = wp->GetParent(); } - AutoJSAPI jsapi; - JSContext* cx = jsapi.cx(); - ClearException ce(cx); - nsPIDOMWindow* window = wp->GetWindow(); NS_ENSURE_TRUE_VOID(window); nsRefPtr win = static_cast(window); NS_ENSURE_TRUE_VOID(win); - JSAutoCompartment ac(cx, win->GetWrapperPreserveColor()); + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(win))) { + return; + } + JSContext* cx = jsapi.cx(); + ClearException ce(cx); ErrorResult error; nsRefPtr console = win->GetConsole(error); diff --git a/dom/base/MessagePort.cpp b/dom/base/MessagePort.cpp index b57498c4f1c..15e81ab397c 100644 --- a/dom/base/MessagePort.cpp +++ b/dom/base/MessagePort.cpp @@ -272,14 +272,11 @@ PostMessageRunnable::Run() { MOZ_ASSERT(mPort); - nsCOMPtr globalObject = do_QueryInterface(mPort->GetOwner()); - if (NS_WARN_IF(!globalObject)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.Init(mPort->GetParentObject()))) { return NS_ERROR_UNEXPECTED; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, globalObject->GetGlobalJSObject()); // Deserialize the structured clone data JS::Rooted messageData(cx); diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index 18340e93c2d..ece2c83ffb0 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -14,6 +14,8 @@ #include "nsIScriptGlobalObject.h" #include "nsIScriptContext.h" #include "nsContentUtils.h" +#include "nsGlobalWindow.h" +#include "nsPIDOMWindow.h" #include "nsTArray.h" #include "nsJSUtils.h" @@ -221,47 +223,100 @@ FindJSContext(nsIGlobalObject* aGlobalObject) } AutoJSAPI::AutoJSAPI() - : mCx(nsContentUtils::GetDefaultJSContextForThread()) + : mCx(nullptr) { - if (NS_IsMainThread()) { - mCxPusher.construct(mCx); - } - - // Leave the cx in a null compartment. - mNullAc.construct(mCx); } -AutoJSAPI::AutoJSAPI(JSContext *aCx, bool aIsMainThread, bool aSkipNullAc) - : mCx(aCx) +void +AutoJSAPI::InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread) { - MOZ_ASSERT_IF(aIsMainThread, NS_IsMainThread()); + mCx = aCx; if (aIsMainThread) { mCxPusher.construct(mCx); } - // In general we want to leave the cx in a null compartment, but we let - // subclasses skip this if they plan to immediately enter a compartment. - if (!aSkipNullAc) { - mNullAc.construct(mCx); + mAutoNullableCompartment.construct(mCx, aGlobal); +} + +AutoJSAPI::AutoJSAPI(nsIGlobalObject* aGlobalObject, + bool aIsMainThread, + JSContext* aCx) +{ + MOZ_ASSERT(aGlobalObject); + MOZ_ASSERT(aGlobalObject->GetGlobalJSObject(), "Must have a JS global"); + MOZ_ASSERT(aCx); + MOZ_ASSERT_IF(aIsMainThread, NS_IsMainThread()); + + InitInternal(aGlobalObject->GetGlobalJSObject(), aCx, aIsMainThread); +} + +void +AutoJSAPI::Init() +{ + MOZ_ASSERT(!mCx, "An AutoJSAPI should only be initialised once"); + + InitInternal(/* aGlobal */ nullptr, + nsContentUtils::GetDefaultJSContextForThread(), + NS_IsMainThread()); +} + +bool +AutoJSAPI::Init(nsIGlobalObject* aGlobalObject, JSContext* aCx) +{ + MOZ_ASSERT(!mCx, "An AutoJSAPI should only be initialised once"); + MOZ_ASSERT(aCx); + + if (NS_WARN_IF(!aGlobalObject)) { + return false; } + + JSObject* global = aGlobalObject->GetGlobalJSObject(); + if (NS_WARN_IF(!global)) { + return false; + } + + InitInternal(global, aCx, NS_IsMainThread()); + return true; } -AutoJSAPIWithErrorsReportedToWindow::AutoJSAPIWithErrorsReportedToWindow(nsIScriptContext* aScx) - : AutoJSAPI(aScx->GetNativeContext(), /* aIsMainThread = */ true) +bool +AutoJSAPI::Init(nsIGlobalObject* aGlobalObject) { + return Init(aGlobalObject, nsContentUtils::GetDefaultJSContextForThread()); } -AutoJSAPIWithErrorsReportedToWindow::AutoJSAPIWithErrorsReportedToWindow(nsIGlobalObject* aGlobalObject) - : AutoJSAPI(FindJSContext(aGlobalObject), /* aIsMainThread = */ true) +bool +AutoJSAPI::InitWithLegacyErrorReporting(nsIGlobalObject* aGlobalObject) { + MOZ_ASSERT(NS_IsMainThread()); + + return Init(aGlobalObject, FindJSContext(aGlobalObject)); +} + +bool +AutoJSAPI::InitUsingWin(nsPIDOMWindow* aWindow, JSContext* aCx) +{ + return Init(static_cast(aWindow), aCx); +} + +bool +AutoJSAPI::InitUsingWin(nsPIDOMWindow* aWindow) +{ + return Init(static_cast(aWindow)); +} + +bool +AutoJSAPI::InitWithLegacyErrorReportingUsingWin(nsPIDOMWindow* aWindow) +{ + return InitWithLegacyErrorReporting(static_cast(aWindow)); } AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx) - : AutoJSAPI(aCx ? aCx : FindJSContext(aGlobalObject), aIsMainThread, /* aSkipNullAc = */ true) + : AutoJSAPI(aGlobalObject, aIsMainThread, + aCx ? aCx : FindJSContext(aGlobalObject)) , ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true) - , mAc(cx(), aGlobalObject->GetGlobalJSObject()) , mWebIDLCallerPrincipal(nullptr) { MOZ_ASSERT(aGlobalObject); diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h index 2d2e98e1309..ac48af2807a 100644 --- a/dom/base/ScriptSettings.h +++ b/dom/base/ScriptSettings.h @@ -16,7 +16,7 @@ #include "mozilla/Maybe.h" -class nsIGlobalObject; +class nsPIDOMWindow; namespace mozilla { namespace dom { @@ -92,12 +92,14 @@ private: * must be on the stack. * * This base class should be instantiated as-is when the caller wants to use - * JSAPI but doesn't expect to run script. Its current duties are as-follows: + * JSAPI but doesn't expect to run script. The caller must then call one of its + * Init functions before being able to access the JSContext through cx(). + * Its current duties are as-follows (see individual Init comments for details): * * * Grabbing an appropriate JSContext, and, on the main thread, pushing it onto * the JSContext stack. - * * Entering a null compartment, so that the consumer is forced to select a - * compartment to enter before manipulating objects. + * * Entering an initial (possibly null) compartment, to ensure that the + * previously entered compartment for that JSContext is not used by mistake. * * Additionally, the following duties are planned, but not yet implemented: * @@ -121,37 +123,64 @@ private: */ class AutoJSAPI { public: - // Public constructor for use when the base class is constructed as-is. It - // uses the SafeJSContext (or worker equivalent), and enters a null - // compartment. + // Trivial constructor. One of the Init functions must be called before + // accessing the JSContext through cx(). AutoJSAPI(); - JSContext* cx() const { return mCx; } + + // This uses the SafeJSContext (or worker equivalent), and enters a null + // compartment, so that the consumer is forced to select a compartment to + // enter before manipulating objects. + void Init(); + + // This uses the SafeJSContext (or worker equivalent), and enters the + // compartment of aGlobalObject. + // If aGlobalObject or its associated JS global are null then it returns + // false and use of cx() will cause an assertion. + bool Init(nsIGlobalObject* aGlobalObject); + + // Unsurprisingly, this uses aCx and enters the compartment of aGlobalObject. + // If aGlobalObject or its associated JS global are null then it returns + // false and use of cx() will cause an assertion. + // If aCx is null it will cause an assertion. + bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx); + + // This may only be used on the main thread. + // This attempts to use the JSContext associated with aGlobalObject, otherwise + // it uses the SafeJSContext. It then enters the compartment of aGlobalObject. + // This means that existing error reporting mechanisms that use the JSContext + // to find the JSErrorReporter should still work as before. + // We should be able to remove this around bug 981198. + // If aGlobalObject or its associated JS global are null then it returns + // false and use of cx() will cause an assertion. + bool InitWithLegacyErrorReporting(nsIGlobalObject* aGlobalObject); + + // Convenience functions to take an nsPIDOMWindow*, when it is more easily + // available than an nsIGlobalObject. + bool InitUsingWin(nsPIDOMWindow* aWindow); + bool InitUsingWin(nsPIDOMWindow* aWindow, JSContext* aCx); + bool InitWithLegacyErrorReportingUsingWin(nsPIDOMWindow* aWindow); + + JSContext* cx() const { + MOZ_ASSERT(mCx, "Must call Init before using an AutoJSAPI"); + return mCx; + } bool CxPusherIsStackTop() { return mCxPusher.ref().IsStackTop(); } protected: // Protected constructor, allowing subclasses to specify a particular cx to - // be used. - AutoJSAPI(JSContext *aCx, bool aIsMainThread, bool aSkipNullAC = false); + // be used. This constructor initialises the AutoJSAPI, so Init must NOT be + // called on subclasses that use this. + // If aGlobalObject, its associated JS global or aCx are null this will cause + // an assertion, as will setting aIsMainThread incorrectly. + AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx); private: mozilla::Maybe mCxPusher; - mozilla::Maybe mNullAc; + mozilla::Maybe mAutoNullableCompartment; JSContext *mCx; -}; -// Note - the ideal way to implement this is with an accessor on AutoJSAPI -// that lets us select the error reporting target. But at present, -// implementing it that way would require us to destroy and reconstruct -// mCxPusher, which is pretty wasteful. So we do this for now, since it should -// be pretty easy to switch things over later. -// -// This should only be used on the main thread. -class AutoJSAPIWithErrorsReportedToWindow : public AutoJSAPI { - public: - AutoJSAPIWithErrorsReportedToWindow(nsIScriptContext* aScx); - // Equivalent to AutoJSAPI if aGlobal is not a Window. - AutoJSAPIWithErrorsReportedToWindow(nsIGlobalObject* aGlobalObject); + void InitInternal(JSObject* aGlobal, JSContext* aCx, bool aIsMainThread); }; /* @@ -170,7 +199,6 @@ public: } private: - JSAutoCompartment mAc; // It's safe to make this a weak pointer, since it's the subject principal // when we go on the stack, so can't go away until after we're gone. In // particular, this is only used from the CallSetup constructor, and only in diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index fa07bf3c408..05a4d10b462 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -2359,6 +2359,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument, #endif AutoJSAPI jsapi; + jsapi.Init(); JSContext *cx = jsapi.cx(); if (!mDoc) { @@ -8005,6 +8006,7 @@ PostMessageEvent::Run() "should have been passed an outer window!"); AutoJSAPI jsapi; + jsapi.Init(); JSContext* cx = jsapi.cx(); // If we bailed before this point we're going to leak mMessage, but diff --git a/dom/base/nsJSEnvironment.cpp b/dom/base/nsJSEnvironment.cpp index b921ab1be94..e2c3c905d54 100644 --- a/dom/base/nsJSEnvironment.cpp +++ b/dom/base/nsJSEnvironment.cpp @@ -1595,6 +1595,7 @@ nsJSContext::InitClasses(JS::Handle aGlobalObj) { JSOptionChangedCallback(js_options_dot_str, this); AutoJSAPI jsapi; + jsapi.Init(); JSContext* cx = jsapi.cx(); JSAutoCompartment ac(cx, aGlobalObj); diff --git a/dom/devicestorage/nsDeviceStorage.cpp b/dom/devicestorage/nsDeviceStorage.cpp index 8756b5c100f..d726b74f7cc 100644 --- a/dom/devicestorage/nsDeviceStorage.cpp +++ b/dom/devicestorage/nsDeviceStorage.cpp @@ -1724,15 +1724,11 @@ JS::Value StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString) MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aWindow); - JSObject* global = - static_cast(aWindow)->GetWrapperPreserveColor(); - if (NS_WARN_IF(!global)) { + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitUsingWin(aWindow))) { return JSVAL_NULL; } - - AutoJSAPI jsapi; JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, global); JS::Rooted result(cx); if (!xpc::StringToJsval(cx, aString, &result)) { diff --git a/dom/events/EventListenerManager.cpp b/dom/events/EventListenerManager.cpp index 5b135b2b1d2..5ced5beb973 100644 --- a/dom/events/EventListenerManager.cpp +++ b/dom/events/EventListenerManager.cpp @@ -775,12 +775,12 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener, GetScriptGlobalAndDocument(getter_AddRefs(doc)); NS_ENSURE_STATE(global); - nsIScriptContext* context = global->GetScriptContext(); - NS_ENSURE_STATE(context); - // Activate JSAPI, and make sure that exceptions are reported on the right // Window. - AutoJSAPIWithErrorsReportedToWindow jsapi(context); + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReporting(global))) { + return NS_ERROR_UNEXPECTED; + } JSContext* cx = jsapi.cx(); nsCOMPtr typeAtom = aListener->mTypeAtom; @@ -851,7 +851,7 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener, // // The wrapScope doesn't really matter here, because the target will create // its reflector in the proper scope, and then we'll enter that compartment. - JS::Rooted wrapScope(cx, context->GetWindowProxy()); + JS::Rooted wrapScope(cx, global->GetGlobalJSObject()); JS::Rooted v(cx); { JSAutoCompartment ac(cx, wrapScope); diff --git a/dom/icc/src/Icc.cpp b/dom/icc/src/Icc.cpp index ec9e127c854..d4b1eaca0a7 100644 --- a/dom/icc/src/Icc.cpp +++ b/dom/icc/src/Icc.cpp @@ -48,13 +48,11 @@ Icc::NotifyEvent(const nsAString& aName) nsresult Icc::NotifyStkEvent(const nsAString& aName, const nsAString& aMessage) { - nsresult rv; - nsIScriptContext* sc = GetContextForEventHandlers(&rv); - NS_ENSURE_SUCCESS(rv, rv); - - AutoJSAPIWithErrorsReportedToWindow jsapi(sc); + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReportingUsingWin(GetOwner()))) { + return NS_ERROR_UNEXPECTED; + } JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, sc->GetWindowProxyPreserveColor()); JS::Rooted value(cx); if (!aMessage.IsEmpty()) { diff --git a/dom/workers/WorkerPrivate.cpp b/dom/workers/WorkerPrivate.cpp index 01d8859355e..e3ed11934ff 100644 --- a/dom/workers/WorkerPrivate.cpp +++ b/dom/workers/WorkerPrivate.cpp @@ -3135,10 +3135,11 @@ WorkerPrivateParent::BroadcastErrorToSharedWorkers( size_t actionsIndex = windowActions.LastIndexOf(WindowAction(window)); - nsIGlobalObject* global = sharedWorker->GetParentObject(); - AutoJSAPIWithErrorsReportedToWindow jsapi(global); + AutoJSAPI jsapi; + if (NS_WARN_IF(!jsapi.InitWithLegacyErrorReportingUsingWin(sharedWorker->GetOwner()))) { + continue; + } JSContext* cx = jsapi.cx(); - JSAutoCompartment ac(cx, global->GetGlobalJSObject()); RootedDictionary errorInit(aCx); errorInit.mBubbles = false; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index f696de94690..7470ff2f4c8 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -982,15 +982,20 @@ JSAutoCompartment::~JSAutoCompartment() cx_->leaveCompartment(oldCompartment_); } -JSAutoNullCompartment::JSAutoNullCompartment(JSContext *cx) +JSAutoNullableCompartment::JSAutoNullableCompartment(JSContext *cx, + JSObject *targetOrNull) : cx_(cx), oldCompartment_(cx->compartment()) { AssertHeapIsIdleOrIterating(cx_); - cx_->enterNullCompartment(); + if (targetOrNull) { + cx_->enterCompartment(targetOrNull->compartment()); + } else { + cx_->enterNullCompartment(); + } } -JSAutoNullCompartment::~JSAutoNullCompartment() +JSAutoNullableCompartment::~JSAutoNullableCompartment() { cx_->leaveCompartment(oldCompartment_); } diff --git a/js/src/jsapi.h b/js/src/jsapi.h index d442621a506..8aab51050b2 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -1699,13 +1699,13 @@ class JS_PUBLIC_API(JSAutoCompartment) ~JSAutoCompartment(); }; -class JS_PUBLIC_API(JSAutoNullCompartment) +class JS_PUBLIC_API(JSAutoNullableCompartment) { JSContext *cx_; JSCompartment *oldCompartment_; public: - explicit JSAutoNullCompartment(JSContext *cx); - ~JSAutoNullCompartment(); + explicit JSAutoNullableCompartment(JSContext *cx, JSObject *targetOrNull); + ~JSAutoNullableCompartment(); }; /* NB: This API is infallible; a nullptr return value does not indicate error. */