diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..115e4dd7b33bd33e09fd4e7a7eafb3f950efc60f
--- /dev/null
+++ b/src/sbbs3/js_internal.c
@@ -0,0 +1,193 @@
+/* js_internal.c */
+
+/* Synchronet "js" object, for internal JavaScript branch and GC control */
+
+/* $Id$ */
+
+/****************************************************************************
+ * @format.tab-size 4		(Plain Text/Source Code File Header)			*
+ * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
+ *																			*
+ * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html		*
+ *																			*
+ * This program is free software; you can redistribute it and/or			*
+ * modify it under the terms of the GNU General Public License				*
+ * as published by the Free Software Foundation; either version 2			*
+ * of the License, or (at your option) any later version.					*
+ * See the GNU General Public License for more details: gpl.txt or			*
+ * http://www.fsf.org/copyleft/gpl.html										*
+ *																			*
+ * Anonymous FTP access to the most recent released source is available at	*
+ * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
+ *																			*
+ * Anonymous CVS access to the development source and modification history	*
+ * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
+ *     (just hit return, no password is necessary)							*
+ * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
+ *																			*
+ * For Synchronet coding style and modification guidelines, see				*
+ * http://www.synchro.net/source.html										*
+ *																			*
+ * You are encouraged to submit any modifications (preferably in Unix diff	*
+ * format) via e-mail to mods@synchro.net									*
+ *																			*
+ * Note: If this box doesn't appear square, then you need to fix your tabs.	*
+ ****************************************************************************/
+
+#include "sbbs.h"
+
+#include <jscntxt.h>	/* Needed for Context-private data structure */
+
+enum {
+	 PROP_BRANCH_COUNTER
+	,PROP_BRANCH_LIMIT
+	,PROP_YIELD_INTERVAL
+	,PROP_GC_INTERVAL
+#ifdef jscntxt_h___
+	,PROP_GC_BYTES
+	,PROP_GC_LASTBYTES
+	,PROP_GC_MAXBYTES
+	,PROP_GC_COUNTER
+#endif
+};
+
+static JSBool js_get(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    jsint			tiny;
+	js_branch_t*	branch;
+
+	if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL)
+		return(JS_FALSE);
+
+    tiny = JSVAL_TO_INT(id);
+
+	switch(tiny) {
+		case PROP_BRANCH_COUNTER:
+			JS_NewNumberValue(cx,branch->counter,vp);
+			break;
+		case PROP_BRANCH_LIMIT:
+			JS_NewNumberValue(cx,branch->limit,vp);
+			break;
+		case PROP_YIELD_INTERVAL:
+			JS_NewNumberValue(cx,branch->yield_freq,vp);
+			break;
+		case PROP_GC_INTERVAL:
+			JS_NewNumberValue(cx,branch->gc_freq,vp);
+			break;
+#ifdef jscntxt_h___
+		case PROP_GC_BYTES:
+			JS_NewNumberValue(cx,cx->runtime->gcBytes,vp);
+			break;
+		case PROP_GC_LASTBYTES:
+			JS_NewNumberValue(cx,cx->runtime->gcLastBytes,vp);
+			break;
+		case PROP_GC_MAXBYTES:
+			JS_NewNumberValue(cx,cx->runtime->gcMaxBytes,vp);
+			break;
+		case PROP_GC_COUNTER:
+			JS_NewNumberValue(cx,cx->runtime->gcNumber,vp);
+			break;
+#endif
+	}
+
+	return(JS_TRUE);
+}
+
+static JSBool js_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
+{
+    jsint			tiny;
+	js_branch_t*	branch;
+
+	if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL)
+		return(JS_FALSE);
+
+    tiny = JSVAL_TO_INT(id);
+
+	switch(tiny) {
+		case PROP_BRANCH_COUNTER:
+			JS_ValueToInt32(cx, *vp, (int32*)&branch->counter);
+			break;
+		case PROP_BRANCH_LIMIT:
+			JS_ValueToInt32(cx, *vp, (int32*)&branch->limit);
+			break;
+		case PROP_GC_INTERVAL:
+			JS_ValueToInt32(cx, *vp, (int32*)&branch->gc_freq);
+			break;
+		case PROP_YIELD_INTERVAL:
+			JS_ValueToInt32(cx, *vp, (int32*)&branch->yield_freq);
+			break;
+	}
+
+	return(TRUE);
+}
+
+#define GC_PROP_FLAGS	JSPROP_ENUMERATE|JSPROP_READONLY
+
+static struct JSPropertySpec js_properties[] = {
+/*		 name,				tinyid,						flags,				getter,	setter	*/
+
+	{	"branch_counter",	PROP_BRANCH_COUNTER,JSPROP_ENUMERATE,	NULL,	NULL },
+	{	"branch_limit",		PROP_BRANCH_LIMIT,	JSPROP_ENUMERATE,	NULL,	NULL },
+	{	"yield_interval",	PROP_YIELD_INTERVAL,JSPROP_ENUMERATE,	NULL,	NULL },
+	{	"gc_interval",		PROP_GC_INTERVAL,	JSPROP_ENUMERATE,	NULL,	NULL },
+#ifdef jscntxt_h___
+	{	"gc_bytes",			PROP_GC_BYTES,		GC_PROP_FLAGS,		NULL,	NULL },
+	{	"gc_last_bytes",	PROP_GC_LASTBYTES,	GC_PROP_FLAGS,		NULL,	NULL },
+	{	"gc_max_bytes",		PROP_GC_MAXBYTES,	GC_PROP_FLAGS,		NULL,	NULL },
+	{	"gc_counter",		PROP_GC_COUNTER,	GC_PROP_FLAGS,		NULL,	NULL },
+#endif
+	{0}
+};
+
+#ifdef _DEBUG
+static char* prop_desc[] = {
+	 "counter incremented for each branch"
+	,"maximum number of branches, used for infinite-loop detection (0=disabled)"
+	,"interval of periodic garbage collection (lower number=higher frequency, 0=disabled)"
+	,"interval of periodic time-slice yields (lower number=higher frequency, 0=disabled)"
+#ifdef jscntxt_h___
+	,"number of bytes currently in heap"
+	,"number of bytes in heap after last garbage collection"
+	,"maximum number of bytes in heap"
+	,"number of garbage collections"
+#endif
+	,NULL
+};
+#endif
+
+
+static JSClass js_internal_class = {
+     "JsInternal"				/* name			*/
+    ,JSCLASS_HAS_PRIVATE	/* flags		*/
+	,JS_PropertyStub		/* addProperty	*/
+	,JS_PropertyStub		/* delProperty	*/
+	,js_get					/* getProperty	*/
+	,js_set					/* setProperty	*/
+	,JS_EnumerateStub		/* enumerate	*/
+	,JS_ResolveStub			/* resolve		*/
+	,JS_ConvertStub			/* convert		*/
+	,JS_FinalizeStub		/* finalize		*/
+};
+
+JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_branch_t* branch)
+{
+	JSObject*	obj;
+
+	if((obj = JS_DefineObject(cx, parent, "js", &js_internal_class, NULL
+		,JSPROP_ENUMERATE|JSPROP_READONLY))==NULL)
+		return(NULL);
+
+	if(!JS_SetPrivate(cx, obj, branch))	/* Store a pointer to js_branch_t */
+		return(NULL);
+
+	if(!JS_DefineProperties(cx, obj, js_properties))	/* expose them */
+		return(NULL);
+
+#ifdef _DEBUG
+	js_DescribeObject(cx,obj,"JavaScript internal control object");
+	js_CreateArrayOfStrings(cx, obj, "_property_desc_list", prop_desc, JSPROP_READONLY);
+#endif
+
+	return(obj);
+}
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index f0fb377d03609402e7f3b33290ec1f64ec842584..1e2db890a720e3c6fdd2c8f9e428431e71bf4bf4 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -470,8 +470,8 @@ static BOOL js_init(char** environ)
 	if((js_glob=js_CreateGlobalObject(js_cx, &scfg, js_global_functions))==NULL)
 		return(FALSE);
 
-	/* Branch Object */
-	if(js_CreateBranchObject(js_cx, js_glob, &branch)==NULL)
+	/* Internal JS Object */
+	if(js_CreateInternalJsObject(js_cx, js_glob, &branch)==NULL)
 		return(FALSE);
 
 	/* System Object */
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index c0c0609ef215bb7a3152a315026a1626dca01cb9..9dcc7e8dee9907686f5964f0689b9aab2b5a4d35 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -789,8 +789,8 @@ bool sbbs_t::js_init()
 		if(js_CreateSystemObject(js_cx, js_glob, &cfg, uptime, startup->host_name)==NULL)
 			break;
 
-		/* Branch Object */
-		if(js_CreateBranchObject(js_cx, js_glob, &js_branch)==NULL)
+		/* Internal JS Object */
+		if(js_CreateInternalJsObject(js_cx, js_glob, &js_branch)==NULL)
 			break;
 
 		/* Client Object */
diff --git a/src/sbbs3/objects.mk b/src/sbbs3/objects.mk
index cd32a840bd9bb842c6b4da64e819fae7906d233b..ffa58be53b3e38c72ebd281e8906c47c6b86be6a 100644
--- a/src/sbbs3/objects.mk
+++ b/src/sbbs3/objects.mk
@@ -44,12 +44,12 @@ OBJS	=	$(LIBODIR)$(SLASH)ansiterm.$(OFILE)\
 			$(LIBODIR)$(SLASH)inkey.$(OFILE)\
 			$(LIBODIR)$(SLASH)ident.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_bbs.$(OFILE)\
-			$(LIBODIR)$(SLASH)js_branch.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_client.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_console.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_file.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_file_area.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_global.$(OFILE)\
+			$(LIBODIR)$(SLASH)js_internal.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_msg_area.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_msgbase.$(OFILE)\
 			$(LIBODIR)$(SLASH)js_socket.$(OFILE)\
diff --git a/src/sbbs3/sbbs.dsp b/src/sbbs3/sbbs.dsp
index a59908744893b5ee05bdfa04e483d3f74b051c6a..99a2ec229513eb080e7d5cb38ade284355e67d07 100644
--- a/src/sbbs3/sbbs.dsp
+++ b/src/sbbs3/sbbs.dsp
@@ -254,10 +254,6 @@ SOURCE=.\js_bbs.cpp
 # End Source File
 # Begin Source File
 
-SOURCE=.\js_branch.c
-# End Source File
-# Begin Source File
-
 SOURCE=.\js_client.c
 # End Source File
 # Begin Source File
@@ -278,6 +274,10 @@ SOURCE=.\js_global.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\js_internal.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\js_msg_area.c
 # End Source File
 # Begin Source File
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 2427ebcdf7a0d4d3c4a1953c4f4afd6751735d04..2a343d324e974bbfd34b460b509086f38e1ebc57 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -897,8 +897,8 @@ extern "C" {
 	/* js_global.c */
 	DLLEXPORT JSObject* DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsMethodSpec* methods);
 
-	/* js_branch.c */
-	DLLEXPORT JSObject* DLLCALL js_CreateBranchObject(JSContext* cx, JSObject* parent, js_branch_t* branch);
+	/* js_internal.c */
+	DLLEXPORT JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_branch_t* branch);
 
 	/* 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 adc53070a69c7f741227e6a016d45f24940ad19e..162b66b3cacc794cd19d6de5d27870342da0170f 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -781,8 +781,8 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 		if (!JS_DefineFunctions(js_cx, js_glob, js_global_functions))
 			break;
 
-		/* Branch Object */
-		if(js_CreateBranchObject(js_cx, js_glob, &service_client->branch)==NULL)
+		/* Internal JS Object */
+		if(js_CreateInternalJsObject(js_cx, js_glob, &service_client->branch)==NULL)
 			break;
 
 		/* Client Object */