зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1052052 - Hoist AutoCxPusher into ScriptSettings.h. r=gabor
This commit is contained in:
Родитель
9d7a41f0f8
Коммит
35f3a10cb0
|
@ -24,6 +24,7 @@
|
|||
#include "mozilla/GuardObjects.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsContentListDeclarations.h"
|
||||
#include "nsCxPusher.h"
|
||||
#include "nsMathUtils.h"
|
||||
#include "nsTArrayForwardDeclare.h"
|
||||
#include "Units.h"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "xpcprivate.h" // For AutoCxPusher guts
|
||||
#include "xpcpublic.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
|
@ -18,6 +19,7 @@
|
|||
#include "nsPIDOMWindow.h"
|
||||
#include "nsTArray.h"
|
||||
#include "nsJSUtils.h"
|
||||
#include "nsDOMJSUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -373,5 +375,66 @@ AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThread)
|
|||
}
|
||||
}
|
||||
|
||||
danger::AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull)
|
||||
{
|
||||
MOZ_ASSERT_IF(!allowNull, cx);
|
||||
|
||||
// Hold a strong ref to the nsIScriptContext, if any. This ensures that we
|
||||
// only destroy the mContext of an nsJSContext when it is not on the cx stack
|
||||
// (and therefore not in use). See nsJSContext::DestroyJSContext().
|
||||
if (cx)
|
||||
mScx = GetScriptContextFromJSContext(cx);
|
||||
|
||||
XPCJSContextStack *stack = XPCJSRuntime::Get()->GetJSContextStack();
|
||||
if (!stack->Push(cx)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
mStackDepthAfterPush = stack->Count();
|
||||
|
||||
#ifdef DEBUG
|
||||
mPushedContext = cx;
|
||||
mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
|
||||
#endif
|
||||
|
||||
// Enter a request and a compartment for the duration that the cx is on the
|
||||
// stack if non-null.
|
||||
if (cx) {
|
||||
mAutoRequest.emplace(cx);
|
||||
|
||||
// DOM JSContexts don't store their default compartment object on the cx.
|
||||
JSObject *compartmentObject = mScx ? mScx->GetWindowProxy()
|
||||
: js::DefaultObjectForContextOrNull(cx);
|
||||
if (compartmentObject)
|
||||
mAutoCompartment.emplace(cx, compartmentObject);
|
||||
}
|
||||
}
|
||||
|
||||
danger::AutoCxPusher::~AutoCxPusher()
|
||||
{
|
||||
// Leave the compartment and request before popping.
|
||||
mAutoCompartment.reset();
|
||||
mAutoRequest.reset();
|
||||
|
||||
// When we push a context, we may save the frame chain and pretend like we
|
||||
// haven't entered any compartment. This gets restored on Pop(), but we can
|
||||
// run into trouble if a Push/Pop are interleaved with a
|
||||
// JSAutoEnterCompartment. Make sure the compartment depth right before we
|
||||
// pop is the same as it was right after we pushed.
|
||||
MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
|
||||
js::GetEnterCompartmentDepth(mPushedContext));
|
||||
DebugOnly<JSContext*> stackTop;
|
||||
MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext());
|
||||
XPCJSRuntime::Get()->GetJSContextStack()->Pop();
|
||||
mScx = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
danger::AutoCxPusher::IsStackTop() const
|
||||
{
|
||||
uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
|
||||
MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
|
||||
return currentDepth == mStackDepthAfterPush;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -9,19 +9,52 @@
|
|||
#ifndef mozilla_dom_ScriptSettings_h
|
||||
#define mozilla_dom_ScriptSettings_h
|
||||
|
||||
#include "nsCxPusher.h"
|
||||
#include "MainThreadUtils.h"
|
||||
#include "nsIGlobalObject.h"
|
||||
#include "nsIPrincipal.h"
|
||||
|
||||
#include "mozilla/Maybe.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
class nsGlobalWindow;
|
||||
class nsIScriptContext;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace danger {
|
||||
|
||||
/**
|
||||
* Fundamental cx pushing class. All other cx pushing classes are implemented
|
||||
* in terms of this class.
|
||||
*/
|
||||
class MOZ_STACK_CLASS AutoCxPusher
|
||||
{
|
||||
public:
|
||||
explicit AutoCxPusher(JSContext *aCx, bool aAllowNull = false);
|
||||
~AutoCxPusher();
|
||||
|
||||
nsIScriptContext* GetScriptContext() { return mScx; }
|
||||
|
||||
// Returns true if this AutoCxPusher performed the push that is currently at
|
||||
// the top of the cx stack.
|
||||
bool IsStackTop() const;
|
||||
|
||||
private:
|
||||
mozilla::Maybe<JSAutoRequest> mAutoRequest;
|
||||
mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
|
||||
nsCOMPtr<nsIScriptContext> mScx;
|
||||
uint32_t mStackDepthAfterPush;
|
||||
#ifdef DEBUG
|
||||
JSContext* mPushedContext;
|
||||
unsigned mCompartmentDepthOnEntry;
|
||||
#endif
|
||||
};
|
||||
|
||||
} /* namespace danger */
|
||||
|
||||
/*
|
||||
* System-wide setup/teardown routines. Init and Destroy should be invoked
|
||||
* once each, at startup and shutdown (respectively).
|
||||
|
@ -183,7 +216,7 @@ protected:
|
|||
AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
|
||||
|
||||
private:
|
||||
mozilla::Maybe<AutoCxPusher> mCxPusher;
|
||||
mozilla::Maybe<danger::AutoCxPusher> mCxPusher;
|
||||
mozilla::Maybe<JSAutoNullableCompartment> mAutoNullableCompartment;
|
||||
JSContext *mCx;
|
||||
|
||||
|
@ -241,7 +274,7 @@ class AutoNoJSAPI : protected ScriptSettingsStackEntry {
|
|||
public:
|
||||
explicit AutoNoJSAPI(bool aIsMainThread = NS_IsMainThread());
|
||||
private:
|
||||
mozilla::Maybe<AutoCxPusher> mCxPusher;
|
||||
mozilla::Maybe<danger::AutoCxPusher> mCxPusher;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -15,67 +15,6 @@ using mozilla::DebugOnly;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
AutoCxPusher::AutoCxPusher(JSContext* cx, bool allowNull)
|
||||
{
|
||||
MOZ_ASSERT_IF(!allowNull, cx);
|
||||
|
||||
// Hold a strong ref to the nsIScriptContext, if any. This ensures that we
|
||||
// only destroy the mContext of an nsJSContext when it is not on the cx stack
|
||||
// (and therefore not in use). See nsJSContext::DestroyJSContext().
|
||||
if (cx)
|
||||
mScx = GetScriptContextFromJSContext(cx);
|
||||
|
||||
XPCJSContextStack *stack = XPCJSRuntime::Get()->GetJSContextStack();
|
||||
if (!stack->Push(cx)) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
mStackDepthAfterPush = stack->Count();
|
||||
|
||||
#ifdef DEBUG
|
||||
mPushedContext = cx;
|
||||
mCompartmentDepthOnEntry = cx ? js::GetEnterCompartmentDepth(cx) : 0;
|
||||
#endif
|
||||
|
||||
// Enter a request and a compartment for the duration that the cx is on the
|
||||
// stack if non-null.
|
||||
if (cx) {
|
||||
mAutoRequest.emplace(cx);
|
||||
|
||||
// DOM JSContexts don't store their default compartment object on the cx.
|
||||
JSObject *compartmentObject = mScx ? mScx->GetWindowProxy()
|
||||
: js::DefaultObjectForContextOrNull(cx);
|
||||
if (compartmentObject)
|
||||
mAutoCompartment.emplace(cx, compartmentObject);
|
||||
}
|
||||
}
|
||||
|
||||
AutoCxPusher::~AutoCxPusher()
|
||||
{
|
||||
// Leave the compartment and request before popping.
|
||||
mAutoCompartment.reset();
|
||||
mAutoRequest.reset();
|
||||
|
||||
// When we push a context, we may save the frame chain and pretend like we
|
||||
// haven't entered any compartment. This gets restored on Pop(), but we can
|
||||
// run into trouble if a Push/Pop are interleaved with a
|
||||
// JSAutoEnterCompartment. Make sure the compartment depth right before we
|
||||
// pop is the same as it was right after we pushed.
|
||||
MOZ_ASSERT_IF(mPushedContext, mCompartmentDepthOnEntry ==
|
||||
js::GetEnterCompartmentDepth(mPushedContext));
|
||||
DebugOnly<JSContext*> stackTop;
|
||||
MOZ_ASSERT(mPushedContext == nsXPConnect::XPConnect()->GetCurrentJSContext());
|
||||
XPCJSRuntime::Get()->GetJSContextStack()->Pop();
|
||||
mScx = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
AutoCxPusher::IsStackTop() const
|
||||
{
|
||||
uint32_t currentDepth = XPCJSRuntime::Get()->GetJSContextStack()->Count();
|
||||
MOZ_ASSERT(currentDepth >= mStackDepthAfterPush);
|
||||
return currentDepth == mStackDepthAfterPush;
|
||||
}
|
||||
|
||||
AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
||||
: mCx(nullptr)
|
||||
{
|
||||
|
|
|
@ -9,39 +9,13 @@
|
|||
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* Fundamental cx pushing class. All other cx pushing classes are implemented
|
||||
* in terms of this class.
|
||||
*/
|
||||
class MOZ_STACK_CLASS AutoCxPusher
|
||||
{
|
||||
public:
|
||||
explicit AutoCxPusher(JSContext *aCx, bool aAllowNull = false);
|
||||
~AutoCxPusher();
|
||||
|
||||
nsIScriptContext* GetScriptContext() { return mScx; }
|
||||
|
||||
// Returns true if this AutoCxPusher performed the push that is currently at
|
||||
// the top of the cx stack.
|
||||
bool IsStackTop() const;
|
||||
|
||||
private:
|
||||
mozilla::Maybe<JSAutoRequest> mAutoRequest;
|
||||
mozilla::Maybe<JSAutoCompartment> mAutoCompartment;
|
||||
nsCOMPtr<nsIScriptContext> mScx;
|
||||
uint32_t mStackDepthAfterPush;
|
||||
#ifdef DEBUG
|
||||
JSContext* mPushedContext;
|
||||
unsigned mCompartmentDepthOnEntry;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Use AutoJSContext when you need a JS context on the stack but don't have one
|
||||
* passed as a parameter. AutoJSContext will take care of finding the most
|
||||
|
@ -61,7 +35,7 @@ protected:
|
|||
void Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||
|
||||
JSContext* mCx;
|
||||
Maybe<AutoCxPusher> mPusher;
|
||||
Maybe<mozilla::dom::danger::AutoCxPusher> mPusher;
|
||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||
};
|
||||
|
||||
|
|
|
@ -2863,7 +2863,7 @@ public:
|
|||
{ return &mStack; }
|
||||
|
||||
private:
|
||||
friend class mozilla::AutoCxPusher;
|
||||
friend class mozilla::dom::danger::AutoCxPusher;
|
||||
friend bool xpc::PushJSContextNoScriptContext(JSContext *aCx);;
|
||||
friend void xpc::PopJSContextNoScriptContext();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче