Bug 589028 - make nsContentUtils::GetDocumentFromCaller not depend on slow-native constructors (r=jst)

--HG--
extra : rebase_source : a12eb25eadefa5ed1bb1799516ee9b287d171aa2
This commit is contained in:
Luke Wagner 2010-08-19 18:12:02 -07:00
parent 139d2a2a71
commit a80ab46add
7 changed files with 129 additions and 17 deletions

View File

@ -1526,25 +1526,17 @@ nsIDOMDocument *
nsContentUtils::GetDocumentFromCaller() nsContentUtils::GetDocumentFromCaller()
{ {
JSContext *cx = nsnull; JSContext *cx = nsnull;
sThreadJSContextStack->Peek(&cx); JSObject *obj = nsnull;
sXPConnect->GetCaller(&cx, &obj);
NS_ASSERTION(cx && obj, "Caller ensures something is running");
nsIDOMDocument *doc = nsnull; nsCOMPtr<nsPIDOMWindow> win =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, obj));
if (cx) { if (!win) {
JSObject *callee = nsnull; return nsnull;
JSStackFrame *fp = nsnull;
while (!callee && (fp = ::JS_FrameIterator(cx, &fp))) {
callee = ::JS_GetFrameCalleeObject(cx, fp);
}
nsCOMPtr<nsPIDOMWindow> win =
do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(cx, callee));
if (win) {
doc = win->GetExtantDocument();
}
} }
return doc; return win->GetExtantDocument();
} }
nsIDOMDocument * nsIDOMDocument *

View File

@ -399,7 +399,7 @@ interface nsIXPCFunctionThisTranslator : nsISupports
{ 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } } { 0xbd, 0xd6, 0x0, 0x0, 0x64, 0x65, 0x73, 0x74 } }
%} %}
[uuid(7a3c8687-6f52-47d5-9b8e-2ed8bf86c415)] [uuid(227ab41e-24dc-42a6-9e7b-e3a62132d781)]
interface nsIXPConnect : nsISupports interface nsIXPConnect : nsISupports
{ {
%{ C++ %{ C++
@ -892,4 +892,10 @@ interface nsIXPConnect : nsISupports
*/ */
nsIXPConnectJSObjectHolder holdObject(in JSContextPtr aJSContext, nsIXPConnectJSObjectHolder holdObject(in JSContextPtr aJSContext,
in JSObjectPtr aObject); in JSObjectPtr aObject);
/**
* Return the caller object of the current call from JS.
*/
[noscript,notxpcom] void getCaller(out JSContextPtr aJSContext,
out JSObjectPtr aObject);
}; };

View File

@ -2781,6 +2781,16 @@ nsXPConnect::HoldObject(JSContext *aJSContext, JSObject *aObject,
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP_(void)
nsXPConnect::GetCaller(JSContext **aJSContext, JSObject **aObj)
{
XPCCallContext *ccx = XPCPerThreadData::GetData(nsnull)->GetCallContext();
*aJSContext = ccx->GetJSContext();
// Set to the caller in XPC_WN_Helper_{Call,Construct}
*aObj = ccx->GetFlattenedJSObject();
}
/* These are here to be callable from a debugger */ /* These are here to be callable from a debugger */
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C
JS_EXPORT_API(void) DumpJSStack() JS_EXPORT_API(void) DumpJSStack()

View File

@ -1069,6 +1069,12 @@ XPC_WN_Helper_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if(!(obj = JSVAL_TO_OBJECT(argv[-2]))) if(!(obj = JSVAL_TO_OBJECT(argv[-2])))
return JS_FALSE; return JS_FALSE;
XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, JSID_VOID, argc, argv, rval);
if(!ccx.IsValid())
return JS_FALSE;
JS_ASSERT(obj == ccx.GetFlattenedJSObject());
SLIM_LOG_WILL_MORPH(cx, obj); SLIM_LOG_WILL_MORPH(cx, obj);
PRE_HELPER_STUB_NO_SLIM PRE_HELPER_STUB_NO_SLIM
Call(wrapper, cx, obj, argc, argv, rval, &retval); Call(wrapper, cx, obj, argc, argv, rval, &retval);
@ -1084,6 +1090,12 @@ XPC_WN_Helper_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
if(!(obj = JSVAL_TO_OBJECT(argv[-2]))) if(!(obj = JSVAL_TO_OBJECT(argv[-2])))
return JS_FALSE; return JS_FALSE;
XPCCallContext ccx(JS_CALLER, cx, obj, nsnull, JSID_VOID, argc, argv, rval);
if(!ccx.IsValid())
return JS_FALSE;
JS_ASSERT(obj == ccx.GetFlattenedJSObject());
SLIM_LOG_WILL_MORPH(cx, obj); SLIM_LOG_WILL_MORPH(cx, obj);
PRE_HELPER_STUB_NO_SLIM PRE_HELPER_STUB_NO_SLIM
Construct(wrapper, cx, obj, argc, argv, rval, &retval); Construct(wrapper, cx, obj, argc, argv, rval, &retval);

View File

@ -75,6 +75,8 @@ _TEST_FILES = bug500931_helper.html \
test_bug564330.html \ test_bug564330.html \
test_cows.html \ test_cows.html \
test_frameWrapping.html \ test_frameWrapping.html \
test_bug589028.html \
bug589028_helper.html \
$(NULL) $(NULL)
libs:: $(_TEST_FILES) libs:: $(_TEST_FILES)

View File

@ -0,0 +1,27 @@
<html>
<head>
<script>
function getMyOption() {
return new Option();
}
function getCallersOption(caller) {
return new caller.Option();
}
function getMyAudio() {
return new Audio();
}
function getCallersAudio(caller) {
return new caller.Audio();
}
function getMyImage() {
return new Image();
}
function getCallersImage(caller) {
return new caller.Image();
}
</script>
</head>
<body>
the iframe
</body>
</html>

View File

@ -0,0 +1,63 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=589028
-->
<head>
<title>Test for Bug 589028</title>
<script type="application/javascript" src="/MochiKit/packed.js"></script>
<script type="application/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=589028">Mozilla Bug 589028</a>
<p id="display"></p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script>
/** Test for Bug 589028 **/
SimpleTest.waitForExplicitFinish();
var p = 0;
function go() {
var ifr = $('ifr');
var ifrwin = ifr.contentWindow;
var ifrdoc = ifr.contentDocument;
o1 = new ifrwin.Option();
is(o1.ownerDocument, ifrdoc, "ownerDocument doesn't match iframe");
o2 = ifrwin.getMyOption();
is(o2.ownerDocument, ifrdoc, "ownerDocument doesn't match iframe");
o3 = ifrwin.getCallersOption(this);
is(o3.ownerDocument, document);
a1 = new ifrwin.Audio();
is(a1.ownerDocument, ifrdoc, "ownerDocument doesn't match iframe");
a2 = ifrwin.getMyAudio();
is(a2.ownerDocument, ifrdoc, "ownerDocument doesn't match iframe");
a3 = ifrwin.getCallersAudio(this);
is(a3.ownerDocument, document);
i1 = new ifrwin.Image();
is(i1.ownerDocument, ifrdoc, "ownerDocument doesn't match iframe");
i2 = ifrwin.getMyImage();
is(i2.ownerDocument, ifrdoc, "ownerDocument doesn't match iframe");
i3 = ifrwin.getCallersImage(this);
is(i3.ownerDocument, document);
SimpleTest.finish();
}
</script>
</pre>
<iframe src="bug589028_helper.html" id="ifr" onload="go()"></iframe>
</body>
</html>