Bug 575795 - Clean up the nsIScriptContext interface to the global object to be able to split the work that nsIScriptContext::InitContext does out. r=jst

This commit is contained in:
Blake Kaplan 2010-07-15 15:16:29 -07:00
parent e246dfb71d
commit 44fa338e2b
6 changed files with 108 additions and 120 deletions

View File

@ -263,7 +263,7 @@ nsXBLDocGlobalObject::SetContext(nsIScriptContext *aScriptContext)
// hook up to the existing nsIScriptGlobalObject global setup by
// nsGlobalWindow.
nsresult rv;
rv = aScriptContext->InitContext(nsnull);
rv = aScriptContext->InitContext();
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "Script Language's InitContext failed");
aScriptContext->SetGCOnDestruction(PR_FALSE);
aScriptContext->DidInitializeContext();

View File

@ -684,7 +684,7 @@ nsXULPDGlobalObject::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScrip
aScriptContext->WillInitializeContext();
// NOTE: We init this context with a NULL global - this is subtly
// different than nsGlobalWindow which passes 'this'
rv = aScriptContext->InitContext(nsnull);
rv = aScriptContext->InitContext();
NS_ENSURE_SUCCESS(rv, rv);
}

View File

@ -1285,22 +1285,15 @@ nsGlobalWindow::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptCont
"We don't support this language ID");
NS_ASSERTION(IsOuterWindow(), "Uh, SetScriptContext() called on inner window!");
if (!aScriptContext) {
NS_WARNING("Possibly early removal of script object, see bug #41608");
} else {
NS_ASSERTION(!aScriptContext || !mContext, "Bad call to SetContext()!");
if (aScriptContext) {
// should probably assert the context is clean???
aScriptContext->WillInitializeContext();
// Bind the script context and the global object
nsresult rv = aScriptContext->InitContext(this);
nsresult rv = aScriptContext->InitContext();
NS_ENSURE_SUCCESS(rv, rv);
}
NS_ASSERTION(!aScriptContext || !mContext, "Bad call to SetContext()!");
void *script_glob = nsnull;
if (aScriptContext) {
if (IsFrame()) {
// This window is a [i]frame, don't bother GC'ing when the
// frame's context is destroyed since a GC will happen when the
@ -1309,13 +1302,12 @@ nsGlobalWindow::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptCont
aScriptContext->SetGCOnDestruction(PR_FALSE);
}
aScriptContext->CreateOuterObject(this);
aScriptContext->DidInitializeContext();
script_glob = aScriptContext->GetNativeGlobal();
NS_ASSERTION(script_glob, "GetNativeGlobal returned NULL!");
mJSObject = (JSObject *)aScriptContext->GetNativeGlobal();
}
mContext = aScriptContext;
mJSObject = (JSObject *)script_glob;
return NS_OK;
}
@ -1329,7 +1321,8 @@ nsGlobalWindow::EnsureScriptEnvironment(PRUint32 aLangID)
if (mJSObject)
return NS_OK;
NS_ASSERTION(!GetCurrentInnerWindowInternal(), "Huh?");
NS_ASSERTION(!GetCurrentInnerWindowInternal(),
"mJSObject is null, but we have an inner window?");
nsCOMPtr<nsIScriptRuntime> scriptRuntime;
nsresult rv = NS_GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRuntime));
@ -1894,13 +1887,11 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// ensure that the outer window gets a new prototype so we don't
// leak prototype properties from the old inner window to the
// new one.
JS_BeginRequest((JSContext *)mContext->GetNativeContext());
mContext->InitContext(this);
mContext->InitOuterWindow();
// Now that both the the inner and outer windows are initialized
// let the script context do its magic to hook them together.
mContext->ConnectToInner(newInnerWindow, mJSObject);
JS_EndRequest((JSContext *)mContext->GetNativeContext());
nsCOMPtr<nsIContent> frame = do_QueryInterface(GetFrameElementInternal());
if (frame && frame->GetOwnerDoc()) {
@ -1985,7 +1976,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
// make sure the cached document property gets updated.
// XXXmarkh - tell other languages about this?
JSAutoRequest ar(cx);
::JS_DeleteProperty(cx, currentInner->mJSObject, "document");
}
} else {
@ -1998,7 +1988,6 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
if (navigatorHolder) {
// Restore window.navigator onto the new inner window.
JSAutoRequest ar(cx);
::JS_DefineProperty(cx, newInnerWindow->mJSObject, "navigator",
nav, nsnull, nsnull,

View File

@ -72,10 +72,10 @@ public:
NS_DEFINE_STATIC_IID_ACCESSOR(nsIScriptContextPrincipal,
NS_ISCRIPTCONTEXTPRINCIPAL_IID)
// A4FE2B52-62B5-40C3-BF9C-5E0A27B10F90
// 5a5d683e-f387-4694-9ff0-3a90b3e6749e
#define NS_ISCRIPTCONTEXT_IID \
{ 0xA4FE2B52, 0x62B5, 0x40C3, \
{ 0xBF, 0x9C, 0x5E, 0x0A, 0x27, 0xB1, 0x0F, 0x90 } }
{ 0x5a5d683e, 0xf387, 0x4694, \
{ 0x9f, 0xf0, 0x3a, 0x90, 0xb3, 0xe6, 0x74, 0x9e } }
/* This MUST match JSVERSION_DEFAULT. This version stuff if we don't
know what language we have is a little silly... */
@ -333,17 +333,22 @@ public:
/**
* Init this context ready for use. If aGlobalObject is not NULL, this
* function may initialize based on this global (for example, using the
* global to locate a chrome window, create a new 'scope' for this
* global, etc)
*
* @param aGlobalObject the gobal object, which may be nsnull.
*
* @return NS_OK if context initialization was successful
*
* Initialize the context generally. Does not create a global object.
**/
virtual nsresult InitContext(nsIScriptGlobalObject *aGlobalObject) = 0;
virtual nsresult InitContext() = 0;
/**
* Creates the outer window for this context.
*
* @param aGlobalObject The script global object to use as our global.
*/
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject) = 0;
/**
* Prepares this context for use with the current inner window for the
* context's global object. This must be called after InitOuterWindow.
*/
virtual nsresult InitOuterWindow() = 0;
/**
* Check to see if context is as yet intialized. Used to prevent

View File

@ -2574,7 +2574,7 @@ nsJSContext::GetNativeContext()
}
nsresult
nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject)
nsJSContext::InitContext()
{
// Make sure callers of this use
// WillInitializeContext/DidInitializeContext around this call.
@ -2585,105 +2585,97 @@ nsJSContext::InitContext(nsIScriptGlobalObject *aGlobalObject)
::JS_SetErrorReporter(mContext, NS_ScriptErrorReporter);
if (!aGlobalObject) {
// If we don't get a global object then there's nothing more to do here.
return NS_OK;
nsIXPConnect *xpc = nsContentUtils::XPConnect();
if (!nsDOMClassInfo::GetXPCNativeWrapperGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetNativeWrapperGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXPCNativeWrapperGetPropertyOp(getProperty);
}
nsCxPusher cxPusher;
if (!cxPusher.Push(mContext)) {
return NS_ERROR_FAILURE;
if (!nsDOMClassInfo::GetXrayWrapperPropertyHolderGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetXrayWrapperPropertyHolderGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXrayWrapperPropertyHolderGetPropertyOp(getProperty);
}
return NS_OK;
}
nsresult
nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject)
{
NS_PRECONDITION(!JS_GetGlobalObject(mContext),
"Outer window already initialized");
nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aGlobalObject));
PRUint32 flags = 0;
if (chromeWindow) {
// Flag this window's global object and objects under it as "system",
// for optional automated XPCNativeWrapper construction when chrome JS
// views a content DOM.
flags = nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
// Always enable E4X for XUL and other chrome content -- there is no
// need to preserve the <!-- script hiding hack from JS-in-HTML daze
// (introduced in 1995 for graceful script degradation in Netscape 1,
// Mosaic, and other pre-JS browsers).
::JS_SetOptions(mContext, ::JS_GetOptions(mContext) | JSOPTION_XML);
}
nsIXPConnect *xpc = nsContentUtils::XPConnect();
JSObject *global = ::JS_GetGlobalObject(mContext);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
// If there's already a global object in mContext we won't tell
// XPConnect to wrap aGlobalObject since it's already wrapped.
nsresult rv;
if (!global) {
nsCOMPtr<nsIDOMChromeWindow> chromeWindow(do_QueryInterface(aGlobalObject));
PRUint32 flags = 0;
if (chromeWindow) {
// Flag this window's global object and objects under it as "system",
// for optional automated XPCNativeWrapper construction when chrome JS
// views a content DOM.
flags = nsIXPConnect::FLAG_SYSTEM_GLOBAL_OBJECT;
// Always enable E4X for XUL and other chrome content -- there is no
// need to preserve the <!-- script hiding hack from JS-in-HTML daze
// (introduced in 1995 for graceful script degradation in Netscape 1,
// Mosaic, and other pre-JS browsers).
::JS_SetOptions(mContext, ::JS_GetOptions(mContext) | JSOPTION_XML);
}
rv = xpc->InitClassesWithNewWrappedGlobal(mContext, aGlobalObject,
NS_GET_IID(nsISupports),
flags,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Now check whether we need to grab a pointer to the
// XPCNativeWrapper and XrayWrapperPropertyHolder getProperty ops.
if (!nsDOMClassInfo::GetXPCNativeWrapperGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetNativeWrapperGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXPCNativeWrapperGetPropertyOp(getProperty);
}
if (!nsDOMClassInfo::GetXrayWrapperPropertyHolderGetPropertyOp()) {
JSPropertyOp getProperty;
xpc->GetXrayWrapperPropertyHolderGetPropertyOp(&getProperty);
nsDOMClassInfo::SetXrayWrapperPropertyHolderGetPropertyOp(getProperty);
}
} else {
// There's already a global object. We are preparing this outer window
// object for use as a real outer window (i.e. everything needs to live on
// the inner window).
// Call ClearScope to nuke any properties (e.g. Function and Object) on the
// outer object. From now on, anybody asking the outer object for these
// properties will be forwarded to the inner window.
::JS_ClearScope(mContext, global);
// Now that the inner and outer windows are connected, tell XPConnect to
// re-initialize the prototypes on the outer window's scope.
rv = xpc->InitClassesForOuterObject(mContext, global);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(aGlobalObject));
if (ci) {
jsval v;
rv = nsContentUtils::WrapNative(mContext, global, aGlobalObject, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
rv = wrapper->RefreshPrototype();
NS_ENSURE_SUCCESS(rv, rv);
}
}
nsresult rv =
xpc->InitClassesWithNewWrappedGlobal(mContext, aGlobalObject,
NS_GET_IID(nsISupports),
flags, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
// Hold a strong reference to the wrapper for the global to avoid
// rooting and unrooting the global object every time its AddRef()
// or Release() methods are called
mGlobalWrapperRef = holder;
return NS_OK;
}
holder->GetJSObject(&global);
nsresult
nsJSContext::InitOuterWindow()
{
JSObject *global = JS_GetGlobalObject(mContext);
nsIScriptGlobalObject *sgo = GetGlobalObject();
// Call ClearScope to nuke any properties (e.g. Function and Object) on the
// outer object. From now on, anybody asking the outer object for these
// properties will be forwarded to the inner window.
JS_ClearScope(mContext, global);
// Now that the inner and outer windows are connected, tell XPConnect to
// re-initialize the prototypes on the outer window's scope.
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsresult rv = xpc->InitClassesForOuterObject(mContext, global);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIClassInfo> ci(do_QueryInterface(sgo));
if (ci) {
jsval v;
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = nsContentUtils::WrapNative(mContext, global, sgo, &v,
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
rv = wrapper->RefreshPrototype();
NS_ENSURE_SUCCESS(rv, rv);
}
rv = InitClasses(global); // this will complete global object initialization
NS_ENSURE_SUCCESS(rv, rv);
return rv;
return NS_OK;
}
nsresult

View File

@ -139,7 +139,9 @@ public:
nsISupports **aHolder);
virtual nsresult ConnectToInner(nsIScriptGlobalObject *aNewInner,
void *aOuterGlobal);
virtual nsresult InitContext(nsIScriptGlobalObject *aGlobalObject);
virtual nsresult InitContext();
virtual nsresult CreateOuterObject(nsIScriptGlobalObject *aGlobalObject);
virtual nsresult InitOuterWindow();
virtual PRBool IsContextInitialized();
virtual void FinalizeContext();