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:   24-Jun-2017 21:09:35
  Branch: rpm-5_4                          Handle: 2017062419093401

  Modified files:           (Branch: rpm-5_4)
    rpm/rpmio               rpmjs17.cpp rpmjs185.cpp rpmjs24.cpp rpmjs31.cpp
                            rpmjs38.cpp rpmjs45.cpp rpmjss.h

  Log:
    - rpmjss: return the script result.

  Summary:
    Revision    Changes     Path
    1.1.2.6     +11 -6      rpm/rpmio/rpmjs17.cpp
    1.1.2.6     +11 -6      rpm/rpmio/rpmjs185.cpp
    1.1.2.7     +11 -6      rpm/rpmio/rpmjs24.cpp
    1.1.2.7     +11 -6      rpm/rpmio/rpmjs31.cpp
    1.1.2.7     +11 -6      rpm/rpmio/rpmjs38.cpp
    1.1.2.8     +1528 -16   rpm/rpmio/rpmjs45.cpp
    1.1.2.2     +2  -1      rpm/rpmio/rpmjss.h
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs17.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.5 -r1.1.2.6 rpmjs17.cpp
  --- rpm/rpmio/rpmjs17.cpp     23 Jun 2017 06:51:22 -0000      1.1.2.5
  +++ rpm/rpmio/rpmjs17.cpp     24 Jun 2017 19:09:34 -0000      1.1.2.6
  @@ -484,8 +484,8 @@
       return I;
   }
   
  -static int mozRun(rpmjss jss,
  -             const char * script, const char * filename, int lineno)
  +static int mozRun(rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln)
   {
       JSI_t I = (JSI_t) jss->I;
   
  @@ -500,15 +500,17 @@
        JSAutoCompartment ac(I->cx, I->global);
   
        ok = JS_EvaluateScript(I->cx, I->global,
  -                     script, strlen(script), filename, lineno,
  +                     script, strlen(script), fn, ln,
                        rval.address());
        if (!ok)
            return 1;
       }
       JSString *str = rval.toString();
       char * t = JS_EncodeString(I->cx, str);
  -    printf("%s\n", t);
  -    t = _free(t);
  +    if (resultp)
  +     *resultp = t;
  +    else
  +     t = _free(t);
   
       return 0;
   }
  @@ -530,7 +532,10 @@
   
       {
        const char *script = "'hello'+'world, it is '+new Date()";
  -     rc = mozRun(jss, script, __FILE__, __LINE__);
  +     const char * result = NULL;
  +     rc = mozRun(jss, &result, script, __FILE__, __LINE__);
  +     fprintf(stderr, "<== result |%s|\n", result);
  +     result = _free(result);
       }
   
       mozFini(jss);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs185.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.5 -r1.1.2.6 rpmjs185.cpp
  --- rpm/rpmio/rpmjs185.cpp    23 Jun 2017 06:51:22 -0000      1.1.2.5
  +++ rpm/rpmio/rpmjs185.cpp    24 Jun 2017 19:09:35 -0000      1.1.2.6
  @@ -466,8 +466,8 @@
       return I;
   }
   
  -static int mozRun(rpmjss jss,
  -             const char * script, const char * filename, int lineno)
  +static int mozRun(rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln)
   {
       JSI_t I = (JSI_t) jss->I;
   
  @@ -488,15 +488,17 @@
   #endif
   
        ok = JS_EvaluateScript(I->cx, I->global,
  -                     script, strlen(script), filename, lineno,
  +                     script, strlen(script), fn, ln,
                        &rval);
        if (!ok)
            return 1;
       }
       JSString *str = JS_ValueToString(I->cx, rval);
       char * t = JS_EncodeString(I->cx, str);
  -    printf("%s\n", t);
  -    t = _free(t);
  +    if (resultp)
  +     *resultp = t;
  +    else
  +     t = _free(t);
   
       return 0;
   }
  @@ -518,7 +520,10 @@
   
       {
        const char *script = "'hello'+'world, it is '+new Date()";
  -     rc = mozRun(jss, script, __FILE__, __LINE__);
  +     const char * result = NULL;
  +     rc = mozRun(jss, &result, script, __FILE__, __LINE__);
  +     fprintf(stderr, "<== result |%s|\n", result);
  +     result = _free(result);
       }
   
       mozFini(jss);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs24.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.6 -r1.1.2.7 rpmjs24.cpp
  --- rpm/rpmio/rpmjs24.cpp     23 Jun 2017 06:51:22 -0000      1.1.2.6
  +++ rpm/rpmio/rpmjs24.cpp     24 Jun 2017 19:09:35 -0000      1.1.2.7
  @@ -103,8 +103,8 @@
       return I;
   }
   
  -static int mozRun(rpmjss jss,
  -             const char * script, const char * filename, int lineno)
  +static int mozRun(rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln)
   {
       JSI_t I = (JSI_t) jss->I;
   
  @@ -133,15 +133,17 @@
        JS_InitStandardClasses(I->cx, global);
   
        ok = JS_EvaluateScript(I->cx, global,
  -                     script, strlen(script), filename, lineno,
  +                     script, strlen(script), fn, ln,
                        rval.address());
        if (!ok)
            return 1;
       }
       JSString *str = rval.toString();
       char * t = JS_EncodeString(I->cx, str);
  -    printf("%s\n", t);
  -    t = _free(t);
  +    if (resultp)
  +     *resultp = t;
  +    else
  +     t = _free(t);
   
       return 0;
   }
  @@ -163,7 +165,10 @@
   
       {
        const char *script = "'hello'+'world, it is '+new Date()";
  -     rc = mozRun(jss, script, __FILE__, __LINE__);
  +     const char * result = NULL;
  +     rc = mozRun(jss, &result, script, __FILE__, __LINE__);
  +     fprintf(stderr, "<== result |%s|\n", result);
  +     result = _free(result);
       }
   
       mozFini(jss);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs31.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.6 -r1.1.2.7 rpmjs31.cpp
  --- rpm/rpmio/rpmjs31.cpp     23 Jun 2017 06:51:22 -0000      1.1.2.6
  +++ rpm/rpmio/rpmjs31.cpp     24 Jun 2017 19:09:35 -0000      1.1.2.7
  @@ -101,8 +101,8 @@
       return I;
   }
   
  -static int mozRun(rpmjss jss,
  -             const char * script, const char * filename, int lineno)
  +static int mozRun(rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln)
   {
       JSI_t I = (JSI_t) jss->I;
   
  @@ -130,15 +130,17 @@
        JS_InitStandardClasses(I->cx, global);
   
        ok = JS_EvaluateScript(I->cx, global,
  -                     script, strlen(script), filename, lineno,
  +                     script, strlen(script), fn, ln,
                        &rval);
        if (!ok)
            return 1;
       }
       JSString *str = rval.toString();
       char * t = JS_EncodeString(I->cx, str);
  -    printf("%s\n", t);
  -    t = _free(t);
  +    if (resultp)
  +     *resultp = t;
  +    else
  +     t = _free(t);
   
       return 0;
   }
  @@ -160,7 +162,10 @@
   
       {
        const char *script = "'hello'+'world, it is '+new Date()";
  -     rc = mozRun(jss, script, __FILE__, __LINE__);
  +     const char * result = NULL;
  +     rc = mozRun(jss, &result, script, __FILE__, __LINE__);
  +     fprintf(stderr, "<== result |%s|\n", result);
  +     result = _free(result);
       }
   
       mozFini(jss);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs38.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.6 -r1.1.2.7 rpmjs38.cpp
  --- rpm/rpmio/rpmjs38.cpp     23 Jun 2017 06:51:22 -0000      1.1.2.6
  +++ rpm/rpmio/rpmjs38.cpp     24 Jun 2017 19:09:35 -0000      1.1.2.7
  @@ -101,8 +101,8 @@
       return I;
   }
   
  -static int mozRun(rpmjss jss,
  -             const char * script, const char * filename, int lineno)
  +static int mozRun(rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln)
   {
       JSI_t I = (JSI_t) jss->I;
   
  @@ -130,15 +130,17 @@
        JS_InitStandardClasses(I->cx, global);
   
        JS::CompileOptions opts(I->cx);
  -     opts.setFileAndLine(filename, lineno);
  +     opts.setFileAndLine(fn, ln);
        ok = JS::Evaluate(I->cx, global, opts, script, strlen(script), &rval);
        if (!ok)
            return 1;
       }
       JSString *str = rval.toString();
       char * t = JS_EncodeString(I->cx, str);
  -    printf("%s\n", t);
  -    t = _free(t);
  +    if (resultp)
  +     *resultp = t;
  +    else
  +     t = _free(t);
   
       return 0;
   }
  @@ -160,7 +162,10 @@
   
       {
        const char *script = "'hello'+'world, it is '+new Date()";
  -     rc = mozRun(jss, script, __FILE__, __LINE__);
  +     const char * result = NULL;
  +     rc = mozRun(jss, &result, script, __FILE__, __LINE__);
  +     fprintf(stderr, "<== result |%s|\n", result);
  +     result = _free(result);
       }
   
       mozFini(jss);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs45.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.7 -r1.1.2.8 rpmjs45.cpp
  --- rpm/rpmio/rpmjs45.cpp     23 Jun 2017 06:51:22 -0000      1.1.2.7
  +++ rpm/rpmio/rpmjs45.cpp     24 Jun 2017 19:09:35 -0000      1.1.2.8
  @@ -200,20 +200,1527 @@
   }
   #endif       /* NOTYET */
   
  +static FILE* gErrFile = stderr;
  +static FILE* gOutFile = stdout;
  +
  +#ifdef       NOTYET
  +static bool
  +Evaluate(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() < 1 || args.length() > 2) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                             args.length() < 1 ? JSSMSG_NOT_ENOUGH_ARGS : 
JSSMSG_TOO_MANY_ARGS,
  +                             "evaluate");
  +        return false;
  +    }
  +
  +    RootedString code(cx, nullptr);
  +    RootedObject cacheEntry(cx, nullptr);
  +    if (args[0].isString()) {
  +        code = args[0].toString();
  +    } else if (args[0].isObject() && 
CacheEntry_isCacheEntry(&args[0].toObject())) {
  +        cacheEntry = &args[0].toObject();
  +        code = CacheEntry_getSource(cacheEntry);
  +    }
  +
  +    if (!code || (args.length() == 2 && args[1].isPrimitive())) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_INVALID_ARGS, "evaluate");
  +        return false;
  +    }
  +
  +    CompileOptions options(cx);
  +    JSAutoByteString fileNameBytes;
  +    bool newContext = false;
  +    RootedString displayURL(cx);
  +    RootedString sourceMapURL(cx);
  +    RootedObject global(cx, nullptr);
  +    bool catchTermination = false;
  +    bool saveFrameChain = false;
  +    bool loadBytecode = false;
  +    bool saveBytecode = false;
  +    bool assertEqBytecode = false;
  +    RootedObject callerGlobal(cx, cx->global());
  +
  +    options.setIntroductionType("js shell evaluate")
  +           .setFileAndLine("@evaluate", 1);
  +
  +    global = JS_GetGlobalForObject(cx, &args.callee());
  +    if (!global)
  +        return false;
  +
  +    if (args.length() == 2) {
  +        RootedObject opts(cx, &args[1].toObject());
  +        RootedValue v(cx);
  +
  +        if (!ParseCompileOptions(cx, options, opts, fileNameBytes))
  +            return false;
  +
  +        if (!JS_GetProperty(cx, opts, "newContext", &v))
  +            return false;
  +        if (!v.isUndefined())
  +            newContext = ToBoolean(v);
  +
  +        if (!JS_GetProperty(cx, opts, "displayURL", &v))
  +            return false;
  +        if (!v.isUndefined()) {
  +            displayURL = ToString(cx, v);
  +            if (!displayURL)
  +                return false;
  +        }
  +
  +        if (!JS_GetProperty(cx, opts, "sourceMapURL", &v))
  +            return false;
  +        if (!v.isUndefined()) {
  +            sourceMapURL = ToString(cx, v);
  +            if (!sourceMapURL)
  +                return false;
  +        }
  +
  +        if (!JS_GetProperty(cx, opts, "global", &v))
  +            return false;
  +        if (!v.isUndefined()) {
  +            if (v.isObject()) {
  +                global = js::UncheckedUnwrap(&v.toObject());
  +                if (!global)
  +                    return false;
  +            }
  +            if (!global || !(JS_GetClass(global)->flags & 
JSCLASS_IS_GLOBAL)) {
  +                JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, 
JSMSG_UNEXPECTED_TYPE,
  +                                     "\"global\" passed to evaluate()", "not 
a global object");
  +                return false;
  +            }
  +        }
  +
  +        if (!JS_GetProperty(cx, opts, "catchTermination", &v))
  +            return false;
  +        if (!v.isUndefined())
  +            catchTermination = ToBoolean(v);
  +
  +        if (!JS_GetProperty(cx, opts, "saveFrameChain", &v))
  +            return false;
  +        if (!v.isUndefined())
  +            saveFrameChain = ToBoolean(v);
  +
  +        if (!JS_GetProperty(cx, opts, "loadBytecode", &v))
  +            return false;
  +        if (!v.isUndefined())
  +            loadBytecode = ToBoolean(v);
  +
  +        if (!JS_GetProperty(cx, opts, "saveBytecode", &v))
  +            return false;
  +        if (!v.isUndefined())
  +            saveBytecode = ToBoolean(v);
  +
  +        if (!JS_GetProperty(cx, opts, "assertEqBytecode", &v))
  +            return false;
  +        if (!v.isUndefined())
  +            assertEqBytecode = ToBoolean(v);
  +
  +        // We cannot load or save the bytecode if we have no object where the
  +        // bytecode cache is stored.
  +        if (loadBytecode || saveBytecode) {
  +            if (!cacheEntry) {
  +                JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_INVALID_ARGS,
  +                                     "evaluate");
  +                return false;
  +            }
  +        }
  +    }
  +
  +    AutoStableStringChars codeChars(cx);
  +    if (!codeChars.initTwoByte(cx, code))
  +        return false;
  +
  +    AutoNewContext ancx;
  +    if (newContext) {
  +        if (!ancx.enter(cx))
  +            return false;
  +        cx = ancx.get();
  +    }
  +
  +    uint32_t loadLength = 0;
  +    uint8_t* loadBuffer = nullptr;
  +    uint32_t saveLength = 0;
  +    ScopedJSFreePtr<uint8_t> saveBuffer;
  +
  +    if (loadBytecode) {
  +        loadBuffer = CacheEntry_getBytecode(cacheEntry, &loadLength);
  +        if (!loadBuffer)
  +            return false;
  +    }
  +
  +    {
  +        AutoSaveFrameChain asfc(cx);
  +        if (saveFrameChain && !asfc.save())
  +            return false;
  +
  +        JSAutoCompartment ac(cx, global);
  +        RootedScript script(cx);
  +
  +        {
  +            if (saveBytecode) {
  +                if (!JS::CompartmentOptionsRef(cx).cloneSingletons()) {
  +                    JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                                         JSSMSG_CACHE_SINGLETON_FAILED);
  +                    return false;
  +                }
  +
  +                // cloneSingletons implies that singletons are used as 
template objects.
  +                
MOZ_ASSERT(JS::CompartmentOptionsRef(cx).getSingletonsAsTemplates());
  +            }
  +
  +            if (loadBytecode) {
  +                script = JS_DecodeScript(cx, loadBuffer, loadLength);
  +            } else {
  +                mozilla::Range<const char16_t> chars = 
codeChars.twoByteRange();
  +                (void) JS::Compile(cx, options, chars.start().get(), 
chars.length(), &script);
  +            }
  +
  +            if (!script)
  +                return false;
  +        }
  +
  +        if (displayURL && !script->scriptSource()->hasDisplayURL()) {
  +            JSFlatString* flat = displayURL->ensureFlat(cx);
  +            if (!flat)
  +                return false;
  +
  +            AutoStableStringChars chars(cx);
  +            if (!chars.initTwoByte(cx, flat))
  +                return false;
  +
  +            const char16_t* durl = chars.twoByteRange().start().get();
  +            if (!script->scriptSource()->setDisplayURL(cx, durl))
  +                return false;
  +        }
  +        if (sourceMapURL && !script->scriptSource()->hasSourceMapURL()) {
  +            JSFlatString* flat = sourceMapURL->ensureFlat(cx);
  +            if (!flat)
  +                return false;
  +
  +            AutoStableStringChars chars(cx);
  +            if (!chars.initTwoByte(cx, flat))
  +                return false;
  +
  +            const char16_t* smurl = chars.twoByteRange().start().get();
  +            if (!script->scriptSource()->setSourceMapURL(cx, smurl))
  +                return false;
  +        }
  +        if (!JS_ExecuteScript(cx, script, args.rval())) {
  +            if (catchTermination && !JS_IsExceptionPending(cx)) {
  +                JSAutoCompartment ac1(cx, callerGlobal);
  +                JSString* str = JS_NewStringCopyZ(cx, "terminated");
  +                if (!str)
  +                    return false;
  +                args.rval().setString(str);
  +                return true;
  +            }
  +            return false;
  +        }
  +
  +        if (saveBytecode) {
  +            saveBuffer = reinterpret_cast<uint8_t*>(JS_EncodeScript(cx, 
script, &saveLength));
  +            if (!saveBuffer)
  +                return false;
  +        }
  +    }
  +
  +    if (saveBytecode) {
  +        // If we are both loading and saving, we assert that we are going to
  +        // replace the current bytecode by the same stream of bytes.
  +        if (loadBytecode && assertEqBytecode) {
  +            if (saveLength != loadLength) {
  +                char loadLengthStr[16];
  +                JS_snprintf(loadLengthStr, sizeof(loadLengthStr), "%u", 
loadLength);
  +                char saveLengthStr[16];
  +                JS_snprintf(saveLengthStr, sizeof(saveLengthStr), "%u", 
saveLength);
  +
  +                JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_CACHE_EQ_SIZE_FAILED,
  +                                     loadLengthStr, saveLengthStr);
  +                return false;
  +            }
  +
  +            if (!PodEqual(loadBuffer, saveBuffer.get(), loadLength)) {
  +                JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                                     JSSMSG_CACHE_EQ_CONTENT_FAILED);
  +                return false;
  +            }
  +        }
  +
  +        if (!CacheEntry_setBytecode(cx, cacheEntry, saveBuffer, saveLength))
  +            return false;
  +
  +        saveBuffer.forget();
  +    }
  +
  +    return JS_WrapValue(cx, args.rval());
  +}
  +#endif       /* NOTYET */
  +
  +#ifdef       NOTYET
  +JSString*
  +js::shell::FileAsString(JSContext* cx, const char* pathname)
  +{
  +    FILE* file;
  +    RootedString str(cx);
  +    size_t len, cc;
  +    char* buf;
  +
  +    file = fopen(pathname, "rb");
  +    if (!file) {
  +        JS_ReportError(cx, "can't open %s: %s", pathname, strerror(errno));
  +        return nullptr;
  +    }
  +    AutoCloseFile autoClose(file);
  +
  +    if (fseek(file, 0, SEEK_END) != 0) {
  +        JS_ReportError(cx, "can't seek end of %s", pathname);
  +    } else {
  +        len = ftell(file);
  +        if (fseek(file, 0, SEEK_SET) != 0) {
  +            JS_ReportError(cx, "can't seek start of %s", pathname);
  +        } else {
  +            buf = (char*) JS_malloc(cx, len + 1);
  +            if (buf) {
  +                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");
  +                } else {
  +                    char16_t* ucbuf =
  +                        JS::UTF8CharsToNewTwoByteCharsZ(cx, 
JS::UTF8Chars(buf, len), &len).get();
  +                    if (!ucbuf) {
  +                        JS_ReportError(cx, "Invalid UTF-8 in file '%s'", 
pathname);
  +                        return nullptr;
  +                    }
  +                    str = JS_NewUCStringCopyN(cx, ucbuf, len);
  +                    free(ucbuf);
  +                }
  +                JS_free(cx, buf);
  +            }
  +        }
  +    }
  +
  +    return str;
  +}
  +
  +/*
  + * Function to run scripts and return compilation + execution time. Semantics
  + * are closely modelled after the equivalent function in WebKit, as this is 
used
  + * to produce benchmark timings by SunSpider.
  + */
  +static bool
  +Run(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() != 1) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_INVALID_ARGS, "run");
  +        return false;
  +    }
  +
  +    RootedString str(cx, JS::ToString(cx, args[0]));
  +    if (!str)
  +        return false;
  +    args[0].setString(str);
  +    JSAutoByteString filename(cx, str);
  +    if (!filename)
  +        return false;
  +
  +    str = FileAsString(cx, filename.ptr());
  +    if (!str)
  +        return false;
  +
  +    AutoStableStringChars chars(cx);
  +    if (!chars.initTwoByte(cx, str))
  +        return false;
  +
  +    const char16_t* ucbuf = chars.twoByteRange().start().get();
  +    size_t buflen = str->length();
  +
  +    RootedScript script(cx);
  +    int64_t startClock = PRMJ_Now();
  +    {
  +        JS::CompileOptions options(cx);
  +        options.setIntroductionType("js shell run")
  +               .setFileAndLine(filename.ptr(), 1)
  +               .setIsRunOnce(true)
  +               .setNoScriptRval(true);
  +        if (!JS_CompileUCScript(cx, ucbuf, buflen, options, &script))
  +            return false;
  +    }
  +
  +    if (!JS_ExecuteScript(cx, script))
  +        return false;
  +
  +    int64_t endClock = PRMJ_Now();
  +
  +    args.rval().setDouble((endClock - startClock) / 
double(PRMJ_USEC_PER_MSEC));
  +    return true;
  +}
  +#endif       /* NOTYET */
  +
  +static bool
  +PutStr(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() != 0) {
  +        RootedString str(cx, JS::ToString(cx, args[0]));
  +        if (!str)
  +            return false;
  +        char* bytes = JS_EncodeStringToUTF8(cx, str);
  +        if (!bytes)
  +            return false;
  +        fputs(bytes, gOutFile);
  +        JS_free(cx, bytes);
  +        fflush(gOutFile);
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +#ifdef       NOTYET
  +static bool
  +Now(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    double now = PRMJ_Now() / double(PRMJ_USEC_PER_MSEC);
  +    args.rval().setDouble(now);
  +    return true;
  +}
  +#endif
  +
  +static bool
  +PrintInternal(JSContext* cx, const CallArgs& args, FILE* file)
  +{
  +    for (unsigned i = 0; i < args.length(); i++) {
  +        RootedString str(cx, JS::ToString(cx, args[i]));
  +        if (!str)
  +            return false;
  +        char* bytes = JS_EncodeStringToUTF8(cx, str);
  +        if (!bytes)
  +            return false;
  +        fprintf(file, "%s%s", i ? " " : "", bytes);
  +        JS_free(cx, bytes);
  +    }
  +
  +    fputc('\n', file);
  +    fflush(file);
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +static bool
  +Print(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    return PrintInternal(cx, args, gOutFile);
  +}
  +
  +static bool
  +PrintErr(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    return PrintInternal(cx, args, gErrFile);
  +}
  +
  +#ifdef       NOTYET
  +static bool
  +Help(JSContext* cx, unsigned argc, Value* vp);
  +
  +static bool
  +Quit(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +
  +#ifdef JS_MORE_DETERMINISTIC
  +    // Print a message to stderr in more-deterministic builds to help 
jsfunfuzz
  +    // find uncatchable-exception bugs.
  +    fprintf(stderr, "quit called\n");
  +#endif
  +
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    int32_t code;
  +    if (!ToInt32(cx, args.get(0), &code))
  +        return false;
  +
  +    // The fuzzers check the shell's exit code and assume a value >= 128 
means
  +    // the process crashed (for instance, SIGSEGV will result in code 139). 
On
  +    // POSIX platforms, the exit code is 8-bit and negative values can also
  +    // result in an exit code >= 128. We restrict the value to range [0, 
127] to
  +    // avoid false positives.
  +    if (code < 0 || code >= 128) {
  +        JS_ReportError(cx, "quit exit code should be in range 0-127");
  +        return false;
  +    }
  +
  +    sr->exitCode = code;
  +    sr->quitting = true;
  +    return false;
  +}
  +#endif       /* NOTYET */
  +
  +#ifdef       NOTYET
  +static bool
  +StartTimingMutator(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() > 0) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                             JSSMSG_TOO_MANY_ARGS, "startTimingMutator");
  +        return false;
  +    }
  +
  +    if (!cx->runtime()->gc.stats.startTimingMutator()) {
  +        JS_ReportError(cx, "StartTimingMutator should only be called from 
outside of GC");
  +        return false;
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +static bool
  +StopTimingMutator(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() > 0) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                             JSSMSG_TOO_MANY_ARGS, "stopTimingMutator");
  +        return false;
  +    }
  +
  +    double mutator_ms, gc_ms;
  +    if (!cx->runtime()->gc.stats.stopTimingMutator(mutator_ms, gc_ms)) {
  +        JS_ReportError(cx, "stopTimingMutator called when not timing the 
mutator");
  +        return false;
  +    }
  +    double total_ms = mutator_ms + gc_ms;
  +    if (total_ms > 0) {
  +        fprintf(gOutFile, "Mutator: %.3fms (%.1f%%), GC: %.3fms (%.1f%%)\n",
  +                mutator_ms, mutator_ms / total_ms * 100.0, gc_ms, gc_ms / 
total_ms * 100.0);
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif       /* NOTYET */
  +
  +static const char*
  +ToSource(JSContext* cx, MutableHandleValue vp, JSAutoByteString* bytes)
  +{
  +    JSString* str = JS_ValueToSource(cx, vp);
  +    if (str) {
  +        vp.setString(str);
  +        if (bytes->encodeLatin1(cx, str))
  +            return bytes->ptr();
  +    }
  +    JS_ClearPendingException(cx);
  +    return "<<error converting value to string>>";
  +}
  +
  +static bool
  +AssertEq(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (!(args.length() == 2 || (args.length() == 3 && args[2].isString()))) 
{
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                             (args.length() < 2)
  +                             ? JSSMSG_NOT_ENOUGH_ARGS
  +                             : (args.length() == 3)
  +                             ? JSSMSG_INVALID_ARGS
  +                             : JSSMSG_TOO_MANY_ARGS,
  +                             "assertEq");
  +        return false;
  +    }
  +
  +    bool same;
  +    if (!JS_SameValue(cx, args[0], args[1], &same))
  +        return false;
  +    if (!same) {
  +        JSAutoByteString bytes0, bytes1;
  +        const char* actual = ToSource(cx, args[0], &bytes0);
  +        const char* expected = ToSource(cx, args[1], &bytes1);
  +        if (args.length() == 2) {
  +            JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_ASSERT_EQ_FAILED,
  +                                 actual, expected);
  +        } else {
  +            JSAutoByteString bytes2(cx, args[2].toString());
  +            if (!bytes2)
  +                return false;
  +            JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_ASSERT_EQ_FAILED_MSG,
  +                                 actual, expected, bytes2.ptr());
  +        }
  +        return false;
  +    }
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +#ifdef       NOTYET
  +static JSScript*
  +ValueToScript(JSContext* cx, Value vArg, JSFunction** funp = nullptr)
  +{
  +    RootedValue v(cx, vArg);
  +
  +    if (v.isString()) {
  +        // To convert a string to a script, compile it. Parse it as an ES6 
Program.
  +        RootedLinearString linearStr(cx, StringToLinearString(cx, 
v.toString()));
  +        if (!linearStr)
  +            return nullptr;
  +        size_t len = GetLinearStringLength(linearStr);
  +        AutoStableStringChars linearChars(cx);
  +        if (!linearChars.initTwoByte(cx, linearStr))
  +            return nullptr;
  +        const char16_t* chars = linearChars.twoByteRange().start().get();
  +
  +        RootedScript script(cx);
  +        CompileOptions options(cx);
  +        if (!JS::Compile(cx, options, chars, len, &script))
  +            return nullptr;
  +        return script;
  +    }
  +
  +    RootedFunction fun(cx, JS_ValueToFunction(cx, v));
  +    if (!fun)
  +        return nullptr;
  +
  +    // Unwrap bound functions.
  +    while (fun->isBoundFunction()) {
  +        JSObject* target = fun->getBoundFunctionTarget();
  +        if (target && target->is<JSFunction>())
  +            fun = &target->as<JSFunction>();
  +        else
  +            break;
  +    }
  +
  +    if (!fun->isInterpreted()) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_SCRIPTS_ONLY);
  +        return nullptr;
  +    }
  +
  +    JSScript* script = fun->getOrCreateScript(cx);
  +    if (!script)
  +        return nullptr;
  +
  +    if (fun && funp)
  +        *funp = fun;
  +
  +    return script;
  +}
  +
  +static JSScript*
  +GetTopScript(JSContext* cx)
  +{
  +    NonBuiltinScriptFrameIter iter(cx);
  +    return iter.done() ? nullptr : iter.script();
  +}
  +
  +static bool
  +GetScriptAndPCArgs(JSContext* cx, unsigned argc, Value* argv, 
MutableHandleScript scriptp,
  +                   int32_t* ip)
  +{
  +    RootedScript script(cx, GetTopScript(cx));
  +    *ip = 0;
  +    if (argc != 0) {
  +        Value v = argv[0];
  +        unsigned intarg = 0;
  +        if (v.isObject() &&
  +            JS_GetClass(&v.toObject()) == Jsvalify(&JSFunction::class_)) {
  +            script = ValueToScript(cx, v);
  +            if (!script)
  +                return false;
  +            intarg++;
  +        }
  +        if (argc > intarg) {
  +            if (!JS::ToInt32(cx, 
HandleValue::fromMarkedLocation(&argv[intarg]), ip))
  +                return false;
  +            if ((uint32_t)*ip >= script->length()) {
  +                JS_ReportError(cx, "Invalid PC");
  +                return false;
  +            }
  +        }
  +    }
  +
  +    scriptp.set(script);
  +
  +    return true;
  +}
  +
  +static bool
  +LineToPC(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() == 0) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_LINE2PC_USAGE);
  +        return false;
  +    }
  +
  +    RootedScript script(cx, GetTopScript(cx));
  +    int32_t lineArg = 0;
  +    if (args[0].isObject() && args[0].toObject().is<JSFunction>()) {
  +        script = ValueToScript(cx, args[0]);
  +        if (!script)
  +            return false;
  +        lineArg++;
  +    }
  +
  +    uint32_t lineno;
  +    if (!ToUint32(cx, args.get(lineArg), &lineno))
  +         return false;
  +
  +    jsbytecode* pc = LineNumberToPC(script, lineno);
  +    if (!pc)
  +        return false;
  +    args.rval().setInt32(script->pcToOffset(pc));
  +    return true;
  +}
  +
  +static bool
  +PCToLine(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedScript script(cx);
  +    int32_t i;
  +    unsigned lineno;
  +
  +    if (!GetScriptAndPCArgs(cx, args.length(), args.array(), &script, &i))
  +        return false;
  +    lineno = PCToLineNumber(script, script->offsetToPC(i));
  +    if (!lineno)
  +        return false;
  +    args.rval().setInt32(lineno);
  +    return true;
  +}
  +
  +#ifdef DEBUG
  +
  +static void
  +UpdateSwitchTableBounds(JSContext* cx, HandleScript script, unsigned offset,
  +                        unsigned* start, unsigned* end)
  +{
  +    jsbytecode* pc;
  +    JSOp op;
  +    ptrdiff_t jmplen;
  +    int32_t low, high, n;
  +
  +    pc = script->offsetToPC(offset);
  +    op = JSOp(*pc);
  +    switch (op) {
  +      case JSOP_TABLESWITCH:
  +        jmplen = JUMP_OFFSET_LEN;
  +        pc += jmplen;
  +        low = GET_JUMP_OFFSET(pc);
  +        pc += JUMP_OFFSET_LEN;
  +        high = GET_JUMP_OFFSET(pc);
  +        pc += JUMP_OFFSET_LEN;
  +        n = high - low + 1;
  +        break;
  +
  +      default:
  +        /* [condswitch] switch does not have any jump or lookup tables. */
  +        MOZ_ASSERT(op == JSOP_CONDSWITCH);
  +        return;
  +    }
  +
  +    *start = script->pcToOffset(pc);
  +    *end = *start + (unsigned)(n * jmplen);
  +}
  +
  +static void
  +SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp)
  +{
  +    Sprint(sp, "\nSource notes:\n");
  +    Sprint(sp, "%4s %4s %5s %6s %-8s %s\n",
  +           "ofs", "line", "pc", "delta", "desc", "args");
  +    Sprint(sp, "---- ---- ----- ------ -------- ------\n");
  +    unsigned offset = 0;
  +    unsigned colspan = 0;
  +    unsigned lineno = script->lineno();
  +    jssrcnote* notes = script->notes();
  +    unsigned switchTableEnd = 0, switchTableStart = 0;
  +    for (jssrcnote* sn = notes; !SN_IS_TERMINATOR(sn); sn = SN_NEXT(sn)) {
  +        unsigned delta = SN_DELTA(sn);
  +        offset += delta;
  +        SrcNoteType type = (SrcNoteType) SN_TYPE(sn);
  +        const char* name = js_SrcNoteSpec[type].name;
  +        Sprint(sp, "%3u: %4u %5u [%4u] %-8s", unsigned(sn - notes), lineno, 
offset, delta, name);
  +        switch (type) {
  +          case SRC_NULL:
  +          case SRC_IF:
  +          case SRC_CONTINUE:
  +          case SRC_BREAK:
  +          case SRC_BREAK2LABEL:
  +          case SRC_SWITCHBREAK:
  +          case SRC_ASSIGNOP:
  +          case SRC_XDELTA:
  +            break;
  +
  +          case SRC_COLSPAN:
  +            colspan = SN_OFFSET_TO_COLSPAN(GetSrcNoteOffset(sn, 0));
  +            Sprint(sp, "%d", colspan);
  +            break;
  +
  +          case SRC_SETLINE:
  +            lineno = GetSrcNoteOffset(sn, 0);
  +            Sprint(sp, " lineno %u", lineno);
  +            break;
  +
  +          case SRC_NEWLINE:
  +            ++lineno;
  +            break;
  +
  +          case SRC_FOR:
  +            Sprint(sp, " cond %u update %u tail %u",
  +                   unsigned(GetSrcNoteOffset(sn, 0)),
  +                   unsigned(GetSrcNoteOffset(sn, 1)),
  +                   unsigned(GetSrcNoteOffset(sn, 2)));
  +            break;
  +
  +          case SRC_IF_ELSE:
  +            Sprint(sp, " else %u", unsigned(GetSrcNoteOffset(sn, 0)));
  +            break;
  +
  +          case SRC_FOR_IN:
  +          case SRC_FOR_OF:
  +            Sprint(sp, " closingjump %u", unsigned(GetSrcNoteOffset(sn, 0)));
  +            break;
  +
  +          case SRC_COND:
  +          case SRC_WHILE:
  +          case SRC_NEXTCASE:
  +            Sprint(sp, " offset %u", unsigned(GetSrcNoteOffset(sn, 0)));
  +            break;
  +
  +          case SRC_TABLESWITCH: {
  +            JSOp op = JSOp(script->code()[offset]);
  +            MOZ_ASSERT(op == JSOP_TABLESWITCH);
  +            Sprint(sp, " length %u", unsigned(GetSrcNoteOffset(sn, 0)));
  +            UpdateSwitchTableBounds(cx, script, offset,
  +                                    &switchTableStart, &switchTableEnd);
  +            break;
  +          }
  +          case SRC_CONDSWITCH: {
  +            JSOp op = JSOp(script->code()[offset]);
  +            MOZ_ASSERT(op == JSOP_CONDSWITCH);
  +            Sprint(sp, " length %u", unsigned(GetSrcNoteOffset(sn, 0)));
  +            unsigned caseOff = (unsigned) GetSrcNoteOffset(sn, 1);
  +            if (caseOff)
  +                Sprint(sp, " first case offset %u", caseOff);
  +            UpdateSwitchTableBounds(cx, script, offset,
  +                                    &switchTableStart, &switchTableEnd);
  +            break;
  +          }
  +
  +          case SRC_TRY:
  +            MOZ_ASSERT(JSOp(script->code()[offset]) == JSOP_TRY);
  +            Sprint(sp, " offset to jump %u", unsigned(GetSrcNoteOffset(sn, 
0)));
  +            break;
  +
  +          default:
  +            MOZ_ASSERT(0);
  +            break;
  +        }
  +        Sprint(sp, "\n");
  +    }
  +}
  +
  +static bool
  +Notes(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    Sprinter sprinter(cx);
  +    if (!sprinter.init())
  +        return false;
  +
  +    for (unsigned i = 0; i < args.length(); i++) {
  +        RootedScript script (cx, ValueToScript(cx, args[i]));
  +        if (!script)
  +            return false;
  +
  +        SrcNotes(cx, script, &sprinter);
  +    }
  +
  +    JSString* str = JS_NewStringCopyZ(cx, sprinter.string());
  +    if (!str)
  +        return false;
  +    args.rval().setString(str);
  +    return true;
  +}
  +
  +JS_STATIC_ASSERT(JSTRY_CATCH == 0);
  +JS_STATIC_ASSERT(JSTRY_FINALLY == 1);
  +JS_STATIC_ASSERT(JSTRY_FOR_IN == 2);
  +
  +static const char* const TryNoteNames[] = { "catch", "finally", "for-in", 
"for-of", "loop" };
  +
  +static bool
  +TryNotes(JSContext* cx, HandleScript script, Sprinter* sp)
  +{
  +    if (!script->hasTrynotes())
  +        return true;
  +
  +    JSTryNote* tn = script->trynotes()->vector;
  +    JSTryNote* tnlimit = tn + script->trynotes()->length;
  +    Sprint(sp, "\nException table:\nkind      stack    start      end\n");
  +    do {
  +        MOZ_ASSERT(tn->kind < ArrayLength(TryNoteNames));
  +        Sprint(sp, " %-7s %6u %8u %8u\n",
  +               TryNoteNames[tn->kind], tn->stackDepth,
  +               tn->start, tn->start + tn->length);
  +    } while (++tn != tnlimit);
  +    return true;
  +}
  +
  +static bool
  +BlockNotes(JSContext* cx, HandleScript script, Sprinter* sp)
  +{
  +    if (!script->hasBlockScopes())
  +        return true;
  +
  +    Sprint(sp, "\nBlock table:\n   index   parent    start      end\n");
  +
  +    BlockScopeArray* scopes = script->blockScopes();
  +    for (uint32_t i = 0; i < scopes->length; i++) {
  +        const BlockScopeNote* note = &scopes->vector[i];
  +        if (note->index == BlockScopeNote::NoBlockScopeIndex)
  +            Sprint(sp, "%8s ", "(none)");
  +        else
  +            Sprint(sp, "%8u ", note->index);
  +        if (note->parent == BlockScopeNote::NoBlockScopeIndex)
  +            Sprint(sp, "%8s ", "(none)");
  +        else
  +            Sprint(sp, "%8u ", note->parent);
  +        Sprint(sp, "%8u %8u\n", note->start, note->start + note->length);
  +    }
  +    return true;
  +}
  +
  +static bool
  +DisassembleScript(JSContext* cx, HandleScript script, HandleFunction fun,
  +                  bool lines, bool recursive, bool sourceNotes, Sprinter* sp)
  +{
  +    if (fun) {
  +        Sprint(sp, "flags:");
  +        if (fun->isLambda())
  +            Sprint(sp, " LAMBDA");
  +        if (fun->needsCallObject())
  +            Sprint(sp, " NEEDS_CALLOBJECT");
  +        if (fun->isConstructor())
  +            Sprint(sp, " CONSTRUCTOR");
  +        if (fun->isExprBody())
  +            Sprint(sp, " EXPRESSION_CLOSURE");
  +        if (fun->isFunctionPrototype())
  +            Sprint(sp, " Function.prototype");
  +        if (fun->isSelfHostedBuiltin())
  +            Sprint(sp, " SELF_HOSTED");
  +        if (fun->isArrow())
  +            Sprint(sp, " ARROW");
  +        Sprint(sp, "\n");
  +    }
  +
  +    if (!Disassemble(cx, script, lines, sp))
  +        return false;
  +    if (sourceNotes)
  +        SrcNotes(cx, script, sp);
  +    TryNotes(cx, script, sp);
  +    BlockNotes(cx, script, sp);
  +
  +    if (recursive && script->hasObjects()) {
  +        ObjectArray* objects = script->objects();
  +        for (unsigned i = 0; i != objects->length; ++i) {
  +            JSObject* obj = objects->vector[i];
  +            if (obj->is<JSFunction>()) {
  +                Sprint(sp, "\n");
  +                RootedFunction fun(cx, &obj->as<JSFunction>());
  +                if (fun->isInterpreted()) {
  +                    RootedScript script(cx, fun->getOrCreateScript(cx));
  +                    if (script) {
  +                        if (!DisassembleScript(cx, script, fun, lines, 
recursive, sourceNotes, sp))
  +                            return false;
  +                    }
  +                } else {
  +                    Sprint(sp, "[native code]\n");
  +                }
  +            }
  +        }
  +    }
  +    return true;
  +}
  +
  +namespace {
  +
  +struct DisassembleOptionParser {
  +    unsigned argc;
  +    Value* argv;
  +    bool lines;
  +    bool recursive;
  +    bool sourceNotes;
  +
  +    DisassembleOptionParser(unsigned argc, Value* argv)
  +      : argc(argc), argv(argv), lines(false), recursive(false), 
sourceNotes(true) {}
  +
  +    bool parse(JSContext* cx) {
  +        /* Read options off early arguments */
  +        while (argc > 0 && argv[0].isString()) {
  +            JSString* str = argv[0].toString();
  +            JSFlatString* flatStr = JS_FlattenString(cx, str);
  +            if (!flatStr)
  +                return false;
  +            if (JS_FlatStringEqualsAscii(flatStr, "-l"))
  +                lines = true;
  +            else if (JS_FlatStringEqualsAscii(flatStr, "-r"))
  +                recursive = true;
  +            else if (JS_FlatStringEqualsAscii(flatStr, "-S"))
  +                sourceNotes = false;
  +            else
  +                break;
  +            argv++, argc--;
  +        }
  +        return true;
  +    }
  +};
  +
  +} /* anonymous namespace */
  +
  +static bool
  +DisassembleToSprinter(JSContext* cx, unsigned argc, Value* vp, Sprinter* 
sprinter)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    DisassembleOptionParser p(args.length(), args.array());
  +    if (!p.parse(cx))
  +        return false;
  +
  +    if (p.argc == 0) {
  +        /* Without arguments, disassemble the current script. */
  +        RootedScript script(cx, GetTopScript(cx));
  +        if (script) {
  +            JSAutoCompartment ac(cx, script);
  +            if (!Disassemble(cx, script, p.lines, sprinter))
  +                return false;
  +            SrcNotes(cx, script, sprinter);
  +            TryNotes(cx, script, sprinter);
  +            BlockNotes(cx, script, sprinter);
  +        }
  +    } else {
  +        for (unsigned i = 0; i < p.argc; i++) {
  +            RootedFunction fun(cx);
  +            RootedScript script(cx);
  +            RootedValue value(cx, p.argv[i]);
  +            if (value.isObject() && value.toObject().is<ModuleObject>())
  +                script = value.toObject().as<ModuleObject>().script();
  +            else
  +                script = ValueToScript(cx, value, fun.address());
  +            if (!script)
  +                return false;
  +            if (!DisassembleScript(cx, script, fun, p.lines, p.recursive, 
p.sourceNotes, sprinter))
  +                return false;
  +        }
  +    }
  +
  +    return !sprinter->hadOutOfMemory();
  +}
  +
  +static bool
  +DisassembleToString(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    Sprinter sprinter(cx);
  +    if (!sprinter.init())
  +        return false;
  +    if (!DisassembleToSprinter(cx, args.length(), vp, &sprinter))
  +        return false;
  +
  +    JSString* str = JS_NewStringCopyZ(cx, sprinter.string());
  +    if (!str)
  +        return false;
  +    args.rval().setString(str);
  +    return true;
  +}
  +
  +static bool
  +Disassemble(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    Sprinter sprinter(cx);
  +    if (!sprinter.init())
  +        return false;
  +    if (!DisassembleToSprinter(cx, args.length(), vp, &sprinter))
  +        return false;
  +
  +    fprintf(stdout, "%s\n", sprinter.string());
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +static bool
  +DisassFile(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    /* Support extra options at the start, just like Disassemble. */
  +    DisassembleOptionParser p(args.length(), args.array());
  +    if (!p.parse(cx))
  +        return false;
  +
  +    if (!p.argc) {
  +        args.rval().setUndefined();
  +        return true;
  +    }
  +
  +    // We should change DisassembleOptionParser to store CallArgs.
  +    JSString* str = JS::ToString(cx, 
HandleValue::fromMarkedLocation(&p.argv[0]));
  +    if (!str)
  +        return false;
  +    JSAutoByteString filename(cx, str);
  +    if (!filename)
  +        return false;
  +    RootedScript script(cx);
  +
  +    {
  +        CompileOptions options(cx);
  +        options.setIntroductionType("js shell disFile")
  +               .setUTF8(true)
  +               .setFileAndLine(filename.ptr(), 1)
  +               .setIsRunOnce(true)
  +               .setNoScriptRval(true);
  +
  +        if (!JS::Compile(cx, options, filename.ptr(), &script))
  +            return false;
  +    }
  +
  +    Sprinter sprinter(cx);
  +    if (!sprinter.init())
  +        return false;
  +    bool ok = DisassembleScript(cx, script, nullptr, p.lines, p.recursive, 
p.sourceNotes, &sprinter);
  +    if (ok)
  +        fprintf(stdout, "%s\n", sprinter.string());
  +    if (!ok)
  +        return false;
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +static bool
  +DisassWithSrc(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +#define LINE_BUF_LEN 512
  +    unsigned len, line1, line2, bupline;
  +    FILE* file;
  +    char linebuf[LINE_BUF_LEN];
  +    static const char sep[] = ";-------------------------";
  +
  +    bool ok = true;
  +    RootedScript script(cx);
  +    for (unsigned i = 0; ok && i < args.length(); i++) {
  +        script = ValueToScript(cx, args[i]);
  +        if (!script)
  +           return false;
  +
  +        if (!script->filename()) {
  +            JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                                 JSSMSG_FILE_SCRIPTS_ONLY);
  +            return false;
  +        }
  +
  +        file = fopen(script->filename(), "r");
  +        if (!file) {
  +            JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                                 JSSMSG_CANT_OPEN, script->filename(),
  +                                 strerror(errno));
  +            return false;
  +        }
  +
  +        jsbytecode* pc = script->code();
  +        jsbytecode* end = script->codeEnd();
  +
  +        Sprinter sprinter(cx);
  +        if (!sprinter.init()) {
  +            ok = false;
  +            goto bail;
  +        }
  +
  +        /* burn the leading lines */
  +        line2 = PCToLineNumber(script, pc);
  +        for (line1 = 0; line1 < line2 - 1; line1++) {
  +            char* tmp = fgets(linebuf, LINE_BUF_LEN, file);
  +            if (!tmp) {
  +                JS_ReportError(cx, "failed to read %s fully", 
script->filename());
  +                ok = false;
  +                goto bail;
  +            }
  +        }
  +
  +        bupline = 0;
  +        while (pc < end) {
  +            line2 = PCToLineNumber(script, pc);
  +
  +            if (line2 < line1) {
  +                if (bupline != line2) {
  +                    bupline = line2;
  +                    Sprint(&sprinter, "%s %3u: BACKUP\n", sep, line2);
  +                }
  +            } else {
  +                if (bupline && line1 == line2)
  +                    Sprint(&sprinter, "%s %3u: RESTORE\n", sep, line2);
  +                bupline = 0;
  +                while (line1 < line2) {
  +                    if (!fgets(linebuf, LINE_BUF_LEN, file)) {
  +                        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                                             JSSMSG_UNEXPECTED_EOF,
  +                                             script->filename());
  +                        ok = false;
  +                        goto bail;
  +                    }
  +                    line1++;
  +                    Sprint(&sprinter, "%s %3u: %s", sep, line1, linebuf);
  +                }
  +            }
  +
  +            len = Disassemble1(cx, script, pc, script->pcToOffset(pc), true, 
&sprinter);
  +            if (!len) {
  +                ok = false;
  +                goto bail;
  +            }
  +            pc += len;
  +        }
  +
  +        fprintf(stdout, "%s\n", sprinter.string());
  +
  +      bail:
  +        fclose(file);
  +    }
  +    args.rval().setUndefined();
  +    return ok;
  +#undef LINE_BUF_LEN
  +}
  +
  +#endif /* DEBUG */
  +
  +static bool
  +Intern(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    JSString* str = JS::ToString(cx, args.get(0));
  +    if (!str)
  +        return false;
  +
  +    AutoStableStringChars strChars(cx);
  +    if (!strChars.initTwoByte(cx, str))
  +        return false;
  +
  +    mozilla::Range<const char16_t> chars = strChars.twoByteRange();
  +
  +    if (!JS_AtomizeAndPinUCStringN(cx, chars.start().get(), chars.length()))
  +        return false;
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +
  +static bool
  +Clone(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedObject parent(cx);
  +    RootedObject funobj(cx);
  +
  +    if (!args.length()) {
  +        JS_ReportError(cx, "Invalid arguments to clone");
  +        return false;
  +    }
  +
  +    {
  +        Maybe<JSAutoCompartment> ac;
  +        RootedObject obj(cx, args[0].isPrimitive() ? nullptr : 
&args[0].toObject());
  +
  +        if (obj && obj->is<CrossCompartmentWrapperObject>()) {
  +            obj = UncheckedUnwrap(obj);
  +            ac.emplace(cx, obj);
  +            args[0].setObject(*obj);
  +        }
  +        if (obj && obj->is<JSFunction>()) {
  +            funobj = obj;
  +        } else {
  +            JSFunction* fun = JS_ValueToFunction(cx, args[0]);
  +            if (!fun)
  +                return false;
  +            funobj = JS_GetFunctionObject(fun);
  +        }
  +    }
  +
  +    if (args.length() > 1) {
  +        if (!JS_ValueToObject(cx, args[1], &parent))
  +            return false;
  +    } else {
  +        parent = js::GetGlobalForObjectCrossCompartment(&args.callee());
  +    }
  +
  +    // Should it worry us that we might be getting with wrappers
  +    // around with wrappers here?
  +    JS::AutoObjectVector scopeChain(cx);
  +    if (!parent->is<GlobalObject>() && !scopeChain.append(parent))
  +        return false;
  +    JSObject* clone = JS::CloneFunctionObject(cx, funobj, scopeChain);
  +    if (!clone)
  +        return false;
  +    args.rval().setObject(*clone);
  +    return true;
  +}
  +
  +static bool
  +GetSLX(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedScript script(cx);
  +
  +    script = ValueToScript(cx, args.get(0));
  +    if (!script)
  +        return false;
  +    args.rval().setInt32(GetScriptLineExtent(script));
  +    return true;
  +}
  +#endif       /* NOTYET */
  +
  +#ifdef       NOTYET
  +static bool
  +GetSLX(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedScript script(cx);
  +
  +    script = ValueToScript(cx, args.get(0));
  +    if (!script)
  +        return false;
  +    args.rval().setInt32(GetScriptLineExtent(script));
  +    return true;
  +}
  +#endif       /* NOTYET */
  +
  +static bool
  +ThrowError(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    JS_ReportError(cx, "This is an error");
  +    return false;
  +}
  +
  +#ifdef       NOTYET
  +static bool
  +EntryPoints(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() != 1) {
  +        JS_ReportError(cx, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    RootedObject opts(cx, ToObject(cx, args[0]));
  +    if (!opts)
  +        return false;
  +
  +    // { function: f } --- Call f.
  +    {
  +        RootedValue fun(cx), dummy(cx);
  +
  +        if (!JS_GetProperty(cx, opts, "function", &fun))
  +            return false;
  +        if (!fun.isUndefined()) {
  +            js::shell::ShellAutoEntryMonitor sarep(cx);
  +            if (!Call(cx, UndefinedHandleValue, fun, 
JS::HandleValueArray::empty(), &dummy))
  +                return false;
  +            return sarep.buildResult(cx, args.rval());
  +        }
  +    }
  +
  +    // { object: o, property: p, value: v } --- Fetch o[p], or if
  +    // v is present, assign o[p] = v.
  +    {
  +        RootedValue objectv(cx), propv(cx), valuev(cx);
  +
  +        if (!JS_GetProperty(cx, opts, "object", &objectv) ||
  +            !JS_GetProperty(cx, opts, "property", &propv))
  +            return false;
  +        if (!objectv.isUndefined() && !propv.isUndefined()) {
  +            RootedObject object(cx, ToObject(cx, objectv));
  +            if (!object)
  +                return false;
  +
  +            RootedString string(cx, ToString(cx, propv));
  +            if (!string)
  +                return false;
  +            RootedId id(cx);
  +            if (!JS_StringToId(cx, string, &id))
  +                return false;
  +
  +            if (!JS_GetProperty(cx, opts, "value", &valuev))
  +                return false;
  +
  +            js::shell::ShellAutoEntryMonitor sarep(cx);
  +
  +            if (!valuev.isUndefined()) {
  +                if (!JS_SetPropertyById(cx, object, id, valuev))
  +                    return false;
  +            } else {
  +                if (!JS_GetPropertyById(cx, object, id, &valuev))
  +                    return false;
  +            }
  +
  +            return sarep.buildResult(cx, args.rval());
  +        }
  +    }
  +
  +    // { ToString: v } --- Apply JS::ToString to v.
  +    {
  +        RootedValue v(cx);
  +
  +        if (!JS_GetProperty(cx, opts, "ToString", &v))
  +            return false;
  +        if (!v.isUndefined()) {
  +            js::shell::ShellAutoEntryMonitor sarep(cx);
  +            if (!JS::ToString(cx, v))
  +                return false;
  +            return sarep.buildResult(cx, args.rval());
  +        }
  +    }
  +
  +    // { ToNumber: v } --- Apply JS::ToNumber to v.
  +    {
  +        RootedValue v(cx);
  +        double dummy;
  +
  +        if (!JS_GetProperty(cx, opts, "ToNumber", &v))
  +            return false;
  +        if (!v.isUndefined()) {
  +            js::shell::ShellAutoEntryMonitor sarep(cx);
  +            if (!JS::ToNumber(cx, v, &dummy))
  +                return false;
  +            return sarep.buildResult(cx, args.rval());
  +        }
  +    }
  +
  +    // { eval: code } --- Apply ToString and then Evaluate to code.
  +    {
  +        RootedValue code(cx), dummy(cx);
  +
  +        if (!JS_GetProperty(cx, opts, "eval", &code))
  +            return false;
  +        if (!code.isUndefined()) {
  +            RootedString codeString(cx, ToString(cx, code));
  +            if (!codeString || !codeString->ensureFlat(cx))
  +                return false;
  +
  +            AutoStableStringChars stableChars(cx);
  +            if (!stableChars.initTwoByte(cx, codeString))
  +                return false;
  +            const char16_t* chars = stableChars.twoByteRange().start().get();
  +            size_t length = codeString->length();
  +
  +            CompileOptions options(cx);
  +            options.setIntroductionType("entryPoint eval")
  +                   .setFileAndLine("entryPoint eval", 1);
  +
  +            js::shell::ShellAutoEntryMonitor sarep(cx);
  +            if (!JS::Evaluate(cx, options, chars, length, &dummy))
  +                return false;
  +            return sarep.buildResult(cx, args.rval());
  +        }
  +    }
  +
  +    JS_ReportError(cx, "bad 'params' object");
  +    return false;
  +}
  +#endif       /* NOTYET */
  +
   static const JSFunctionSpec global_functions[] = {
  -    JS_FN("version", Version,        0,0),
  +    JS_FN("version",                 Version,                        0,0),
   #ifdef       NOTYET
  -    JS_FN("load",    Load,           1,0),
  -    JS_FN("evaluate",        Evaluate,       1,0),
  -    JS_FN("run",     Run,            1,0),
  -#ifdef       NOTYET
  -    JS_FN("readline",        ReadLine,       0,0),
  -#endif
  -    JS_FN("print",   Print,          0,0),
  -    JS_FN("putstr",  PutStr,         0,0),
  -    JS_FN("dateNow", Now,            0,0),
  -    JS_FS("require", Require,        0,0),
  +    JS_FN("options",                 Options,                        0,0),
  +    JS_FN("load",                    Load,                           1,0),
  +    JS_FN("loadRelativeToScript",    LoadScriptRelativeToScript,     1,0),
  +    JS_FN("evaluate",                        Evaluate,                       
2,0),
  +    JS_FN("run",                     Run,                            1,0),
  +    JS_FN("readline",                        ReadLine,                       
0,0),
  +#endif       /* NOTYET */
  +    JS_FN("print",                   Print,                          0,0),
  +    JS_FN("printErr",                        PrintErr,                       
0,0),
  +    JS_FN("putstr",                  PutStr,                         0,0),
  +#ifdef       NOTYET
  +    JS_FN("dateNow",                 Now,                            0,0),
  +    JS_FN("help",                    Help,                           0,0),
  +    JS_FN("quit",                    Quit,                           0,0),
  +#endif       /* NOTYET */
  +    JS_FN("assertEq",                        AssertEq,                       
2,0),
  +#ifdef       NOTYET
  +    JS_FN("startTimingMutator",              StartTimingMutator,             
0,0),
  +    JS_FN("stopTimingMutator",               StopTimingMutator,              
0,0),
  +#endif       /* NOTYET */
  +    JS_FN("throwError",                      ThrowError,                     
0,0),
  +#ifdef       NOTYET
  +#ifdef DEBUG
  +    JS_FN("disassemble",             DisassembleToString,            1,0),
  +    JS_FN("dis",                     Disassemble,                    1,0),
  +    JS_FN("disfile",                 DisassFile,                     1,0),
  +    JS_FN("dissrc",                  DisassWithSrc,                  1,0),
  +    JS_FN("notes",                   Notes,                          1,0),
  +    JS_FN("stackDump",                       StackDump,                      
3,0),
  +#endif       /* DEBUG */
  +    JS_FN("intern",                  Intern,                         1,0),
  +    JS_FN("getslx",                  GetSLX,                         1,0),
  +    JS_FN("evalcx",                  EvalInContext,                  1,0),
  +    JS_FN("evalInWorker",            EvalInWorker,                   1,0),
  +    JS_FN("getSharedArrayBuffer",    GetSharedArrayBuffer,           0,0),
  +    JS_FN("setSharedArrayBuffer",    SetSharedArrayBuffer,           0,0),
  +    JS_FN("shapeOf",                 ShapeOf,                        1,0),
  +#ifdef DEBUG
  +    JS_FN("arrayInfo",                       ArrayInfo,                      
1,0),
   #endif
  +    JS_FN("sleep",                   Sleep_fn,                       1,0),
  +    JS_FN("compile",                 Compile,                        1,0),
  +    JS_FN("parseModule",             ParseModule,                    1,0),
  +    JS_FN("setModuleResolveHook",    SetModuleResolveHook,           1,0),
  +    JS_FN("getModuleLoadPath",               GetModuleLoadPath,              
0,0),
  +    JS_FN("parse",                   Parse,                          1,0),
  +    JS_FN("syntaxParse",             SyntaxParse,                    1,0),
  +    JS_FN("offThreadCompileScript",  OffThreadCompileScript,         1,0),
  +    JS_FN("runOffThreadScript",              runOffThreadScript,             
0,0),
  +    JS_FN("timeout",                 Timeout,                        1,0),
  +    JS_FN("interruptIf",             InterruptIf,                    1,0),
  +    JS_FN("invokeInterruptCallback", InvokeInterruptCallbackWrapper, 0,0),
  +    JS_FN("setInterruptCallback",    SetInterruptCallback,           1,0),
  +    JS_FN("enableLastWarning",               EnableLastWarning,              
0,0),
  +    JS_FN("disableLastWarning",              DisableLastWarning,             
0,0),
  +    JS_FN("getLastWarning",          GetLastWarning,                 0,0),
  +    JS_FN("clearLastWarning",                ClearLastWarning,               
0,0),
  +    JS_FN("elapsed",                 Elapsed,                        0,0),
  +    JS_FN("decompileFunction",               DecompileFunction,              
1,0),
  +    JS_FN("decompileThis",           DecompileThisScript,            0,0),
  +    JS_FN("thisFilename",            ThisFilename,                   0,0),
  +    JS_FN("newGlobal",                       NewGlobal,                      
1,0),
  +    JS_FN("nukeCCW",                 NukeCCW,                        1,0),
  +    JS_FN("createMappedArrayBuffer", CreateMappedArrayBuffer,        1,0),
  +    JS_FN("getMaxArgs",                      GetMaxArgs,                     
0,0),
  +    JS_FN("objectEmulatingUndefined",        ObjectEmulatingUndefined,       
0,0),
  +    JS_FN("isCachingEnabled",                IsCachingEnabled,               
0,0),
  +    JS_FN("setCachingEnabled",               SetCachingEnabled,              
1,0),
  +    JS_FN("cacheEntry",                      CacheEntry,                     
1,0),
  +    JS_FN("printProfilerEvents",     PrintProfilerEvents,            0,0),
  +    JS_FN("enableSingleStepProfiling",       EnableSingleStepProfiling,      
0,0),
  +    JS_FN("disableSingleStepProfiling",      DisableSingleStepProfiling,     
0,0),
  +    JS_FN("isLatin1",                        IsLatin1,                       
1,0),
  +    JS_FN("stackPointerInfo",                StackPointerInfo,               
0,0),
  +    JS_FN("entryPoints",             EntryPoints,                    1,0),
  +
  +    JS_FS("require",                 Require,                        0,0),
  +#endif       /* NOTYET */
       JS_FS_END
   };
   
  @@ -792,8 +2299,8 @@
       return I;
   }
   
  -static int mozRun(rpmjss jss,
  -             const char * script, const char * fn, int ln)
  +static int mozRun(rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln)
   {
       JSI_t I = (JSI_t) jss->I;
   
  @@ -814,8 +2321,10 @@
   
       JSString *str = rval.toString();
       char * t = JS_EncodeString(I->cx, str);
  -    printf("%s\n", t);
  -    t = _free(t);
  +    if (resultp)
  +     *resultp = t;
  +    else
  +     t = _free(t);
   
       return 0;
   }
  @@ -837,7 +2346,10 @@
   
       {
        const char *script = "'hello'+'world, it is '+new Date()";
  -     rc = mozRun(jss, script, __FILE__, __LINE__);
  +     const char * result = NULL;
  +     rc = mozRun(jss, &result, script, __FILE__, __LINE__);
  +     fprintf(stderr, "<== result |%s|\n", result);
  +     result = _free(result);
       }
   
       mozFini(jss);
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjss.h
  ============================================================================
  $ cvs diff -u -r1.1.2.1 -r1.1.2.2 rpmjss.h
  --- rpm/rpmio/rpmjss.h        23 Jun 2017 03:39:44 -0000      1.1.2.1
  +++ rpm/rpmio/rpmjss.h        24 Jun 2017 19:09:35 -0000      1.1.2.2
  @@ -54,7 +54,8 @@
   struct JSIO_s {
       void (*mozFini)  (rpmjss jss);
       void * (*mozInit)        (rpmjss jss);
  -    int  (*mozRun)   (rpmjss jss, const char * script, const char * 
filename, int lineno);
  +    int  (*mozRun)   (rpmjss jss, const char ** resultp,
  +             const char * script, const char * fn, unsigned ln);
   };
   
   extern JSIO_t mozjs185;
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to