diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index 1478cea8f3888855473dc43a27ad359afb401314..aa99f66d30bba936d3ba5f5104a527195835742a 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -524,6 +524,29 @@ char * sbbs_t::copystrvar(csi_t *csi, char *p, char *str)
 
 #ifdef JAVASCRIPT
 
+static JSBool
+js_BranchCallback(JSContext *cx, JSScript *script)
+{
+	sbbs_t*		sbbs;
+
+	if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
+		return(JS_FALSE);
+
+	sbbs->js_loop++;
+
+	/* Termination and infinite loop detection */
+	if(sbbs->terminated || sbbs->js_loop>JAVASCRIPT_BRANCH_LIMIT) {
+		sbbs->js_loop=0;
+		return(JS_FALSE);
+	}
+	
+	/* Give up timeslices every once in a while */
+	if(!(sbbs->js_loop%JAVASCRIPT_YIELD_FREQUENCY))
+		mswait(1);
+
+    return(JS_TRUE);
+}
+
 static JSClass js_scope_class ={
         "Scope",
 		0,			/* flags */
@@ -607,6 +630,8 @@ long sbbs_t::js_execfile(char *cmd)
 		return(-1);
 	}
 
+	JS_SetBranchCallback(js_cx, js_BranchCallback);
+
 	JS_ExecuteScript(js_cx, js_scope, js_script, &rval);
 
 	JS_DestroyScript(js_cx, js_script);
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index edde9fac5ecde5a630feb4e4aec9cd73eb518bf6..40008173e33a366ed45a46f2c3e8d2dba2447e14 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -100,9 +100,10 @@ typedef struct {
 	user_t			user;
 	client_t*		client;
 	service_t*		service;
+	ulong			js_loop;
 } service_client_t;
 
-static service_t	*service; //[MAX_SERVICES];
+static service_t	*service;
 static DWORD		services=0;
 
 static int lprintf(char *fmt, ...)
@@ -487,20 +488,15 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 	jsval		val;
 	BOOL		success=FALSE;
 
-//	lprintf("%04d JavaScript: Initializing context",sock);
-
     if((js_cx = JS_NewContext(js_runtime, JAVASCRIPT_CONTEXT_STACK))==NULL)
 		return(NULL);
 
-//	lprintf("%04d JavaScript: Context created",sock);
-
     JS_SetErrorReporter(js_cx, js_ErrorReporter);
 
 	do {
 
 		JS_SetContextPrivate(js_cx, service_client);
 
-//		lprintf("%04d JavaScript: Initializing Global object",sock);
 		if((js_glob=js_CreateGlobalObject(js_cx, &scfg))==NULL) 
 			break;
 
@@ -527,7 +523,6 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 		if(js_CreateFileClass(js_cx, js_glob)==NULL)
 			break;
 
-//		lprintf("%04d JavaScript: Initializing System object",sock);
 		if(js_CreateSystemObject(js_cx, js_glob, &scfg, uptime)==NULL) 
 			break;
 		
@@ -561,6 +556,36 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 	return(js_cx);
 }
 
+static JSBool
+js_BranchCallback(JSContext *cx, JSScript *script)
+{
+	service_client_t* client;
+
+	if((client=(service_client_t*)JS_GetContextPrivate(cx))==NULL)
+		return(JS_FALSE);
+
+	client->js_loop++;
+
+	/* Terminated? */ 
+	if(terminated) {
+		lprintf("%04d %s !Terminated"
+			,client->socket,client->service->protocol);
+		return(JS_FALSE);
+	}
+	/* Infinite loop detection */
+	if(client->js_loop>JAVASCRIPT_BRANCH_LIMIT) {
+		lprintf("%04d %s !INFINITE LOOOP (%lu branches) detected"
+			,client->socket,client->service->protocol,JAVASCRIPT_BRANCH_LIMIT);
+		client->js_loop=0;
+		return(JS_FALSE);
+	}
+	/* Give up timeslices every once in a while */
+	if(!(client->js_loop%JAVASCRIPT_YIELD_FREQUENCY))
+		mswait(1);
+
+    return(JS_TRUE);
+}
+
 
 static void js_service_thread(void* arg)
 {
@@ -710,14 +735,12 @@ static void js_service_thread(void* arg)
 	if(js_script==NULL) 
 		lprintf("%04d !JavaScript FAILED to compile script (%s)",socket,spath);
 	else  {
+		JS_SetBranchCallback(js_cx, js_BranchCallback);
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
-//		lprintf("%04d %s JS_DestroyScript",socket,service->protocol);
 		JS_DestroyScript(js_cx, js_script);
 	}
-//	lprintf("%04d %s JS_DestroyContext",socket,service->protocol);
 	JS_DestroyContext(js_cx);	/* Free Context */
 
-//	lprintf("%04d %s JS_DestroyRuntime",socket,service->protocol);
 	JS_DestroyRuntime(js_runtime);
 
 	if(service_client.user.number) {