Bug 1041731 - Unforgeable Xrayed methods aren't getting cached on the holder. r=bholley.

--HG--
extra : rebase_source : 9e86ba2d864e6894cc10722ddaf83ded41d88e42
This commit is contained in:
Peter Van der Beken 2014-08-22 11:25:07 +02:00
parent 00081078d1
commit 6339a35cea
5 changed files with 107 additions and 28 deletions

View File

@ -970,6 +970,7 @@ static bool
XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder,
const NativeProperties* nativeProperties);
static bool
@ -977,13 +978,17 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
const NativePropertyHooks* nativePropertyHooks,
DOMObjectType type, JS::Handle<JSObject*> obj,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc);
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder);
bool
XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc)
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder)
{
cacheOnHolder = false;
DOMObjectType type;
const NativePropertyHooks *nativePropertyHooks =
GetNativePropertyHooks(cx, obj, type);
@ -992,20 +997,20 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
// For prototype objects and interface objects, just return their
// normal set of properties.
return XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
obj, id, desc);
obj, id, desc, cacheOnHolder);
}
// Check for unforgeable properties before doing mResolveOwnProperty weirdness
const NativePropertiesHolder& nativeProperties =
nativePropertyHooks->mNativeProperties;
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc,
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc, cacheOnHolder,
nativeProperties.regular)) {
return false;
}
if (desc.object()) {
return true;
}
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc,
if (!XrayResolveUnforgeableProperty(cx, wrapper, obj, id, desc, cacheOnHolder,
nativeProperties.chromeOnly)) {
return false;
}
@ -1021,7 +1026,8 @@ static bool
XrayResolveAttribute(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
const Prefable<const JSPropertySpec>* attributes, jsid* attributeIds,
const JSPropertySpec* attributeSpecs, JS::MutableHandle<JSPropertyDescriptor> desc)
const JSPropertySpec* attributeSpecs, JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder)
{
for (; attributes->specs; ++attributes) {
if (attributes->isEnabled(cx, obj)) {
@ -1030,6 +1036,8 @@ XrayResolveAttribute(JSContext* cx, JS::Handle<JSObject*> wrapper,
size_t i = attributes->specs - attributeSpecs;
for ( ; attributeIds[i] != JSID_VOID; ++i) {
if (id == attributeIds[i]) {
cacheOnHolder = true;
const JSPropertySpec& attrSpec = attributeSpecs[i];
// Because of centralization, we need to make sure we fault in the
// JitInfos as well. At present, until the JSAPI changes, the easiest
@ -1073,7 +1081,8 @@ XrayResolveMethod(JSContext* cx, JS::Handle<JSObject*> wrapper,
const Prefable<const JSFunctionSpec>* methods,
jsid* methodIds,
const JSFunctionSpec* methodSpecs,
JS::MutableHandle<JSPropertyDescriptor> desc)
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder)
{
const Prefable<const JSFunctionSpec>* method;
for (method = methods; method->specs; ++method) {
@ -1083,6 +1092,8 @@ XrayResolveMethod(JSContext* cx, JS::Handle<JSObject*> wrapper,
size_t i = method->specs - methodSpecs;
for ( ; methodIds[i] != JSID_VOID; ++i) {
if (id == methodIds[i]) {
cacheOnHolder = true;
const JSFunctionSpec& methodSpec = methodSpecs[i];
JSFunction *fun;
if (methodSpec.selfHostedName) {
@ -1117,6 +1128,7 @@ XrayResolveMethod(JSContext* cx, JS::Handle<JSObject*> wrapper,
XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder,
const NativeProperties* nativeProperties)
{
if (!nativeProperties) {
@ -1128,7 +1140,7 @@ XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
nativeProperties->unforgeableAttributes,
nativeProperties->unforgeableAttributeIds,
nativeProperties->unforgeableAttributeSpecs,
desc)) {
desc, cacheOnHolder)) {
return false;
}
@ -1142,7 +1154,7 @@ XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
nativeProperties->unforgeableMethods,
nativeProperties->unforgeableMethodIds,
nativeProperties->unforgeableMethodSpecs,
desc)) {
desc, cacheOnHolder)) {
return false;
}
@ -1157,7 +1169,8 @@ XrayResolveUnforgeableProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
static bool
XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc, DOMObjectType type,
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder, DOMObjectType type,
const NativeProperties* nativeProperties)
{
const Prefable<const JSFunctionSpec>* methods;
@ -1174,7 +1187,7 @@ XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
}
if (methods) {
if (!XrayResolveMethod(cx, wrapper, obj, id, methods, methodIds,
methodSpecs, desc)) {
methodSpecs, desc, cacheOnHolder)) {
return false;
}
if (desc.object()) {
@ -1187,7 +1200,8 @@ XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
if (!XrayResolveAttribute(cx, wrapper, obj, id,
nativeProperties->staticAttributes,
nativeProperties->staticAttributeIds,
nativeProperties->staticAttributeSpecs, desc)) {
nativeProperties->staticAttributeSpecs, desc,
cacheOnHolder)) {
return false;
}
if (desc.object()) {
@ -1199,7 +1213,8 @@ XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
if (!XrayResolveAttribute(cx, wrapper, obj, id,
nativeProperties->attributes,
nativeProperties->attributeIds,
nativeProperties->attributeSpecs, desc)) {
nativeProperties->attributeSpecs, desc,
cacheOnHolder)) {
return false;
}
if (desc.object()) {
@ -1217,6 +1232,8 @@ XrayResolveProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
size_t i = constant->specs - nativeProperties->constantSpecs;
for ( ; nativeProperties->constantIds[i] != JSID_VOID; ++i) {
if (id == nativeProperties->constantIds[i]) {
cacheOnHolder = true;
desc.setAttributes(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
desc.object().set(wrapper);
desc.value().set(nativeProperties->constantSpecs[i].value);
@ -1234,7 +1251,8 @@ static bool
ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj,
size_t protoAndIfaceCacheIndex, unsigned attrs,
JS::MutableHandle<JSPropertyDescriptor> desc)
JS::MutableHandle<JSPropertyDescriptor> desc,
bool cacheOnHolder)
{
JS::Rooted<JSObject*> global(cx, js::GetGlobalForObjectCrossCompartment(obj));
{
@ -1245,6 +1263,9 @@ ResolvePrototypeOrConstructor(JSContext* cx, JS::Handle<JSObject*> wrapper,
if (!protoOrIface) {
return false;
}
cacheOnHolder = true;
desc.object().set(wrapper);
desc.setAttributes(attrs);
desc.setGetter(JS_PropertyStub);
@ -1259,28 +1280,29 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
const NativePropertyHooks* nativePropertyHooks,
DOMObjectType type, JS::Handle<JSObject*> obj,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc)
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder)
{
if (type == eInterface && IdEquals(id, "prototype")) {
return nativePropertyHooks->mPrototypeID == prototypes::id::_ID_Count ||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
nativePropertyHooks->mPrototypeID,
JSPROP_PERMANENT | JSPROP_READONLY,
desc);
desc, cacheOnHolder);
}
if (type == eInterfacePrototype && IdEquals(id, "constructor")) {
return nativePropertyHooks->mConstructorID == constructors::id::_ID_Count ||
ResolvePrototypeOrConstructor(cx, wrapper, obj,
nativePropertyHooks->mConstructorID,
0, desc);
0, desc, cacheOnHolder);
}
const NativePropertiesHolder& nativeProperties =
nativePropertyHooks->mNativeProperties;
if (nativeProperties.regular &&
!XrayResolveProperty(cx, wrapper, obj, id, desc, type,
!XrayResolveProperty(cx, wrapper, obj, id, desc, cacheOnHolder, type,
nativeProperties.regular)) {
return false;
}
@ -1288,7 +1310,7 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
if (!desc.object() &&
nativeProperties.chromeOnly &&
xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
!XrayResolveProperty(cx, wrapper, obj, id, desc, type,
!XrayResolveProperty(cx, wrapper, obj, id, desc, cacheOnHolder, type,
nativeProperties.chromeOnly)) {
return false;
}
@ -1299,8 +1321,11 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
bool
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj,
JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc)
JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder)
{
cacheOnHolder = false;
DOMObjectType type;
const NativePropertyHooks* nativePropertyHooks =
GetNativePropertyHooks(cx, obj, type);
@ -1314,7 +1339,7 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
if (type == eInterfacePrototype) {
do {
if (!XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
obj, id, desc)) {
obj, id, desc, cacheOnHolder)) {
return false;
}
@ -1327,7 +1352,7 @@ XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
}
return XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type, obj,
id, desc);
id, desc, cacheOnHolder);
}
bool
@ -1666,7 +1691,8 @@ NativeToString(JSContext* cx, JS::Handle<JSObject*> wrapper,
toStringDesc.value().set(JS::UndefinedValue());
JS::Rooted<jsid> id(cx,
nsXPConnect::GetRuntimeInstance()->GetStringID(XPCJSRuntime::IDX_TO_STRING));
if (!XrayResolveNativeProperty(cx, wrapper, obj, id, &toStringDesc)) {
bool unused;
if (!XrayResolveNativeProperty(cx, wrapper, obj, id, &toStringDesc, unused)) {
return false;
}

View File

@ -2301,7 +2301,8 @@ bool
XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj,
JS::Handle<jsid> id,
JS::MutableHandle<JSPropertyDescriptor> desc);
JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder);
/**
* This resolves operations, attributes and constants of the interfaces for obj.
@ -2313,7 +2314,8 @@ XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
bool
XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
JS::Handle<JSObject*> obj,
JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc);
JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc,
bool& cacheOnHolder);
/**
* Define a property on obj through an Xray wrapper.

View File

@ -4,3 +4,4 @@
[test_bug775543.html]
[test_document_location_set_via_xray.html]
[test_proxies_via_xray.html]
[test_document_location_via_xray_cached.html]

View File

@ -0,0 +1,36 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1041731
-->
<head>
<meta charset="utf-8">
<title>Test for Bug 1041731</title>
<script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1041731">Mozilla Bug 1041731</a>
<p id="display"></p>
<div id="content" style="display: none">
<iframe id="t" src="http://example.org/tests/dom/bindings/test/file_document_location_set_via_xray.html"></iframe>
</div>
<pre id="test">
<script type="application/javascript">
/** Test for Bug 1041731 **/
function test()
{
var loc = document.getElementById("t").contentWindow.document.location;
ise(loc.toString, loc.toString, "Unforgeable method on the Xray should be cached");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
addLoadEvent(test);
</script>
</pre>
</body>
</html>

View File

@ -2060,8 +2060,9 @@ DOMXrayTraits::resolveNativeProperty(JSContext *cx, HandleObject wrapper,
HandleObject holder, HandleId id,
MutableHandle<JSPropertyDescriptor> desc)
{
bool unused;
RootedObject obj(cx, getTargetObject(wrapper));
if (!XrayResolveNativeProperty(cx, wrapper, obj, id, desc))
if (!XrayResolveNativeProperty(cx, wrapper, obj, id, desc, unused))
return false;
MOZ_ASSERT(!desc.object() || desc.object() == wrapper, "What did we resolve this on?");
@ -2102,13 +2103,26 @@ DOMXrayTraits::resolveOwnProperty(JSContext *cx, const Wrapper &jsWrapper, Handl
}
}
if (!JS_GetPropertyDescriptorById(cx, holder, id, desc))
return false;
if (desc.object()) {
desc.object().set(wrapper);
return true;
}
RootedObject obj(cx, getTargetObject(wrapper));
if (!XrayResolveOwnProperty(cx, wrapper, obj, id, desc))
bool cacheOnHolder;
if (!XrayResolveOwnProperty(cx, wrapper, obj, id, desc, cacheOnHolder))
return false;
MOZ_ASSERT(!desc.object() || desc.object() == wrapper, "What did we resolve this on?");
return true;
if (!desc.object() || !cacheOnHolder)
return true;
return JS_DefinePropertyById(cx, holder, id, desc.value(), desc.attributes(),
desc.getter(), desc.setter()) &&
JS_GetPropertyDescriptorById(cx, holder, id, desc);
}
bool