Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
Пример #4
0
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;

	}

}
Пример #5
0
Файл: js.c Проект: Hr-/showtime
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;
}
Пример #6
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;
}
Пример #7
0
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;
}
Пример #8
0
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;
}