diff --git a/exec/tests/global/except.js b/exec/tests/global/except.js
index ed5ef1bcc8545029b9efd6963ce273d55f5f8e7f..68a45188f583e1efced8c8eef9d51994292ecc40 100644
--- a/exec/tests/global/except.js
+++ b/exec/tests/global/except.js
@@ -3,9 +3,9 @@
 // Value (e.g. 0, 1) is number of non-null/undefined args required
 var func_list = {
 	'ascii': 1,
-	'ascii_str': 1,
+	'ascii_str': 0,
 	'alert': 0,
-	'backslash': 1,
+	'backslash': 0,
 	'base64_encode': 1,
 	'base64_decode': 1,
 	'beep': 1,
@@ -28,8 +28,8 @@ var func_list = {
 	'file_exists': 0,
 	'file_getcase': 1,
 	'file_getdosname': 1,
-	'file_getext': 1,
-	'file_getname': 1,
+	'file_getext': 0,
+	'file_getname': 0,
 	'file_isdir': 0,
 	'file_mode': 1,
 	'file_mutex': 1,
@@ -43,7 +43,7 @@ var func_list = {
 	'fullpath': 1,
 	'html_encode': 1,
 	'html_decode': 1,
-	'lfexpand': 1,
+	'lfexpand': 0,
 	'load': 1,
 	'log': 0,
 	'md5_calc': 1,
@@ -59,8 +59,8 @@ var func_list = {
 	'resolve_ip': 1,
 	'rmdir': 1,
 	'rmfiles': 1,
-	'rot13_translate': 1,
-	'skipsp': 1,
+	'rot13_translate': 0,
+	'skipsp': 0,
 	'sha1_calc': 1,
 	'socket_strerror': 1,
 	'str_has_ctrl': 0,
@@ -69,17 +69,17 @@ var func_list = {
 	'str_is_utf8': 0,
 	'strerror': 1,
 	'strftime': 1,
-	'strip_ansi': 1,
-	'strip_ctrl': 1,
-	'strip_ctrl_a': 1,
-	'strip_exascii': 1,
-	'truncsp': 1,
+	'strip_ansi': 0,
+	'strip_ctrl': 0,
+	'strip_ctrl_a': 0,
+	'strip_exascii': 0,
+	'truncsp': 0,
 	'truncstr': 2,
-	'utf8_decode': 1,
-	'utf8_encode': 1,
+	'utf8_decode': 0,
+	'utf8_encode': 0,
 	'utf8_get_width': 1,
 	'wildmatch': 0,
-	'word_wrap': 1,
+	'word_wrap': 0,
 	'yield': 1,
 };
 
diff --git a/exec/tests/global/rtypes.js b/exec/tests/global/rtypes.js
index ddd4f0528db2b065e977034dd09056a49190c294..694d7ffc8c6284d2c4ef2f036fd896f2acf1c3c1 100644
--- a/exec/tests/global/rtypes.js
+++ b/exec/tests/global/rtypes.js
@@ -1,4 +1,5 @@
 // Test global function return types
+// @format.tab-size 4, @format.use-tabs true
 
 var type = {
 	'alert(0)'				: 'undefined',
@@ -6,7 +7,11 @@ var type = {
 	'ascii("A")'		    : 'number',
 	'ascii_str("A")'	    : 'string',
 	'ascii_str(1)'		    : 'string',
+	'ascii_str(null)'		: 'object', // null
+	'ascii_str(undefined)'	: 'undefined',
 	'backslash("")'		    : 'string',
+	'backslash(null)'		: 'object', // null
+	'backslaash(undefined)'	: 'undefined',
 	'base64_encode("")'		: 'object', // null
 	'base64_encode("1")'	: 'string',
 	'base64_decode("")'		: 'object', // null
@@ -35,6 +40,8 @@ var type = {
 	'flags_str(0)'			: 'string',
 	'fullpath("")'			: 'string',
 	'lfexpand("")'			: 'string',
+	'lfexpand(null)'		: 'object', // null
+	'lfexpand(undefined)'	: 'undefined',
 	'log("")'				: 'string',
 	'md5_calc("")'			: 'string',
 	'mswait()'				: 'number',
@@ -53,6 +60,8 @@ var type = {
 	'str_is_utf16("")'		: 'boolean',
 	'str_is_utf8("")'		: 'boolean',
 	'strftime("")'			: 'string',
+	'strip_ctrl(null)'		: 'null',
+	'strip_ctrl(undefined)'	: 'undefined',
 	'strip_ctrl("")'		: 'string',
 	'strip_ctrl_a("")'		: 'string',
 	'strip_ansi("")'		: 'string',
diff --git a/src/sbbs3/js_global.c b/src/sbbs3/js_global.c
index 111e9dac120bb91dbdd9d367778a2dbaf75affa4..c9f5469d943a26d6791952c0f2eed1bca9401599 100644
--- a/src/sbbs3/js_global.c
+++ b/src/sbbs3/js_global.c
@@ -1081,9 +1081,10 @@ js_ascii_str(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
 	HANDLE_PENDING(cx, buf);
 	if (buf == NULL)
@@ -1113,9 +1114,10 @@ js_strip_ctrl(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL);
 	HANDLE_PENDING(cx, buf);
 	if (buf == NULL)
@@ -1144,9 +1146,10 @@ js_strip_ctrl_a(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL);
 	HANDLE_PENDING(cx, buf);
 	if (buf == NULL)
@@ -1175,9 +1178,10 @@ js_strip_ansi(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
 	HANDLE_PENDING(cx, buf);
 	if (buf == NULL)
@@ -1206,9 +1210,10 @@ js_strip_exascii(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
 	HANDLE_PENDING(cx, buf);
 	if (buf == NULL)
@@ -1239,9 +1244,10 @@ js_lfexpand(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
 	HANDLE_PENDING(cx, inbuf);
 	if (inbuf == NULL)
@@ -1287,9 +1293,10 @@ js_word_wrap(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
 	HANDLE_PENDING(cx, inbuf);
 	if (inbuf == NULL)
@@ -2767,9 +2774,10 @@ js_internal_charfunc(JSContext *cx, uintN argc, jsval *arglist, char *(*func)(ch
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JS_SET_RVAL(cx, arglist, JSVAL_VOID);
 	JSVALUE_TO_MSTRING(cx, argv[0], str, &strlen);
 	HANDLE_PENDING(cx, str);
@@ -2854,9 +2862,12 @@ js_truncstr(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 2))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0) || js_argvIsNullOrVoid(cx, argv, 1))
+	if (js_argvIsNullOrVoid(cx, argv, 1))
 		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
 	HANDLE_PENDING(cx, str);
 	if (str == NULL)
@@ -4585,9 +4596,10 @@ js_utf8_encode(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	if (JSVAL_IS_STRING(argv[0])) {
 		if (str_is_utf16(cx, argv[0])) {
 			js_str = JS_ValueToString(cx, argv[0]);
@@ -4685,9 +4697,10 @@ js_utf8_decode(JSContext *cx, uintN argc, jsval *arglist)
 
 	if (js_argcIsInsufficient(cx, argc, 1))
 		return JS_FALSE;
-	if (js_argvIsNullOrVoid(cx, argv, 0))
-		return JS_FALSE;
-
+	if (JSVAL_NULL_OR_VOID(argv[0])) {
+		JS_SET_RVAL(cx, arglist, argv[0]);
+		return JS_TRUE;
+	}
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL);
 	HANDLE_PENDING(cx, buf);
 	if (buf == NULL)
@@ -4932,31 +4945,31 @@ static jsSyncMethodSpec js_global_functions[] = {
 	 , JSDOCSTR("Convert single character to numeric ASCII value or vice-versa (returns number OR string)")
 	 , 310},
 	{"ascii_str",       js_ascii_str,       1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Convert extended-ASCII (CP437) characters in text string to plain US-ASCII equivalent, returns modified string")
+	 , JSDOCSTR("Convert extended-ASCII (CP437) characters in text string to plain US-ASCII equivalent, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 310},
 	{"strip_ctrl",      js_strip_ctrl,      1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Strip all control characters and Ctrl-A (attribute) sequences from string, returns modified string")
+	 , JSDOCSTR("Strip all control characters and Ctrl-A (attribute) sequences from string, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 310},
 	{"strip_ctrl_a",    js_strip_ctrl_a,    1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Strip all Ctrl-A (attribute) sequences from string, returns modified string")
+	 , JSDOCSTR("Strip all Ctrl-A (attribute) sequences from string, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 320},
 	{"strip_ansi",      js_strip_ansi,      1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Strip all ANSI terminal control sequences from string, returns modified string")
+	 , JSDOCSTR("Strip all ANSI terminal control sequences from string, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 31802},
 	{"strip_exascii",   js_strip_exascii,   1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Strip all extended-ASCII characters from string, returns modified string")
+	 , JSDOCSTR("Strip all extended-ASCII characters from string, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 310},
 	{"skipsp",          js_skipsp,          1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Skip (trim) white-space characters off <b>beginning</b> of string, returns modified string")
+	 , JSDOCSTR("Skip (trim) white-space characters off <b>beginning</b> of string, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 315},
 	{"truncsp",         js_truncsp,         1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Truncate (trim) white-space characters off <b>end</b> of string, returns modified string")
+	 , JSDOCSTR("Truncate (trim) white-space characters off <b>end</b> of string, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 310},
 	{"truncstr",        js_truncstr,        2,  JSTYPE_STRING,  JSDOCSTR("text, charset")
-	 , JSDOCSTR("Truncate (trim) string at first char in <i>charset</i>, returns modified string")
+	 , JSDOCSTR("Truncate (trim) string at first char in <i>charset</i>, returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 310},
 	{"lfexpand",        js_lfexpand,        1,  JSTYPE_STRING,  JSDOCSTR("text")
-	 , JSDOCSTR("Expand sole line-feeds (LF) to carriage-return/line-feed sequences (CRLF), returns modified string")
+	 , JSDOCSTR("Expand sole line-feeds (LF) to carriage-return/line-feed sequences (CRLF), returns modified string or <tt>null</tt> or <tt>undefined</tt> if passed those values")
 	 , 310},
 	{"wildmatch",       js_wildmatch,       2,  JSTYPE_BOOLEAN, JSDOCSTR("[<i>bool</i> case_sensitive=false,] filename [,pattern='*'] [,path=false]")
 	 , JSDOCSTR("Return <tt>true</tt> if the <i>filename</i> matches the wildcard <i>pattern</i> (wildcard characters supported are '*' and '?'), "