Skip to content
Snippets Groups Projects
Commit 385ee4e9 authored by deuce's avatar deuce
Browse files

Make the on_exit() evals happen when the scope exits rather than when the

global object exits.

This fixes a problem where the terminal server reuses the same global object
for all JS scripts, and they uses nested exec()s.  When the innermost script
would exit, the on_exit evals would occure in IT'S scope rather than in the
scope it was defined in, resulting in incorrect behaviour.
parent 49926b67
No related branches found
No related tags found
No related merge requests found
...@@ -52,14 +52,6 @@ ...@@ -52,14 +52,6 @@
#ifdef JAVASCRIPT #ifdef JAVASCRIPT
typedef struct {
scfg_t* cfg;
jsSyncMethodSpec* methods;
js_startup_t* startup;
unsigned bg_count;
sem_t bg_sem;
} private_t;
/* Global Object Properites */ /* Global Object Properites */
enum { enum {
GLOB_PROP_ERRNO GLOB_PROP_ERRNO
...@@ -241,12 +233,12 @@ static jsval* js_CopyValue(JSContext* cx, jsrefcount *cx_rc, jsval val, JSContex ...@@ -241,12 +233,12 @@ static jsval* js_CopyValue(JSContext* cx, jsrefcount *cx_rc, jsval val, JSContex
JSBool BGContextCallback(JSContext *cx, uintN contextOp) JSBool BGContextCallback(JSContext *cx, uintN contextOp)
{ {
JSObject *gl=JS_GetGlobalObject(cx); JSObject *gl=JS_GetGlobalObject(cx);
private_t* p; global_private_t* p;
if(!gl) if(!gl)
return JS_TRUE; return JS_TRUE;
if((p=(private_t*)JS_GetPrivate(cx,gl))==NULL) if((p=(global_private_t*)JS_GetPrivate(cx,gl))==NULL)
return(JS_TRUE); return(JS_TRUE);
switch(contextOp) { switch(contextOp) {
...@@ -275,7 +267,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist) ...@@ -275,7 +267,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
uintN argn=0; uintN argn=0;
char* filename; char* filename;
JSObject* script; JSObject* script;
private_t* p; global_private_t* p;
jsval val; jsval val;
JSObject* js_argv; JSObject* js_argv;
JSObject* exec_obj; JSObject* exec_obj;
...@@ -289,7 +281,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist) ...@@ -289,7 +281,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
JS_SET_RVAL(cx, arglist,JSVAL_VOID); JS_SET_RVAL(cx, arglist,JSVAL_VOID);
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) if((p=(global_private_t*)JS_GetPrivate(cx,obj))==NULL)
return(JS_FALSE); return(JS_FALSE);
exec_obj=JS_GetScopeChain(cx); exec_obj=JS_GetScopeChain(cx);
...@@ -353,6 +345,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist) ...@@ -353,6 +345,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
} }
if((bg->logobj=JS_NewObjectWithGivenProto(bg->cx, NULL, NULL, bg->obj))==NULL) { if((bg->logobj=JS_NewObjectWithGivenProto(bg->cx, NULL, NULL, bg->obj))==NULL) {
JS_RemoveObjectRoot(bg->cx, &bg->obj);
JS_ENDREQUEST(bg->cx); JS_ENDREQUEST(bg->cx);
JS_DestroyContext(bg->cx); JS_DestroyContext(bg->cx);
jsrt_Release(bg->runtime); jsrt_Release(bg->runtime);
...@@ -1412,7 +1405,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist) ...@@ -1412,7 +1405,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist)
struct tm tm; struct tm tm;
time_t now; time_t now;
BOOL nodisplay=FALSE; BOOL nodisplay=FALSE;
private_t* p; global_private_t* p;
uchar attr_stack[64]; /* Saved attributes (stack) */ uchar attr_stack[64]; /* Saved attributes (stack) */
int attr_sp=0; /* Attribute stack pointer */ int attr_sp=0; /* Attribute stack pointer */
ulong clear_screen=0; ulong clear_screen=0;
...@@ -1425,7 +1418,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist) ...@@ -1425,7 +1418,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist)
if(argc==0 || JSVAL_IS_VOID(argv[0])) if(argc==0 || JSVAL_IS_VOID(argv[0]))
return(JS_TRUE); return(JS_TRUE);
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) /* Will this work? Ask DM */ if((p=(global_private_t*)JS_GetPrivate(cx,obj))==NULL) /* Will this work? Ask DM */
return(JS_FALSE); return(JS_FALSE);
JSVALUE_TO_STRING(cx, argv[0], inbuf, NULL); JSVALUE_TO_STRING(cx, argv[0], inbuf, NULL);
...@@ -3924,9 +3917,9 @@ static jsConstIntSpec js_global_const_ints[] = { ...@@ -3924,9 +3917,9 @@ static jsConstIntSpec js_global_const_ints[] = {
static void js_global_finalize(JSContext *cx, JSObject *obj) static void js_global_finalize(JSContext *cx, JSObject *obj)
{ {
private_t* p; global_private_t* p;
p=(private_t*)JS_GetPrivate(cx,obj); p=(global_private_t*)JS_GetPrivate(cx,obj);
if(p!=NULL) if(p!=NULL)
free(p); free(p);
...@@ -3938,10 +3931,10 @@ static void js_global_finalize(JSContext *cx, JSObject *obj) ...@@ -3938,10 +3931,10 @@ static void js_global_finalize(JSContext *cx, JSObject *obj)
static JSBool js_global_resolve(JSContext *cx, JSObject *obj, jsid id) static JSBool js_global_resolve(JSContext *cx, JSObject *obj, jsid id)
{ {
char* name=NULL; char* name=NULL;
private_t* p; global_private_t* p;
JSBool ret=JS_TRUE; JSBool ret=JS_TRUE;
if((p=(private_t*)JS_GetPrivate(cx,obj))==NULL) if((p=(global_private_t*)JS_GetPrivate(cx,obj))==NULL)
return(JS_FALSE); return(JS_FALSE);
if(id != JSID_VOID && id != JSID_EMPTY && id != JS_DEFAULT_XML_NAMESPACE_ID) { if(id != JSID_VOID && id != JSID_EMPTY && id != JS_DEFAULT_XML_NAMESPACE_ID) {
...@@ -3981,14 +3974,15 @@ static JSClass js_global_class = { ...@@ -3981,14 +3974,15 @@ static JSClass js_global_class = {
BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t* startup, JSObject**glob) BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t* startup, JSObject**glob)
{ {
private_t* p; global_private_t* p;
if((p = (private_t*)malloc(sizeof(private_t)))==NULL) if((p = (global_private_t*)malloc(sizeof(global_private_t)))==NULL)
return(FALSE); return(FALSE);
p->cfg = cfg; p->cfg = cfg;
p->methods = methods; p->methods = methods;
p->startup = startup; p->startup = startup;
p->exit_func=NULL;
if((*glob = JS_NewCompartmentAndGlobalObject(cx, &js_global_class, NULL)) ==NULL) if((*glob = JS_NewCompartmentAndGlobalObject(cx, &js_global_class, NULL)) ==NULL)
return(FALSE); return(FALSE);
......
...@@ -372,21 +372,33 @@ js_report_error(JSContext *cx, uintN argc, jsval *arglist) ...@@ -372,21 +372,33 @@ js_report_error(JSContext *cx, uintN argc, jsval *arglist)
static JSBool static JSBool
js_on_exit(JSContext *cx, uintN argc, jsval *arglist) js_on_exit(JSContext *cx, uintN argc, jsval *arglist)
{ {
JSObject *obj=JS_THIS_OBJECT(cx, arglist); JSObject *thisobj=JS_THIS_OBJECT(cx, arglist);
JSObject *parent=JS_GetParent(cx,thisobj);
JSObject *glob=JS_GetGlobalObject(cx);
jsval *argv=JS_ARGV(cx, arglist); jsval *argv=JS_ARGV(cx, arglist);
js_callback_t* cb; global_private_t* pd;
str_list_t list;
char *p; char *p;
JS_SET_RVAL(cx, arglist, JSVAL_VOID); JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL) if(thisobj==parent) {
if((pd=(global_private_t*)JS_GetPrivate(cx,glob))==NULL)
return(JS_FALSE); return(JS_FALSE);
if(pd->exit_func==NULL)
if(cb->exit_func==NULL) pd->exit_func=strListInit();
cb->exit_func=strListInit(); list=pd->exit_func;
}
else {
list=(str_list_t)JS_GetPrivate(cx,parent);
if(list==NULL) {
list=strListInit();
JS_SetPrivate(cx,parent,list);
}
}
JSVALUE_TO_STRING(cx, argv[0], p, NULL); JSVALUE_TO_STRING(cx, argv[0], p, NULL);
strListPush(&cb->exit_func,p); strListPush(&list,p);
return(JS_TRUE); return(JS_TRUE);
} }
...@@ -473,17 +485,27 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) ...@@ -473,17 +485,27 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb)
jsval rval; jsval rval;
JSObject* script; JSObject* script;
BOOL auto_terminate=cb->auto_terminate; BOOL auto_terminate=cb->auto_terminate;
JSObject *glob=JS_GetGlobalObject(cx);
global_private_t *pt;
str_list_t list;
if(glob==obj) {
pt=(global_private_t *)JS_GetPrivate(cx,JS_GetGlobalObject(cx));
list=pt->exit_func;
}
else
list=JS_GetPrivate(cx,obj);
cb->auto_terminate=FALSE; cb->auto_terminate=FALSE;
while((p=strListPop(&cb->exit_func))!=NULL) { while((p=strListPop(&list))!=NULL) {
if((script=JS_CompileScript(cx, obj, p, strlen(p), NULL, 0))!=NULL) { if((script=JS_CompileScript(cx, obj, p, strlen(p), NULL, 0))!=NULL) {
JS_ExecuteScript(cx, obj, script, &rval); JS_ExecuteScript(cx, obj, script, &rval);
} }
free(p); free(p);
} }
strListFree(&cb->exit_func); strListFree(&list);
if(auto_terminate) if(auto_terminate)
cb->auto_terminate = TRUE; cb->auto_terminate = TRUE;
......
...@@ -1045,6 +1045,14 @@ extern "C" { ...@@ -1045,6 +1045,14 @@ extern "C" {
,js_server_props_t* props); ,js_server_props_t* props);
/* js_global.c */ /* js_global.c */
typedef struct {
scfg_t* cfg;
jsSyncMethodSpec* methods;
js_startup_t* startup;
unsigned bg_count;
sem_t bg_sem;
str_list_t exit_func;
} global_private_t;
DLLEXPORT BOOL DLLCALL js_argc(JSContext *cx, uintN argc, uintN min); DLLEXPORT BOOL DLLCALL js_argc(JSContext *cx, uintN argc, uintN min);
DLLEXPORT BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t*, JSObject**); DLLEXPORT BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t*, JSObject**);
DLLEXPORT BOOL DLLCALL js_CreateCommonObjects(JSContext* cx DLLEXPORT BOOL DLLCALL js_CreateCommonObjects(JSContext* cx
......
...@@ -86,7 +86,6 @@ typedef struct { ...@@ -86,7 +86,6 @@ typedef struct {
ulong gc_attempts; ulong gc_attempts;
BOOL auto_terminate; BOOL auto_terminate;
volatile BOOL* terminated; volatile BOOL* terminated;
str_list_t exit_func;
} js_callback_t; } js_callback_t;
#define JSVAL_NULL_OR_VOID(val) (JSVAL_IS_NULL(val) || JSVAL_IS_VOID(val)) #define JSVAL_NULL_OR_VOID(val) (JSVAL_IS_NULL(val) || JSVAL_IS_VOID(val))
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment