Bug 639720. Get rid of the Window class setter so that SETNAME on the global is faster in the browser. r=mrbkap

This commit is contained in:
Boris Zbarsky 2011-08-31 18:10:16 -04:00
parent 3b06c78f95
commit dd3d708aa6
4 changed files with 146 additions and 66 deletions

View File

@ -48,6 +48,7 @@
#include "AccessCheck.h"
#include "xpcprivate.h"
#include "XPCWrapper.h"
#include "nscore.h"
#include "nsDOMClassInfo.h"
@ -516,7 +517,6 @@ static const char kDOMStringBundleURL[] =
#define WINDOW_SCRIPTABLE_FLAGS \
(nsIXPCScriptable::WANT_GETPROPERTY | \
nsIXPCScriptable::WANT_SETPROPERTY | \
nsIXPCScriptable::WANT_PRECREATE | \
nsIXPCScriptable::WANT_FINALIZE | \
nsIXPCScriptable::WANT_EQUALITY | \
@ -5269,39 +5269,6 @@ nsWindowSH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
return NS_OK;
}
NS_IMETHODIMP
nsWindowSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
{
if (id == sLocation_id) {
JSAutoRequest ar(cx);
JSString *val = ::JS_ValueToString(cx, *vp);
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMWindow> window = do_QueryWrappedNative(wrapper);
NS_ENSURE_TRUE(window, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMLocation> location;
nsresult rv = window->GetLocation(getter_AddRefs(location));
NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && location, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, obj, location, &NS_GET_IID(nsIDOMLocation), PR_TRUE,
vp, getter_AddRefs(holder));
NS_ENSURE_SUCCESS(rv, rv);
nsDependentJSString depStr;
NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
rv = location->SetHref(depStr);
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
return NS_OK;
}
NS_IMETHODIMP
nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRBool *_retval)
@ -6392,6 +6359,68 @@ static JSNewResolveOp sOtherResolveFuncs[] = {
mozilla::dom::workers::ResolveWorkerClasses
};
template<class Interface>
static nsresult
LocationSetterGuts(JSContext *cx, JSObject *obj, jsval *vp)
{
// This function duplicates some of the logic in XPC_WN_HelperSetProperty
XPCWrappedNative *wrapper =
XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj);
// The error checks duplicate code in THROW_AND_RETURN_IF_BAD_WRAPPER
NS_ENSURE_TRUE(wrapper, NS_ERROR_XPC_BAD_OP_ON_WN_PROTO);
NS_ENSURE_TRUE(wrapper->IsValid(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN);
nsCOMPtr<Interface> xpcomObj = do_QueryWrappedNative(wrapper);
NS_ENSURE_TRUE(xpcomObj, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMLocation> location;
nsresult rv = xpcomObj->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
JSString *val = ::JS_ValueToString(cx, *vp);
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
nsDependentJSString depStr;
NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
rv = location->SetHref(depStr);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
return WrapNative(cx, JS_GetGlobalForScopeChain(cx), location,
&NS_GET_IID(nsIDOMLocation), PR_TRUE, vp,
getter_AddRefs(holder));
}
template<class Interface>
static JSBool
LocationSetter(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
jsval *vp)
{
nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp);
if (NS_FAILED(rv)) {
if (!::JS_IsExceptionPending(cx)) {
nsDOMClassInfo::ThrowJSException(cx, rv);
}
return JS_FALSE;
}
return JS_TRUE;
}
static JSBool
LocationSetterUnwrapper(JSContext *cx, JSObject *obj, jsid id, JSBool strict,
jsval *vp)
{
JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj);
if (wrapped) {
obj = wrapped;
}
return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp);
}
NS_IMETHODIMP
nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, PRUint32 flags,
@ -6544,7 +6573,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
NS_ENSURE_SUCCESS(rv, rv);
JSBool ok = JS_WrapValue(cx, &v) &&
JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull,
JS_DefinePropertyById(cx, obj, id, v, nsnull,
LocationSetterUnwrapper,
JSPROP_PERMANENT | JSPROP_ENUMERATE);
if (!ok) {
@ -8177,7 +8207,8 @@ nsDocumentSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSAutoRequest ar(cx);
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, v, nsnull, nsnull,
JSBool ok = ::JS_DefinePropertyById(cx, obj, id, v, nsnull,
LocationSetter<nsIDOMDocument>,
JSPROP_PERMANENT | JSPROP_ENUMERATE);
if (!ok) {
@ -8222,34 +8253,6 @@ NS_IMETHODIMP
nsDocumentSH::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval)
{
if (id == sLocation_id) {
nsCOMPtr<nsIDOMDocument> doc = do_QueryWrappedNative(wrapper);
NS_ENSURE_TRUE(doc, NS_ERROR_UNEXPECTED);
nsCOMPtr<nsIDOMLocation> location;
nsresult rv = doc->GetLocation(getter_AddRefs(location));
NS_ENSURE_SUCCESS(rv, rv);
if (location) {
JSAutoRequest ar(cx);
JSString *val = ::JS_ValueToString(cx, *vp);
NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED);
nsDependentJSString depStr;
NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED);
rv = location->SetHref(depStr);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIXPConnectJSObjectHolder> holder;
rv = WrapNative(cx, JS_GetGlobalForScopeChain(cx), location,
&NS_GET_IID(nsIDOMLocation), PR_TRUE, vp,
getter_AddRefs(holder));
return NS_FAILED(rv) ? rv : NS_SUCCESS_I_DID_SOMETHING;
}
}
if (id == sDocumentURIObject_id && IsPrivilegedScript()) {
// We don't want privileged script that can read this property to set it,
// but _do_ want to allow everyone else to set a value they can then read.

View File

@ -407,8 +407,6 @@ public:
#endif
NS_IMETHOD GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, jsid id, jsval *vp, PRBool *_retval);
NS_IMETHOD Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
JSObject *obj, PRBool *_retval);
NS_IMETHOD NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,

View File

@ -55,6 +55,7 @@ _TEST_FILES = \
test_location.html \
test_innerWidthHeight_script.html \
innerWidthHeight_script.html \
test_location_setters.html \
$(NULL)
libs:: $(_TEST_FILES)

View File

@ -0,0 +1,78 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=639720
-->
<head>
<title>Test for Bug 639720</title>
<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=639720">Mozilla Bug 639720</a>
<p id="display">
<iframe id="f"></iframe>
</p>
<div id="content" style="display: none">
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 639720 **/
SimpleTest.waitForExplicitFinish();
var tests = [
{ url: "data:text/plain,1" },
{ url: "data:text/plain,2",
useDocument: true },
{ prepURL: "http://www.example.com",
url: "data:text/plain,3" }
];
var currentTest = 0;
function checkTest() {
is($("f").contentWindow.location.href, tests[currentTest].url,
"href of content window's location should match url of current test");
++currentTest;
runNextTest();
}
function runCurrentTest() {
var test = tests[currentTest];
$("f").onload = checkTest;
if (test.useDocument) {
$("f").contentDocument.location = test.url;
} else {
$("f").contentWindow.location = test.url;
}
is(typeof($("f").contentWindow.location), "object",
"Location should not have become string");
}
function prepComplete() {
runCurrentTest();
}
function runNextTest() {
if (currentTest == tests.length) {
SimpleTest.finish();
return;
}
var test = tests[currentTest];
if ("prepURL" in test) {
$("f").onload = prepComplete;
$("f").src = test.prepURL;
return;
}
runCurrentTest();
}
addLoadEvent(runNextTest);
</script>
</pre>
</body>
</html>