diff -r 370ea18e73f5 js/src/jit-test/tests/basic/testCrossCompartmentTransparency2.js --- a/js/src/jit-test/tests/basic/testCrossCompartmentTransparency2.js Mon Apr 23 22:28:15 2012 -0400 +++ b/js/src/jit-test/tests/basic/testCrossCompartmentTransparency2.js Thu Apr 26 15:59:24 2012 -0400 @@ -8,18 +8,8 @@ var number = g.eval("new Number(42)"); var bool = g.eval("new Boolean(false)"); var string = g.eval("new String('ponies')"); assertEq(JSON.stringify({n:number, b:bool, s:string}), "{\"n\":42,\"b\":false,\"s\":\"ponies\"}"); assertEq(JSON.stringify({arr:array}), "{\"arr\":[1,2,3]}"); assertEq(JSON.stringify({2:'ponies', unicorns:'not real'}, array), "{\"2\":\"ponies\"}"); assertEq(JSON.stringify({42:true, ponies:true, unicorns:'sad'}, [number, string]), "{\"42\":true,\"ponies\":true}"); assertEq(JSON.stringify({a:true,b:false}, undefined, number), "{\n \"a\": true,\n \"b\": false\n}"); assertEq(JSON.stringify({a:true,b:false}, undefined, string), "{\nponies\"a\": true,\nponies\"b\": false\n}"); - -var o = Proxy.create({getPropertyDescriptor:function(name) {}}, Object.prototype); -var threw = false; -try { - print([].concat(o).toString()); -} catch(e) { - assertEq(e instanceof TypeError, true); - threw = true; -} -assertEq(threw, true); diff -r 370ea18e73f5 js/src/jit-test/tests/basic/testCrossGlobalInvokeSession.js --- a/js/src/jit-test/tests/basic/testCrossGlobalInvokeSession.js Mon Apr 23 22:28:15 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -otherGlobal = newGlobal("same-compartment"); -otherGlobal.poison = Proxy.create({}); -callee = new otherGlobal.Function("return this.poison;"); - -var caught = false; -try { - [1,2,3,4,5,6,7,8].sort(callee); -} catch(e) { - assertEq(e instanceof Error, true); - caught = true; -} -assertEq(caught, true); diff -r 370ea18e73f5 js/src/jit-test/tests/basic/testReconstructImacroPCStack.js --- a/js/src/jit-test/tests/basic/testReconstructImacroPCStack.js Mon Apr 23 22:28:15 2012 -0400 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -x = Proxy.create((function () { - return { - get: function () {} - } -}()), Object.e) - -var hit = false; - -try { - Function("\ - for(var a = 0; a < 2; ++a) {\ - if (a == 0) {}\ - else {\ - x > x\ - }\ - }\ - ")() -} catch (e) { - hit = true; - - var str = String(e); - var match = (str == "TypeError: x is not a function" || - str == "TypeError: can't convert x to number"); - - assertEq(match, true); -} - -assertEq(hit, true); diff -r 370ea18e73f5 js/src/jsproxy.cpp --- a/js/src/jsproxy.cpp Mon Apr 23 22:28:15 2012 -0400 +++ b/js/src/jsproxy.cpp Thu Apr 26 15:59:24 2012 -0400 @@ -41,21 +41,22 @@ #include #include "jsapi.h" #include "jscntxt.h" #include "jsgc.h" #include "jsgcmark.h" #include "jsprvtd.h" #include "jsnum.h" -#include "jsobj.h" +#include "jsobjinlines.h" #include "jsproxy.h" #include "jsscope.h" #include "vm/MethodGuard.h" +#include "vm/RegExpObject-inl.h" #include "jsatominlines.h" #include "jsinferinlines.h" #include "jsobjinlines.h" using namespace js; using namespace js::gc; @@ -276,40 +277,52 @@ ProxyHandler::iterate(JSContext *cx, JSO if ((flags & JSITER_OWNONLY) ? !keys(cx, proxy, props) : !enumerate(cx, proxy, props)) { return false; } return EnumeratedIdVectorToIterator(cx, proxy, flags, props, vp); } +bool +ProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc, + Value *vp) +{ + Value v = UndefinedValue(); + js_ReportIsNotFunction(cx, &v, 0); + return false; +} + +bool +ProxyHandler::construct(JSContext *cx, JSObject *proxy, unsigned argc, + Value *argv, Value *rval) +{ + Value v = UndefinedValue(); + js_ReportIsNotFunction(cx, &v, JSV2F_CONSTRUCT); + return false; +} + JSString * ProxyHandler::obj_toString(JSContext *cx, JSObject *proxy) { - JS_ASSERT(proxy->isProxy()); - - return JS_NewStringCopyZ(cx, IsFunctionProxy(proxy) - ? "[object Function]" - : "[object Object]"); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, + js_Object_str, js_toString_str, + "object"); + return NULL; } JSString * ProxyHandler::fun_toString(JSContext *cx, JSObject *proxy, unsigned indent) { - JS_ASSERT(proxy->isProxy()); - Value fval = GetCall(proxy); - if (IsFunctionProxy(proxy) && - (fval.isPrimitive() || !fval.toObject().isFunction())) { - JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, - JSMSG_INCOMPATIBLE_PROTO, - js_Function_str, js_toString_str, - "object"); - return NULL; - } - return fun_toStringHelper(cx, &fval.toObject(), indent); + JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL, + JSMSG_INCOMPATIBLE_PROTO, + js_Function_str, js_toString_str, + "object"); + return NULL; } bool ProxyHandler::regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) { JS_NOT_REACHED("This should have been a wrapped regexp"); return false; } @@ -323,51 +336,29 @@ ProxyHandler::defaultValue(JSContext *cx bool ProxyHandler::iteratorNext(JSContext *cx, JSObject *proxy, Value *vp) { vp->setMagic(JS_NO_ITER_VALUE); return true; } bool -ProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc, Value *vp) -{ - JS_ASSERT(OperationInProgress(cx, proxy)); - AutoValueRooter rval(cx); - JSBool ok = Invoke(cx, vp[1], GetCall(proxy), argc, JS_ARGV(cx, vp), rval.addr()); - if (ok) - JS_SET_RVAL(cx, vp, rval.value()); - return ok; -} - -bool -ProxyHandler::construct(JSContext *cx, JSObject *proxy, - unsigned argc, Value *argv, Value *rval) -{ - JS_ASSERT(OperationInProgress(cx, proxy)); - Value fval = GetConstruct(proxy); - if (fval.isUndefined()) - return InvokeConstructor(cx, GetCall(proxy), argc, argv, rval); - return Invoke(cx, UndefinedValue(), fval, argc, argv, rval); -} - -bool ProxyHandler::nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, Native native, CallArgs args) { JS_ASSERT(OperationInProgress(cx, proxy)); ReportIncompatibleMethod(cx, args, clasp); return false; } bool ProxyHandler::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); + js_ReportValueError(cx, JSMSG_BAD_INSTANCEOF_RHS, JSDVG_SEARCH_STACK, + ObjectValue(*proxy), NULL); return false; } JSType ProxyHandler::typeOf(JSContext *cx, JSObject *proxy) { JS_ASSERT(OperationInProgress(cx, proxy)); return IsFunctionProxy(proxy) ? JSTYPE_FUNCTION : JSTYPE_OBJECT; @@ -385,16 +376,194 @@ ProxyHandler::finalize(JSFreeOp *fop, JS { } void ProxyHandler::trace(JSTracer *trc, JSObject *proxy) { } +AbstractProxyHandler::AbstractProxyHandler(void *family) : ProxyHandler(family) +{ +} + +bool +AbstractProxyHandler::getPropertyDescriptor(JSContext *cx, JSObject *proxy, + jsid id, bool set, + PropertyDescriptor *desc) +{ + return JS_GetPropertyDescriptorById(cx, GetProxyTargetObject(proxy), id, + JSRESOLVE_QUALIFIED, desc); +} + +static bool +GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSPropertyDescriptor *desc) +{ + // If obj is a proxy, we can do better than just guessing. This is + // important for certain types of wrappers that wrap other wrappers. + if (obj->isProxy()) + return Proxy::getOwnPropertyDescriptor(cx, obj, id, flags & JSRESOLVE_ASSIGNING, desc); + + if (!JS_GetPropertyDescriptorById(cx, obj, id, flags, desc)) + return false; + if (desc->obj != obj) + desc->obj = NULL; + return true; +} + +bool +AbstractProxyHandler::getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, + jsid id, bool set, + PropertyDescriptor *desc) +{ + return GetOwnPropertyDescriptor(cx, GetProxyTargetObject(proxy), id, + JSRESOLVE_QUALIFIED, desc); +} + +bool +AbstractProxyHandler::defineProperty(JSContext *cx, JSObject *proxy, jsid id, + PropertyDescriptor *desc) +{ + return JS_DefinePropertyById(cx, GetProxyTargetObject(proxy), id, + desc->value, desc->getter, desc->setter, + desc->attrs); +} + +bool +AbstractProxyHandler::getOwnPropertyNames(JSContext *cx, JSObject *proxy, + AutoIdVector &props) +{ + return GetPropertyNames(cx, GetProxyTargetObject(proxy), + JSITER_OWNONLY | JSITER_HIDDEN, &props); +} + +bool +AbstractProxyHandler::delete_(JSContext *cx, JSObject *proxy, jsid id, bool *bp) +{ + Value v; + if (!JS_DeletePropertyById2(cx, GetProxyTargetObject(proxy), id, &v)) + return false; + JSBool b; + if (!JS_ValueToBoolean(cx, v, &b)) + return false; + *bp = !!b; + return true; +} + +bool +AbstractProxyHandler::enumerate(JSContext *cx, JSObject *proxy, + AutoIdVector &props) +{ + return GetPropertyNames(cx, GetProxyTargetObject(proxy), 0, &props); +} + +bool +AbstractProxyHandler::call(JSContext *cx, JSObject *proxy, unsigned argc, + Value *vp) +{ + JS_ASSERT(OperationInProgress(cx, proxy)); + AutoValueRooter rval(cx); + JSBool ok = Invoke(cx, vp[1], GetCall(proxy), argc, JS_ARGV(cx, vp), rval.addr()); + if (ok) + JS_SET_RVAL(cx, vp, rval.value()); + return ok; +} + +bool +AbstractProxyHandler::construct(JSContext *cx, JSObject *proxy, unsigned argc, + Value *argv, Value *rval) +{ + JS_ASSERT(OperationInProgress(cx, proxy)); + Value fval = GetConstruct(proxy); + if (fval.isUndefined()) + return InvokeConstructor(cx, GetCall(proxy), argc, argv, rval); + return Invoke(cx, UndefinedValue(), fval, argc, argv, rval); +} + +bool +AbstractProxyHandler::nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, + Native native, CallArgs args) +{ + return CallJSNative(cx, native, args); +} + +bool +AbstractProxyHandler::hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, + bool *bp) MOZ_OVERRIDE +{ + JSBool b; + if (!JS_HasInstance(cx, GetProxyTargetObject(proxy), *vp, &b)) + return false; + *bp = !!b; + return true; +} + +JSType +AbstractProxyHandler::typeOf(JSContext *cx, JSObject *proxy) +{ + return TypeOfValue(cx, ObjectValue(*GetProxyTargetObject(proxy))); +} + +bool +AbstractProxyHandler::objectClassIs(JSObject *proxy, ESClassValue classValue, + JSContext *cx) +{ + return ObjectClassIs(*GetProxyTargetObject(proxy), classValue, cx); +} + +JSString * +AbstractProxyHandler::obj_toString(JSContext *cx, JSObject *proxy) +{ + return obj_toStringHelper(cx, GetProxyTargetObject(proxy)); +} + +JSString * +AbstractProxyHandler::fun_toString(JSContext *cx, JSObject *proxy, + unsigned indent) +{ + return fun_toStringHelper(cx, GetProxyTargetObject(proxy), indent); +} + +bool +AbstractProxyHandler::regexp_toShared(JSContext *cx, JSObject *proxy, + RegExpGuard *g) +{ + return GetProxyTargetObject(proxy)->asRegExp().getShared(cx, g); +} + +bool +AbstractProxyHandler::defaultValue(JSContext *cx, JSObject *proxy, JSType hint, + Value *vp) +{ + *vp = ObjectValue(*GetProxyTargetObject(proxy)); + if (hint == JSTYPE_VOID) + return ToPrimitive(cx, vp); + return ToPrimitive(cx, hint, vp); +} + +bool +AbstractProxyHandler::iteratorNext(JSContext *cx, JSObject *proxy, Value *vp) +{ + if (!js_IteratorMore(cx, RootedVarObject(cx, GetProxyTargetObject(proxy)), + vp)) + return false; + if (vp->toBoolean()) { + *vp = cx->iterValue; + cx->iterValue.setUndefined(); + } else + vp->setMagic(JS_NO_ITER_VALUE); + return true; +} + +void +AbstractProxyHandler::trace(JSTracer *trc, JSObject *proxy) +{ + MarkSlot(trc, &proxy->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "targetObject"); +} + static bool GetTrap(JSContext *cx, JSObject *handler, JSAtom *atom, Value *fvalp) { JS_CHECK_RECURSION(cx, return false); return handler->getGeneric(cx, ATOM_TO_JSID(atom), fvalp); } @@ -511,17 +680,17 @@ ArrayToIdVector(JSContext *cx, const Val if (!props.append(js_CheckForStringIndex(id))) return false; } return true; } /* Derived class for all scripted proxy handlers. */ -class ScriptedProxyHandler : public ProxyHandler { +class ScriptedProxyHandler : public AbstractProxyHandler { public: ScriptedProxyHandler(); virtual ~ScriptedProxyHandler(); /* ES5 Harmony fundamental proxy traps. */ virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, PropertyDescriptor *desc); virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, @@ -541,17 +710,17 @@ class ScriptedProxyHandler : public Prox virtual bool keys(JSContext *cx, JSObject *proxy, AutoIdVector &props); virtual bool iterate(JSContext *cx, JSObject *proxy, unsigned flags, Value *vp); static ScriptedProxyHandler singleton; }; static int sScriptedProxyHandlerFamily = 0; -ScriptedProxyHandler::ScriptedProxyHandler() : ProxyHandler(&sScriptedProxyHandlerFamily) +ScriptedProxyHandler::ScriptedProxyHandler() : AbstractProxyHandler(&sScriptedProxyHandlerFamily) { } ScriptedProxyHandler::~ScriptedProxyHandler() { } static bool diff -r 370ea18e73f5 js/src/jsproxy.h --- a/js/src/jsproxy.h Mon Apr 23 22:28:15 2012 -0400 +++ b/js/src/jsproxy.h Thu Apr 26 15:59:24 2012 -0400 @@ -95,16 +95,60 @@ class JS_FRIEND_API(ProxyHandler) { return false; } inline void *family() { return mFamily; } }; +class JS_PUBLIC_API(AbstractProxyHandler) : public ProxyHandler { + public: + explicit AbstractProxyHandler(void *family); + + /* ES5 Harmony fundamental proxy traps. */ + virtual bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, + bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, + jsid id, bool set, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool defineProperty(JSContext *cx, JSObject *proxy, jsid id, + PropertyDescriptor *desc) MOZ_OVERRIDE; + virtual bool getOwnPropertyNames(JSContext *cx, JSObject *proxy, + AutoIdVector &props) MOZ_OVERRIDE; + virtual bool delete_(JSContext *cx, JSObject *proxy, jsid id, + bool *bp) MOZ_OVERRIDE; + virtual bool enumerate(JSContext *cx, JSObject *proxy, + AutoIdVector &props) MOZ_OVERRIDE; + + /* Spidermonkey extensions. */ + virtual bool call(JSContext *cx, JSObject *proxy, unsigned argc, + Value *vp) MOZ_OVERRIDE; + virtual bool construct(JSContext *cx, JSObject *proxy, unsigned argc, + Value *argv, Value *rval) MOZ_OVERRIDE; + virtual bool nativeCall(JSContext *cx, JSObject *proxy, Class *clasp, + Native native, CallArgs args) MOZ_OVERRIDE; + virtual bool hasInstance(JSContext *cx, JSObject *proxy, const Value *vp, + bool *bp) MOZ_OVERRIDE; + virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; + virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, + JSContext *cx) MOZ_OVERRIDE; + virtual JSString *obj_toString(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; + virtual JSString *fun_toString(JSContext *cx, JSObject *proxy, + unsigned indent) MOZ_OVERRIDE; + virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, + RegExpGuard *g) MOZ_OVERRIDE; + virtual bool defaultValue(JSContext *cx, JSObject *obj, JSType hint, + Value *vp) MOZ_OVERRIDE; + virtual bool iteratorNext(JSContext *cx, JSObject *proxy, + Value *vp) MOZ_OVERRIDE; + virtual void trace(JSTracer *trc, JSObject *proxy) MOZ_OVERRIDE; +}; + /* Dispatch point for handlers that executes the appropriate C++ or scripted traps. */ class Proxy { public: /* ES5 Harmony fundamental proxy traps. */ static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, PropertyDescriptor *desc); static bool getPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, Value *vp); static bool getOwnPropertyDescriptor(JSContext *cx, JSObject *proxy, jsid id, bool set, @@ -185,16 +229,23 @@ GetProxyHandler(const JSObject *obj) inline const Value & GetProxyPrivate(const JSObject *obj) { JS_ASSERT(IsProxy(obj)); return GetReservedSlot(obj, JSSLOT_PROXY_PRIVATE); } +inline JSObject * +GetProxyTargetObject(const JSObject *obj) +{ + JS_ASSERT(IsProxy(obj)); + return GetProxyPrivate(obj).toObjectOrNull(); +} + inline const Value & GetProxyExtra(const JSObject *obj, size_t n) { JS_ASSERT(IsProxy(obj)); return GetReservedSlot(obj, JSSLOT_PROXY_EXTRA + n); } inline void diff -r 370ea18e73f5 js/src/jswrapper.cpp --- a/js/src/jswrapper.cpp Mon Apr 23 22:28:15 2012 -0400 +++ b/js/src/jswrapper.cpp Thu Apr 26 15:59:24 2012 -0400 @@ -108,17 +108,17 @@ js::UnwrapObjectChecked(JSContext *cx, J bool js::IsCrossCompartmentWrapper(const JSObject *wrapper) { return wrapper->isWrapper() && !!(Wrapper::wrapperHandler(wrapper)->flags() & Wrapper::CROSS_COMPARTMENT); } AbstractWrapper::AbstractWrapper(unsigned flags) : - ProxyHandler(&sWrapperFamily), + AbstractProxyHandler(&sWrapperFamily), mFlags(flags) { } Wrapper::Wrapper(unsigned flags) : AbstractWrapper(flags) { } @@ -134,88 +134,16 @@ Wrapper::~Wrapper() bool ok = (op); \ leave(cx, wrapper); \ return ok; \ JS_END_MACRO #define SET(action) CHECKED(action, SET) #define GET(action) CHECKED(action, GET) -bool -AbstractWrapper::getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc) -{ - desc->obj = NULL; // default result if we refuse to perform this action - CHECKED(JS_GetPropertyDescriptorById(cx, wrappedObject(wrapper), id, JSRESOLVE_QUALIFIED, desc), - set ? SET : GET); -} - -static bool -GetOwnPropertyDescriptor(JSContext *cx, JSObject *obj, jsid id, unsigned flags, JSPropertyDescriptor *desc) -{ - // If obj is a proxy, we can do better than just guessing. This is - // important for certain types of wrappers that wrap other wrappers. - if (obj->isProxy()) - return Proxy::getOwnPropertyDescriptor(cx, obj, id, flags & JSRESOLVE_ASSIGNING, desc); - - if (!JS_GetPropertyDescriptorById(cx, obj, id, flags, desc)) - return false; - if (desc->obj != obj) - desc->obj = NULL; - return true; -} - -bool -AbstractWrapper::getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc) -{ - desc->obj = NULL; // default result if we refuse to perform this action - CHECKED(GetOwnPropertyDescriptor(cx, wrappedObject(wrapper), id, JSRESOLVE_QUALIFIED, desc), - set ? SET : GET); -} - -bool -AbstractWrapper::defineProperty(JSContext *cx, JSObject *wrapper, jsid id, PropertyDescriptor *desc) -{ - SET(JS_DefinePropertyById(cx, wrappedObject(wrapper), id, desc->value, - desc->getter, desc->setter, desc->attrs)); -} - -bool -AbstractWrapper::getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) -{ - // if we refuse to perform this action, props remains empty - jsid id = JSID_VOID; - GET(GetPropertyNames(cx, wrappedObject(wrapper), JSITER_OWNONLY | JSITER_HIDDEN, &props)); -} - -static bool -ValueToBoolean(Value *vp, bool *bp) -{ - *bp = js_ValueToBoolean(*vp); - return true; -} - -bool -AbstractWrapper::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) -{ - *bp = true; // default result if we refuse to perform this action - Value v; - SET(JS_DeletePropertyById2(cx, wrappedObject(wrapper), id, &v) && - ValueToBoolean(&v, bp)); -} - -bool -AbstractWrapper::enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) -{ - // if we refuse to perform this action, props remains empty - static jsid id = JSID_VOID; - GET(GetPropertyNames(cx, wrappedObject(wrapper), 0, &props)); -} - static bool Cond(JSBool b, bool *bp) { *bp = !!b; return true; } bool @@ -267,67 +195,54 @@ Wrapper::iterate(JSContext *cx, JSObject GET(GetIterator(cx, RootedVarObject(cx, wrappedObject(wrapper)), flags, vp)); } bool Wrapper::call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) { vp->setUndefined(); // default result if we refuse to perform this action const jsid id = JSID_VOID; - CHECKED(ProxyHandler::call(cx, wrapper, argc, vp), CALL); + CHECKED(AbstractProxyHandler::call(cx, wrapper, argc, vp), CALL); } bool Wrapper::construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *vp) { vp->setUndefined(); // default result if we refuse to perform this action const jsid id = JSID_VOID; - GET(ProxyHandler::construct(cx, wrapper, argc, argv, vp)); + GET(AbstractProxyHandler::construct(cx, wrapper, argc, argv, vp)); } bool Wrapper::nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) { const jsid id = JSID_VOID; - CHECKED(CallJSNative(cx, native, args), CALL); + CHECKED(AbstractProxyHandler::nativeCall(cx, wrapper, clasp, native, args), CALL); } bool Wrapper::hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) { *bp = false; // default result if we refuse to perform this action const jsid id = JSID_VOID; - JSBool b = JS_FALSE; - GET(JS_HasInstance(cx, wrappedObject(wrapper), *vp, &b) && Cond(b, bp)); -} - -JSType -Wrapper::typeOf(JSContext *cx, JSObject *wrapper) -{ - return TypeOfValue(cx, ObjectValue(*wrappedObject(wrapper))); -} - -bool -Wrapper::objectClassIs(JSObject *wrapper, ESClassValue classValue, JSContext *cx) -{ - return ObjectClassIs(*wrappedObject(wrapper), classValue, cx); + GET(AbstractProxyHandler::hasInstance(cx, wrapper, vp, bp)); } JSString * Wrapper::obj_toString(JSContext *cx, JSObject *wrapper) { bool status; if (!enter(cx, wrapper, JSID_VOID, GET, &status)) { if (status) { // Perform some default behavior that doesn't leak any information. return JS_NewStringCopyZ(cx, "[object Object]"); } return NULL; } - JSString *str = obj_toStringHelper(cx, wrappedObject(wrapper)); + JSString *str = AbstractProxyHandler::obj_toString(cx, wrapper); leave(cx, wrapper); return str; } JSString * Wrapper::fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) { bool status; @@ -337,57 +252,21 @@ Wrapper::fun_toString(JSContext *cx, JSO if (wrapper->isCallable()) return JS_NewStringCopyZ(cx, "function () {\n [native code]\n}"); js::Value v = ObjectValue(*wrapper); js_ReportIsNotFunction(cx, &v, 0); return NULL; } return NULL; } - JSString *str = ProxyHandler::fun_toString(cx, wrapper, indent); + JSString *str = AbstractProxyHandler::fun_toString(cx, wrapper, indent); leave(cx, wrapper); return str; } -bool -Wrapper::regexp_toShared(JSContext *cx, JSObject *wrapper, RegExpGuard *g) -{ - return wrappedObject(wrapper)->asRegExp().getShared(cx, g); -} - -bool -Wrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) -{ - *vp = ObjectValue(*wrappedObject(wrapper)); - if (hint == JSTYPE_VOID) - return ToPrimitive(cx, vp); - return ToPrimitive(cx, hint, vp); -} - -bool -Wrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) -{ - if (!js_IteratorMore(cx, RootedVarObject(cx, wrappedObject(wrapper)), vp)) - return false; - - if (vp->toBoolean()) { - *vp = cx->iterValue; - cx->iterValue.setUndefined(); - } else { - vp->setMagic(JS_NO_ITER_VALUE); - } - return true; -} - -void -Wrapper::trace(JSTracer *trc, JSObject *wrapper) -{ - MarkSlot(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), "wrappedObject"); -} - JSObject * AbstractWrapper::wrappedObject(const JSObject *wrapper) { return GetProxyPrivate(wrapper).toObjectOrNull(); } AbstractWrapper * AbstractWrapper::wrapperHandler(const JSObject *wrapper) @@ -865,37 +744,37 @@ CrossCompartmentWrapper::fun_toString(JS bool CrossCompartmentWrapper::defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) { AutoCompartment call(cx, wrappedObject(wrapper)); if (!call.enter()) return false; - if (!Wrapper::defaultValue(cx, wrapper, hint, vp)) + if (!AbstractProxyHandler::defaultValue(cx, wrapper, hint, vp)) return false; call.leave(); return call.origin->wrap(cx, vp); } bool CrossCompartmentWrapper::iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) { PIERCE(cx, wrapper, GET, NOTHING, - Wrapper::iteratorNext(cx, wrapper, vp), + AbstractProxyHandler::iteratorNext(cx, wrapper, vp), call.origin->wrap(cx, vp)); } void CrossCompartmentWrapper::trace(JSTracer *trc, JSObject *wrapper) { MarkCrossCompartmentSlot(trc, &wrapper->getReservedSlotRef(JSSLOT_PROXY_PRIVATE), - "wrappedObject"); + "targetObject"); } CrossCompartmentWrapper CrossCompartmentWrapper::singleton(0u); /* Security wrappers. */ template SecurityWrapper::SecurityWrapper(unsigned flags) diff -r 370ea18e73f5 js/src/jswrapper.h --- a/js/src/jswrapper.h Mon Apr 23 22:28:15 2012 -0400 +++ b/js/src/jswrapper.h Thu Apr 26 15:59:24 2012 -0400 @@ -51,35 +51,24 @@ namespace js { class DummyFrameGuard; /* Base class that just implements no-op forwarding methods for fundamental * traps. This is meant to be used as a base class for ProxyHandlers that * want transparent forwarding behavior but don't want to use the derived * traps and other baggage of js::Wrapper. */ -class JS_FRIEND_API(AbstractWrapper) : public ProxyHandler +class JS_FRIEND_API(AbstractWrapper) : public AbstractProxyHandler { unsigned mFlags; public: unsigned flags() const { return mFlags; } explicit AbstractWrapper(unsigned flags); - /* ES5 Harmony fundamental wrapper traps. */ - virtual bool getPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool getOwnPropertyDescriptor(JSContext *cx, JSObject *wrapper, jsid id, bool set, - PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool defineProperty(JSContext *cx, JSObject *wrapper, jsid id, - PropertyDescriptor *desc) MOZ_OVERRIDE; - virtual bool getOwnPropertyNames(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; - virtual bool delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp) MOZ_OVERRIDE; - virtual bool enumerate(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; - /* Policy enforcement traps. * * enter() allows the policy to specify whether the caller may perform |act| * on the underlying object's |id| property. In the case when |act| is CALL, * |id| is generally JSID_VOID. * * leave() allows the policy to undo various scoped state changes taken in * enter(). If enter() succeeds, leave() must be called upon completion of @@ -130,25 +119,18 @@ class JS_FRIEND_API(Wrapper) : public Ab virtual bool keys(JSContext *cx, JSObject *wrapper, AutoIdVector &props) MOZ_OVERRIDE; virtual bool iterate(JSContext *cx, JSObject *wrapper, unsigned flags, Value *vp) MOZ_OVERRIDE; /* Spidermonkey extensions. */ virtual bool call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) MOZ_OVERRIDE; virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE; virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE; virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE; - virtual JSType typeOf(JSContext *cx, JSObject *proxy) MOZ_OVERRIDE; - virtual bool objectClassIs(JSObject *obj, ESClassValue classValue, JSContext *cx) MOZ_OVERRIDE; virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE; - virtual bool regexp_toShared(JSContext *cx, JSObject *proxy, RegExpGuard *g) MOZ_OVERRIDE; - virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE; - virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp) MOZ_OVERRIDE; - - virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE; using AbstractWrapper::Action; static Wrapper singleton; static JSObject *New(JSContext *cx, JSObject *obj, JSObject *proto, JSObject *parent, Wrapper *handler); @@ -195,18 +177,17 @@ class JS_FRIEND_API(CrossCompartmentWrap virtual bool call(JSContext *cx, JSObject *wrapper, unsigned argc, Value *vp) MOZ_OVERRIDE; virtual bool construct(JSContext *cx, JSObject *wrapper, unsigned argc, Value *argv, Value *rval) MOZ_OVERRIDE; virtual bool nativeCall(JSContext *cx, JSObject *wrapper, Class *clasp, Native native, CallArgs args) MOZ_OVERRIDE; virtual bool hasInstance(JSContext *cx, JSObject *wrapper, const Value *vp, bool *bp) MOZ_OVERRIDE; virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper) MOZ_OVERRIDE; virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, unsigned indent) MOZ_OVERRIDE; virtual bool defaultValue(JSContext *cx, JSObject *wrapper, JSType hint, Value *vp) MOZ_OVERRIDE; virtual bool iteratorNext(JSContext *cx, JSObject *wrapper, Value *vp); - - virtual void trace(JSTracer *trc, JSObject *wrapper) MOZ_OVERRIDE; + virtual void trace(JSTracer *trc, JSObject *wrapper); static CrossCompartmentWrapper singleton; }; /* * Base class for security wrappers. A security wrapper is potentially hiding * all or part of some wrapped object thus SecurityWrapper defaults to denying * access to the wrappee. This is the opposite of Wrapper which tries to be