Bug 1025476 - Part 1: Add compulsory Init functions to AutoJSAPI. r=bholley

This commit is contained in:
Bob Owen 2014-06-19 08:21:14 +01:00
parent 2f50cf2037
commit 2aaffc99ec
23 changed files with 193 additions and 146 deletions

View File

@ -1236,15 +1236,11 @@ EventSource::DispatchAllMessageEvents()
return;
}
// We need a parent object so that we can enter its compartment.
nsCOMPtr<nsIGlobalObject> 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<Message>

View File

@ -865,14 +865,11 @@ WebSocket::CreateAndDispatchMessageEvent(const nsACString& aData,
if (NS_FAILED(rv))
return NS_OK;
nsCOMPtr<nsIGlobalObject> 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<JS::Value> jsData(cx);

View File

@ -6411,15 +6411,12 @@ nsContentUtils::IsPatternMatching(nsAString& aValue, nsAString& aPattern,
nsIDocument* aDocument)
{
NS_ASSERTION(aDocument, "aDocument should be a valid pointer (not null)");
nsCOMPtr<nsIGlobalObject> 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);

View File

@ -383,14 +383,11 @@ nsDOMDataChannel::DoOnMessageAvailable(const nsACString& aData,
return NS_OK;
}
nsCOMPtr<nsIGlobalObject> 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<JS::Value> jsData(cx);

View File

@ -887,16 +887,13 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIScriptContext> context = globalObject->GetScriptContext();
if (!context) {
AutoJSAPI jsapi;
if (!jsapi.InitWithLegacyErrorReporting(globalObject)) {
return NS_ERROR_FAILURE;
}
AutoJSAPIWithErrorsReportedToWindow jsapi(context);
JSContext* cx = jsapi.cx();
JS::Rooted<JSObject*> global(cx, globalObject->GetGlobalJSObject());
JSAutoCompartment ac(cx, global);
JS::CompileOptions options(cx);
FillCompileOptionsForRequest(aRequest, global, &options);

View File

@ -437,6 +437,7 @@ AudioContext::DecodeAudioData(const ArrayBuffer& aBuffer,
const Optional<OwningNonNull<DecodeErrorCallback> >& aFailureCallback)
{
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JSAutoCompartment ac(cx, aBuffer.Obj());

View File

@ -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;

View File

@ -41,16 +41,12 @@ already_AddRefed<AudioBuffer>
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<AudioBuffer> buffer =
AudioBuffer::Create(mNode->Context(), aNumberOfChannels,

View File

@ -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;

View File

@ -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<AudioBuffer> inputBuffer;

View File

@ -131,19 +131,12 @@ ArchiveRequest::ReaderReady(nsTArray<nsCOMPtr<nsIDOMFile> >& aFileList,
nsresult rv;
nsCOMPtr<nsIGlobalObject> 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<JSObject*> global(cx, globalObject->GetGlobalJSObject());
NS_ASSERTION(global, "Failed to get global object!");
JSAutoCompartment ac(cx, global);
JS::Rooted<JS::Value> result(cx);
switch (mOperation) {
case GetFilenames:

View File

@ -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<nsGlobalWindow> win = static_cast<nsGlobalWindow*>(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> 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<nsGlobalWindow> win = static_cast<nsGlobalWindow*>(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> console = win->GetConsole(error);

View File

@ -272,14 +272,11 @@ PostMessageRunnable::Run()
{
MOZ_ASSERT(mPort);
nsCOMPtr<nsIGlobalObject> 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<JS::Value> messageData(cx);

View File

@ -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<nsGlobalWindow*>(aWindow), aCx);
}
bool
AutoJSAPI::InitUsingWin(nsPIDOMWindow* aWindow)
{
return Init(static_cast<nsGlobalWindow*>(aWindow));
}
bool
AutoJSAPI::InitWithLegacyErrorReportingUsingWin(nsPIDOMWindow* aWindow)
{
return InitWithLegacyErrorReporting(static_cast<nsGlobalWindow*>(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);

View File

@ -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<AutoCxPusher> mCxPusher;
mozilla::Maybe<JSAutoNullCompartment> mNullAc;
mozilla::Maybe<JSAutoNullableCompartment> 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

View File

@ -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

View File

@ -1595,6 +1595,7 @@ nsJSContext::InitClasses(JS::Handle<JSObject*> aGlobalObj)
{
JSOptionChangedCallback(js_options_dot_str, this);
AutoJSAPI jsapi;
jsapi.Init();
JSContext* cx = jsapi.cx();
JSAutoCompartment ac(cx, aGlobalObj);

View File

@ -1724,15 +1724,11 @@ JS::Value StringToJsval(nsPIDOMWindow* aWindow, nsAString& aString)
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
JSObject* global =
static_cast<nsGlobalWindow*>(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<JS::Value> result(cx);
if (!xpc::StringToJsval(cx, aString, &result)) {

View File

@ -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<nsIAtom> 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<JSObject*> wrapScope(cx, context->GetWindowProxy());
JS::Rooted<JSObject*> wrapScope(cx, global->GetGlobalJSObject());
JS::Rooted<JS::Value> v(cx);
{
JSAutoCompartment ac(cx, wrapScope);

View File

@ -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<JS::Value> value(cx);
if (!aMessage.IsEmpty()) {

View File

@ -3135,10 +3135,11 @@ WorkerPrivateParent<Derived>::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<ErrorEventInit> errorInit(aCx);
errorInit.mBubbles = false;

View File

@ -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_);
}

View File

@ -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. */