зеркало из 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/GuardObjects.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
#include "nsContentListDeclarations.h"
|
#include "nsContentListDeclarations.h"
|
||||||
|
#include "nsCxPusher.h"
|
||||||
#include "nsMathUtils.h"
|
#include "nsMathUtils.h"
|
||||||
#include "nsTArrayForwardDeclare.h"
|
#include "nsTArrayForwardDeclare.h"
|
||||||
#include "Units.h"
|
#include "Units.h"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
|
#include "xpcprivate.h" // For AutoCxPusher guts
|
||||||
#include "xpcpublic.h"
|
#include "xpcpublic.h"
|
||||||
#include "nsIGlobalObject.h"
|
#include "nsIGlobalObject.h"
|
||||||
#include "nsIScriptGlobalObject.h"
|
#include "nsIScriptGlobalObject.h"
|
||||||
|
@ -18,6 +19,7 @@
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsTArray.h"
|
#include "nsTArray.h"
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
|
#include "nsDOMJSUtils.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
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 dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -9,19 +9,52 @@
|
||||||
#ifndef mozilla_dom_ScriptSettings_h
|
#ifndef mozilla_dom_ScriptSettings_h
|
||||||
#define mozilla_dom_ScriptSettings_h
|
#define mozilla_dom_ScriptSettings_h
|
||||||
|
|
||||||
#include "nsCxPusher.h"
|
|
||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
#include "nsIGlobalObject.h"
|
#include "nsIGlobalObject.h"
|
||||||
#include "nsIPrincipal.h"
|
#include "nsIPrincipal.h"
|
||||||
|
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
|
||||||
class nsPIDOMWindow;
|
class nsPIDOMWindow;
|
||||||
class nsGlobalWindow;
|
class nsGlobalWindow;
|
||||||
|
class nsIScriptContext;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace dom {
|
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
|
* System-wide setup/teardown routines. Init and Destroy should be invoked
|
||||||
* once each, at startup and shutdown (respectively).
|
* once each, at startup and shutdown (respectively).
|
||||||
|
@ -183,7 +216,7 @@ protected:
|
||||||
AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
|
AutoJSAPI(nsIGlobalObject* aGlobalObject, bool aIsMainThread, JSContext* aCx);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mozilla::Maybe<AutoCxPusher> mCxPusher;
|
mozilla::Maybe<danger::AutoCxPusher> mCxPusher;
|
||||||
mozilla::Maybe<JSAutoNullableCompartment> mAutoNullableCompartment;
|
mozilla::Maybe<JSAutoNullableCompartment> mAutoNullableCompartment;
|
||||||
JSContext *mCx;
|
JSContext *mCx;
|
||||||
|
|
||||||
|
@ -241,7 +274,7 @@ class AutoNoJSAPI : protected ScriptSettingsStackEntry {
|
||||||
public:
|
public:
|
||||||
explicit AutoNoJSAPI(bool aIsMainThread = NS_IsMainThread());
|
explicit AutoNoJSAPI(bool aIsMainThread = NS_IsMainThread());
|
||||||
private:
|
private:
|
||||||
mozilla::Maybe<AutoCxPusher> mCxPusher;
|
mozilla::Maybe<danger::AutoCxPusher> mCxPusher;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
|
|
|
@ -15,67 +15,6 @@ using mozilla::DebugOnly;
|
||||||
|
|
||||||
namespace mozilla {
|
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)
|
AutoJSContext::AutoJSContext(MOZ_GUARD_OBJECT_NOTIFIER_ONLY_PARAM_IN_IMPL)
|
||||||
: mCx(nullptr)
|
: mCx(nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,39 +9,13 @@
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "mozilla/Maybe.h"
|
#include "mozilla/Maybe.h"
|
||||||
|
#include "mozilla/dom/ScriptSettings.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
|
||||||
class nsIScriptContext;
|
class nsIScriptContext;
|
||||||
|
|
||||||
namespace mozilla {
|
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
|
* 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
|
* 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);
|
void Init(bool aSafe MOZ_GUARD_OBJECT_NOTIFIER_PARAM);
|
||||||
|
|
||||||
JSContext* mCx;
|
JSContext* mCx;
|
||||||
Maybe<AutoCxPusher> mPusher;
|
Maybe<mozilla::dom::danger::AutoCxPusher> mPusher;
|
||||||
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2863,7 +2863,7 @@ public:
|
||||||
{ return &mStack; }
|
{ return &mStack; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class mozilla::AutoCxPusher;
|
friend class mozilla::dom::danger::AutoCxPusher;
|
||||||
friend bool xpc::PushJSContextNoScriptContext(JSContext *aCx);;
|
friend bool xpc::PushJSContextNoScriptContext(JSContext *aCx);;
|
||||||
friend void xpc::PopJSContextNoScriptContext();
|
friend void xpc::PopJSContextNoScriptContext();
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче