mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Fix for bug 370265 (nsDOMScriptObjectHolder/NS_DropScriptObject tries to get service while shutting down). r/sr=jst.
This commit is contained in:
parent
e4dac66084
commit
3d6360dc54
@ -52,6 +52,8 @@
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
|
||||
class nsIDOMScriptObjectFactory;
|
||||
class nsIXPConnect;
|
||||
@ -84,7 +86,6 @@ class nsIWordBreaker;
|
||||
class nsIJSRuntimeService;
|
||||
class nsIEventListenerManager;
|
||||
class nsIScriptContext;
|
||||
class nsIScriptGlobalObject;
|
||||
template<class E> class nsCOMArray;
|
||||
class nsIPref;
|
||||
class nsVoidArray;
|
||||
@ -955,6 +956,32 @@ public:
|
||||
*/
|
||||
static void DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent);
|
||||
|
||||
static nsresult HoldScriptObject(PRUint32 aLangID, void *aObject);
|
||||
static nsresult DropScriptObject(PRUint32 aLangID, void *aObject);
|
||||
|
||||
class ScriptObjectHolder
|
||||
{
|
||||
public:
|
||||
ScriptObjectHolder(PRUint32 aLangID) : mLangID(aLangID),
|
||||
mObject(nsnull)
|
||||
{
|
||||
}
|
||||
~ScriptObjectHolder()
|
||||
{
|
||||
DropScriptObject(mLangID, mObject);
|
||||
}
|
||||
nsresult set(void *aObject)
|
||||
{
|
||||
nsresult rv = HoldScriptObject(mLangID, aObject);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mObject = aObject;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
PRUint32 mLangID;
|
||||
void *mObject;
|
||||
};
|
||||
|
||||
private:
|
||||
static nsresult doReparentContentWrapper(nsIContent *aChild,
|
||||
JSContext *cx,
|
||||
@ -965,6 +992,8 @@ private:
|
||||
|
||||
static nsresult EnsureStringBundle(PropertiesFile aFile);
|
||||
|
||||
static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
|
||||
|
||||
static nsIDOMScriptObjectFactory *sDOMScriptObjectFactory;
|
||||
|
||||
static nsIXPConnect *sXPConnect;
|
||||
@ -1006,8 +1035,11 @@ private:
|
||||
// For now, we don't want to automatically clean this up in Shutdown(), since
|
||||
// consumers might unfortunately end up wanting to use it after that
|
||||
static nsIJSRuntimeService* sJSRuntimeService;
|
||||
static JSRuntime* sScriptRuntime;
|
||||
static PRInt32 sScriptRootCount;
|
||||
static JSRuntime* sJSScriptRuntime;
|
||||
static PRInt32 sJSScriptRootCount;
|
||||
|
||||
static nsIScriptRuntime* sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
||||
static PRInt32 sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
||||
|
||||
#ifdef IBMBIDI
|
||||
static nsIBidiKeyboard* sBidiKeyboard;
|
||||
|
@ -173,8 +173,10 @@ nsILineBreaker *nsContentUtils::sLineBreaker;
|
||||
nsIWordBreaker *nsContentUtils::sWordBreaker;
|
||||
nsVoidArray *nsContentUtils::sPtrsToPtrsToRelease;
|
||||
nsIJSRuntimeService *nsContentUtils::sJSRuntimeService;
|
||||
JSRuntime *nsContentUtils::sScriptRuntime;
|
||||
PRInt32 nsContentUtils::sScriptRootCount = 0;
|
||||
JSRuntime *nsContentUtils::sJSScriptRuntime;
|
||||
PRInt32 nsContentUtils::sJSScriptRootCount = 0;
|
||||
nsIScriptRuntime *nsContentUtils::sScriptRuntimes[NS_STID_ARRAY_UBOUND];
|
||||
PRInt32 nsContentUtils::sScriptRootCount[NS_STID_ARRAY_UBOUND];
|
||||
#ifdef IBMBIDI
|
||||
nsIBidiKeyboard *nsContentUtils::sBidiKeyboard = nsnull;
|
||||
#endif
|
||||
@ -223,12 +225,6 @@ EventListenerManagerHashClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
lm->~EventListenerManagerMapEntry();
|
||||
}
|
||||
|
||||
PR_STATIC_CALLBACK(void)
|
||||
NopClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
// static
|
||||
nsresult
|
||||
nsContentUtils::Init()
|
||||
@ -596,18 +592,9 @@ nsContentUtils::Shutdown()
|
||||
nsISupports *
|
||||
nsContentUtils::GetClassInfoInstance(nsDOMClassInfoID aID)
|
||||
{
|
||||
if (!sDOMScriptObjectFactory) {
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
nsIDOMScriptObjectFactory *factory = GetDOMScriptObjectFactory();
|
||||
|
||||
CallGetService(kDOMScriptObjectFactoryCID, &sDOMScriptObjectFactory);
|
||||
|
||||
if (!sDOMScriptObjectFactory) {
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
return sDOMScriptObjectFactory->GetClassInfoInstance(aID);
|
||||
return factory ? factory->GetClassInfoInstance(aID) : nsnull;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -2544,13 +2531,13 @@ nsContentUtils::GetContentPolicy()
|
||||
nsresult
|
||||
nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
|
||||
{
|
||||
if (!sScriptRuntime) {
|
||||
if (!sJSScriptRuntime) {
|
||||
nsresult rv = CallGetService("@mozilla.org/js/xpc/RuntimeService;1",
|
||||
&sJSRuntimeService);
|
||||
NS_ENSURE_TRUE(sJSRuntimeService, rv);
|
||||
|
||||
sJSRuntimeService->GetRuntime(&sScriptRuntime);
|
||||
if (!sScriptRuntime) {
|
||||
sJSRuntimeService->GetRuntime(&sJSScriptRuntime);
|
||||
if (!sJSScriptRuntime) {
|
||||
NS_RELEASE(sJSRuntimeService);
|
||||
NS_WARNING("Unable to get JS runtime from JS runtime service");
|
||||
return NS_ERROR_FAILURE;
|
||||
@ -2558,20 +2545,20 @@ nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
|
||||
}
|
||||
|
||||
PRBool ok;
|
||||
ok = ::JS_AddNamedRootRT(sScriptRuntime, aPtr, aName);
|
||||
ok = ::JS_AddNamedRootRT(sJSScriptRuntime, aPtr, aName);
|
||||
if (!ok) {
|
||||
if (sScriptRootCount == 0) {
|
||||
if (sJSScriptRootCount == 0) {
|
||||
// We just got the runtime... Just null things out, since no
|
||||
// one's expecting us to have a runtime yet
|
||||
NS_RELEASE(sJSRuntimeService);
|
||||
sScriptRuntime = nsnull;
|
||||
sJSScriptRuntime = nsnull;
|
||||
}
|
||||
NS_WARNING("JS_AddNamedRootRT failed");
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// We now have one more root we added to the runtime
|
||||
++sScriptRootCount;
|
||||
++sJSScriptRootCount;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -2580,16 +2567,16 @@ nsContentUtils::AddJSGCRoot(void* aPtr, const char* aName)
|
||||
nsresult
|
||||
nsContentUtils::RemoveJSGCRoot(void* aPtr)
|
||||
{
|
||||
if (!sScriptRuntime) {
|
||||
if (!sJSScriptRuntime) {
|
||||
NS_NOTREACHED("Trying to remove a JS GC root when none were added");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
::JS_RemoveRootRT(sScriptRuntime, aPtr);
|
||||
::JS_RemoveRootRT(sJSScriptRuntime, aPtr);
|
||||
|
||||
if (--sScriptRootCount == 0) {
|
||||
if (--sJSScriptRootCount == 0) {
|
||||
NS_RELEASE(sJSRuntimeService);
|
||||
sScriptRuntime = nsnull;
|
||||
sJSScriptRuntime = nsnull;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -3393,3 +3380,56 @@ nsContentUtils::DestroyAnonymousContent(nsCOMPtr<nsIContent>* aContent)
|
||||
*aContent = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsIDOMScriptObjectFactory*
|
||||
nsContentUtils::GetDOMScriptObjectFactory()
|
||||
{
|
||||
if (!sDOMScriptObjectFactory) {
|
||||
static NS_DEFINE_CID(kDOMScriptObjectFactoryCID,
|
||||
NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
CallGetService(kDOMScriptObjectFactoryCID, &sDOMScriptObjectFactory);
|
||||
}
|
||||
|
||||
return sDOMScriptObjectFactory;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::HoldScriptObject(PRUint32 aLangID, void *aObject)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
||||
nsIScriptRuntime *runtime = sScriptRuntimes[langIndex];
|
||||
if (!runtime) {
|
||||
nsIDOMScriptObjectFactory *factory = GetDOMScriptObjectFactory();
|
||||
NS_ENSURE_TRUE(factory, NS_ERROR_FAILURE);
|
||||
|
||||
rv = factory->GetScriptRuntimeByID(aLangID, &runtime);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// This makes sScriptRuntimes hold a strong ref.
|
||||
sScriptRuntimes[langIndex] = runtime;
|
||||
}
|
||||
|
||||
rv = runtime->HoldScriptObject(aObject);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
++sScriptRootCount[langIndex];
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
nsContentUtils::DropScriptObject(PRUint32 aLangID, void *aObject)
|
||||
{
|
||||
PRUint32 langIndex = NS_STID_INDEX(aLangID);
|
||||
nsresult rv = sScriptRuntimes[langIndex]->DropScriptObject(aObject);
|
||||
if (--sScriptRootCount[langIndex] == 0) {
|
||||
NS_RELEASE(sScriptRuntimes[langIndex]);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
@ -817,11 +817,12 @@ nsScriptEventHandlerOwnerTearoff::CompileEventHandler(
|
||||
if (attr) {
|
||||
XUL_PROTOTYPE_ATTRIBUTE_METER(gNumCacheFills);
|
||||
// take a copy of the event handler, and tell the language about it.
|
||||
attr->mEventHandler = (void *)aHandler;
|
||||
if (attr->mEventHandler) {
|
||||
rv = aContext->HoldScriptObject(attr->mEventHandler);
|
||||
if (aHandler) {
|
||||
rv = nsContentUtils::HoldScriptObject(aContext->GetScriptTypeID(),
|
||||
aHandler);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
}
|
||||
attr->mEventHandler = (void *)aHandler;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
@ -2474,7 +2475,7 @@ void
|
||||
nsXULPrototypeAttribute::Finalize(PRUint32 aLangID)
|
||||
{
|
||||
if (mEventHandler) {
|
||||
if (NS_FAILED(NS_DropScriptObject(aLangID, mEventHandler)))
|
||||
if (NS_FAILED(nsContentUtils::DropScriptObject(aLangID, mEventHandler)))
|
||||
NS_ERROR("Failed to drop script object");
|
||||
mEventHandler = nsnull;
|
||||
}
|
||||
@ -2543,7 +2544,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
|
||||
rv |= aStream->Write32(child->mType);
|
||||
nsXULPrototypeScript* script = NS_STATIC_CAST(nsXULPrototypeScript*, child);
|
||||
|
||||
rv |= aStream->Write32(script->mScriptObject.getScriptTypeID());
|
||||
rv |= aStream->Write32(script->mScriptObject.mLangID);
|
||||
|
||||
rv |= aStream->Write8(script->mOutOfLine);
|
||||
if (! script->mOutOfLine) {
|
||||
@ -2553,7 +2554,7 @@ nsXULPrototypeElement::Serialize(nsIObjectOutputStream* aStream,
|
||||
NS_GET_IID(nsIURI),
|
||||
PR_TRUE);
|
||||
|
||||
if (script->mScriptObject) {
|
||||
if (script->mScriptObject.mObject) {
|
||||
// This may return NS_OK without muxing script->mSrcURI's
|
||||
// data into the FastLoad file, in the case where that
|
||||
// muxed document is already there (written by a prior
|
||||
@ -2766,7 +2767,7 @@ nsXULPrototypeScript::nsXULPrototypeScript(PRUint32 aLangID, PRUint32 aLineNo, P
|
||||
mOutOfLine(PR_TRUE),
|
||||
mSrcLoadWaiters(nsnull),
|
||||
mLangVersion(aVersion),
|
||||
mScriptObject(aLangID, nsnull)
|
||||
mScriptObject(aLangID)
|
||||
{
|
||||
NS_LOG_ADDREF(this, 1, ClassName(), ClassSize());
|
||||
NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
|
||||
@ -2784,10 +2785,11 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
|
||||
const nsCOMArray<nsINodeInfo> *aNodeInfos)
|
||||
{
|
||||
nsIScriptContext *context = aGlobal->GetScriptContext(
|
||||
mScriptObject.getScriptTypeID());
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mScriptObject,
|
||||
mScriptObject.mLangID);
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull ||
|
||||
!mScriptObject.mObject,
|
||||
"script source still loading when serializing?!");
|
||||
if (!mScriptObject)
|
||||
if (!mScriptObject.mObject)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Write basic prototype data
|
||||
@ -2797,7 +2799,7 @@ nsXULPrototypeScript::Serialize(nsIObjectOutputStream* aStream,
|
||||
rv = aStream->Write32(mLangVersion);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
// And delegate the writing to the nsIScriptContext
|
||||
rv = context->Serialize(aStream, mScriptObject);
|
||||
rv = context->Serialize(aStream, mScriptObject.mObject);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
return NS_OK;
|
||||
@ -2878,7 +2880,8 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
|
||||
NS_TIMELINE_MARK_FUNCTION("chrome script deserialize");
|
||||
nsresult rv;
|
||||
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull || !mScriptObject,
|
||||
NS_ASSERTION(!mSrcLoading || mSrcLoadWaiters != nsnull ||
|
||||
!mScriptObject.mObject,
|
||||
"prototype script not well-initialized when deserializing?!");
|
||||
|
||||
// Read basic prototype data
|
||||
@ -2886,7 +2889,7 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
|
||||
aStream->Read32(&mLangVersion);
|
||||
|
||||
nsIScriptContext *context = aGlobal->GetScriptContext(
|
||||
mScriptObject.getScriptTypeID());
|
||||
mScriptObject.mLangID);
|
||||
NS_ASSERTION(context != nsnull, "Have no context for deserialization");
|
||||
NS_ENSURE_TRUE(context, NS_ERROR_UNEXPECTED);
|
||||
nsScriptObjectHolder newScriptObject(context);
|
||||
@ -2895,7 +2898,7 @@ nsXULPrototypeScript::Deserialize(nsIObjectInputStream* aStream,
|
||||
NS_WARNING("Language deseralization failed");
|
||||
return rv;
|
||||
}
|
||||
mScriptObject = newScriptObject;
|
||||
mScriptObject.set(newScriptObject);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2946,7 +2949,7 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
// ctor and not setting it until the scriptObject is set -
|
||||
// code that pre-fetches these globals will then start
|
||||
// asserting.)
|
||||
if (mScriptObject.getScriptTypeID() != newLangID) {
|
||||
if (mScriptObject.mLangID != newLangID) {
|
||||
NS_ERROR("XUL cache gave different language?");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
@ -2955,7 +2958,7 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
}
|
||||
}
|
||||
|
||||
if (! mScriptObject) {
|
||||
if (! mScriptObject.mObject) {
|
||||
nsCOMPtr<nsIURI> oldURI;
|
||||
|
||||
if (mSrcURI) {
|
||||
@ -3003,8 +3006,8 @@ nsXULPrototypeScript::DeserializeOutOfLine(nsIObjectInputStream* aInput,
|
||||
mSrcURI->SchemeIs("chrome", &isChrome);
|
||||
if (isChrome) {
|
||||
cache->PutScript(mSrcURI,
|
||||
mScriptObject.getScriptTypeID(),
|
||||
mScriptObject);
|
||||
mScriptObject.mLangID,
|
||||
mScriptObject.mObject);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -3050,7 +3053,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
||||
if (! global)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
context = global->GetScriptContext(mScriptObject.getScriptTypeID());
|
||||
context = global->GetScriptContext(mScriptObject.mLangID);
|
||||
NS_ASSERTION(context != nsnull, "no context for script global");
|
||||
if (! context)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
@ -3076,7 +3079,7 @@ nsXULPrototypeScript::Compile(const PRUnichar* aText,
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
|
||||
mScriptObject = newScriptObject;
|
||||
mScriptObject.set(newScriptObject);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ public:
|
||||
PRPackedBool mOutOfLine;
|
||||
nsXULDocument* mSrcLoadWaiters; // [OWNER] but not COMPtr
|
||||
PRUint32 mLangVersion;
|
||||
nsScriptObjectHolder mScriptObject;
|
||||
nsContentUtils::ScriptObjectHolder mScriptObject;
|
||||
|
||||
static void ReleaseGlobals()
|
||||
{
|
||||
|
@ -324,7 +324,7 @@ XULContentSinkImpl::ContextStack::GetTopNodeScriptType(PRUint32 *aScriptType)
|
||||
case nsXULPrototypeNode::eType_Script: {
|
||||
nsXULPrototypeScript *parent = \
|
||||
NS_REINTERPRET_CAST(nsXULPrototypeScript*, node);
|
||||
*aScriptType = parent->mScriptObject.getScriptTypeID();
|
||||
*aScriptType = parent->mScriptObject.mLangID;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -782,7 +782,7 @@ XULContentSinkImpl::HandleEndElement(const PRUnichar *aName)
|
||||
NS_STATIC_CAST(nsXULPrototypeScript*, node);
|
||||
|
||||
// If given a src= attribute, we must ignore script tag content.
|
||||
if (! script->mSrcURI && ! script->mScriptObject) {
|
||||
if (! script->mSrcURI && ! script->mScriptObject.mObject) {
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
|
||||
script->mOutOfLine = PR_FALSE;
|
||||
|
@ -2916,7 +2916,7 @@ nsXULDocument::ResumeWalk()
|
||||
if (NS_SUCCEEDED(rv) && blocked)
|
||||
return NS_OK;
|
||||
}
|
||||
else if (scriptproto->mScriptObject) {
|
||||
else if (scriptproto->mScriptObject.mObject) {
|
||||
// An inline script
|
||||
rv = ExecuteScript(scriptproto);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
@ -3198,7 +3198,7 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, PRBool* aBlock)
|
||||
// Load a transcluded script
|
||||
nsresult rv;
|
||||
|
||||
if (aScriptProto->mScriptObject) {
|
||||
if (aScriptProto->mScriptObject.mObject) {
|
||||
rv = ExecuteScript(aScriptProto);
|
||||
|
||||
// Ignore return value from execution, and don't block
|
||||
@ -3221,14 +3221,14 @@ nsXULDocument::LoadScript(nsXULPrototypeScript* aScriptProto, PRBool* aBlock)
|
||||
if (newScriptObject) {
|
||||
// The script language for a proto must remain constant - we
|
||||
// can't just change it for this unexpected language.
|
||||
if (aScriptProto->mScriptObject.getScriptTypeID() != fetchedLang) {
|
||||
if (aScriptProto->mScriptObject.mLangID != fetchedLang) {
|
||||
NS_ERROR("XUL cache gave me an incorrect script language");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
aScriptProto->mScriptObject.set(newScriptObject);
|
||||
}
|
||||
|
||||
if (aScriptProto->mScriptObject) {
|
||||
if (aScriptProto->mScriptObject.mObject) {
|
||||
rv = ExecuteScript(aScriptProto);
|
||||
|
||||
// Ignore return value from execution, and don't block
|
||||
@ -3366,8 +3366,8 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
|
||||
if (useXULCache && IsChromeURI(mDocumentURI)) {
|
||||
gXULCache->PutScript(scriptProto->mSrcURI,
|
||||
scriptProto->mScriptObject.getScriptTypeID(),
|
||||
scriptProto->mScriptObject);
|
||||
scriptProto->mScriptObject.mLangID,
|
||||
scriptProto->mScriptObject.mObject);
|
||||
}
|
||||
|
||||
if (mIsWritingFastLoad && mCurrentPrototype != mMasterPrototype) {
|
||||
@ -3387,7 +3387,7 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
|
||||
NS_ASSERTION(global != nsnull, "master prototype w/o global?!");
|
||||
if (global) {
|
||||
PRUint32 stid = scriptProto->mScriptObject.getScriptTypeID();
|
||||
PRUint32 stid = scriptProto->mScriptObject.mLangID;
|
||||
nsIScriptContext *scriptContext = \
|
||||
global->GetScriptContext(stid);
|
||||
NS_ASSERTION(scriptContext != nsnull,
|
||||
@ -3419,7 +3419,7 @@ nsXULDocument::OnStreamComplete(nsIStreamLoader* aLoader,
|
||||
doc->mNextSrcLoadWaiter = nsnull;
|
||||
|
||||
// Execute only if we loaded and compiled successfully, then resume
|
||||
if (NS_SUCCEEDED(aStatus) && scriptProto->mScriptObject) {
|
||||
if (NS_SUCCEEDED(aStatus) && scriptProto->mScriptObject.mObject) {
|
||||
doc->ExecuteScript(scriptProto);
|
||||
}
|
||||
doc->ResumeWalk();
|
||||
@ -3456,7 +3456,7 @@ nsXULDocument::ExecuteScript(nsXULPrototypeScript *aScript)
|
||||
NS_PRECONDITION(aScript != nsnull, "null ptr");
|
||||
NS_ENSURE_TRUE(aScript, NS_ERROR_NULL_POINTER);
|
||||
NS_ENSURE_TRUE(mScriptGlobalObject, NS_ERROR_NOT_INITIALIZED);
|
||||
PRUint32 stid = aScript->mScriptObject.getScriptTypeID();
|
||||
PRUint32 stid = aScript->mScriptObject.mLangID;
|
||||
|
||||
nsresult rv;
|
||||
rv = mScriptGlobalObject->EnsureScriptEnvironment(stid);
|
||||
@ -3467,8 +3467,8 @@ nsXULDocument::ExecuteScript(nsXULPrototypeScript *aScript)
|
||||
// failure getting a script context is fatal.
|
||||
NS_ENSURE_TRUE(context != nsnull, NS_ERROR_UNEXPECTED);
|
||||
|
||||
if (aScript->mScriptObject)
|
||||
rv = ExecuteScript(context, aScript->mScriptObject);
|
||||
if (aScript->mScriptObject.mObject)
|
||||
rv = ExecuteScript(context, aScript->mScriptObject.mObject);
|
||||
else
|
||||
rv = NS_ERROR_UNEXPECTED;
|
||||
return rv;
|
||||
|
@ -39,48 +39,9 @@
|
||||
#ifndef nsDOMScriptObjectHolder_h__
|
||||
#define nsDOMScriptObjectHolder_h__
|
||||
|
||||
#include "nsIScriptRuntime.h"
|
||||
#include "nsIScriptContext.h"
|
||||
#include "nsIDOMScriptObjectFactory.h"
|
||||
|
||||
class nsIScriptContext;
|
||||
|
||||
// Drop a reference to a script object when all you have is the script
|
||||
// language ID.
|
||||
inline nsresult NS_DropScriptObject(PRUint32 aLangID, void *aThing)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> scriptRT;
|
||||
NS_DEFINE_CID(cid, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(cid, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = factory->GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRT));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = scriptRT->DropScriptObject(aThing);
|
||||
if (NS_FAILED(rv))
|
||||
NS_ERROR("Failed to drop the script object");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// Hold a reference to a script object when all you have is the script
|
||||
// language ID, and you need to take a copy of the void script object.
|
||||
// Must be matched by an NS_DropScriptObject
|
||||
inline nsresult NS_HoldScriptObject(PRUint32 aLangID, void *aThing)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIScriptRuntime> scriptRT;
|
||||
NS_DEFINE_CID(cid, NS_DOM_SCRIPT_OBJECT_FACTORY_CID);
|
||||
|
||||
nsCOMPtr<nsIDOMScriptObjectFactory> factory = do_GetService(cid, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = factory->GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRT));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = scriptRT->HoldScriptObject(aThing);
|
||||
if (NS_FAILED(rv))
|
||||
NS_ERROR("Failed to hold the script object");
|
||||
return rv;
|
||||
}
|
||||
|
||||
// A thin class used to help with script object memory management. No virtual
|
||||
// functions and a fully inline implementation should keep the cost down.
|
||||
// [Note that a fully inline implementation is necessary for use by other
|
||||
@ -90,59 +51,23 @@ public:
|
||||
// A constructor that will cause a reference to |ctx| to be stored in
|
||||
// the object. Only use for short-lived object holders.
|
||||
nsScriptObjectHolder(nsIScriptContext *ctx, void *aObject = nsnull) :
|
||||
mObject(aObject), mContextOrLangID(NS_REINTERPRET_CAST(PtrBits, ctx)) {
|
||||
mObject(aObject), mContext(ctx) {
|
||||
NS_ASSERTION(ctx, "Must provide a valid context");
|
||||
NS_ADDREF(ctx);
|
||||
}
|
||||
|
||||
// A constructor that stores only the integer language ID - freeing the
|
||||
// script object is slower in this case, but is safe for long-lived
|
||||
// object holders.
|
||||
nsScriptObjectHolder(PRUint32 aLangID, void *aObject = nsnull) :
|
||||
mObject(aObject),
|
||||
mContextOrLangID((aLangID << 1) | SOH_HAS_LANGID_BIT) {
|
||||
NS_ASSERTION(aLangID != nsIProgrammingLanguage::UNKNOWN,
|
||||
"Please supply a valid language ID");
|
||||
}
|
||||
|
||||
// copy constructor
|
||||
nsScriptObjectHolder(const nsScriptObjectHolder& other) :
|
||||
mObject(other.mObject),
|
||||
mContextOrLangID(other.mContextOrLangID)
|
||||
mContext(other.mContext)
|
||||
{
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
if (mObject) {
|
||||
NS_HoldScriptObject(getScriptTypeIDFromBits(), mObject);
|
||||
}
|
||||
} else {
|
||||
// New hold the script object and new reference on the script context.
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "Lost context pointer?");
|
||||
NS_ADDREF(ctx);
|
||||
if (mObject)
|
||||
ctx->HoldScriptObject(mObject);
|
||||
}
|
||||
// New hold the script object and new reference on the script context.
|
||||
if (mObject)
|
||||
mContext->HoldScriptObject(mObject);
|
||||
}
|
||||
|
||||
~nsScriptObjectHolder() {
|
||||
// If we have a language ID, then we only need to NS_DropScriptObject if
|
||||
// we are holding a script object.
|
||||
// If we have a script context, we must always release our reference to it,
|
||||
// even if we are not holding a script object.
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
if (mObject) {
|
||||
NS_DropScriptObject(getScriptTypeIDFromBits(), mObject);
|
||||
}
|
||||
} else {
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "Lost context pointer?");
|
||||
if (mObject) {
|
||||
ctx->DropScriptObject(mObject);
|
||||
}
|
||||
NS_IF_RELEASE(ctx);
|
||||
}
|
||||
if (mObject)
|
||||
mContext->DropScriptObject(mObject);
|
||||
}
|
||||
|
||||
// misc operators
|
||||
@ -157,19 +82,11 @@ public:
|
||||
return mObject;
|
||||
}
|
||||
|
||||
// Drop the script object - but *not* the nsIScriptContext nor the language
|
||||
// ID.
|
||||
// Drop the script object - but *not* the nsIScriptContext.
|
||||
nsresult drop() {
|
||||
nsresult rv = NS_OK;
|
||||
if (mObject) {
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
rv = NS_DropScriptObject(getScriptTypeIDFromBits(), mObject);
|
||||
} else {
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "Lost ctx pointer!");
|
||||
rv = ctx->DropScriptObject(mObject);
|
||||
}
|
||||
rv = mContext->DropScriptObject(mObject);
|
||||
mObject = nsnull;
|
||||
}
|
||||
return rv;
|
||||
@ -181,13 +98,7 @@ public:
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
if (object) {
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
rv = NS_HoldScriptObject(getScriptTypeIDFromBits(), object);
|
||||
} else {
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
rv = ctx->HoldScriptObject(object);
|
||||
}
|
||||
rv = mContext->HoldScriptObject(object);
|
||||
// don't store the pointer if we failed to lock it.
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mObject = object;
|
||||
@ -205,27 +116,11 @@ public:
|
||||
}
|
||||
// Get the language ID.
|
||||
PRUint32 getScriptTypeID() const {
|
||||
if (mContextOrLangID & SOH_HAS_LANGID_BIT) {
|
||||
return getScriptTypeIDFromBits();
|
||||
}
|
||||
nsIScriptContext *ctx = NS_REINTERPRET_CAST(nsIScriptContext *,
|
||||
mContextOrLangID);
|
||||
NS_ASSERTION(ctx, "How did I lose my pointer?");
|
||||
return ctx->GetScriptTypeID();
|
||||
return mContext->GetScriptTypeID();
|
||||
}
|
||||
protected:
|
||||
PRUint32 getScriptTypeIDFromBits() const {
|
||||
NS_ASSERTION(mContextOrLangID & SOH_HAS_LANGID_BIT, "Not in the bits!");
|
||||
return (mContextOrLangID & ~SOH_HAS_LANGID_BIT) >> 1;
|
||||
}
|
||||
void *mObject;
|
||||
// We store either an nsIScriptContext* if this bit is clear,
|
||||
// else the language ID (specifically, ((lang_id << 1) | SOH_HAS_LANGID_BIT)
|
||||
// when set.
|
||||
typedef PRWord PtrBits;
|
||||
enum { SOH_HAS_LANGID_BIT = 0x1 };
|
||||
|
||||
PtrBits mContextOrLangID;
|
||||
nsCOMPtr<nsIScriptContext> mContext;
|
||||
};
|
||||
|
||||
#endif // nsDOMScriptObjectHolder_h__
|
||||
|
Loading…
Reference in New Issue
Block a user