diff --git a/js/src/jscompartment.cpp b/js/src/jscompartment.cpp index b8a8ae90439a..2076c2b7b619 100644 --- a/js/src/jscompartment.cpp +++ b/js/src/jscompartment.cpp @@ -45,6 +45,7 @@ #include "jsproxy.h" #include "jsscope.h" #include "jstracer.h" +#include "jswrapper.h" #include "assembler/wtf/Platform.h" #include "methodjit/MethodJIT.h" #include "methodjit/PolyIC.h" @@ -176,6 +177,12 @@ JSCompartment::arenaListsAreEmpty() return true; } +static bool +IsCrossCompartmentWrapper(JSObject *wrapper) +{ + return !!(JSWrapper::wrapperHandler(wrapper)->flags() & JSWrapper::CROSS_COMPARTMENT); +} + bool JSCompartment::wrap(JSContext *cx, Value *vp) { @@ -276,8 +283,16 @@ JSCompartment::wrap(JSContext *cx, Value *vp) /* If we already have a wrapper for this value, use it. */ if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) { *vp = p->value; - if (vp->isObject()) - vp->toObject().setParent(global); + if (vp->isObject()) { + JSObject *obj = &vp->toObject(); + JS_ASSERT(IsCrossCompartmentWrapper(obj)); + if (obj->getParent() != global) { + do { + obj->setParent(global); + obj = obj->getProto(); + } while (obj && IsCrossCompartmentWrapper(obj)); + } + } return true; } diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index eea30a8c2b39..8e4e0c875790 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -417,12 +417,6 @@ JSCrossCompartmentWrapper::~JSCrossCompartmentWrapper() { } -bool -JSCrossCompartmentWrapper::isCrossCompartmentWrapper(JSObject *obj) -{ - return obj->isProxy() && obj->getProxyHandler() == &JSCrossCompartmentWrapper::singleton; -} - #define PIERCE(cx, wrapper, mode, pre, op, post) \ JS_BEGIN_MACRO \ AutoCompartment call(cx, wrappedObject(wrapper)); \ diff --git a/js/src/jswrapper.h b/js/src/jswrapper.h index 86dee77a8f45..23514ff0a50e 100644 --- a/js/src/jswrapper.h +++ b/js/src/jswrapper.h @@ -151,8 +151,6 @@ class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper { virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper); virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent); - static bool isCrossCompartmentWrapper(JSObject *obj); - static JSCrossCompartmentWrapper singleton; }; diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index a159cdac4431..9605ba770829 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -3459,8 +3459,10 @@ EvalInContext(JSContext *cx, uintN argc, jsval *vp) JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL); { JSAutoEnterCompartment ac; - if (JSCrossCompartmentWrapper::isCrossCompartmentWrapper(sobj)) { - sobj = sobj->unwrap(); + uintN flags; + JSObject *unwrapped = sobj->unwrap(&flags); + if (flags & JSWrapper::CROSS_COMPARTMENT) { + sobj = unwrapped; if (!ac.enter(cx, sobj)) return false; }