nsresult nsJSUtils::EvaluateString(JSContext* aCx, const nsAString& aScript, JS::Handle<JSObject*> aScopeObject, JS::CompileOptions& aCompileOptions, EvaluateOptions& aEvaluateOptions, JS::Value* aRetValue, void **aOffThreadToken) { PROFILER_LABEL("JS", "EvaluateString"); MOZ_ASSERT_IF(aCompileOptions.versionSet, aCompileOptions.version != JSVERSION_UNKNOWN); MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aRetValue); MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aRetValue); MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); // Unfortunately, the JS engine actually compiles scripts with a return value // in a different, less efficient way. Furthermore, it can't JIT them in many // cases. So we need to be explicitly told whether the caller cares about the // return value. Callers use null to indicate they don't care. if (aRetValue) { *aRetValue = JSVAL_VOID; } JS::ExposeObjectToActiveJS(aScopeObject); nsAutoMicroTask mt; nsresult rv = NS_OK; bool ok = false; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); NS_ENSURE_TRUE(ssm->ScriptAllowed(js::GetGlobalForObjectCrossCompartment(aScopeObject)), NS_OK); mozilla::Maybe<AutoDontReportUncaught> dontReport; if (!aEvaluateOptions.reportUncaught) { // We need to prevent AutoLastFrameCheck from reporting and clearing // any pending exceptions. dontReport.construct(aCx); } // Scope the JSAutoCompartment so that we can later wrap the return value // into the caller's cx. { JSAutoCompartment ac(aCx, aScopeObject); JS::Rooted<JSObject*> rootedScope(aCx, aScopeObject); if (aOffThreadToken) { JSScript *script = JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken); *aOffThreadToken = nullptr; // Mark the token as having been finished. if (script) { ok = JS_ExecuteScript(aCx, rootedScope, script, aRetValue); } else { ok = false; } } else { ok = JS::Evaluate(aCx, rootedScope, aCompileOptions, PromiseFlatString(aScript).get(), aScript.Length(), aRetValue); } if (ok && aEvaluateOptions.coerceToString && !aRetValue->isUndefined()) { JS::Rooted<JS::Value> value(aCx, *aRetValue); JSString* str = JS::ToString(aCx, value); ok = !!str; *aRetValue = ok ? JS::StringValue(str) : JS::UndefinedValue(); } } if (!ok) { if (aEvaluateOptions.reportUncaught) { ReportPendingException(aCx); if (aRetValue) { *aRetValue = JS::UndefinedValue(); } } else { rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE : NS_ERROR_OUT_OF_MEMORY; JS::Rooted<JS::Value> exn(aCx); JS_GetPendingException(aCx, &exn); if (aRetValue) { *aRetValue = exn; } JS_ClearPendingException(aCx); } } // Wrap the return value into whatever compartment aCx was in. if (aRetValue) { JS::Rooted<JS::Value> v(aCx, *aRetValue); if (!JS_WrapValue(aCx, &v)) { return NS_ERROR_OUT_OF_MEMORY; } *aRetValue = v; } return rv; }
JSBool gjs_console_interact(JSContext *context, uintN argc, jsval *vp) { JSObject *object = JS_THIS_OBJECT(context, vp); gboolean eof = FALSE; JSObject *script = NULL; jsval result; JSString *str; GString *buffer = NULL; char *temp_buf = NULL; gunichar2 *u16_buffer; glong u16_buffer_len; int lineno; int startline; GError *error = NULL; FILE *file = stdin; JS_SetErrorReporter(context, gjs_console_error_reporter); /* It's an interactive filehandle; drop into read-eval-print loop. */ lineno = 1; do { /* * Accumulate lines until we get a 'compilable unit' - one that either * generates an error (before running out of source) or that compiles * cleanly. This should be whenever we get a complete statement that * coincides with the end of a line. */ startline = lineno; buffer = g_string_new(""); do { if (!gjs_console_readline(context, &temp_buf, file, startline == lineno ? "gjs> " : ".... ")) { eof = JS_TRUE; break; } g_string_append(buffer, temp_buf); g_free(temp_buf); lineno++; /* Note in this case, we are trying to parse the buffer as * ISO-8859-1 which is broken for non-ASCII. */ } while (!JS_BufferIsCompilableUnit(context, object, buffer->str, buffer->len)); if ((u16_buffer = g_utf8_to_utf16 (buffer->str, buffer->len, NULL, &u16_buffer_len, &error)) == NULL) { g_printerr ("%s\n", error->message); g_clear_error (&error); continue; } script = JS_CompileUCScript(context, object, u16_buffer, u16_buffer_len, "typein", startline); g_free (u16_buffer); if (script) JS_ExecuteScript(context, object, script, &result); if (JS_GetPendingException(context, &result)) { str = JS_ValueToString(context, result); JS_ClearPendingException(context); } else if (JSVAL_IS_VOID(result)) { goto next; } else { str = JS_ValueToString(context, result); } if (str) { char *display_str; display_str = gjs_value_debug_string(context, result); if (display_str != NULL) { g_fprintf(stdout, "%s\n", display_str); g_free(display_str); } } next: g_string_free(buffer, TRUE); } while (!eof); g_fprintf(stdout, "\n"); if (file != stdin) fclose(file); return JS_TRUE; }
nsresult ProxyAutoConfig::SetupJS() { mJSNeedsSetup = false; NS_ABORT_IF_FALSE(!sRunning, "JIT is running"); delete mJSRuntime; mJSRuntime = nullptr; if (mPACScript.IsEmpty()) return NS_ERROR_FAILURE; mJSRuntime = JSRuntimeWrapper::Create(); if (!mJSRuntime) return NS_ERROR_FAILURE; JSContext* cx = mJSRuntime->Context(); JSAutoRequest ar(cx); JSAutoCompartment ac(cx, mJSRuntime->Global()); // check if this is a data: uri so that we don't spam the js console with // huge meaningless strings. this is not on the main thread, so it can't // use nsIRUI scheme methods bool isDataURI = nsDependentCSubstring(mPACURI, 0, 5).LowerCaseEqualsASCII("data:", 5); sRunning = this; JS::Rooted<JSObject*> global(cx, mJSRuntime->Global()); JS::CompileOptions options(cx); options.setFileAndLine(mPACURI.get(), 1); JS::Rooted<JSScript*> script(cx, JS_CompileScript(cx, global, mPACScript.get(), mPACScript.Length(), options)); if (!script || !JS_ExecuteScript(cx, global, script, nullptr)) { nsString alertMessage(NS_LITERAL_STRING("PAC file failed to install from ")); if (isDataURI) { alertMessage += NS_LITERAL_STRING("data: URI"); } else { alertMessage += NS_ConvertUTF8toUTF16(mPACURI); } PACLogToConsole(alertMessage); sRunning = nullptr; return NS_ERROR_FAILURE; } sRunning = nullptr; mJSRuntime->SetOK(); nsString alertMessage(NS_LITERAL_STRING("PAC file installed from ")); if (isDataURI) { alertMessage += NS_LITERAL_STRING("data: URI"); } else { alertMessage += NS_ConvertUTF8toUTF16(mPACURI); } PACLogToConsole(alertMessage); // we don't need these now mPACScript.Truncate(); mPACURI.Truncate(); return NS_OK; }
int ExecShellScript(const char * file, int argc, char** argv, JSContext * context, JSObject * env, jsval * vp) { register FILE * filep; register int c; filep = fopen(file, "rb"); if (!filep) { JS_ReportError(context, "%s: %s", file, "No such file or directory"); return 0; } if (getc(filep) == '#' && getc(filep) == '!') { c = 1; while (c != EOF && c != '\n') c = getc(filep); ungetc(c, filep); } else { fclose(filep); JS_ReportError(context, "%s: %s", file, "is not a shell script"); return 0; } JSObject* argsObj = JS_NewArrayObject(context, 0, NULL); JS_DefineProperty(context, env, "parameter", OBJECT_TO_JSVAL(argsObj), NULL, NULL, 0); JSString* str = JS_NewStringCopyZ(context, file); JS_DefineElement(context, argsObj, 0, STRING_TO_JSVAL(str), NULL, NULL, JSPROP_ENUMERATE); int i; for (i = 0; i < argc; i++) { str = JS_NewStringCopyZ(context, argv[i]); JS_DefineElement(context, argsObj, i + 1, STRING_TO_JSVAL(str), NULL, NULL, JSPROP_ENUMERATE); } setenv(SMASH_RESOURCE_PATH_ENV_ID, GET_STRING_DEF(SMASH_RESOURCE_PATH), 0); JS_InitCTypesClass(context, env); JS_DefineFunctions(context, env, shell_functions); JS_DefineProperties(context, env, shell_properties); jsval fun; JS_GetProperty(context, env, "system", &fun); JS_DefineFunction(context, JSVAL_TO_OBJECT(fun), "read", ShellSystemRead, 1, JSPROP_ENUMERATE); JS_DefineFunction(context, JSVAL_TO_OBJECT(fun), "write", ShellSystemWrite, 2, JSPROP_ENUMERATE); jsval fun2; JS_GetProperty(context, env, "echo", &fun2); JS_DefineFunction(context, JSVAL_TO_OBJECT(fun2), "error", ShellEchoError, 1, JSPROP_ENUMERATE); jsval fun3; JS_GetProperty(context, env, "setFileContent", &fun3); JS_DefineFunction(context, JSVAL_TO_OBJECT(fun3), "append", ShellSetFileContentAppend, 2, JSPROP_ENUMERATE); #ifdef SMASH_MAIN_LOADER //ExecScriptFile(context, env, GET_STRING_DEF(SMASH_MAIN_LOADER), NULL); #endif #ifdef SMASH_SHELL_LOADER ExecScriptFile(context, env, GET_STRING_DEF(SMASH_SHELL_LOADER), NULL); #endif JSObject * jsTemp = JS_CompileFileHandle(context, env, file, filep); fclose(filep); if (jsTemp) { return JS_ExecuteScript(context, env, jsTemp, vp); } else { JS_ReportPendingException(context); return 1; } }
int js_plugin_load(const char *id, const char *url, char *errbuf, size_t errlen) { char *sbuf; struct fa_stat fs; JSContext *cx; js_plugin_t *jsp; JSObject *pobj, *gobj; JSScript *s; char path[PATH_MAX]; jsval val; fa_handle_t *ref; ref = fa_reference(url); if((sbuf = fa_quickload(url, &fs, NULL, errbuf, errlen)) == NULL) { fa_unreference(ref); return -1; } cx = js_newctx(err_reporter); JS_BeginRequest(cx); /* Remove any plugin with same URL */ LIST_FOREACH(jsp, &js_plugins, jsp_link) if(!strcmp(jsp->jsp_id, id)) break; if(jsp != NULL) js_plugin_unload0(cx, jsp); jsp = calloc(1, sizeof(js_plugin_t)); jsp->jsp_url = strdup(url); jsp->jsp_id = strdup(id); jsp->jsp_ref = ref; LIST_INSERT_HEAD(&js_plugins, jsp, jsp_link); gobj = JS_NewObject(cx, &global_class, NULL, NULL); JS_InitStandardClasses(cx, gobj); JS_DefineProperty(cx, gobj, "showtime", OBJECT_TO_JSVAL(showtimeobj), NULL, NULL, JSPROP_READONLY | JSPROP_PERMANENT); /* Plugin object */ pobj = JS_NewObject(cx, &plugin_class, NULL, gobj); JS_AddNamedRoot(cx, &pobj, "plugin"); JS_SetPrivate(cx, pobj, jsp); JS_DefineFunctions(cx, pobj, plugin_functions); val = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, url)); JS_SetProperty(cx, pobj, "url", &val); if(!fa_parent(path, sizeof(path), url)) { val = STRING_TO_JSVAL(JS_NewStringCopyZ(cx, path)); JS_SetProperty(cx, pobj, "path", &val); } JS_DefineProperty(cx, pobj, "URIRouting", BOOLEAN_TO_JSVAL(1), NULL, jsp_setEnableURIRoute, JSPROP_PERMANENT); jsp->jsp_enable_uri_routing = 1; JS_DefineProperty(cx, pobj, "search", BOOLEAN_TO_JSVAL(1), NULL, jsp_setEnableSearch, JSPROP_PERMANENT); jsp->jsp_enable_search = 1; jsp->jsp_protect_object = 1; s = JS_CompileScript(cx, pobj, sbuf, fs.fs_size, url, 1); free(sbuf); if(s != NULL) { JSObject *sobj = JS_NewScriptObject(cx, s); jsval result; JS_AddNamedRoot(cx, &sobj, "script"); JS_ExecuteScript(cx, pobj, s, &result); JS_RemoveRoot(cx, &sobj); } JS_RemoveRoot(cx, &pobj); JS_EndRequest(cx); JS_GC(cx); JS_DestroyContext(cx); return 0; }
PRBool CreateFakeBrowserWindow(JSContext* cx, JSObject* parent, nsIPrincipal* systemPrincipal) { nsresult rv; jsval value; nsCOMPtr<nsIXPConnect> xpc = do_GetService(nsIXPConnect::GetCID()); if (xpc == nsnull) { JS_ReportError(cx, "Adblock Plus: Coult not retrieve nsIXPConnect - wrong Gecko version?"); return PR_FALSE; } rv = xpc->FlagSystemFilenamePrefix("adblockplus.dll/"); if (NS_FAILED(rv)) { JS_ReportError(cx, "Adblock Plus: Failed to enable protection for inline JavaScript"); return PR_FALSE; } JSObject* obj = JS_NewObject(cx, nsnull, nsnull, parent); if (obj == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to create fake browser window object - out of memory?"); return PR_FALSE; } JS_SetGlobalObject(cx, obj); // Have to loop through the methods manually because JS_DefineFunctions won't do anything for some reason for (JSFunctionSpec *fs = window_methods; fs->name; fs++) { JSFunction *fun = JS_DefineFunction(cx, obj, fs->name, fs->call, fs->nargs, fs->flags); if (!fun) { JS_ReportError(cx, "Adblock Plus: Failed to attach native methods to fake browser window"); return PR_FALSE; } } if (!JS_DefineProperties(cx, obj, window_properties)) { JS_ReportError(cx, "Adblock Plus: Failed to attach native properties to fake browser window"); return PR_FALSE; } JSPrincipals* principals; rv = systemPrincipal->GetJSPrincipals(cx, &principals); if (NS_FAILED(rv)) { JS_ReportError(cx, "Adblock Plus: Could not convert system principal into JavaScript principals"); return PR_FALSE; } for (int i = 0; includes[i]; i += 2) { JSScript* inlineScript = JS_CompileScriptForPrincipals(cx, obj, principals, includes[i+1], strlen(includes[i+1]), includes[i], 1); if (inlineScript == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to compile %s", includes[i]); return PR_FALSE; } if (!JS_ExecuteScript(cx, obj, inlineScript, &value)) { JS_ReportError(cx, "Adblock Plus: Failed to execute %s", includes[i]); return PR_FALSE; } JS_DestroyScript(cx, inlineScript); } JSPRINCIPALS_DROP(cx, principals); nsCOMPtr<nsISupports> wrapped; rv = xpc->WrapJS(cx, obj, NS_GET_IID(nsISupports), getter_AddRefs(wrapped)); if (NS_FAILED(rv)) { JS_ReportError(cx, "Adblock Plus: Failed to create XPConnect wrapper for fake browser window"); return PR_FALSE; } fakeBrowserWindow = do_QueryInterface(wrapped); if (fakeBrowserWindow == nsnull) { JS_ReportError(cx, "Adblock Plus: Failed to QI fake browser window"); return PR_FALSE; } jsval readerVal; JS_GetProperty(cx, obj, "_dtdReader", &readerVal); if (readerVal == JSVAL_VOID) { JS_ReportError(cx, "Adblock Plus: Failed to retrieve DTD reader object"); return PR_FALSE; } JSObject* reader = JSVAL_TO_OBJECT(readerVal); for (int i = 0; i < NUM_LABELS; i++) { JSString* str = JS_NewStringCopyZ(cx, context_labels[i]); if (str == nsnull) { JS_ReportError(cx, "Adblock Plus: Could not create JavaScript string for '%s' - out of memory?", context_labels[i]); return PR_FALSE; } jsval args[] = {STRING_TO_JSVAL(str)}; jsval retval; if (!JS_CallFunctionName(cx, reader, "getEntity", 1, args, &retval)) { JS_ReportError(cx, "Adblock Plus: Failed to retrieve entity '%s' from overlay.dtd", context_labels[i]); return PR_FALSE; } str = JS_ValueToString(cx, retval); if (str == nsnull) { JS_ReportError(cx, "Adblock Plus: Could not convert return value of _dtdReader.getEntity() to string"); return PR_FALSE; } strcpy_s(labelValues[i], sizeof(labelValues[i]), JS_GetStringBytes(str)); } return PR_TRUE; }
nsresult nsJSUtils::EvaluateString(JSContext* aCx, JS::SourceBufferHolder& aSrcBuf, JS::Handle<JSObject*> aScopeObject, JS::CompileOptions& aCompileOptions, const EvaluateOptions& aEvaluateOptions, JS::MutableHandle<JS::Value> aRetValue, void **aOffThreadToken) { PROFILER_LABEL("nsJSUtils", "EvaluateString", js::ProfileEntry::Category::JS); MOZ_ASSERT_IF(aCompileOptions.versionSet, aCompileOptions.version != JSVERSION_UNKNOWN); MOZ_ASSERT_IF(aEvaluateOptions.coerceToString, aEvaluateOptions.needResult); MOZ_ASSERT_IF(!aEvaluateOptions.reportUncaught, aEvaluateOptions.needResult); MOZ_ASSERT(aCx == nsContentUtils::GetCurrentJSContext()); MOZ_ASSERT(aSrcBuf.get()); // Unfortunately, the JS engine actually compiles scripts with a return value // in a different, less efficient way. Furthermore, it can't JIT them in many // cases. So we need to be explicitly told whether the caller cares about the // return value. Callers can do this by calling the other overload of // EvaluateString() which calls this function with aEvaluateOptions.needResult // set to false. aRetValue.setUndefined(); JS::ExposeObjectToActiveJS(aScopeObject); nsAutoMicroTask mt; nsresult rv = NS_OK; bool ok = false; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); NS_ENSURE_TRUE(ssm->ScriptAllowed(js::GetGlobalForObjectCrossCompartment(aScopeObject)), NS_OK); mozilla::Maybe<AutoDontReportUncaught> dontReport; if (!aEvaluateOptions.reportUncaught) { // We need to prevent AutoLastFrameCheck from reporting and clearing // any pending exceptions. dontReport.emplace(aCx); } // Scope the JSAutoCompartment so that we can later wrap the return value // into the caller's cx. { JSAutoCompartment ac(aCx, aScopeObject); JS::Rooted<JSObject*> rootedScope(aCx, aScopeObject); if (aOffThreadToken) { JS::Rooted<JSScript*> script(aCx, JS::FinishOffThreadScript(aCx, JS_GetRuntime(aCx), *aOffThreadToken)); *aOffThreadToken = nullptr; // Mark the token as having been finished. if (script) { if (aEvaluateOptions.needResult) { ok = JS_ExecuteScript(aCx, rootedScope, script, aRetValue); } else { ok = JS_ExecuteScript(aCx, rootedScope, script); } } else { ok = false; } } else { if (aEvaluateOptions.needResult) { ok = JS::Evaluate(aCx, rootedScope, aCompileOptions, aSrcBuf, aRetValue); } else { ok = JS::Evaluate(aCx, rootedScope, aCompileOptions, aSrcBuf); } } if (ok && aEvaluateOptions.coerceToString && !aRetValue.isUndefined()) { JS::Rooted<JS::Value> value(aCx, aRetValue); JSString* str = JS::ToString(aCx, value); ok = !!str; aRetValue.set(ok ? JS::StringValue(str) : JS::UndefinedValue()); } } if (!ok) { if (aEvaluateOptions.reportUncaught) { ReportPendingException(aCx); if (aEvaluateOptions.needResult) { aRetValue.setUndefined(); } } else { rv = JS_IsExceptionPending(aCx) ? NS_ERROR_FAILURE : NS_ERROR_OUT_OF_MEMORY; JS::Rooted<JS::Value> exn(aCx); JS_GetPendingException(aCx, &exn); if (aEvaluateOptions.needResult) { aRetValue.set(exn); } JS_ClearPendingException(aCx); } } // Wrap the return value into whatever compartment aCx was in. if (aEvaluateOptions.needResult) { JS::Rooted<JS::Value> v(aCx, aRetValue); if (!JS_WrapValue(aCx, &v)) { return NS_ERROR_OUT_OF_MEMORY; } aRetValue.set(v); } return rv; }
PRIntn prmain(PRIntn argc, char **argv) { void *stackBasePtr; gpsee_interpreter_t *jsi; /* Handle describing a GPSEE/JavaScript Interpreter */ gpsee_realm_t *realm; /* Interpreter's primordial realm */ JSContext *cx; /* A context in realm */ const char *scriptCode = NULL; /* String with JavaScript program in it */ const char *scriptFilename = NULL; /* Filename with JavaScript program in it */ char * const *script_argv; /* Becomes arguments array in JS program */ char * const *script_environ = NULL; /* Environment to pass to script */ char *flags = malloc(8); /* Flags found on command line */ int noRunScript = 0; /* !0 = compile but do not run */ int fiArg = 0; int skipSheBang = 0; int exitCode; int verbosity; /* Verbosity to use before flags are processed */ #ifdef GPSEE_DEBUGGER JSDContext *jsdc; #endif #if defined(__SURELYNX__) permanent_pool = apr_initRuntime(); #endif gpsee_setVerbosity(isatty(STDERR_FILENO) ? GSR_PREPROGRAM_TTY_VERBOSITY : GSR_PREPROGRAM_NOTTY_VERBOSITY); gpsee_openlog(gpsee_basename(argv[0])); /* Print usage and exit if no arguments were given */ if (argc < 2) usage(argv[0]); flags[0] = (char)0; fiArg = findFileToInterpret(argc, argv); if (fiArg == 0) /* Not a script file interpreter (shebang) */ { int c; char *flag_p = flags; while ((c = getopt(argc, argv, whenSureLynx("D:r:","") "v:c:hHnf:F:aCRxSUWdeJz")) != -1) { switch(c) { #if defined(__SURELYNX__) case 'D': redirect_output(permanent_pool, optarg); break; case 'r': /* handled by cfg_openfile() */ break; #endif case 'c': scriptCode = optarg; break; case 'h': usage(argv[0]); break; case 'H': moreHelp(argv[0]); break; case 'n': noRunScript = 1; break; case 'F': skipSheBang = 1; case 'f': scriptFilename = optarg; break; case 'a': case 'C': case 'd': case 'e': case 'J': case 'S': case 'R': case 'U': case 'W': case 'x': case 'z': { char *flags_storage = realloc(flags, (flag_p - flags) + 1 + 1); if (flags_storage != flags) { flag_p = (flag_p - flags) + flags_storage; flags = flags_storage; } *flag_p++ = c; *flag_p = '\0'; } break; case '?': { char buf[32]; snprintf(buf, sizeof(buf), "Invalid option: %c\n", optopt); fatal(buf); } case ':': { char buf[32]; snprintf(buf, sizeof(buf), "Missing parameter to option '%c'\n", optopt); fatal(buf); } } } /* getopt wend */ /* Create the script's argument vector with the script name as arguments[0] */ { char **nc_script_argv = malloc(sizeof(argv[0]) * (2 + (argc - optind))); nc_script_argv[0] = (char *)scriptFilename; memcpy(nc_script_argv + 1, argv + optind, sizeof(argv[0]) * ((1 + argc) - optind)); script_argv = nc_script_argv; } *flag_p = (char)0; } else { scriptFilename = argv[fiArg]; if (fiArg == 2) { if (argv[1][0] != '-') fatal("Invalid syntax for file-interpreter flags! (Must begin with '-')"); flags = realloc(flags, strlen(argv[1]) + 1); strcpy(flags, argv[1] + 1); } /* This is a file interpreter; script_argv is correct at offset fiArg. */ script_argv = argv + fiArg; } if (strchr(flags, 'a')) { #if defined(GPSEE_DARWIN_SYSTEM) script_environ = (char * const *)_NSGetEnviron(); #else extern char **environ; script_environ = (char * const *)environ; #endif } loadRuntimeConfig(scriptFilename, flags, argc, argv); if (strchr(flags, 'U') || (cfg_bool_value(cfg, "gpsee_force_no_utf8_c_strings") == cfg_true) || getenv("GPSEE_NO_UTF8_C_STRINGS")) { JS_DestroyRuntime(JS_NewRuntime(1024)); putenv((char *)"GPSEE_NO_UTF8_C_STRINGS=1"); } jsi = gpsee_createInterpreter(); realm = jsi->realm; cx = jsi->cx; #if defined(GPSEE_DEBUGGER) jsdc = gpsee_initDebugger(cx, realm, DEBUGGER_JS); #endif gpsee_setThreadStackLimit(cx, &stackBasePtr, strtol(cfg_default_value(cfg, "gpsee_thread_stack_limit_bytes", "0x80000"), NULL, 0)); processFlags(cx, flags, &verbosity); free(flags); #if defined(__SURELYNX__) sl_set_debugLevel(gpsee_verbosity(0)); /* enableTerminalLogs(permanent_pool, gpsee_verbosity(0) > 0, NULL); */ #else if (verbosity < GSR_MIN_TTY_VERBOSITY && isatty(STDERR_FILENO)) verbosity = GSR_MIN_TTY_VERBOSITY; #endif if (gpsee_verbosity(0) < verbosity) gpsee_setVerbosity(verbosity); /* Run JavaScript specified with -c */ if (scriptCode) { jsval v; if (JS_EvaluateScript(cx, realm->globalObject, scriptCode, strlen(scriptCode), "command_line", 1, &v) == JS_FALSE) { v = JSVAL_NULL; goto out; } v = JSVAL_NULL; } if ((argv[0][0] == '/') #if defined(SYSTEM_GSR) && (strcmp(argv[0], SYSTEM_GSR) != 0) #endif && cfg_bool_value(cfg, "no_gsr_preload_script") != cfg_true) { char preloadScriptFilename[FILENAME_MAX]; char mydir[FILENAME_MAX]; int i; jsi->grt->exitType = et_unknown; i = snprintf(preloadScriptFilename, sizeof(preloadScriptFilename), "%s/.%s_preload", gpsee_dirname(argv[0], mydir, sizeof(mydir)), gpsee_basename(argv[0])); if ((i == 0) || (i == (sizeof(preloadScriptFilename) -1))) gpsee_log(cx, GLOG_EMERG, PRODUCT_SHORTNAME ": Unable to create preload script filename!"); else errno = 0; if (access(preloadScriptFilename, F_OK) == 0) { jsval v; JSScript *script; JSObject *scrobj; if (!gpsee_compileScript(cx, preloadScriptFilename, NULL, NULL, &script, realm->globalObject, &scrobj)) { jsi->grt->exitType = et_compileFailure; gpsee_log(cx, GLOG_EMERG, PRODUCT_SHORTNAME ": Unable to compile preload script '%s'", preloadScriptFilename); goto out; } if (!script || !scrobj) goto out; if (!noRunScript) { JS_AddNamedObjectRoot(cx, &scrobj, "preload_scrobj"); jsi->grt->exitType = et_execFailure; if (JS_ExecuteScript(cx, realm->globalObject, script, &v) == JS_TRUE) jsi->grt->exitType = et_finished; else jsi->grt->exitType = et_exception; JS_RemoveObjectRoot(cx, &scrobj); v = JSVAL_NULL; } } if (jsi->grt->exitType & et_errorMask) goto out; } /* Setup for main-script running -- cancel preprogram verbosity and use our own error reporting system in gsr that does not use error reporter */ gpsee_setVerbosity(verbosity); JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_DONT_REPORT_UNCAUGHT); if (!scriptFilename) { if (!scriptCode) /* Command-line options did not include code to run */ usage(argv[0]); if (jsi->grt->exitType == et_unknown) jsi->grt->exitType = et_finished; } else { FILE *scriptFile = openScriptFile(cx, scriptFilename, skipSheBang || (fiArg != 0)); if (!scriptFile) { gpsee_log(cx, GLOG_NOTICE, PRODUCT_SHORTNAME ": Unable to open' script '%s'! (%m)", scriptFilename); jsi->grt->exitType = et_compileFailure; goto out; } processInlineFlags(cx, scriptFile, &verbosity); gpsee_setVerbosity(verbosity); /* Just compile and exit? */ if (noRunScript) { JSScript *script; JSObject *scrobj; if (!gpsee_compileScript(cx, scriptFilename, scriptFile, NULL, &script, realm->globalObject, &scrobj)) { jsi->grt->exitType = et_exception; gpsee_reportUncaughtException(cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } else { jsi->grt->exitType = et_finished; } } else /* noRunScript is false; run the program */ { jsi->grt->exitType = et_execFailure; if (gpsee_runProgramModule(cx, scriptFilename, NULL, scriptFile, script_argv, script_environ) == JS_TRUE) { jsi->grt->exitType = et_finished; } else { int code; code = gpsee_getExceptionExitCode(cx); if (code >= 0) /** e.g. throw 6 */ { jsi->grt->exitType = et_requested; jsi->grt->exitCode = code; } else { if (JS_IsExceptionPending(cx)) { jsi->grt->exitType = et_exception; gpsee_reportUncaughtException(cx, JSVAL_NULL, (gpsee_verbosity(0) >= GSR_FORCE_STACK_DUMP_VERBOSITY) || ((gpsee_verbosity(0) >= GPSEE_ERROR_OUTPUT_VERBOSITY) && isatty(STDERR_FILENO))); } } } } fclose(scriptFile); goto out; } out: #ifdef GPSEE_DEBUGGER gpsee_finiDebugger(jsdc); #endif if (jsi->grt->exitType & et_successMask) { exitCode = jsi->grt->exitCode; } else { const char *reason; exitCode = 1; switch(jsi->grt->exitType) { case et_successMask: case et_errorMask: case et_requested: case et_finished: case et_dummy: default: GPSEE_NOT_REACHED("impossible"); reason = NULL; /* quell compiler warning below */ break; case et_execFailure: reason = "execFailure - probable native module error, returning JS_FALSE without setting exception"; break; case et_compileFailure: reason = "script could not be compiled"; break; case et_unknown: reason = "unknown - probable native module error, returning JS_FALSE without setting exception"; break; case et_exception: reason = NULL; break; } if (reason) { gpsee_log(cx, GLOG_NOTICE, "Unexpected interpreter shutdown: %s (%m)", reason); if (gpsee_verbosity(0) == 0) { /* not gpsee_ */ fprintf(stderr, "*** Unexpected interpreter shutdown: %s", reason); if (errno) fprintf(stderr, " (%s)\n", strerror(errno)); else fputs("\n", stderr); } } } gpsee_destroyInterpreter(jsi); JS_ShutDown(); return exitCode; }