mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 971673: Replace ScriptSettingsStack's array with a C++-stack-allocated linked list. r=bholley
This commit is contained in:
parent
6635575960
commit
b546e7c699
@ -20,65 +20,51 @@
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ScriptSettingsStack;
|
||||
static mozilla::ThreadLocal<ScriptSettingsStack*> sScriptSettingsTLS;
|
||||
|
||||
ScriptSettingsStackEntry ScriptSettingsStackEntry::NoJSAPISingleton;
|
||||
static mozilla::ThreadLocal<ScriptSettingsStackEntry*> sScriptSettingsTLS;
|
||||
|
||||
class ScriptSettingsStack {
|
||||
public:
|
||||
static ScriptSettingsStack& Ref() {
|
||||
return *sScriptSettingsTLS.get();
|
||||
}
|
||||
ScriptSettingsStack() {};
|
||||
|
||||
void Push(ScriptSettingsStackEntry* aSettings) {
|
||||
// The bottom-most entry must always be a candidate entry point.
|
||||
MOZ_ASSERT_IF(mStack.Length() == 0 || mStack.LastElement()->NoJSAPI(),
|
||||
aSettings->mIsCandidateEntryPoint);
|
||||
mStack.AppendElement(aSettings);
|
||||
static ScriptSettingsStackEntry* Top() {
|
||||
return sScriptSettingsTLS.get();
|
||||
}
|
||||
|
||||
void PushNoJSAPI() {
|
||||
mStack.AppendElement(&ScriptSettingsStackEntry::NoJSAPISingleton);
|
||||
static void Push(ScriptSettingsStackEntry *aEntry) {
|
||||
MOZ_ASSERT(!aEntry->mOlder);
|
||||
// Whenever JSAPI use is disabled, the next stack entry pushed must
|
||||
// always be a candidate entry point.
|
||||
MOZ_ASSERT_IF(!Top() || Top()->NoJSAPI(), aEntry->mIsCandidateEntryPoint);
|
||||
|
||||
aEntry->mOlder = Top();
|
||||
sScriptSettingsTLS.set(aEntry);
|
||||
}
|
||||
|
||||
void Pop() {
|
||||
MOZ_ASSERT(mStack.Length() > 0);
|
||||
mStack.RemoveElementAt(mStack.Length() - 1);
|
||||
static void Pop(ScriptSettingsStackEntry *aEntry) {
|
||||
MOZ_ASSERT(aEntry == Top());
|
||||
sScriptSettingsTLS.set(aEntry->mOlder);
|
||||
}
|
||||
|
||||
ScriptSettingsStackEntry* Incumbent() {
|
||||
if (!mStack.Length()) {
|
||||
return nullptr;
|
||||
}
|
||||
return mStack.LastElement();
|
||||
}
|
||||
|
||||
nsIGlobalObject* IncumbentGlobal() {
|
||||
ScriptSettingsStackEntry *entry = Incumbent();
|
||||
static nsIGlobalObject* IncumbentGlobal() {
|
||||
ScriptSettingsStackEntry *entry = Top();
|
||||
return entry ? entry->mGlobalObject : nullptr;
|
||||
}
|
||||
|
||||
ScriptSettingsStackEntry* EntryPoint() {
|
||||
if (!mStack.Length())
|
||||
static ScriptSettingsStackEntry* EntryPoint() {
|
||||
ScriptSettingsStackEntry *entry = Top();
|
||||
if (!entry) {
|
||||
return nullptr;
|
||||
for (int i = mStack.Length() - 1; i >= 0; --i) {
|
||||
if (mStack[i]->mIsCandidateEntryPoint) {
|
||||
return mStack[i];
|
||||
}
|
||||
}
|
||||
while (entry) {
|
||||
if (entry->mIsCandidateEntryPoint)
|
||||
return entry;
|
||||
entry = entry->mOlder;
|
||||
}
|
||||
MOZ_CRASH("Non-empty stack should always have an entry point");
|
||||
}
|
||||
|
||||
nsIGlobalObject* EntryGlobal() {
|
||||
static nsIGlobalObject* EntryGlobal() {
|
||||
ScriptSettingsStackEntry *entry = EntryPoint();
|
||||
return entry ? entry->mGlobalObject : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
// These pointers are caller-owned.
|
||||
nsTArray<ScriptSettingsStackEntry*> mStack;
|
||||
};
|
||||
|
||||
void
|
||||
@ -91,16 +77,44 @@ InitScriptSettings()
|
||||
}
|
||||
}
|
||||
|
||||
ScriptSettingsStack* ptr = new ScriptSettingsStack();
|
||||
sScriptSettingsTLS.set(ptr);
|
||||
sScriptSettingsTLS.set(nullptr);
|
||||
}
|
||||
|
||||
void DestroyScriptSettings()
|
||||
{
|
||||
ScriptSettingsStack* ptr = sScriptSettingsTLS.get();
|
||||
MOZ_ASSERT(ptr);
|
||||
sScriptSettingsTLS.set(nullptr);
|
||||
delete ptr;
|
||||
MOZ_ASSERT(sScriptSettingsTLS.get() == nullptr);
|
||||
}
|
||||
|
||||
ScriptSettingsStackEntry::ScriptSettingsStackEntry(nsIGlobalObject *aGlobal,
|
||||
bool aCandidate)
|
||||
: mGlobalObject(aGlobal)
|
||||
, mIsCandidateEntryPoint(aCandidate)
|
||||
, mOlder(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(mGlobalObject);
|
||||
MOZ_ASSERT(mGlobalObject->GetGlobalJSObject(),
|
||||
"Must have an actual JS global for the duration on the stack");
|
||||
MOZ_ASSERT(JS_IsGlobalObject(mGlobalObject->GetGlobalJSObject()),
|
||||
"No outer windows allowed");
|
||||
|
||||
ScriptSettingsStack::Push(this);
|
||||
}
|
||||
|
||||
// This constructor is only for use by AutoNoJSAPI.
|
||||
ScriptSettingsStackEntry::ScriptSettingsStackEntry()
|
||||
: mGlobalObject(nullptr)
|
||||
, mIsCandidateEntryPoint(true)
|
||||
, mOlder(nullptr)
|
||||
{
|
||||
ScriptSettingsStack::Push(this);
|
||||
}
|
||||
|
||||
ScriptSettingsStackEntry::~ScriptSettingsStackEntry()
|
||||
{
|
||||
// We must have an actual JS global for the entire time this is on the stack.
|
||||
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
|
||||
|
||||
ScriptSettingsStack::Pop(this);
|
||||
}
|
||||
|
||||
// This mostly gets the entry global, but doesn't entirely match the spec in
|
||||
@ -115,7 +129,7 @@ BrokenGetEntryGlobal()
|
||||
// must be no entry global on the stack.
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
|
||||
if (!cx) {
|
||||
MOZ_ASSERT(ScriptSettingsStack::Ref().EntryGlobal() == nullptr);
|
||||
MOZ_ASSERT(ScriptSettingsStack::EntryGlobal() == nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -135,7 +149,7 @@ GetIncumbentGlobal()
|
||||
// global either.
|
||||
JSContext *cx = nsContentUtils::GetCurrentJSContextForThread();
|
||||
if (!cx) {
|
||||
MOZ_ASSERT(ScriptSettingsStack::Ref().EntryGlobal() == nullptr);
|
||||
MOZ_ASSERT(ScriptSettingsStack::EntryGlobal() == nullptr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -149,17 +163,17 @@ GetIncumbentGlobal()
|
||||
|
||||
// Ok, nothing from the JS engine. Let's use whatever's on the
|
||||
// explicit stack.
|
||||
return ScriptSettingsStack::Ref().IncumbentGlobal();
|
||||
return ScriptSettingsStack::IncumbentGlobal();
|
||||
}
|
||||
|
||||
nsIPrincipal*
|
||||
GetWebIDLCallerPrincipal()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
ScriptSettingsStackEntry *entry = ScriptSettingsStack::Ref().EntryPoint();
|
||||
ScriptSettingsStackEntry *entry = ScriptSettingsStack::EntryPoint();
|
||||
|
||||
// If we have an entry point that is not the NoJSAPI singleton, we know it
|
||||
// must be an AutoEntryScript.
|
||||
// If we have an entry point that is not NoJSAPI, we know it must be an
|
||||
// AutoEntryScript.
|
||||
if (!entry || entry->NoJSAPI()) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -248,37 +262,21 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject,
|
||||
: AutoJSAPI(aCx ? aCx : FindJSContext(aGlobalObject), aIsMainThread, /* aSkipNullAc = */ true)
|
||||
, ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true)
|
||||
, mAc(cx(), aGlobalObject->GetGlobalJSObject())
|
||||
, mStack(ScriptSettingsStack::Ref())
|
||||
, mWebIDLCallerPrincipal(nullptr)
|
||||
{
|
||||
MOZ_ASSERT(aGlobalObject);
|
||||
MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread.
|
||||
MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject));
|
||||
mStack.Push(this);
|
||||
}
|
||||
|
||||
AutoEntryScript::~AutoEntryScript()
|
||||
{
|
||||
MOZ_ASSERT(mStack.Incumbent() == this);
|
||||
mStack.Pop();
|
||||
}
|
||||
|
||||
AutoIncumbentScript::AutoIncumbentScript(nsIGlobalObject* aGlobalObject)
|
||||
: ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ false)
|
||||
, mStack(ScriptSettingsStack::Ref())
|
||||
, mCallerOverride(nsContentUtils::GetCurrentJSContextForThread())
|
||||
{
|
||||
mStack.Push(this);
|
||||
}
|
||||
|
||||
AutoIncumbentScript::~AutoIncumbentScript()
|
||||
{
|
||||
MOZ_ASSERT(mStack.Incumbent() == this);
|
||||
mStack.Pop();
|
||||
}
|
||||
|
||||
AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThread)
|
||||
: mStack(ScriptSettingsStack::Ref())
|
||||
: ScriptSettingsStackEntry()
|
||||
{
|
||||
MOZ_ASSERT_IF(nsContentUtils::GetCurrentJSContextForThread(),
|
||||
!JS_IsExceptionPending(nsContentUtils::GetCurrentJSContextForThread()));
|
||||
@ -286,12 +284,6 @@ AutoNoJSAPI::AutoNoJSAPI(bool aIsMainThread)
|
||||
mCxPusher.construct(static_cast<JSContext*>(nullptr),
|
||||
/* aAllowNull = */ true);
|
||||
}
|
||||
mStack.PushNoJSAPI();
|
||||
}
|
||||
|
||||
AutoNoJSAPI::~AutoNoJSAPI()
|
||||
{
|
||||
mStack.Pop();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
@ -66,33 +66,25 @@ inline JSObject& IncumbentJSGlobal()
|
||||
}
|
||||
|
||||
class ScriptSettingsStack;
|
||||
struct ScriptSettingsStackEntry {
|
||||
class ScriptSettingsStackEntry {
|
||||
friend class ScriptSettingsStack;
|
||||
|
||||
public:
|
||||
ScriptSettingsStackEntry(nsIGlobalObject *aGlobal, bool aCandidate);
|
||||
~ScriptSettingsStackEntry();
|
||||
|
||||
bool NoJSAPI() { return !mGlobalObject; }
|
||||
|
||||
protected:
|
||||
nsCOMPtr<nsIGlobalObject> mGlobalObject;
|
||||
bool mIsCandidateEntryPoint;
|
||||
|
||||
ScriptSettingsStackEntry(nsIGlobalObject *aGlobal, bool aCandidate)
|
||||
: mGlobalObject(aGlobal)
|
||||
, mIsCandidateEntryPoint(aCandidate)
|
||||
{
|
||||
MOZ_ASSERT(mGlobalObject);
|
||||
MOZ_ASSERT(mGlobalObject->GetGlobalJSObject(),
|
||||
"Must have an actual JS global for the duration on the stack");
|
||||
MOZ_ASSERT(JS_IsGlobalObject(mGlobalObject->GetGlobalJSObject()),
|
||||
"No outer windows allowed");
|
||||
}
|
||||
|
||||
~ScriptSettingsStackEntry() {
|
||||
// We must have an actual JS global for the entire time this is on the stack.
|
||||
MOZ_ASSERT_IF(mGlobalObject, mGlobalObject->GetGlobalJSObject());
|
||||
}
|
||||
|
||||
bool NoJSAPI() { return this == &NoJSAPISingleton; }
|
||||
static ScriptSettingsStackEntry NoJSAPISingleton;
|
||||
|
||||
private:
|
||||
ScriptSettingsStackEntry() : mGlobalObject(nullptr)
|
||||
, mIsCandidateEntryPoint(true)
|
||||
{}
|
||||
// This constructor is only for use by AutoNoJSAPI.
|
||||
friend class AutoNoJSAPI;
|
||||
ScriptSettingsStackEntry();
|
||||
|
||||
ScriptSettingsStackEntry *mOlder;
|
||||
};
|
||||
|
||||
/*
|
||||
@ -172,7 +164,6 @@ public:
|
||||
bool aIsMainThread = NS_IsMainThread(),
|
||||
// Note: aCx is mandatory off-main-thread.
|
||||
JSContext* aCx = nullptr);
|
||||
~AutoEntryScript();
|
||||
|
||||
void SetWebIDLCallerPrincipal(nsIPrincipal *aPrincipal) {
|
||||
mWebIDLCallerPrincipal = aPrincipal;
|
||||
@ -180,7 +171,6 @@ public:
|
||||
|
||||
private:
|
||||
JSAutoCompartment mAc;
|
||||
dom::ScriptSettingsStack& mStack;
|
||||
// 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
|
||||
@ -198,9 +188,7 @@ private:
|
||||
class AutoIncumbentScript : protected ScriptSettingsStackEntry {
|
||||
public:
|
||||
AutoIncumbentScript(nsIGlobalObject* aGlobalObject);
|
||||
~AutoIncumbentScript();
|
||||
private:
|
||||
dom::ScriptSettingsStack& mStack;
|
||||
JS::AutoHideScriptedCaller mCallerOverride;
|
||||
};
|
||||
|
||||
@ -212,12 +200,10 @@ private:
|
||||
*
|
||||
* This class may not be instantiated if an exception is pending.
|
||||
*/
|
||||
class AutoNoJSAPI {
|
||||
class AutoNoJSAPI : protected ScriptSettingsStackEntry {
|
||||
public:
|
||||
AutoNoJSAPI(bool aIsMainThread = NS_IsMainThread());
|
||||
~AutoNoJSAPI();
|
||||
private:
|
||||
dom::ScriptSettingsStack& mStack;
|
||||
mozilla::Maybe<AutoCxPusher> mCxPusher;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user