Bug 691192 - JSAutoEnterCompartment::enter shouldn't malloc(). r=luke

--HG--
extra : rebase_source : da6559e93617f17aca01fb9dd3ca7f08361696cd
This commit is contained in:
Justin Lebar 2011-10-04 15:25:18 -04:00
parent e89848a4cc
commit 1696317323
2 changed files with 47 additions and 17 deletions

View File

@ -1323,13 +1323,20 @@ JS_LeaveCrossCompartmentCall(JSCrossCompartmentCall *call)
bool bool
JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target) JSAutoEnterCompartment::enter(JSContext *cx, JSObject *target)
{ {
JS_ASSERT(!call); JS_ASSERT(state == STATE_UNENTERED);
if (cx->compartment == target->compartment()) { if (cx->compartment == target->compartment()) {
call = reinterpret_cast<JSCrossCompartmentCall*>(1); state = STATE_SAME_COMPARTMENT;
return true; return true;
} }
call = JS_EnterCrossCompartmentCall(cx, target);
return call != NULL; JS_STATIC_ASSERT(sizeof(bytes) == sizeof(AutoCompartment));
CHECK_REQUEST(cx);
AutoCompartment *call = new (bytes) AutoCompartment(cx, target);
if (call->enter()) {
state = STATE_OTHER_COMPARTMENT;
return true;
}
return false;
} }
void void
@ -1338,6 +1345,15 @@ JSAutoEnterCompartment::enterAndIgnoreErrors(JSContext *cx, JSObject *target)
(void) enter(cx, target); (void) enter(cx, target);
} }
JSAutoEnterCompartment::~JSAutoEnterCompartment()
{
if (state == STATE_OTHER_COMPARTMENT) {
AutoCompartment* ac = reinterpret_cast<AutoCompartment*>(bytes);
CHECK_REQUEST(ac->context);
ac->~AutoCompartment();
}
}
namespace JS { namespace JS {
bool bool

View File

@ -2214,27 +2214,41 @@ JS_END_EXTERN_C
class JS_PUBLIC_API(JSAutoEnterCompartment) class JS_PUBLIC_API(JSAutoEnterCompartment)
{ {
JSCrossCompartmentCall *call; /*
* This is a poor man's Maybe<AutoCompartment>, because we don't have
* access to the AutoCompartment definition here. We statically assert in
* jsapi.cpp that we have the right size here.
*/
#if !defined(_MSC_VER) && !defined(__arm__)
void* bytes[13];
#else
void* bytes[sizeof(void*) == 4 ? 16 : 13];
#endif
/*
* This object may be in one of three states. If enter() or
* enterAndIgnoreErrors() hasn't been called, it's in STATE_UNENTERED.
* Otherwise, if we were asked to enter into the current compartment, our
* state is STATE_SAME_COMPARTMENT. If we actually created an
* AutoCompartment and entered another compartment, our state is
* STATE_OTHER_COMPARTMENT.
*/
enum State {
STATE_UNENTERED,
STATE_SAME_COMPARTMENT,
STATE_OTHER_COMPARTMENT
} state;
public: public:
JSAutoEnterCompartment() : call(NULL) {} JSAutoEnterCompartment() : state(STATE_UNENTERED) {}
bool enter(JSContext *cx, JSObject *target); bool enter(JSContext *cx, JSObject *target);
void enterAndIgnoreErrors(JSContext *cx, JSObject *target); void enterAndIgnoreErrors(JSContext *cx, JSObject *target);
bool entered() const { return call != NULL; } bool entered() const { return state != STATE_UNENTERED; }
~JSAutoEnterCompartment() { ~JSAutoEnterCompartment();
if (call && call != reinterpret_cast<JSCrossCompartmentCall*>(1))
JS_LeaveCrossCompartmentCall(call);
}
void swap(JSAutoEnterCompartment &other) {
JSCrossCompartmentCall *tmp = call;
call = other.call;
other.call = tmp;
}
}; };
JS_BEGIN_EXTERN_C JS_BEGIN_EXTERN_C