diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index abee3dbc8b356603454d1dfdb24c56cf8b13a435..b25de7c048294495fb1fb4e079943b1fbf3df597 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -647,6 +647,7 @@ long sbbs_t::js_execfile(const char *cmd)
 
 	JS_SetBranchCallback(js_cx, js_BranchCallback);
 
+	js_PrepareToExecute(js_cx, js_scope, path);
 	JS_ExecuteScript(js_cx, js_scope, js_script, &rval);
 
 	JS_GetProperty(js_cx, js_scope, "exit_code", &rval);
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 59b7aeac8ac6a8728000035d15f3b1df27eeb8a9..3fb71ab9c5a9a000da47202a668efab22db5032f 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -1000,6 +1000,7 @@ BOOL js_generate_index(JSContext* js_cx, JSObject* parent,
 			break;
 		}
 
+		js_PrepareToExecute(js_cx, parent, spath);
 		if((success=JS_ExecuteScript(js_cx, parent, js_script, &rval))!=TRUE) {
 			lprintf(LOG_ERR,"%04d !JavaScript FAILED to execute script (%s)",sock,spath);
 			break;
diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c
index 160ac41065885725c8a1831909422f77aa71b963..ab6d3ccef7a353c57f503d93cb763e6d5547d6d3 100644
--- a/src/sbbs3/js_internal.c
+++ b/src/sbbs3/js_internal.c
@@ -483,3 +483,31 @@ JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_
 
 	return(obj);
 }
+
+void DLLCALL js_PrepareToExecute(JSContext *cx, JSObject *obj, const char *filename)
+{
+	JSString*	str;
+	jsval		val;
+
+	if(JS_GetProperty(cx, obj, "js", &val) && JSVAL_IS_OBJECT(val)) {
+		JSObject* js = JSVAL_TO_OBJECT(val);
+		char	dir[MAX_PATH+1];
+
+		if(filename!=NULL) {
+			char* p;
+
+			if((str=JS_NewStringCopyZ(cx, filename)) != NULL)
+				JS_DefineProperty(cx, js, "exec_path", STRING_TO_JSVAL(str)
+					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+			if((str=JS_NewStringCopyZ(cx, getfname(filename))) != NULL)
+				JS_DefineProperty(cx, js, "exec_file", STRING_TO_JSVAL(str)
+					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+			SAFECOPY(dir,filename);
+			p=getfname(dir);
+			*p=0;
+			if((str=JS_NewStringCopyZ(cx, dir)) != NULL)
+				JS_DefineProperty(cx, js, "exec_dir", STRING_TO_JSVAL(str)
+					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+		}
+	}
+}
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index 5d5c7bcbfa4aabab7f5b0a3519cdba2defbe1bfd..114a4fdc22ad5dbac39aad8de706df880ebbca4a 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -802,6 +802,7 @@ long js_exec(const char *fname, char** args)
 			,path
 			,diff);
 
+	js_PrepareToExecute(js_cx, js_glob, fname==NULL ? NULL : path);
 	start=xp_timer();
 	JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
 	JS_GetProperty(js_cx, js_glob, "exit_code", &rval);
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index f3da5452737fc70edddeec334e5e7f74e23e1427..ee01fcaa00f1acdd9d6f8fcda9cd228e2ec5f4de 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -1784,7 +1784,8 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 		} else {
 			lprintf(LOG_DEBUG,"%04d %s Executing: %s"
 				,sock, log_prefix, cmdline);
-			js_script=JS_CompileFile(*js_cx, js_scope, path);
+			if((js_script=JS_CompileFile(*js_cx, js_scope, path)) != NULL)
+				js_PrepareToExecute(*js_cx, js_scope, path);
 		}
 		if(js_script==NULL)
 			break;
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 0007b9b97f0db91f84b531732b377b12f2703bb8..43bb75e42644318ea0b70f78433a913ccaadf1ec 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -1020,6 +1020,7 @@ extern "C" {
 	DLLEXPORT JSObject* DLLCALL js_CreateInternalJsObject(JSContext*, JSObject* parent, js_branch_t*, js_startup_t*);
 	DLLEXPORT JSBool	DLLCALL js_CommonBranchCallback(JSContext*, js_branch_t*);
 	DLLEXPORT void		DLLCALL js_EvalOnExit(JSContext*, JSObject*, js_branch_t*);
+	DLLEXPORT void		DLLCALL	js_PrepareToExecute(JSContext*, JSObject*, const char *filename);
 
 	/* js_system.c */
 	DLLEXPORT JSObject* DLLCALL js_CreateSystemObject(JSContext* cx, JSObject* parent
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 9e4813f284e4b72a2ada68e91ba81841b9b8ddc8..7600dacaf32472bd6d7d9188cd504ca443cbef23 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -1164,6 +1164,7 @@ static void js_service_thread(void* arg)
 	if(js_script==NULL) 
 		lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile script (%s)",socket,spath);
 	else  {
+		js_PrepareToExecute(js_cx, js_glob, spath);
 		JS_SetBranchCallback(js_cx, js_BranchCallback);
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
 		js_EvalOnExit(js_cx, js_glob, &service_client.branch);
@@ -1267,6 +1268,7 @@ static void js_static_service_thread(void* arg)
 			break;
 		}
 
+		js_PrepareToExecute(js_cx, js_glob, spath);
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
 		js_EvalOnExit(js_cx, js_glob, &service_client.branch);
 		JS_DestroyScript(js_cx, js_script);
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 88f762e232dbd50073963c451adde86f568df7e3..067643d17847c67ef4b61ed19ff9062c4525fbda 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -4620,6 +4620,7 @@ static BOOL exec_ssjs(http_session_t* session, char* script)  {
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Executing script: %s",session->socket,script);
 		start=xp_timer();
+		js_PrepareToExecute(session->js_cx, session->js_glob, script);
 		JS_ExecuteScript(session->js_cx, session->js_glob, js_script, &rval);
 		js_EvalOnExit(session->js_cx, session->js_glob, &session->js_branch);
 		lprintf(LOG_DEBUG,"%04d JavaScript: Done executing script: %s (%.2Lf seconds)"