From 15df9eaaec39ba11925094a8d9c981548441fb63 Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Sun, 10 Oct 2010 15:39:26 -0700 Subject: [PATCH] bug 580128 - Allow proxies to answer the "hasInstance" question. r=mrbkap --- js/src/jscompartment.h | 2 +- js/src/jsproxy.cpp | 26 ++++++++++++++++++++++---- js/src/jsproxy.h | 1 + js/src/jswrapper.cpp | 21 +++++++++++++++++++++ js/src/jswrapper.h | 2 ++ 5 files changed, 47 insertions(+), 5 deletions(-) diff --git a/js/src/jscompartment.h b/js/src/jscompartment.h index 944b2dcd24b2..7add238c7d6c 100644 --- a/js/src/jscompartment.h +++ b/js/src/jscompartment.h @@ -49,7 +49,7 @@ #include "jsclist.h" #include "jsxml.h" -struct JSCompartment { +struct JS_FRIEND_API(JSCompartment) { JSRuntime *rt; JSPrincipals *principals; js::gc::Chunk *chunk; diff --git a/js/src/jsproxy.cpp b/js/src/jsproxy.cpp index 2daa9587acb7..85877cda3bc0 100644 --- a/js/src/jsproxy.cpp +++ b/js/src/jsproxy.cpp @@ -284,6 +284,15 @@ JSProxyHandler::construct(JSContext *cx, JSObject *proxy, return ExternalInvoke(cx, thisobj, fval, argc, argv, rval); } +bool +JSProxyHandler::hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, bool *bp) +{ + JS_ASSERT(OperationInProgress(cx, proxy)); + js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, + JSDVG_SEARCH_STACK, ObjectValue(*proxy), NULL); + return false; +} + void JSProxyHandler::finalize(JSContext *cx, JSObject *proxy) { @@ -920,6 +929,17 @@ proxy_Finalize(JSContext *cx, JSObject *obj) obj->getProxyHandler()->finalize(cx, obj); } +static JSBool +proxy_HasInstance(JSContext *cx, JSObject *proxy, const Value *v, JSBool *bp) +{ + AutoPendingProxyOperation pending(cx, proxy); + bool b; + if (!proxy->getProxyHandler()->hasInstance(cx, proxy, v, &b)) + return false; + *bp = !!b; + return true; +} + JS_FRIEND_API(Class) ObjectProxyClass = { "Proxy", Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(3), @@ -936,7 +956,7 @@ JS_FRIEND_API(Class) ObjectProxyClass = { NULL, /* call */ NULL, /* construct */ NULL, /* xdrObject */ - NULL, /* hasInstance */ + proxy_HasInstance, /* hasInstance */ NULL, /* mark */ JS_NULL_CLASS_EXT, { @@ -1022,8 +1042,6 @@ proxy_TypeOf_fun(JSContext *cx, JSObject *obj) return JSTYPE_FUNCTION; } -#define proxy_HasInstance js_FunctionClass.hasInstance - JS_FRIEND_API(Class) FunctionProxyClass = { "Proxy", Class::NON_NATIVE | JSCLASS_HAS_RESERVED_SLOTS(5), @@ -1040,7 +1058,7 @@ JS_FRIEND_API(Class) FunctionProxyClass = { proxy_Call, proxy_Construct, NULL, /* xdrObject */ - proxy_HasInstance, + js_FunctionClass.hasInstance, NULL, /* mark */ JS_NULL_CLASS_EXT, { diff --git a/js/src/jsproxy.h b/js/src/jsproxy.h index 53f447576e34..3f560e955971 100644 --- a/js/src/jsproxy.h +++ b/js/src/jsproxy.h @@ -79,6 +79,7 @@ class JS_FRIEND_API(JSProxyHandler) { virtual bool call(JSContext *cx, JSObject *proxy, uintN argc, js::Value *vp); virtual bool construct(JSContext *cx, JSObject *proxy, uintN argc, js::Value *argv, js::Value *rval); + virtual bool hasInstance(JSContext *cx, JSObject *proxy, const js::Value *vp, bool *bp); virtual JSString *obj_toString(JSContext *cx, JSObject *proxy); virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, uintN indent); virtual void finalize(JSContext *cx, JSObject *proxy); diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 003d138d40a1..9669b7da87d3 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -239,6 +239,14 @@ JSWrapper::construct(JSContext *cx, JSObject *wrapper, uintN argc, Value *argv, GET(JSProxyHandler::construct(cx, wrapper, argc, argv, rval)); } +bool +JSWrapper::hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) +{ + const jsid id = JSID_VOID; + JSBool b; + GET(JS_HasInstance(cx, wrappedObject(wrapper), Jsvalify(*vp), &b) && Cond(b, bp)); +} + JSString * JSWrapper::obj_toString(JSContext *cx, JSObject *wrapper) { @@ -604,6 +612,19 @@ JSCrossCompartmentWrapper::construct(JSContext *cx, JSObject *wrapper, uintN arg call.origin->wrapException(cx); } +bool +JSCrossCompartmentWrapper::hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) +{ + AutoCompartment call(cx, wrappedObject(wrapper)); + if (!call.enter()) + return false; + + Value v = *vp; + if (!call.destination->wrap(cx, &v)) + return false; + return JSWrapper::hasInstance(cx, wrapper, &v, bp); +} + JSString * JSCrossCompartmentWrapper::obj_toString(JSContext *cx, JSObject *wrapper) { diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index a7ff77102462..7840be30ab3b 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -83,6 +83,7 @@ class JS_FRIEND_API(JSWrapper) : public js::JSProxyHandler { virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp); virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *argv, js::Value *rval); + virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const js::Value *vp, bool *bp); virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper); virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent); @@ -135,6 +136,7 @@ class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper { virtual bool call(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *vp); virtual bool construct(JSContext *cx, JSObject *wrapper, uintN argc, js::Value *argv, js::Value *rval); + virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const js::Value *vp, bool *bp); virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper); virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);