Bug 519145 - Make iteration over XPCNWs work again. r=jst

This commit is contained in:
Blake Kaplan 2009-09-30 15:15:51 -07:00
parent f07999d17b
commit c77dd603f8
3 changed files with 82 additions and 11 deletions

View File

@ -89,6 +89,9 @@ XPC_NW_Trace(JSTracer *trc, JSObject *obj);
static JSBool
XPC_NW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp);
static JSObject *
XPC_NW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly);
static JSBool
XPC_NW_FunctionWrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval);
@ -112,8 +115,14 @@ JSExtendedClass XPCNativeWrapper::sXPC_NW_JSClass = {
nsnull, XPC_NW_HasInstance,
JS_CLASS_TRACE(XPC_NW_Trace), nsnull
},
// JSExtendedClass initialization
XPC_NW_Equality
XPC_NW_Equality,
nsnull, // outerObject
nsnull, // innerObject
XPC_NW_Iterator,
nsnull, // wrappedObject
JSCLASS_NO_RESERVED_MEMBERS
};
// If one of our class hooks is ever called from a non-system script, bypass
@ -1086,6 +1095,36 @@ XPC_NW_Equality(JSContext *cx, JSObject *obj, jsval v, JSBool *bp)
return JS_TRUE;
}
static JSObject *
XPC_NW_Iterator(JSContext *cx, JSObject *obj, JSBool keysonly)
{
XPCCallContext ccx(JS_CALLER, cx);
if (!ccx.IsValid()) {
ThrowException(NS_ERROR_FAILURE, cx);
return nsnull;
}
JSObject *wrapperIter =
JS_NewObjectWithGivenProto(cx, XPCNativeWrapper::GetJSClass(), nsnull,
STOBJ_GET_PARENT(obj));
if (!wrapperIter) {
return nsnull;
}
JSAutoTempValueRooter tvr(cx, OBJECT_TO_JSVAL(wrapperIter));
// Initialize our native wrapper.
XPCWrappedNative *wn = static_cast<XPCWrappedNative *>(JS_GetPrivate(cx, obj));
JS_SetPrivate(cx, wrapperIter, wn);
if (!JS_SetReservedSlot(cx, wrapperIter, 0,
INT_TO_JSVAL(FLAG_DEEP | FLAG_EXPLICIT))) {
return nsnull;
}
return XPCWrapper::CreateIteratorObj(cx, wrapperIter, obj,
wn->GetFlatJSObject(), keysonly);
}
static JSBool
XPC_NW_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
jsval *rval)

View File

@ -211,6 +211,21 @@ XPCWrapper::CreateIteratorObj(JSContext *cx, JSObject *tempWrapper,
return nsnull;
}
if (XPCNativeWrapper::IsNativeWrapper(wrapperObj)) {
// For native wrappers, expandos on the wrapper itself aren't propagated
// to the wrapped object, so we have to actually iterate the wrapper here.
// In order to do so, we set the prototype of the iter to the wrapper,
// call enumerate, and then re-set the prototype. As we do this, we have
// to protec the temporary wrapper from garbage collection.
JSAutoTempValueRooter tvr(cx, tempWrapper);
if (!JS_SetPrototype(cx, iterObj, wrapperObj) ||
!XPCWrapper::Enumerate(cx, iterObj, wrapperObj) ||
!JS_SetPrototype(cx, iterObj, tempWrapper)) {
return nsnull;
}
}
// Start enumerating over all of our properties.
do {
if (!XPCWrapper::Enumerate(cx, iterObj, innerObj)) {

View File

@ -7,9 +7,18 @@
</head>
<body>
<script class="testbody" type="text/javascript;version=1.7">
var answer = [];
location.foopy = 3;
var xow_answer = [];
for (let i in location)
answer.push(i);
xow_answer.push(i);
var xpcnw_answer = [];
var xpcnw = new XPCNativeWrapper(location);
xpcnw.barpy = 4;
for (let i in xpcnw)
xpcnw_answer.push(i);
var expected = [
"hash",
"host",
@ -21,26 +30,34 @@
"search",
"reload",
"replace",
"assign"
"assign",
"foopy"
];
is(answer.sort().toString(),
var xpcnw_expected = expected.slice(0, expected.length - 1);
xpcnw_expected.push("barpy");
is(xow_answer.sort().toString(),
expected.sort().toString(),
'enumeration over XOWs walks the prototype chain');
answer = [];
is(xpcnw_answer.sort().toString(),
xpcnw_expected.sort().toString(),
'enumeration over XPCNWs walks the prototype chain');
let sjow_answer = [];
let (obj = { a: 3 }) {
for (let i in XPCSafeJSObjectWrapper({ __proto__: obj}))
answer.push(i);
is(answer.toString(), 'a',
sjow_answer.push(i);
is(sjow_answer.toString(), 'a',
'enumeration over SJOWs walks the prototype chain');
}
answer = [];
sjow_answer = [];
for (let i in XPCSafeJSObjectWrapper(location))
answer.push(i);
sjow_answer.push(i);
is(answer.sort().toString(),
is(sjow_answer.sort().toString(),
expected.sort().toString(),
'enumeration over SJOWs walks the prototype chain and works over XOWs');