diff --git a/src/sbbs3/js_global.cpp b/src/sbbs3/js_global.cpp index ef287cba5c04ea27c31c37f53c97173db9ba7348..665a3cb26ce14c02462a8aaed72204c504c9fece 100644 --- a/src/sbbs3/js_global.cpp +++ b/src/sbbs3/js_global.cpp @@ -232,7 +232,7 @@ 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::HandleValue js_CopyValue(JSContext* cx, JS::HandleValue val, JSContext* new_cx, JS::MutableHandleValue rval) +JS::HandleValue DLLCALL js_CopyValue(JSContext* cx, JS::HandleValue val, JSContext* new_cx, JS::MutableHandleValue rval) { JS::StructuredCloneScope scope(JS::StructuredCloneScope::SameProcessSameThread); JSStructuredCloneData nval(scope); diff --git a/src/sbbs3/js_internal.cpp b/src/sbbs3/js_internal.cpp index c318f7003ba1552728e40ff55f7a3a7f51a99052..4472320d8428f7d7ea8a4a5c799455057e39584a 100644 --- a/src/sbbs3/js_internal.cpp +++ b/src/sbbs3/js_internal.cpp @@ -37,9 +37,7 @@ #include "sbbs.h" #include "js_request.h" - -/* SpiderMonkey: */ -#include <jsdbgapi.h> +#include "js_rtpool.h" enum { PROP_VERSION @@ -61,7 +59,7 @@ enum { static JSObject *getCurrentCompartmentGlobalObject(JSContext *cx) { - JSObject *obj = JS_NewObject(cx, NULL, NULL, NULL); + JS::RootedObject obj(cx, JS_NewPlainObject(cx)); JSCompartment *c; c = JS_EnterCompartment(cx, obj); @@ -71,92 +69,92 @@ static JSObject *getCurrentCompartmentGlobalObject(JSContext *cx) static bool js_get(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp) { - JS::Value idval; - int tiny; + JS::RootedValue idval(cx); + int32_t tiny; js_callback_t* cb; js_callback_t* top_cb; if((cb=(js_callback_t*)JS_GetPrivate(obj))==NULL) return(false); - JS_IdToValue(cx, id, &idval); - tiny = JSVAL_TO_INT(idval); + JS_IdToValue(cx, id, &idval); + tiny = idval.toInt32(); switch(tiny) { case PROP_VERSION: - vp.set(STRING_TO_JSVAL(JS_NewStringCopyZ(cx,(char *)JS_GetImplementationVersion()))); + vp.setString(JS_NewStringCopyZ(cx,(char *)JS_GetImplementationVersion())); break; case PROP_TERMINATED: for(top_cb=cb; top_cb->bg && top_cb->parent_cb; top_cb=top_cb->parent_cb) { if(top_cb->terminated && *top_cb->terminated) { - vp.set(BOOLEAN_TO_JSVAL(TRUE)); + vp.setBoolean(true); return true; } } if(top_cb->terminated==NULL) - vp.set(JSVAL_FALSE); + vp.setBoolean(false); else - vp.set(BOOLEAN_TO_JSVAL(*top_cb->terminated)); + vp.setBoolean(*top_cb->terminated); break; case PROP_AUTO_TERMINATE: - vp.set(BOOLEAN_TO_JSVAL(cb->auto_terminate)); + vp.setBoolean(cb->auto_terminate); break; case PROP_COUNTER: - vp.set(DOUBLE_TO_JSVAL((double)cb->counter)); + vp.setNumber((double)cb->counter); break; case PROP_TIME_LIMIT: - vp.set(DOUBLE_TO_JSVAL(cb->limit)); + vp.setNumber(cb->limit); break; case PROP_YIELD_INTERVAL: - vp.set(DOUBLE_TO_JSVAL((double)cb->yield_interval)); + vp.setNumber((double)cb->yield_interval); break; case PROP_GC_INTERVAL: - vp.set(DOUBLE_TO_JSVAL((double)cb->gc_interval)); + vp.setNumber((double)cb->gc_interval); break; case PROP_GC_ATTEMPTS: - vp.set(DOUBLE_TO_JSVAL((double)cb->gc_attempts)); + vp.setNumber((double)cb->gc_attempts); break; #ifdef jscntxt_h___ case PROP_GC_COUNTER: - vp.set(UINT_TO_JSVAL(cx->runtime->gcNumber)); + vp.setNumber(cx->runtime->gcNumber); break; case PROP_GC_LASTBYTES: - vp.set(DOUBLE_TO_JSVAL((double)cx->runtime->gcLastBytes)); + vp.setNumber((double)cx->runtime->gcLastBytes); break; case PROP_BYTES: - vp.set(DOUBLE_TO_JSVAL((double)cx->runtime->gcBytes)); + vp.setNumber((double)cx->runtime->gcBytes); break; case PROP_MAXBYTES: - vp.set(DOUBLE_TO_JSVAL((double)cx->runtime->gcMaxBytes)); + vp.setNumber((double)cx->runtime->gcMaxBytes); break; #endif case PROP_GLOBAL: - vp.set(OBJECT_TO_JSVAL(getCurrentCompartmentGlobalObject(cx))); + vp.setObject(*getCurrentCompartmentGlobalObject(cx)); break; } return(true); } -static bool js_set(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool strict, JS::MutableHandleValue vp) +static bool js_set(JSContext *cx, JS::HandleObject obj, JS::HandleId id, JS::MutableHandleValue vp, JS::ObjectOpResult &result) { - JS::Value idval; - int tiny; + JS::RootedValue idval(cx); + int32_t tiny; js_callback_t* cb; if((cb=(js_callback_t*)JS_GetPrivate(obj))==NULL) return(false); - JS_IdToValue(cx, id, &idval); - tiny = JSVAL_TO_INT(idval); + JS_IdToValue(cx, id, &idval); + tiny = idval.toInt32(); switch(tiny) { case PROP_TERMINATED: if(cb->terminated!=NULL) - *cb->terminated = JS::ToBoolean(vp); + *cb->terminated = vp.toBoolean(); break; case PROP_AUTO_TERMINATE: - cb->auto_terminate = JS::ToBoolean(vp); + cb->auto_terminate = vp.toBoolean(); break; case PROP_COUNTER: if(!JS::ToInt32(cx, vp, (int32_t*)&cb->counter)) @@ -182,6 +180,7 @@ static bool js_set(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool st #endif } + result.succeed(); return(true); } @@ -256,7 +255,7 @@ js_CommonInterruptCallback(JSContext *cx, js_callback_t* cb) if(cb->auto_terminate) { for(top_cb=cb; top_cb; top_cb=top_cb->parent_cb) { if (top_cb->terminated!=NULL && *top_cb->terminated) { - JS_ReportWarning(cx,"Terminated"); + JS_ReportWarningASCII(cx,"Terminated"); cb->counter=0; return(false); } @@ -265,7 +264,7 @@ js_CommonInterruptCallback(JSContext *cx, js_callback_t* cb) /* Infinite loop? */ if(cb->limit && cb->counter > cb->limit) { - JS_ReportError(cx,"Infinite loop (%lu operation callbacks) detected",cb->counter); + JS_ReportErrorASCII(cx,"Infinite loop (%" PRIu32 " operation callbacks) detected",cb->counter); cb->counter=0; return(false); } @@ -284,7 +283,7 @@ js_CommonInterruptCallback(JSContext *cx, js_callback_t* cb) } // This is kind of halfway between js_execfile() in exec.cpp and js_load -static int +static bool js_execfile(JSContext *cx, unsigned argc, JS::Value *arglist) { char* cmd = NULL; @@ -293,76 +292,72 @@ js_execfile(JSContext *cx, unsigned argc, JS::Value *arglist) char* startup_dir = NULL; unsigned arg=0; char path[MAX_PATH+1] = ""; - JSObject* js_scope = NULL; - JSObject* pscope; - JSScript* js_script=NULL; - JSObject* nargv; - JS::Value rval; + JS::RootedObject js_scope(cx, NULL); + JS::RootedObject pscope(cx); + JS::RootedScript js_script(cx, NULL); + JS::RootedObject nargv(cx); + JS::RootedValue rval(cx); unsigned i; - JS::Value val; - JSObject *js_obj; - JSObject *pjs_obj; + JS::RootedValue val(cx); + JS::RootedObject js_obj(cx); + JS::RootedObject pjs_obj(cx); js_callback_t * js_callback; JS::CallArgs args = JS::CallArgsFromVp(argc, arglist); - JSObject* scope = JS_GetGlobalForObject(cx, &args.callee()); + JS::RootedObject scope(cx, JS_GetGlobalForObject(cx, &args.callee())); if(argc<1) { - JS_ReportError(cx, "No filename passed"); + JS_ReportErrorASCII(cx, "No filename passed"); return(false); } - JS::Value *argv=JS_ARGV(cx, arglist); + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); - if (!JSVAL_IS_STRING(argv[arg])) { - JS_ReportError(cx, "Invalid script name"); + if (!argv[arg].isString()) { + JS_ReportErrorASCII(cx, "Invalid script name"); return(false); } JSVALUE_TO_MSTRING(cx, argv[arg++], cmd, NULL); HANDLE_PENDING(cx, cmd); if (cmd == NULL) { - JS_ReportError(cx, "Invalid NULL string"); + JS_ReportErrorASCII(cx, "Invalid NULL string"); return(false); } if (argc > arg) { - if (JSVAL_IS_STRING(argv[arg])) { + if (argv[arg].isString()) { JSVALUE_TO_MSTRING(cx, argv[arg++], startup_dir, &cmdlen); HANDLE_PENDING(cx, cmd); if(startup_dir == NULL) { free(cmd); - JS_ReportError(cx, "Invalid NULL string"); + JS_ReportErrorASCII(cx, "Invalid NULL string"); return(false); } } } - if (argc > arg && JSVAL_IS_OBJECT(argv[arg])) { - js_scope = JSVAL_TO_OBJECT(argv[arg++]); + if (argc > arg && argv[arg].isObject()) { + js_scope = &argv[arg++].toObject(); if (js_scope == scope) { free(cmd); free(startup_dir); - JS_ReportError(cx, "Invalid Scope"); + JS_ReportErrorASCII(cx, "Invalid Scope"); return(false); } } else { free(cmd); free(startup_dir); - JS_ReportError(cx, "Invalid Scope"); + JS_ReportErrorASCII(cx, "Invalid Scope"); return(false); } - pscope = scope; - while ((!JS_GetProperty(cx, pscope, "js", &val) || val==JS::UndefinedValue() || !JSVAL_IS_OBJECT(val)) && pscope != NULL) { - pscope = JS_GetParent(pscope); - if (pscope == NULL) { - free(cmd); - free(startup_dir); - JS_ReportError(cx, "Walked to global, no js object!"); - return false; - } + if (!JS_GetProperty(cx, scope, "js", &val) || val.isUndefined() || !val.isObject()) { + free(cmd); + free(startup_dir); + JS_ReportErrorASCII(cx, "Unable to locate js object!"); + return false; } - pjs_obj = JSVAL_TO_OBJECT(val); + pjs_obj = &val.toObject(); js_callback = (js_callback_t *)JS_GetPrivate(pjs_obj); if(isfullpath(cmd)) @@ -379,7 +374,7 @@ js_execfile(JSContext *cx, unsigned argc, JS::Value *arglist) // Then check js.exec_dir /* if js.exec_dir is defined (location of executed script), search there first */ if (*path == 0) { - if(JS_GetProperty(cx, pjs_obj, "exec_dir", &val) && val!=JS::UndefinedValue() && JSVAL_IS_STRING(val)) { + if(JS_GetProperty(cx, pjs_obj, "exec_dir", &val) && val!=JS::UndefinedValue() && val.isString()) { JSVALUE_TO_STRBUF(cx, val, path, sizeof(path), &pathlen); strncat(path, cmd, sizeof(path)-pathlen-1); if(!fexistcase(path)) @@ -390,93 +385,103 @@ js_execfile(JSContext *cx, unsigned argc, JS::Value *arglist) free(cmd); if(!fexistcase(path)) { - JS_ReportError(cx, "Script file (%s) does not exist", path); + JS_ReportErrorASCII(cx, "Script file (%s) does not exist", path); free(startup_dir); return false; } - nargv=JS_NewArrayObject(cx, 0, NULL); + nargv=JS_NewArrayObject(cx, 0); - JS_DefineProperty(cx, js_scope, "argv", OBJECT_TO_JSVAL(nargv) - ,NULL,NULL,JSPROP_READONLY|JSPROP_ENUMERATE); + JS_DefineProperty(cx, js_scope, "argv", nargv + ,JSPROP_READONLY|JSPROP_ENUMERATE); unsigned nargc = 0; for(i=arg; i<argc; i++) { - JS_SetElement(cx, nargv, nargc, &argv[i]); + JS_SetElement(cx, nargv, nargc, argv[i]); nargc++; } - JS_DefineProperty(cx, js_scope, "argc", INT_TO_JSVAL(nargc) - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_DefineProperty(cx, js_scope, "argc", nargc + ,JSPROP_ENUMERATE|JSPROP_READONLY); js_obj = js_CreateInternalJsObject(cx, js_scope, js_callback, NULL); js_PrepareToExecute(cx, js_scope, path, startup_dir, js_scope); free(startup_dir); // Copy in the load_path_list... if(pjs_obj != NULL) { - JSObject* pload_path_list; - JSObject* load_path_list; + JS::RootedObject pload_path_list(cx); + JS::RootedObject load_path_list(cx); uint32_t plen; uint32_t pcnt; + bool isarray; - if (JS_GetProperty(cx, pjs_obj, JAVASCRIPT_LOAD_PATH_LIST, &val) && val!=JS::UndefinedValue() && JSVAL_IS_OBJECT(val)) { - pload_path_list = JSVAL_TO_OBJECT(val); - if (!JS_IsArrayObject(cx, pload_path_list)) { - JS_ReportError(cx, "Weird js." JAVASCRIPT_LOAD_PATH_LIST " value"); + if (JS_GetProperty(cx, pjs_obj, JAVASCRIPT_LOAD_PATH_LIST, &val) && val!=JS::UndefinedValue() && val.isObject()) { + pload_path_list = &val.toObject(); + if (!JS_IsArrayObject(cx, pload_path_list, &isarray) || !isarray) { + JS_ReportErrorASCII(cx, "Weird js." JAVASCRIPT_LOAD_PATH_LIST " value"); return false; } - if((load_path_list=JS_NewArrayObject(cx, 0, NULL))==NULL) { - JS_ReportError(cx, "Unable to create js." JAVASCRIPT_LOAD_PATH_LIST); + if((load_path_list=JS_NewArrayObject(cx, 0))==NULL) { + JS_ReportErrorASCII(cx, "Unable to create js." JAVASCRIPT_LOAD_PATH_LIST); return false; } - val = OBJECT_TO_JSVAL(load_path_list); - JS_SetProperty(cx, js_obj, JAVASCRIPT_LOAD_PATH_LIST, &val); + val.setObject(*load_path_list); + JS_SetProperty(cx, js_obj, JAVASCRIPT_LOAD_PATH_LIST, val); JS_GetArrayLength(cx, pload_path_list, &plen); for (pcnt = 0; pcnt < plen; pcnt++) { JS_GetElement(cx, pload_path_list, pcnt, &val); - JS_SetElement(cx, load_path_list, pcnt, &val); + JS_SetElement(cx, load_path_list, pcnt, val); } } else { - JS_ReportError(cx, "Unable to get parent js." JAVASCRIPT_LOAD_PATH_LIST " array."); + JS_ReportErrorASCII(cx, "Unable to get parent js." JAVASCRIPT_LOAD_PATH_LIST " array."); return false; } } else { - JS_ReportError(cx, "Unable to get parent js object"); + JS_ReportErrorASCII(cx, "Unable to get parent js object"); return false; } JS::CompileOptions options(cx); options.setFileAndLine(path, 1); - js_script = JS::Compile(cx, JS::RootedObject(cx, js_scope), options, path); + bool compiled = JS::Compile(cx, options, path, &js_script); - if(js_script == NULL) { + if(!compiled) { /* If the script fails to compile, it's not a fatal error * for the caller. */ if (JS_IsExceptionPending(cx)) { JS_GetPendingException(cx, &rval); - JS_SET_RVAL(cx, arglist, rval); + argv.rval().set(rval); } JS_ClearPendingException(cx); return(true); } - JS_ExecuteScript(cx, js_scope, js_script, &rval); + JS::AutoObjectVector js_vscope(cx); + js_vscope.append(js_scope); + JS_ExecuteScript(cx, js_vscope, js_script, &rval); if (JS_IsExceptionPending(cx)) { JS_GetPendingException(cx, &rval); } else { JS_GetProperty(cx, js_scope, "exit_code", &rval); } - JS_SET_RVAL(cx, arglist, rval); + argv.rval().set(rval); JS_ClearPendingException(cx); js_EvalOnExit(cx, js_scope, js_callback); - JS_ReportPendingException(cx); + if (JS_IsExceptionPending(cx)) { + JS::RootedValue vp(cx); + + if (JS_GetPendingException(cx, &vp)) { + JS::RootedObject err(cx, &vp.toObject()); + JS::GetWarningReporter(cx)(cx, JS_ErrorFromException(cx, err)); + } + JS_ClearPendingException(cx); + } JS_DestroyScript(cx, js_script); - // TODO: Can't garbage collect a context in 24... comes back in 52 though. - JS_MaybeGC(cx); + JS_GC(cx); return true; } @@ -484,69 +489,71 @@ js_execfile(JSContext *cx, unsigned argc, JS::Value *arglist) static JSClass eval_class = { "Global", /* name */ JSCLASS_GLOBAL_FLAGS, /* flags */ - JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, - JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, NULL, - JSCLASS_NO_OPTIONAL_MEMBERS }; /* Execute a string in its own context (away from Synchronet objects) */ static bool js_eval(JSContext *parent_cx, unsigned argc, JS::Value *arglist) { - JS::Value *argv=JS_ARGV(parent_cx, arglist); + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); char* buf = NULL; size_t buflen; - JSString* str; - JSScript* script; + JS::RootedString str(parent_cx); JSContext* cx; - JSObject* obj; - JSErrorReporter reporter; - JS_SET_RVAL(cx, arglist, JS::UndefinedValue()); + argv.rval().setUndefined(); if(argc<1) return(true); - if((str=JS_ValueToString(parent_cx, argv[0]))==NULL) + if((str=JS::ToString(parent_cx, argv[0]))==NULL) return(false); JSSTRING_TO_MSTRING(parent_cx, str, buf, &buflen); HANDLE_PENDING(parent_cx, buf); if(buf==NULL) return(true); - if((cx=JS_NewContext(JS_GetRuntime(parent_cx),JAVASCRIPT_CONTEXT_STACK))==NULL) { + if((cx=JS_NewContext(JAVASCRIPT_CONTEXT_STACK, JS::DefaultNurseryBytes, parent_cx))==NULL) { free(buf); return(false); } /* Use the error reporter from the parent context */ - reporter=JS_SetErrorReporter(parent_cx,NULL); - JS_SetErrorReporter(parent_cx,reporter); - JS_SetErrorReporter(cx,reporter); + JS::SetWarningReporter(parent_cx,JS::GetWarningReporter(parent_cx)); /* Use the operation callback from the parent context */ JS_SetContextPrivate(cx, JS_GetContextPrivate(parent_cx)); - JS_AddInterruptCallback(cx, JS_GetInterruptCallback(parent_cx)); + // TODO: No way to get the parents InterruptCallback... + //JS_AddInterruptCallback(cx, JS_GetInterruptCallback(parent_cx)); + + JS::CompartmentOptions opts; + opts.behaviors().setVersion(JSVERSION_DEFAULT); + opts.creationOptions().setSharedMemoryAndAtomicsEnabled(true); - if((obj=JS_NewGlobalObject(cx, &eval_class, NULL))==NULL) { + JS::RootedObject obj(cx); + if((obj=JS_NewGlobalObject(cx, &eval_class, NULL, JS::FireOnNewGlobalHook, opts))==NULL) { + JS_DestroyContext(cx); + free(buf); + return(false); + } + if(!JS_InitStandardClasses(cx,obj)) { JS_DestroyContext(cx); free(buf); return(false); } - { // Scope for auto compartment... - JSAutoCompartment ac(cx, obj); - if(!JS_InitStandardClasses(cx,obj)) { - JS_DestroyContext(cx); - free(buf); - return(false); - } - - if((script=JS_CompileScript(cx, obj, buf, buflen, NULL, 0))!=NULL) { - JS::Value rval; - JS_ExecuteScript(cx, obj, script, &rval); - JS_SET_RVAL(cx, arglist, rval); - } + JS::CompileOptions options(cx); + options.setFileAndLine("js.eval", 1); + JS::RootedScript script(cx); + if(JS::Compile(cx, options, buf, buflen, &script)) { + JS::RootedValue rval(cx); + JS::RootedValue prval(parent_cx); + JS::AutoObjectVector js_vscope(cx); + + js_vscope.append(obj); + JS_ExecuteScript(cx, js_vscope, script, &rval); + js_CopyValue(cx, rval, parent_cx, &prval); + argv.rval().set(prval); } free(buf); @@ -558,23 +565,22 @@ js_eval(JSContext *parent_cx, unsigned argc, JS::Value *arglist) static bool js_gc(JSContext *cx, unsigned argc, JS::Value *arglist) { - JSObject *obj=JS_THIS_OBJECT(cx, arglist); - JS::Value *argv=JS_ARGV(cx, arglist); + JS::RootedObject obj(cx, JS_THIS_OBJECT(cx, arglist)); + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); bool forced=true; js_callback_t* cb; - JS_SET_RVAL(cx, arglist, JS::UndefinedValue()); - if((cb=(js_callback_t*)JS_GetPrivate(obj))==NULL) return(false); + argv.rval().setUndefined(); + if(argc) - JS_ValueToBoolean(cx,argv[0],&forced); + forced = argv[0].toBoolean(); - // TODO: Can't garbage collect a context in 24... comes back in 52 though. - //if(forced) - // JS_GC(cx); - //else + if(forced) + JS_GC(cx); + else JS_MaybeGC(cx); cb->gc_attempts++; @@ -585,40 +591,40 @@ js_gc(JSContext *cx, unsigned argc, JS::Value *arglist) static bool js_report_error(JSContext *cx, unsigned argc, JS::Value *arglist) { - JS::Value *argv=JS_ARGV(cx, arglist); + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); char *p = NULL; JSVALUE_TO_MSTRING(cx, argv[0], p, NULL); HANDLE_PENDING(cx, p); if(p==NULL) - JS_ReportError(cx,"NULL"); + JS_ReportErrorASCII(cx,"NULL"); else { - JS_ReportError(cx,"%s",p); + JS_ReportErrorASCII(cx,"%s",p); free(p); } - JS_SET_RVAL(cx, arglist, JS::UndefinedValue()); - - if(argc>1 && argv[1]==JSVAL_TRUE) + if(argc>1 && argv[1].toBoolean()) return(false); /* fatal */ + argv.rval().setUndefined(); + return(true); } static bool js_on_exit(JSContext *cx, unsigned argc, JS::Value *arglist) { - JSObject *glob=getCurrentCompartmentGlobalObject(cx); - JS::Value *argv=JS_ARGV(cx, arglist); + JS::RootedObject glob(cx, getCurrentCompartmentGlobalObject(cx)); + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); global_private_t* pd; struct js_onexit_scope *oes = NULL; str_list_t oldlist; str_list_t list; char *p = NULL; JS::CallArgs args = JS::CallArgsFromVp(argc, arglist); - JSObject* scope = JS_GetGlobalForObject(cx, &args.callee()); + JS::RootedObject scope(cx, JS_GetGlobalForObject(cx, &args.callee())); - JS_SET_RVAL(cx, arglist, JS::UndefinedValue()); + argv.rval().setUndefined(); if((pd=(global_private_t*)JS_GetPrivate(glob))==NULL) return(false); @@ -638,14 +644,13 @@ js_on_exit(JSContext *cx, unsigned argc, JS::Value *arglist) if (oes == NULL) { oes = (struct js_onexit_scope *)malloc(sizeof(*oes)); if (oes == NULL) { - JS_ReportError(cx, "Unable to allocate memory for onexit scope"); + JS_ReportErrorASCII(cx, "Unable to allocate memory for onexit scope"); return false; } oes->next = pd->onexit; pd->onexit = oes; - oes->scope = scope; + oes->scope = scope.get(); oes->onexit = strListInit(); - JS_AddObjectRoot(cx, &oes->scope); } list = oes->onexit; } @@ -666,34 +671,36 @@ js_on_exit(JSContext *cx, unsigned argc, JS::Value *arglist) return(true); } +#ifdef TODO_BATMAN static bool js_get_parent(JSContext *cx, unsigned argc, JS::Value *arglist) { - JS::Value *argv=JS_ARGV(cx, arglist); - JSObject* child=NULL; - JSObject* parent; + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); + JS::RootedObject child(cx, NULL); + JS::RootedObject parent(cx); - if(JS_ValueToObject(cx, argv[0], &child) + if((child = JS::ToObject(cx, argv[0])) != NULL && child!=NULL && (parent=JS_GetParent(child))!=NULL) JS_SET_RVAL(cx, arglist, OBJECT_TO_JSVAL(parent)); return(true); } +#endif static bool js_getsize(JSContext *cx, unsigned argc, JS::Value *arglist) { - JS::Value *argv=JS_ARGV(cx, arglist); - JSObject* tmp_obj; + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); + JS::RootedObject tmp_obj(cx); - JS_ReportError(cx, "get_size() no longer functional."); + JS_ReportErrorASCII(cx, "get_size() no longer functional."); return false; #ifdef TODO_GETOBJECTTOTALSIZE - if(!JSVAL_IS_OBJECT(argv[0])) { - JS_ReportError(cx, "get_size() error! Parameter is not an object."); + if(!argv[0].isObject()) { + JS_ReportErrorASCII(cx, "get_size() error! Parameter is not an object."); return(false); } - tmp_obj=JSVAL_TO_OBJECT(argv[0]); + tmp_obj=argv[0].toObject(); if(!tmp_obj) return(false); JS_SET_RVAL(cx, arglist, DOUBLE_TO_JSVAL(JS_GetObjectTotalSize(cx, tmp_obj))); @@ -703,14 +710,14 @@ static bool js_getsize(JSContext *cx, unsigned argc, JS::Value *arglist) static bool js_flatten(JSContext *cx, unsigned argc, JS::Value *arglist) { - JS::Value *argv=JS_ARGV(cx, arglist); + JS::CallArgs argv = JS::CallArgsFromVp(argc, arglist); - if(!JSVAL_IS_STRING(argv[0])) { - JS_ReportError(cx, "get_size() error! Parameter is not a string."); + if(!argv[0].isString()) { + JS_ReportErrorASCII(cx, "get_size() error! Parameter is not a string."); return(false); } - JS_FlattenString(cx, JSVAL_TO_STRING(argv[0])); - JS_SET_RVAL(cx, arglist, JS::UndefinedValue()); + JS_FlattenString(cx, argv[0].toString()); + argv.rval().setUndefined(); return(true); } @@ -735,10 +742,12 @@ static jsSyncMethodSpec js_functions[] = { "if <i>fatal</i> is <i>true</i>, immediately terminates script") ,313 }, +#ifdef TODO_BATMAN {"get_parent", js_get_parent, 1, JSTYPE_OBJECT, JSDOCSTR("object") ,JSDOCSTR("return the parent of the specified object") ,314 }, +#endif {"get_size", js_getsize, 1, JSTYPE_NUMBER, JSDOCSTR("[object]") ,JSDOCSTR("return the size in bytes the object uses in memory (forces GC) ") ,316 @@ -759,52 +768,54 @@ static jsSyncMethodSpec js_functions[] = { {0} }; -static bool js_internal_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id) +static bool js_internal_resolve(JSContext *cx, JS::HandleObject obj, JS::HandleId id, bool *resolved) { char* name=NULL; - bool ret; if(id != JSID_VOID && id != JSID_EMPTY) { - 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); HANDLE_PENDING(cx, name); } } - ret=js_SyncResolve(cx, obj, name, js_properties, js_functions, NULL, 0); + *resolved = js_SyncResolve(cx, obj, name, js_properties, js_functions, NULL, 0); if(name) free(name); - return(ret); + return(true); } static bool js_internal_enumerate(JSContext *cx, JS::HandleObject obj) { - return(js_internal_resolve(cx, obj, JS::JSID_VOIDHANDLE)); + bool resolved; + return(js_internal_resolve(cx, obj, JSID_VOIDHANDLE, &resolved)); } -static JSClass js_internal_class = { - "JsInternal" /* name */ - ,JSCLASS_HAS_PRIVATE /* flags */ - ,JS_PropertyStub /* addProperty */ - ,JS_DeletePropertyStub /* delProperty */ +static JSClassOps js_internal_class_ops = { + NULL /* addProperty */ + ,NULL /* delProperty */ ,js_get /* getProperty */ ,js_set /* setProperty */ ,js_internal_enumerate /* enumerate */ ,js_internal_resolve /* resolve */ - ,JS_ConvertStub /* convert */ - ,NULL /* finalize */ }; -void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) +static JSClass js_internal_class = { + "JsInternal" /* name */ + ,JSCLASS_HAS_PRIVATE /* flags */ + ,&js_internal_class_ops +}; + +void DLLCALL js_EvalOnExit(JSContext *cx, JS::HandleObject obj, js_callback_t* cb) { char* p; - JS::Value rval; + JS::RootedValue rval(cx); JSScript* script; BOOL auto_terminate=cb->auto_terminate; - JSObject *glob=getCurrentCompartmentGlobalObject(cx); + JS::RootedObject glob(cx, getCurrentCompartmentGlobalObject(cx)); global_private_t *pt; str_list_t list = NULL; struct js_onexit_scope **prev_oes_next = NULL; @@ -816,7 +827,7 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) while (pt->onexit) { if (pt->onexit->scope == glob) { // This shouldn't happen, but let's not go inifinite eh? - JS_ReportError(cx, "js_EvalOnExit() extra scope is global"); + JS_ReportErrorASCII(cx, "js_EvalOnExit() extra scope is global"); return; } else { @@ -824,7 +835,7 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) js_EvalOnExit(cx, pt->onexit->scope, cb); if (oes == pt->onexit) { // This *really* shouldn't happen... - JS_ReportError(cx, "js_EvalOnExit() did not pop on_exit stack"); + JS_ReportErrorASCII(cx, "js_EvalOnExit() did not pop on_exit stack"); return; } } @@ -837,7 +848,7 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) if (oes->scope == obj) { (*prev_oes_next) = oes->next; list = oes->onexit; - JS_RemoveObjectRoot(cx, &oes->scope); + oes->scope = NULL; free(oes); break; } @@ -849,8 +860,13 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) cb->auto_terminate=FALSE; while((p=strListPop(&list))!=NULL) { - if((script=JS_CompileScript(cx, obj, p, strlen(p), NULL, 0))!=NULL) { - JS_ExecuteScript(cx, obj, script, &rval); + JS::CompileOptions options(cx); + options.setFileAndLine("js.on_exit", 1); + JS::RootedScript script(cx); + if(JS::Compile(cx, options, p, strlen(p), &script)) { + JS::AutoObjectVector js_vscope(cx); + js_vscope.append(obj); + JS_ExecuteScript(cx, js_vscope, script, &rval); } free(p); } @@ -863,36 +879,36 @@ void DLLCALL js_EvalOnExit(JSContext *cx, JSObject *obj, js_callback_t* cb) cb->auto_terminate = TRUE; } -JSObject* DLLCALL js_CreateInternalJsObject(JSContext* cx, JSObject* parent, js_callback_t* cb, js_startup_t* startup) +JS::HandleObject DLLCALL js_CreateInternalJsObject(JSContext* cx, JS::HandleObject parent, js_callback_t* cb, js_startup_t* startup) { - JSObject* obj; + JS::RootedObject obj(cx); - if((obj = JS_DefineObject(cx, parent, "js", &js_internal_class, NULL + if((obj = JS_DefineObject(cx, parent, "js", &js_internal_class ,JSPROP_ENUMERATE|JSPROP_READONLY))==NULL) return(NULL); JS_SetPrivate(obj, cb); /* Store a pointer to js_callback_t */ if(startup!=NULL) { - JSObject* load_path_list; - JS::Value val; + JS::RootedObject load_path_list(cx); + JS::RootedValue val(cx); str_list_t load_path; - if((load_path_list=JS_NewArrayObject(cx, 0, NULL))==NULL) + if((load_path_list=JS_NewArrayObject(cx, 0))==NULL) return(NULL); - val=OBJECT_TO_JSVAL(load_path_list); - if(!JS_SetProperty(cx, obj, JAVASCRIPT_LOAD_PATH_LIST, &val)) + val.setObject(*load_path_list); + if(!JS_SetProperty(cx, obj, JAVASCRIPT_LOAD_PATH_LIST, val)) return(NULL); if((load_path=strListSplitCopy(NULL, startup->load_path, ",")) != NULL) { - JSString* js_str; + JS::RootedString js_str(cx); unsigned i; for(i=0; load_path[i]!=NULL; i++) { if((js_str=JS_NewStringCopyZ(cx, load_path[i]))==NULL) break; - val=STRING_TO_JSVAL(js_str); - if(!JS_SetElement(cx, load_path_list, i, &val)) + val.setString(js_str); + if(!JS_SetElement(cx, load_path_list, i, val)) break; } strListFree(&load_path); @@ -917,41 +933,41 @@ void msvc_invalid_parameter_handler(const wchar_t* expression, } #endif -void DLLCALL js_PrepareToExecute(JSContext *cx, JSObject *obj, const char *filename, const char* startup_dir, JSObject *scope) +void DLLCALL js_PrepareToExecute(JSContext *cx, JS::HandleObject obj, const char *filename, const char* startup_dir, JS::HandleObject scope) { - JSString* str; - JS::Value val; + JS::RootedString str(cx); + JS::RootedValue val(cx); - if(JS_GetProperty(cx, obj, "js", &val) && JSVAL_IS_OBJECT(val)) { - JSObject* js = JSVAL_TO_OBJECT(val); + if(JS_GetProperty(cx, obj, "js", &val) && val.isObject()) { + JS::RootedObject js(cx, &val.toObject()); char dir[MAX_PATH+1]; if(filename!=NULL) { char* p; if((str=JS_NewStringCopyZ(cx, filename)) != NULL) - JS_DefineProperty(cx, js, "exec_path", STRING_TO_JSVAL(str) - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_DefineProperty(cx, js, "exec_path", str + ,JSPROP_ENUMERATE|JSPROP_READONLY); if((str=JS_NewStringCopyZ(cx, getfname(filename))) != NULL) - JS_DefineProperty(cx, js, "exec_file", STRING_TO_JSVAL(str) - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_DefineProperty(cx, js, "exec_file", str + ,JSPROP_ENUMERATE|JSPROP_READONLY); SAFECOPY(dir,filename); p=getfname(dir); *p=0; if((str=JS_NewStringCopyZ(cx, dir)) != NULL) - JS_DefineProperty(cx, js, "exec_dir", STRING_TO_JSVAL(str) - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_DefineProperty(cx, js, "exec_dir", str + ,JSPROP_ENUMERATE|JSPROP_READONLY); } if(startup_dir==NULL) startup_dir=""; if((str=JS_NewStringCopyZ(cx, startup_dir)) != NULL) - JS_DefineProperty(cx, js, "startup_dir", STRING_TO_JSVAL(str) - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); - JS_DefineProperty(cx, js, "scope", OBJECT_TO_JSVAL(scope) - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_DefineProperty(cx, js, "startup_dir", str + ,JSPROP_ENUMERATE|JSPROP_READONLY); + JS_DefineProperty(cx, js, "scope", scope + ,JSPROP_ENUMERATE|JSPROP_READONLY); } - JS_DefineProperty(cx, scope, "exit_code", JSVAL_NULL - ,NULL,NULL,JSPROP_ENUMERATE|JSPROP_PERMANENT); + JS_DefineProperty(cx, scope, "exit_code", JS::RootedValue(cx, JS::NullValue()) + ,JSPROP_ENUMERATE|JSPROP_PERMANENT); #if defined(_MSC_VER) _set_invalid_parameter_handler(msvc_invalid_parameter_handler); #endif diff --git a/src/sbbs3/sbbs.h b/src/sbbs3/sbbs.h index c7ce1baafa6084eb9de4a0de0390282614148aad..89dfec7b43ad70379448bdebf2cf6d0475e15ba8 100644 --- a/src/sbbs3/sbbs.h +++ b/src/sbbs3/sbbs.h @@ -1344,7 +1344,7 @@ extern char lastuseron[LEN_ALIAS+1]; /* Name of user last online */ /* js_global.c */ struct js_onexit_scope { - JS::HandleObject scope; + JS::PersistentRootedObject scope; str_list_t onexit; struct js_onexit_scope *next; }; @@ -1361,6 +1361,7 @@ extern char lastuseron[LEN_ALIAS+1]; /* Name of user last online */ } 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*, JSObject**); + DLLEXPORT JS::HandleValue DLLCALL js_CopyValue(JSContext* cx, JS::HandleValue val, JSContext* new_cx, JS::MutableHandleValue rval); /* js_internal.c */ DLLEXPORT JS::HandleObject DLLCALL js_CreateInternalJsObject(JSContext*, JS::HandleObject parent, js_callback_t*, js_startup_t*);