diff --git a/src/sbbs3/js_global.cpp b/src/sbbs3/js_global.cpp
index 0ffbd30b3fbf7510d37b15358eb2dbad80330d2a..ef287cba5c04ea27c31c37f53c97173db9ba7348 100644
--- a/src/sbbs3/js_global.cpp
+++ b/src/sbbs3/js_global.cpp
@@ -41,12 +41,12 @@
 #include "ini_file.h"
 #include "js_rtpool.h"
 #include "js_request.h"
+#include "js_private.h"
 #include "wordwrap.h"
 #include "utf8.h"
 
 /* SpiderMonkey: */
 #include <jsapi.h>
-#include <jsdbgapi.h>
 
 #define MAX_ANSI_SEQ	16
 #define MAX_ANSI_PARAMS	8
@@ -63,41 +63,41 @@ enum {
 	,GLOB_PROP_SOCKET_ERRNO_STR
 };
 
-BOOL DLLCALL js_argc(JSContext *cx, unsigned argc, unsigned min)
+bool DLLCALL js_argc(JSContext *cx, unsigned argc, unsigned min)
 {
 	if(argc < min) {
-		JS_ReportError(cx, "Insufficient Arguments");
-		return FALSE;
+		JS_ReportErrorASCII(cx, "Insufficient Arguments");
+		return false;
 	}
-	return TRUE;
+	return true;
 }
 
 static bool js_system_get(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp)
 {
-	JS::Value idval;
-	char		err[256];
-    int       tiny;
-	JSString*	js_str;
+	JS::RootedValue  idval(cx);
+	char             err[256];
+	int32_t          tiny;
+	JS::RootedString js_str(cx);
 
-    JS_IdToValue(cx, id, &idval);
-    tiny = JSVAL_TO_INT(idval);
+	JS_IdToValue(cx, id, &idval);
+	tiny = idval.toInt32();
 
 	switch(tiny) {
 		case GLOB_PROP_SOCKET_ERRNO:
-			vp.set(DOUBLE_TO_JSVAL(ERROR_VALUE));
+			vp.setNumber((double)ERROR_VALUE);
 			break;
 		case GLOB_PROP_SOCKET_ERRNO_STR:
 			if((js_str=JS_NewStringCopyZ(cx, socket_strerror(socket_errno, err, sizeof(err))))==NULL)
 				return(false);
-	        vp.set(STRING_TO_JSVAL(js_str));
+			vp.setString(js_str);
 			break;
 		case GLOB_PROP_ERRNO:
-			vp.set(INT_TO_JSVAL(errno));
+			vp.setNumber((double)errno);
 			break;
 		case GLOB_PROP_ERRNO_STR:
 			if((js_str=JS_NewStringCopyZ(cx, strerror(errno)))==NULL)
 				return(false);
-	        vp.set(STRING_TO_JSVAL(js_str));
+			vp.setString(js_str);
 			break;
 	}
 	return(true);
@@ -116,24 +116,24 @@ static jsSyncPropertySpec js_global_properties[] = {
 };
 
 typedef struct {
-	JSRuntime*		runtime;
-	JSContext*		cx;
-	JSContext*		parent_cx;
-	JSObject*		obj;
-	JSObject*		script;
-	msg_queue_t*	msg_queue;
-	js_callback_t	cb;
-	JSErrorReporter error_reporter;
-	JSObject*		logobj;
-	sem_t			*sem;
+	JSRuntime*          runtime;
+	JSContext*          cx;
+	JSContext*          parent_cx;
+	JS::HandleObject    obj;
+	JS::HandleObject    script;
+	msg_queue_t*        msg_queue;
+	js_callback_t       cb;
+	JS::WarningReporter error_reporter;
+	JS::HandleObject    logobj;
+	sem_t               *sem;
 } background_data_t;
 
 #ifdef TODO_BACKGROUND_THREADS
 static void background_thread(void* arg)
 {
 	background_data_t* bg = (background_data_t*)arg;
-	JS::Value result=JS::UndefinedValue();
-	JS::Value exit_code;
+	JS::RootedValue result(cx, JS::UndefinedValue());
+	JS::RootedValue exit_code(cx);
 
 	SetThreadName("sbbs/jsBackgrnd");
 	msgQueueAttach(bg->msg_queue);
@@ -165,7 +165,7 @@ static void background_thread(void* arg)
 #endif
 
 static void
-js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
+js_ErrorReporter(JSContext *cx, JSErrorReport *report)
 {
 	background_data_t* bg;
 
@@ -176,7 +176,7 @@ js_ErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
 	JS_SetContextPrivate(cx, JS_GetContextPrivate(bg->parent_cx));
 
 	/* Call parent's error reporter */
-	bg->error_reporter(cx, message, report);
+	bg->error_reporter(cx, report);
 
 	/* Restore our context private data */
 	JS_SetContextPrivate(cx, bg);
@@ -208,13 +208,13 @@ js_InterruptCallback(JSContext *cx)
 static bool
 js_log(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	bool retval;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	bool               retval;
 	background_data_t* bg;
-	JS::Value	rval;
+	JS::RootedValue    rval(cx);
 
-	rval=JS::UndefinedValue();
-	JS_SET_RVAL(cx, arglist, rval);
+	rval.setUndefined();
+	argv.rval().set(rval);
 
 	if((bg=(background_data_t*)JS_GetContextPrivate(cx))==NULL)
 		return false;
@@ -223,7 +223,7 @@ js_log(JSContext *cx, unsigned argc, JS::Value *arglist)
 	JS_SetContextPrivate(cx, JS_GetContextPrivate(bg->parent_cx));
 
 	/* Call parent's log() function */
-	retval = JS_CallFunctionName(cx, bg->logobj, "log", argc, argv, &rval);
+	retval = JS_CallFunctionName(cx, bg->logobj, "log", argv, &rval);
 
 	/* Restore our context private data */
 	JS_SetContextPrivate(cx, bg);
@@ -232,19 +232,17 @@ js_log(JSContext *cx, unsigned argc, JS::Value *arglist)
 }
 
 /* Create a new value in the new context with a value from the original context */
-static JS::Value* js_CopyValue(JSContext* cx, JS::Value val, JSContext* new_cx, JS::Value* rval)
+static JS::HandleValue js_CopyValue(JSContext* cx, JS::HandleValue val, JSContext* new_cx, JS::MutableHandleValue rval)
 {
-	size_t	size;
-	uint64_t	*nval;
-
-	if (cx != new_cx) {
-		JS_ReportError(cx, "js_CopyValue() does not work across contexts anymore.");
-		return rval;
-	}
-	*rval = JS::UndefinedValue();
-	if(JS_WriteStructuredClone(cx, val, &nval, &size, NULL, NULL, JSVAL_FALSE)) {
-		JS_ReadStructuredClone(new_cx, nval, size, JS_STRUCTURED_CLONE_VERSION, rval, NULL, NULL);
-		JS_free(cx, nval);
+	JS::StructuredCloneScope scope(JS::StructuredCloneScope::SameProcessSameThread);
+	JSStructuredCloneData nval(scope);
+	JS::CloneDataPolicy policy;
+	JS::RootedValue transferable(cx);
+
+	rval.setUndefined();
+	transferable.setBoolean(true);
+	if(JS_WriteStructuredClone(cx, val, &nval, scope, policy, NULL, NULL, JS::UndefinedHandleValue)) {
+		JS_ReadStructuredClone(new_cx, nval, JS_STRUCTURED_CLONE_VERSION, scope, rval, NULL, NULL);
 	}
 
 	return rval;
@@ -253,41 +251,41 @@ static JS::Value* js_CopyValue(JSContext* cx, JS::Value val, JSContext* new_cx,
 static bool
 js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JSObject *obj=JS_THIS_OBJECT(cx, arglist);
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char		path[MAX_PATH+1];
-    unsigned		i;
-	unsigned		argn=0;
-    char*		filename;
-    JSScript*	script;
-	global_private_t*	p;
-	JS::Value		val;
-	JSObject*	js_argv;
-	JS::Value		old_js_argv = JS::UndefinedValue();
-	JS::Value		old_js_argc = JS::UndefinedValue();
-	BOOL		restore_args = FALSE;
-	JSObject*	exec_obj;
-	JSObject*	js_internal;
-	JSContext*	exec_cx=cx;
-	bool		success;
-	bool		background=false;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, arglist));
+	char               path[MAX_PATH+1];
+	unsigned           i;
+	unsigned           argn=0;
+	char*              filename;
+	JS::RootedScript   script(cx);
+	global_private_t*  p;
+	JS::RootedValue    val(cx);
+	JS::RootedObject   js_argv(cx);
+	JS::RootedValue    old_js_argv(cx, JS::UndefinedValue());
+	JS::RootedValue    old_js_argc(cx, JS::UndefinedValue());
+	bool               restore_args = false;
+	JS::RootedObject   exec_obj(cx);
+	JS::RootedObject   js_internal(cx);
+	JSContext*         exec_cx=cx;
+	bool               success;
+	bool               background=false;
+#ifdef TODO_BACKGROUND_THREADS
 	background_data_t* bg;
-	size_t		len;
-	JS::CallArgs args = JS::CallArgsFromVp(argc, arglist);
-	JSObject*       scope = JS_GetGlobalForObject(cx, &args.callee());
-
-	JS_SET_RVAL(cx, arglist,JS::UndefinedValue());
+#endif
+	size_t             len;
+	JS::RootedObject   scope(cx, JS_GetGlobalForObject(cx, &argv.callee()));
 
 	if((p=(global_private_t*)js_GetClassPrivate(cx, obj, &js_global_class))==NULL)
 		return(false);
 
+	argv.rval().setUndefined();
 	exec_obj=scope;
 
-	if(JSVAL_IS_BOOLEAN(argv[argn]))
-		background=JSVAL_TO_BOOLEAN(argv[argn++]);
+	if(argv[argn].isBoolean())
+		background=argv[argn++].toBoolean();
 
 	if(background) {
-		JS_ReportError(cx, "Background threads not supported");
+		JS_ReportErrorASCII(cx, "Background threads not supported");
 		return false;
 #ifdef TODO_BACKGROUND_THREADS
 
@@ -305,12 +303,12 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 		bg->cb.terminated=NULL;	/* could be bad pointer at any time */
 		bg->cb.counter=0;
 		bg->cb.gc_attempts=0;
-		bg->cb.bg = TRUE;
+		bg->cb.bg = true;
 
 		// Get the js.internal private data since it's the parents js_callback_t...
-		if((JS_GetProperty(cx, scope, "js", &val) && !JSVAL_NULL_OR_VOID(val))
-		    || (JS_GetProperty(cx, obj, "js", &val) && !JSVAL_NULL_OR_VOID(val))) {
-			js_internal = JSVAL_TO_OBJECT(val);
+		if((JS_GetProperty(cx, scope, "js", &val) && !val.isNullOrUndefined())
+		    || (JS_GetProperty(cx, obj, "js", &val) && !val.isNullOrUndefined())) {
+			js_internal = &val.toObject();
 			bg->cb.parent_cb = (js_callback_t*)JS_GetPrivate(cx,js_internal);
 			if (bg->cb.parent_cb == NULL) {
 				lprintf(LOG_ERR, "!ERROR parent CB is NULL");
@@ -380,8 +378,8 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 		/* Save parent's 'log' function (for later use by our log function) */
 		if(JS_GetProperty(cx, scope, "log", &val) || JS_GetProperty(cx, obj, "log", &val)) {
 			JSFunction* func;
-			if((func=JS_ValueToFunction(cx, val))!=NULL) {
-				JSObject *obj;
+			if((func=JS::ToFunction(cx, val))!=NULL) {
+				JS::RootedObject obj(cx);
 
 				obj=JS_CloneFunctionObject(bg->cx, JS_GetFunctionObject(func), bg->logobj);
 				JS_DefineProperty(bg->cx, bg->logobj, "log", OBJECT_TO_JSVAL(obj), NULL, NULL, JSPROP_ENUMERATE|JSPROP_PERMANENT);
@@ -406,14 +404,14 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 		exec_cx = bg->cx;
 		exec_obj = bg->obj;
 #endif
-	} else if(JSVAL_IS_OBJECT(argv[argn])) {
-		JSObject* tmp_obj=JSVAL_TO_OBJECT(argv[argn++]);
+	} else if(argv[argn].isObject()) {
+		JS::RootedObject tmp_obj(cx, &argv[argn++].toObject());
 		if(!JS_ObjectIsFunction(cx,tmp_obj))	/* Scope specified */
 			exec_obj=tmp_obj;
 	}
 
 	if(argn==argc) {
-		JS_ReportError(cx,"no filename specified");
+		JS_ReportErrorASCII(cx,"no filename specified");
 #ifdef TODO_BACKGROUND_THREADS
 		if(background) {
 			JS_RemoveObjectRoot(bg->cx, &bg->obj);
@@ -447,13 +445,11 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 		}
 		else {
 			JS_GetProperty(exec_cx, exec_obj, "argv", &old_js_argv);
-			JS_AddValueRoot(exec_cx, &old_js_argv);
 			JS_GetProperty(exec_cx, exec_obj, "argc", &old_js_argc);
-			JS_AddValueRoot(exec_cx, &old_js_argc);
-			restore_args = TRUE;
+			restore_args = true;
 		}
 
-		if((js_argv=JS_NewArrayObject(exec_cx, 0, NULL)) == NULL) {
+		if((js_argv=JS_NewArrayObject(exec_cx, 0)) == NULL) {
 #ifdef TODO_BACKGROUND_THREADS
 			if(background) {
 				JS_RemoveObjectRoot(bg->cx, &bg->obj);
@@ -467,11 +463,11 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 			return(false);
 		}
 
-		JS_DefineProperty(exec_cx, exec_obj, "argv", OBJECT_TO_JSVAL(js_argv)
-			,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+		JS_DefineProperty(exec_cx, exec_obj, "argv", js_argv
+			,JSPROP_ENUMERATE|JSPROP_READONLY);
 
 		for(i=argn; i<argc; i++) {
-			JS::Value *copy;
+			JS::RootedValue copy(cx);
 #ifdef TODO_BACKGROUND_THREADS
 			if(background) {
 				copy=js_CopyValue(cx,argv[i],exec_cx,&val);
@@ -484,8 +480,8 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 			JS_SetElement(exec_cx, js_argv, i-argn, copy);
 		}
 
-                JS_DefineProperty(exec_cx, exec_obj, "argc", INT_TO_JSVAL(MAX(argc-argn, 0))
-                       ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+                JS_DefineProperty(exec_cx, exec_obj, "argc", MAX(argc-argn, 0)
+                       ,JSPROP_ENUMERATE|JSPROP_READONLY);
 
 	//}
 
@@ -493,24 +489,24 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(isfullpath(filename))
 		SAFECOPY(path,filename);
 	else {
-		JSObject* js_load_list = NULL;
+		JS::RootedObject js_load_list(cx, NULL);
 
 		path[0]=0;	/* Empty path, indicates load file not found (yet) */
 
-		if((JS_GetProperty(cx, scope, "js", &val) && val!=JS::UndefinedValue() && JSVAL_IS_OBJECT(val))
-		    || (JS_GetProperty(cx, obj, "js", &val) && val!=JS::UndefinedValue() && JSVAL_IS_OBJECT(val))) {
-			JSObject* js_obj = JSVAL_TO_OBJECT(val);
+		if((JS_GetProperty(cx, scope, "js", &val) && val.isObject())
+		    || (JS_GetProperty(cx, obj, "js", &val) && val.isObject())) {
+			JS::RootedObject js_obj(cx, &val.toObject());
 			
 			/* if js.exec_dir is defined (location of executed script), search there first */
-			if(JS_GetProperty(cx, js_obj, "exec_dir", &val) && val!=JS::UndefinedValue() && JSVAL_IS_STRING(val)) {
+			if(JS_GetProperty(cx, js_obj, "exec_dir", &val) && val.isString()) {
 				JSVALUE_TO_STRBUF(cx, val, path, sizeof(path), &len);
 				strncat(path, filename, sizeof(path)-len);
 				path[sizeof(path)-1]=0;
 				if(!fexistcase(path))
 					path[0]=0;
 			}
-			if(JS_GetProperty(cx, js_obj, JAVASCRIPT_LOAD_PATH_LIST, &val) && val!=JS::UndefinedValue() && JSVAL_IS_OBJECT(val))
-				js_load_list = JSVAL_TO_OBJECT(val);
+			if(JS_GetProperty(cx, js_obj, JAVASCRIPT_LOAD_PATH_LIST, &val) && val.isObject())
+				js_load_list = &val.toObject();
 
 			/* if mods_dir is defined, search mods/js.load_path_list[n] next */
 			if(path[0]==0 && p->cfg->mods_dir[0]!=0 && js_load_list!=NULL) {
@@ -518,7 +514,7 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 				char		prefix[MAX_PATH+1];
 
 				for(i=0;path[0]==0;i++) {
-					if(!JS_GetElement(cx, js_load_list, i, &val) || val==JS::UndefinedValue())
+					if(!JS_GetElement(cx, js_load_list, i, &val) || val.isUndefined())
 						break;
 					JSVALUE_TO_STRBUF(cx, val, prefix, sizeof(prefix), NULL);
 					if(prefix[0]==0)
@@ -582,7 +578,8 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	JS::CompileOptions options(exec_cx);
 	options.setFileAndLine(path, 1);
-	script = JS::Compile(exec_cx, JS::RootedObject(exec_cx, exec_obj), options, path);
+	if (!JS::Compile(exec_cx, options, path, &script))
+		script = NULL;
 	if (script == NULL) {
 #ifdef TODO_BACKGROUND_THREADS
 		if(background) {
@@ -601,20 +598,18 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 			}
 			else {
 				JS_DefineProperty(exec_cx, exec_obj, "argv", old_js_argv
-					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+					,JSPROP_ENUMERATE|JSPROP_READONLY);
 				JS_DefineProperty(exec_cx, exec_obj, "argc", old_js_argc
-					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+					,JSPROP_ENUMERATE|JSPROP_READONLY);
 			}
 		}
-		JS_RemoveValueRoot(exec_cx, &old_js_argv);
-		JS_RemoveValueRoot(exec_cx, &old_js_argc);
 		return(false);
 	}
 
 	if(background) {
 #ifdef TODO_BACKGROUND_THREADS
 		bg->script = script;
-		JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(js_CreateQueueObject(cx, obj, NULL, bg->msg_queue)));
+		argv.rval().setObject(*js_CreateQueueObject(cx, obj, NULL, bg->msg_queue));
 		js_PrepareToExecute(bg->cx, bg->obj, path, NULL, bg->obj);
 		JS_ENDREQUEST(bg->cx);
 		JS_ClearContextThread(bg->cx);
@@ -627,10 +622,12 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 #endif
 		success = false;
 	} else {
-		JS::Value	rval;
+		JS::RootedValue	rval(cx);
+		JS::AutoObjectVector ov(exec_cx);
 
-		success = JS_ExecuteScript(exec_cx, exec_obj, script, &rval);
-		JS_SET_RVAL(cx, arglist, rval);
+		ov.append(exec_obj);
+		success = JS_ExecuteScript(exec_cx, ov, script, &rval);
+		argv.rval().set(rval);
 		if (restore_args) {
 			if (old_js_argv == JS::UndefinedValue()) {
 				JS_DeleteProperty(exec_cx, exec_obj, "argv");
@@ -638,12 +635,10 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
 			}
 			else {
 				JS_DefineProperty(exec_cx, exec_obj, "argv", old_js_argv
-					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+					,JSPROP_ENUMERATE|JSPROP_READONLY);
 				JS_DefineProperty(exec_cx, exec_obj, "argc", old_js_argc
-					,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+					,JSPROP_ENUMERATE|JSPROP_READONLY);
 			}
-			JS_RemoveValueRoot(exec_cx, &old_js_argv);
-			JS_RemoveValueRoot(exec_cx, &old_js_argc);
 		}
 	}
 
@@ -654,30 +649,33 @@ js_load(JSContext *cx, unsigned argc, JS::Value *arglist)
  * This is hacky, but a but less hacky than using a magic '2'
  * It does assume the args are always last though (which seems reasonable
  * since it's variable length)
+ * 
+ * Also, doesn't work with v52
  */
-#define JS_ARGS_OFFSET	((unsigned long)(JS_ARGV(0, (JS::Value *)NULL))/sizeof(JS::Value *))
+//#define JS_ARGS_OFFSET	((unsigned long)(JS_ARGV(0, (JS::Value *)NULL))/sizeof(JS::Value *))
+#define JS_ARGS_OFFSET 2
 
 static bool
 js_require(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	unsigned argn = 0;
-	unsigned fnarg;
-	JSObject*	tmp_obj;
-    char*		property;
-    char*		filename;
-    bool		found = false;
-    bool		ret;
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	JS::CallArgs args = JS::CallArgsFromVp(argc, arglist);
-	JSObject*       exec_obj = JS_GetGlobalForObject(cx, &args.callee());
-
-	if(JSVAL_IS_BOOLEAN(argv[argn])) {
-		JS_ReportError(cx,"cannot require() background processes");
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, arglist));
+	unsigned         argn = 0;
+	unsigned         fnarg;
+	JS::RootedObject tmp_obj(cx);
+	char*            property;
+	char*            filename;
+	bool             found = false;
+	bool             ret;
+	JS::RootedObject exec_obj(cx, JS_GetGlobalForObject(cx, &argv.callee()));
+
+	if(argv[argn].isBoolean()) {
+		JS_ReportErrorASCII(cx,"cannot require() background processes");
 		return(false);
 	}
 
-	if(JSVAL_IS_OBJECT(argv[argn])) {
-		tmp_obj=JSVAL_TO_OBJECT(argv[argn++]);
+	if(argv[argn].isObject()) {
+		tmp_obj = &argv[argn++].toObject();
 		if(!JS_ObjectIsFunction(cx,tmp_obj))	/* Scope specified */
 			exec_obj=tmp_obj;
 	}
@@ -686,14 +684,14 @@ js_require(JSContext *cx, unsigned argc, JS::Value *arglist)
 	fnarg = argn++;
 
 	if(argn==argc) {
-		JS_ReportError(cx,"no symbol name specified");
+		JS_ReportErrorASCII(cx,"no symbol name specified");
 		return(false);
 	}
 	JSVALUE_TO_MSTRING(cx, argv[argn], property, NULL);
 
 	// TODO: Does this support sub-objects?
 	if (JS_HasProperty(cx, exec_obj, property, &found) && found) {
-		JS_SET_RVAL(cx, arglist,JS::UndefinedValue());
+		argv.rval().setUndefined();
 		free(property);
 		return true;
 	}
@@ -707,7 +705,7 @@ js_require(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if (!JS_IsExceptionPending(cx)) {
 		if (!JS_HasProperty(cx, exec_obj, property, &found) || !found) {
 			JSVALUE_TO_MSTRING(cx, argv[fnarg], filename, NULL);
-			JS_ReportError(cx,"symbol '%s' not defined by script '%s'", property, filename);
+			JS_ReportErrorASCII(cx,"symbol '%s' not defined by script '%s'", property, filename);
 			free(filename);
 			return(false);
 		}
@@ -719,14 +717,12 @@ js_require(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_format(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char*		p;
-    JSString*	str;
-
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char*            p;
+	JS::RootedString str(cx);
 
 	if((p=js_sprintf(cx, 0, argc, argv))==NULL) {
-		JS_ReportError(cx,"js_sprintf failed");
+		JS_ReportErrorASCII(cx,"js_sprintf failed");
 		return(false);
 	}
 
@@ -736,20 +732,21 @@ js_format(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str));
-    return(true);
+	argv.rval().setString(str);
+	return(true);
 }
 
 static bool
 js_yield(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	BOOL forced=TRUE;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	bool forced=true;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
 	if(argc)
-		JS_ValueToBoolean(cx, argv[0], &forced);
+		forced = argv[0].toBoolean();
+
 	if(forced) {
 		YIELD();
 	} else {
@@ -762,17 +759,17 @@ js_yield(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_mswait(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	int32_t val=1;
 	clock_t start=msclock();
 
 	if(argc) {
-		if(!JS_ValueToInt32(cx,argv[0],&val))
+		if(!JS::ToInt32(cx,argv[0],&val))
 			return false;
 	}
 	mswait(val);
 
-	JS_SET_RVAL(cx, arglist,UINT_TO_JSVAL(msclock()-start));
+	argv.rval().setNumber((double)msclock()-start);
 
 	return(true);
 }
@@ -780,41 +777,42 @@ js_mswait(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_random(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	int32_t val=100;
 
 	if(argc) {
-		if(!JS_ValueToInt32(cx,argv[0],&val))
+		if(!JS::ToInt32(cx,argv[0],&val))
 			return false;
 	}
 
-	JS_SET_RVAL(cx, arglist,INT_TO_JSVAL(sbbs_random(val)));
+	argv.rval().setNumber((double)sbbs_random(val));
 	return(true);
 }
 
 static bool
 js_time(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS_SET_RVAL(cx, arglist,UINT_TO_JSVAL((uint32_t)time(NULL)));
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+
+	argv.rval().setNumber((double)time(NULL));
 	return(true);
 }
 
-
 static bool
 js_beep(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	int32_t freq=500;
 	int32_t dur=500;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
 	if(argc) {
-		if(!JS_ValueToInt32(cx,argv[0],&freq))
+		if(!JS::ToInt32(cx,argv[0],&freq))
 			return false;
 	}
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&dur))
+		if(!JS::ToInt32(cx,argv[1],&dur))
 			return false;
 	}
 
@@ -825,27 +823,26 @@ js_beep(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_exit(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JSObject *obj=JS_THIS_OBJECT(cx, arglist);
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	JS::Value val;
-	JS::CallArgs args = JS::CallArgsFromVp(argc, arglist);
-	JSObject*       scope = JS_GetGlobalForObject(cx, &args.callee());
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, arglist));
+	JS::RootedValue  val(cx);
+	JS::RootedObject scope(cx, JS_GetGlobalForObject(cx, &argv.callee()));
 
 	if(argc) {
-		if((JS_GetProperty(cx, scope, "js", &val) && JSVAL_IS_OBJECT(val)) || 
-		    (JS_GetProperty(cx, obj, "js", &val) && JSVAL_IS_OBJECT(val))) {
-			obj = JSVAL_TO_OBJECT(val);
-			if(JS_GetProperty(cx, obj, "scope", &val) && JSVAL_IS_OBJECT(val))
-				obj = JSVAL_TO_OBJECT(val);
+		if((JS_GetProperty(cx, scope, "js", &val) && val.isObject()) || 
+		    (JS_GetProperty(cx, obj, "js", &val) && val.isObject())) {
+			obj = &val.toObject();
+			if(JS_GetProperty(cx, obj, "scope", &val) && val.isObject())
+				obj = &val.toObject();
 			else
 				obj = JS_THIS_OBJECT(cx, arglist);
 		}
-		if(JSVAL_IS_NUMBER(argv[0]))
+		if(argv[0].isNumber())
 			JS_DefineProperty(cx, obj, "exit_code", argv[0]
-				,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY);
+				,JSPROP_ENUMERATE|JSPROP_READONLY);
 	}
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
 	return(false);
 }
@@ -853,14 +850,14 @@ js_exit(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_crc16(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	size_t		len;
 	uint16_t	cs;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, &len);
@@ -870,21 +867,21 @@ js_crc16(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	cs=crc16(p,len);
 	free(p);
-	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(cs));
+	argv.rval().setNumber((unsigned)cs);
 	return(true);
 }
 
 static bool
 js_crc32(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	size_t		len;
 	uint32_t	cs;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, &len);
@@ -894,22 +891,22 @@ js_crc32(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	cs=crc32(p,len);
 	free(p);
-	JS_SET_RVAL(cx, arglist,UINT_TO_JSVAL(cs));
+	argv.rval().setNumber(cs);
 	return(true);
 }
 
 static bool
 js_chksum(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	ulong		sum=0;
 	char*		p = NULL;
 	char*		sp;
 	size_t		len;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, &len);
@@ -921,35 +918,37 @@ js_chksum(JSContext *cx, unsigned argc, JS::Value *arglist)
 	while(len--) sum+=*(sp++);
 	free(p);
 
-	JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)sum));
+	argv.rval().setNumber((double)sum);
 	return(true);
 }
 
 static bool
 js_ascii(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char		str[2];
-	int32_t		i=0;
-	JSString*	js_str;
-	const jschar	*p;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char             str[2];
+	int32_t          i=0;
+	JS::RootedString js_str(cx);
+	char     *p;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	if(JSVAL_IS_STRING(argv[0])) {	/* string to ascii-int */
-		p=JS_GetStringCharsZ(cx, JSVAL_TO_STRING(argv[0]));
+	if(argv[0].isString()) {	/* string to ascii-int */
+		p=JS_EncodeString(cx, argv[0].toString());
 		if(p==NULL)
-			JS_SET_RVAL(cx, arglist,INT_TO_JSVAL(0));
-		else
-			JS_SET_RVAL(cx, arglist,INT_TO_JSVAL((uchar)*p));
+			argv.rval().setNumber(0U);
+		else {
+			argv.rval().setNumber((unsigned)*p);
+			JS_free(cx, p);
+		}
 		return(true);
 	}
 
 	/* ascii-int to str */
-	if(!JS_ValueToInt32(cx,argv[0],&i))
+	if(!JS::ToInt32(cx,argv[0],&i))
 		return false;
 	str[0]=(uchar)i;
 	str[1]=0;
@@ -957,34 +956,35 @@ js_ascii(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if((js_str = JS_NewStringCopyN(cx, str, 1))==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char		ch;
-	char		str[2];
-	int32_t		i=0;
-	JSString*	js_str;
-	const jschar	*p;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char		 ch;
+	char		 str[2];
+	int32_t		 i=0;
+	JS::RootedString js_str(cx);
+	char*            p;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	if(JSVAL_IS_STRING(argv[0])) {	
-		p=JS_GetStringCharsZ(cx, JSVAL_TO_STRING(argv[0]));
+	if(argv[0].isString()) {	
+		p = JS_EncodeString(cx, argv[0].toString());
 		if(p==NULL) {
-			JS_ReportError(cx, "Invalid NULL string");
+			JS_ReportErrorASCII(cx, "Invalid NULL string");
 			return(false);
 		}
-		ch=(uchar)*p;
+		ch=*p;
+		JS_free(cx, p);
 	} else {
-		if(!JS_ValueToInt32(cx,argv[0],&i))
+		if(!JS::ToInt32(cx,argv[0],&i))
 			return false;
 		ch=(char)i;
 	}
@@ -995,20 +995,20 @@ js_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if((js_str = JS_NewStringCopyZ(cx, str))==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_ascii_str(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char*		buf = NULL;
-	JSString*	str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char*            buf = NULL;
+	JS::RootedString str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
@@ -1023,21 +1023,20 @@ js_ascii_str(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str));
+	argv.rval().setString(str);
 	return(true);
 }
 
-
 static bool
 js_strip_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char*		buf = NULL;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char*            buf = NULL;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL);
@@ -1052,20 +1051,20 @@ js_strip_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_strip_ansi(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char*		buf = NULL;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char*            buf = NULL;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
@@ -1080,20 +1079,20 @@ js_strip_ansi(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return false;
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return true;
 }
 
 static bool
 js_strip_exascii(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char*		buf = NULL;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char*            buf = NULL;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL)
@@ -1108,22 +1107,22 @@ js_strip_exascii(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_lfexpand(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	ulong		i,j;
-	char*		inbuf = NULL;
-	char*		outbuf;
-	JSString*	str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	ulong            i,j;
+	char*            inbuf = NULL;
+	char*            outbuf;
+	JS::RootedString str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
@@ -1132,7 +1131,7 @@ js_lfexpand(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if((outbuf=(char*)malloc((strlen(inbuf)*2)+1))==NULL) {
-		JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", (strlen(inbuf)*2)+1, getfname(__FILE__), __LINE__);
+		JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", (strlen(inbuf)*2)+1, getfname(__FILE__), __LINE__);
 		free(inbuf);
 		return(false);
 	}
@@ -1150,25 +1149,25 @@ js_lfexpand(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str));
+	argv.rval().setString(str);
 	return(true);
 }
 
 static bool
 js_word_wrap(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	int32_t		len=79;
-	int32_t		oldlen=79;
-	bool		handle_quotes=true;
-	bool		is_utf8=false;
-	char*		inbuf = NULL;
-	char*		outbuf;
-	JSString*	js_str;
-
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
-
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	int32_t          len=79;
+	int32_t          oldlen=79;
+	bool             handle_quotes=true;
+	bool             is_utf8=false;
+	char*            inbuf = NULL;
+	char*            outbuf;
+	JS::RootedString js_str(cx);
+
+	argv.rval().setUndefined();
+
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
@@ -1177,58 +1176,57 @@ js_word_wrap(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&len)) {
+		if(!JS::ToInt32(cx,argv[1],&len)) {
 			free(inbuf);
 			return false;
 		}
 	}
 
 	if(argc>2) {
-		if(!JS_ValueToInt32(cx,argv[2],&oldlen)) {
+		if(!JS::ToInt32(cx,argv[2],&oldlen)) {
 			free(inbuf);
 			return false;
 		}
 	}
 
-	if(argc>3 && JSVAL_IS_BOOLEAN(argv[3]))
-		handle_quotes = JSVAL_TO_BOOLEAN(argv[3]);
-	if(argc>4 && JSVAL_IS_BOOLEAN(argv[4]))
-		is_utf8 = JSVAL_TO_BOOLEAN(argv[4]);
+	if(argc>3 && argv[3].isBoolean())
+		handle_quotes = argv[3].toBoolean();
+	if(argc>4 && argv[4].isBoolean())
+		is_utf8 = argv[4].toBoolean();
 
 	outbuf=wordwrap(inbuf, len, oldlen, handle_quotes, is_utf8);
 	free(inbuf);
 
-
 	if(outbuf==NULL) {
-		JS_ReportError(cx, "Allocation error in wordwrap()");
+		JS_ReportErrorASCII(cx, "Allocation error in wordwrap()");
 		return(false);
 	}
 	js_str = JS_NewStringCopyZ(cx, outbuf);
 	free(outbuf);
 	if(js_str==NULL)
 		return(false);
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_quote_msg(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	int32_t		len=79;
-	int			i,l,clen;
-	char*		inbuf = NULL;
-	char*		outbuf;
-	char*		linebuf;
-	char*		tmpptr;
-	const char	*prefix_def = " > ";
-	char*		prefix=(char *)prefix_def;
-	JSString*	js_str;
-	size_t		linebuf_sz=0;
-
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
-
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	int32_t          len=79;
+	int              i,l,clen;
+	char*            inbuf = NULL;
+	char*            outbuf;
+	char*            linebuf;
+	char*            tmpptr;
+	const char       *prefix_def = " > ";
+	char*            prefix=(char *)prefix_def;
+	JS::RootedString js_str(cx);
+	size_t           linebuf_sz=0;
+
+	argv.rval().setUndefined();
+
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
@@ -1237,7 +1235,7 @@ js_quote_msg(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&len)) {
+		if(!JS::ToInt32(cx,argv[1],&len)) {
 			free(inbuf);
 			return false;
 		}
@@ -1254,7 +1252,7 @@ js_quote_msg(JSContext *cx, unsigned argc, JS::Value *arglist)
 	}
 
 	if((outbuf=(char*)malloc((strlen(inbuf)*(strlen(prefix)+1))+1))==NULL) {
-		JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", (strlen(inbuf)*(strlen(prefix)+1))+1, getfname(__FILE__), __LINE__);
+		JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", (strlen(inbuf)*(strlen(prefix)+1))+1, getfname(__FILE__), __LINE__);
 		free(inbuf);
 		if(prefix != prefix_def)
 			free(prefix);
@@ -1276,7 +1274,7 @@ js_quote_msg(JSContext *cx, unsigned argc, JS::Value *arglist)
 		free(outbuf);
 		if(prefix != prefix_def)
 			free(prefix);
-		JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", linebuf_sz, getfname(__FILE__), __LINE__);
+		JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", linebuf_sz, getfname(__FILE__), __LINE__);
 		return(false);
 	}
 
@@ -1303,7 +1301,7 @@ js_quote_msg(JSContext *cx, unsigned argc, JS::Value *arglist)
 				free(outbuf);
 				if(prefix != prefix_def)
 					free(prefix);
-				JS_ReportError(cx, "Error reallocating %lu bytes at %s:%d", linebuf_sz, getfname(__FILE__), __LINE__);
+				JS_ReportErrorASCII(cx, "Error reallocating %lu bytes at %s:%d", linebuf_sz, getfname(__FILE__), __LINE__);
 				return false;
 			}
 			linebuf=tmpptr;
@@ -1327,19 +1325,19 @@ js_quote_msg(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_netaddr_type(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*	str = NULL;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -1347,7 +1345,7 @@ js_netaddr_type(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(str==NULL) 
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(smb_netaddr_type(str)));
+	argv.rval().setNumber((double)smb_netaddr_type(str));
 	free(str);
 
 	return(true);
@@ -1357,7 +1355,7 @@ js_netaddr_type(JSContext *cx, unsigned argc, JS::Value *arglist)
 /* Much of this table supplied by Deuce (thanks!) */
 static struct { 
 	int		value;
-	char*	name;
+	const char*	name;
 } exasctbl[128] = {
 /*  HTML val,name             ASCII  description */
 	{ 199	,"Ccedil"	}, /* 128 C, cedilla */
@@ -1492,7 +1490,7 @@ static struct {
 
 static struct { 
 	int		value;
-	char*	name;
+	const char*	name;
 } lowasctbl[32] = {
 	{ 160	,"nbsp"		}, /* NULL non-breaking space */
 	{ 9786	,NULL		}, /* 0x263a white smiling face (^A, 1) */
@@ -1531,55 +1529,55 @@ static struct {
 static bool
 js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JSObject *obj=JS_THIS_OBJECT(cx, arglist);
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	int			ch;
-	ulong		i,j;
-	char*		inbuf = NULL;
-	char*		tmpbuf;
-	size_t		tmpbuf_sz;
-	char*		outbuf;
-	char*		param;
-	char*		lastparam;
-	char*		tmpptr;
-	bool		exascii=true;
-	bool		wsp=true;
-	bool		ansi=true;
-	bool		ctrl_a=true;
-	JSString*	js_str;
-	int32_t		fg=7;
-	int32_t		bg=0;
-	bool		blink=FALSE;
-	bool		bold=FALSE;
-	int			esccount=0;
-	char		ansi_seq[MAX_ANSI_SEQ+1];
-	int			ansi_param[MAX_ANSI_PARAMS];
-	int			k,l;
-	ulong		savepos=0;
-	int32_t		hpos=0;
-	int32_t		currrow=0;
-	int			savehpos=0;
-	int			savevpos=0;
-	int32_t		wraphpos=-2;
-	int32_t		wrapvpos=-2;
-	int32_t		wrappos=0;
-	BOOL		extchar=FALSE;
-	ulong		obsize;
-	int32_t		lastcolor=7;
-	char		tmp1[128];
-	struct		tm tm;
-	time_t		now;
-	BOOL		nodisplay=FALSE;
-	global_private_t*	p;
-	uchar   	attr_stack[64]; /* Saved attributes (stack) */
-	int     	attr_sp=0;                /* Attribute stack pointer */
-	ulong		clear_screen=0;
-	JSObject*	stateobj=NULL;
-	JS::Value		val;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, arglist));
+	int               ch;
+	ulong             i,j;
+	char*             inbuf = NULL;
+	char*             tmpbuf;
+	size_t            tmpbuf_sz;
+	char*             outbuf;
+	char*             param;
+	char*             lastparam;
+	char*             tmpptr;
+	bool              exascii=true;
+	bool              wsp=true;
+	bool              ansi=true;
+	bool              ctrl_a=true;
+	JS::RootedString  js_str(cx);
+	int32_t           fg=7;
+	int32_t           bg=0;
+	bool              blink=false;
+	bool              bold=false;
+	int               esccount=0;
+	char              ansi_seq[MAX_ANSI_SEQ+1];
+	int               ansi_param[MAX_ANSI_PARAMS];
+	int               k,l;
+	ulong             savepos=0;
+	int32_t           hpos=0;
+	int32_t           currrow=0;
+	int               savehpos=0;
+	int               savevpos=0;
+	int32_t           wraphpos=-2;
+	int32_t           wrapvpos=-2;
+	int32_t           wrappos=0;
+	bool              extchar=false;
+	ulong             obsize;
+	int32_t           lastcolor=7;
+	char              tmp1[128];
+	struct            tm tm;
+	time_t            now;
+	bool              nodisplay=false;
+	global_private_t* p;
+	uchar             attr_stack[64]; /* Saved attributes (stack) */
+	int               attr_sp=0;                /* Attribute stack pointer */
+	ulong             clear_screen=0;
+	JS::RootedObject  stateobj(cx, NULL);
+	JS::RootedValue   val(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	if((p=(global_private_t*)js_GetClassPrivate(cx, obj, &js_global_class))==NULL)
@@ -1590,90 +1588,84 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(inbuf==NULL)
 		return(true);
 
-	if(argc>1 && JSVAL_IS_BOOLEAN(argv[1]))
-		exascii=JSVAL_TO_BOOLEAN(argv[1]);
+	if(argc>1 && argv[1].isBoolean())
+		exascii=argv[1].toBoolean();
 
-	if(argc>2 && JSVAL_IS_BOOLEAN(argv[2]))
-		wsp=JSVAL_TO_BOOLEAN(argv[2]);
+	if(argc>2 && argv[2].isBoolean())
+		wsp=argv[2].toBoolean();
 
-	if(argc>3 && JSVAL_IS_BOOLEAN(argv[3]))
-		ansi=JSVAL_TO_BOOLEAN(argv[3]);
+	if(argc>3 && argv[3].isBoolean())
+		ansi=argv[3].toBoolean();
 
-	if(argc>4 && JSVAL_IS_BOOLEAN(argv[4]))
+	if(argc>4 && argv[4].isBoolean())
 	{
-		ctrl_a=JSVAL_TO_BOOLEAN(argv[4]);
+		ctrl_a=argv[4].toBoolean();
 		if(ctrl_a)
 			ansi=ctrl_a;
 	}
 
-	if(argc>5 && JSVAL_IS_OBJECT(argv[5])) {
-		stateobj=JSVAL_TO_OBJECT(argv[5]);
+	if(argc>5 && argv[5].isObject()) {
+		stateobj=&argv[5].toObject();
 		JS_GetProperty(cx,stateobj,"fg",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &fg)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &fg)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"bg",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &bg)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &bg)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"lastcolor",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &lastcolor)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &lastcolor)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"blink",&val);
-		if(JSVAL_IS_BOOLEAN(val)) {
-			if(!JS_ValueToBoolean(cx, val, &blink)) {
-				free(inbuf);
-				return false;
-			}
+		if(val.isBoolean()) {
+			blink = val.toBoolean();
 		}
 		JS_GetProperty(cx,stateobj,"bold",&val);
-		if(JSVAL_IS_BOOLEAN(val)) {
-			if(!JS_ValueToBoolean(cx, val, &bold)) {
-				free(inbuf);
-				return false;
-			}
+		if(val.isBoolean()) {
+			bold = val.toBoolean();
 		}
 		JS_GetProperty(cx,stateobj,"hpos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &hpos)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &hpos)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"currrow",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &currrow)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &currrow)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"wraphpos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &wraphpos)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &wraphpos)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"wrapvpos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &wrapvpos)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &wrapvpos)) {
 				free(inbuf);
 				return false;
 			}
 		}
 		JS_GetProperty(cx,stateobj,"wrappos",&val);
-		if(JSVAL_IS_NUMBER(val)) {
-			if(!JS_ValueToInt32(cx, val, &wrappos)) {
+		if(val.isNumber()) {
+			if(!JS::ToInt32(cx, val, &wrappos)) {
 				free(inbuf);
 				return false;
 			}
@@ -1683,7 +1675,7 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	tmpbuf_sz = (strlen(inbuf)*10)+1;
 	if((tmpbuf=(char*)malloc(tmpbuf_sz))==NULL) {
 		free(inbuf);
-		JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", tmpbuf_sz, getfname(__FILE__), __LINE__);
+		JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", tmpbuf_sz, getfname(__FILE__), __LINE__);
 		return(false);
 	}
 
@@ -1760,7 +1752,7 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 			if(tmpptr==NULL) {
 				free(tmpbuf);
 				free(inbuf);
-				JS_ReportError(cx, "Error reallocating %lu bytes at %s:%d", tmpbuf_sz, getfname(__FILE__), __LINE__);
+				JS_ReportErrorASCII(cx, "Error reallocating %lu bytes at %s:%d", tmpbuf_sz, getfname(__FILE__), __LINE__);
 				return false;
 			}
 			tmpbuf=tmpptr;
@@ -1777,7 +1769,7 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 		if((outbuf=(char*)malloc(obsize))==NULL)
 		{
 			free(tmpbuf);
-			JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", obsize, getfname(__FILE__), __LINE__);
+			JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", obsize, getfname(__FILE__), __LINE__);
 			return(false);
 		}
 		j=sprintf(outbuf,"<span style=\"%s\">",htmlansi[7]);
@@ -1790,7 +1782,7 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 				{
 					free(tmpbuf);
 					free(outbuf);
-					JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", obsize, getfname(__FILE__), __LINE__);
+					JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", obsize, getfname(__FILE__), __LINE__);
 					return(false);
 				}
 				outbuf=param;
@@ -1838,20 +1830,20 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 								case 0:
 									fg=7;
 									bg=0;
-									blink=FALSE;
-									bold=FALSE;
+									blink=false;
+									bold=false;
 									break;
 								case 1:
-									bold=TRUE;
+									bold=true;
 									break;
 								case 2:
-									bold=FALSE;
+									bold=false;
 									break;
 								case 5:
-									blink=TRUE;
+									blink=true;
 									break;
 								case 6:
-									blink=TRUE;
+									blink=true;
 									break;
 								case 7:
 									l=fg;
@@ -1860,8 +1852,8 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 									break;
 								case 8:
 									fg=bg;
-									blink=FALSE;
-									bold=FALSE;
+									blink=false;
+									bold=false;
 									break;
 								case 30:
 								case 31:
@@ -2052,10 +2044,10 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 						bg=7;
 						break;
 					case 'H':
-						bold=TRUE;
+						bold=true;
 						break;
 					case 'I':
-						blink=TRUE;
+						blink=true;
 						break;
 					case '+':
 						if(attr_sp<(int)sizeof(attr_stack))
@@ -2064,15 +2056,15 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 					case '-':
 						if(attr_sp>0)
 						{
-							blink=(attr_stack[--attr_sp]&(1<<7))?TRUE:FALSE;
+							blink=(attr_stack[--attr_sp]&(1<<7))?true:false;
 							bg=(attr_stack[attr_sp] >> 4) & 7;
-							blink=(attr_stack[attr_sp]&(1<<3))?TRUE:FALSE;
+							blink=(attr_stack[attr_sp]&(1<<3))?true:false;
 							fg=attr_stack[attr_sp] & 7;
 						}
 						else if(bold || blink || bg)
 						{
-							bold=FALSE;
-							blink=FALSE;
+							bold=false;
+							blink=false;
 							fg=7;
 							bg=0;
 						}
@@ -2080,15 +2072,15 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 					case '_':
 						if(blink || bg)
 						{
-							bold=FALSE;
-							blink=FALSE;
+							bold=false;
+							blink=false;
 							fg=7;
 							bg=0;
 						}
 						break;
 					case 'N':
-						bold=FALSE;
-						blink=FALSE;
+						bold=false;
+						blink=false;
 						fg=7;
 						bg=0;
 						break;
@@ -2114,10 +2106,10 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 					case '&':
 					case '*':
 					case '(':
-						nodisplay=TRUE;
+						nodisplay=true;
 						break;
 					case ')':
-						nodisplay=FALSE;
+						nodisplay=false;
 						break;
 
 					case 'D':
@@ -2231,9 +2223,9 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 						}
 						outbuf[j++]=tmpbuf[i];
 						if(tmpbuf[i]=='&')
-							extchar=TRUE;
+							extchar=true;
 						if(tmpbuf[i]==';')
-							extchar=FALSE;
+							extchar=false;
 						if(!extchar)
 							hpos++;
 						/* ToDo: Fix hard-coded terminal window width (80) */
@@ -2263,29 +2255,29 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 
 	if(stateobj!=NULL) {
-		JS_DefineProperty(cx, stateobj, "fg", INT_TO_JSVAL(fg)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "bg", INT_TO_JSVAL(bg)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "lastcolor", INT_TO_JSVAL(lastcolor)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "blink", BOOLEAN_TO_JSVAL(blink)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "bold", BOOLEAN_TO_JSVAL(bold)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "hpos", INT_TO_JSVAL(hpos)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "currrow", INT_TO_JSVAL(currrow)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "wraphpos", INT_TO_JSVAL(wraphpos)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "wrapvpos", INT_TO_JSVAL(wrapvpos)
-			,NULL,NULL,JSPROP_ENUMERATE);
-		JS_DefineProperty(cx, stateobj, "wrappos", INT_TO_JSVAL(wrappos)
-			,NULL,NULL,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "fg", fg
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "bg", bg
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "lastcolor", lastcolor
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "blink", blink
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "bold", bold
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "hpos", hpos
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "currrow", currrow
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "wraphpos", wraphpos
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "wrapvpos", wrapvpos
+			,JSPROP_ENUMERATE);
+		JS_DefineProperty(cx, stateobj, "wrappos", wrappos
+			,JSPROP_ENUMERATE);
 	}
 
 	return(true);
@@ -2294,19 +2286,19 @@ js_html_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_html_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	int			ch;
-	int			val;
-	ulong		i,j;
-	char*		inbuf = NULL;
-	char*		outbuf;
-	char		token[16];
-	size_t		t;
-	JSString*	js_str;
-
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
-
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	int              ch;
+	int              val;
+	ulong            i,j;
+	char*            inbuf = NULL;
+	char*            outbuf;
+	char             token[16];
+	size_t           t;
+	JS::RootedString js_str(cx);
+
+	argv.rval().setUndefined();
+
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
@@ -2428,24 +2420,24 @@ js_html_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_b64_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	int			res;
-	size_t		len;
-	size_t		inbuf_len;
-	char*		inbuf = NULL;
-	char*		outbuf;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	int              res;
+	size_t           len;
+	size_t           inbuf_len;
+	char*            inbuf = NULL;
+	char*            outbuf;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, &inbuf_len);
@@ -2457,7 +2449,7 @@ js_b64_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	if((outbuf=(char*)malloc(len))==NULL) {
 		free(inbuf);
-		JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", len, getfname(__FILE__), __LINE__);
+		JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", len, getfname(__FILE__), __LINE__);
 		return(false);
 	}
 
@@ -2474,23 +2466,23 @@ js_b64_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_b64_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	int			res;
-	size_t		len;
-	char*		inbuf = NULL;
-	char*		outbuf;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	int              res;
+	size_t           len;
+	char*            inbuf = NULL;
+	char*            outbuf;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, NULL);
@@ -2501,7 +2493,7 @@ js_b64_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	len=strlen(inbuf)+1;
 
 	if((outbuf=(char*)malloc(len))==NULL) {
-		JS_ReportError(cx, "Error allocating %lu bytes at %s:%d", len, getfname(__FILE__), __LINE__);
+		JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d", len, getfname(__FILE__), __LINE__);
 		free(inbuf);
 		return(false);
 	}
@@ -2519,24 +2511,24 @@ js_b64_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_md5_calc(JSContext* cx, unsigned argc, JS::Value* arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	BYTE		digest[MD5_DIGEST_SIZE];
-	bool		hex=false;
-	size_t		inbuf_len;
-	char*		inbuf = NULL;
-	char		outbuf[64];
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	uint8_t          digest[MD5_DIGEST_SIZE];
+	bool             hex=false;
+	size_t           inbuf_len;
+	char*            inbuf = NULL;
+	char             outbuf[64];
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], inbuf, &inbuf_len);
@@ -2544,14 +2536,14 @@ js_md5_calc(JSContext* cx, unsigned argc, JS::Value* arglist)
 	if(inbuf==NULL)
 		return(true);
 
-	if(argc>1 && JSVAL_IS_BOOLEAN(argv[1]))
-		hex=JSVAL_TO_BOOLEAN(argv[1]);
+	if(argc>1 && argv[1].isBoolean())
+		hex=argv[1].toBoolean();
 
 	MD5_calc(digest,inbuf,inbuf_len);
 	free(inbuf);
 
 	if(hex)
-		MD5_hex((BYTE*)outbuf,digest);
+		MD5_hex((uint8_t*)outbuf,digest);
 	else
 		b64_encode(outbuf,sizeof(outbuf),(char*)digest,sizeof(digest));
 
@@ -2559,21 +2551,21 @@ js_md5_calc(JSContext* cx, unsigned argc, JS::Value* arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_internal_charfunc(JSContext *cx, unsigned argc, JS::Value *arglist, char *(*func)(char *), unsigned extra_bytes)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char		*str = NULL, *rastr, *funcret;
-	JSString*	js_str;
-	size_t		strlen;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char             *str = NULL, *rastr, *funcret;
+	JS::RootedString js_str(cx);
+	size_t           strlen;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, &strlen);
@@ -2592,7 +2584,7 @@ js_internal_charfunc(JSContext *cx, unsigned argc, JS::Value *arglist, char *(*f
 		js_str = JS_NewStringCopyZ(cx, funcret);
 		if (js_str == NULL)
 			goto error;
-		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+		argv.rval().setString(js_str);
 	}
 	free(str);
 
@@ -2652,14 +2644,14 @@ js_getfext(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_truncstr(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char*		str = NULL;
-	char*		set;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char*            str = NULL;
+	char*            set;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -2686,21 +2678,21 @@ js_truncstr(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
 js_fullpath(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char		path[MAX_PATH+1];
-	char*		str = NULL;
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char             path[MAX_PATH+1];
+	char*            str = NULL;
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -2714,7 +2706,7 @@ js_fullpath(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if((js_str = JS_NewStringCopyZ(cx, path))==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
@@ -2722,13 +2714,13 @@ js_fullpath(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_getfcase(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	char		path[MAX_PATH+1];
-	JSString*	js_str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	char             path[MAX_PATH+1];
+	JS::RootedString js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_STRBUF(cx, argv[0], path, sizeof(path), NULL);
@@ -2738,7 +2730,7 @@ js_getfcase(JSContext *cx, unsigned argc, JS::Value *arglist)
 		if(js_str==NULL)
 			return(false);
 
-		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+		argv.rval().setString(js_str);
 	}
 	return(true);
 }
@@ -2746,16 +2738,16 @@ js_getfcase(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_dosfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 #if defined(_WIN32)
 	char*		str = NULL;
 	char		path[MAX_PATH+1];
-	JSString*	js_str;
+	JS::RootedString	js_str;
 #endif
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 #if defined(_WIN32)
@@ -2771,7 +2763,7 @@ js_dosfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 		if(js_str==NULL)
 			return(false);
 
-		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+		argv.rval().setString(js_str);
 	}
 	else {
 		free(str);
@@ -2779,7 +2771,7 @@ js_dosfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 #else	/* No non-Windows equivalent */
 
-	JS_SET_RVAL(cx, arglist, argv[0]);
+	argv.rval().set(argv[0]);
 
 #endif
 
@@ -2789,15 +2781,15 @@ js_dosfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_cfgfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		path = NULL;
 	char*		fname;
 	char		result[MAX_PATH+1];
 	char*		cstr;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc < 2 || JSVAL_IS_VOID(argv[0]))
+	if(argc < 2 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], path, NULL);
@@ -2814,7 +2806,7 @@ js_cfgfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 	cstr = iniFileName(result,sizeof(result),path,fname);
 	free(fname);
 	free(path);
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(JS_NewStringCopyZ(cx,cstr)));
+	argv.rval().setString(JS_NewStringCopyZ(cx,cstr));
 
 	return(true);
 }
@@ -2822,13 +2814,13 @@ js_cfgfname(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_fexist(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		fe;
+	bool		fe;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -2838,20 +2830,20 @@ js_fexist(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	fe=fexist(p);
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(fe));
+	argv.rval().setBoolean(fe);
 	return(true);
 }
 
 static bool
 js_removecase(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -2861,20 +2853,20 @@ js_removecase(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=removecase(p)==0;
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_remove(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -2884,24 +2876,24 @@ js_remove(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=remove(p)==0;
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_rename(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		oldname = NULL;
 	char*		newname = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(false));
+	argv.rval().setBoolean(false);
 	JSVALUE_TO_MSTRING(cx, argv[0], oldname, NULL);
 	HANDLE_PENDING(cx, oldname);
 	if(oldname==NULL)
@@ -2921,24 +2913,24 @@ js_rename(JSContext *cx, unsigned argc, JS::Value *arglist)
 	ret=rename(oldname,newname)==0;
 	free(oldname);
 	free(newname);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_fcopy(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		src = NULL;
 	char*		dest;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(false));
+	argv.rval().setBoolean(false);
 	JSVALUE_TO_MSTRING(cx, argv[0], src, NULL);
 	HANDLE_PENDING(cx, src);
 	if(src==NULL)
@@ -2957,24 +2949,24 @@ js_fcopy(JSContext *cx, unsigned argc, JS::Value *arglist)
 	ret = CopyFile(src, dest, /* failIfExists: */FALSE);
 	free(src);
 	free(dest);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_fcompare(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		fn1 = NULL;
 	char*		fn2 = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(false));
+	argv.rval().setBoolean(false);
 	JSVALUE_TO_MSTRING(cx, argv[0], fn1, NULL);
 	HANDLE_PENDING(cx, fn1);
 	if(fn1==NULL)
@@ -2994,59 +2986,56 @@ js_fcompare(JSContext *cx, unsigned argc, JS::Value *arglist)
 	ret=fcompare(fn1,fn2);
 	free(fn1);
 	free(fn2);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_backup(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		fname = NULL;
 	int32_t		level=5;
-	BOOL		ren=FALSE;
-	BOOL		ret;
+	bool		ren=false;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(false));
+	argv.rval().setBoolean(false);
 	JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
 	HANDLE_PENDING(cx, fname);
 	if(fname==NULL)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&level)) {
+		if(!JS::ToInt32(cx,argv[1],&level)) {
 			free(fname);
 			return false;
 		}
 	}
 	if(argc>2) {
-		if(!JS_ValueToBoolean(cx,argv[2],&ren)) {
-			free(fname);
-			return false;
-		}
+		ren = JS::ToBoolean(argv[2]);
 	}
 
 	ret=backup(fname,level,ren);
 	free(fname);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_isdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3056,20 +3045,20 @@ js_isdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=isdir(p);
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_fattr(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	int			attr;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3079,20 +3068,20 @@ js_fattr(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	attr=getfattr(p);
 	free(p);
-	JS_SET_RVAL(cx, arglist,INT_TO_JSVAL(attr));
+	argv.rval().setNumber((double)attr);
 	return(true);
 }
 
 static bool
 js_fmode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		fname = NULL;
 	int			mode = -1;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL)
@@ -3104,20 +3093,20 @@ js_fmode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(stat(fname, &st) == 0)
 		mode = st.st_mode;
 	free(fname);
-	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(mode));
+	argv.rval().setNumber((double)mode);
 	return true;
 }
 
 static bool
 js_chmod(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		fname = NULL;
 	int32_t		mode;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc < 2 || JSVAL_IS_VOID(argv[0]))
+	if(argc < 2 || argv[0].isUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL)
@@ -3125,27 +3114,27 @@ js_chmod(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(fname == NULL) 
 		return true;
 
-	if(!JS_ValueToInt32(cx, argv[1], &mode)) {
+	if(!JS::ToInt32(cx, argv[1], &mode)) {
 		free(fname);
 		return false;
 	}
 
 	int result = CHMOD(fname, mode);
 	free(fname);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result == 0));
+	argv.rval().setBoolean(result == 0);
 	return true;
 }
 
 static bool
 js_fdate(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	time_t		fd;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3155,20 +3144,20 @@ js_fdate(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	fd=fdate(p);
 	free(p);
-	JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)fd));
+	argv.rval().setNumber((double)fd);
 	return(true);
 }
 
 static bool
 js_fcdate(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	time_t		fd;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3178,26 +3167,26 @@ js_fcdate(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	fd=fcdate(p);
 	free(p);
-	JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)fd));
+	argv.rval().setNumber((double)fd);
 	return(true);
 }
 
 static bool
 js_utime(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*			fname = NULL;
 	int32_t			actime;
 	int32_t			modtime;
 	struct utimbuf	ut;
-	BOOL			ret;
+	bool			ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+	argv.rval().setBoolean(false);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
 	HANDLE_PENDING(cx, fname);
@@ -3209,12 +3198,12 @@ js_utime(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	if(argc>1) {
 		actime=modtime=(int32_t)ut.actime;
-		if(!JS_ValueToInt32(cx,argv[1],&actime)) {
+		if(!JS::ToInt32(cx,argv[1],&actime)) {
 			free(fname);
 			return false;
 		}
 		if(argc>2) {
- 			if(!JS_ValueToInt32(cx,argv[2],&modtime)) {
+ 			if(!JS::ToInt32(cx,argv[2],&modtime)) {
 				free(fname);
 				return false;
 			}
@@ -3225,7 +3214,7 @@ js_utime(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=utime(fname,&ut)==0;
 	free(fname);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 
 	return(true);
 }
@@ -3234,13 +3223,13 @@ js_utime(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_flength(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	off_t		fl;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3250,7 +3239,7 @@ js_flength(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	fl=flength(p);
 	free(p);
-	JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)fl));
+	argv.rval().setNumber((double)fl);
 	return(true);
 }
 
@@ -3258,13 +3247,13 @@ js_flength(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_ftouch(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		fname = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], fname, NULL);
@@ -3274,23 +3263,23 @@ js_ftouch(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=ftouch(fname);
 	free(fname);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_fmutex(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		fname = NULL;
 	char*		text=NULL;
 	int32_t		max_age=0;
 	unsigned		argn=0;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[argn], fname, NULL);
@@ -3298,7 +3287,7 @@ js_fmutex(JSContext *cx, unsigned argc, JS::Value *arglist)
 	HANDLE_PENDING(cx, fname);
 	if(fname==NULL) 
 		return(true);
-	if(argc > argn && JSVAL_IS_STRING(argv[argn])) {
+	if(argc > argn && argv[argn].isString()) {
 		JSVALUE_TO_MSTRING(cx, argv[argn], text, NULL);
 		argn++;
 		if(JS_IsExceptionPending(cx)) {
@@ -3307,8 +3296,8 @@ js_fmutex(JSContext *cx, unsigned argc, JS::Value *arglist)
 			return false;
 		}
 	}
-	if(argc > argn && JSVAL_IS_NUMBER(argv[argn])) {
-		if(!JS_ValueToInt32(cx, argv[argn++], &max_age)) {
+	if(argc > argn && argv[argn].isNumber()) {
+		if(!JS::ToInt32(cx, argv[argn++], &max_age)) {
 			FREE_AND_NULL(text);
 			free(fname);
 			return false;
@@ -3319,26 +3308,26 @@ js_fmutex(JSContext *cx, unsigned argc, JS::Value *arglist)
 	free(fname);
 	if(text)
 		free(text);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 		
 static bool
 js_sound(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret=FALSE;
+	bool		ret=false;
 
 	if(!argc) {	/* Stop playing sound */
 #ifdef _WIN32
 		PlaySound(NULL,NULL,0);
 #endif
-		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(true));
+		argv.rval().setBoolean(true);
 		return(true);
 	}
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3350,7 +3339,7 @@ js_sound(JSContext *cx, unsigned argc, JS::Value *arglist)
 	ret=PlaySound(p, NULL, SND_ASYNC|SND_FILENAME);
 #endif
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 
 	return(true);
 }
@@ -3358,22 +3347,22 @@ js_sound(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_directory(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	int			i;
 	int32_t		flags=GLOB_MARK;
 	char*		p = NULL;
 	glob_t		g;
-	JSObject*	array;
-	JSString*	js_str;
+	JS::RootedObject array(cx);
+	JS::RootedString js_str(cx);
     int       len=0;
-	JS::Value		val;
+	JS::RootedValue		val(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
 	HANDLE_PENDING(cx, p);
@@ -3381,13 +3370,13 @@ js_directory(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&flags)) {
+		if(!JS::ToInt32(cx,argv[1],&flags)) {
 			free(p);
 			return false;
 		}
 	}
 
-    if((array = JS_NewArrayObject(cx, 0, NULL))==NULL) {
+    if((array = JS_NewArrayObject(cx, 0))==NULL) {
 		free(p);
 		return(false);
 	}
@@ -3397,13 +3386,13 @@ js_directory(JSContext *cx, unsigned argc, JS::Value *arglist)
 	for(i=0;i<(int)g.gl_pathc;i++) {
 		if((js_str=JS_NewStringCopyZ(cx,g.gl_pathv[i]))==NULL)
 			break;
-		val=STRING_TO_JSVAL(js_str);
-        if(!JS_SetElement(cx, array, len++, &val))
+		val.setString(js_str);
+        if(!JS_SetElement(cx, array, len++, val))
 			break;
 	}
 	globfree(&g);
 
-    JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
+	argv.rval().setObject(*array);
 
     return(true);
 }
@@ -3411,18 +3400,18 @@ js_directory(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_wildmatch(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	BOOL		case_sensitive=FALSE;
-	BOOL		path=FALSE;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	bool		case_sensitive=false;
+	bool		path=false;
 	char*		fname = NULL;
 	const char	*spec_def="*";
 	char*		spec=(char *)spec_def;
 	unsigned		argn=0;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(JSVAL_IS_BOOLEAN(argv[argn]))
-		JS_ValueToBoolean(cx, argv[argn++], &case_sensitive);
+	if(argv[argn].isBoolean())
+		case_sensitive = JS::ToBoolean(argv[argn++]);
 
 	JSVALUE_TO_MSTRING(cx, argv[argn], fname, NULL);
 	argn++;
@@ -3430,7 +3419,7 @@ js_wildmatch(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(fname==NULL)
 		return(true);
 
-	if(argn<argc && argv[argn]!=JS::UndefinedValue()) {
+	if(argn<argc && !argv[argn].isUndefined()) {
 		JSVALUE_TO_MSTRING(cx, argv[argn], spec, NULL);
 		argn++;
 		if(JS_IsExceptionPending(cx)) {
@@ -3445,13 +3434,13 @@ js_wildmatch(JSContext *cx, unsigned argc, JS::Value *arglist)
 		}
 	}
 
-	if(argn<argc && argv[argn]!=JS::UndefinedValue())
-		JS_ValueToBoolean(cx, argv[argn++], &path);
+	if(argn<argc && !argv[argn].isUndefined())
+		path = JS::ToBoolean(argv[argn++]);
 	
 	if(case_sensitive)
-		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(wildmatch(fname, spec, path)));
+		argv.rval().setBoolean(wildmatch(fname, spec, path));
 	else
-		JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(wildmatchi(fname, spec, path)));
+		argv.rval().setBoolean(wildmatchi(fname, spec, path));
 	free(fname);
 	if(spec != spec_def)
 		free(spec);
@@ -3463,14 +3452,14 @@ js_wildmatch(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_freediskspace(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	int32_t		unit=0;
 	char*		p = NULL;
 	ulong		fd;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3479,7 +3468,7 @@ js_freediskspace(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&unit)) {
+		if(!JS::ToInt32(cx,argv[1],&unit)) {
 			free(p);
 			return false;
 		}
@@ -3487,7 +3476,7 @@ js_freediskspace(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	fd=getfreediskspace(p,unit);
 	free(p);
-	JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)fd));
+	argv.rval().setNumber((double)fd);
 
     return(true);
 }
@@ -3495,14 +3484,14 @@ js_freediskspace(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_disksize(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	int32_t		unit=0;
 	char*		p = NULL;
 	ulong		ds;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3511,7 +3500,7 @@ js_disksize(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToInt32(cx,argv[1],&unit)) {
+		if(!JS::ToInt32(cx,argv[1],&unit)) {
 			free(p);
 			return false;
 		}
@@ -3519,7 +3508,8 @@ js_disksize(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ds=getdisksize(p,unit);
 	free(p);
-	JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)ds));
+
+	argv.rval().setNumber((double)ds);
 
     return(true);
 }
@@ -3527,12 +3517,12 @@ js_disksize(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_socket_select(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	JSObject*	inarray[3]={NULL, NULL, NULL};
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject	inarray[3] = {{cx, NULL}, {cx, NULL}, {cx, NULL}};
 	unsigned		inarray_cnt = 0;
-	JSObject*	robj;
-	JSObject*	rarray;
-	BOOL		poll_for_write=FALSE;
+	JS::RootedObject	robj(cx);
+	JS::RootedObject	rarray(cx);
+	bool		poll_for_write=false;
 	fd_set		socket_set[3];
 	fd_set*		sets[3] = {NULL, NULL, NULL};
 	unsigned		argn;
@@ -3542,29 +3532,30 @@ js_socket_select(JSContext *cx, unsigned argc, JS::Value *arglist)
 	unsigned		i;
 	unsigned		j;
 	unsigned      limit[3];
-	JS::Value		val;
+	JS::RootedValue		val(cx);
 	int			len=0;
-	BOOL	all_zero = TRUE;
+	bool	all_zero = true;
+	bool isarray;
 	const char *props[3] = {"read", "write", "except"};
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
 	for(argn=0;argn<argc;argn++) {
-		if(JSVAL_IS_BOOLEAN(argv[argn]))
-			poll_for_write=JSVAL_TO_BOOLEAN(argv[argn]);
-		else if(JSVAL_IS_OBJECT(argv[argn]))
-			inarray[inarray_cnt++] = JSVAL_TO_OBJECT(argv[argn]);
-		else if(JSVAL_IS_NUMBER(argv[argn]))
+		if(argv[argn].isBoolean())
+			poll_for_write=argv[argn].toBoolean();
+		else if(argv[argn].isObject())
+			inarray[inarray_cnt++] = &argv[argn].toObject();
+		else if(argv[argn].isNumber())
 			js_timeval(cx,argv[argn],&tv);
 	}
 
 	if(inarray_cnt == 0)
 		return(true);	/* This not a fatal error */
 	for (i = 0; i < inarray_cnt; i++) {
-		if (!JS_IsArrayObject(cx, inarray[i]))
+		if (!JS_IsArrayObject(cx, inarray[i], &isarray) || !isarray)
 			return(true);	/* This not a fatal error */
 		if (JS_GetArrayLength(cx, inarray[i], &limit[i]) != 0)
-			all_zero = FALSE;
+			all_zero = false;
 	}
 	if (inarray_cnt > 3)
 		inarray_cnt = 3;
@@ -3574,7 +3565,7 @@ js_socket_select(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	if (inarray_cnt == 1) {
 		/* Return array */
-		if((robj = JS_NewArrayObject(cx, 0, NULL))==NULL)
+		if((robj = JS_NewArrayObject(cx, 0))==NULL)
 			return(false);
 		FD_ZERO(&socket_set[0]);
 		if(poll_for_write)
@@ -3597,21 +3588,21 @@ js_socket_select(JSContext *cx, unsigned argc, JS::Value *arglist)
 				if(!JS_GetElement(cx, inarray[0], i, &val))
 					break;
 				if(js_socket_isset(cx,val,&socket_set[0])) {
-					val=INT_TO_JSVAL(i);
-					if(!JS_SetElement(cx, robj, len++, &val)) {
+					val.setNumber(i);
+					if(!JS_SetElement(cx, robj, len++, val)) {
 						break;
 					}
 				}
 			}
 
-			JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
+			argv.rval().setObject(*robj);
 		}
 
 		return(true);
 	}
 	else {
 		/* Return object */
-		if((robj = JS_NewObject(cx, NULL, NULL, NULL))==NULL)
+		if((robj = JS_NewPlainObject(cx))==NULL)
 			return(false);
 		for (j = 0; j < inarray_cnt; j++) {
 			if (limit[j] > 0) {
@@ -3633,25 +3624,25 @@ js_socket_select(JSContext *cx, unsigned argc, JS::Value *arglist)
 			for (j = 0; j < inarray_cnt; j++) {
 				if (limit[j] > 0) {
 					len = 0;
-					if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL)
+					if((rarray = JS_NewArrayObject(cx, 0))==NULL)
 						return(false);
-					val = OBJECT_TO_JSVAL(rarray);
-					if (!JS_SetProperty(cx, robj, props[j], &val))
+					val.setObject(*rarray);
+					if (!JS_SetProperty(cx, robj, props[j], val))
 						return false;
 					for(i=0;i<limit[j];i++) {
 						if(!JS_GetElement(cx, inarray[j], i, &val)) {
 							break;
 						}
 						if(js_socket_isset(cx,val,&socket_set[j])) {
-							val=INT_TO_JSVAL(i);
-							if(!JS_SetElement(cx, rarray, len++, &val)) {
+							val.setNumber(i);
+							if(!JS_SetElement(cx, rarray, len++, val)) {
 								break;
 							}
 						}
 					}
 				}
 			}
-			JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(robj));
+			argv.rval().setObject(*robj);
 		}
 
 		return(true);
@@ -3664,17 +3655,18 @@ js_socket_strerror(JSContext *cx, unsigned argc, JS::Value *arglist)
  	if(!js_argc(cx, argc, 1))
 		return false;
 
-	JS::Value *argv = JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+
 	int32_t err = 0;
-	if(!JS_ValueToInt32(cx, argv[0], &err))
+	if(!JS::ToInt32(cx, argv[0], &err))
 		return false;
 
 	char		str[256];
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 	if((js_str = JS_NewStringCopyZ(cx, socket_strerror(err, str, sizeof(str)))) == NULL)
 		return false;
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return true;
 }
 
@@ -3684,30 +3676,31 @@ js_strerror(JSContext *cx, unsigned argc, JS::Value *arglist)
  	if(!js_argc(cx, argc, 1))
 		return false;
 
-	JS::Value *argv = JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+
 	int32_t err = 0;
-	if(!JS_ValueToInt32(cx, argv[0], &err))
+	if(!JS::ToInt32(cx, argv[0], &err))
 		return false;
 
 	char		str[256];
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 	if((js_str = JS_NewStringCopyZ(cx, safe_strerror(err, str, sizeof(str)))) == NULL)
 		return false;
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return true;
 }
 
 static bool
 js_mkdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3717,20 +3710,20 @@ js_mkdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=MKDIR(p)==0;
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_mkpath(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3740,20 +3733,20 @@ js_mkpath(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=mkpath(p)==0;
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
 static bool
 js_rmdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
-	BOOL		ret;
+	bool		ret;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3763,7 +3756,7 @@ js_rmdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 	ret=rmdir(p)==0;
 	free(p);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(ret));
+	argv.rval().setBoolean(ret);
 	return(true);
 }
 
@@ -3771,17 +3764,17 @@ js_rmdir(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_strftime(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char		str[128];
 	char*		fmt = NULL;
 	double	jst=(double)time(NULL);
 	time_t		t;
 	struct tm	tm;
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], fmt, NULL);
@@ -3790,7 +3783,7 @@ js_strftime(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 
 	if(argc>1) {
-		if(!JS_ValueToNumber(cx,argv[1],&jst)) {
+		if(!JS::ToNumber(cx,argv[1],&jst)) {
 			free(fmt);
 			return false;
 		}
@@ -3805,7 +3798,7 @@ js_strftime(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if((js_str=JS_NewStringCopyZ(cx, str))==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
@@ -3813,27 +3806,27 @@ js_strftime(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_resolve_ip(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
-	JSString*	str;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedString	str(cx);
 	char*		p=NULL;
 	struct addrinfo	hints,*res,*cur;
 	char		ip_str[INET6_ADDRSTRLEN];
-	BOOL		want_array=FALSE;
-	JSObject	*rarray;
+	bool		want_array=false;
+	JS::RootedObject	rarray(cx);
 	unsigned	alen=0;
 	unsigned		argn;
-	JS::Value		val;
+	JS::RootedValue		val(cx);
 	int			result;
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	for(argn=0; argn < argc; argn++) {
-		if(JSVAL_IS_BOOLEAN(argv[argn]))
-			want_array = JSVAL_TO_BOOLEAN(argv[argn]);
-		else if(JSVAL_IS_STRING(argv[argn])) {
+		if(argv[argn].isBoolean())
+			want_array = argv[argn].toBoolean();
+		else if(argv[argn].isString()) {
 			if(p)
 				free(p);
 			JSVALUE_TO_MSTRING(cx, argv[argn], p, NULL)
@@ -3854,19 +3847,19 @@ js_resolve_ip(JSContext *cx, unsigned argc, JS::Value *arglist)
 	free(p);
 
 	if(want_array) {
-		if((rarray = JS_NewArrayObject(cx, 0, NULL))==NULL) {
+		if((rarray = JS_NewArrayObject(cx, 0))==NULL) {
 			freeaddrinfo(res);
 			return(false);
 		}
-		JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(rarray));
+		argv.rval().setObject(*rarray);
 		for(cur=res; cur; cur=cur->ai_next) {
 			inet_addrtop((union xp_sockaddr *)cur->ai_addr, ip_str, sizeof(ip_str));
 			if((str=JS_NewStringCopyZ(cx, ip_str))==NULL) {
 				freeaddrinfo(res);
 				return(false);
 			}
-			val = STRING_TO_JSVAL(str);
-			if(!JS_SetElement(cx, rarray, alen++, &val))
+			val.setString(str);
+			if(!JS_SetElement(cx, rarray, alen++, val))
 				break;
 		}
 		freeaddrinfo(res);
@@ -3878,7 +3871,7 @@ js_resolve_ip(JSContext *cx, unsigned argc, JS::Value *arglist)
 		if((str=JS_NewStringCopyZ(cx, ip_str))==NULL)
 			return(false);
 
-		JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(str));
+		argv.rval().setString(str);
 	}
 	return(true);
 }
@@ -3887,14 +3880,14 @@ js_resolve_ip(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_resolve_host(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	struct addrinfo	hints,*res;
 	char		host_name[256];
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	JSVALUE_TO_MSTRING(cx, argv[0], p, NULL)
@@ -3917,7 +3910,7 @@ js_resolve_host(JSContext *cx, unsigned argc, JS::Value *arglist)
 		return(true);
 	}
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(JS_NewStringCopyZ(cx,host_name)));
+	argv.rval().setString(JS_NewStringCopyZ(cx,host_name));
 	freeaddrinfo(res);
 
 	return(true);
@@ -3929,29 +3922,30 @@ extern link_list_t named_queues;	/* js_queue.c */
 static bool
 js_list_named_queues(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JSObject*	array;
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject	array(cx);
     int       len=0;
-	JS::Value		val;
+	JS::RootedValue		val(cx);
 	list_node_t* node;
 	msg_queue_t* q;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-    if((array = JS_NewArrayObject(cx, 0, NULL))==NULL)
+    if((array = JS_NewArrayObject(cx, 0))==NULL)
 		return(false);
 
 	listLock(&named_queues);
 	for(node=named_queues.first;node!=NULL;node=node->next) {
 		if((q=(msg_queue_t *)listNodeData(node))==NULL)
 			continue;
-		val=STRING_TO_JSVAL(JS_NewStringCopyZ(cx,q->name));
-        if(!JS_SetElement(cx, array, len++, &val)) {
+		val.setString(JS_NewStringCopyZ(cx,q->name));
+        if(!JS_SetElement(cx, array, len++, val)) {
 			break;
 		}
 	}
 	listUnlock(&named_queues);
 
-    JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(array));
+    argv.rval().setObject(*array);
 
     return(true);
 }
@@ -3959,50 +3953,51 @@ js_list_named_queues(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_flags_str(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		p = NULL;
 	char		str[64];
 	double	d;
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
-	if(JSVAL_IS_STRING(argv[0])) {	/* string to long */
-		JSSTRING_TO_MSTRING(cx, JSVAL_TO_STRING(argv[0]), p, NULL);
+	if(argv[0].isString()) {	/* string to long */
+		JSSTRING_TO_MSTRING(cx, argv[0].toString(), p, NULL);
 		HANDLE_PENDING(cx, p);
 		if(p==NULL) 
 			return(true);
 
-		JS_SET_RVAL(cx, arglist,DOUBLE_TO_JSVAL((double)aftol(p)));
+		argv.rval().setNumber((double)aftol(p));
 		free(p);
 		return(true);
 	}
 
 	/* number to string */
-	JS_ValueToNumber(cx,argv[0],&d);
+	JS::ToNumber(cx,argv[0],&d);
 
 	if((js_str = JS_NewStringCopyZ(cx, ltoaf((long)d,str)))==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 
 static bool
-str_is_utf16(JSContext *cx, JS::Value val)
+str_is_utf16(JSContext *cx, JS::HandleValue val)
 {
-	if(JSVAL_NULL_OR_VOID(val))
+	if(val.isNullOrUndefined())
 		return false;
 
-	JSString* js_str = JS_ValueToString(cx, val);
+	JS::RootedString js_str(cx, val.toString());
 	if(js_str == NULL)
 		return false;
 
 	size_t len;
-	const jschar * str = JS_GetStringCharsAndLength(cx, js_str, &len);
+	JS::AutoCheckCannotGC nogc;
+	const char16_t * str = JS_GetTwoByteStringCharsAndLength(cx, nogc, js_str, &len);
 	if(str == NULL)
 		return false;
 
@@ -4017,31 +4012,32 @@ str_is_utf16(JSContext *cx, JS::Value val)
 static bool
 js_utf8_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	size_t		len;
 	char*		outbuf;
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc==0 || argv[0].isNullOrUndefined())
 		return true;
 
-	if(JSVAL_IS_STRING(argv[0])) {
+	if(argv[0].isString()) {
 		if(str_is_utf16(cx, argv[0])) {
-			js_str = JS_ValueToString(cx, argv[0]);
+			js_str = JS::ToString(cx, argv[0]);
 			if(js_str == NULL)
 				return true;
 
 			size_t inbuf_len;
-			const jschar * inbuf = JS_GetStringCharsAndLength(cx, js_str, &inbuf_len);
+			JS::AutoCheckCannotGC nogc;
+			const char16_t * inbuf = JS_GetTwoByteStringCharsAndLength(cx, nogc, js_str, &inbuf_len);
 			if(inbuf == NULL)
 				return true;
 
 			len = (inbuf_len * UTF8_MAX_LEN) + 1;
 
 			if((outbuf = (char *)malloc(len)) == NULL) {
-				JS_ReportError(cx, "Error allocating %lu bytes at %s:%d"
+				JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d"
 					, len, getfname(__FILE__), __LINE__);
 				return false;
 			}
@@ -4067,7 +4063,7 @@ js_utf8_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 
 			if((outbuf = (char *)malloc(len)) == NULL) {
 				free(inbuf);
-				JS_ReportError(cx, "Error allocating %lu bytes at %s:%d"
+				JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d"
 					, len, getfname(__FILE__), __LINE__);
 				return false;
 			}
@@ -4076,26 +4072,26 @@ js_utf8_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 			free(inbuf);
 		}
 	}
-	else if(JSVAL_IS_NUMBER(argv[0])) {
+	else if(argv[0].isNumber()) {
 		len = UTF8_MAX_LEN + 1;
 		if((outbuf = (char *)malloc(len)) == NULL) {
-			JS_ReportError(cx, "Error allocating %lu bytes at %s:%d"
+			JS_ReportErrorASCII(cx, "Error allocating %lu bytes at %s:%d"
 				, len, getfname(__FILE__), __LINE__);
 			return false;
 		}
 		int32_t codepoint = 0;
-		if(!JS_ValueToInt32(cx, argv[0], &codepoint))
+		if(!JS::ToInt32(cx, argv[0], &codepoint))
 			return false;
 		int result = utf8_putc(outbuf, len - 1, (enum unicode_codepoint)codepoint);
 		if(result < 1) {
 			free(outbuf);
-			JS_ReportError(cx, "utf8_encode: error: %d", result);
+			JS_ReportErrorASCII(cx, "utf8_encode: error: %d", result);
 			return false;
 		}
 		outbuf[result] = 0;
 	}
 	else {
-		JS_ReportError(cx, "utf8_encode: Invalid argument type");
+		JS_ReportErrorASCII(cx, "utf8_encode: Invalid argument type");
 		return false;
 	}
 
@@ -4104,20 +4100,20 @@ js_utf8_encode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return false;
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return true;
 }
 
 static bool
 js_utf8_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		buf = NULL;
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_NULL);
+	argv.rval().setNull();
 
-	if(argc==0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc==0 || argv[0].isNullOrUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], buf, NULL);
@@ -4132,19 +4128,19 @@ js_utf8_decode(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if(js_str==NULL)
 		return false;
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return true;
 }
 
 static bool
 js_utf8_get_width(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		str = NULL;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc==0 || argv[0].isNullOrUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -4155,19 +4151,19 @@ js_utf8_get_width(JSContext *cx, unsigned argc, JS::Value *arglist)
 	size_t width = utf8_str_total_width(str);
 
 	free(str);
-	JS_SET_RVAL(cx, arglist, INT_TO_JSVAL(width));
+	argv.rval().setNumber((double)width);
 	return true;
 }
 
 static bool
 js_str_is_utf8(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		str = NULL;
 
-	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+	argv.rval().setBoolean(false);
 
-	if(argc==0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc==0 || argv[0].isNullOrUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -4178,34 +4174,34 @@ js_str_is_utf8(JSContext *cx, unsigned argc, JS::Value *arglist)
 	bool result = utf8_str_is_valid(str);
 
 	free(str);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));
+	argv.rval().setBoolean(result);
 	return true;
 }
 
 static bool
 js_str_is_utf16(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 
-	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+	argv.rval().setBoolean(false);
 
-	if(argc == 0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc == 0 || argv[0].isNullOrUndefined())
 		return true;
 
 	bool result = str_is_utf16(cx, argv[0]);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));
+	argv.rval().setBoolean(result);
 	return true;
 }
 
 static bool
 js_str_is_ascii(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		str = NULL;
 
-	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+	argv.rval().setBoolean(false);
 
-	if(argc==0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc==0 || argv[0].isNullOrUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -4216,19 +4212,19 @@ js_str_is_ascii(JSContext *cx, unsigned argc, JS::Value *arglist)
 	bool result = str_is_ascii(str);
 
 	free(str);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));
+	argv.rval().setBoolean(result);
 	return true;
 }
 
 static bool
 js_str_has_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JS::Value *argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
 	char*		str = NULL;
 
-	JS_SET_RVAL(cx, arglist, JSVAL_FALSE);
+	argv.rval().setBoolean(false);
 
-	if(argc==0 || JSVAL_NULL_OR_VOID(argv[0]))
+	if(argc==0 || argv[0].isNullOrUndefined())
 		return true;
 
 	JSVALUE_TO_MSTRING(cx, argv[0], str, NULL);
@@ -4239,7 +4235,7 @@ js_str_has_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 	bool result = str_has_ctrl(str);
 
 	free(str);
-	JS_SET_RVAL(cx, arglist, BOOLEAN_TO_JSVAL(result));
+	argv.rval().setBoolean(result);
 	return true;
 }
 
@@ -4248,16 +4244,16 @@ js_str_has_ctrl(JSContext *cx, unsigned argc, JS::Value *arglist)
 static bool
 js_qwknet_route(JSContext *cx, unsigned argc, JS::Value *arglist)
 {
-	JSObject *	obj=JS_THIS_OBJECT(cx, arglist);
-	JS::Value *		argv=JS_ARGV(cx, arglist);
+	JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist);
+	JS::RootedObject	obj=JS_THIS_OBJECT(cx, arglist);
 	char		path[MAX_PATH+1];
 	char*		str;
-	JSString*	js_str;
+	JS::RootedString	js_str(cx);
 	global_private_t* p;
 
-	JS_SET_RVAL(cx, arglist, JS::UndefinedValue());
+	argv.rval().setUndefined();
 
-	if(argc==0 || JSVAL_IS_VOID(argv[0]))
+	if(argc==0 || argv[0].isUndefined())
 		return(true);
 
 	if((p=(global_private_t*)JS_GetPrivate(obj))==NULL)		/* Will this work?  Ask DM */
@@ -4274,7 +4270,7 @@ js_qwknet_route(JSContext *cx, unsigned argc, JS::Value *arglist)
 	if((js_str = JS_NewStringCopyZ(cx, path))==NULL)
 		return(false);
 
-	JS_SET_RVAL(cx, arglist, STRING_TO_JSVAL(js_str));
+	argv.rval().setString(js_str);
 	return(true);
 }
 #endif
@@ -4761,6 +4757,7 @@ static void js_global_finalize(JSFreeOp *fop, JSObject *obj)
 				p->bg_count--; 
 		}
 		sem_destroy(&p->bg_sem);
+		js_DeleteContextCfg(p->cx);
 		free(p);
 	}
 
@@ -4768,22 +4765,22 @@ static void js_global_finalize(JSFreeOp *fop, JSObject *obj)
 	JS_SetPrivate(obj,p);
 }
 
-static bool js_global_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id)
+static bool js_global_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *resolved)
 {
 	char*		name=NULL;
 	global_private_t*	p;
-	bool		ret=true;
 
+	*resolved = true;
 	if((p=(global_private_t*)JS_GetPrivate(obj))==NULL)
 		return(false);
 
 	// TODO: XML stuff obsolete...
 	if(id != JSID_VOID && id != JSID_EMPTY /* && id != JS_DEFAULT_XML_NAMESPACE_ID */) {
-		JS::Value idval;
-		
+		JS::RootedValue idval(cx);;
+
 		JS_IdToValue(cx, id, &idval);
-		if(JSVAL_IS_STRING(idval)) {
-			JSSTRING_TO_MSTRING(cx, JSVAL_TO_STRING(idval), name, NULL);
+		if(idval.isString()) {
+			JSSTRING_TO_MSTRING(cx, idval.toString(), name, NULL);
 			if(JS_IsExceptionPending(cx)) {
 				JS_ClearPendingException(cx);
 				free(name);
@@ -4794,43 +4791,46 @@ static bool js_global_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId
 
 	if(p->methods) {
 		if(js_SyncResolve(cx, obj, name, NULL, p->methods, NULL, 0)==false)
-			ret=false;
+			*resolved=false;
 	}
 	if(js_SyncResolve(cx, obj, name, js_global_properties, js_global_functions, js_global_const_ints, 0)==false)
-		ret=false;
+		*resolved=false;
 	if(name)
 		free(name);
-	return(ret);
+	return(true);
 }
 
 static bool js_global_enumerate(JSContext *cx, JS::HandleObject obj)
 {
-	return(js_global_resolve(cx, obj, JS::JSID_VOIDHANDLE));
+	bool resolved;
+	return(js_global_resolve(cx, obj, JSID_VOIDHANDLE, &resolved));
 }
 
+static JSClassOps js_global_class_ops = {
+	 NULL                /* addProperty */
+	,NULL                /* delProperty */
+	,js_system_get       /* getProperty */
+	,NULL                /* setProperty */
+	,js_global_enumerate /* enumerate   */
+	,js_global_resolve   /* resolve     */
+	,NULL                /* mayResolve  */
+	,js_global_finalize  /* finalize    */
+};
+
 JSClass js_global_class = {
-     "Global"				/* name			*/
-    ,JSCLASS_HAS_PRIVATE|JSCLASS_GLOBAL_FLAGS	/* flags		*/
-	,JS_PropertyStub		/* addProperty	*/
-	,JS_DeletePropertyStub		/* delProperty	*/
-	,js_system_get			/* getProperty	*/
-	,JS_StrictPropertyStub	/* setProperty	*/
-	,js_global_enumerate	/* enumerate	*/
-	,js_global_resolve		/* resolve		*/
-	,JS_ConvertStub			/* convert		*/
-	,js_global_finalize		/* finalize		*/
+     "Global"                                 /* name  */
+    ,JSCLASS_HAS_PRIVATE|JSCLASS_GLOBAL_FLAGS /* flags */
+    ,&js_global_class_ops                     /* cOps  */
 };
 
-BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t* startup, JSObject**glob)
+bool DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t* startup, JSObject **glob)
 {
 	global_private_t*	p;
-	JSRuntime*			rt;
 
-	if((rt=JS_GetRuntime(cx)) != NULL)
-		JS_SetRuntimePrivate(rt, cfg);
+	js_SetContextCfg(cx, cfg);
 
 	if((p = (global_private_t*)malloc(sizeof(global_private_t)))==NULL)
-		return(FALSE);
+		return(false);
 
 	p->cfg = cfg;
 	p->methods = methods;
@@ -4838,46 +4838,41 @@ BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec*
 	p->exit_func=NULL;
 	p->onexit = NULL;
 
-	if((*glob = JS_NewGlobalObject(cx, &js_global_class, NULL)) ==NULL) {
+	JS::CompartmentOptions opts;
+	opts.behaviors().setVersion(JSVERSION_DEFAULT);
+	opts.creationOptions().setSharedMemoryAndAtomicsEnabled(true);
+	JS::RootedObject nglob(cx, JS_NewGlobalObject(cx, &js_global_class, NULL, JS::FireOnNewGlobalHook, opts));
+	*glob = nglob.get();
+	if(*glob == NULL) {
 		free(p);
-		return(FALSE);
-	}
-	if(!JS_AddObjectRoot(cx, glob)) {
-		free(p);
-		return(FALSE);
+		return(false);
 	}
 
-	// TODO: Until version 31, we need to explicitly put glob into a compartment.
-	//       31 and later, a compartment is created by JS_NewGlobalObject()
-	p->oldcompartment = JS_EnterCompartment(cx, *glob);
-	JS_SetPrivate( *glob, p);	/* Store a pointer to scfg_t and the new methods */
+	JS_SetPrivate(*glob, p);	/* Store a pointer to scfg_t and the new methods */
 
-	if (!JS_InitStandardClasses(cx, *glob)) {
-		JS_RemoveObjectRoot(cx, glob);
+	if (!JS_InitStandardClasses(cx, nglob)) {
 		free(p);
-		return(FALSE);
+		return(false);
 	}
 
 	p->bg_count=0;
 	if(sem_init(&p->bg_sem, 0, 0)==-1) {
-		JS_RemoveObjectRoot(cx, glob);
 		free(p);
-		return(FALSE);
+		return(false);
 	}
 
 #ifdef TODO_NO_RESERVED_SLOTS
-	if (!JS_SetReservedSlot(cx, *glob, 0, INT_TO_JSVAL(0))) {
-		JS_RemoveObjectRoot(cx, glob);
+	if (!JS_SetReservedSlot(cx, nglob, 0, INT_TO_JSVAL(0))) {
 		free(p);
-		return(FALSE);
+		return(false);
 	}
 #endif
 
 #ifdef BUILD_JSDOCS
-	js_DescribeSyncObject(cx,*glob
+	js_DescribeSyncObject(cx, nglob
 		,"Top-level functions and properties (common to all servers and services)",310);
 #endif
 
-	return(TRUE);
+	return(true);
 }
 #endif	/* JAVSCRIPT */
diff --git a/src/sbbs3/js_private.cpp b/src/sbbs3/js_private.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..15def895f4303752fc6e6b2e49b2f018d6b748bb
--- /dev/null
+++ b/src/sbbs3/js_private.cpp
@@ -0,0 +1,66 @@
+#include <threadwrap.h>
+#include <link_list.h>
+#include "js_private.h"
+
+static pthread_once_t init_once = PTHREAD_ONCE_INIT;
+static pthread_mutex_t		cfg_mutex;
+static link_list_t	cfg_list;
+
+struct cfg_list_data {
+	JSContext *cx;
+	scfg_t *cfg;
+};
+
+static void init_list(void)
+{
+	listInit(&cfg_list, 0);
+	pthread_mutex_init(&cfg_mutex, NULL);
+	listInit(&cfg_list, LINK_LIST_MUTEX);
+}
+
+// It's not at all clear why we can't use the cfg in the global_private_t...
+
+scfg_t *js_GetContextCfg(JSContext *cx)
+{
+	scfg_t *ret = NULL;
+
+	pthread_once(&init_once, init_list);
+	pthread_mutex_lock(&cfg_mutex);
+	list_node_t *node = listFindNode(&cfg_list, cx, sizeof(cx));
+	if (node) {
+		struct cfg_list_data * d = (struct cfg_list_data *)node->data;
+		ret = d->cfg;
+	}
+	pthread_mutex_unlock(&cfg_mutex);
+	return ret;
+}
+
+void js_SetContextCfg(JSContext *cx, scfg_t *cfg)
+{
+	struct cfg_list_data * d;
+
+	pthread_once(&init_once, init_list);
+	pthread_mutex_lock(&cfg_mutex);
+	list_node_t *node = listFindNode(&cfg_list, cx, sizeof(cx));
+	if (node) {
+		d = (struct cfg_list_data *)node->data;
+		d->cfg = cfg;
+	}
+	else {
+		d = (struct cfg_list_data *)calloc(1, sizeof (struct cfg_list_data));
+		d->cx = cx;
+		d->cfg = cfg;
+		listPushNode(&cfg_list, d);
+	}
+	pthread_mutex_unlock(&cfg_mutex);
+}
+
+void js_DeleteContextCfg(JSContext *cx)
+{
+	pthread_once(&init_once, init_list);
+	pthread_mutex_lock(&cfg_mutex);
+	list_node_t *node = listFindNode(&cfg_list, cx, sizeof(cx));
+	if (node)
+		listRemoveNode(&cfg_list, node, FALSE);
+	pthread_mutex_unlock(&cfg_mutex);
+}
diff --git a/src/sbbs3/js_private.h b/src/sbbs3/js_private.h
new file mode 100644
index 0000000000000000000000000000000000000000..56cbe2b74d89a10c24b91416367e59bac2def3b2
--- /dev/null
+++ b/src/sbbs3/js_private.h
@@ -0,0 +1,15 @@
+#ifndef JS_PRIVATE_H
+#define JS_PRIVATE_H
+
+#ifdef __cplusplus
+
+#include <jsapi.h>
+#include "scfgdefs.h"
+
+scfg_t *js_GetContextCfg(JSContext *cx);
+void js_SetContextCfg(JSContext *cx, scfg_t *cfg);
+void js_DeleteContextCfg(JSContext *cx);
+
+#endif
+
+#endif
diff --git a/src/sbbs3/objects.mk b/src/sbbs3/objects.mk
index ca9c0d657fc1c4d82a66f3f91314485df78c2bf0..358d72390535e67ee0813bc4589f8acb4ac52cb0 100644
--- a/src/sbbs3/objects.mk
+++ b/src/sbbs3/objects.mk
@@ -40,6 +40,7 @@ OBJS	=	$(MTOBJODIR)$(DIRSEP)ansiterm$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)getstr$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)inkey$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)ident$(OFILE)\
+			$(MTOBJODIR)$(DIRSEP)js_private$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_bbs$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_client$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_com$(OFILE)\
@@ -245,6 +246,7 @@ JSDOOR_OBJS = \
 			$(MTOBJODIR)$(DIRSEP)date_str$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)dat_rec$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)jsdoor$(OFILE) \
+			$(MTOBJODIR)$(DIRSEP)js_private$(OFILE)\
 			$(MTOBJODIR)$(DIRSEP)js_uifc$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)js_conio$(OFILE) \
 			$(MTOBJODIR)$(DIRSEP)js_request$(OFILE) \
diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h
index 7d2cc271001a1e7c5bf1c5a1f8479b9313b7c03f..c7ce1baafa6084eb9de4a0de0390282614148aad 100644
--- a/src/sbbs3/sbbs.h
+++ b/src/sbbs3/sbbs.h
@@ -1357,10 +1357,10 @@ extern char lastuseron[LEN_ALIAS+1];  /* Name of user last online */
 		sem_t				bg_sem;
 		str_list_t			exit_func;
 		struct js_onexit_scope	*onexit;
-		JSCompartment *oldcompartment;
+		JSContext *cx;
 	} global_private_t;
-	DLLEXPORT BOOL DLLCALL js_argc(JSContext *cx, unsigned argc, unsigned min);
-	DLLEXPORT BOOL DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t*, JS::HandleObject*);
+	DLLEXPORT bool DLLCALL js_argc(JSContext *cx, unsigned argc, unsigned min);
+	DLLEXPORT bool DLLCALL js_CreateGlobalObject(JSContext* cx, scfg_t* cfg, jsSyncMethodSpec* methods, js_startup_t*, JSObject**);
 
 	/* js_internal.c */
 	DLLEXPORT JS::HandleObject DLLCALL js_CreateInternalJsObject(JSContext*, JS::HandleObject parent, js_callback_t*, js_startup_t*);