Bug 571849 - Fix enumerateOwn and the Iterate constructor on Xray wrappers. r=gal a=blocking

This commit is contained in:
Blake Kaplan 2010-11-10 14:08:44 -08:00
Родитель a62b73d32e
Коммит 9d5a3c58b6
7 изменённых файлов: 201 добавлений и 120 удалений

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

@ -205,8 +205,11 @@ JSProxyHandler::iterate(JSContext *cx, JSObject *proxy, uintN flags, Value *vp)
{
JS_ASSERT(OperationInProgress(cx, proxy));
AutoIdVector props(cx);
if (!enumerate(cx, proxy, props))
if ((flags & JSITER_OWNONLY)
? !enumerateOwn(cx, proxy, props)
: !enumerate(cx, proxy, props)) {
return false;
}
return EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp);
}

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

@ -56,6 +56,7 @@ _CHROME_FILES = \
test_bug484459.xul \
test_cows.xul \
test_bug517163.xul \
test_bug571849.xul \
$(NULL)
# Disabled until this test gets updated to test the new proxy based

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

@ -0,0 +1,45 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
type="text/css"?>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=500931
-->
<window title="Mozilla Bug 500931"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript"
src="chrome://mochikit/content/MochiKit/packed.js"></script>
<script type="application/javascript"
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
<!-- test results are displayed in the html:body -->
<body xmlns="http://www.w3.org/1999/xhtml">
<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=500931"
target="_blank">Mozilla Bug 500931</a>
<!-- test code goes here -->
<script type="application/javascript"><![CDATA[
/** Test for Bug 500931 **/
function go() {
var ifr = document.getElementById('ifr');
var docnodes = ifr.contentDocument.body.childNodes;
var output;
for (let i in Iterator(docnodes))
output = i;
is(output[0], "0", "enumerated the 0th element");
ok(/Text/.test(output[1]), "the 0th element was a text node");
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
]]></script>
<iframe type="content"
src="http://example.org/tests/js/src/xpconnect/tests/mochitest/bug571849_helper.html"
onload="go()"
id="ifr">
</iframe>
</body>
</window>

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

@ -48,6 +48,7 @@ _TEST_FILES = bug500931_helper.html \
inner.html \
bug92773_helper.html \
bug504877_helper.html \
bug571849_helper.html \
chrome_wrappers_helper.html \
file_doublewrappedcompartments.html \
file_evalInSandbox.html \

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

@ -0,0 +1,7 @@
<html>
<head>
</head>
<body>
TEXT NODE TEXT NODE
</body>
</html>

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

@ -215,34 +215,6 @@ ResolveNativeProperty(JSContext *cx, JSObject *wrapper, JSObject *holder, jsid i
// This will do verification and the method lookup for us.
XPCCallContext ccx(JS_CALLER, cx, wnObject, nsnull, id);
// Run the resolve hook of the wrapped native.
if (NATIVE_HAS_FLAG(wn, WantNewResolve)) {
JSAutoEnterCompartment ac;
if (!ac.enter(cx, holder))
return false;
JSBool retval = true;
JSObject *pobj = NULL;
uintN flags = (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED;
nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id,
flags, &pobj, &retval);
if (NS_FAILED(rv)) {
if (retval) {
XPCThrower::Throw(rv, cx);
}
return false;
}
if (pobj) {
#ifdef DEBUG
JSBool hasProp;
NS_ASSERTION(JS_HasPropertyById(cx, holder, id, &hasProp) &&
hasProp, "id got defined somewhere else?");
#endif
return JS_GetPropertyDescriptorById(cx, holder, id, flags, desc);
}
}
// There are no native numeric properties, so we can shortcut here. We will not
// find the property.
if (!JSID_IS_ATOM(id)) {
@ -430,9 +402,8 @@ IsTransparent(JSContext *cx, JSObject *wrapper)
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::resolveWrappedJSObject(JSContext *cx, JSObject *wrapper,
jsid id, bool set,
PropertyDescriptor *desc_in)
XrayWrapper<Base, Policy>::resolveOwnProperty(JSContext *cx, JSObject *wrapper, jsid id, bool set,
PropertyDescriptor *desc_in)
{
JSPropertyDescriptor *desc = Jsvalify(desc_in);
@ -451,7 +422,50 @@ XrayWrapper<Base, Policy>::resolveWrappedJSObject(JSContext *cx, JSObject *wrapp
return true;
}
desc->obj = NULL;
JSObject *holder = GetHolder(wrapper);
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
return false;
if (!JS_GetPropertyDescriptorById(cx, expando, id,
(set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
desc)) {
return false;
}
if (desc->obj)
return true;
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
XPCWrappedNative *wn = GetWrappedNative(wnObject);
// Run the resolve hook of the wrapped native.
if (NATIVE_HAS_FLAG(wn, WantNewResolve)) {
JSBool retval = true;
JSObject *pobj = NULL;
uintN flags = (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED;
nsresult rv = wn->GetScriptableInfo()->GetCallback()->NewResolve(wn, cx, wrapper, id,
flags, &pobj, &retval);
if (NS_FAILED(rv)) {
if (retval)
XPCThrower::Throw(rv, cx);
return false;
}
if (pobj) {
#ifdef DEBUG
JSBool hasProp;
NS_ASSERTION(JS_HasPropertyById(cx, holder, id, &hasProp) &&
hasProp, "id got defined somewhere else?");
#endif
if (!JS_GetPropertyDescriptorById(cx, holder, id, flags, desc))
return false;
desc->obj = wrapper;
return true;
}
}
desc->obj = nsnull;
return true;
}
@ -461,13 +475,6 @@ XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrappe
bool set, PropertyDescriptor *desc_in)
{
JSPropertyDescriptor *desc = Jsvalify(desc_in);
if (!resolveWrappedJSObject(cx, wrapper, id, set, desc_in))
return false;
if (desc->obj)
return true;
JSObject *holder = GetHolder(wrapper);
if (IsResolving(holder, id)) {
desc->obj = NULL;
@ -481,14 +488,8 @@ XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrappe
ResolvingId resolving(holder, id);
void *priv;
if (!Policy::enter(cx, wrapper, &id, set ? JSWrapper::SET : JSWrapper::GET, &priv))
return false;
// Redirect access straight to the wrapper if we should be transparent.
if (Transparent(cx, wrapper)) {
Policy::leave(cx, wrapper, priv);
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
{
@ -506,7 +507,17 @@ XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrappe
return cx->compartment->wrap(cx, desc_in);
}
bool ok = ResolveNativeProperty(cx, wrapper, holder, id, false, desc);
if (!this->resolveOwnProperty(cx, wrapper, id, set, desc_in))
return false;
if (desc->obj)
return true;
void *priv;
if (!Policy::enter(cx, wrapper, &id, set ? JSWrapper::SET : JSWrapper::GET, &priv))
return false;
bool ok = ResolveNativeProperty(cx, wrapper, holder, id, set, desc);
Policy::leave(cx, wrapper, priv);
if (!ok || desc->obj)
return ok;
@ -525,8 +536,7 @@ XrayWrapper<Base, Policy>::getPropertyDescriptor(JSContext *cx, JSObject *wrappe
return true;
}
return getOwnPropertyDescriptor(cx, wrapper, id, set, desc_in);
return true;
}
template <typename Base, typename Policy>
@ -535,21 +545,42 @@ XrayWrapper<Base, Policy>::getOwnPropertyDescriptor(JSContext *cx, JSObject *wra
bool set, PropertyDescriptor *desc_in)
{
JSPropertyDescriptor *desc = Jsvalify(desc_in);
if (!resolveWrappedJSObject(cx, wrapper, id, false, desc_in))
return false;
if (desc->obj)
return true;
JSObject *holder = GetHolder(wrapper);
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
if (IsResolving(holder, id)) {
desc->obj = NULL;
return true;
}
if (!this->enter(cx, wrapper, id, set ? JSWrapper::SET : JSWrapper::GET))
return false;
return JS_GetPropertyDescriptorById(cx, expando, id,
(set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
desc);
AutoLeaveHelper<Base, Policy> helper(*this, cx, wrapper);
ResolvingId resolving(holder, id);
// NB: Nothing we do here acts on the wrapped native itself, so we don't
// enter our policy.
// Redirect access straight to the wrapper if we should be transparent.
if (Transparent(cx, wrapper)) {
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wnObject))
return false;
if (!JS_GetPropertyDescriptorById(cx, wnObject, id,
(set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED,
desc)) {
return false;
}
}
desc->obj = (desc->obj == wnObject) ? wrapper : nsnull;
return cx->compartment->wrap(cx, desc_in);
}
return this->resolveOwnProperty(cx, wrapper, id, set, desc_in);
}
template <typename Base, typename Policy>
@ -602,29 +633,58 @@ XrayWrapper<Base, Policy>::defineProperty(JSContext *cx, JSObject *wrapper, jsid
jsdesc->attrs);
}
static bool
EnumerateNames(JSContext *cx, JSObject *wrapper, uintN flags, js::AutoIdVector &props)
{
JSObject *holder = GetHolder(wrapper);
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
// Redirect access straight to the wrapper if we should be transparent.
if (Transparent(cx, wrapper)) {
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wnObject))
return false;
return js::GetPropertyNames(cx, wnObject, flags, &props);
}
// Enumerate expando properties first.
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
return false;
if (!js::GetPropertyNames(cx, expando, flags, &props))
return false;
// Force all native properties to be materialized onto the wrapped native.
js::AutoIdVector wnProps(cx);
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wnObject))
return false;
if (!js::GetPropertyNames(cx, wnObject, flags, &wnProps))
return false;
}
// Go through the properties we got and enumerate all native ones.
for (size_t n = 0; n < wnProps.length(); ++n) {
jsid id = wnProps[n];
JSBool hasProp;
if (!JS_HasPropertyById(cx, wrapper, id, &hasProp))
return false;
if (hasProp)
props.append(id);
}
return true;
}
template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::getOwnPropertyNames(JSContext *cx, JSObject *wrapper,
js::AutoIdVector &props)
{
JSObject *holder = GetHolder(wrapper);
// Redirect access straight to the wrapper if we should be transparent.
if (Transparent(cx, wrapper)) {
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wnObject))
return false;
return js::GetPropertyNames(cx, wnObject, JSITER_OWNONLY | JSITER_HIDDEN, &props);
}
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
return false;
return js::GetPropertyNames(cx, expando, JSITER_OWNONLY | JSITER_HIDDEN, &props);
return EnumerateNames(cx, wrapper, JSITER_OWNONLY | JSITER_HIDDEN, props);
}
template <typename Base, typename Policy>
@ -663,47 +723,7 @@ template <typename Base, typename Policy>
bool
XrayWrapper<Base, Policy>::enumerate(JSContext *cx, JSObject *wrapper, js::AutoIdVector &props)
{
JSObject *holder = GetHolder(wrapper);
JSObject *wnObject = GetWrappedNativeObjectFromHolder(cx, holder);
// Redirect access straight to the wrapper if we should be transparent.
if (Transparent(cx, wrapper)) {
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wnObject))
return false;
return js::GetPropertyNames(cx, wnObject, 0, &props);
}
// Enumerate expando properties first.
JSObject *expando = GetExpandoObject(cx, holder);
if (!expando)
return false;
if (!js::GetPropertyNames(cx, expando, JSITER_OWNONLY, &props))
return false;
// Force all native properties to be materialized onto the wrapped native.
js::AutoIdVector wnProps(cx);
{
JSAutoEnterCompartment ac;
if (!ac.enter(cx, wnObject))
return false;
if (!js::GetPropertyNames(cx, wnObject, 0, &wnProps))
return false;
}
// Go through the properties we got and enumerate all native ones.
for (size_t n = 0; n < wnProps.length(); ++n) {
jsid id = wnProps[n];
JSBool hasProp;
if (!JS_HasPropertyById(cx, wrapper, id, &hasProp))
return false;
if (hasProp)
props.append(id);
}
return true;
return EnumerateNames(cx, wrapper, 0, props);
}
template <typename Base, typename Policy>

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

@ -93,6 +93,10 @@ class XrayWrapper : public Base {
static JSObject *createHolder(JSContext *cx, JSObject *wrappedNative, JSObject *parent);
static XrayWrapper singleton;
private:
bool resolveOwnProperty(JSContext *cx, JSObject *wrapper, jsid id, bool set,
js::PropertyDescriptor *desc);
};
class CrossCompartmentXray {