diff --git a/src/sbbs3/ctrl/MainFormUnit.cpp b/src/sbbs3/ctrl/MainFormUnit.cpp
index 6ea745b8023b5e0553b3a691a78fa80013b8cf19..4f6e469cff634b05c66fe933e5cd28e40790f5ae 100644
--- a/src/sbbs3/ctrl/MainFormUnit.cpp
+++ b/src/sbbs3/ctrl/MainFormUnit.cpp
@@ -815,7 +815,7 @@ __fastcall TMainForm::TMainForm(TComponent* Owner)
     SAFECOPY(global.ctrl_dir,"c:\\sbbs\\ctrl\\");
     global.js.max_bytes=JAVASCRIPT_MAX_BYTES;
     global.js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
-    global.js.branch_limit=JAVASCRIPT_BRANCH_LIMIT;
+    global.js.time_limit=JAVASCRIPT_TIME_LIMIT;
     global.js.gc_interval=JAVASCRIPT_GC_INTERVAL;
     global.js.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
     global.sem_chk_freq=5;		/* seconds */
@@ -1995,8 +1995,6 @@ void __fastcall TMainForm::StartupTimerTick(TObject *Sender)
             global.js.cx_stack=Registry->ReadInteger("JS_ContextStack");
         if(global.js.cx_stack==0)
             global.js.cx_stack=JAVASCRIPT_CONTEXT_STACK;
-        if(Registry->ValueExists("JS_BranchLimit"))
-            global.js.branch_limit=Registry->ReadInteger("JS_BranchLimit");
         if(Registry->ValueExists("JS_GcInterval"))
             global.js.gc_interval=Registry->ReadInteger("JS_GcInterval");
         if(Registry->ValueExists("JS_YieldInterval"))
@@ -3156,8 +3154,7 @@ void __fastcall TMainForm::PropertiesExecute(TObject *Sender)
     PropertiesDlg->PasswordEdit->Text=Password;
     PropertiesDlg->JS_MaxBytesEdit->Text=IntToStr(global.js.max_bytes);
     PropertiesDlg->JS_ContextStackEdit->Text=IntToStr(global.js.cx_stack);
-    PropertiesDlg->JS_ThreadStackEdit->Text=IntToStr(global.js.thread_stack);    
-    PropertiesDlg->JS_BranchLimitEdit->Text=IntToStr(global.js.branch_limit);
+    PropertiesDlg->JS_TimeLimitEdit->Text=IntToStr(global.js.time_limit);
     PropertiesDlg->JS_GcIntervalEdit->Text=IntToStr(global.js.gc_interval);
     PropertiesDlg->JS_YieldIntervalEdit->Text=IntToStr(global.js.yield_interval);
     PropertiesDlg->JS_LoadPathEdit->Text=global.js.load_path;
@@ -3217,10 +3214,8 @@ void __fastcall TMainForm::PropertiesExecute(TObject *Sender)
         	=PropertiesDlg->JS_MaxBytesEdit->Text.ToIntDef(JAVASCRIPT_MAX_BYTES);
         global.js.cx_stack
         	=PropertiesDlg->JS_ContextStackEdit->Text.ToIntDef(JAVASCRIPT_CONTEXT_STACK);
-        global.js.thread_stack
-        	=PropertiesDlg->JS_ThreadStackEdit->Text.ToIntDef(JAVASCRIPT_THREAD_STACK);
-        global.js.branch_limit
-        	=PropertiesDlg->JS_BranchLimitEdit->Text.ToIntDef(JAVASCRIPT_BRANCH_LIMIT);
+        global.js.time_limit
+        	=PropertiesDlg->JS_TimeLimitEdit->Text.ToIntDef(JAVASCRIPT_TIME_LIMIT);
         global.js.gc_interval
         	=PropertiesDlg->JS_GcIntervalEdit->Text.ToIntDef(JAVASCRIPT_GC_INTERVAL);
         global.js.yield_interval
diff --git a/src/sbbs3/ctrl/PropertiesDlgUnit.dfm b/src/sbbs3/ctrl/PropertiesDlgUnit.dfm
index c9cd2485ee146bd95ab930c5c5f72bb4c9873339..4120f0a959c569f01cd292a0de538c7e1f7ccf7a 100644
--- a/src/sbbs3/ctrl/PropertiesDlgUnit.dfm
+++ b/src/sbbs3/ctrl/PropertiesDlgUnit.dfm
@@ -3,8 +3,8 @@ object PropertiesDlg: TPropertiesDlg
   Top = 219
   BorderStyle = bsDialog
   Caption = 'Control Panel Properties'
-  ClientHeight = 288
-  ClientWidth = 433
+  ClientHeight = 234
+  ClientWidth = 352
   Color = clBtnFace
   ParentFont = True
   OldCreateOrder = True
@@ -12,15 +12,15 @@ object PropertiesDlg: TPropertiesDlg
   ShowHint = True
   OnShow = FormShow
   DesignSize = (
-    433
-    288)
-  PixelsPerInch = 120
-  TextHeight = 16
+    352
+    234)
+  PixelsPerInch = 96
+  TextHeight = 13
   object OKBtn: TButton
-    Left = 329
-    Top = 10
-    Width = 93
-    Height = 31
+    Left = 267
+    Top = 8
+    Width = 76
+    Height = 25
     Anchors = [akTop, akRight]
     Caption = 'OK'
     Default = True
@@ -28,10 +28,10 @@ object PropertiesDlg: TPropertiesDlg
     TabOrder = 0
   end
   object CancelBtn: TButton
-    Left = 329
-    Top = 47
-    Width = 93
-    Height = 31
+    Left = 267
+    Top = 38
+    Width = 76
+    Height = 25
     Anchors = [akTop, akRight]
     Cancel = True
     Caption = 'Cancel'
@@ -39,10 +39,10 @@ object PropertiesDlg: TPropertiesDlg
     TabOrder = 1
   end
   object PageControl: TPageControl
-    Left = 9
-    Top = 9
-    Width = 312
-    Height = 272
+    Left = 7
+    Top = 7
+    Width = 254
+    Height = 221
     ActivePage = JavaScriptTabSheet
     Anchors = [akLeft, akTop, akBottom]
     TabIndex = 3
@@ -50,57 +50,57 @@ object PropertiesDlg: TPropertiesDlg
     object SettingsTabSheet: TTabSheet
       Caption = 'Settings'
       object Label3: TLabel
-        Left = 9
-        Top = 12
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 10
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Login Command'
       end
       object Label2: TLabel
-        Left = 9
-        Top = 44
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 36
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Config Command'
       end
       object Label4: TLabel
-        Left = 9
-        Top = 76
-        Width = 224
-        Height = 24
+        Left = 7
+        Top = 62
+        Width = 182
+        Height = 19
         AutoSize = False
         Caption = 'Node Display Interval (seconds)'
       end
       object Label5: TLabel
-        Left = 9
-        Top = 108
-        Width = 224
-        Height = 24
+        Left = 7
+        Top = 88
+        Width = 182
+        Height = 19
         AutoSize = False
         Caption = 'Client Display Interval (seconds)'
       end
       object PasswordLabel: TLabel
-        Left = 9
-        Top = 206
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 167
+        Width = 89
+        Height = 20
         AutoSize = False
         Caption = 'Password'
       end
       object Label10: TLabel
-        Left = 9
-        Top = 138
-        Width = 224
-        Height = 23
+        Left = 7
+        Top = 112
+        Width = 182
+        Height = 19
         AutoSize = False
         Caption = 'Semaphore Check Interval (seconds)'
       end
       object LoginCmdEdit: TEdit
-        Left = 121
-        Top = 12
-        Width = 168
+        Left = 98
+        Top = 10
+        Width = 137
         Height = 24
         Hint = 'Login command-line or URL (default = telnet://localhost)'
         ParentShowHint = False
@@ -108,9 +108,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 0
       end
       object ConfigCmdEdit: TEdit
-        Left = 121
-        Top = 44
-        Width = 168
+        Left = 98
+        Top = 36
+        Width = 137
         Height = 24
         Hint = 'Configuration command line'
         ParentShowHint = False
@@ -118,9 +118,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 1
       end
       object NodeIntEdit: TEdit
-        Left = 240
-        Top = 76
-        Width = 25
+        Left = 195
+        Top = 62
+        Width = 20
         Height = 24
         Hint = 'Frequency of updates to Node window'
         ParentShowHint = False
@@ -129,10 +129,10 @@ object PropertiesDlg: TPropertiesDlg
         Text = '1'
       end
       object NodeIntUpDown: TUpDown
-        Left = 265
-        Top = 76
-        Width = 19
-        Height = 24
+        Left = 215
+        Top = 62
+        Width = 16
+        Height = 19
         Associate = NodeIntEdit
         Min = 1
         Max = 99
@@ -141,9 +141,9 @@ object PropertiesDlg: TPropertiesDlg
         Wrap = False
       end
       object ClientIntEdit: TEdit
-        Left = 240
-        Top = 108
-        Width = 25
+        Left = 195
+        Top = 88
+        Width = 20
         Height = 24
         Hint = 'Frequency of updates to clients window'
         ParentShowHint = False
@@ -152,10 +152,10 @@ object PropertiesDlg: TPropertiesDlg
         Text = '1'
       end
       object ClientIntUpDown: TUpDown
-        Left = 265
-        Top = 108
-        Width = 19
-        Height = 24
+        Left = 215
+        Top = 88
+        Width = 16
+        Height = 19
         Associate = ClientIntEdit
         Min = 1
         Max = 99
@@ -164,10 +164,10 @@ object PropertiesDlg: TPropertiesDlg
         Wrap = False
       end
       object TrayIconCheckBox: TCheckBox
-        Left = 9
-        Top = 170
-        Width = 280
-        Height = 24
+        Left = 7
+        Top = 138
+        Width = 228
+        Height = 20
         Hint = 'Create tray icon when minimized'
         Caption = 'Minimize to System Tray'
         ParentShowHint = False
@@ -176,9 +176,9 @@ object PropertiesDlg: TPropertiesDlg
         OnClick = TrayIconCheckBoxClick
       end
       object PasswordEdit: TEdit
-        Left = 121
-        Top = 206
-        Width = 168
+        Left = 98
+        Top = 167
+        Width = 137
         Height = 24
         Hint = 'Required password for restoring from system tray icon'
         ParentShowHint = False
@@ -187,9 +187,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 9
       end
       object SemFreqEdit: TEdit
-        Left = 240
-        Top = 138
-        Width = 25
+        Left = 195
+        Top = 112
+        Width = 20
         Height = 24
         Hint = 'Frequency of checks for signaled semaphore files'
         ParentShowHint = False
@@ -198,10 +198,10 @@ object PropertiesDlg: TPropertiesDlg
         Text = '1'
       end
       object SemFreqUpDown: TUpDown
-        Left = 265
-        Top = 138
-        Width = 18
-        Height = 24
+        Left = 215
+        Top = 112
+        Width = 15
+        Height = 20
         Associate = SemFreqEdit
         Min = 1
         Max = 99
@@ -214,11 +214,11 @@ object PropertiesDlg: TPropertiesDlg
       Caption = 'Customize'
       ImageIndex = 1
       object SourceComboBox: TComboBox
-        Left = 9
-        Top = 12
-        Width = 134
-        Height = 24
-        ItemHeight = 16
+        Left = 7
+        Top = 10
+        Width = 109
+        Height = 21
+        ItemHeight = 13
         TabOrder = 0
         Text = 'Node List'
         OnChange = SourceComboBoxChange
@@ -233,46 +233,46 @@ object PropertiesDlg: TPropertiesDlg
           'Services Log')
       end
       object ExampleEdit: TEdit
-        Left = 154
-        Top = 12
-        Width = 135
+        Left = 125
+        Top = 10
+        Width = 110
         Height = 24
         TabOrder = 1
         Text = 'Scheme'
       end
       object FontButton: TButton
-        Left = 9
-        Top = 44
-        Width = 134
-        Height = 24
+        Left = 7
+        Top = 36
+        Width = 109
+        Height = 19
         Caption = 'Change Font'
         TabOrder = 2
         OnClick = FontButtonClick
       end
       object BackgroundButton: TButton
-        Left = 154
-        Top = 44
-        Width = 135
-        Height = 24
+        Left = 125
+        Top = 36
+        Width = 110
+        Height = 19
         Caption = 'Background Color'
         TabOrder = 3
         OnClick = BackgroundButtonClick
       end
       object ApplyButton: TButton
-        Left = 9
-        Top = 76
-        Width = 134
-        Height = 24
+        Left = 7
+        Top = 62
+        Width = 109
+        Height = 19
         Caption = 'Apply Scheme To:'
         TabOrder = 4
         OnClick = ApplyButtonClick
       end
       object TargetComboBox: TComboBox
-        Left = 154
-        Top = 76
-        Width = 135
-        Height = 24
-        ItemHeight = 16
+        Left = 125
+        Top = 62
+        Width = 110
+        Height = 21
+        ItemHeight = 13
         TabOrder = 5
         Items.Strings = (
           'Node List'
@@ -286,27 +286,27 @@ object PropertiesDlg: TPropertiesDlg
           'All  Windows')
       end
       object LogFontGroupBox: TGroupBox
-        Left = 8
-        Top = 128
-        Width = 281
-        Height = 97
+        Left = 7
+        Top = 104
+        Width = 228
+        Height = 79
         Caption = 'Log Fonts'
         TabOrder = 6
         object LogLevelLabel: TLabel
-          Left = 22
-          Top = 26
-          Width = 113
-          Height = 23
+          Left = 18
+          Top = 21
+          Width = 92
+          Height = 19
           Alignment = taRightJustify
           AutoSize = False
           Caption = 'Log Level'
         end
         object LogLevelComboBox: TComboBox
-          Left = 146
-          Top = 24
-          Width = 119
-          Height = 24
-          ItemHeight = 16
+          Left = 119
+          Top = 20
+          Width = 96
+          Height = 21
+          ItemHeight = 13
           ItemIndex = 7
           TabOrder = 0
           Text = 'Debug'
@@ -322,18 +322,18 @@ object PropertiesDlg: TPropertiesDlg
             'Debug')
         end
         object LogFontExampleEdit: TEdit
-          Left = 146
-          Top = 56
-          Width = 119
+          Left = 119
+          Top = 46
+          Width = 96
           Height = 24
           TabOrder = 1
           Text = 'Example'
         end
         object LogFontButton: TButton
-          Left = 16
-          Top = 56
-          Width = 122
-          Height = 24
+          Left = 13
+          Top = 46
+          Width = 99
+          Height = 19
           Caption = 'Change Font'
           TabOrder = 2
           OnClick = LogFontButtonClick
@@ -344,49 +344,49 @@ object PropertiesDlg: TPropertiesDlg
       Caption = 'Advanced'
       ImageIndex = 2
       object Label1: TLabel
-        Left = 9
-        Top = 12
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 10
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Control Directory'
       end
       object Label6: TLabel
-        Left = 9
-        Top = 76
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 62
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Hostname'
       end
       object Label8: TLabel
-        Left = 9
-        Top = 108
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 88
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Log Window Size'
       end
       object Label9: TLabel
-        Left = 9
-        Top = 44
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 36
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Temp Directory'
       end
       object ErrorSoundLabel: TLabel
-        Left = 9
-        Top = 140
-        Width = 80
-        Height = 25
+        Left = 7
+        Top = 114
+        Width = 65
+        Height = 20
         AutoSize = False
         Caption = 'Error Sound'
       end
       object CtrlDirEdit: TEdit
-        Left = 121
-        Top = 12
-        Width = 168
+        Left = 98
+        Top = 10
+        Width = 137
         Height = 24
         Hint = 'Control directory (e.g. c:\sbbs\ctrl)'
         ParentShowHint = False
@@ -394,9 +394,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 0
       end
       object HostnameEdit: TEdit
-        Left = 121
-        Top = 76
-        Width = 168
+        Left = 98
+        Top = 62
+        Width = 137
         Height = 24
         Hint = 'Hostname (if different than configured in SCFG)'
         ParentShowHint = False
@@ -404,9 +404,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 2
       end
       object MaxLogLenEdit: TEdit
-        Left = 121
-        Top = 108
-        Width = 168
+        Left = 98
+        Top = 88
+        Width = 137
         Height = 24
         Hint = 
           'Maximum number of lines to store in log windows before auto-dele' +
@@ -416,9 +416,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 3
       end
       object TempDirEdit: TEdit
-        Left = 121
-        Top = 44
-        Width = 168
+        Left = 98
+        Top = 36
+        Width = 137
         Height = 24
         Hint = 'Temp directory (e.g. C:\SBBSTEMP)'
         ParentShowHint = False
@@ -426,10 +426,10 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 1
       end
       object UndockableCheckBox: TCheckBox
-        Left = 9
-        Top = 177
-        Width = 280
-        Height = 25
+        Left = 7
+        Top = 144
+        Width = 228
+        Height = 20
         Hint = 'Allow child windows to be "un-docked" from main window'
         Caption = 'Undockable Windows'
         ParentShowHint = False
@@ -437,10 +437,10 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 6
       end
       object FileAssociationsCheckBox: TCheckBox
-        Left = 9
-        Top = 209
-        Width = 280
-        Height = 25
+        Left = 7
+        Top = 170
+        Width = 228
+        Height = 20
         Hint = 'Use Windows file associations when viewing or editing files'
         Caption = 'Use File Associations'
         ParentShowHint = False
@@ -448,9 +448,9 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 7
       end
       object ErrorSoundEdit: TEdit
-        Left = 121
-        Top = 140
-        Width = 137
+        Left = 98
+        Top = 114
+        Width = 112
         Height = 24
         Hint = 'Sound file to play when an error condition is logged'
         ParentShowHint = False
@@ -458,10 +458,10 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 4
       end
       object ErrorSoundButton: TButton
-        Left = 263
-        Top = 140
-        Width = 25
-        Height = 26
+        Left = 214
+        Top = 114
+        Width = 20
+        Height = 21
         Caption = '...'
         TabOrder = 5
         OnClick = ErrorSoundButtonClick
@@ -471,66 +471,58 @@ object PropertiesDlg: TPropertiesDlg
       Caption = 'JavaScript'
       ImageIndex = 3
       object Label7: TLabel
-        Left = 9
-        Top = 12
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 10
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Heap Size'
       end
       object Label11: TLabel
-        Left = 9
-        Top = 44
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 36
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Context Stack'
       end
       object Label12: TLabel
-        Left = 9
-        Top = 108
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 62
+        Width = 89
+        Height = 19
         AutoSize = False
-        Caption = 'Branch Limit'
+        Caption = 'Time Limit'
       end
       object Label13: TLabel
-        Left = 9
-        Top = 140
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 88
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'GC Interval'
       end
       object Label14: TLabel
-        Left = 9
-        Top = 172
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 114
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Yield Interval'
       end
-      object Label15: TLabel
-        Left = 9
-        Top = 76
-        Width = 109
-        Height = 24
-        AutoSize = False
-        Caption = 'Thread Stack'
-      end
       object Label16: TLabel
-        Left = 9
-        Top = 204
-        Width = 109
-        Height = 24
+        Left = 7
+        Top = 140
+        Width = 89
+        Height = 19
         AutoSize = False
         Caption = 'Load Path'
       end
       object JS_MaxBytesEdit: TEdit
-        Left = 121
-        Top = 12
-        Width = 168
-        Height = 24
+        Left = 98
+        Top = 10
+        Width = 137
+        Height = 21
         Hint = 
           'Maximum number of bytes that can be allocated per runtime before' +
           ' garbage collection'
@@ -539,68 +531,58 @@ object PropertiesDlg: TPropertiesDlg
         TabOrder = 0
       end
       object JS_ContextStackEdit: TEdit
-        Left = 121
-        Top = 44
-        Width = 168
-        Height = 24
+        Left = 98
+        Top = 36
+        Width = 137
+        Height = 21
         Hint = 'Size of context stack (in bytes)'
         ParentShowHint = False
         ShowHint = True
         TabOrder = 1
       end
-      object JS_BranchLimitEdit: TEdit
-        Left = 121
-        Top = 108
-        Width = 168
-        Height = 24
+      object JS_TimeLimitEdit: TEdit
+        Left = 98
+        Top = 62
+        Width = 137
+        Height = 21
         Hint = 
-          'Maximum number of branches before triggering "infinite loop" det' +
-          'ection (0=disabled)'
+          'Maximum number of 100ms ticks before triggering "infinite loop" ' +
+          'detection (0=disabled)'
         ParentShowHint = False
         ShowHint = True
-        TabOrder = 3
+        TabOrder = 2
       end
       object JS_GcIntervalEdit: TEdit
-        Left = 121
-        Top = 140
-        Width = 168
-        Height = 24
+        Left = 98
+        Top = 88
+        Width = 137
+        Height = 21
         Hint = 
-          'Number of branches between attempted garbage collections (0=disa' +
-          'bled)'
+          'Number of ticks between attempted garbage collections (0=disable' +
+          'd)'
         ParentShowHint = False
         ShowHint = True
-        TabOrder = 4
+        TabOrder = 3
       end
       object JS_YieldIntervalEdit: TEdit
-        Left = 121
-        Top = 172
-        Width = 168
-        Height = 24
-        Hint = 'Number of branches between forced yields (0=disabled)'
-        ParentShowHint = False
-        ShowHint = True
-        TabOrder = 5
-      end
-      object JS_ThreadStackEdit: TEdit
-        Left = 121
-        Top = 76
-        Width = 168
-        Height = 24
-        Hint = 'JS thread stack limit (in bytes, 0=unlimited)'
+        Left = 98
+        Top = 114
+        Width = 137
+        Height = 21
+        Hint = 'Number of ticks between forced yields (0=disabled)'
         ParentShowHint = False
         ShowHint = True
-        TabOrder = 2
+        TabOrder = 4
       end
       object JS_LoadPathEdit: TEdit
-        Left = 121
-        Top = 204
-        Width = 168
-        Height = 24
+        Left = 98
+        Top = 140
+        Width = 137
+        Height = 21
         Hint = 'Comma-separated list of directories to search for loaded scripts'
         ParentShowHint = False
         ShowHint = True
-        TabOrder = 6
+        TabOrder = 5
       end
     end
   end
diff --git a/src/sbbs3/ctrl/PropertiesDlgUnit.h b/src/sbbs3/ctrl/PropertiesDlgUnit.h
index 55e7aecc089c36a7219896dd554c5be9f8420d02..2ee7edd0b7da69b8f874991f8cc5328891004b9d 100644
--- a/src/sbbs3/ctrl/PropertiesDlgUnit.h
+++ b/src/sbbs3/ctrl/PropertiesDlgUnit.h
@@ -4,7 +4,7 @@
  * @format.tab-size 4		(Plain Text/Source Code File Header)			*
  * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
  *																			*
- * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html		*
+ * Copyright 2011 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				*
@@ -96,14 +96,12 @@ __published:
 	TLabel *Label11;
 	TEdit *JS_ContextStackEdit;
 	TLabel *Label12;
-	TEdit *JS_BranchLimitEdit;
+    TEdit *JS_TimeLimitEdit;
 	TLabel *Label13;
 	TEdit *JS_GcIntervalEdit;
 	TLabel *Label14;
 	TEdit *JS_YieldIntervalEdit;
     TCheckBox *FileAssociationsCheckBox;
-    TLabel *Label15;
-    TEdit *JS_ThreadStackEdit;
     TGroupBox *LogFontGroupBox;
     TComboBox *LogLevelComboBox;
     TEdit *LogFontExampleEdit;
diff --git a/src/sbbs3/exec.cpp b/src/sbbs3/exec.cpp
index edc38e8ba7e03b456db2756d75741b98aecd13c6..d16d9589df82b779b5a9d2a41d114dbcf10af8a2 100644
--- a/src/sbbs3/exec.cpp
+++ b/src/sbbs3/exec.cpp
@@ -537,34 +537,25 @@ char * sbbs_t::copystrvar(csi_t *csi, char *p, char *str)
 #ifdef JAVASCRIPT
 
 static JSBool
-js_BranchCallback(JSContext *cx, JSObject *script)
+js_OperationCallback(JSContext *cx)
 {
+	JSBool	ret;
 	sbbs_t*		sbbs;
 
 	if((sbbs=(sbbs_t*)JS_GetContextPrivate(cx))==NULL)
 		return(JS_FALSE);
 
-	if(sbbs->js_branch.auto_terminate && !sbbs->online) {
+	if(sbbs->js_callback.auto_terminate && !sbbs->online) {
 		JS_ReportWarning(cx,"Disconnected");
-		sbbs->js_branch.counter=0;
+		sbbs->js_callback.counter=0;
 		return(JS_FALSE);
 	}
 
-	return(js_CommonBranchCallback(cx,&sbbs->js_branch));
-}
-
-#if JS_VERSION>180
-static JSBool
-js_OperationCallback(JSContext *cx)
-{
-	JSBool	ret;
-
 	JS_SetOperationCallback(cx, NULL);
-	ret=js_BranchCallback(cx, NULL);
+	ret=js_CommonOperationCallback(cx,&sbbs->js_callback);
 	JS_SetOperationCallback(cx, js_OperationCallback);
 	return ret;
 }
-#endif
 
 static const char* js_ext(const char* fname)
 {
@@ -663,7 +654,7 @@ long sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* sco
 	}
 
 	if(scope==NULL) {
-		js_branch.counter=0;	// Reset loop counter
+		js_callback.counter=0;	// Reset loop counter
 
 #if JS_VERSION>180
 		JS_SetOperationCallback(js_cx, js_OperationCallback);
@@ -680,7 +671,7 @@ long sbbs_t::js_execfile(const char *cmd, const char* startup_dir, JSObject* sco
 		if(rval!=JSVAL_VOID)
 			JS_ValueToInt32(js_cx,rval,&result);
 
-		js_EvalOnExit(js_cx, js_scope, &js_branch);
+		js_EvalOnExit(js_cx, js_scope, &js_callback);
 	}
 
 	JS_ReportPendingException(js_cx);	/* Added Dec-4-2005, rswindell */
diff --git a/src/sbbs3/ftpsrvr.c b/src/sbbs3/ftpsrvr.c
index 5c4b30fa8cdf96d74c17d68a425915898711cc32..440d4cad6dd4b0e5e8a26aa53a2ab42c3d6fde44 100644
--- a/src/sbbs3/ftpsrvr.c
+++ b/src/sbbs3/ftpsrvr.c
@@ -477,7 +477,7 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 }
 
 static JSContext* 
-js_initcx(JSRuntime* runtime, SOCKET sock, JSObject** glob, JSObject** ftp, js_branch_t* branch)
+js_initcx(JSRuntime* runtime, SOCKET sock, JSObject** glob, JSObject** ftp, js_callback_t* cb)
 {
 	JSContext*	js_cx;
 	JSObject*	js_glob;
@@ -494,7 +494,7 @@ js_initcx(JSRuntime* runtime, SOCKET sock, JSObject** glob, JSObject** ftp, js_b
 
     JS_SetErrorReporter(js_cx, js_ErrorReporter);
 
-	memset(branch, 0, sizeof(js_branch_t));
+	memset(cb, 0, sizeof(js_callback_t));
 
 	/* ToDo: call js_CreateCommonObjects() instead */
 
@@ -508,7 +508,7 @@ js_initcx(JSRuntime* runtime, SOCKET sock, JSObject** glob, JSObject** ftp, js_b
 			break;
 
 		/* Internal JS Object */
-		if(js_CreateInternalJsObject(js_cx, js_glob, branch, &startup->js)==NULL)
+		if(js_CreateInternalJsObject(js_cx, js_glob, cb, &startup->js)==NULL)
 			break;
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Initializing System object",sock);
@@ -2444,7 +2444,7 @@ static void ctrl_thread(void* arg)
 	JSObject*	js_glob;
 	JSObject*	js_ftp;
 	JSString*	js_str;
-	js_branch_t	js_branch;
+	js_callback_t	js_callback;
 #endif
 
 	SetThreadName("FTP CTRL");
@@ -3978,7 +3978,7 @@ static void ctrl_thread(void* arg)
 
 					if(js_cx==NULL) {	/* Context not yet created, create it now */
 						/* js_initcx() starts a request */
-						if(((js_cx=js_initcx(js_runtime, sock,&js_glob,&js_ftp,&js_branch))==NULL)) {
+						if(((js_cx=js_initcx(js_runtime, sock,&js_glob,&js_ftp,&js_callback))==NULL)) {
 							lprintf(LOG_ERR,"%04d !ERROR initializing JavaScript context",sock);
 							sockprintf(sock,"451 Error initializing JavaScript context");
 							filepos=0;
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 81e18b9e7e0f45d48d239a36091e5514acc49e97..774f4902d08a7fd75bc221497379730f52b4028e 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -108,7 +108,7 @@ typedef struct {
 	JSObject*		obj;
 	JSObject*		script;
 	msg_queue_t*	msg_queue;
-	js_branch_t		branch;
+	js_callback_t	cb;
 	JSErrorReporter error_reporter;
 	JSNative		log;
 } background_data_t;
@@ -122,12 +122,11 @@ static void background_thread(void* arg)
 	SetThreadName("JS Background");
 	msgQueueAttach(bg->msg_queue);
 	JS_SetContextThread(bg->cx);
-	JS_SetThreadStackLimit(bg->cx, 0);
 	JS_BEGINREQUEST(bg->cx);
 	if(!JS_ExecuteScript(bg->cx, bg->obj, bg->script, &result)
 		&& JS_GetProperty(bg->cx, bg->obj, "exit_code", &exit_code))
 		result=exit_code;
-	js_EvalOnExit(bg->cx, bg->obj, &bg->branch);
+	js_EvalOnExit(bg->cx, bg->obj, &bg->cb);
 	js_enqueue_value(bg->cx, bg->msg_queue, result, NULL);
 	JS_ENDREQUEST(bg->cx);
 	JS_DestroyContext(bg->cx);
@@ -153,9 +152,11 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 	JS_SetContextPrivate(cx, bg);
 }
 
-static JSBool js_BranchCallback(JSContext *cx, JSObject* script)
+static JSBool
+js_OperationCallback(JSContext *cx)
 {
 	background_data_t* bg;
+	JSBool	ret;
 
 	if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
 		return(JS_FALSE);
@@ -163,21 +164,11 @@ static JSBool js_BranchCallback(JSContext *cx, JSObject* script)
 	if(bg->parent_cx!=NULL && !JS_IsRunning(bg->parent_cx)) 	/* die when parent dies */
 		return(JS_FALSE);
 
-	return js_CommonBranchCallback(cx,&bg->branch);
-}
-
-#if JS_VERSION>180
-static JSBool
-js_OperationCallback(JSContext *cx)
-{
-	JSBool	ret;
-
 	JS_SetOperationCallback(cx, NULL);
-	ret=js_BranchCallback(cx, NULL);
+	ret=js_CommonOperationCallback(cx,&bg->cb);
 	JS_SetOperationCallback(cx, js_OperationCallback);
 	return ret;
 }
-#endif
 
 /* Create a new value in the new context with a value from the original context */
 /* Note: objects (including arrays) not currently supported */
@@ -249,17 +240,17 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 
 		bg->parent_cx = cx;
 
-		/* Setup default values for branch settings */
-		bg->branch.limit=p->startup->branch_limit;
-		bg->branch.gc_interval=p->startup->gc_interval;
-		bg->branch.yield_interval=p->startup->yield_interval;
+		/* Setup default values for callback settings */
+		bg->cb.limit=p->startup->time_limit;
+		bg->cb.gc_interval=p->startup->gc_interval;
+		bg->cb.yield_interval=p->startup->yield_interval;
 #if 0
 		if(JS_GetProperty(cx, obj,"js",&val))	/* copy branch settings from parent */
 			memcpy(&bg->branch,JS_GetPrivate(cx,JSVAL_TO_OBJECT(val)),sizeof(bg->branch));
 #endif
-		bg->branch.terminated=NULL;	/* could be bad pointer at any time */
-		bg->branch.counter=0;
-		bg->branch.gc_attempts=0;
+		bg->cb.terminated=NULL;	/* could be bad pointer at any time */
+		bg->cb.counter=0;
+		bg->cb.gc_attempts=0;
 
 		if((bg->runtime = jsrt_GetNew(JAVASCRIPT_MAX_BYTES, 1000, __FILE__, __LINE__))==NULL)
 			return(JS_FALSE);
@@ -275,7 +266,7 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 				,0				/* uptime */
 				,""				/* hostname */
 				,""				/* socklib_desc */
-				,&bg->branch	/* js */
+				,&bg->cb		/* js */
 				,p->startup		/* js */
 				,NULL			/* client */
 				,INVALID_SOCKET	/* client_socket */
@@ -292,13 +283,9 @@ js_load(JSContext *cx, uintN argc, jsval *arglist)
 		JS_SetErrorReporter(cx,bg->error_reporter);
 		JS_SetErrorReporter(bg->cx,js_ErrorReporter);
 
-		/* Set our branch callback (which calls the generic branch callback) */
+		/* Set our Operation callback (which calls the generic branch callback) */
 		JS_SetContextPrivate(bg->cx, bg);
-#if JS_VERSION>180
 		JS_SetOperationCallback(bg->cx, js_OperationCallback);
-#else
-		JS_SetBranchCallback(bg->cx, js_BranchCallback);
-#endif
 
 		/* Save parent's 'log' function (for later use by our log function) */
 		if(JS_GetProperty(cx, obj, "log", &val)) {
@@ -3850,7 +3837,7 @@ JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx
 										,time_t uptime				/* system */
 										,char* host_name			/* system */
 										,char* socklib_desc			/* system */
-										,js_branch_t* branch		/* js */
+										,js_callback_t* cb			/* js */
 										,js_startup_t* js_startup	/* js */
 										,client_t* client			/* client */
 										,SOCKET client_socket		/* client */
@@ -3871,8 +3858,8 @@ JSObject* DLLCALL js_CreateCommonObjects(JSContext* js_cx
 		return(NULL);
 
 	/* Internal JS Object */
-	if(branch!=NULL 
-		&& js_CreateInternalJsObject(js_cx, js_glob, branch, js_startup)==NULL)
+	if(cb!=NULL 
+		&& js_CreateInternalJsObject(js_cx, js_glob, cb, js_startup)==NULL)
 		return(NULL);
 
 	/* Client Object */
diff --git a/src/sbbs3/js_internal.c b/src/sbbs3/js_internal.c
index f9454d60cf4c7b58db767d0fceee6c7b72a9fc2a..564397c5612b706ef448ee4a67ba2aa878a5c1a4 100644
--- a/src/sbbs3/js_internal.c
+++ b/src/sbbs3/js_internal.c
@@ -1,6 +1,6 @@
 /* js_internal.c */
 
-/* Synchronet "js" object, for internal JavaScript branch and GC control */
+/* Synchronet "js" object, for internal JavaScript callback and GC control */
 
 /* $Id$ */
 
@@ -42,8 +42,8 @@ enum {
 	 PROP_VERSION
 	,PROP_TERMINATED
 	,PROP_AUTO_TERMINATE
-	,PROP_BRANCH_COUNTER
-	,PROP_BRANCH_LIMIT
+	,PROP_COUNTER
+	,PROP_TIME_LIMIT
 	,PROP_YIELD_INTERVAL
 	,PROP_GC_INTERVAL
 	,PROP_GC_ATTEMPTS
@@ -60,9 +60,9 @@ static JSBool js_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 {
 	jsval idval;
     jsint			tiny;
-	js_branch_t*	branch;
+	js_callback_t*	cb;
 
-	if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL)
+	if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL)
 		return(JS_FALSE);
 
     JS_IdToValue(cx, id, &idval);
@@ -73,28 +73,28 @@ static JSBool js_get(JSContext *cx, JSObject *obj, jsid id, jsval *vp)
 			*vp=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,(char *)JS_GetImplementationVersion()));
 			break;
 		case PROP_TERMINATED:
-			if(branch->terminated==NULL)
+			if(cb->terminated==NULL)
 				*vp=JSVAL_FALSE;
 			else
-				*vp=BOOLEAN_TO_JSVAL(*branch->terminated);
+				*vp=BOOLEAN_TO_JSVAL(*cb->terminated);
 			break;
 		case PROP_AUTO_TERMINATE:
-			*vp=BOOLEAN_TO_JSVAL(branch->auto_terminate);
+			*vp=BOOLEAN_TO_JSVAL(cb->auto_terminate);
 			break;
-		case PROP_BRANCH_COUNTER:
-			*vp=DOUBLE_TO_JSVAL((double)branch->counter);
+		case PROP_COUNTER:
+			*vp=DOUBLE_TO_JSVAL((double)cb->counter);
 			break;
-		case PROP_BRANCH_LIMIT:
-			*vp=DOUBLE_TO_JSVAL(branch->limit);
+		case PROP_TIME_LIMIT:
+			*vp=DOUBLE_TO_JSVAL(cb->limit);
 			break;
 		case PROP_YIELD_INTERVAL:
-			*vp=DOUBLE_TO_JSVAL((double)branch->yield_interval);
+			*vp=DOUBLE_TO_JSVAL((double)cb->yield_interval);
 			break;
 		case PROP_GC_INTERVAL:
-			*vp=DOUBLE_TO_JSVAL((double)branch->gc_interval);
+			*vp=DOUBLE_TO_JSVAL((double)cb->gc_interval);
 			break;
 		case PROP_GC_ATTEMPTS:
-			*vp=DOUBLE_TO_JSVAL((double)branch->gc_attempts);
+			*vp=DOUBLE_TO_JSVAL((double)cb->gc_attempts);
 			break;
 #ifdef jscntxt_h___
 		case PROP_GC_COUNTER:
@@ -122,9 +122,9 @@ static JSBool js_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval
 {
 	jsval idval;
     jsint			tiny;
-	js_branch_t*	branch;
+	js_callback_t*	cb;
 
-	if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL)
+	if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL)
 		return(JS_FALSE);
 
     JS_IdToValue(cx, id, &idval);
@@ -132,26 +132,26 @@ static JSBool js_set(JSContext *cx, JSObject *obj, jsid id, JSBool strict, jsval
 
 	switch(tiny) {
 		case PROP_TERMINATED:
-			if(branch->terminated!=NULL)
-				JS_ValueToBoolean(cx, *vp, (int *)branch->terminated);
+			if(cb->terminated!=NULL)
+				JS_ValueToBoolean(cx, *vp, (int *)cb->terminated);
 			break;
 		case PROP_AUTO_TERMINATE:
-			JS_ValueToBoolean(cx,*vp,&branch->auto_terminate);
+			JS_ValueToBoolean(cx,*vp,&cb->auto_terminate);
 			break;
-		case PROP_BRANCH_COUNTER:
-			if(!JS_ValueToInt32(cx, *vp, (int32*)&branch->counter))
+		case PROP_COUNTER:
+			if(!JS_ValueToInt32(cx, *vp, (int32*)&cb->counter))
 				return JS_FALSE;
 			break;
-		case PROP_BRANCH_LIMIT:
-			if(!JS_ValueToInt32(cx, *vp, (int32*)&branch->limit))
+		case PROP_TIME_LIMIT:
+			if(!JS_ValueToInt32(cx, *vp, (int32*)&cb->limit))
 				return JS_FALSE;
 			break;
 		case PROP_GC_INTERVAL:
-			if(!JS_ValueToInt32(cx, *vp, (int32*)&branch->gc_interval))
+			if(!JS_ValueToInt32(cx, *vp, (int32*)&cb->gc_interval))
 				return JS_FALSE;
 			break;
 		case PROP_YIELD_INTERVAL:
-			if(!JS_ValueToInt32(cx, *vp, (int32*)&branch->yield_interval))
+			if(!JS_ValueToInt32(cx, *vp, (int32*)&cb->yield_interval))
 				return JS_FALSE;
 			break;
 #ifdef jscntxt_h___
@@ -173,8 +173,10 @@ static jsSyncPropertySpec js_properties[] = {
 	{	"version",			PROP_VERSION,		PROP_FLAGS,			311 },
 	{	"auto_terminate",	PROP_AUTO_TERMINATE,JSPROP_ENUMERATE,	311 },
 	{	"terminated",		PROP_TERMINATED,	JSPROP_ENUMERATE,	311 },
-	{	"branch_counter",	PROP_BRANCH_COUNTER,JSPROP_ENUMERATE,	311 },
-	{	"branch_limit",		PROP_BRANCH_LIMIT,	JSPROP_ENUMERATE,	311 },
+	{	"branch_counter",	PROP_COUNTER,		0,					311 },
+	{	"counter",			PROP_COUNTER,		JSPROP_ENUMERATE,	316 },
+	{	"branch_limit",		PROP_TIME_LIMIT,	0,					311 },
+	{	"time_limit",		PROP_TIME_LIMIT,	JSPROP_ENUMERATE,	316 },
 	{	"yield_interval",	PROP_YIELD_INTERVAL,JSPROP_ENUMERATE,	311 },
 	{	"gc_interval",		PROP_GC_INTERVAL,	JSPROP_ENUMERATE,	311 },
 	{	"gc_attempts",		PROP_GC_ATTEMPTS,	PROP_FLAGS,			311 },
@@ -210,28 +212,27 @@ static char* prop_desc[] = {
 #endif
 
 JSBool DLLCALL
-js_CommonBranchCallback(JSContext *cx, js_branch_t* branch)
+js_CommonOperationCallback(JSContext *cx, js_callback_t* cb)
 {
-	branch->counter++;
+	cb->counter++;
 
 	/* Terminated? */
-	if(branch->auto_terminate &&
-		(branch->terminated!=NULL && *branch->terminated)) {
+	if(cb->auto_terminate &&
+		(cb->terminated!=NULL && *cb->terminated)) {
 		JS_ReportWarning(cx,"Terminated");
-		branch->counter=0;
+		cb->counter=0;
 		return(JS_FALSE);
 	}
 
 	/* Infinite loop? */
-	if(branch->limit && branch->counter > branch->limit) {
-		JS_ReportError(cx,"Infinite loop (%lu branches) detected",branch->counter);
-		branch->counter=0;
+	if(cb->limit && cb->counter > cb->limit) {
+		JS_ReportError(cx,"Infinite loop (%lu branches) detected",cb->counter);
+		cb->counter=0;
 		return(JS_FALSE);
 	}
 
-#ifndef USE_JS_OPERATION_CALLBACK
 	/* Give up timeslices every once in a while */
-	if(branch->yield_interval && (branch->counter%branch->yield_interval)==0) {
+	if(cb->yield_interval && (cb->counter%cb->yield_interval)==0) {
 		jsrefcount	rc;
 
 		rc=JS_SUSPENDREQUEST(cx);
@@ -240,9 +241,8 @@ js_CommonBranchCallback(JSContext *cx, js_branch_t* branch)
 	}
 
 	/* Periodic Garbage Collection */
-	if(branch->gc_interval && (branch->counter%branch->gc_interval)==0)
-		JS_MaybeGC(cx), branch->gc_attempts++;
-#endif
+	if(cb->gc_interval && (cb->counter%cb->gc_interval)==0)
+		JS_MaybeGC(cx), cb->gc_attempts++;
 
     return(JS_TRUE);
 }
@@ -288,23 +288,9 @@ js_eval(JSContext *parent_cx, uintN argc, jsval *arglist)
 	JS_SetErrorReporter(parent_cx,reporter);
 	JS_SetErrorReporter(cx,reporter);
 
-#ifdef EVAL_BRANCH_CALLBACK
-	JS_SetContextPrivate(cx, JS_GetPrivate(parent_cx, parent_obj));
-#if JS_VERSION>180
-	JS_SetOperationCallback(cx, js_OperationCallback);
-#else
-	JS_SetBranchCallback(cx, js_BranchCallback);
-#endif
-#else	/* Use the branch callback from the parent context */
+	/* Use the branch callback from the parent context */
 	JS_SetContextPrivate(cx, JS_GetContextPrivate(parent_cx));
-#if JS_VERSION>180
 	JS_SetOperationCallback(cx, JS_GetOperationCallback(parent_cx));
-#else
-	callback=JS_SetBranchCallback(parent_cx,NULL);
-	JS_SetBranchCallback(parent_cx, callback);
-	JS_SetBranchCallback(cx, callback);
-#endif
-#endif
 
 	if((obj=JS_NewCompartmentAndGlobalObject(cx, &eval_class, NULL))==NULL
 		|| !JS_InitStandardClasses(cx,obj)) {
@@ -330,11 +316,11 @@ js_gc(JSContext *cx, uintN argc, jsval *arglist)
 	JSObject *obj=JS_THIS_OBJECT(cx, arglist);
 	jsval *argv=JS_ARGV(cx, arglist);
 	JSBool			forced=JS_TRUE;
-	js_branch_t*	branch;
+	js_callback_t*	cb;
 
 	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
 
-	if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL)
+	if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL)
 		return(JS_FALSE);
 
 	if(argc)
@@ -345,7 +331,7 @@ js_gc(JSContext *cx, uintN argc, jsval *arglist)
 	else
 		JS_MaybeGC(cx);
 
-	branch->gc_attempts++;
+	cb->gc_attempts++;
 
 	return(JS_TRUE);
 }
@@ -372,19 +358,19 @@ js_on_exit(JSContext *cx, uintN argc, jsval *arglist)
 {
 	JSObject *obj=JS_THIS_OBJECT(cx, arglist);
 	jsval *argv=JS_ARGV(cx, arglist);
-	js_branch_t*	branch;
+	js_callback_t*	cb;
 	char		*p;
 
 	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
 
-	if((branch=(js_branch_t*)JS_GetPrivate(cx,obj))==NULL)
+	if((cb=(js_callback_t*)JS_GetPrivate(cx,obj))==NULL)
 		return(JS_FALSE);
 
-	if(branch->exit_func==NULL)
-		branch->exit_func=strListInit();
+	if(cb->exit_func==NULL)
+		cb->exit_func=strListInit();
 
 	JSVALUE_TO_STRING(cx, argv[0], p, NULL);
-	strListPush(&branch->exit_func,p);
+	strListPush(&cb->exit_func,p);
 
 	return(JS_TRUE);
 }
@@ -464,29 +450,29 @@ static JSClass js_internal_class = {
 	,JS_FinalizeStub		/* finalize		*/
 };
 
-void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_branch_t* branch)
+void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb)
 {
 	char*	p;
 	jsval	rval;
 	JSObject* script;
-	BOOL	auto_terminate=branch->auto_terminate;
+	BOOL	auto_terminate=cb->auto_terminate;
 
-	branch->auto_terminate=FALSE;
+	cb->auto_terminate=FALSE;
 
-	while((p=strListPop(&branch->exit_func))!=NULL) {
+	while((p=strListPop(&cb->exit_func))!=NULL) {
 		if((script=JS_CompileScript(cx, obj, p, strlen(p), NULL, 0))!=NULL) {
 			JS_ExecuteScript(cx, obj, script, &rval);
 		}
 		free(p);
 	}
 
-	strListFree(&branch->exit_func);
+	strListFree(&cb->exit_func);
 
 	if(auto_terminate)
-		branch->auto_terminate = TRUE;
+		cb->auto_terminate = TRUE;
 }
 
-JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_branch_t* branch, js_startup_t* startup)
+JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_callback_t* cb, js_startup_t* startup)
 {
 	JSObject*	obj;
 
@@ -494,7 +480,7 @@ JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_
 		,JSPROP_ENUMERATE|JSPROP_READONLY))==NULL)
 		return(NULL);
 
-	if(!JS_SetPrivate(cx, obj, branch))	/* Store a pointer to js_branch_t */
+	if(!JS_SetPrivate(cx, obj, cb))	/* Store a pointer to js_callback_t */
 		return(NULL);
 
 	if(startup!=NULL) {
diff --git a/src/sbbs3/jsexec.c b/src/sbbs3/jsexec.c
index d279feec8ca5ec3f71b3a8958e0b53ac1e33d391..4f03921dc96da55aecc6c36cfb457135fb46827c 100644
--- a/src/sbbs3/jsexec.c
+++ b/src/sbbs3/jsexec.c
@@ -55,11 +55,10 @@
 JSRuntime*	js_runtime;
 JSContext*	js_cx;
 JSObject*	js_glob;
-js_branch_t	branch;
+js_callback_t	cb;
 scfg_t		scfg;
 ulong		js_max_bytes=JAVASCRIPT_MAX_BYTES;
 ulong		js_cx_stack=JAVASCRIPT_CONTEXT_STACK;
-ulong		stack_limit=JAVASCRIPT_THREAD_STACK;
 FILE*		confp;
 FILE*		errfp;
 FILE*		nulfp;
@@ -111,8 +110,7 @@ void usage(FILE* fp)
 #endif
 		"\t-m<bytes>      set maximum heap size (default=%u bytes)\n"
 		"\t-s<bytes>      set context stack size (default=%u bytes)\n"
-		"\t-S<bytes>      set thread stack limit (default=%u, 0=unlimited)\n"
-		"\t-b<limit>      set branch limit (default=%u, 0=unlimited)\n"
+		"\t-t<limit>      set time limit (default=%u, 0=unlimited)\n"
 		"\t-y<interval>   set yield interval (default=%u, 0=never)\n"
 		"\t-g<interval>   set garbage collection interval (default=%u, 0=never)\n"
 		"\t-h[hostname]   use local or specified host name (instead of SCFG value)\n"
@@ -133,8 +131,7 @@ void usage(FILE* fp)
 		"\t-!             wait for keypress (pause) on error\n"
 		,JAVASCRIPT_MAX_BYTES
 		,JAVASCRIPT_CONTEXT_STACK
-		,JAVASCRIPT_THREAD_STACK
-		,JAVASCRIPT_BRANCH_LIMIT
+		,JAVASCRIPT_TIME_LIMIT
 		,JAVASCRIPT_YIELD_INTERVAL
 		,JAVASCRIPT_GC_INTERVAL
 		,DEFAULT_LOG_LEVEL
@@ -660,25 +657,17 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 	JS_RESUMEREQUEST(cx, rc);
 }
 
-static JSBool
-js_BranchCallback(JSContext *cx, JSObject *script)
-{
-    return(js_CommonBranchCallback(cx,&branch));
-}
-
-#if JS_VERSION>180
 static JSBool
 js_OperationCallback(JSContext *cx)
 {
 	JSBool	ret;
 
 	JS_SetOperationCallback(cx, NULL);
-	ret=js_BranchCallback(cx, NULL);
+	ret=js_CommonOperationCallback(cx, NULL);
 	JS_SetOperationCallback(cx, js_OperationCallback);
 	return ret;
 }
 #endif
-
 static BOOL js_CreateEnvObject(JSContext* cx, JSObject* glob, char** env)
 {
 	char		name[256];
@@ -731,16 +720,12 @@ static BOOL js_init(char** environ)
 		return(FALSE);
 	JS_BEGINREQUEST(js_cx);
 
-	if(stack_limit)
-		fprintf(statfp,"JavaScript: Thread stack limit: %lu bytes\n"
-			,stack_limit);
-
 	JS_SetErrorReporter(js_cx, js_ErrorReporter);
 
 	/* Global Object */
 	if((js_glob=js_CreateCommonObjects(js_cx, &scfg, NULL, js_global_functions
 		,time(NULL), host_name, SOCKLIB_DESC	/* system */
-		,&branch,&startup						/* js */
+		,&cb,&startup						/* js */
 		,NULL,INVALID_SOCKET					/* client */
 		,NULL									/* server */
 		))==NULL) {
@@ -776,7 +761,6 @@ static const char* js_ext(const char* fname)
 
 long js_exec(const char *fname, char** args)
 {
-	ulong		stack_frame;
 	int			argc=0;
 	uint		line_no;
 	char		path[MAX_PATH+1];
@@ -820,15 +804,6 @@ long js_exec(const char *fname, char** args)
 	}
 	JS_ClearPendingException(js_cx);
 
-	if(stack_limit) {
-#if JS_STACK_GROWTH_DIRECTION > 0
-		stack_frame=((ulong)&stack_frame)+stack_limit;
-#else
-		stack_frame=((ulong)&stack_frame)-stack_limit;
-#endif
-		JS_SetThreadStackLimit(js_cx, stack_frame);
-	}
-
 	argv=JS_NewArrayObject(js_cx, 0, NULL);
 	JS_DefineProperty(js_cx, js_glob, "argv", OBJECT_TO_JSVAL(argv)
 		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
@@ -863,13 +838,9 @@ long js_exec(const char *fname, char** args)
 		,STRING_TO_JSVAL(JS_NewStringCopyZ(js_cx,rev_detail))
 		,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE);
 
-	branch.terminated=&terminated;
+	cb.terminated=&terminated;
 
-#if JS_VERSION>180
 	JS_SetOperationCallback(js_cx, js_OperationCallback);
-#else
-	JS_SetBranchCallback(js_cx, js_BranchCallback);
-#endif
 
 	if(fp==stdin) 	 /* Using stdin for script source */
 		SAFECOPY(path,"stdin");
@@ -918,7 +889,7 @@ long js_exec(const char *fname, char** args)
 		mfprintf(statfp,"Using JavaScript exit_code: %s",p);
 		JS_ValueToInt32(js_cx,rval,&result);
 	}
-	js_EvalOnExit(js_cx, js_glob, &branch);
+	js_EvalOnExit(js_cx, js_glob, &cb);
 
 	JS_ReportPendingException(js_cx);
 
@@ -945,7 +916,7 @@ void recycle_handler(int type)
 {
 	lprintf(LOG_NOTICE,"\n-> Recycled Locally (signal: %d)",type);
 	recycled=TRUE;
-	branch.terminated=&recycled;
+	cb.terminated=&recycled;
 }
 
 
@@ -1005,10 +976,10 @@ int main(int argc, char **argv, char** environ)
 	else	/* if redirected, don't send status messages to stderr */
 		statfp=nulfp;
 
-	branch.limit=JAVASCRIPT_BRANCH_LIMIT;
-	branch.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
-	branch.gc_interval=JAVASCRIPT_GC_INTERVAL;
-	branch.auto_terminate=TRUE;
+	cb.limit=JAVASCRIPT_TIME_LIMIT;
+	cb.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
+	cb.gc_interval=JAVASCRIPT_GC_INTERVAL;
+	cb.auto_terminate=TRUE;
 
 	sscanf("$Revision$", "%*s %s", revision);
 	DESCRIBE_COMPILER(compiler);
@@ -1040,21 +1011,17 @@ int main(int argc, char **argv, char** environ)
 					if(*p==0) p=argv[++argn];
 					js_cx_stack=strtoul(p,NULL,0);
 					break;
-				case 'S':
-					if(*p==0) p=argv[++argn];
-					stack_limit=strtoul(p,NULL,0);
-					break;
-				case 'b':
+				case 't':
 					if(*p==0) p=argv[++argn];
-					branch.limit=strtoul(p,NULL,0);
+					cb.limit=strtoul(p,NULL,0);
 					break;
 				case 'y':
 					if(*p==0) p=argv[++argn];
-					branch.yield_interval=strtoul(p,NULL,0);
+					cb.yield_interval=strtoul(p,NULL,0);
 					break;
 				case 'g':
 					if(*p==0) p=argv[++argn];
-					branch.gc_interval=strtoul(p,NULL,0);
+					cb.gc_interval=strtoul(p,NULL,0);
 					break;
 				case 'h':
 					if(*p==0)
@@ -1095,7 +1062,7 @@ int main(int argc, char **argv, char** environ)
 					statfp=nulfp;
 					break;
 				case 'x':
-					branch.auto_terminate=FALSE;
+					cb.auto_terminate=FALSE;
 					break;
 				case 'l':
 					loop=TRUE;
diff --git a/src/sbbs3/mailsrvr.c b/src/sbbs3/mailsrvr.c
index 24750e735f9466c25cefd2ca2769971209d688b3..7fd591df5f969b5f2d387d8495eb927b3ae94722 100644
--- a/src/sbbs3/mailsrvr.c
+++ b/src/sbbs3/mailsrvr.c
@@ -1753,12 +1753,12 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 	JSObject*	argv;
 	jsuint		argc;
 	JSObject*	js_script;
-	js_branch_t	js_branch;
+	js_callback_t	js_callback;
 	jsval		val;
 	jsval		rval=JSVAL_VOID;
 	private_t	priv;
 
-	ZERO_VAR(js_branch);
+	ZERO_VAR(js_callback);
 
 	SAFECOPY(fname,cmdline);
 	truncstr(fname," \t");
@@ -1802,7 +1802,7 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 			/* Global Objects (including system, js, client, Socket, MsgBase, File, User, etc. */
 			if((*js_glob=js_CreateCommonObjects(*js_cx, &scfg, &scfg, NULL
 						,uptime, startup->host_name, SOCKLIB_DESC	/* system */
-						,&js_branch									/* js */
+						,&js_callback									/* js */
 						,&startup->js
 						,client, sock								/* client */
 						,&js_server_props							/* server */
@@ -1895,6 +1895,7 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 		if(js_script==NULL)
 			break;
 
+		/* ToDo: Set operational callback */
 		success=JS_ExecuteScript(*js_cx, js_scope, js_script, &rval);
 
 		JS_GetProperty(*js_cx, *js_glob, "exit_code", &rval);
@@ -1902,7 +1903,7 @@ js_mailproc(SOCKET sock, client_t* client, user_t* user, struct mailproc* mailpr
 		if(rval!=JSVAL_VOID && JSVAL_IS_NUMBER(rval))
 			JS_ValueToInt32(*js_cx,rval,result);
 
-		js_EvalOnExit(*js_cx, js_scope, &js_branch);
+		js_EvalOnExit(*js_cx, js_scope, &js_callback);
 
 		JS_ReportPendingException(*js_cx);
 
diff --git a/src/sbbs3/main.cpp b/src/sbbs3/main.cpp
index 716351ba5173e4fc8dd0bd7c267be0936c0f2a43..87578ee2ce9c423de223099004d43dd391fd63f2 100644
--- a/src/sbbs3/main.cpp
+++ b/src/sbbs3/main.cpp
@@ -1152,22 +1152,6 @@ bool sbbs_t::js_init(ulong* stack_frame)
 		if(js_CreateConsoleObject(js_cx, js_glob)==NULL)
 			break;
 
-		if(startup->js.thread_stack) {
-			ulong stack_limit;
-
-#if JS_STACK_GROWTH_DIRECTION > 0
-			stack_limit=((ulong)stack_frame)+startup->js.thread_stack;
-#else
-			stack_limit=((ulong)stack_frame)-startup->js.thread_stack;
-#endif
-			JS_SetThreadStackLimit(js_cx, stack_limit);
-
-			lprintf(LOG_DEBUG,"%s JavaScript: Thread stack limit: %lu bytes"
-				,node, startup->js.thread_stack);
-		}
-		else
-			JS_SetThreadStackLimit(js_cx, 0);
-
 		success=true;
 
 	} while(0);
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index eff88d5eafdadb32d783a6193d165b9dd604c98e..05092972b2561dd8b5c57c72081962d5ac912bb1 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -256,14 +256,14 @@ public:
 
 #ifdef JAVASCRIPT
 
-	JSRuntime*	js_runtime;
-	JSContext*	js_cx;
-	JSObject*	js_glob;
-	js_branch_t	js_branch;
-	long		js_execfile(const char *fname, const char* startup_dir, JSObject* scope=NULL);
-	bool		js_init(ulong* stack_frame);
-	void		js_cleanup(const char* node);
-	void		js_create_user_objects(void);
+	JSRuntime*		js_runtime;
+	JSContext*		js_cx;
+	JSObject*		js_glob;
+	js_callback_t	js_callback;
+	long			js_execfile(const char *fname, const char* startup_dir, JSObject* scope=NULL);
+	bool			js_init(ulong* stack_frame);
+	void			js_cleanup(const char* node);
+	void			js_create_user_objects(void);
 
 #endif
 
@@ -1053,7 +1053,7 @@ extern "C" {
 													,time_t uptime				/* system */
 													,char* host_name			/* system */
 													,char* socklib_desc			/* system */
-													,js_branch_t*				/* js */
+													,js_callback_t*				/* js */
 													,js_startup_t*				/* js */
 													,client_t* client			/* client */
 													,SOCKET client_socket		/* client */
@@ -1061,9 +1061,9 @@ extern "C" {
 													);
 
 	/* js_internal.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 JSObject* DLLCALL js_CreateInternalJsObject(JSContext*, JSObject* parent, js_callback_t*, js_startup_t*);
+	DLLEXPORT JSBool	DLLCALL js_CommonOperationCallback(JSContext*, js_callback_t*);
+	DLLEXPORT void		DLLCALL js_EvalOnExit(JSContext*, JSObject*, js_callback_t*);
 	DLLEXPORT void		DLLCALL	js_PrepareToExecute(JSContext*, JSObject*, const char *filename, const char* startup_dir);
 	DLLEXPORT char*		DLLCALL js_getstring(JSContext *cx, JSString *str);
 
diff --git a/src/sbbs3/sbbs_ini.c b/src/sbbs3/sbbs_ini.c
index bd235cfeb9555f361d8cae9793eba2998ce574b6..0e63e4cb7675590167cae66f2ba7124c8b0d1277 100644
--- a/src/sbbs3/sbbs_ini.c
+++ b/src/sbbs3/sbbs_ini.c
@@ -65,8 +65,7 @@ static const char*	strLoginAttemptHackThreshold="LoginAttemptHackThreshold";
 static const char*	strLoginAttemptFilterThreshold="LoginAttemptFilterThreshold";
 static const char*	strJavaScriptMaxBytes		="JavaScriptMaxBytes";
 static const char*	strJavaScriptContextStack	="JavaScriptContextStack";
-static const char*	strJavaScriptThreadStack	="JavaScriptThreadStack";
-static const char*	strJavaScriptBranchLimit	="JavaScriptBranchLimit";
+static const char*	strJavaScriptTimeLimit		="JavaScriptTimeLimit";
 static const char*	strJavaScriptGcInterval		="JavaScriptGcInterval";
 static const char*	strJavaScriptYieldInterval	="JavaScriptYieldInterval";
 static const char*	strJavaScriptLoadPath		="JavaScriptLoadPath";
@@ -122,8 +121,7 @@ void sbbs_get_js_settings(
 
 	js->max_bytes		= (ulong)iniGetBytes(list,section,strJavaScriptMaxBytes		,/* unit: */1,defaults->max_bytes);
 	js->cx_stack		= (ulong)iniGetBytes(list,section,strJavaScriptContextStack	,/* unit: */1,defaults->cx_stack);
-	js->thread_stack	= (ulong)iniGetBytes(list,section,strJavaScriptThreadStack	,/* unit: */1,defaults->thread_stack);
-	js->branch_limit	= iniGetInteger(list,section,strJavaScriptBranchLimit	,defaults->branch_limit);
+	js->time_limit		= iniGetInteger(list,section,strJavaScriptTimeLimit		,defaults->time_limit);
 	js->gc_interval		= iniGetInteger(list,section,strJavaScriptGcInterval	,defaults->gc_interval);
 	js->yield_interval	= iniGetInteger(list,section,strJavaScriptYieldInterval	,defaults->yield_interval);
 
@@ -148,8 +146,7 @@ BOOL sbbs_set_js_settings(
 	js_startup_t global_defaults = {
 			 JAVASCRIPT_MAX_BYTES
 			,JAVASCRIPT_CONTEXT_STACK
-			,JAVASCRIPT_THREAD_STACK
-			,JAVASCRIPT_BRANCH_LIMIT
+			,JAVASCRIPT_TIME_LIMIT
 			,JAVASCRIPT_GC_INTERVAL
 			,JAVASCRIPT_YIELD_INTERVAL
             ,JAVASCRIPT_LOAD_PATH
@@ -171,15 +168,10 @@ BOOL sbbs_set_js_settings(
 	else 
 		failure|=iniSetBytes(lp,section,strJavaScriptContextStack,/*unit: */1,js->cx_stack,style)==NULL;
 
-	if(js->thread_stack==defaults->thread_stack)
-		iniRemoveValue(lp,section,strJavaScriptThreadStack);
-	else 
-		failure|=iniSetBytes(lp,section,strJavaScriptThreadStack,/*unit: */1,js->thread_stack,style)==NULL;
-
-	if(js->branch_limit==defaults->branch_limit)
-		iniRemoveValue(lp,section,strJavaScriptBranchLimit);
+	if(js->time_limit==defaults->time_limit)
+		iniRemoveValue(lp,section,strJavaScriptTimeLimit);
 	else
-		failure|=iniSetInteger(lp,section,strJavaScriptBranchLimit,js->branch_limit,style)==NULL;
+		failure|=iniSetInteger(lp,section,strJavaScriptTimeLimit,js->time_limit,style)==NULL;
 
 	if(js->gc_interval==defaults->gc_interval)
 		iniRemoveValue(lp,section,strJavaScriptGcInterval);
@@ -238,8 +230,7 @@ static void get_ini_globals(str_list_t list, global_startup_t* global)
 	/* Setup default values here */
 	global->js.max_bytes		= JAVASCRIPT_MAX_BYTES;
 	global->js.cx_stack			= JAVASCRIPT_CONTEXT_STACK;
-	global->js.thread_stack		= JAVASCRIPT_THREAD_STACK;
-	global->js.branch_limit		= JAVASCRIPT_BRANCH_LIMIT;
+	global->js.time_limit		= JAVASCRIPT_TIME_LIMIT;
 	global->js.gc_interval		= JAVASCRIPT_GC_INTERVAL;
 	global->js.yield_interval	= JAVASCRIPT_YIELD_INTERVAL;
     SAFECOPY(global->js.load_path, JAVASCRIPT_LOAD_PATH);
diff --git a/src/sbbs3/sbbsdefs.h b/src/sbbs3/sbbsdefs.h
index 20b53ae83c92b1345c81e380331f98559b3b0d3a..4c63ead0c57210eff2187a43e1bada16076d200a 100644
--- a/src/sbbs3/sbbsdefs.h
+++ b/src/sbbs3/sbbsdefs.h
@@ -72,8 +72,7 @@
 
 #define	JAVASCRIPT_MAX_BYTES		(8*1024*1024)
 #define JAVASCRIPT_CONTEXT_STACK	(16*1024)
-#define JAVASCRIPT_THREAD_STACK		(256*1024)
-#define JAVASCRIPT_BRANCH_LIMIT		99999999
+#define JAVASCRIPT_TIME_LIMIT		(24*60*600)			/* in 100ms ticks */
 #define JAVASCRIPT_YIELD_INTERVAL	10000
 #define JAVASCRIPT_GC_INTERVAL		100 
 #define JAVASCRIPT_LOAD_PATH		"load"
@@ -88,7 +87,7 @@ typedef struct {
 	BOOL	auto_terminate;
 	volatile BOOL*	terminated;
 	str_list_t	exit_func;
-} js_branch_t;
+} js_callback_t;
 
 #define JSVAL_NULL_OR_VOID(val)		(JSVAL_IS_NULL(val) || JSVAL_IS_VOID(val))
 
diff --git a/src/sbbs3/services.c b/src/sbbs3/services.c
index 6ccddc629432532aa7c24baf05c2be79c17aceca..7773867e0691f6fb1408f50ee18eefb4ab86a020 100644
--- a/src/sbbs3/services.c
+++ b/src/sbbs3/services.c
@@ -104,7 +104,7 @@ typedef struct {
 	user_t			user;
 	client_t*		client;
 	service_t*		service;
-	js_branch_t		branch;
+	js_callback_t	callback;
 	/* Initial UDP datagram */
 	BYTE*			udp_buf;
 	int				udp_len;
@@ -832,7 +832,6 @@ js_client_remove(JSContext *cx, uintN argc, jsval *arglist)
 static JSContext* 
 js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client, JSObject** glob)
 {
-	ulong		stack_frame;
 	JSContext*	js_cx;
 	JSObject*	js_glob;
 	JSObject*	server;
@@ -857,7 +856,7 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 			break;
 
 		/* Internal JS Object */
-		if(js_CreateInternalJsObject(js_cx, js_glob, &service_client->branch, &service_client->service->js)==NULL)
+		if(js_CreateInternalJsObject(js_cx, js_glob, &service_client->callback, &service_client->service->js)==NULL)
 			break;
 
 		/* Client Object */
@@ -953,15 +952,6 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 		if(glob!=NULL)
 			*glob=js_glob;
 
-		if(service_client->service->js.thread_stack) {
-#if JS_STACK_GROWTH_DIRECTION > 0
-			stack_frame=((ulong)&stack_frame)+service_client->service->js.thread_stack;
-#else
-			stack_frame=((ulong)&stack_frame)-service_client->service->js.thread_stack;
-#endif
-			JS_SetThreadStackLimit(js_cx, stack_frame);
-		}
-
 		success=TRUE;
 
 	} while(0);
@@ -977,35 +967,27 @@ js_initcx(JSRuntime* js_runtime, SOCKET sock, service_client_t* service_client,
 }
 
 static JSBool
-js_BranchCallback(JSContext *cx, JSObject *script)
+js_OperationCallback(JSContext *cx)
 {
+	JSBool	ret;
 	service_client_t* client;
 
 	if((client=(service_client_t*)JS_GetContextPrivate(cx))==NULL)
 		return(JS_FALSE);
 
 	/* Terminated? */ 
-	if(client->branch.auto_terminate && terminated) {
+	if(client->callback.auto_terminate && terminated) {
 		JS_ReportWarning(cx,"Terminated");
-		client->branch.counter=0;
+		client->callback.counter=0;
 		return(JS_FALSE);
 	}
 
-	return js_CommonBranchCallback(cx,&client->branch);
-}
-
-#if JS_VERSION>180
-static JSBool
-js_OperationCallback(JSContext *cx)
-{
-	JSBool	ret;
-
 	JS_SetOperationCallback(cx, NULL);
-	ret=js_BranchCallback(cx, NULL);
+	ret=js_CommonOperationCallback(cx,&client->callback);
 	JS_SetOperationCallback(cx, js_OperationCallback);
+
 	return ret;
 }
-#endif
 
 static void js_init_args(JSContext* js_cx, JSObject* js_obj, const char* cmdline)
 {
@@ -1198,13 +1180,9 @@ static void js_service_thread(void* arg)
 		lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile script (%s)",socket,spath);
 	else  {
 		js_PrepareToExecute(js_cx, js_glob, spath, /* startup_dir */NULL);
-#if JS_VERSION>180
 		JS_SetOperationCallback(js_cx, js_OperationCallback);
-#else
-		JS_SetBranchCallback(js_cx, js_BranchCallback);
-#endif
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
-		js_EvalOnExit(js_cx, js_glob, &service_client.branch);
+		js_EvalOnExit(js_cx, js_glob, &service_client.callback);
 	}
 	JS_ENDREQUEST(js_cx);
 	JS_DestroyContext(js_cx);	/* Free Context */
@@ -1267,11 +1245,11 @@ static void js_static_service_thread(void* arg)
 	memset(&service_client,0,sizeof(service_client));
 	service_client.socket = service->socket;
 	service_client.service = service;
-	service_client.branch.limit = service->js.branch_limit;
-	service_client.branch.gc_interval = service->js.gc_interval;
-	service_client.branch.yield_interval = service->js.yield_interval;
-	service_client.branch.terminated = &service->terminated;
-	service_client.branch.auto_terminate = TRUE;
+	service_client.callback.limit = service->js.time_limit;
+	service_client.callback.gc_interval = service->js.gc_interval;
+	service_client.callback.yield_interval = service->js.yield_interval;
+	service_client.callback.terminated = &service->terminated;
+	service_client.callback.auto_terminate = TRUE;
 
 	if((js_runtime=jsrt_GetNew(service->js.max_bytes, 5000, __FILE__, __LINE__))==NULL) {
 		lprintf(LOG_ERR,"%04d !%s ERROR initializing JavaScript runtime"
@@ -1300,11 +1278,7 @@ static void js_static_service_thread(void* arg)
 		val = BOOLEAN_TO_JSVAL(JS_FALSE);
 		JS_SetProperty(js_cx, js_glob, "logged_in", &val);
 
-#if JS_VERSION>180
 		JS_SetOperationCallback(js_cx, js_OperationCallback);
-#else
-		JS_SetBranchCallback(js_cx, js_BranchCallback);
-#endif
 	
 		if((js_script=JS_CompileFile(js_cx, js_glob, spath))==NULL)  {
 			lprintf(LOG_ERR,"%04d !JavaScript FAILED to compile script (%s)",service->socket,spath);
@@ -1313,7 +1287,7 @@ static void js_static_service_thread(void* arg)
 
 		js_PrepareToExecute(js_cx, js_glob, spath, /* startup_dir */NULL);
 		JS_ExecuteScript(js_cx, js_glob, js_script, &rval);
-		js_EvalOnExit(js_cx, js_glob, &service_client.branch);
+		js_EvalOnExit(js_cx, js_glob, &service_client.callback);
 
 		JS_ENDREQUEST(js_cx);
 		JS_DestroyContext(js_cx);	/* Free Context */
@@ -2197,11 +2171,11 @@ void DLLCALL services_thread(void* arg)
 				client->service->clients++;		/* this should be mutually exclusive */
 				client->udp_buf=udp_buf;
 				client->udp_len=udp_len;
-				client->branch.limit			= service[i].js.branch_limit;
-				client->branch.gc_interval		= service[i].js.gc_interval;
-				client->branch.yield_interval	= service[i].js.yield_interval;
-				client->branch.terminated		= &client->service->terminated;
-				client->branch.auto_terminate	= TRUE;
+				client->callback.limit			= service[i].js.time_limit;
+				client->callback.gc_interval	= service[i].js.gc_interval;
+				client->callback.yield_interval	= service[i].js.yield_interval;
+				client->callback.terminated		= &client->service->terminated;
+				client->callback.auto_terminate	= TRUE;
 
 				udp_buf = NULL;
 
diff --git a/src/sbbs3/startup.h b/src/sbbs3/startup.h
index 288168285e189576ead2465bb3afc04d6b3d62bb..63ff8bb31d124b630cb4e687a48aae60fb69a362 100644
--- a/src/sbbs3/startup.h
+++ b/src/sbbs3/startup.h
@@ -52,10 +52,9 @@
 typedef struct {
 	ulong	max_bytes;		/* max allocated bytes before garbage collection */
 	ulong	cx_stack;		/* bytes for script execution stack */
-	ulong	thread_stack;	/* limit of stack size for native execution thread */
-	ulong	branch_limit;	/* maximum number of branches (for infinite loop detection) */
-	ulong	gc_interval;	/* number of branches between garbage collection attempts */
-	ulong	yield_interval;	/* number of branches between time-slice yields */
+	ulong	time_limit;		/* maximum number of ticks (for infinite loop detection) */
+	ulong	gc_interval;	/* number of ticks between garbage collection attempts */
+	ulong	yield_interval;	/* number of ticks between time-slice yields */
 	char	load_path[INI_MAX_VALUE_LEN];	/* additional (comma-separated) directories to search for load()ed scripts */
 } js_startup_t;
 
diff --git a/src/sbbs3/websrvr.c b/src/sbbs3/websrvr.c
index 686af303f20fd9d922e14da5563410c08f0d285f..a47c1981d9ea12d01273a32369ea799dee367c39 100644
--- a/src/sbbs3/websrvr.c
+++ b/src/sbbs3/websrvr.c
@@ -253,7 +253,7 @@ typedef struct  {
 	JSObject*		js_header;
 	JSObject*		js_cookie;
 	JSObject*		js_request;
-	js_branch_t		js_branch;
+	js_callback_t	js_callback;
 	subscan_t		*subscan;
 
 	/* Ring Buffer Stuff */
@@ -4424,28 +4424,20 @@ static JSFunctionSpec js_global_functions[] = {
 };
 
 static JSBool
-js_BranchCallback(JSContext *cx, JSObject *script)
+js_OperationCallback(JSContext *cx)
 {
+	JSBool	ret;
 	http_session_t* session;
 
 	if((session=(http_session_t*)JS_GetContextPrivate(cx))==NULL)
 		return(JS_FALSE);
 
-    return(js_CommonBranchCallback(cx,&session->js_branch));
-}
-
-#if JS_VERSION>180
-static JSBool
-js_OperationCallback(JSContext *cx)
-{
-	JSBool	ret;
-
 	JS_SetOperationCallback(cx, NULL);
-	ret=js_BranchCallback(cx, NULL);
+    ret=js_CommonOperationCallback(cx,&session->js_callback);
 	JS_SetOperationCallback(cx, js_OperationCallback);
+
 	return ret;
 }
-#endif
 
 static JSContext* 
 js_initcx(http_session_t *session)
@@ -4463,11 +4455,7 @@ js_initcx(http_session_t *session)
 
     JS_SetErrorReporter(js_cx, js_ErrorReporter);
 
-#if JS_VERSION>180
 	JS_SetOperationCallback(js_cx, js_OperationCallback);
-#else
-	JS_SetBranchCallback(js_cx, js_BranchCallback);
-#endif
 
 	lprintf(LOG_DEBUG,"%04d JavaScript: Creating Global Objects and Classes",session->socket);
 	if((session->js_glob=js_CreateCommonObjects(js_cx, &scfg, NULL
@@ -4475,7 +4463,7 @@ js_initcx(http_session_t *session)
 									,uptime						/* system */
 									,startup->host_name			/* system */
 									,SOCKLIB_DESC				/* system */
-									,&session->js_branch		/* js */
+									,&session->js_callback		/* js */
 									,&startup->js				/* js */
 									,&session->client			/* client */
 									,session->socket			/* client */
@@ -4632,7 +4620,7 @@ static BOOL exec_ssjs(http_session_t* session, char* script)  {
 		/* RUN SCRIPT */
 		JS_ClearPendingException(session->js_cx);
 
-		session->js_branch.counter=0;
+		session->js_callback.counter=0;
 
 		lprintf(LOG_DEBUG,"%04d JavaScript: Compiling script: %s",session->socket,script);
 		if((js_script=JS_CompileFile(session->js_cx, session->js_glob
@@ -4647,7 +4635,7 @@ static BOOL exec_ssjs(http_session_t* session, char* script)  {
 		start=xp_timer();
 		js_PrepareToExecute(session->js_cx, session->js_glob, script, /* startup_dir */NULL);
 		JS_ExecuteScript(session->js_cx, session->js_glob, js_script, &rval);
-		js_EvalOnExit(session->js_cx, session->js_glob, &session->js_branch);
+		js_EvalOnExit(session->js_cx, session->js_glob, &session->js_callback);
 		lprintf(LOG_DEBUG,"%04d JavaScript: Done executing script: %s (%.2Lf seconds)"
 			,session->socket,script,xp_timer()-start);
 	} while(0);
@@ -5769,11 +5757,11 @@ void DLLCALL web_server(void* arg)
 			SAFECOPY(session->host_ip,host_ip);
 			session->addr=client_addr;
    			session->socket=client_socket;
-			session->js_branch.auto_terminate=TRUE;
-			session->js_branch.terminated=&terminate_server;
-			session->js_branch.limit=startup->js.branch_limit;
-			session->js_branch.gc_interval=startup->js.gc_interval;
-			session->js_branch.yield_interval=startup->js.yield_interval;
+			session->js_callback.auto_terminate=TRUE;
+			session->js_callback.terminated=&terminate_server;
+			session->js_callback.limit=startup->js.time_limit;
+			session->js_callback.gc_interval=startup->js.gc_interval;
+			session->js_callback.yield_interval=startup->js.yield_interval;
 #ifdef ONE_JS_RUNTIME
 			session->js_runtime=js_runtime;
 #endif