diff --git a/js/jsd/jsd.h b/js/jsd/jsd.h index 65418937207..58b54ef7a8f 100644 --- a/js/jsd/jsd.h +++ b/js/jsd/jsd.h @@ -340,7 +340,9 @@ extern void JSD_ASSERT_VALID_OBJECT(JSDObject* jsdobj); extern JSDContext* jsd_DebuggerOnForUser(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, - void* user); + void* user, + JSObject* scopeobj); + extern JSDContext* jsd_DebuggerOn(void); diff --git a/js/jsd/jsd_high.c b/js/jsd/jsd_high.c index b2e6fc00b3c..512527636d6 100644 --- a/js/jsd/jsd_high.c +++ b/js/jsd/jsd_high.c @@ -86,9 +86,11 @@ _validateUserCallbacks(JSD_UserCallbacks* callbacks) static JSDContext* _newJSDContext(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, - void* user) + void* user, + JSObject* scopeobj) { JSDContext* jsdc = NULL; + JSCompartment *compartment; if( ! jsrt ) return NULL; @@ -137,7 +139,11 @@ _newJSDContext(JSRuntime* jsrt, JS_BeginRequest(jsdc->dumbContext); + if( scopeobj ) + compartment = js_SwitchToObjectCompartment(jsdc->dumbContext, scopeobj); jsdc->glob = JS_NewGlobalObject(jsdc->dumbContext, &global_class); + if( scopeobj ) + js_SwitchToCompartment(jsdc->dumbContext, compartment); if( ! jsdc->glob ) goto label_newJSDContext_failure; @@ -194,12 +200,13 @@ _destroyJSDContext(JSDContext* jsdc) JSDContext* jsd_DebuggerOnForUser(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, - void* user) + void* user, + JSObject* scopeobj) { JSDContext* jsdc; JSContext* iter = NULL; - jsdc = _newJSDContext(jsrt, callbacks, user); + jsdc = _newJSDContext(jsrt, callbacks, user, scopeobj); if( ! jsdc ) return NULL; @@ -226,7 +233,7 @@ jsd_DebuggerOn(void) { JS_ASSERT(_jsrt); JS_ASSERT(_validateUserCallbacks(&_callbacks)); - return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user); + return jsd_DebuggerOnForUser(_jsrt, &_callbacks, _user, NULL); } void diff --git a/js/jsd/jsdebug.c b/js/jsd/jsdebug.c index 5aa4177eeff..173c9d060fe 100644 --- a/js/jsd/jsdebug.c +++ b/js/jsd/jsdebug.c @@ -49,7 +49,7 @@ JSD_DebuggerOnForUser(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user) { - return jsd_DebuggerOnForUser(jsrt, callbacks, user); + return jsd_DebuggerOnForUser(jsrt, callbacks, user, NULL); } JSD_PUBLIC_API(JSDContext*) diff --git a/js/jsd/jsdebug.h b/js/jsd/jsdebug.h index 41eab2a9429..fcdc2e04ee8 100644 --- a/js/jsd/jsdebug.h +++ b/js/jsd/jsdebug.h @@ -142,6 +142,16 @@ JSD_DebuggerOnForUser(JSRuntime* jsrt, JSD_UserCallbacks* callbacks, void* user); +/* + * Startup JSD in an application that uses compartments. Debugger + * objects will be allocated in the same compartment as scopeobj. + */ +extern JSD_PUBLIC_API(JSDContext*) +JSD_DebuggerOnForUserWithCompartment(JSRuntime* jsrt, + JSD_UserCallbacks* callbacks, + void* user, + JSObject* scopeobj); + /* * Shutdown JSD for this JSDContext */ diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index fa2c26ebdb3..4a27e11ce3f 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1185,22 +1185,20 @@ JSAutoCrossCompartmentCall::enter(JSContext *cx, JSObject *target) return call != NULL; } -JSAutoEnterCompartment::JSAutoEnterCompartment(JSContext *cx, - JSCompartment *newCompartment) - : cx(cx), compartment(cx->compartment) -{ - cx->compartment = newCompartment; -} - -JSAutoEnterCompartment::JSAutoEnterCompartment(JSContext *cx, JSObject *target) - : cx(cx), compartment(cx->compartment) -{ - cx->compartment = target->getCompartment(cx); -} - -JSAutoEnterCompartment::~JSAutoEnterCompartment() +JS_FRIEND_API(JSCompartment *) +js_SwitchToCompartment(JSContext *cx, JSCompartment *compartment) { + JSCompartment *c = cx->compartment; cx->compartment = compartment; + return c; +} + +JS_FRIEND_API(JSCompartment *) +js_SwitchToObjectCompartment(JSContext *cx, JSObject *obj) +{ + JSCompartment *c = cx->compartment; + cx->compartment = obj->getCompartment(cx); + return c; } JS_PUBLIC_API(void *) @@ -1245,7 +1243,8 @@ JS_SetGlobalObject(JSContext *cx, JSObject *obj) CHECK_REQUEST(cx); cx->globalObject = obj; - cx->compartment = obj ? obj->getCompartment(cx) : cx->runtime->defaultCompartment; + if (!cx->maybefp()) + cx->compartment = obj ? obj->getCompartment(cx) : cx->runtime->defaultCompartment; } class AutoResolvingEntry { @@ -1334,10 +1333,14 @@ JS_InitStandardClasses(JSContext *cx, JSObject *obj) { CHECK_REQUEST(cx); - if (cx->globalObject) - assertSameCompartment(cx, obj); - else + /* + * JS_SetGlobalObject might or might not change cx's compartment, so call + * it before assertSameCompartment. (The API contract is that *after* this, + * cx and obj must be in the same compartment.) + */ + if (!cx->globalObject) JS_SetGlobalObject(cx, obj); + assertSameCompartment(cx, obj); /* Define a top-level property 'undefined' with the undefined value. */ JSAtom *atom = cx->runtime->atomState.typeAtoms[JSTYPE_VOID]; diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 34198f88508..35a12295877 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -957,6 +957,12 @@ JS_RewrapObject(JSContext *cx, JSObject **objp); extern JS_PUBLIC_API(JSBool) JS_RewrapValue(JSContext *cx, jsval *p); +extern JS_FRIEND_API(JSCompartment *) +js_SwitchToCompartment(JSContext *cx, JSCompartment *compartment); + +extern JS_FRIEND_API(JSCompartment *) +js_SwitchToObjectCompartment(JSContext *cx, JSObject *obj); + #ifdef __cplusplus JS_END_EXTERN_C @@ -982,14 +988,20 @@ class JS_PUBLIC_API(JSAutoCrossCompartmentCall) } }; -class JS_FRIEND_API(JSAutoEnterCompartment) +class JSAutoEnterCompartment { JSContext *cx; JSCompartment *compartment; public: - JSAutoEnterCompartment(JSContext *cx, JSCompartment *newCompartment); - JSAutoEnterCompartment(JSContext *cx, JSObject *target); - ~JSAutoEnterCompartment(); + JSAutoEnterCompartment(JSContext *cx, JSCompartment *newCompartment) : cx(cx) { + compartment = js_SwitchToCompartment(cx, newCompartment); + } + JSAutoEnterCompartment(JSContext *cx, JSObject *target) : cx(cx) { + compartment = js_SwitchToObjectCompartment(cx, target); + } + ~JSAutoEnterCompartment() { + js_SwitchToCompartment(cx, compartment); + } }; JS_BEGIN_EXTERN_C