Bug 633879 - Stop wrappers from holding old scopes alive. r=mrbkap@gmail.com,jst@mozilla.com, a=blocker

This commit is contained in:
Andreas Gal 2011-02-14 14:19:36 -08:00
Родитель 8f23700918
Коммит 31e333792b
4 изменённых файлов: 21 добавлений и 12 удалений

Просмотреть файл

@ -45,6 +45,7 @@
#include "jsproxy.h" #include "jsproxy.h"
#include "jsscope.h" #include "jsscope.h"
#include "jstracer.h" #include "jstracer.h"
#include "jswrapper.h"
#include "assembler/wtf/Platform.h" #include "assembler/wtf/Platform.h"
#include "methodjit/MethodJIT.h" #include "methodjit/MethodJIT.h"
#include "methodjit/PolyIC.h" #include "methodjit/PolyIC.h"
@ -176,6 +177,12 @@ JSCompartment::arenaListsAreEmpty()
return true; return true;
} }
static bool
IsCrossCompartmentWrapper(JSObject *wrapper)
{
return !!(JSWrapper::wrapperHandler(wrapper)->flags() & JSWrapper::CROSS_COMPARTMENT);
}
bool bool
JSCompartment::wrap(JSContext *cx, Value *vp) 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 we already have a wrapper for this value, use it. */
if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) { if (WrapperMap::Ptr p = crossCompartmentWrappers.lookup(*vp)) {
*vp = p->value; *vp = p->value;
if (vp->isObject()) if (vp->isObject()) {
vp->toObject().setParent(global); 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; return true;
} }

Просмотреть файл

@ -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) \ #define PIERCE(cx, wrapper, mode, pre, op, post) \
JS_BEGIN_MACRO \ JS_BEGIN_MACRO \
AutoCompartment call(cx, wrappedObject(wrapper)); \ AutoCompartment call(cx, wrappedObject(wrapper)); \

Просмотреть файл

@ -151,8 +151,6 @@ class JS_FRIEND_API(JSCrossCompartmentWrapper) : public JSWrapper {
virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper); virtual JSString *obj_toString(JSContext *cx, JSObject *wrapper);
virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent); virtual JSString *fun_toString(JSContext *cx, JSObject *wrapper, uintN indent);
static bool isCrossCompartmentWrapper(JSObject *obj);
static JSCrossCompartmentWrapper singleton; static JSCrossCompartmentWrapper singleton;
}; };

Просмотреть файл

@ -3459,8 +3459,10 @@ EvalInContext(JSContext *cx, uintN argc, jsval *vp)
JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL); JSStackFrame *fp = JS_GetScriptedCaller(cx, NULL);
{ {
JSAutoEnterCompartment ac; JSAutoEnterCompartment ac;
if (JSCrossCompartmentWrapper::isCrossCompartmentWrapper(sobj)) { uintN flags;
sobj = sobj->unwrap(); JSObject *unwrapped = sobj->unwrap(&flags);
if (flags & JSWrapper::CROSS_COMPARTMENT) {
sobj = unwrapped;
if (!ac.enter(cx, sobj)) if (!ac.enter(cx, sobj))
return false; return false;
} }