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

Reply via email to