Bug 1257335. Replace some AutoSafeJSContext uses with AutoJSAPI or AutoJSContext uses. r=bholley

In general, using an AutoJSAPI inited with an object is NOT the same as using
AutoSafeJSContext (or AutoJSAPI inited without an object) and then entering the
compartment of the object: the former will report exceptions to the global of
the object as it comes off the stack, while the latter will not.  This only
really matters if we have an object from a window or worker global and hence
might fire error events, or report internal stuff to the web console.

The changes to initing with an object made in this bug are OK for the following
reasons:

1) dom/base/Console.cpp: Always clears its exception before coming off the stack.
2) dom/base/nsDOMClassInfo.cpp: Inits with a non-web global.
3) dom/base/nsFrameMessageManager.cpp: Inits with a non-web global.
4) dom/media/MediaPermissionGonk.cpp: We probably want the caller to notice if
   anything here throws.
5) dom/xbl/nsXBLPrototypeBinding.cpp: Inits with a non-web global.
6) dom/xul/nsXULElement.cpp: Inits with a non-web global.
7) extensions/pref/autoconfig/src/nsJSConfigTriggers.cpp: Inits with a non-web global.
8) ipc/testshell/XPCShellEnvironment.cpp: Inits with a non-web global.
This commit is contained in:
Boris Zbarsky 2016-03-18 10:48:38 -04:00
parent 6d089acee2
commit 172598b4e2
21 changed files with 138 additions and 85 deletions

View File

@ -1333,12 +1333,14 @@ Console::ProcessCallData(ConsoleCallData* aData, JS::Handle<JSObject*> aGlobal,
frame = *aData->mTopStackFrame; frame = *aData->mTopStackFrame;
} }
AutoSafeJSContext cx; AutoJSAPI jsapi;
if (!jsapi.Init(aGlobal)) {
return;
}
JSContext* cx = jsapi.cx();
ClearException ce(cx); ClearException ce(cx);
RootedDictionary<ConsoleEvent> event(cx); RootedDictionary<ConsoleEvent> event(cx);
JSAutoCompartment ac(cx, aGlobal);
event.mID.Construct(); event.mID.Construct();
event.mInnerID.Construct(); event.mInnerID.Construct();

View File

@ -221,12 +221,20 @@ public:
// This uses the SafeJSContext (or worker equivalent), and enters a null // This uses the SafeJSContext (or worker equivalent), and enters a null
// compartment, so that the consumer is forced to select a compartment to // compartment, so that the consumer is forced to select a compartment to
// enter before manipulating objects. // enter before manipulating objects.
//
// This variant will ensure that any errors reported by this AutoJSAPI as it
// comes off the stack will not fire error events or be associated with any
// particular web-visible global.
void Init(); void Init();
// This uses the SafeJSContext (or worker equivalent), and enters the // This uses the SafeJSContext (or worker equivalent), and enters the
// compartment of aGlobalObject. // compartment of aGlobalObject.
// If aGlobalObject or its associated JS global are null then it returns // If aGlobalObject or its associated JS global are null then it returns
// false and use of cx() will cause an assertion. // false and use of cx() will cause an assertion.
//
// If aGlobalObject represents a web-visible global, errors reported by this
// AutoJSAPI as it comes off the stack will fire the relevant error events and
// show up in the corresponding web console.
bool Init(nsIGlobalObject* aGlobalObject); bool Init(nsIGlobalObject* aGlobalObject);
// This is a helper that grabs the native global associated with aObject and // This is a helper that grabs the native global associated with aObject and
@ -237,6 +245,10 @@ public:
// If aGlobalObject or its associated JS global are null then it returns // If aGlobalObject or its associated JS global are null then it returns
// false and use of cx() will cause an assertion. // false and use of cx() will cause an assertion.
// If aCx is null it will cause an assertion. // If aCx is null it will cause an assertion.
//
// If aGlobalObject represents a web-visible global, errors reported by this
// AutoJSAPI as it comes off the stack will fire the relevant error events and
// show up in the corresponding web console.
bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx); bool Init(nsIGlobalObject* aGlobalObject, JSContext* aCx);
// Convenience functions to take an nsPIDOMWindow* or nsGlobalWindow*, // Convenience functions to take an nsPIDOMWindow* or nsGlobalWindow*,

View File

@ -325,9 +325,13 @@ nsDOMClassInfo::GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj)
} }
nsresult nsresult
nsDOMClassInfo::DefineStaticJSVals(JSContext *cx) nsDOMClassInfo::DefineStaticJSVals()
{ {
#define SET_JSID_TO_STRING(_id, _cx, _str) \ AutoJSAPI jsapi;
jsapi.Init(xpc::UnprivilegedJunkScope());
JSContext* cx = jsapi.cx();
#define SET_JSID_TO_STRING(_id, _cx, _str) \
if (JSString *str = ::JS_AtomizeAndPinString(_cx, _str)) \ if (JSString *str = ::JS_AtomizeAndPinString(_cx, _str)) \
_id = INTERNED_STRING_TO_JSID(_cx, str); \ _id = INTERNED_STRING_TO_JSID(_cx, str); \
else \ else \
@ -500,8 +504,6 @@ nsDOMClassInfo::Init()
nsCOMPtr<nsIXPCFunctionThisTranslator> elt = new nsEventListenerThisTranslator(); nsCOMPtr<nsIXPCFunctionThisTranslator> elt = new nsEventListenerThisTranslator();
sXPConnect->SetFunctionThisTranslator(NS_GET_IID(nsIDOMEventListener), elt); sXPConnect->SetFunctionThisTranslator(NS_GET_IID(nsIDOMEventListener), elt);
AutoSafeJSContext cx;
DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor) DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor)
DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor) DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor)
DOM_CLASSINFO_MAP_END DOM_CLASSINFO_MAP_END
@ -665,7 +667,7 @@ nsDOMClassInfo::Init()
#endif #endif
// Initialize static JSString's // Initialize static JSString's
DefineStaticJSVals(cx); DefineStaticJSVals();
int32_t i; int32_t i;

View File

@ -110,7 +110,7 @@ protected:
static nsIXPConnect *sXPConnect; static nsIXPConnect *sXPConnect;
// nsIXPCScriptable code // nsIXPCScriptable code
static nsresult DefineStaticJSVals(JSContext *cx); static nsresult DefineStaticJSVals();
static bool sIsInitialized; static bool sIsInitialized;

View File

@ -1646,7 +1646,6 @@ void
nsMessageManagerScriptExecutor::Shutdown() nsMessageManagerScriptExecutor::Shutdown()
{ {
if (sCachedScripts) { if (sCachedScripts) {
AutoSafeJSContext cx;
NS_ASSERTION(sCachedScripts != nullptr, "Need cached scripts"); NS_ASSERTION(sCachedScripts != nullptr, "Need cached scripts");
for (auto iter = sCachedScripts->Iter(); !iter.Done(); iter.Next()) { for (auto iter = sCachedScripts->Iter(); !iter.Done(); iter.Next()) {
delete iter.Data(); delete iter.Data();
@ -1761,12 +1760,13 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
JS::SourceBufferHolder::GiveOwnership); JS::SourceBufferHolder::GiveOwnership);
if (dataStringBuf && dataStringLength > 0) { if (dataStringBuf && dataStringLength > 0) {
AutoSafeJSContext cx;
// Compile the script in the compilation scope instead of the current global // Compile the script in the compilation scope instead of the current global
// to avoid keeping the current compartment alive. // to avoid keeping the current compartment alive.
JS::Rooted<JSObject*> global(cx, xpc::CompilationScope()); AutoJSAPI jsapi;
if (!jsapi.Init(xpc::CompilationScope())) {
JSAutoCompartment ac(cx, global); return;
}
JSContext* cx = jsapi.cx();
JS::CompileOptions options(cx, JSVERSION_LATEST); JS::CompileOptions options(cx, JSVERSION_LATEST);
options.setFileAndLine(url.get(), 1); options.setFileAndLine(url.get(), 1);
options.setNoScriptRval(true); options.setNoScriptRval(true);
@ -1801,8 +1801,7 @@ nsMessageManagerScriptExecutor::TryCacheLoadAndCompileScript(
const nsAString& aURL, const nsAString& aURL,
bool aRunInGlobalScope) bool aRunInGlobalScope)
{ {
AutoSafeJSContext cx; JS::Rooted<JSScript*> script(nsContentUtils::RootingCx());
JS::Rooted<JSScript*> script(cx);
TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script); TryCacheLoadAndCompileScript(aURL, aRunInGlobalScope, true, &script);
} }

View File

@ -4012,7 +4012,9 @@ nsGlobalWindow::GetMozSelfSupport(ErrorResult& aError)
return mMozSelfSupport; return mMozSelfSupport;
} }
AutoSafeJSContext cx; // We're called from JS and want to use out existing JSContext (and,
// importantly, its compartment!) here.
AutoJSContext cx;
GlobalObject global(cx, FastGetGlobalJSObject()); GlobalObject global(cx, FastGetGlobalJSObject());
mMozSelfSupport = MozSelfSupport::Constructor(global, cx, aError); mMozSelfSupport = MozSelfSupport::Constructor(global, cx, aError);
return mMozSelfSupport; return mMozSelfSupport;
@ -5700,8 +5702,13 @@ nsGlobalWindow::DispatchResizeEvent(const CSSIntSize& aSize)
return false; return false;
} }
AutoSafeJSContext cx; // We don't init the AutoJSAPI with ourselves because we don't want it
// reporting errors to our onerror handlers.
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JSAutoCompartment ac(cx, GetWrapperPreserveColor()); JSAutoCompartment ac(cx, GetWrapperPreserveColor());
DOMWindowResizeEventDetail detail; DOMWindowResizeEventDetail detail;
detail.mWidth = aSize.width; detail.mWidth = aSize.width;
detail.mHeight = aSize.height; detail.mHeight = aSize.height;
@ -8672,8 +8679,7 @@ nsGlobalWindow::NotifyDOMWindowThawed(nsGlobalWindow* aWindow) {
JSObject* JSObject*
nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey) nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey)
{ {
AutoSafeJSContext cx; JS::Rooted<JSObject*> handler(nsContentUtils::RootingCx());
JS::Rooted<JSObject*> handler(cx);
if (mCachedXBLPrototypeHandlers) { if (mCachedXBLPrototypeHandlers) {
mCachedXBLPrototypeHandlers->Get(aKey, handler.address()); mCachedXBLPrototypeHandlers->Get(aKey, handler.address());
} }

View File

@ -3720,11 +3720,15 @@ nsObjectLoadingContent::TeardownProtoChain()
nsCOMPtr<nsIContent> thisContent = nsCOMPtr<nsIContent> thisContent =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
// Use the safe JSContext here as we're not always able to find the NS_ENSURE_TRUE_VOID(thisContent->GetWrapper());
// JSContext associated with the NPP any more.
AutoSafeJSContext cx; // We don't init the AutoJSAPI with our wrapper because we don't want it
// reporting errors to our window's onerror listeners.
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> obj(cx, thisContent->GetWrapper()); JS::Rooted<JSObject*> obj(cx, thisContent->GetWrapper());
NS_ENSURE_TRUE(obj, /* void */); MOZ_ASSERT(obj);
JS::Rooted<JSObject*> proto(cx); JS::Rooted<JSObject*> proto(cx);
JSAutoCompartment ac(cx, obj); JSAutoCompartment ac(cx, obj);

View File

@ -2412,13 +2412,13 @@ GetRequestBody(nsIVariant* aBody, nsIInputStream** aResult, uint64_t* aContentLe
} }
// ArrayBuffer? // ArrayBuffer?
AutoSafeJSContext cx; JSContext* rootingCx = nsContentUtils::RootingCx();
JS::Rooted<JS::Value> realVal(cx); JS::Rooted<JS::Value> realVal(rootingCx);
nsresult rv = aBody->GetAsJSVal(&realVal); nsresult rv = aBody->GetAsJSVal(&realVal);
if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) { if (NS_SUCCEEDED(rv) && !realVal.isPrimitive()) {
JS::Rooted<JSObject*> obj(cx, realVal.toObjectOrNull()); JS::Rooted<JSObject*> obj(rootingCx, realVal.toObjectOrNull());
ArrayBuffer buf; RootedTypedArray<ArrayBuffer> buf(rootingCx);
if (buf.Init(obj)) { if (buf.Init(obj)) {
buf.ComputeLengthAndData(); buf.ComputeLengthAndData();
return GetRequestBody(buf.Data(), buf.Length(), aResult, return GetRequestBody(buf.Data(), buf.Length(), aResult,

View File

@ -325,7 +325,11 @@ CallbackObjectHolderBase::ToXPCOMCallback(CallbackObject* aCallback,
return nullptr; return nullptr;
} }
AutoSafeJSContext cx; // We don't init the AutoJSAPI with our callback because we don't want it
// reporting errors to its global's onerror handlers.
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> callback(cx, aCallback->Callback()); JS::Rooted<JSObject*> callback(cx, aCallback->Callback());

View File

@ -8,6 +8,7 @@
#include "BluetoothReplyRunnable.h" #include "BluetoothReplyRunnable.h"
#include "BluetoothUtils.h" #include "BluetoothUtils.h"
#include "DOMRequest.h" #include "DOMRequest.h"
#include "nsContentUtils.h"
#include "mozilla/dom/ScriptSettings.h" #include "mozilla/dom/ScriptSettings.h"
#include "mozilla/dom/bluetooth/BluetoothTypes.h" #include "mozilla/dom/bluetooth/BluetoothTypes.h"
#include "mozilla/dom/Promise.h" #include "mozilla/dom/Promise.h"
@ -92,8 +93,7 @@ BluetoothReplyRunnable::Run()
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mReply); MOZ_ASSERT(mReply);
AutoSafeJSContext cx; JS::Rooted<JS::Value> v(nsContentUtils::RootingCx(), JS::UndefinedValue());
JS::Rooted<JS::Value> v(cx, JS::UndefinedValue());
nsresult rv; nsresult rv;
if (mReply->type() != BluetoothReply::TBluetoothReplySuccess) { if (mReply->type() != BluetoothReply::TBluetoothReplySuccess) {

View File

@ -112,7 +112,9 @@ DataStoreDB::CreateFactoryIfNeeded()
nsIXPConnect* xpc = nsContentUtils::XPConnect(); nsIXPConnect* xpc = nsContentUtils::XPConnect();
MOZ_ASSERT(xpc); MOZ_ASSERT(xpc);
AutoSafeJSContext cx; AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> global(cx); JS::Rooted<JSObject*> global(cx);
rv = xpc->CreateSandbox(cx, principal, global.address()); rv = xpc->CreateSandbox(cx, principal, global.address());
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
@ -222,10 +224,8 @@ DataStoreDB::UpgradeSchema(nsIDOMEvent* aEvent)
MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION); MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION);
#endif #endif
AutoSafeJSContext cx;
ErrorResult error; ErrorResult error;
JS::Rooted<JS::Value> result(cx); JS::Rooted<JS::Value> result(nsContentUtils::RootingCx());
mRequest->GetResult(&result, error); mRequest->GetResult(&result, error);
if (NS_WARN_IF(error.Failed())) { if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult(); return error.StealNSResult();
@ -284,10 +284,8 @@ DataStoreDB::DatabaseOpened()
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
AutoSafeJSContext cx;
ErrorResult error; ErrorResult error;
JS::Rooted<JS::Value> result(cx); JS::Rooted<JS::Value> result(nsContentUtils::RootingCx());
mRequest->GetResult(&result, error); mRequest->GetResult(&result, error);
if (NS_WARN_IF(error.Failed())) { if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult(); return error.StealNSResult();

View File

@ -243,9 +243,12 @@ MediaPermissionRequest::Allow(JS::HandleValue aChoices)
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
} }
// iterate through audio-capture and video-capture // iterate through audio-capture and video-capture
AutoSafeJSContext cx; AutoJSAPI jsapi;
if (!jsapi.init(&aChoices.toObject())) {
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> obj(cx, &aChoices.toObject()); JS::Rooted<JSObject*> obj(cx, &aChoices.toObject());
JSAutoCompartment ac(cx, obj);
JS::Rooted<JS::Value> v(cx); JS::Rooted<JS::Value> v(cx);
// get selected audio device name // get selected audio device name

View File

@ -1134,8 +1134,7 @@ AudioManager::MaybeUpdateVolumeSettingToDatabase(bool aForce)
} }
// Send events to update the Gaia volumes // Send events to update the Gaia volumes
mozilla::AutoSafeJSContext cx; JS::Rooted<JS::Value> value(nsContentUtils::RootingCx());
JS::Rooted<JS::Value> value(cx);
uint32_t volume = 0; uint32_t volume = 0;
for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) { for (uint32_t idx = 0; idx < MOZ_ARRAY_LENGTH(gVolumeData); ++idx) {
int32_t streamType = gVolumeData[idx].mStreamType; int32_t streamType = gVolumeData[idx].mStreamType;

View File

@ -209,8 +209,8 @@ public:
settingsService->CreateLock(nullptr, getter_AddRefs(lock)); settingsService->CreateLock(nullptr, getter_AddRefs(lock));
// lock may be null if this gets called during shutdown. // lock may be null if this gets called during shutdown.
if (lock) { if (lock) {
mozilla::AutoSafeJSContext cx; JS::Rooted<JS::Value> value(nsContentUtils::RootingCx(),
JS::Rooted<JS::Value> value(cx, JS::Int32Value(mStatus)); JS::Int32Value(mStatus));
lock->Set(UMS_STATUS, value, nullptr, nullptr); lock->Set(UMS_STATUS, value, nullptr, nullptr);
} }
return NS_OK; return NS_OK;

View File

@ -78,15 +78,13 @@ SystemWorkerManager::Init()
NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread"); NS_ASSERTION(NS_IsMainThread(), "We can only initialize on the main thread");
NS_ASSERTION(!mShutdown, "Already shutdown!"); NS_ASSERTION(!mShutdown, "Already shutdown!");
mozilla::AutoSafeJSContext cx; nsresult rv = InitWifi();
nsresult rv = InitWifi(cx);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING("Failed to initialize WiFi Networking!"); NS_WARNING("Failed to initialize WiFi Networking!");
return rv; return rv;
} }
InitKeyStore(cx); InitKeyStore();
InitAutoMounter(); InitAutoMounter();
InitializeTimeZoneSettingObserver(); InitializeTimeZoneSettingObserver();
@ -205,7 +203,7 @@ SystemWorkerManager::RegisterRilWorker(unsigned int aClientId,
} }
nsresult nsresult
SystemWorkerManager::InitWifi(JSContext *cx) SystemWorkerManager::InitWifi()
{ {
nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID); nsCOMPtr<nsIWorkerHolder> worker = do_CreateInstance(kWifiWorkerCID);
NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE); NS_ENSURE_TRUE(worker, NS_ERROR_FAILURE);
@ -215,7 +213,7 @@ SystemWorkerManager::InitWifi(JSContext *cx)
} }
nsresult nsresult
SystemWorkerManager::InitKeyStore(JSContext *cx) SystemWorkerManager::InitKeyStore()
{ {
mKeyStore = new KeyStore(); mKeyStore = new KeyStore();
return NS_OK; return NS_OK;

View File

@ -59,8 +59,8 @@ private:
SystemWorkerManager(); SystemWorkerManager();
~SystemWorkerManager(); ~SystemWorkerManager();
nsresult InitWifi(JSContext *cx); nsresult InitWifi();
nsresult InitKeyStore(JSContext *cx); nsresult InitKeyStore();
nsCOMPtr<nsIWorkerHolder> mWifiWorker; nsCOMPtr<nsIWorkerHolder> mWifiWorker;

View File

@ -32,7 +32,6 @@ public:
} }
void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo) void Notify(const SystemTimezoneChangeInformation& aSystemTimezoneChangeInfo)
{ {
mozilla::AutoSafeJSContext cx;
JS::ResetTimeZone(); JS::ResetTimeZone();
} }

View File

@ -881,9 +881,12 @@ nsXBLPrototypeBinding::Read(nsIObjectInputStream* aStream,
mInterfaceTable.Put(iid, mBinding); mInterfaceTable.Put(iid, mBinding);
} }
AutoSafeJSContext cx; // We're not directly using this AutoJSAPI here, but callees use it via
JS::Rooted<JSObject*> compilationGlobal(cx, xpc::CompilationScope()); // AutoJSContext.
JSAutoCompartment ac(cx, compilationGlobal); AutoJSAPI jsapi;
if (!jsapi.Init(xpc::CompilationScope())) {
return NS_ERROR_UNEXPECTED;
}
bool isFirstBinding = aFlags & XBLBinding_Serialize_IsFirstBinding; bool isFirstBinding = aFlags & XBLBinding_Serialize_IsFirstBinding;
rv = Init(id, aDocInfo, nullptr, isFirstBinding); rv = Init(id, aDocInfo, nullptr, isFirstBinding);
@ -1024,9 +1027,12 @@ nsXBLPrototypeBinding::Write(nsIObjectOutputStream* aStream)
// mKeyHandlersRegistered and mKeyHandlers are not serialized as they are // mKeyHandlersRegistered and mKeyHandlers are not serialized as they are
// computed on demand. // computed on demand.
AutoSafeJSContext cx; // We're not directly using this AutoJSAPI here, but callees use it via
JS::Rooted<JSObject*> compilationGlobal(cx, xpc::CompilationScope()); // AutoJSContext.
JSAutoCompartment ac(cx, compilationGlobal); AutoJSAPI jsapi;
if (!jsapi.Init(xpc::CompilationScope())) {
return NS_ERROR_UNEXPECTED;
}
uint8_t flags = mInheritStyle ? XBLBinding_Serialize_InheritStyle : 0; uint8_t flags = mInheritStyle ? XBLBinding_Serialize_InheritStyle : 0;

View File

@ -2526,10 +2526,11 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos) const nsTArray<RefPtr<mozilla::dom::NodeInfo>> *aNodeInfos)
{ {
NS_ENSURE_TRUE(aProtoDoc, NS_ERROR_UNEXPECTED); NS_ENSURE_TRUE(aProtoDoc, NS_ERROR_UNEXPECTED);
AutoSafeJSContext cx;
JS::Rooted<JSObject*> global(cx, xpc::CompilationScope()); AutoJSAPI jsapi;
NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED); if (!jsapi.Init(xpc::CompilationScope())) {
JSAutoCompartment ac(cx, global); return NS_ERROR_UNEXPECTED;
}
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nullptr || NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nullptr ||
!mScriptObject, !mScriptObject,
@ -2549,6 +2550,7 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
// been set. // been set.
JS::Handle<JSScript*> script = JS::Handle<JSScript*> script =
JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address()); JS::Handle<JSScript*>::fromMarkedLocation(mScriptObject.address());
JSContext* cx = jsapi.cx();
MOZ_ASSERT(xpc::CompilationScope() == JS::CurrentGlobalOrNull(cx)); MOZ_ASSERT(xpc::CompilationScope() == JS::CurrentGlobalOrNull(cx));
return nsContentUtils::XPConnect()->WriteScript(aStream, cx, return nsContentUtils::XPConnect()->WriteScript(aStream, cx,
xpc_UnmarkGrayScript(script)); xpc_UnmarkGrayScript(script));
@ -2618,10 +2620,11 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
rv = aStream->Read32(&mLangVersion); rv = aStream->Read32(&mLangVersion);
if (NS_FAILED(rv)) return rv; if (NS_FAILED(rv)) return rv;
AutoSafeJSContext cx; AutoJSAPI jsapi;
JS::Rooted<JSObject*> global(cx, xpc::CompilationScope()); if (!jsapi.Init(xpc::CompilationScope())) {
NS_ENSURE_TRUE(global, NS_ERROR_UNEXPECTED); return NS_ERROR_UNEXPECTED;
JSAutoCompartment ac(cx, global); }
JSContext* cx = jsapi.cx();
JS::Rooted<JSScript*> newScriptObject(cx); JS::Rooted<JSScript*> newScriptObject(cx);
rv = nsContentUtils::XPConnect()->ReadScript(aStream, cx, rv = nsContentUtils::XPConnect()->ReadScript(aStream, cx,
@ -2746,13 +2749,15 @@ NotifyOffThreadScriptCompletedRunnable::Run()
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
// Note: this unroots mScript so that it is available to be collected by the JS::Rooted<JSScript*> script(nsContentUtils::RootingCx());
// JS GC. The receiver needs to root the script before performing a call that
// could GC.
JSScript *script;
{ {
AutoSafeJSContext cx; AutoJSAPI jsapi;
JSAutoCompartment ac(cx, xpc::CompilationScope()); if (!jsapi.Init(xpc::CompilationScope())) {
// Now what? I guess we just leak... this should probably never
// happen.
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = jsapi.cx();
script = JS::FinishOffThreadScript(cx, JS_GetRuntime(cx), mToken); script = JS::FinishOffThreadScript(cx, JS_GetRuntime(cx), mToken);
} }
@ -2787,8 +2792,11 @@ nsXULPrototypeScript::Compile(JS::SourceBufferHolder& aSrcBuf,
nsIOffThreadScriptReceiver *aOffThreadReceiver /* = nullptr */) nsIOffThreadScriptReceiver *aOffThreadReceiver /* = nullptr */)
{ {
// We'll compile the script in the compilation scope. // We'll compile the script in the compilation scope.
AutoSafeJSContext cx; AutoJSAPI jsapi;
JSAutoCompartment ac(cx, xpc::CompilationScope()); if (!jsapi.Init(xpc::CompilationScope())) {
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = jsapi.cx();
nsAutoCString urlspec; nsAutoCString urlspec;
nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec); nsContentUtils::GetWrapperSafeScriptFilename(aDocument, aURI, urlspec);

View File

@ -21,6 +21,7 @@
extern mozilla::LazyLogModule MCD; extern mozilla::LazyLogModule MCD;
using mozilla::AutoSafeJSContext; using mozilla::AutoSafeJSContext;
using mozilla::dom::AutoJSAPI;
//***************************************************************************** //*****************************************************************************
@ -102,8 +103,11 @@ nsresult EvaluateAdminConfigScript(const char *js_buffer, size_t length,
return rv; return rv;
} }
AutoSafeJSContext cx; AutoJSAPI jsapi;
JSAutoCompartment ac(cx, autoconfigSb); if (!jsapi.Init(autoconfigSb)) {
return NS_ERROR_UNEXPECTED;
}
JSContext* cx = jsapi.cx();
nsAutoCString script(js_buffer, length); nsAutoCString script(js_buffer, length);
JS::RootedValue v(cx); JS::RootedValue v(cx);

View File

@ -46,6 +46,8 @@ using mozilla::ipc::XPCShellEnvironment;
using mozilla::ipc::TestShellChild; using mozilla::ipc::TestShellChild;
using mozilla::ipc::TestShellParent; using mozilla::ipc::TestShellParent;
using mozilla::AutoSafeJSContext; using mozilla::AutoSafeJSContext;
using mozilla::dom::AutoJSAPI;
using mozilla::dom::AutoEntryScript;
using namespace JS; using namespace JS;
namespace { namespace {
@ -73,8 +75,11 @@ private:
inline XPCShellEnvironment* inline XPCShellEnvironment*
Environment(Handle<JSObject*> global) Environment(Handle<JSObject*> global)
{ {
AutoSafeJSContext cx; AutoJSAPI jsapi;
JSAutoCompartment ac(cx, global); if (!jsapi.Init(global)) {
return nullptr;
}
JSContext* cx = jsapi.cx();
Rooted<Value> v(cx); Rooted<Value> v(cx);
if (!JS_GetProperty(cx, global, "__XPCShellEnvironment", &v) || if (!JS_GetProperty(cx, global, "__XPCShellEnvironment", &v) ||
!v.get().isDouble()) !v.get().isDouble())
@ -451,10 +456,14 @@ XPCShellEnvironment::XPCShellEnvironment()
XPCShellEnvironment::~XPCShellEnvironment() XPCShellEnvironment::~XPCShellEnvironment()
{ {
if (GetGlobalObject()) {
AutoJSAPI jsapi;
if (!jsapi.Init(GetGlobalObject())) {
return;
}
JSContext* cx = jsapi.cx();
Rooted<JSObject*> global(cx, GetGlobalObject());
AutoSafeJSContext cx;
Rooted<JSObject*> global(cx, GetGlobalObject());
if (global) {
{ {
JSAutoCompartment ac(cx, global); JSAutoCompartment ac(cx, global);
JS_SetAllNonReservedSlotsToUndefined(cx, global); JS_SetAllNonReservedSlotsToUndefined(cx, global);
@ -568,9 +577,9 @@ bool
XPCShellEnvironment::EvaluateString(const nsString& aString, XPCShellEnvironment::EvaluateString(const nsString& aString,
nsString* aResult) nsString* aResult)
{ {
AutoSafeJSContext cx; AutoEntryScript aes(GetGlobalObject(),
JS::Rooted<JSObject*> global(cx, GetGlobalObject()); "ipc XPCShellEnvironment::EvaluateString");
JSAutoCompartment ac(cx, global); JSContext* cx = aes.cx();
JS::CompileOptions options(cx); JS::CompileOptions options(cx);
options.setFileAndLine("typein", 0); options.setFileAndLine("typein", 0);