RPM Package Manager, CVS Repository http://rpm5.org/cvs/ ____________________________________________________________________________
Server: rpm5.org Name: Jeff Johnson Root: /v/rpm/cvs Email: j...@rpm5.org Module: rpm Date: 26-Jun-2017 00:46:55 Branch: rpm-5_4 Handle: 2017062522465400 Modified files: (Branch: rpm-5_4) rpm/rpmio rpmjs45.cpp rpmjss.inp Log: - rpmjss: WIP. Summary: Revision Changes Path 1.1.2.11 +1245 -131 rpm/rpmio/rpmjs45.cpp 1.1.2.3 +3 -2 rpm/rpmio/rpmjss.inp ____________________________________________________________________________ patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjs45.cpp ============================================================================ $ cvs diff -u -r1.1.2.10 -r1.1.2.11 rpmjs45.cpp --- rpm/rpmio/rpmjs45.cpp 25 Jun 2017 08:20:02 -0000 1.1.2.10 +++ rpm/rpmio/rpmjs45.cpp 25 Jun 2017 22:46:54 -0000 1.1.2.11 @@ -6,124 +6,991 @@ #include "system.h" +#define JS_CODEGEN_X64 1 + +#include "mozilla/ArrayUtils.h" +#include "mozilla/Atomics.h" +#include "mozilla/DebugOnly.h" +#include "mozilla/GuardObjects.h" +#include "mozilla/mozalloc.h" +#include "mozilla/PodOperations.h" + #include "jsapi.h" #include "jsprf.h" #include "js/Initialization.h" #include "js/Conversions.h" -#include "jsfriendapi.h" +#include "jsfriendapi.h" + +#include "jswrapper.h" + +using namespace JS; +using namespace js; +#ifdef NOTYET +using namespace js::cli; +using namespace js::shell; +#endif + +using mozilla::ArrayLength; +using mozilla::Atomic; +using mozilla::MakeUnique; +using mozilla::Maybe; +using mozilla::NumberEqualsInt32; +using mozilla::PodCopy; +using mozilla::PodEqual; +using mozilla::UniquePtr; + +#define _RPMJSS_INTERNAL +#include <rpmjss.h> + +#include "debug.h" + +/*==============================================================*/ +typedef struct JSI_s * JSI_t; +struct JSI_s { + JSRuntime *rt; + JSContext *cx; + JSObject *global; +}; + +// Shell state set once at startup. +static bool enableCodeCoverage = false; +static bool enableDisassemblyDumps = false; +static bool offthreadCompilation = false; +static bool enableBaseline = false; +static bool enableIon = false; +static bool enableAsmJS = false; +static bool enableNativeRegExp = false; +static bool enableUnboxedArrays = false; +#ifdef JS_GC_ZEAL +static char gZealStr[128]; +#endif +static bool printTiming = false; +static const char* jsCacheDir = nullptr; +static const char* jsCacheAsmJSPath = nullptr; +static bool reportWarnings = true; +static bool compileOnly = false; +static bool fuzzingSafe = false; +static bool disableOOMFunctions = false; +static const char* moduleLoadPath = "."; + +#ifdef DEBUG +static bool dumpEntrainedVariables = false; +static bool OOM_printAllocationCount = false; +#endif + +/*==============================================================*/ +static bool +global_enumerate(JSContext* cx, HandleObject obj) +{ +#ifdef LAZY_STANDARD_CLASSES + return JS_EnumerateStandardClasses(cx, obj); +#else + return true; +#endif +} + +static bool +global_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp) +{ +#ifdef LAZY_STANDARD_CLASSES + if (!JS_ResolveStandardClass(cx, obj, id, resolvedp)) + return false; +#endif + return true; +} + +static bool +global_mayResolve(const JSAtomState& names, jsid id, JSObject* maybeObj) +{ + return JS_MayResolveStandardClass(names, id, maybeObj); +} + +static JSClass global_class = { + "global", + JSCLASS_GLOBAL_FLAGS, + nullptr, + nullptr, + nullptr, + nullptr, + global_enumerate, + global_resolve, + global_mayResolve, + nullptr, + nullptr, + nullptr, + nullptr, + JS_GlobalObjectTraceHook +}; + +static int rpmjss_nopens; + +static int _rpmjss45_debug; +#define SPEW(_fmt, ...) \ + if (_rpmjss45_debug) \ + fprintf(stderr, _fmt, __VA_ARGS__) + +/*==============================================================*/ +static void +rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) +{ + fprintf(stderr, "%s:%u:%s\n", + report->filename ? report->filename : "<no filename=\"filename\">", + (unsigned int) report->lineno, message); +} + +static void +rpmjssOOMCallback(JSContext* cx, void* data) +{ +#ifdef NOTYET + // If a script is running, the engine is about to throw the string "out of + // memory", which may or may not be caught. Otherwise the engine will just + // unwind and return null/false, with no exception set. + if (!JS_IsRunning(cx)) + GetShellRuntime(cx)->gotError = true; +#endif +} + +enum JSShellErrNum { +#define MSG_DEF(name, count, exception, format) \ + name, +#include "jsshell.msg" +#undef MSG_DEF + JSShellErr_Limit +}; + +static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = { +#define MSG_DEF(name, count, exception, format) \ + { format, count, JSEXN_ERR } , +#include "jsshell.msg" +#undef MSG_DEF +}; + +const JSErrorFormatString* +my_GetErrorMessage(void* userRef, const unsigned errorNumber) +{ + if (errorNumber == 0 || errorNumber >= JSShellErr_Limit) + return nullptr; + + return &jsShell_ErrorFormatString[errorNumber]; +} + +/*==============================================================*/ +enum PathResolutionMode { /* XXX shell/OSObject.h */ + RootRelative, + ScriptRelative +}; + +#ifdef NOTYET +#include "jsobj.h" +#ifdef XP_WIN +# include "jswin.h" +#endif +#include "jswrapper.h" + +#include "js/Conversions.h" +#include "shell/jsshell.h" +#include "vm/StringBuffer.h" +#include "vm/TypedArrayObject.h" + +#include "jsobjinlines.h" + +#ifdef XP_WIN +# define PATH_MAX (MAX_PATH > _MAX_DIR ? MAX_PATH : _MAX_DIR) +# define getcwd _getcwd +#else +# include <libgen.h> +#endif + +using namespace JS; + +namespace js { +namespace shell { +#endif /* NOTYET */ + +#ifdef XP_WIN +const char PathSeparator = '\\'; +#else +const char PathSeparator = '/'; +#endif + +static bool +IsAbsolutePath(const JSAutoByteString& filename) +{ + const char* pathname = filename.ptr(); + + if (pathname[0] == PathSeparator) + return true; + +#ifdef XP_WIN + // On Windows there are various forms of absolute paths (see + // http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247%28v=vs.85%29.aspx + // for details): + // + // "\..." + // "\\..." + // "C:\..." + // + // The first two cases are handled by the test above so we only need a test + // for the last one here. + + if ((strlen(pathname) > 3 && + isalpha(pathname[0]) && pathname[1] == ':' && pathname[2] == '\\')) + { + return true; + } +#endif + + return false; +} + +/* + * Resolve a (possibly) relative filename to an absolute path. If + * |scriptRelative| is true, then the result will be relative to the directory + * containing the currently-running script, or the current working directory if + * the currently-running script is "-e" (namely, you're using it from the + * command line.) Otherwise, it will be relative to the current working + * directory. + */ +#ifndef NOTYET +JSString* +ResolvePath(JSContext* cx, HandleString filenameStr, PathResolutionMode resolveMode) +{ + JSAutoByteString filename(cx, filenameStr); + if (!filename) + return nullptr; + + if (IsAbsolutePath(filename)) + return filenameStr; + + /* Get the currently executing script's name. */ + JS::AutoFilename scriptFilename; + if (!DescribeScriptedCaller(cx, &scriptFilename)) + return nullptr; + + if (!scriptFilename.get()) + return nullptr; + + if (strcmp(scriptFilename.get(), "-e") == 0 || strcmp(scriptFilename.get(), "typein") == 0) + resolveMode = RootRelative; + + static char buffer[PATH_MAX+1]; + if (resolveMode == ScriptRelative) { +#ifdef XP_WIN + // The docs say it can return EINVAL, but the compiler says it's void + _splitpath(scriptFilename.get(), nullptr, buffer, nullptr, nullptr); +#else + strncpy(buffer, scriptFilename.get(), PATH_MAX+1); + if (buffer[PATH_MAX] != '\0') + return nullptr; + + // dirname(buffer) might return buffer, or it might return a + // statically-allocated string + memmove(buffer, dirname(buffer), strlen(buffer) + 1); +#endif + } else { + const char* cwd = getcwd(buffer, PATH_MAX); + if (!cwd) + return nullptr; + } + + size_t len = strlen(buffer); + buffer[len] = '/'; + strncpy(buffer + len + 1, filename.ptr(), sizeof(buffer) - (len+1)); + if (buffer[PATH_MAX] != '\0') + return nullptr; + + return JS_NewStringCopyZ(cx, buffer); +} +#endif + +#ifdef NOTYET +static JSObject* +FileAsTypedArray(JSContext* cx, const char* pathname) +{ + FILE* file = fopen(pathname, "rb"); + if (!file) { + JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno)); + return nullptr; + } + AutoCloseFile autoClose(file); + + RootedObject obj(cx); + if (fseek(file, 0, SEEK_END) != 0) { + JS_ReportError(cx, "can't seek end of %s", pathname); + } else { + size_t len = ftell(file); + if (fseek(file, 0, SEEK_SET) != 0) { + JS_ReportError(cx, "can't seek start of %s", pathname); + } else { + obj = JS_NewUint8Array(cx, len); + if (!obj) + return nullptr; + js::TypedArrayObject& ta = obj->as<js::TypedArrayObject>(); + if (ta.isSharedMemory()) { + // Must opt in to use shared memory. For now, don't. + // + // (It is incorrect to read into the buffer without + // synchronization since that can create a race. A + // lock here won't fix it - both sides must + // participate. So what one must do is to create a + // temporary buffer, read into that, and use a + // race-safe primitive to copy memory into the + // buffer.) + JS_ReportError(cx, "can't read %s: shared memory buffer", pathname); + return nullptr; + } + char* buf = static_cast<char*>(ta.viewDataUnshared()); + size_t cc = fread(buf, 1, len, file); + if (cc != len) { + JS_ReportError(cx, "can't read %s: %s", pathname, + (ptrdiff_t(cc) < 0) ? strerror(errno) : "short read"); + obj = nullptr; + } + } + } + return obj; +} +#endif + +#ifdef NOTYET +static bool +ReadFile(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() < 1 || args.length() > 2) { + JS_ReportErrorNumber(cx, js::shell::my_GetErrorMessage, nullptr, + args.length() < 1 ? JSSMSG_NOT_ENOUGH_ARGS : JSSMSG_TOO_MANY_ARGS, + "snarf"); + return false; + } + + if (!args[0].isString() || (args.length() == 2 && !args[1].isString())) { + JS_ReportErrorNumber(cx, js::shell::my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "snarf"); + return false; + } + + RootedString givenPath(cx, args[0].toString()); + RootedString str(cx, js::shell::ResolvePath(cx, givenPath, scriptRelative ? ScriptRelative : RootRelative)); + if (!str) + return false; + + JSAutoByteString filename(cx, str); + if (!filename) + return false; + + if (args.length() > 1) { + JSString* opt = JS::ToString(cx, args[1]); + if (!opt) + return false; + bool match; + if (!JS_StringEqualsAscii(cx, opt, "binary", &match)) + return false; + if (match) { + JSObject* obj; + if (!(obj = FileAsTypedArray(cx, filename.ptr()))) + return false; + args.rval().setObject(*obj); + return true; + } + } + + if (!(str = FileAsString(cx, filename.ptr()))) + return false; + args.rval().setString(str); + return true; +} +#endif + +#ifdef NOTYET +static bool +osfile_readFile(JSContext* cx, unsigned argc, Value* vp) +{ + return ReadFile(cx, argc, vp, false); +} +#endif + +#ifdef NOTYET +static bool +osfile_readRelativeToScript(JSContext* cx, unsigned argc, Value* vp) +{ + return ReadFile(cx, argc, vp, true); +} +#endif + +#ifdef NOTYET +static bool +osfile_writeTypedArrayToFile(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() != 2 || + !args[0].isString() || + !args[1].isObject() || + !args[1].toObject().is<TypedArrayObject>()) + { + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, + JSSMSG_INVALID_ARGS, "writeTypedArrayToFile"); + return false; + } + + RootedString givenPath(cx, args[0].toString()); + RootedString str(cx, ResolvePath(cx, givenPath, RootRelative)); + if (!str) + return false; + + JSAutoByteString filename(cx, str); + if (!filename) + return false; + + FILE* file = fopen(filename.ptr(), "wb"); + if (!file) { + JS_ReportError(cx, "can't open %s: %s", filename.ptr(), strerror(errno)); + return false; + } + AutoCloseFile autoClose(file); + + TypedArrayObject* obj = &args[1].toObject().as<TypedArrayObject>(); + + if (obj->isSharedMemory()) { + // Must opt in to use shared memory. For now, don't. + // + // See further comments in FileAsTypedArray, above. + JS_ReportError(cx, "can't write %s: shared memory buffer", filename.ptr()); + return false; + } + void* buf = obj->viewDataUnshared(); + if (fwrite(buf, obj->bytesPerElement(), obj->length(), file) != obj->length() || + !autoClose.release()) + { + JS_ReportError(cx, "can't write %s", filename.ptr()); + return false; + } + + args.rval().setUndefined(); + return true; +} +#endif + +#ifdef NOTYET +static bool +Redirect(JSContext* cx, FILE* fp, HandleString relFilename) +{ + RootedString filename(cx, ResolvePath(cx, relFilename, RootRelative)); + if (!filename) + return false; + JSAutoByteString filenameABS(cx, filename); + if (!filenameABS) + return false; + if (freopen(filenameABS.ptr(), "wb", fp) == nullptr) { + JS_ReportError(cx, "cannot redirect to %s: %s", filenameABS.ptr(), strerror(errno)); + return false; + } + return true; +} +#endif + +#ifdef NOTYET +static bool +osfile_redirect(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() < 1 || args.length() > 2) { + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "redirect"); + return false; + } + + if (args[0].isString()) { + RootedString stdoutPath(cx, args[0].toString()); + if (!stdoutPath) + return false; + if (!Redirect(cx, stdout, stdoutPath)) + return false; + } + + if (args.length() > 1 && args[1].isString()) { + RootedString stderrPath(cx, args[1].toString()); + if (!stderrPath) + return false; + if (!Redirect(cx, stderr, stderrPath)) + return false; + } + + args.rval().setUndefined(); + return true; +} +#endif + +#ifdef NOTYET +static const JSFunctionSpecWithHelp osfile_functions[] = { + JS_FN_HELP("readFile", osfile_readFile, 1, 0, +"readFile(filename, [\"binary\"])", +" Read filename into returned string. Filename is relative to the current\n" + " working directory."), + + JS_FN_HELP("readRelativeToScript", osfile_readRelativeToScript, 1, 0, +"readRelativeToScript(filename, [\"binary\"])", +" Read filename into returned string. Filename is relative to the directory\n" +" containing the current script."), + + JS_FS_HELP_END +}; +#endif + +#ifdef NOTYET +static const JSFunctionSpecWithHelp osfile_unsafe_functions[] = { + JS_FN_HELP("writeTypedArrayToFile", osfile_writeTypedArrayToFile, 2, 0, +"writeTypedArrayToFile(filename, data)", +" Write the contents of a typed array to the named file."), + + JS_FN_HELP("redirect", osfile_redirect, 2, 0, +"redirect(stdoutFilename[, stderrFilename])", +" Redirect stdout and/or stderr to the named file. Pass undefined to avoid\n" +" redirecting. Filenames are relative to the current working directory."), + + JS_FS_HELP_END +}; +#endif + +#ifdef NOTYET +static bool +ospath_isAbsolute(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() != 1 || !args[0].isString()) { + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "isAbsolute"); + return false; + } + + JSAutoByteString path(cx, args[0].toString()); + if (!path) + return false; + + args.rval().setBoolean(IsAbsolutePath(path)); + return true; +} +#endif + +#ifdef NOTYET +static bool +ospath_join(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() < 1) { + JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, JSSMSG_INVALID_ARGS, "join"); + return false; + } + + // This function doesn't take into account some aspects of Windows paths, + // e.g. the drive letter is always reset when an absolute path is appended. + + StringBuffer buffer(cx); + + for (unsigned i = 0; i < args.length(); i++) { + if (!args[i].isString()) { + JS_ReportError(cx, "join expects string arguments only"); + return false; + } + + JSAutoByteString path(cx, args[i].toString()); + if (!path) + return false; + + if (IsAbsolutePath(path)) { + MOZ_ALWAYS_TRUE(buffer.resize(0)); + } else if (i != 0) { + if (!buffer.append(PathSeparator)) + return false; + } + + if (!buffer.append(args[i].toString())) + return false; + } + + JSString* result = buffer.finishString(); + if (!result) + return false; + + args.rval().setString(result); + return true; +} +#endif + +#ifdef NOTYET +static const JSFunctionSpecWithHelp ospath_functions[] = { + JS_FN_HELP("isAbsolute", ospath_isAbsolute, 1, 0, +"isAbsolute(path)", +" Return whether the given path is absolute."), + + JS_FN_HELP("join", ospath_join, 1, 0, +"join(paths...)", +" Join one or more path components in a platform independent way."), + + JS_FS_HELP_END +}; +#endif + +#ifdef NOTYET +static bool +os_getenv(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + if (args.length() < 1) { + JS_ReportError(cx, "os.getenv requires 1 argument"); + return false; + } + RootedString key(cx, ToString(cx, args[0])); + if (!key) + return false; + JSAutoByteString keyBytes; + if (!keyBytes.encodeUtf8(cx, key)) + return false; + + if (const char* valueBytes = getenv(keyBytes.ptr())) { + RootedString value(cx, JS_NewStringCopyZ(cx, valueBytes)); + if (!value) + return false; + args.rval().setString(value); + } else { + args.rval().setUndefined(); + } + return true; +} +#endif + +#ifdef NOTYET +static bool +os_getpid(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + if (args.length() != 0) { + JS_ReportError(cx, "os.getpid takes no arguments"); + return false; + } + args.rval().setInt32(getpid()); + return true; +} +#endif + +#if !defined(XP_WIN) -#include "jswrapper.h" +// There are two possible definitions of strerror_r floating around. The GNU +// one returns a char* which may or may not be the buffer you passed in. The +// other one returns an integer status code, and always writes the result into +// the provided buffer. -using namespace JS; +#ifdef NOTYET +inline char* +strerror_message(int result, char* buffer) +{ + return result == 0 ? buffer : nullptr; +} +#endif -#define _RPMJSS_INTERNAL -#include <rpmjss.h> +#ifdef NOTYET +inline char* +strerror_message(char* result, char* buffer) +{ + return result; +} +#endif -#include "debug.h" +#endif -/*==============================================================*/ -static bool -global_enumerate(JSContext* cx, HandleObject obj) +#ifdef NOTYET +static void +ReportSysError(JSContext* cx, const char* prefix) { -#ifdef LAZY_STANDARD_CLASSES - return JS_EnumerateStandardClasses(cx, obj); + char buffer[200]; + +#if defined(XP_WIN) + strerror_s(buffer, sizeof(buffer), errno); + const char* errstr = buffer; #else - return true; + const char* errstr = strerror_message(strerror_r(errno, buffer, sizeof(buffer)), buffer); +#endif + + if (!errstr) + errstr = "unknown error"; + + size_t nbytes = strlen(prefix) + strlen(errstr) + 3; + char* final = (char*) js_malloc(nbytes); + if (!final) { + JS_ReportOutOfMemory(cx); + return; + } + +#ifdef XP_WIN + _snprintf(final, nbytes, "%s: %s", prefix, errstr); +#else + snprintf(final, nbytes, "%s: %s", prefix, errstr); #endif + + JS_ReportError(cx, final); + js_free(final); } +#endif +#ifdef NOTYET static bool -global_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* resolvedp) +os_system(JSContext* cx, unsigned argc, Value* vp) { -#ifdef LAZY_STANDARD_CLASSES - if (!JS_ResolveStandardClass(cx, obj, id, resolvedp)) + CallArgs args = CallArgsFromVp(argc, vp); + + if (args.length() == 0) { + JS_ReportError(cx, "os.system requires 1 argument"); return false; -#endif + } + + JSString* str = JS::ToString(cx, args[0]); + if (!str) + return false; + + JSAutoByteString command(cx, str); + if (!command) + return false; + + int result = system(command.ptr()); + if (result == -1) { + ReportSysError(cx, "system call failed"); + return false; + } + + args.rval().setInt32(result); return true; } +#endif +#ifndef XP_WIN +#ifdef NOTYET static bool -global_mayResolve(const JSAtomState& names, jsid id, JSObject* maybeObj) +os_spawn(JSContext* cx, unsigned argc, Value* vp) { - return JS_MayResolveStandardClass(names, id, maybeObj); -} + CallArgs args = CallArgsFromVp(argc, vp); -static JSClass global_class = { - "global", - JSCLASS_GLOBAL_FLAGS, - nullptr, - nullptr, - nullptr, - nullptr, - global_enumerate, - global_resolve, - global_mayResolve, - nullptr, - nullptr, - nullptr, - nullptr, - JS_GlobalObjectTraceHook -}; + if (args.length() == 0) { + JS_ReportError(cx, "os.spawn requires 1 argument"); + return false; + } -static int rpmjss_nopens; + JSString* str = JS::ToString(cx, args[0]); + if (!str) + return false; -static int _rpmjss45_debug; -#define SPEW(_fmt, ...) \ - if (_rpmjss45_debug) \ - fprintf(stderr, _fmt, __VA_ARGS__) + JSAutoByteString command(cx, str); + if (!command) + return false; -/*==============================================================*/ -typedef struct JSI_s * JSI_t; -struct JSI_s { - JSRuntime *rt; - JSContext *cx; - JSObject *global; -}; + int32_t childPid = fork(); + if (childPid == -1) { + ReportSysError(cx, "fork failed"); + return false; + } -static void -rpmjssReportError(JSContext *cx, const char *message, JSErrorReport *report) -{ - fprintf(stderr, "%s:%u:%s\n", - report->filename ? report->filename : "<no filename=\"filename\">", - (unsigned int) report->lineno, message); + if (childPid) { + args.rval().setInt32(childPid); + return true; + } + + // We are in the child + + const char* cmd[] = {"sh", "-c", nullptr, nullptr}; + cmd[2] = command.ptr(); + + execvp("sh", (char * const*)cmd); + exit(1); } +#endif -static void -rpmjssOOMCallback(JSContext* cx, void* data) -{ #ifdef NOTYET - // If a script is running, the engine is about to throw the string "out of - // memory", which may or may not be caught. Otherwise the engine will just - // unwind and return null/false, with no exception set. - if (!JS_IsRunning(cx)) - GetShellRuntime(cx)->gotError = true; +static bool +os_kill(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + int32_t pid; + if (args.length() < 1) { + JS_ReportError(cx, "os.kill requires 1 argument"); + return false; + } + if (!JS::ToInt32(cx, args[0], &pid)) + return false; + + // It is too easy to kill yourself accidentally with os.kill("goose"). + if (pid == 0 && !args[0].isInt32()) { + JS_ReportError(cx, "os.kill requires numeric pid"); + return false; + } + + int signal = SIGINT; + if (args.length() > 1) { + if (!JS::ToInt32(cx, args[1], &signal)) + return false; + } + + int status = kill(pid, signal); + if (status == -1) { + ReportSysError(cx, "kill failed"); + return false; + } + + args.rval().setUndefined(); + return true; +} #endif + +#ifdef NOTYET +static bool +os_waitpid(JSContext* cx, unsigned argc, Value* vp) +{ + CallArgs args = CallArgsFromVp(argc, vp); + + int32_t pid; + if (args.length() == 0) { + pid = -1; + } else { + if (!JS::ToInt32(cx, args[0], &pid)) + return false; + } + + bool nohang = false; + if (args.length() >= 2) + nohang = JS::ToBoolean(args[1]); + + int status = 0; + pid_t result = waitpid(pid, &status, nohang ? WNOHANG : 0); + if (result == -1) { + ReportSysError(cx, "os.waitpid failed"); + return false; + } + + RootedObject info(cx, JS_NewPlainObject(cx)); + if (!info) + return false; + + RootedValue v(cx); + if (result != 0) { + v.setInt32(result); + if (!JS_DefineProperty(cx, info, "pid", v, JSPROP_ENUMERATE)) + return false; + if (WIFEXITED(status)) { + v.setInt32(WEXITSTATUS(status)); + if (!JS_DefineProperty(cx, info, "exitStatus", v, JSPROP_ENUMERATE)) + return false; + } + } + + args.rval().setObject(*info); + return true; } +#endif /* NOTYET */ +#endif /* !defined(XP_WIN) */ -enum JSShellErrNum { -#define MSG_DEF(name, count, exception, format) \ - name, -#include "jsshell.msg" -#undef MSG_DEF - JSShellErr_Limit -}; +#ifdef NOTYET +static const JSFunctionSpecWithHelp os_functions[] = { + JS_FN_HELP("getenv", os_getenv, 1, 0, +"getenv(variable)", +" Get the value of an environment variable."), + + JS_FN_HELP("getpid", os_getpid, 0, 0, +"getpid()", +" Return the current process id."), + + JS_FN_HELP("system", os_system, 1, 0, +"system(command)", +" Execute command on the current host, returning result code or throwing an\n" +" exception on failure."), + +#ifndef XP_WIN + JS_FN_HELP("spawn", os_spawn, 1, 0, +"spawn(command)", +" Start up a separate process running the given command. Returns the pid."), + + JS_FN_HELP("kill", os_kill, 1, 0, +"kill(pid[, signal])", +" Send a signal to the given pid. The default signal is SIGINT. The signal\n" +" passed in must be numeric, if given."), + + JS_FN_HELP("waitpid", os_waitpid, 1, 0, +"waitpid(pid[, nohang])", +" Calls waitpid(). 'nohang' is a boolean indicating whether to pass WNOHANG.\n" +" The return value is an object containing a 'pid' field, if a process was waitable\n" +" and an 'exitStatus' field if a pid exited."), +#endif -static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] = { -#define MSG_DEF(name, count, exception, format) \ - { format, count, JSEXN_ERR } , -#include "jsshell.msg" -#undef MSG_DEF + JS_FS_HELP_END }; +#endif -const JSErrorFormatString* -my_GetErrorMessage(void* userRef, const unsigned errorNumber) +#ifdef NOTYET +bool +DefineOS(JSContext* cx, HandleObject global, bool fuzzingSafe) { - if (errorNumber == 0 || errorNumber >= JSShellErr_Limit) - return nullptr; + RootedObject obj(cx, JS_NewPlainObject(cx)); + if (!obj || !JS_DefineProperty(cx, global, "os", obj, 0)) + return false; - return &jsShell_ErrorFormatString[errorNumber]; + if (!fuzzingSafe) { + if (!JS_DefineFunctionsWithHelp(cx, obj, os_functions)) + return false; + } + + RootedObject osfile(cx, JS_NewPlainObject(cx)); + if (!osfile || + !JS_DefineFunctionsWithHelp(cx, osfile, osfile_functions) || + !JS_DefineProperty(cx, obj, "file", osfile, 0)) + { + return false; + } + + if (!fuzzingSafe) { + if (!JS_DefineFunctionsWithHelp(cx, osfile, osfile_unsafe_functions)) + return false; + } + + RootedObject ospath(cx, JS_NewPlainObject(cx)); + if (!ospath || + !JS_DefineFunctionsWithHelp(cx, ospath, ospath_functions) || + !JS_DefineProperty(cx, obj, "path", ospath, 0)) + { + return false; + } + + // For backwards compatibility, expose various os.file.* functions as + // direct methods on the global. + RootedValue val(cx); + + struct { + const char* src; + const char* dst; + } osfile_exports[] = { + { "readFile", "read" }, + { "readFile", "snarf" }, + { "readRelativeToScript", "readRelativeToScript" }, + { "redirect", "redirect" } + }; + + for (auto pair : osfile_exports) { + if (!JS_GetProperty(cx, osfile, pair.src, &val)) + return false; + if (val.isObject()) { + RootedObject function(cx, &val.toObject()); + if (!JS_DefineProperty(cx, global, pair.dst, function, 0)) + return false; + } + } + + return true; } +#endif + +#ifdef NOTYET +} // namespace shell +} // namespace js +#endif /*==============================================================*/ enum JSShellExitCode { @@ -163,34 +1030,6 @@ }; #endif -// Shell state set once at startup. -static bool enableCodeCoverage = false; -static bool enableDisassemblyDumps = false; -static bool offthreadCompilation = false; -static bool enableBaseline = false; -static bool enableIon = false; -static bool enableAsmJS = false; -static bool enableNativeRegExp = false; -static bool enableUnboxedArrays = false; -#ifdef JS_GC_ZEAL -static char gZealStr[128]; -#endif -static bool printTiming = false; -static const char* jsCacheDir = nullptr; -static const char* jsCacheAsmJSPath = nullptr; -static FILE* gErrFile = nullptr; -static FILE* gOutFile = nullptr; -static bool reportWarnings = true; -static bool compileOnly = false; -static bool fuzzingSafe = false; -static bool disableOOMFunctions = false; -static const char* moduleLoadPath = "."; - -#ifdef DEBUG -static bool dumpEntrainedVariables = false; -static bool OOM_printAllocationCount = false; -#endif - #ifdef NOTYET ShellRuntime::ShellRuntime() : isWorker(false), @@ -233,7 +1072,7 @@ } else if (args[0].isDouble()) { double fv = args[0].toDouble(); int32_t fvi; - if (mozilla::NumberEqualsInt32(fv, &fvi)) + if (NumberEqualsInt32(fv, &fvi)) v = fvi; } if (v < 0 || v > JSVERSION_LATEST) { @@ -394,7 +1233,7 @@ return true; } -#ifdef NOTYET +#ifndef NOTYET static bool LoadScript(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative) { @@ -435,7 +1274,7 @@ } #endif -#ifdef NOTYET +#ifndef NOTYET static bool Load(JSContext* cx, unsigned argc, Value* vp) { @@ -443,7 +1282,7 @@ } #endif -#ifdef NOTYET +#ifndef NOTYET static bool LoadScriptRelativeToScript(JSContext* cx, unsigned argc, Value* vp) { @@ -598,7 +1437,7 @@ "CacheEntryObject", JSCLASS_HAS_RESERVED_SLOTS(2) }; -#ifdef NOTYET +#ifndef NOTYET static bool CacheEntry(JSContext* cx, unsigned argc, JS::Value* vp) { @@ -618,13 +1457,17 @@ args.rval().setObject(*obj); return true; } +#endif +#ifndef NOTYET static bool CacheEntry_isCacheEntry(JSObject* cache) { return JS_GetClass(cache) == &CacheEntry_class; } +#endif +#ifndef NOTYET static JSString* CacheEntry_getSource(HandleObject cache) { @@ -635,7 +1478,9 @@ return v.toString(); } +#endif +#ifdef NOTYET static uint8_t* CacheEntry_getBytecode(HandleObject cache, uint32_t* length) { @@ -648,7 +1493,9 @@ *length = arrayBuffer->byteLength(); return arrayBuffer->dataPointer(); } +#endif +#ifdef NOTYET static bool CacheEntry_setBytecode(JSContext* cx, HandleObject cache, uint8_t* buffer, uint32_t length) { @@ -1145,6 +1992,7 @@ static bool PutStr(JSContext* cx, unsigned argc, Value* vp) { + FILE* gOutFile = stdout; CallArgs args = CallArgsFromVp(argc, vp); if (args.length() != 0) { @@ -1202,6 +2050,7 @@ static bool Print(JSContext* cx, unsigned argc, Value* vp) { + FILE* gOutFile = stdout; CallArgs args = CallArgsFromVp(argc, vp); return PrintInternal(cx, args, gOutFile); } @@ -1209,6 +2058,7 @@ static bool PrintErr(JSContext* cx, unsigned argc, Value* vp) { + FILE* gErrFile = stderr; CallArgs args = CallArgsFromVp(argc, vp); return PrintInternal(cx, args, gErrFile); } @@ -1256,9 +2106,9 @@ static const JSFunctionSpec global_functions[] = { JS_FN("version", Version, 0,0), JS_FN("options", Options, 0,0), -#ifdef NOTYET JS_FN("load", Load, 1,0), JS_FN("loadRelativeToScript", LoadScriptRelativeToScript, 1,0), +#ifdef NOTYET JS_FN("evaluate", Evaluate, 2,0), JS_FN("run", Run, 1,0), JS_FN("readline", ReadLine, 0,0), @@ -1862,36 +2712,64 @@ JSI_t I = NULL; uint32_t flags = jss->flags; - static uint32_t _maxbytes = 8L * 1024L * 1024L; static size_t _stackChunkSize = 8192; JSPrincipals * _principals = NULL; bool ok; + // Start the engine. if (rpmjss_nopens++ == 0) JS_Init(); I = (JSI_t) calloc(1, sizeof(*I)); assert(I); - I->rt = JS_NewRuntime(_maxbytes); -assert(I->rt); - JS_SetRuntimePrivate(I->rt, (void *)jss); - - I->cx = JS_NewContext(I->rt, _stackChunkSize); -assert(I->cx); - JS_SetContextPrivate(I->cx, (void *)jss); + static uint32_t _maxbytes = 8L * 1024L * 1024L; + static uint32_t _maxNurseryBytes = JS::DefaultNurseryBytes; + JSRuntime * _parentRuntime = nullptr; + JSRuntime * rt = JS_NewRuntime(_maxbytes, _maxNurseryBytes, _parentRuntime); +assert(rt); + JS_SetRuntimePrivate(rt, (void *)jss); + I->rt = rt; + + JS_SetErrorReporter(rt, rpmjssReportError); + JS::SetOutOfMemoryCallback(rt, rpmjssOOMCallback, nullptr); + + // XXX SetRuntimeOptions(rt, op); + + // XXX JS_SetGCParameter(rt, JSGC_MAX_BYTES, 0xffffffff); + // XXX JS_SetGCParametersBasedOnAvailableMemory(rt, availMem); + + // XXX JS_SetTrustedPrincipals(rt, &ShellPrincipals::fullyTrusted); + // XXX JS_SetSecurityCallbacks(rt, &ShellPrincipals::securityCallbacks); + // XXX JS_InitDestroyPrincipalsCallback(rt, ShellPrincipals::destroy); + // XXX JS_SetInterruptCallback(rt, ShellInterruptCallback); + + // XXX JS::SetAsmJSCacheOps(rt, &asmJSCacheOps); + // XXX JS_SetNativeStackQuota(rt, gMaxStackSize); + + // XXX JS::dbg::SetDebuggerMallocSizeOf(rt, moz_malloc_size_of); + + JSContext * cx = JS_NewContext(rt, _stackChunkSize); +assert(cx); + JS_SetContextPrivate(cx, (void *)jss); /* XXX JSI_t I instead? */ + // XXX JS_SetSecondContextPrivate(cx, (void *)jss); + I->cx = cx; + + // XXX JS_SetGCParameter(rt, JSGC_MODE, JSGC_MODE_INCREMENTAL); + // XXX JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 16 * 1024 * 1024 ); + // XXX JS::SetLargeAllocationFailureCallback(rt, my_LargeAllocFailCallback, (void *)cx); - JS_SetErrorReporter(I->rt, rpmjssReportError); - SetOutOfMemoryCallback(I->rt, rpmjssOOMCallback, nullptr); + // XXX js::SetPreserveWrapperCallback(rt, DummyPreserveWrapperCallback); - { - RootedObject glob(I->cx); + // result = Shell(cx, &op, envp); + { + RootedObject glob(cx); JS::CompartmentOptions options; options.setVersion(JSVERSION_DEFAULT); - glob = NewGlobalObject(I->cx, options, _principals); + glob = NewGlobalObject(cx, options, _principals); +assert(glob); I->global = glob; -assert(I->global); - } + } #ifdef HACK ok = JS_InitStandardClasses(I->cx, global); @@ -1975,13 +2853,248 @@ #if defined(RPMJSS_SELF_TEST) #include <rpmio.h> #include <argv.h> +#include <poptIO.h> +/*==============================================================*/ struct rpmjss_s _jss; rpmjss jss = &_jss; -/*==============================================================*/ -int main(int argc, const char *argv[]) +struct poptOption rpmjssIPoptTable[] = { + { "allow", '\0', POPT_BIT_SET, &_jss.flags, RPMJSS_FLAGS_ALLOW, + N_("Allow (read-only) access to caller's environment"), NULL }, + { "nocache", '\0', POPT_BIT_SET, &_jss.flags, RPMJSS_FLAGS_NOCACHE, + N_("Disables compiler caching via JSScript XDR serialization"), NULL }, + { "loadrc", '\0', POPT_BIT_SET, &_jss.flags, RPMJSS_FLAGS_LOADRC, + N_("Load RC file for interpreter based on script filename."), NULL }, + { "nowarn", '\0', POPT_BIT_SET, &_jss.flags, RPMJSS_FLAGS_NOWARN, + N_("Do not report warnings"), NULL }, + + { "norelimit", '\0', POPT_BIT_CLR, &_jss.flags, RPMJSS_FLAGS_RELIMIT, + N_("Do not limit regexps to n^3 levels of backtracking"), NULL }, + { "nojit", '\0', POPT_BIT_CLR, &_jss.flags, RPMJSS_FLAGS_JIT, + N_("Disable nanojit"), NULL }, + { "nostrict", '\0', POPT_BIT_CLR, &_jss.flags, RPMJSS_FLAGS_STRICT, + N_("Disable Strict mode"), NULL }, + { "noutf8", '\0', POPT_BIT_SET, &_jss.flags, RPMJSS_FLAGS_NOUTF8, + N_("Disable UTF-8 C string processing"), NULL }, + { "xml", '\0', POPT_BIT_SET, &_jss.flags, RPMJSS_FLAGS_XML, + N_("Parse <!-- comments --> as E4X tokens"), NULL }, + + { "anonfunfix", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, &_jss.flags, RPMJSS_FLAGS_ANONFUNFIX, + N_("Parse //@line number [\"filename\"] for XUL"), NULL }, + { "atline", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, &_jss.flags, RPMJSS_FLAGS_ATLINE, + N_("Parse //@line number [\"filename\"] for XUL"), NULL }, + { "werror", '\0', POPT_BIT_SET|POPT_ARGFLAG_DOC_HIDDEN, &_jss.flags, RPMJSS_FLAGS_WERROR, + N_("Convert warnings to errors"), NULL }, + POPT_TABLEEND +}; + +static const char *Ifile; +static const char *Imodule; +static const char *Icode; +static const char *js_cache; +static const char *script; +static const char **scriptArgs; +static int thread_count; + +typedef enum rpmjssIonFlags_e { + ION_SHARED_STUBS = (1 << 0), + ION_SCALAR_REPLACEMENT = (1 << 1), + ION_GVN = (1 << 2), + ION_LICM = (1 << 3), + ION_EDGECASE_ANALYSIS = (1 << 4), + ION_PGO = (1 << 5), + ION_RANGE_ANALYSIS = (1 << 6), + ION_SINCOS = (1 << 7), + ION_SINK = (1 << 8), + ION_LOOP_UNROLLING = (1 << 9), + ION_INSTRUCTION_REORDERING = (1 << 10), + ION_CHECK_RANGE_ANALYSIS = (1 << 11), + ION_EXTRA_CHECKS = (1 << 12), + ION_INLINING = (1 << 13), + ION_OSR = (1 << 14), + ION_LIMIT_SCRIPT_SIZE = (1 << 15), + ION_EAGER = (1 << 16), + ION_OFFTHREAD_COMPILE = (1 << 17), + ION_PARALLEL_COMPILE = (1 << 18), +} rpmjssIonFlags; + +rpmjssIonFlags _ionf = (rpmjssIonFlags) ( + ION_SCALAR_REPLACEMENT | + ION_GVN | + ION_LICM | + ION_RANGE_ANALYSIS | + ION_SINCOS | + ION_INLINING | + ION_OSR | + ION_LIMIT_SCRIPT_SIZE | + ION_EAGER | + ION_OFFTHREAD_COMPILE | + 0 +); + +static int ion_warmup_threshold; +static const char * ion_regalloc; + +struct poptOption rpmjssIonPoptTable[] = { + { "ion-shared-stubs", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_SHARED_STUBS, + N_("Use shared stubs (default: off)"), NULL }, + { "ion-scalar-replacement", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_SCALAR_REPLACEMENT, + N_("Scalar replacement (default: on)"), NULL }, + { "ion-gvn", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_GVN, + N_("Global value numbering (default: on)"), NULL }, + { "ion-licm", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_LICM, + N_("Loop invariant code motion (default: on)"), NULL }, + { "ion-edgecase-analysis", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_EDGECASE_ANALYSIS, + N_("Find edge cases where Ion can avoid bailouts (default: off)"), NULL }, + { "ion-pgo", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_PGO, + N_("Profile guided optimization (default: off)"), NULL }, + { "ion-range-analysis", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_RANGE_ANALYSIS, + N_("Range analysis (default: on)"), NULL }, + { "ion-sincos", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_SINCOS, + N_("Replace sin(x)/cos(x) to sincos(x) (default: on)"), NULL }, + { "ion-sink", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_SINK, + N_("Sink code motion (default: off)"), NULL }, + { "ion-loop-unrolling", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_LOOP_UNROLLING, + N_("Loop unrolling (default: off)"), NULL }, + { "ion-instruction-reordering", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_INSTRUCTION_REORDERING, + N_("Instruction reordering (default: off)"), NULL }, + { "ion-check-range-analysis", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_CHECK_RANGE_ANALYSIS, + N_("Range analysis checking (default: off)"), NULL }, + { "ion-extra-checks", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_EXTRA_CHECKS, + N_("Perform extra dynamic validation checks (default: off)"), NULL }, + { "ion-inlining", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_INLINING, + N_("Inline methods where possible (default: on)"), NULL }, + { "ion-osr", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_OSR, + N_("On-Stack Replacement(default: on)"), NULL }, + { "ion-limit-script-size", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_LIMIT_SCRIPT_SIZE, + N_("Don't compile large scripts(default: on)"), NULL }, + { "ion-regalloc", '\0', POPT_ARG_STRING, + &ion_regalloc, 0, + N_("Specify Ion register allocation <mode>"), N_("<mode>") }, + { "ion-eager", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_EAGER, + N_("Always ion-compile methods (default: on)"), NULL }, + { "ion-offthread-compile", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_OFFTHREAD_COMPILE, + N_("Compile scripts off thread (default: on)"), NULL }, + { "ion-parallel-compile", '\0', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, + &_ionf, ION_PARALLEL_COMPILE, + N_("Parallel compilation (deprecated: use --ion-offthread-compile)"), NULL }, + POPT_TABLEEND +}; + +typedef enum rpmjssXFlags_e { + XF_INTERACTIVE = (1 << 0), + XF_COMPILE_ONLY = (1 << 1), + XF_WARNINGS = (1 << 2), + XF_STRICT = (1 << 3), + XF_DUMP_BYTECODE = (1 << 4), + XF_PRINT_TIMING = (1 << 5), + XF_NO_CACHE_PER_PROCESS = (1 << 6), + XF_CODE_COVERAGE = (1 << 7), + XF_PRINT_ALLOC = (1 << 8), + XF_NO_ION = (1 << 9), + XF_NO_ASMJS = (1 << 10), + XF_NATIVE_REGEXP = (1 << 11), + XF_UNBOXED_OBJECTS = (1 << 12), + XF_UNBOXED_ARRAYS = (1 << 13), + XF_BASELINE = (1 << 14), + XF_BASELINE_EAGER = (1 << 15), + XF_NONWRITABLE_JITCODE = (1 << 16), + XF_NO_FPU = (1 << 17), + XF_NO_SSE3 = (1 << 18), + XF_NO_SSE4 = (1 << 19), + XF_NO_AVX = (1 << 20), + XF_FUZZING_SAFE = (1 << 21), + XF_DISABLE_OOM = (1 << 22), + XF_NO_THREADS = (1 << 23), + XF_DUMP_ENTRAINED_VARIABLES = (1 << 24), + XF_NO_GGC = (1 << 25), + XF_NO_CGC = (1 << 26), + XF_ARM_HWCAP = (1 << 27), + XF_ARM_SIM_ICACHE_CHECKS = (1 << 28), + XF_MIPS_SIM_ICACHE_CHECKS = (1 << 29), +} rpmjssXFlags; +rpmjssXFlags _xf; + +static int baseline_warmup_threshold; + +static int available_memory; +static int asm_pool_max_offset; +static int arm_sim_stop_at; +static int mips_sim_stop_at; +static int nursery_size; +static int gc_zeal; +static const char *module_load_path; + +struct poptOption rpmjssOptionsTable[] = { + { "file", 'f', POPT_ARG_STRING, &Ifile, 0, + N_("File <path> to run"), N_("<path>") }, + { "module", 'm', POPT_ARG_STRING, &Imodule, 0, + N_("Module <path> to run"), N_("<path>") }, + { "execute", 'e', POPT_ARG_STRING, &Icode, 0, + N_("Inline <code> to run"), N_("<code>") }, + { "shell", 'i', POPT_BIT_SET, &_xf, XF_INTERACTIVE, + N_("Enter prompt after running code"), NULL }, + { "compileonly", 'c', POPT_BIT_SET, &_xf, XF_COMPILE_ONLY, + N_("Only compile, don't run (syntax checking mode)"), NULL }, + { "warnings", 'w', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_xf, XF_WARNINGS, + N_("Emit warnings"), NULL }, + { "strict", 's', POPT_BIT_SET|POPT_ARGFLAG_TOGGLE, &_xf, XF_STRICT, + N_("Check strictness"), NULL }, + { "dump-bytecode", 'D', POPT_BIT_SET, &_xf, XF_DUMP_BYTECODE, + N_("Dump bytecode with exec count for all scripts"), NULL }, + { "print-timing", 'b', POPT_BIT_SET, &_xf, XF_PRINT_TIMING, + N_("Dump bytecode with exec count for all scripts"), NULL }, + { "js-cache", '\0', POPT_ARG_STRING, &js_cache, 0, + N_("Enable JS caching in <dir>"), N_("<dir>") }, + { "no-js-cache-per-process",'\0', POPT_BIT_SET, &_xf, XF_NO_CACHE_PER_PROCESS, + N_("Deactivate per-process caching"), NULL }, + { "code-coverage", '\0', POPT_BIT_SET, &_xf, XF_CODE_COVERAGE, + N_("Enable code coverage insturmentation"), NULL }, + { "print-alloc", 'O', POPT_BIT_SET, &_xf, XF_PRINT_ALLOC, + N_("Print no. of allocatsions at exit"), NULL }, + { "script", '\0', POPT_ARG_STRING, &script, 0, + N_("Script <path> to run"), N_("<path>") }, + { "scriptArgs", '\0', POPT_ARG_STRING, &scriptArgs, 0, + N_("Script <path> to run"), N_("<path>") }, + { "thread-count", '\0', POPT_ARG_INT, &thread_count, 0, + N_("Use <count> auxiliary threads"), N_("<count>") }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmjssIPoptTable, 0, + N_("JS interpreter options:"), NULL }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmjssIonPoptTable, 0, + N_("JS ion interpreter options:"), NULL }, + + { NULL, '\0', POPT_ARG_INCLUDE_TABLE, rpmioAllPoptTable, 0, + N_("Common options for all rpmio executables:"), NULL }, + + POPT_AUTOALIAS + POPT_AUTOHELP + POPT_TABLEEND +}; + +int main(int argc, char *argv[]) { + poptContext con = rpmioInit(argc, argv, rpmjssOptionsTable); int rc = 0; JSI_t I = (JSI_t) mozInit(jss); @@ -2002,10 +3115,11 @@ result = _free(result); } - av = argvFree(av); - mozFini(jss); + av = argvFree(av); + con = rpmioFini(con); + return rc; } #endif /* RPMJSS_SELF_TEST */ @@ . patch -p0 <<'@@ .' Index: rpm/rpmio/rpmjss.inp ============================================================================ $ cvs diff -u -r1.1.2.2 -r1.1.2.3 rpmjss.inp --- rpm/rpmio/rpmjss.inp 25 Jun 2017 08:20:02 -0000 1.1.2.2 +++ rpm/rpmio/rpmjss.inp 25 Jun 2017 22:46:54 -0000 1.1.2.3 @@ -10,5 +10,6 @@ options("strict") options() dateNow() -var foo = "foo" -quit() +print("foo") +var foo = "bar" +print(foo) @@ . ______________________________________________________________________ RPM Package Manager http://rpm5.org CVS Sources Repository rpm-cvs@rpm5.org