Bug 612267 - window.__proto__ doesn't correspond to Window.prototype. r=jst

This commit is contained in:
Blake Kaplan 2010-12-10 16:05:20 -08:00
Родитель b57d7c1002
Коммит 297a205814
4 изменённых файлов: 47 добавлений и 40 удалений

Просмотреть файл

@ -2548,37 +2548,14 @@ nsJSContext::ConnectToInner(nsIScriptGlobalObject *aNewInner, void *aOuterGlobal
JSObject *newInnerJSObject = (JSObject *)aNewInner->GetScriptGlobal(JAVASCRIPT);
JSObject *outerGlobal = (JSObject *)aOuterGlobal;
// Make the inner and outer window both share the same
// prototype. The prototype we share is the outer window's
// prototype, this way XPConnect can still find the wrapper to
// use when making a call like alert() (w/o qualifying it with
// "window."). XPConnect looks up the wrapper based on the
// function object's parent, which is the object the function
// was called on, and when calling alert() we'll be calling the
// alert() function from the outer window's prototype off of the
// inner window. In this case XPConnect is able to find the
// outer (through the JSExtendedClass hook outerObject), so this
// prototype sharing works.
// Now that we're connecting the outer global to the inner one,
// we must have transplanted it. The JS engine tries to maintain
// the global object's compartment as its default compartment,
// so update that now since it might have changed.
JS_SetGlobalObject(mContext, outerGlobal);
// We do *not* want to use anything else out of the outer
// object's prototype chain than the first prototype, which is
// the XPConnect prototype. The rest we want from the inner
// window's prototype, i.e. the global scope polluter and
// Object.prototype. This way the outer also gets the benefits
// of the global scope polluter, and the inner window's
// Object.prototype.
JSObject *proto = JS_GetPrototype(mContext, outerGlobal);
JSObject *innerProto = JS_GetPrototype(mContext, newInnerJSObject);
JSObject *innerProtoProto = JS_GetPrototype(mContext, innerProto);
JS_SetPrototype(mContext, newInnerJSObject, proto);
JS_SetPrototype(mContext, proto, innerProtoProto);
NS_ASSERTION(JS_GetPrototype(mContext, outerGlobal) ==
JS_GetPrototype(mContext, newInnerJSObject),
"outer and inner globals should have the same prototype");
return NS_OK;
}
@ -2626,19 +2603,6 @@ nsJSContext::CreateOuterObject(nsIScriptGlobalObject *aGlobalObject,
JS_SetOptions(mContext, JS_GetOptions(mContext) | JSOPTION_XML);
}
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
nsresult rv = xpc->WrapNative(mContext, aCurrentInner->GetGlobalJSObject(),
aCurrentInner, NS_GET_IID(nsISupports),
getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectWrappedNative> wrapper(do_QueryInterface(holder));
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->RefreshPrototype();
JSObject *outer =
NS_NewOuterWindowProxy(mContext, aCurrentInner->GetGlobalJSObject());
if (!outer) {
@ -2655,6 +2619,20 @@ nsJSContext::SetOuterObject(void *aOuterObject)
// Force our context's global object to be the outer.
JS_SetGlobalObject(mContext, outer);
// NB: JS_SetGlobalObject sets mContext->compartment.
JSObject *inner = JS_GetParent(mContext, outer);
nsIXPConnect *xpc = nsContentUtils::XPConnect();
nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
nsresult rv = xpc->GetWrappedNativeOfJSObject(mContext, inner,
getter_AddRefs(wrapper));
NS_ENSURE_SUCCESS(rv, rv);
NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
wrapper->RefreshPrototype();
JS_SetPrototype(mContext, outer, JS_GetPrototype(mContext, inner));
return NS_OK;
}

Просмотреть файл

@ -126,6 +126,7 @@ _TEST_FILES = \
test_bug369306.html \
test_bug61098.html \
test_bug597809.html \
test_bug612267.html \
$(NULL)
libs:: $(_TEST_FILES)

Просмотреть файл

@ -0,0 +1,28 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=612267
-->
<head>
<title>Test for Bug 393974</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=612267">Mozilla Bug 612267</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script class="testbody" type="text/javascript">
Window.prototype.test = 'PASS';
is(window.test, 'PASS', "setting Window.prototype affects window.__proto__");
is(test, 'PASS', "setting Window.prototype affects the inner window lookup for sure");
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -1148,7 +1148,7 @@ nsXPConnect::InitClassesWithNewWrappedGlobal(JSContext * aJSContext,
return UnexpectedFailure(NS_ERROR_FAILURE);
// Note: This call cooperates with a call to wrapper->RefreshPrototype()
// in nsJSEnvironment::CreateOuterObject in order to ensure that the
// in nsJSEnvironment::SetOuterObject in order to ensure that the
// prototype defines its constructor on the right global object.
if(wrapper->GetProto()->GetScriptableInfo())
scope->RemoveWrappedNativeProtos();