diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index d0fd4297f4cfbbfd75e0e3a011f10ff1072968c5..fffad2fa624514f9ad97bb6c64af94d8ac65b6b9 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -52,14 +52,6 @@
 
 #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 */
 enum {
 	 GLOB_PROP_ERRNO
@@ -241,12 +233,12 @@ static jsval* js_CopyValue(JSContext* cx, jsrefcount *cx_rc, jsval val, JSContex
 JSBool BGContextCallback(JSContext *cx, uintN contextOp)
 {
 	JSObject	*gl=JS_GetGlobalObject(cx);
-	private_t*	p;
+	global_private_t*	p;
 
 	if(!gl)
 		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);
 
 	switch(contextOp) {
@@ -275,7 +267,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 	uintN		argn=0;
     char*		filename;
     JSObject*	script;
-	private_t*	p;
+	global_private_t*	p;
 	jsval		val;
 	JSObject*	js_argv;
 	JSObject*	exec_obj;
@@ -289,7 +281,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 
 	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);
 
 	exec_obj=JS_GetScopeChain(cx);
@@ -353,6 +345,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 		}
 
 		if((bg->logobj=JS_NewObjectWithGivenProto(bg->cx, NULL, NULL, bg->obj))==NULL) {
+			JS_RemoveObjectRoot(bg->cx, &bg->obj);
 			JS_ENDREQUEST(bg->cx);
 			JS_DestroyContext(bg->cx);
 			jsrt_Release(bg->runtime);
@@ -1412,7 +1405,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist)
 	struct		tm tm;
 	time_t		now;
 	BOOL		nodisplay=FALSE;
-	private_t*	p;
+	global_private_t*	p;
 	uchar   	attr_stack[64]; /* Saved attributes (stack) */
 	int     	attr_sp=0;                /* Attribute stack pointer */
 	ulong		clear_screen=0;
@@ -1425,7 +1418,7 @@ js_html_encode(JSContext *cx, uintN argc, jsval *arglist)
 	if(argc==0 || JSVAL_IS_VOID(argv[0]))
 		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);
 
 	JSVALUE_TO_STRING(cx, argv[0], inbuf, NULL);
@@ -3924,9 +3917,9 @@ static jsConstIntSpec js_global_const_ints[] = {
 
 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)
 		free(p);
@@ -3938,10 +3931,10 @@ static void js_global_finalize(JSContext *cx, JSObject *obj)
 static JSBool js_global_resolve(JSContext *cx, JSObject *obj, jsid id)
 {
 	char*		name=NULL;
-	private_t*	p;
+	global_private_t*	p;
 	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);
 
 	if(id != JSID_VOID && id != JSID_EMPTY && id != JS_DEFAULT_XML_NAMESPACE_ID) {
@@ -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)
 {
-	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);
 
 	p->cfg = cfg;
 	p->methods = methods;
 	p->startup = startup;
+	p->exit_func=NULL;
 
 	if((*glob = JS_NewCompartmentAndGlobalObject(cx, &js_global_class, NULL)) ==NULL)
 		return(FALSE);
diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c
index d852c8196cb00a0911904a8a25f4b43c04261333..14398f7a6d94e36a2c6d72421798b976fec7fedc 100644
--- a/src/sbbs3/js_internal.c
+++ b/src/sbbs3/js_internal.c
@@ -372,21 +372,33 @@ js_report_error(JSContext *cx, uintN argc, jsval *arglist)
 static JSBool
 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);
-	js_callback_t*	cb;
+	global_private_t*	pd;
+	str_list_t	list;
 	char		*p;
 
 	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
 
-	if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL)
-		return(JS_FALSE);
-
-	if(cb->exit_func==NULL)
-		cb->exit_func=strListInit();
+	if(thisobj==parent) {
+		if((pd=(global_private_t*)JS_GetPrivate(cx,glob))==NULL)
+			return(JS_FALSE);
+		if(pd->exit_func==NULL)
+			pd->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);
-	strListPush(&cb->exit_func,p);
+	strListPush(&list,p);
 
 	return(JS_TRUE);
 }
@@ -473,17 +485,27 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb)
 	jsval	rval;
 	JSObject* script;
 	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;
 
-	while((p=strListPop(&cb->exit_func))!=NULL) {
+	while((p=strListPop(&list))!=NULL) {
 		if((script=JS_CompileScript(cx, obj, p, strlen(p), NULL, 0))!=NULL) {
 			JS_ExecuteScript(cx, obj, script, &rval);
 		}
 		free(p);
 	}
 
-	strListFree(&cb->exit_func);
+	strListFree(&list);
 
 	if(auto_terminate)
 		cb->auto_terminate = TRUE;
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 5db05a5771d7b639f800ea6d70daa96727a87044..f3a36af41c3406983dc02f772ae9137f7e1f8ba8 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -1045,6 +1045,14 @@ extern "C" {
 										,js_server_props_t* props);
 
 	/* 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_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t*, JSObject**);
 	DLLEXPORT BOOL	DLLCALL js_CreateCommonObjects(JSContext* cx
diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h
index 8452ce479362e19762c365b858e14986ec3a39f8..8a00bbca4467ae5255bab82c35cdb726aefd8272 100644
--- a/src/sbbs3/sbbsdefs.h
+++ b/src/sbbs3/sbbsdefs.h
@@ -86,7 +86,6 @@ typedef struct {
 	ulong	gc_attempts;
 	BOOL	auto_terminate;
 	volatile BOOL*	terminated;
-	str_list_t	exit_func;
 } js_callback_t;
 
 #define JSVAL_NULL_OR_VOID(val)		(JSVAL_IS_NULL(val) || JSVAL_IS_VOID(val))