Skip to content
Snippets Groups Projects
Commit f09622cd authored by Deucе's avatar Deucе :ok_hand_tone4:
Browse files

Add generic on_exit support.

Store all on_exit() strings in the global scope, execute them
one scope at a time with scopes ordered in reverse order of
first call to js.on_exit().  Within a scope, they are ordered
last string first.
parent e85d181a
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
...@@ -5080,6 +5080,7 @@ BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* ...@@ -5080,6 +5080,7 @@ BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec*
p->methods = methods; p->methods = methods;
p->startup = startup; p->startup = startup;
p->exit_func=NULL; p->exit_func=NULL;
p->onexit = NULL;
if((*glob = JS_NewCompartmentAndGlobalObject(cx, &js_global_class, NULL)) ==NULL) { if((*glob = JS_NewCompartmentAndGlobalObject(cx, &js_global_class, NULL)) ==NULL) {
free(p); free(p);
......
...@@ -59,11 +59,6 @@ enum { ...@@ -59,11 +59,6 @@ enum {
,PROP_GLOBAL ,PROP_GLOBAL
}; };
struct onexit_private {
char signature[7];
str_list_t list;
};
static JSBool js_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp) static JSBool js_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
{ {
jsval idval; jsval idval;
...@@ -606,45 +601,41 @@ js_on_exit(JSContext *cx, uintN argc, jsval *arglist) ...@@ -606,45 +601,41 @@ js_on_exit(JSContext *cx, uintN argc, jsval *arglist)
JSObject *glob=JS_GetGlobalObject(cx); JSObject *glob=JS_GetGlobalObject(cx);
jsval *argv=JS_ARGV(cx, arglist); jsval *argv=JS_ARGV(cx, arglist);
global_private_t* pd; global_private_t* pd;
struct onexit_private *oep = NULL; struct js_onexit_scope *oes = NULL;
str_list_t oldlist; str_list_t oldlist;
str_list_t list; str_list_t list;
char *p = NULL; char *p = NULL;
JS_SET_RVAL(cx, arglist, JSVAL_VOID); JS_SET_RVAL(cx, arglist, JSVAL_VOID);
if(glob==scope) {
if((pd=(global_private_t*)JS_GetPrivate(cx,glob))==NULL) if((pd=(global_private_t*)JS_GetPrivate(cx,glob))==NULL)
return(JS_FALSE); return(JS_FALSE);
if(glob==scope) {
if(pd->exit_func==NULL) if(pd->exit_func==NULL)
pd->exit_func=strListInit(); pd->exit_func=strListInit();
list=pd->exit_func; list=pd->exit_func;
} }
else { else {
oep=(struct onexit_private *)JS_GetPrivate(cx,scope); /* First, look for an existing onexit scope for this scope */
if(oep==NULL) { for (oes = pd->onexit; oes; oes = oes->next) {
oep = malloc(sizeof(*oep)); if (oes->scope == scope)
if (oep == NULL) { break;
JS_ReportError(cx, "Unable to allocate memory for on_exit() list");
return JS_FALSE;
}
memcpy(oep->signature, "onexit", 7);
oep->list=strListInit();
JS_SetPrivate(cx,scope,oep);
} }
else {
if (oep->signature[0] != 'o' /* If one isn't found, insert it */
|| oep->signature[1] != 'n' if (oes == NULL) {
|| oep->signature[2] != 'e' oes = malloc(sizeof(*oes));
|| oep->signature[3] != 'x' if (oes == NULL) {
|| oep->signature[4] != 'i' JS_ReportError(cx, "Unable to allocate memory for onexit scope");
|| oep->signature[5] != 't'
|| oep->signature[6] != 0) {
JS_ReportError(cx, "on_exit not available in %s scopes", JS_GetClass(cx, scope)->name);
return JS_FALSE; return JS_FALSE;
} }
oes->next = pd->onexit;
pd->onexit = oes;
oes->scope = scope;
oes->onexit = strListInit();
JS_AddObjectRoot(cx, &oes->scope);
} }
list = oep->list; list = oes->onexit;
} }
JSVALUE_TO_MSTRING(cx, argv[0], p, NULL); JSVALUE_TO_MSTRING(cx, argv[0], p, NULL);
...@@ -658,7 +649,7 @@ js_on_exit(JSContext *cx, uintN argc, jsval *arglist) ...@@ -658,7 +649,7 @@ js_on_exit(JSContext *cx, uintN argc, jsval *arglist)
if(glob==scope) if(glob==scope)
pd->exit_func=list; pd->exit_func=list;
else else
oep->list = list; oes->onexit = list;
} }
return(JS_TRUE); return(JS_TRUE);
} }
...@@ -800,25 +791,43 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) ...@@ -800,25 +791,43 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb)
JSObject *glob=JS_GetGlobalObject(cx); JSObject *glob=JS_GetGlobalObject(cx);
global_private_t *pt; global_private_t *pt;
str_list_t list = NULL; str_list_t list = NULL;
struct js_onexit_scope **prev_oes_next = NULL;
struct js_onexit_scope *oes = NULL;
if(glob==obj) {
pt=(global_private_t *)JS_GetPrivate(cx,JS_GetGlobalObject(cx)); pt=(global_private_t *)JS_GetPrivate(cx,JS_GetGlobalObject(cx));
if(glob==obj) {
/* Yes, this is recursive to one level */
while (pt->onexit) {
if (pt->onexit->scope == glob) {
// This shouldn't happen, but let's not go inifinite eh?
JS_ReportError(cx, "js_EvalOnExit() extra scope is global");
return;
}
else {
oes = pt->onexit;
js_EvalOnExit(cx, pt->onexit->scope, cb);
if (oes == pt->onexit) {
// This *really* shouldn't happen...
JS_ReportError(cx, "js_EvalOnExit() did not pop on_exit stack");
return;
}
}
}
list=pt->exit_func; list=pt->exit_func;
} }
else { else {
struct onexit_private *oep = JS_GetPrivate(cx,obj); /* Find this scope in onexit list */
if (oep != NULL) { for (prev_oes_next = &pt->onexit, oes = pt->onexit; oes; prev_oes_next = &(oes->next), oes = oes->next) {
if (oep->signature[0] == 'o' if (oes->scope == obj) {
|| oep->signature[1] == 'n' (*prev_oes_next) = oes->next;
|| oep->signature[2] == 'e' list = oes->onexit;
|| oep->signature[3] == 'x' JS_RemoveObjectRoot(cx, &oes->scope);
|| oep->signature[4] == 'i' free(oes);
|| oep->signature[5] == 't' break;
|| oep->signature[6] == 0) {
list = oep->list;
free(oep);
} }
} }
if (oes == NULL)
return;
} }
cb->auto_terminate=FALSE; cb->auto_terminate=FALSE;
...@@ -831,9 +840,7 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) ...@@ -831,9 +840,7 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb)
} }
strListFree(&list); strListFree(&list);
if(glob != obj) if(glob == obj)
JS_SetPrivate(cx,obj,NULL);
else
pt->exit_func=NULL; pt->exit_func=NULL;
if(auto_terminate) if(auto_terminate)
......
...@@ -1295,6 +1295,12 @@ extern "C" { ...@@ -1295,6 +1295,12 @@ extern "C" {
,js_server_props_t* props); ,js_server_props_t* props);
/* js_global.c */ /* js_global.c */
struct js_onexit_scope {
JSObject *scope;
str_list_t onexit;
struct js_onexit_scope *next;
};
typedef struct { typedef struct {
scfg_t* cfg; scfg_t* cfg;
jsSyncMethodSpec* methods; jsSyncMethodSpec* methods;
...@@ -1302,6 +1308,7 @@ extern "C" { ...@@ -1302,6 +1308,7 @@ extern "C" {
unsigned bg_count; unsigned bg_count;
sem_t bg_sem; sem_t bg_sem;
str_list_t exit_func; str_list_t exit_func;
struct js_onexit_scope *onexit;
} global_private_t; } global_private_t;
DLLEXPORT BOOL DLLCALL js_argc(JSContext *cx, unsigned argc, unsigned min); DLLEXPORT BOOL DLLCALL js_argc(JSContext *cx, unsigned argc, unsigned 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**);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment