Bug 1090592 - GetPrototypeOf hook for CPOWProxyHandler. r=billm

This commit is contained in:
Gabor Krizsanits 2015-02-10 16:29:41 +01:00
parent 131099cb58
commit 1925b59d34
8 changed files with 85 additions and 2 deletions

View File

@ -64,11 +64,18 @@ function make_object()
let for_json = { "n": 3, "a": array, "s": "hello", o: { "x": 10 } };
let proto = { data: 42 };
let with_proto = Object.create(proto);
let with_null_proto = Object.create(null);
return { "data": o,
"throwing": throwing,
"document": content.document,
"array": array,
"for_json": for_json
"for_json": for_json,
"with_proto": with_proto,
"with_null_proto": with_null_proto
};
}

View File

@ -126,6 +126,14 @@
ok(j2.a[2] === 3, "JSON array index");
ok(j2.s === "hello", "JSON string property");
ok(j2.o.x === 10, "JSON object property");
let with_proto = message.objects.with_proto;
let proto = Object.getPrototypeOf(with_proto);
ok(proto.data == 42, "Object.getPrototypeOf works on CPOW");
let with_null_proto = message.objects.with_null_proto;
proto = Object.getPrototypeOf(with_null_proto);
ok(proto === null, "Object.getPrototypeOf works on CPOW (null proto)");
}
function recvAsyncMessage(message) {

View File

@ -99,6 +99,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
bool RecvClassName(const uint64_t &objId, nsString *result) {
return Answer::RecvClassName(ObjectId::deserialize(objId), result);
}
bool RecvGetPrototypeOf(const uint64_t &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
return Answer::RecvGetPrototypeOf(ObjectId::deserialize(objId), rs, result);
}
bool RecvRegExpToShared(const uint64_t &objId, ReturnStatus *rs, nsString *source, uint32_t *flags) {
return Answer::RecvRegExpToShared(ObjectId::deserialize(objId), rs, source, flags);
}
@ -188,6 +191,9 @@ class JavaScriptBase : public WrapperOwner, public WrapperAnswer, public Base
bool SendClassName(const ObjectId &objId, nsString *result) {
return Base::SendClassName(objId.serialize(), result);
}
bool SendGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) {
return Base::SendGetPrototypeOf(objId.serialize(), rs, result);
}
bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
nsString *source, uint32_t *flags) {

View File

@ -40,6 +40,7 @@ both:
prio(high) sync HasInstance(uint64_t objId, JSVariant v) returns (ReturnStatus rs, bool has);
prio(high) sync ObjectClassIs(uint64_t objId, uint32_t classValue) returns (bool result);
prio(high) sync ClassName(uint64_t objId) returns (nsString name);
prio(high) sync GetPrototypeOf(uint64_t objId) returns (ReturnStatus rs, ObjectOrNullVariant result);
prio(high) sync RegExpToShared(uint64_t objId) returns (ReturnStatus rs, nsString source, uint32_t flags);
prio(high) sync GetPropertyKeys(uint64_t objId, uint32_t flags) returns (ReturnStatus rs, JSIDVariant[] ids);

View File

@ -556,6 +556,32 @@ WrapperAnswer::RecvClassName(const ObjectId &objId, nsString *name)
return true;
}
bool
WrapperAnswer::RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result)
{
*result = NullVariant();
AutoJSAPI jsapi;
if (NS_WARN_IF(!jsapi.Init(scopeForTargetObjects())))
return false;
JSContext *cx = jsapi.cx();
RootedObject obj(cx, findObjectById(cx, objId));
if (!obj)
return fail(cx, rs);
JS::RootedObject proto(cx);
if (!JS_GetPrototype(cx, obj, &proto))
return fail(cx, rs);
if (!toObjectOrNullVariant(cx, proto, result))
return fail(cx, rs);
LOG("getPrototypeOf(%s)", ReceiverObj(objId));
return ok(rs);
}
bool
WrapperAnswer::RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs,
nsString *source, uint32_t *flags)

View File

@ -53,6 +53,7 @@ class WrapperAnswer : public virtual JavaScriptShared
bool RecvObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result);
bool RecvClassName(const ObjectId &objId, nsString *result);
bool RecvGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result);
bool RecvRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source, uint32_t *flags);
bool RecvGetPropertyKeys(const ObjectId &objId, const uint32_t &flags,

View File

@ -120,6 +120,7 @@ class CPOWProxyHandler : public BaseProxyHandler
virtual void objectMoved(JSObject *proxy, const JSObject *old) const MOZ_OVERRIDE;
virtual bool isCallable(JSObject *obj) const MOZ_OVERRIDE;
virtual bool isConstructor(JSObject *obj) const MOZ_OVERRIDE;
virtual bool getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject protop) const MOZ_OVERRIDE;
static const char family;
static const CPOWProxyHandler singleton;
@ -678,6 +679,32 @@ WrapperOwner::className(JSContext *cx, HandleObject proxy)
return ToNewCString(name);
}
bool
CPOWProxyHandler::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject objp) const
{
FORWARD(getPrototypeOf, (cx, proxy, objp));
}
bool
WrapperOwner::getPrototypeOf(JSContext *cx, HandleObject proxy, MutableHandleObject objp)
{
ObjectId objId = idOf(proxy);
ObjectOrNullVariant val;
ReturnStatus status;
if (!SendGetPrototypeOf(objId, &status, &val))
return ipcfail(cx);
LOG_STACK();
if (!ok(cx, status))
return false;
objp.set(fromObjectOrNullVariant(cx, val));
return true;
}
bool
CPOWProxyHandler::regexp_toShared(JSContext *cx, HandleObject proxy, RegExpGuard *g) const
{
@ -986,11 +1013,15 @@ WrapperOwner::fromRemoteObjectVariant(JSContext *cx, RemoteObject objVar)
RootedObject junkScope(cx, xpc::PrivilegedJunkScope());
JSAutoCompartment ac(cx, junkScope);
RootedValue v(cx, UndefinedValue());
// We need to setLazyProto for the getPrototypeOf hook.
ProxyOptions options;
options.setLazyProto(true);
obj = NewProxyObject(cx,
&CPOWProxyHandler::singleton,
v,
nullptr,
junkScope);
junkScope,
options);
if (!obj)
return nullptr;

View File

@ -54,6 +54,8 @@ class WrapperOwner : public virtual JavaScriptShared
bool hasInstance(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleValue v, bool *bp);
bool objectClassIs(JSContext *cx, JS::HandleObject obj, js::ESClassValue classValue);
const char* className(JSContext *cx, JS::HandleObject proxy);
bool getPrototypeOf(JSContext *cx, JS::HandleObject proxy, JS::MutableHandleObject protop);
bool regexp_toShared(JSContext *cx, JS::HandleObject proxy, js::RegExpGuard *g);
nsresult instanceOf(JSObject *obj, const nsID *id, bool *bp);
@ -134,6 +136,7 @@ class WrapperOwner : public virtual JavaScriptShared
virtual bool SendObjectClassIs(const ObjectId &objId, const uint32_t &classValue,
bool *result) = 0;
virtual bool SendClassName(const ObjectId &objId, nsString *result) = 0;
virtual bool SendGetPrototypeOf(const ObjectId &objId, ReturnStatus *rs, ObjectOrNullVariant *result) = 0;
virtual bool SendRegExpToShared(const ObjectId &objId, ReturnStatus *rs, nsString *source,
uint32_t *flags) = 0;