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:   02-Jul-2017 14:34:30
  Branch: rpm-5_4                          Handle: 2017070212342900

  Modified files:           (Branch: rpm-5_4)
    rpm/rpmio               Makefile.am rpmjs45.cpp rpmjss.inp

  Log:
    - r[pmjs45: WIP.

  Summary:
    Revision    Changes     Path
    1.293.2.103 +1  -1      rpm/rpmio/Makefile.am
    1.1.2.14    +4263 -183  rpm/rpmio/rpmjs45.cpp
    1.1.2.5     +64 -2      rpm/rpmio/rpmjss.inp
  ____________________________________________________________________________

  patch -p0 <<'@@ .'
  Index: rpm/rpmio/Makefile.am
  ============================================================================
  $ cvs diff -u -r1.293.2.102 -r1.293.2.103 Makefile.am
  --- rpm/rpmio/Makefile.am     28 Jun 2017 09:54:15 -0000      1.293.2.102
  +++ rpm/rpmio/Makefile.am     2 Jul 2017 12:34:29 -0000       1.293.2.103
  @@ -575,7 +575,7 @@
   rpmjs38_LDADD = -L/usr/lib64 -lmozjs-38 $(RPMIO_LDADD_COMMON)
   
   rpmjs45_SOURCES = rpmjs45.cpp
  -rpmjs45_CPPFLAGS = -include /usr/include/mozjs-45/js/RequiredDefines.h 
-I/usr/include/mozjs-45 -I/F/mozjs45/firefox-45.9.0esr/js/src -fPIC 
-DRPMJSS_SELF_TEST
  +rpmjs45_CPPFLAGS = -include /usr/include/mozjs-45/js/RequiredDefines.h 
-I/usr/include/mozjs-45 -I./js45/src/shell -I./js45/src -DXP_UNIX -fPIC 
-DRPMJSS_SELF_TEST
   rpmjs45_LDADD = -L/usr/lib64 -lmozjs-45 $(RPMIO_LDADD_COMMON)
   
   mozjs:       rpmjs185 rpmjs17 rpmjs24 rpmjs31 rpmjs38 rpmjs45
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjs45.cpp
  ============================================================================
  $ cvs diff -u -r1.1.2.13 -r1.1.2.14 rpmjs45.cpp
  --- rpm/rpmio/rpmjs45.cpp     1 Jul 2017 04:00:07 -0000       1.1.2.13
  +++ rpm/rpmio/rpmjs45.cpp     2 Jul 2017 12:34:29 -0000       1.1.2.14
  @@ -46,84 +46,6 @@
   
   #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;
  @@ -131,51 +53,13 @@
       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
  +typedef struct JSI_s * JSI_t;
  +struct JSI_s {
  +    JSRuntime        *rt;
  +    JSContext        *cx;
  +    JSObject *global;
   };
   
  -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,
  @@ -353,7 +237,7 @@
               obj = JS_NewUint8Array(cx, len);
               if (!obj) {
   #if !defined(FIXME)
  -             if (file) (void) fclose(file);
  +             if (file && fileno(file) > 2) (void) fclose(file);
   #endif
                   return nullptr;
            }
  @@ -1036,13 +920,76 @@
   #endif
   
   /*==============================================================*/
  +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 JSShellExitCode {
  -    EXITCODE_RUNTIME_ERROR   = 3,
  -    EXITCODE_FILE_NOT_FOUND  = 4,
  -    EXITCODE_OUT_OF_MEMORY   = 5,
  -    EXITCODE_TIMEOUT         = 6
  +    EXITCODE_RUNTIME_ERROR      = 3,
  +    EXITCODE_FILE_NOT_FOUND     = 4,
  +    EXITCODE_OUT_OF_MEMORY      = 5,
  +    EXITCODE_TIMEOUT            = 6
   };
   
  +static const size_t gStackChunkSize = 8192;
  +
  +/*
  + * Note: This limit should match the stack limit set by the browser in
  + *       js/xpconnect/src/XPCJSRuntime.cpp
  + */
  +#if defined(MOZ_ASAN) || (defined(DEBUG) && !defined(XP_WIN))
  +static const size_t gMaxStackSize = 2 * 128 * sizeof(size_t) * 1024;
  +#else
  +static const size_t gMaxStackSize = 128 * sizeof(size_t) * 1024;
  +#endif
  +
  +/*
  + * Limit the timeout to 30 minutes to prevent an overflow on platfoms
  + * that represent the time internally in microseconds using 32-bit int.
  + */
  +static const double MAX_TIMEOUT_INTERVAL = 1800.0;
  +
   // Per-runtime shell state.
   #ifdef       NOTYET
   struct ShellRuntime
  @@ -1073,6 +1020,127 @@
   };
   #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
  +
  +// Shell state this is only accessed on the main thread.
  +bool jsCachingEnabled = false;
  +mozilla::Atomic<bool> jsCacheOpened(false);
  +
  +static bool
  +SetTimeoutValue(JSContext* cx, double t);
  +
  +static bool
  +InitWatchdog(JSRuntime* rt);
  +
  +static void
  +KillWatchdog(JSRuntime *rt);
  +
  +static bool
  +ScheduleWatchdog(JSRuntime* rt, double t);
  +
  +static void
  +CancelExecution(JSRuntime* rt);
  +
  +static JSContext*
  +NewContext(JSRuntime* rt);
  +
  +static void
  +DestroyContext(JSContext* cx, bool withGC);
  +
  +static JSObject*
  +NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options,
  +                JSPrincipals* principals);
  +
  +/*
  + * A toy principals type for the shell.
  + *
  + * In the shell, a principal is simply a 32-bit mask: P subsumes Q if the
  + * set bits in P are a superset of those in Q. Thus, the principal 0 is
  + * subsumed by everything, and the principal ~0 subsumes everything.
  + *
  + * As a special case, a null pointer as a principal is treated like 0xffff.
  + *
  + * The 'newGlobal' function takes an option indicating which principal the
  + * new global should have; 'evaluate' does for the new code.
  + */
  +class ShellPrincipals final : public JSPrincipals {
  +    uint32_t bits;
  +
  +    static uint32_t getBits(JSPrincipals* p) {
  +        if (!p)
  +            return 0xffff;
  +        return static_cast<ShellPrincipals*>(p)->bits;
  +    }
  +
  +  public:
  +    explicit ShellPrincipals(uint32_t bits, int32_t refcount = 0) : 
bits(bits) {
  +        this->refcount = refcount;
  +    }
  +
  +    bool write(JSContext* cx, JSStructuredCloneWriter* writer) override {
  +        MOZ_ASSERT(false, "not implemented");
  +        return false;
  +    }
  +
  +    static void destroy(JSPrincipals* principals) {
  +        MOZ_ASSERT(principals != &fullyTrusted);
  +        MOZ_ASSERT(principals->refcount == 0);
  +        js_delete(static_cast<const ShellPrincipals*>(principals));
  +    }
  +
  +    static bool subsumes(JSPrincipals* first, JSPrincipals* second) {
  +        uint32_t firstBits  = getBits(first);
  +        uint32_t secondBits = getBits(second);
  +        return (firstBits | secondBits) == firstBits;
  +    }
  +
  +    static JSSecurityCallbacks securityCallbacks;
  +
  +    // Fully-trusted principals singleton.
  +    static ShellPrincipals fullyTrusted;
  +};
  +
  +JSSecurityCallbacks ShellPrincipals::securityCallbacks = {
  +    nullptr, // contentSecurityPolicyAllows
  +    subsumes
  +};
  +
  +// The fully-trusted principal subsumes all other principals.
  +ShellPrincipals ShellPrincipals::fullyTrusted(-1, 1);
  +
  +#ifdef EDITLINE
  +extern "C" {
  +extern JS_EXPORT_API(char*) readline(const char* prompt);
  +extern JS_EXPORT_API(void)   add_history(char* line);
  +} // extern "C"
  +#endif
  +
   #ifdef       NOTYET
   ShellRuntime::ShellRuntime()
     : isWorker(false),
  @@ -1089,7 +1157,9 @@
       quitting(false),
       gotError(false)
   {}
  +#endif
   
  +#ifdef       NOTYET
   static ShellRuntime*
   GetShellRuntime(JSRuntime *rt)
   {
  @@ -1099,12 +1169,485 @@
   }
   #endif
   
  -static bool
  -Version(JSContext* cx, unsigned argc, Value* vp)
  +#ifdef       NOTYET
  +static ShellRuntime*
  +GetShellRuntime(JSContext* cx)
   {
  -    CallArgs args = CallArgsFromVp(argc, vp);
  -    JSVersion origVersion = JS_GetVersion(cx);
  -    if (args.length() == 0 || args[0].isUndefined()) {
  +    return GetShellRuntime(cx->runtime());
  +}
  +#endif
  +
  +static char*
  +GetLine(FILE* file, const char * prompt)
  +{
  +#ifdef EDITLINE
  +    /*
  +     * Use readline only if file is stdin, because there's no way to specify
  +     * another handle.  Are other filehandles interactive?
  +     */
  +    if (file == stdin) {
  +        char* linep = readline(prompt);
  +        /*
  +         * We set it to zero to avoid complaining about inappropriate ioctl
  +         * for device in the case of EOF. Looks like errno == 251 if line is
  +         * finished with EOF and errno == 25 (EINVAL on Mac) if there is
  +         * nothing left to read.
  +         */
  +        if (errno == 251 || errno == 25 || errno == EINVAL)
  +            errno = 0;
  +        if (!linep)
  +            return nullptr;
  +        if (linep[0] != '\0')
  +            add_history(linep);
  +        return linep;
  +    }
  +#endif
  +
  +    size_t len = 0;
  +    if (*prompt != '\0') {
  +        fprintf(gOutFile, "%s", prompt);
  +        fflush(gOutFile);
  +    }
  +
  +    size_t size = 80;
  +    char* buffer = static_cast<char*>(malloc(size));
  +    if (!buffer)
  +        return nullptr;
  +
  +    char* current = buffer;
  +    while (true) {
  +        while (true) {
  +            if (fgets(current, size - len, file))
  +                break;
  +            if (errno != EINTR) {
  +                free(buffer);
  +                return nullptr;
  +            }
  +        }
  +
  +        len += strlen(current);
  +        char* t = buffer + len - 1;
  +        if (*t == '\n') {
  +            /* Line was read. We remove '\n' and exit. */
  +            *t = '\0';
  +            return buffer;
  +        }
  +
  +        if (len + 1 == size) {
  +            size = size * 2;
  +            char* tmp = static_cast<char*>(realloc(buffer, size));
  +            if (!tmp) {
  +                free(buffer);
  +                return nullptr;
  +            }
  +            buffer = tmp;
  +        }
  +        current = buffer + len;
  +    }
  +
  +    if (len && !ferror(file))
  +        return buffer;
  +    free(buffer);
  +    return nullptr;
  +}
  +
  +/* State to store as JSContext private. */
  +struct JSShellContextData {
  +    /* Creation timestamp, used by the elapsed() shell builtin. */
  +    int64_t startTime;
  +};
  +
  +static JSShellContextData*
  +NewContextData()
  +{
  +    JSShellContextData* data = (JSShellContextData*)
  +                               js_calloc(sizeof(JSShellContextData), 1);
  +    if (!data)
  +        return nullptr;
  +#ifdef  FIXME
  +    data->startTime = PRMJ_Now();
  +#else
  +    struct timeval tv;
  +    gettimeofday(&tv, NULL);
  +    data->startTime = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +#endif
  +    return data;
  +}
  +
  +static inline JSShellContextData*
  +GetContextData(JSContext* cx)
  +{
  +    JSShellContextData* data = (JSShellContextData*) 
JS_GetContextPrivate(cx);
  +
  +    MOZ_ASSERT(data);
  +    return data;
  +}
  +
  +#ifdef       NOTYET
  +static bool
  +ShellInterruptCallback(JSContext* cx)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    if (!sr->serviceInterrupt)
  +        return true;
  +
  +    // Reset serviceInterrupt. CancelExecution or InterruptIf will set it to
  +    // true to distinguish watchdog or user triggered interrupts.
  +    // Do this first to prevent other interrupts that may occur while the
  +    // user-supplied callback is executing from re-entering the handler.
  +    sr->serviceInterrupt = false;
  +
  +    bool result;
  +    RootedValue interruptFunc(cx, sr->interruptFunc);
  +    if (!interruptFunc.isNull()) {
  +        JS::AutoSaveExceptionState savedExc(cx);
  +        JSAutoCompartment ac(cx, &interruptFunc.toObject());
  +        RootedValue rval(cx);
  +        if (!JS_CallFunctionValue(cx, nullptr, interruptFunc,
  +                                  JS::HandleValueArray::empty(), &rval))
  +        {
  +            return false;
  +        }
  +        if (rval.isBoolean())
  +            result = rval.toBoolean();
  +        else
  +            result = false;
  +    } else {
  +        result = false;
  +    }
  +
  +    if (!result && sr->exitCode == 0)
  +        sr->exitCode = EXITCODE_TIMEOUT;
  +
  +    return result;
  +}
  +#endif
  +
  +/*
  + * Some UTF-8 files, notably those written using Notepad, have a Unicode
  + * Byte-Order-Mark (BOM) as their first character. This is useless 
(byte-order
  + * is meaningless for UTF-8) but causes a syntax error unless we skip it.
  + */
  +static void
  +SkipUTF8BOM(FILE* file)
  +{
  +    int ch1 = fgetc(file);
  +    int ch2 = fgetc(file);
  +    int ch3 = fgetc(file);
  +
  +    // Skip the BOM
  +    if (ch1 == 0xEF && ch2 == 0xBB && ch3 == 0xBF)
  +        return;
  +
  +    // No BOM - revert
  +    if (ch3 != EOF)
  +        ungetc(ch3, file);
  +    if (ch2 != EOF)
  +        ungetc(ch2, file);
  +    if (ch1 != EOF)
  +        ungetc(ch1, file);
  +}
  +
  +#ifdef       NOTYET
  +static void
  +RunFile(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +
  +    SkipUTF8BOM(file);
  +
  +    // To support the UNIX #! shell hack, gobble the first line if it starts
  +    // with '#'.
  +    int ch = fgetc(file);
  +    if (ch == '#') {
  +        while ((ch = fgetc(file)) != EOF) {
  +            if (ch == '\n' || ch == '\r')
  +                break;
  +        }
  +    }
  +    ungetc(ch, file);
  +
  +#ifdef  FIXME
  +    int64_t t1 = PRMJ_Now();
  +#else
  +    struct timeval tv;
  +    gettimeofday(&tv, NULL);
  +    int64_t t1 = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +#endif
  +    RootedScript script(cx);
  +
  +    {
  +        CompileOptions options(cx);
  +        options.setIntroductionType("js shell file")
  +               .setUTF8(true)
  +               .setFileAndLine(filename, 1)
  +               .setIsRunOnce(true)
  +               .setNoScriptRval(true);
  +
  +        sr->gotError = false;
  +        (void) JS::Compile(cx, options, file, &script);
  +        MOZ_ASSERT_IF(!script, sr->gotError);
  +    }
  +
  +    #ifdef DEBUG
  +        if (dumpEntrainedVariables)
  +            AnalyzeEntrainedVariables(cx, script);
  +    #endif
  +    if (script && !compileOnly) {
  +        if (!JS_ExecuteScript(cx, script)) {
  +            if (!sr->quitting && sr->exitCode != EXITCODE_TIMEOUT)
  +                sr->exitCode = EXITCODE_RUNTIME_ERROR;
  +        }
  +#ifdef  FIXME
  +        int64_t t2 = PRMJ_Now() - t1;
  +#else
  +        struct timeval tv;
  +        gettimeofday(&tv, NULL);
  +        int64_t t2 = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +        t2 -= t1;
  +#endif
  +        if (printTiming)
  +            printf("runtime = %.3f ms\n", double(t2) / PRMJ_USEC_PER_MSEC);
  +    }
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +InitModuleLoader(JSContext* cx)
  +{
  +    // Decompress and evaluate the embedded module loader source to 
initialize
  +    // the module loader for the current compartment.
  +
  +    uint32_t srcLen = moduleloader::GetRawScriptsSize();
  +    ScopedJSFreePtr<char> src(cx->pod_malloc<char>(srcLen));
  +    if (!src || !DecompressString(moduleloader::compressedSources, 
moduleloader::GetCompressedSize(),
  +                                  reinterpret_cast<unsigned 
char*>(src.get()), srcLen))
  +    {
  +        return false;
  +    }
  +
  +    CompileOptions options(cx);
  +    options.setIntroductionType("shell module loader");
  +    options.setFileAndLine("shell/ModuleLoader.js", 1);
  +    options.setSelfHostingMode(false);
  +    options.setCanLazilyParse(false);
  +    options.setVersion(JSVERSION_LATEST);
  +    options.werrorOption = true;
  +    options.strictOption = true;
  +
  +    RootedValue rv(cx);
  +    return Evaluate(cx, options, src, srcLen, &rv);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +GetLoaderObject(JSContext* cx, MutableHandleObject resultOut)
  +{
  +    // Look up the |Reflect.Loader| object that has been defined by the 
module
  +    // loader.
  +
  +    RootedObject object(cx, cx->global());
  +    RootedValue value(cx);
  +    if (!JS_GetProperty(cx, object, "Reflect", &value) || !value.isObject())
  +        return false;
  +
  +    object = &value.toObject();
  +    if (!JS_GetProperty(cx, object, "Loader", &value) || !value.isObject())
  +        return false;
  +
  +    resultOut.set(&value.toObject());
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +GetImportMethod(JSContext* cx, HandleObject loader, MutableHandleFunction 
resultOut)
  +{
  +    // Look up the module loader's |import| method.
  +
  +    RootedValue value(cx);
  +    if (!JS_GetProperty(cx, loader, "import", &value) || !value.isObject())
  +        return false;
  +
  +    RootedObject object(cx, &value.toObject());
  +    if (!object->is<JSFunction>())
  +        return false;
  +
  +    resultOut.set(&object->as<JSFunction>());
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static void
  +RunModule(JSContext* cx, const char* filename, FILE* file, bool compileOnly)
  +{
  +    // Exectute a module by calling |Reflect.Loader.import(filename)|.
  +
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +
  +    RootedObject loaderObj(cx);
  +    MOZ_ALWAYS_TRUE(GetLoaderObject(cx, &loaderObj));
  +
  +    RootedFunction importFun(cx);
  +    MOZ_ALWAYS_TRUE(GetImportMethod(cx, loaderObj, &importFun));
  +
  +    AutoValueArray<2> args(cx);
  +    args[0].setString(JS_NewStringCopyZ(cx, filename));
  +    args[1].setUndefined();
  +
  +    RootedValue value(cx);
  +    if (!JS_CallFunction(cx, loaderObj, importFun, args, &value)) {
  +        sr->exitCode = EXITCODE_RUNTIME_ERROR;
  +        return;
  +    }
  +}
  +#endif
  +
  +static bool
  +EvalAndPrint(JSContext* cx, const char* bytes, size_t length,
  +             int lineno, bool compileOnly, FILE* out)
  +{
  +    // Eval.
  +    JS::CompileOptions options(cx);
  +    options.setIntroductionType("js shell interactive")
  +           .setUTF8(true)
  +           .setIsRunOnce(true)
  +           .setFileAndLine("typein", lineno);
  +    RootedScript script(cx);
  +    if (!JS::Compile(cx, options, bytes, length, &script))
  +        return false;
  +    if (compileOnly)
  +        return true;
  +    RootedValue result(cx);
  +    if (!JS_ExecuteScript(cx, script, &result))
  +        return false;
  +
  +    if (!result.isUndefined()) {
  +        // Print.
  +        RootedString str(cx);
  +        str = JS_ValueToSource(cx, result);
  +        if (!str)
  +            return false;
  +
  +        char* utf8chars = JS_EncodeStringToUTF8(cx, str);
  +        if (!utf8chars)
  +            return false;
  +        fprintf(out, "%s\n", utf8chars);
  +        JS_free(cx, utf8chars);
  +    }
  +    return true;
  +}
  +
  +#ifdef       NOTYET
  +static void
  +ReadEvalPrintLoop(JSContext* cx, FILE* in, FILE* out, bool compileOnly)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    int lineno = 1;
  +    bool hitEOF = false;
  +
  +    do {
  +        /*
  +         * Accumulate lines until we get a 'compilable unit' - one that 
either
  +         * generates an error (before running out of source) or that compiles
  +         * cleanly.  This should be whenever we get a complete statement that
  +         * coincides with the end of a line.
  +         */
  +        int startline = lineno;
  +        typedef Vector<char, 32> CharBuffer;
  +        CharBuffer buffer(cx);
  +        do {
  +            ScheduleWatchdog(cx->runtime(), -1);
  +            sr->serviceInterrupt = false;
  +            errno = 0;
  +
  +            char* line = GetLine(in, startline == lineno ? "js> " : "");
  +            if (!line) {
  +                if (errno) {
  +                    JS_ReportError(cx, strerror(errno));
  +                    return;
  +                }
  +                hitEOF = true;
  +                break;
  +            }
  +
  +            if (!buffer.append(line, strlen(line)) || !buffer.append('\n'))
  +                return;
  +
  +            lineno++;
  +            if (!ScheduleWatchdog(cx->runtime(), sr->timeoutInterval)) {
  +                hitEOF = true;
  +                break;
  +            }
  +        } while (!JS_BufferIsCompilableUnit(cx, cx->global(), 
buffer.begin(), buffer.length()));
  +
  +        if (hitEOF && buffer.empty())
  +            break;
  +
  +        if (!EvalAndPrint(cx, buffer.begin(), buffer.length(), startline, 
compileOnly,
  +                          out))
  +        {
  +            // Catch the error, report it, and keep going.
  +            JS_ReportPendingException(cx);
  +        }
  +    } while (!hitEOF && !sr->quitting);
  +
  +    fprintf(out, "\n");
  +}
  +#endif
  +
  +enum FileKind
  +{
  +    FileScript,
  +    FileModule
  +};
  +
  +#ifdef       NOTYET
  +static void
  +Process(JSContext* cx, const char* filename, bool forceTTY, FileKind kind = 
FileScript)
  +{
  +    FILE* file;
  +    if (forceTTY || !filename || strcmp(filename, "-") == 0) {
  +        file = stdin;
  +    } else {
  +        file = fopen(filename, "r");
  +        if (!file) {
  +            JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr,
  +                                 JSSMSG_CANT_OPEN, filename, 
strerror(errno));
  +            return;
  +        }
  +    }
  +#ifdef       FIXME
  +    AutoCloseFile autoClose(file);
  +#endif
  +
  +    if (!forceTTY && !isatty(fileno(file))) {
  +        // It's not interactive - just execute it.
  +        if (kind == FileScript)
  +            RunFile(cx, filename, file, compileOnly);
  +        else
  +            RunModule(cx, filename, file, compileOnly);
  +    } else {
  +        // It's an interactive filehandle; drop into read-eval-print loop.
  +        MOZ_ASSERT(kind == FileScript);
  +        ReadEvalPrintLoop(cx, file, gOutFile, compileOnly);
  +    }
  +#if !defined(FIXME)
  +    if (file && fileno(file) > 2) (void) fclose(file);
  +#endif
  +}
  +#endif
  +
  +static bool
  +Version(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    JSVersion origVersion = JS_GetVersion(cx);
  +    if (args.length() == 0 || args[0].isUndefined()) {
           /* Get version. */
           args.rval().setInt32(origVersion);
       } else {
  @@ -1276,7 +1819,6 @@
       return true;
   }
   
  -#ifndef      NOTYET
   static bool
   LoadScript(JSContext* cx, unsigned argc, Value* vp, bool scriptRelative)
   {
  @@ -1315,28 +1857,22 @@
       args.rval().setUndefined();
       return true;
   }
  -#endif
   
  -#ifndef      NOTYET
   static bool
   Load(JSContext* cx, unsigned argc, Value* vp)
   {
       return LoadScript(cx, argc, vp, false);
   }
  -#endif
   
  -#ifndef      NOTYET
   static bool
   LoadScriptRelativeToScript(JSContext* cx, unsigned argc, Value* vp)
   {
       return LoadScript(cx, argc, vp, true);
   }
  -#endif
   
   // Populate |options| with the options given by |opts|'s properties. If we
   // need to convert a filename to a C string, let fileNameBytes own the
   // bytes.
  -#ifdef       NOTYET
   static bool
   ParseCompileOptions(JSContext* cx, CompileOptions& options, HandleObject 
opts,
                       JSAutoByteString& fileNameBytes)
  @@ -1407,7 +1943,6 @@
   
       return true;
   }
  -#endif
   
   #ifdef       NOTYET
   class AutoNewContext
  @@ -1480,7 +2015,6 @@
       "CacheEntryObject", JSCLASS_HAS_RESERVED_SLOTS(2)
   };
   
  -#ifndef      NOTYET
   static bool
   CacheEntry(JSContext* cx, unsigned argc, JS::Value* vp)
   {
  @@ -1500,17 +2034,13 @@
       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)
   {
  @@ -1521,7 +2051,6 @@
   
       return v.toString();
   }
  -#endif
   
   #ifdef       NOTYET
   static uint8_t*
  @@ -1874,7 +2403,7 @@
                       if (!ucbuf) {
                           JS_ReportError(cx, "Invalid UTF-8 in file '%s'", 
pathname);
   #if !defined(FIXME)
  -                     if (file) fclose(file);
  +                     if (file && fileno(file) > 2) (void) fclose(file);
   #endif
                           return nullptr;
                       }
  @@ -2154,43 +2683,3316 @@
       return false;
   }
   
  -static const JSFunctionSpec global_functions[] = {
  -    JS_FN("version",                 Version,                        0,0),
  -    JS_FN("options",                 Options,                        0,0),
  -    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),
  -#endif       /* NOTYET */
  -    JS_FN("print",                   Print,                          0,0),
  -    JS_FN("printErr",                        PrintErr,                       
0,0),
  -    JS_FN("putstr",                  PutStr,                         0,0),
  -    JS_FN("dateNow",                 Now,                            0,0),
  -#ifdef       NOTYET
  -    JS_FN("help",                    Help,                           0,0),
  -#endif       /* NOTYET */
  -    JS_FN("quit",                    Quit,                           0,0),
  -#ifdef       NOTYET
  -    JS_FN("assertEq",                        AssertEq,                       
2,0),
  -    JS_FN("startTimingMutator",              StartTimingMutator,             
0,0),
  -    JS_FN("stopTimingMutator",               StopTimingMutator,              
0,0),
  -    JS_FN("throwError",                      ThrowError,                     
0,0),
  -#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),
  +#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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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
  +
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static JSScript*
  +GetTopScript(JSContext* cx)
  +{
  +    NonBuiltinScriptFrameIter iter(cx);
  +    return iter.done() ? nullptr : iter.script();
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef DEBUG
  +
  +#ifdef  NOTYET
  +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);
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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");
  +    }
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +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" };
  +
  +#ifdef       NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +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 */
  +#endif
  +
  +#ifdef  NOTYET
  +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();
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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
  +
  +#endif /* DEBUG */
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +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;
  +}
  +#endif
  +
  +#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
  +
  +static bool
  +ThrowError(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    JS_ReportError(cx, "This is an error");
  +    return false;
  +}
  +
  +#define LAZY_STANDARD_CLASSES
  +
  +/* A class for easily testing the inner/outer object callbacks. */
  +typedef struct ComplexObject {
  +    bool isInner;
  +    bool frozen;
  +    JSObject* inner;
  +    JSObject* outer;
  +} ComplexObject;
  +
  +static bool
  +sandbox_enumerate(JSContext* cx, HandleObject obj)
  +{
  +    RootedValue v(cx);
  +
  +    if (!JS_GetProperty(cx, obj, "lazy", &v))
  +        return false;
  +
  +    if (!ToBoolean(v))
  +        return true;
  +
  +    return JS_EnumerateStandardClasses(cx, obj);
  +}
  +
  +static bool
  +sandbox_resolve(JSContext* cx, HandleObject obj, HandleId id, bool* 
resolvedp)
  +{
  +    RootedValue v(cx);
  +    if (!JS_GetProperty(cx, obj, "lazy", &v))
  +        return false;
  +
  +    if (ToBoolean(v))
  +        return JS_ResolveStandardClass(cx, obj, id, resolvedp);
  +    return true;
  +}
  +
  +static const JSClass sandbox_class = {
  +    "sandbox",
  +    JSCLASS_GLOBAL_FLAGS,
  +    nullptr, nullptr, nullptr, nullptr,
  +    sandbox_enumerate, sandbox_resolve,
  +    nullptr, nullptr,
  +    nullptr, nullptr, nullptr,
  +    JS_GlobalObjectTraceHook
  +};
  +
  +#ifdef  NOTYET
  +static JSObject*
  +NewSandbox(JSContext* cx, bool lazy)
  +{
  +    RootedObject obj(cx, JS_NewGlobalObject(cx, &sandbox_class, nullptr,
  +                                            JS::DontFireOnNewGlobalHook));
  +    if (!obj)
  +        return nullptr;
  +
  +    {
  +        JSAutoCompartment ac(cx, obj);
  +        if (!lazy && !JS_InitStandardClasses(cx, obj))
  +            return nullptr;
  +
  +        RootedValue value(cx, BooleanValue(lazy));
  +        if (!JS_SetProperty(cx, obj, "lazy", value))
  +            return nullptr;
  +    }
  +
  +    JS_FireOnNewGlobalObject(cx, obj);
  +
  +    if (!cx->compartment()->wrap(cx, &obj))
  +        return nullptr;
  +    return obj;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +EvalInContext(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (!args.requireAtLeast(cx, "evalcx", 1))
  +        return false;
  +
  +    RootedString str(cx, ToString(cx, args[0]));
  +    if (!str)
  +        return false;
  +
  +    RootedObject sobj(cx);
  +    if (args.hasDefined(1)) {
  +        sobj = ToObject(cx, args[1]);
  +        if (!sobj)
  +            return false;
  +    }
  +
  +    AutoStableStringChars strChars(cx);
  +    if (!strChars.initTwoByte(cx, str))
  +        return false;
  +
  +    mozilla::Range<const char16_t> chars = strChars.twoByteRange();
  +    size_t srclen = chars.length();
  +    const char16_t* src = chars.start().get();
  +
  +    bool lazy = false;
  +    if (srclen == 4) {
  +        if (src[0] == 'l' && src[1] == 'a' && src[2] == 'z' && src[3] == 
'y') {
  +            lazy = true;
  +            srclen = 0;
  +        }
  +    }
  +
  +    if (!sobj) {
  +        sobj = NewSandbox(cx, lazy);
  +        if (!sobj)
  +            return false;
  +    }
  +
  +    if (srclen == 0) {
  +        args.rval().setObject(*sobj);
  +        return true;
  +    }
  +
  +    JS::AutoFilename filename;
  +    unsigned lineno;
  +
  +    DescribeScriptedCaller(cx, &filename, &lineno);
  +    {
  +        Maybe<JSAutoCompartment> ac;
  +        unsigned flags;
  +        JSObject* unwrapped = UncheckedUnwrap(sobj, true, &flags);
  +        if (flags & Wrapper::CROSS_COMPARTMENT) {
  +            sobj = unwrapped;
  +            ac.emplace(cx, sobj);
  +        }
  +
  +        sobj = ToWindowIfWindowProxy(sobj);
  +
  +        if (!(sobj->getClass()->flags & JSCLASS_IS_GLOBAL)) {
  +            JS_ReportError(cx, "Invalid scope argument to evalcx");
  +            return false;
  +        }
  +        JS::CompileOptions opts(cx);
  +        opts.setFileAndLine(filename.get(), lineno);
  +        if (!JS::Evaluate(cx, opts, src, srclen, args.rval())) {
  +            return false;
  +        }
  +    }
  +
  +    if (!cx->compartment()->wrap(cx, args.rval()))
  +        return false;
  +
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +struct WorkerInput
  +{
  +    JSRuntime* runtime;
  +    char16_t* chars;
  +    size_t length;
  +
  +    WorkerInput(JSRuntime* runtime, char16_t* chars, size_t length)
  +      : runtime(runtime), chars(chars), length(length)
  +    {}
  +
  +    ~WorkerInput() {
  +        js_free(chars);
  +    }
  +};
  +#endif
  +
  +static void SetWorkerRuntimeOptions(JSRuntime* rt);
  +
  +#ifdef       NOTYET
  +static void
  +WorkerMain(void* arg)
  +{
  +    WorkerInput* input = (WorkerInput*) arg;
  +
  +    JSRuntime* rt = JS_NewRuntime(8L * 1024L * 1024L, 2L * 1024L * 1024L, 
input->runtime);
  +    if (!rt) {
  +        js_delete(input);
  +        return;
  +    }
  +
  +    mozilla::UniquePtr<ShellRuntime> sr = MakeUnique<ShellRuntime>();
  +    if (!sr) {
  +        JS_DestroyRuntime(rt);
  +        js_delete(input);
  +        return;
  +    }
  +
  +    sr->isWorker = true;
  +    JS_SetRuntimePrivate(rt, sr.get());
  +    JS_SetErrorReporter(rt, my_ErrorReporter);
  +    SetWorkerRuntimeOptions(rt);
  +
  +    if (!InitWatchdog(rt)) {
  +        JS_DestroyRuntime(rt);
  +        js_delete(input);
  +        return;
  +    }
  +
  +    JSContext* cx = NewContext(rt);
  +    if (!cx) {
  +        JS_DestroyRuntime(rt);
  +        js_delete(input);
  +        return;
  +    }
  +
  +    JS::SetLargeAllocationFailureCallback(rt, my_LargeAllocFailCallback, 
(void*)cx);
  +
  +    do {
  +        JSAutoRequest ar(cx);
  +
  +        JS::CompartmentOptions compartmentOptions;
  +        compartmentOptions.setVersion(JSVERSION_DEFAULT);
  +        RootedObject global(cx, NewGlobalObject(cx, compartmentOptions, 
nullptr));
  +        if (!global)
  +            break;
  +
  +        JSAutoCompartment ac(cx, global);
  +
  +        JS::CompileOptions options(cx);
  +        options.setFileAndLine("<string>", 1)
  +               .setIsRunOnce(true);
  +
  +        RootedScript script(cx);
  +        if (!JS::Compile(cx, options, input->chars, input->length, &script))
  +            break;
  +        RootedValue result(cx);
  +        JS_ExecuteScript(cx, script, &result);
  +    } while (0);
  +
  +    JS::SetLargeAllocationFailureCallback(rt, nullptr, nullptr);
  +
  +    DestroyContext(cx, false);
  +    JS_DestroyRuntime(rt);
  +
  +    js_delete(input);
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +Vector<PRThread*, 0, SystemAllocPolicy> workerThreads;
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +EvalInWorker(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    if (!CanUseExtraThreads()) {
  +        JS_ReportError(cx, "Can't create worker threads with --no-threads");
  +        return false;
  +    }
  +
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (!args.get(0).isString()) {
  +        JS_ReportError(cx, "Invalid arguments to evalInWorker");
  +        return false;
  +    }
  +
  +    if (!args[0].toString()->ensureLinear(cx))
  +        return false;
  +
  +    JSLinearString* str = &args[0].toString()->asLinear();
  +
  +    char16_t* chars = (char16_t*) js_malloc(str->length() * 
sizeof(char16_t));
  +    if (!chars)
  +        return false;
  +    CopyChars(chars, *str);
  +
  +    WorkerInput* input = js_new<WorkerInput>(cx->runtime(), chars, 
str->length());
  +    if (!input)
  +        return false;
  +
  +    PRThread* thread = PR_CreateThread(PR_USER_THREAD, WorkerMain, input,
  +                                       PR_PRIORITY_NORMAL, PR_GLOBAL_THREAD, 
PR_JOINABLE_THREAD,
  +                                       gMaxStackSize + 128 * 1024);
  +    if (!thread || !workerThreads.append(thread))
  +        return false;
  +
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +ShapeOf(JSContext* cx, unsigned argc, JS::Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (!args.get(0).isObject()) {
  +        JS_ReportError(cx, "shapeOf: object expected");
  +        return false;
  +    }
  +    JSObject* obj = &args[0].toObject();
  +    args.rval().set(JS_NumberValue(double(uintptr_t(obj->maybeShape()) >> 
3)));
  +    return true;
  +}
  +#endif
  +
  +/*
  + * Check that t1 comes strictly before t2. The function correctly deals with
  + * wrap-around between t2 and t1 assuming that t2 and t1 stays within 
INT32_MAX
  + * from each other. We use MAX_TIMEOUT_INTERVAL to enforce this restriction.
  + */
  +#ifdef       NOTYET
  +static bool
  +IsBefore(int64_t t1, int64_t t2)
  +{
  +    return int32_t(t1 - t2) < 0;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +Sleep_fn(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    int64_t t_ticks;
  +
  +    if (args.length() == 0) {
  +        t_ticks = 0;
  +    } else {
  +        double t_secs;
  +
  +        if (!ToNumber(cx, args[0], &t_secs))
  +            return false;
  +
  +        /* NB: The next condition also filter out NaNs. */
  +        if (!(t_secs <= MAX_TIMEOUT_INTERVAL)) {
  +            JS_ReportError(cx, "Excessive sleep interval");
  +            return false;
  +        }
  +        t_ticks = (t_secs <= 0.0)
  +                  ? 0
  +                  : int64_t(PRMJ_USEC_PER_SEC * t_secs);
  +    }
  +    PR_Lock(sr->watchdogLock);
  +#ifdef  FIXME
  +    int64_t to_wakeup = PRMJ_Now() + t_ticks;
  +#else
  +    struct timeval tv;
  +    gettimeofday(&tv, NULL);
  +    int64_t to_wakeup = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +    to_wakeup += t_ticks;
  +#endif
  +    for (;;) {
  +        PR_WaitCondVar(sr->sleepWakeup, PR_MillisecondsToInterval(t_ticks / 
1000));
  +        if (sr->serviceInterrupt)
  +            break;
  +#ifdef  FIXME
  +        int64_t now = PRMJ_Now();
  +#else
  +        struct timeval tv;
  +        gettimeofday(&tv, NULL);
  +        int64_t now = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +#endif
  +        if (!IsBefore(now, to_wakeup))
  +            break;
  +        t_ticks = to_wakeup - now;
  +    }
  +    PR_Unlock(sr->watchdogLock);
  +    args.rval().setUndefined();
  +    return !sr->serviceInterrupt;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +InitWatchdog(JSRuntime* rt)
  +{
  +    ShellRuntime* sr = GetShellRuntime(rt);
  +    MOZ_ASSERT(!sr->watchdogThread);
  +    sr->watchdogLock = PR_NewLock();
  +    if (sr->watchdogLock) {
  +        sr->watchdogWakeup = PR_NewCondVar(sr->watchdogLock);
  +        if (sr->watchdogWakeup) {
  +            sr->sleepWakeup = PR_NewCondVar(sr->watchdogLock);
  +            if (sr->sleepWakeup)
  +                return true;
  +            PR_DestroyCondVar(sr->watchdogWakeup);
  +        }
  +        PR_DestroyLock(sr->watchdogLock);
  +    }
  +    return false;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static void
  +KillWatchdog(JSRuntime* rt)
  +{
  +    ShellRuntime* sr = GetShellRuntime(rt);
  +    PRThread* thread;
  +
  +    PR_Lock(sr->watchdogLock);
  +    thread = sr->watchdogThread;
  +    if (thread) {
  +        /*
  +         * The watchdog thread is running, tell it to terminate waking it up
  +         * if necessary.
  +         */
  +        sr->watchdogThread = nullptr;
  +        PR_NotifyCondVar(sr->watchdogWakeup);
  +    }
  +    PR_Unlock(sr->watchdogLock);
  +    if (thread)
  +        PR_JoinThread(thread);
  +    PR_DestroyCondVar(sr->sleepWakeup);
  +    PR_DestroyCondVar(sr->watchdogWakeup);
  +    PR_DestroyLock(sr->watchdogLock);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static void
  +WatchdogMain(void* arg)
  +{
  +    PR_SetCurrentThreadName("JS Watchdog");
  +
  +    JSRuntime* rt = (JSRuntime*) arg;
  +    ShellRuntime* sr = GetShellRuntime(rt);
  +
  +    PR_Lock(sr->watchdogLock);
  +    while (sr->watchdogThread) {
  +#ifdef  FIXME
  +        int64_t now = PRMJ_Now();
  +#else
  +        struct timeval tv;
  +        gettimeofday(&tv, NULL);
  +        int64_t now = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +#endif
  +        if (sr->watchdogHasTimeout && !IsBefore(now, sr->watchdogTimeout)) {
  +            /*
  +             * The timeout has just expired. Request an interrupt callback
  +             * outside the lock.
  +             */
  +            sr->watchdogHasTimeout = false;
  +            PR_Unlock(sr->watchdogLock);
  +            CancelExecution(rt);
  +            PR_Lock(sr->watchdogLock);
  +
  +            /* Wake up any threads doing sleep. */
  +            PR_NotifyAllCondVar(sr->sleepWakeup);
  +        } else {
  +            if (sr->watchdogHasTimeout) {
  +                /*
  +                 * Time hasn't expired yet. Simulate an interrupt callback
  +                 * which doesn't abort execution.
  +                 */
  +                JS_RequestInterruptCallback(rt);
  +            }
  +
  +            uint64_t sleepDuration = PR_INTERVAL_NO_TIMEOUT;
  +            if (sr->watchdogHasTimeout)
  +                sleepDuration = PR_TicksPerSecond() / 10;
  +            mozilla::DebugOnly<PRStatus> status =
  +              PR_WaitCondVar(sr->watchdogWakeup, sleepDuration);
  +            MOZ_ASSERT(status == PR_SUCCESS);
  +        }
  +    }
  +    PR_Unlock(sr->watchdogLock);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +ScheduleWatchdog(JSRuntime* rt, double t)
  +{
  +    ShellRuntime* sr = GetShellRuntime(rt);
  +
  +    if (t <= 0) {
  +        PR_Lock(sr->watchdogLock);
  +        sr->watchdogHasTimeout = false;
  +        PR_Unlock(sr->watchdogLock);
  +        return true;
  +    }
  +
  +    int64_t interval = int64_t(ceil(t * PRMJ_USEC_PER_SEC));
  +#ifdef  FIXME
  +    int64_t timeout = PRMJ_Now() + interval;
  +#else
  +    struct timeval tv;
  +    gettimeofday(&tv, NULL);
  +    int64_t timeout = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +    timeout += interval;
  +#endif
  +    PR_Lock(sr->watchdogLock);
  +    if (!sr->watchdogThread) {
  +        MOZ_ASSERT(!sr->watchdogHasTimeout);
  +        sr->watchdogThread = PR_CreateThread(PR_USER_THREAD,
  +                                          WatchdogMain,
  +                                          rt,
  +                                          PR_PRIORITY_NORMAL,
  +                                          PR_GLOBAL_THREAD,
  +                                          PR_JOINABLE_THREAD,
  +                                          0);
  +        if (!sr->watchdogThread) {
  +            PR_Unlock(sr->watchdogLock);
  +            return false;
  +        }
  +    } else if (!sr->watchdogHasTimeout || IsBefore(timeout, 
sr->watchdogTimeout)) {
  +         PR_NotifyCondVar(sr->watchdogWakeup);
  +    }
  +    sr->watchdogHasTimeout = true;
  +    sr->watchdogTimeout = timeout;
  +    PR_Unlock(sr->watchdogLock);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static void
  +CancelExecution(JSRuntime* rt)
  +{
  +    ShellRuntime* sr = GetShellRuntime(rt);
  +    sr->serviceInterrupt = true;
  +    JS_RequestInterruptCallback(rt);
  +
  +    if (!sr->interruptFunc.isNull()) {
  +        static const char msg[] = "Script runs for too long, terminating.\n";
  +        fputs(msg, stderr);
  +    }
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +SetTimeoutValue(JSContext* cx, double t)
  +{
  +    /* NB: The next condition also filter out NaNs. */
  +    if (!(t <= MAX_TIMEOUT_INTERVAL)) {
  +        JS_ReportError(cx, "Excessive timeout value");
  +        return false;
  +    }
  +    GetShellRuntime(cx)->timeoutInterval = t;
  +    if (!ScheduleWatchdog(cx->runtime(), t)) {
  +        JS_ReportError(cx, "Failed to create the watchdog");
  +        return false;
  +    }
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +Timeout(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() == 0) {
  +        args.rval().setNumber(sr->timeoutInterval);
  +        return true;
  +    }
  +
  +    if (args.length() > 2) {
  +        JS_ReportError(cx, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    double t;
  +    if (!ToNumber(cx, args[0], &t))
  +        return false;
  +
  +    if (args.length() > 1) {
  +        RootedValue value(cx, args[1]);
  +        if (!value.isObject() || !value.toObject().is<JSFunction>()) {
  +            JS_ReportError(cx, "Second argument must be a timeout function");
  +            return false;
  +        }
  +        sr->interruptFunc = value;
  +    }
  +
  +    args.rval().setUndefined();
  +    return SetTimeoutValue(cx, t);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +InterruptIf(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() != 1) {
  +        JS_ReportError(cx, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    if (ToBoolean(args[0])) {
  +        GetShellRuntime(cx)->serviceInterrupt = true;
  +        JS_RequestInterruptCallback(cx->runtime());
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +InvokeInterruptCallbackWrapper(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() != 1) {
  +        JS_ReportError(cx, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    GetShellRuntime(cx)->serviceInterrupt = true;
  +    JS_RequestInterruptCallback(cx->runtime());
  +    bool interruptRv = CheckForInterrupt(cx);
  +
  +    // The interrupt handler could have set a pending exception. Since we 
call
  +    // back into JS, don't have it see the pending exception. If we have an
  +    // uncatchable exception that's not propagating a debug mode forced
  +    // return, return.
  +    if (!interruptRv && !cx->isExceptionPending() && 
!cx->isPropagatingForcedReturn())
  +        return false;
  +
  +    JS::AutoSaveExceptionState savedExc(cx);
  +    Value argv[1] = { BooleanValue(interruptRv) };
  +    RootedValue rv(cx);
  +    if (!Invoke(cx, UndefinedValue(), args[0], 1, argv, &rv))
  +        return false;
  +
  +    args.rval().setUndefined();
  +    return interruptRv;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +SetInterruptCallback(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() != 1) {
  +        JS_ReportError(cx, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    RootedValue value(cx, args[0]);
  +    if (!value.isObject() || !value.toObject().is<JSFunction>()) {
  +        JS_ReportError(cx, "Argument must be a function");
  +        return false;
  +    }
  +    GetShellRuntime(cx)->interruptFunc = value;
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +EnableLastWarning(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    sr->lastWarningEnabled = true;
  +    sr->lastWarning.setNull();
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +DisableLastWarning(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    sr->lastWarningEnabled = false;
  +    sr->lastWarning.setNull();
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +GetLastWarning(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (!sr->lastWarningEnabled) {
  +        JS_ReportError(cx, "Call enableLastWarning first.");
  +        return false;
  +    }
  +
  +    if (!JS_WrapValue(cx, &sr->lastWarning))
  +        return false;
  +
  +    args.rval().set(sr->lastWarning);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +ClearLastWarning(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    ShellRuntime* sr = GetShellRuntime(cx);
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (!sr->lastWarningEnabled) {
  +        JS_ReportError(cx, "Call enableLastWarning first.");
  +        return false;
  +    }
  +
  +    sr->lastWarning.setNull();
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef DEBUG
  +static bool
  +StackDump(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    bool showArgs = ToBoolean(args.get(0));
  +    bool showLocals = ToBoolean(args.get(1));
  +    bool showThisProps = ToBoolean(args.get(2));
  +
  +    char* buf = JS::FormatStackDump(cx, nullptr, showArgs, showLocals, 
showThisProps);
  +    if (!buf) {
  +        fputs("Failed to format JavaScript stack for dump\n", gOutFile);
  +    } else {
  +        fputs(buf, gOutFile);
  +        JS_smprintf_free(buf);
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +StackPointerInfo(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    // Copy the truncated stack pointer to the result.  This value is not 
used
  +    // as a pointer but as a way to measure frame-size from JS.
  +    args.rval().setInt32(int32_t(reinterpret_cast<size_t>(&args) & 
0xfffffff));
  +    return true;
  +}
  +#endif
  +
  +
  +#ifdef       NOTYET
  +static bool
  +Elapsed(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() == 0) {
  +        double d = 0.0;
  +        JSShellContextData* data = GetContextData(cx);
  +        if (data) {
  +#ifdef  FIXME
  +            d = PRMJ_Now() - data->startTime;
  +#else
  +            struct timeval tv;
  +            gettimeofday(&tv, NULL);
  +            d = 1000 * 1000 * tv.tv_sec + tv.tv_usec;
  +            d -= data->startTime;
  +#endif
  +        }
  +        args.rval().setDouble(d);
  +        return true;
  +    }
  +    JS_ReportError(cx, "Wrong number of arguments");
  +    return false;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +Compile(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() < 1) {
  +        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, 
JSMSG_MORE_ARGS_NEEDED,
  +                             "compile", "0", "s");
  +        return false;
  +    }
  +    if (!args[0].isString()) {
  +        const char* typeName = InformalValueTypeName(args[0]);
  +        JS_ReportError(cx, "expected string to compile, got %s", typeName);
  +        return false;
  +    }
  +
  +    RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
  +    JSFlatString* scriptContents = args[0].toString()->ensureFlat(cx);
  +    if (!scriptContents)
  +        return false;
  +
  +    AutoStableStringChars stableChars(cx);
  +    if (!stableChars.initTwoByte(cx, scriptContents))
  +        return false;
  +
  +    JS::CompileOptions options(cx);
  +    options.setIntroductionType("js shell compile")
  +           .setFileAndLine("<string>", 1)
  +           .setIsRunOnce(true)
  +           .setNoScriptRval(true);
  +    RootedScript script(cx);
  +    const char16_t* chars = stableChars.twoByteRange().start().get();
  +    bool ok = JS_CompileUCScript(cx, chars, scriptContents->length(), 
options, &script);
  +    args.rval().setUndefined();
  +    return ok;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +ParseModule(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() == 0) {
  +        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
  +                             JSMSG_MORE_ARGS_NEEDED, "parseModule", "0", 
"s");
  +        return false;
  +    }
  +
  +    if (!args[0].isString()) {
  +        const char* typeName = InformalValueTypeName(args[0]);
  +        JS_ReportError(cx, "expected string to compile, got %s", typeName);
  +        return false;
  +    }
  +
  +    RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
  +    JSFlatString* scriptContents = args[0].toString()->ensureFlat(cx);
  +    if (!scriptContents)
  +        return false;
  +
  +    mozilla::UniquePtr<char, JS::FreePolicy> filename;
  +    CompileOptions options(cx);
  +    if (args.length() > 1) {
  +        if (!args[1].isString()) {
  +            const char* typeName = InformalValueTypeName(args[1]);
  +            JS_ReportError(cx, "expected filename string, got %s", typeName);
  +            return false;
  +        }
  +
  +        RootedString str(cx, args[1].toString());
  +        filename.reset(JS_EncodeString(cx, str));
  +        if (!filename)
  +            return false;
  +
  +        options.setFileAndLine(filename.get(), 1);
  +    } else {
  +        options.setFileAndLine("<string>", 1);
  +    }
  +
  +    AutoStableStringChars stableChars(cx);
  +    if (!stableChars.initTwoByte(cx, scriptContents))
  +        return false;
  +
  +    const char16_t* chars = stableChars.twoByteRange().start().get();
  +    SourceBufferHolder srcBuf(chars, scriptContents->length(),
  +                              SourceBufferHolder::NoOwnership);
  +
  +    RootedObject module(cx, frontend::CompileModule(cx, global, options, 
srcBuf));
  +    if (!module)
  +        return false;
  +
  +    args.rval().setObject(*module);
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +SetModuleResolveHook(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() != 1) {
  +        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr,
  +                             JSMSG_MORE_ARGS_NEEDED, "setModuleResolveHook", 
"0", "s");
  +        return false;
  +    }
  +
  +    if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
  +        const char* typeName = InformalValueTypeName(args[0]);
  +        JS_ReportError(cx, "expected hook function, got %s", typeName);
  +        return false;
  +    }
  +
  +    RootedFunction hook(cx, &args[0].toObject().as<JSFunction>());
  +    Rooted<GlobalObject*> global(cx, cx->global());
  +    global->setModuleResolveHook(hook);
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +GetModuleLoadPath(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    args.rval().setString(JS_NewStringCopyZ(cx, moduleLoadPath));
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +Parse(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    using namespace js::frontend;
  +
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() < 1) {
  +        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, 
JSMSG_MORE_ARGS_NEEDED,
  +                             "parse", "0", "s");
  +        return false;
  +    }
  +    if (!args[0].isString()) {
  +        const char* typeName = InformalValueTypeName(args[0]);
  +        JS_ReportError(cx, "expected string to parse, got %s", typeName);
  +        return false;
  +    }
  +
  +    JSFlatString* scriptContents = args[0].toString()->ensureFlat(cx);
  +    if (!scriptContents)
  +        return false;
  +
  +    AutoStableStringChars stableChars(cx);
  +    if (!stableChars.initTwoByte(cx, scriptContents))
  +        return false;
  +
  +    size_t length = scriptContents->length();
  +    const char16_t* chars = stableChars.twoByteRange().start().get();
  +
  +    CompileOptions options(cx);
  +    options.setIntroductionType("js shell parse")
  +           .setFileAndLine("<string>", 1);
  +    Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, 
chars, length,
  +                                    /* foldConstants = */ true, nullptr, 
nullptr);
  +    if (!parser.checkOptions())
  +        return false;
  +
  +    ParseNode* pn = parser.parse();
  +    if (!pn)
  +        return false;
  +#ifdef DEBUG
  +    DumpParseTree(pn);
  +    fputc('\n', stderr);
  +#endif
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +SyntaxParse(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    using namespace js::frontend;
  +
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() < 1) {
  +        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, 
JSMSG_MORE_ARGS_NEEDED,
  +                             "parse", "0", "s");
  +        return false;
  +    }
  +    if (!args[0].isString()) {
  +        const char* typeName = InformalValueTypeName(args[0]);
  +        JS_ReportError(cx, "expected string to parse, got %s", typeName);
  +        return false;
  +    }
  +
  +    JSFlatString* scriptContents = args[0].toString()->ensureFlat(cx);
  +    if (!scriptContents)
  +        return false;
  +    CompileOptions options(cx);
  +    options.setIntroductionType("js shell syntaxParse")
  +           .setFileAndLine("<string>", 1);
  +
  +    AutoStableStringChars stableChars(cx);
  +    if (!stableChars.initTwoByte(cx, scriptContents))
  +        return false;
  +
  +    const char16_t* chars = stableChars.twoByteRange().start().get();
  +    size_t length = scriptContents->length();
  +    Parser<frontend::SyntaxParseHandler> parser(cx, &cx->tempLifoAlloc(),
  +                                                options, chars, length, 
false, nullptr, nullptr);
  +    if (!parser.checkOptions())
  +        return false;
  +
  +    bool succeeded = parser.parse();
  +    if (cx->isExceptionPending())
  +        return false;
  +
  +    if (!succeeded && !parser.hadAbortedSyntaxParse()) {
  +        // If no exception is posted, either there was an OOM or a language
  +        // feature unhandled by the syntax parser was encountered.
  +        MOZ_ASSERT(cx->runtime()->hadOutOfMemory);
  +        return false;
  +    }
  +
  +    args.rval().setBoolean(succeeded);
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +class OffThreadState {
  +  public:
  +    enum State {
  +        IDLE,           /* ready to work; no token, no source */
  +        COMPILING,      /* working; no token, have source */
  +        DONE            /* compilation done: have token and source */
  +    };
  +
  +    OffThreadState() : monitor(), state(IDLE), token(), source(nullptr) { }
  +    bool init() { return monitor.init(); }
  +
  +    bool startIfIdle(JSContext* cx, ScopedJSFreePtr<char16_t>& newSource) {
  +        AutoLockMonitor alm(monitor);
  +        if (state != IDLE)
  +            return false;
  +
  +        MOZ_ASSERT(!token);
  +
  +        source = newSource.forget();
  +
  +        state = COMPILING;
  +        return true;
  +    }
  +
  +    void abandon(JSContext* cx) {
  +        AutoLockMonitor alm(monitor);
  +        MOZ_ASSERT(state == COMPILING);
  +        MOZ_ASSERT(!token);
  +        MOZ_ASSERT(source);
  +
  +        js_free(source);
  +        source = nullptr;
  +
  +        state = IDLE;
  +    }
  +
  +    void markDone(void* newToken) {
  +        AutoLockMonitor alm(monitor);
  +        MOZ_ASSERT(state == COMPILING);
  +        MOZ_ASSERT(!token);
  +        MOZ_ASSERT(source);
  +        MOZ_ASSERT(newToken);
  +
  +        token = newToken;
  +        state = DONE;
  +        alm.notify();
  +    }
  +
  +    void* waitUntilDone(JSContext* cx) {
  +        AutoLockMonitor alm(monitor);
  +        if (state == IDLE)
  +            return nullptr;
  +
  +        if (state == COMPILING) {
  +            while (state != DONE)
  +                alm.wait();
  +        }
  +
  +        MOZ_ASSERT(source);
  +        js_free(source);
  +        source = nullptr;
  +
  +        MOZ_ASSERT(token);
  +        void* holdToken = token;
  +        token = nullptr;
  +        state = IDLE;
  +        return holdToken;
  +    }
  +
  +  private:
  +    Monitor monitor;
  +    State state;
  +    void* token;
  +    char16_t* source;
  +};
  +#endif
  +
  +#ifdef  NOTYET
  +static OffThreadState offThreadState;
  +#endif
  +
  +#ifdef  NOTYET
  +static void
  +OffThreadCompileScriptCallback(void* token, void* callbackData)
  +{
  +    offThreadState.markDone(token);
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +OffThreadCompileScript(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    if (!CanUseExtraThreads()) {
  +        JS_ReportError(cx, "Can't use offThreadCompileScript with 
--no-threads");
  +        return false;
  +    }
  +
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() < 1) {
  +        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, 
JSMSG_MORE_ARGS_NEEDED,
  +                             "offThreadCompileScript", "0", "s");
  +        return false;
  +    }
  +    if (!args[0].isString()) {
  +        const char* typeName = InformalValueTypeName(args[0]);
  +        JS_ReportError(cx, "expected string to parse, got %s", typeName);
  +        return false;
  +    }
  +
  +    JSAutoByteString fileNameBytes;
  +    CompileOptions options(cx);
  +    options.setIntroductionType("js shell offThreadCompileScript")
  +           .setFileAndLine("<string>", 1);
  +
  +    if (args.length() >= 2) {
  +        if (args[1].isPrimitive()) {
  +            JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_INVALID_ARGS, "evaluate");
  +            return false;
  +        }
  +
  +        RootedObject opts(cx, &args[1].toObject());
  +        if (!ParseCompileOptions(cx, options, opts, fileNameBytes))
  +            return false;
  +    }
  +
  +    // These option settings must override whatever the caller requested.
  +    options.setIsRunOnce(true)
  +           .setSourceIsLazy(false);
  +
  +    // We assume the caller wants caching if at all possible, ignoring
  +    // heuristics that make sense for a real browser.
  +    options.forceAsync = true;
  +
  +    JSString* scriptContents = args[0].toString();
  +    AutoStableStringChars stableChars(cx);
  +    if (!stableChars.initTwoByte(cx, scriptContents))
  +        return false;
  +
  +    size_t length = scriptContents->length();
  +    const char16_t* chars = stableChars.twoByteRange().start().get();
  +
  +    // Make sure we own the string's chars, so that they are not freed before
  +    // the compilation is finished.
  +    ScopedJSFreePtr<char16_t> ownedChars;
  +    if (stableChars.maybeGiveOwnershipToCaller()) {
  +        ownedChars = const_cast<char16_t*>(chars);
  +    } else {
  +        char16_t* copy = cx->pod_malloc<char16_t>(length);
  +        if (!copy)
  +            return false;
  +
  +        mozilla::PodCopy(copy, chars, length);
  +        ownedChars = copy;
  +        chars = copy;
  +    }
  +
  +    if (!JS::CanCompileOffThread(cx, options, length)) {
  +        JS_ReportError(cx, "cannot compile code on worker thread");
  +        return false;
  +    }
  +
  +    if (!offThreadState.startIfIdle(cx, ownedChars)) {
  +        JS_ReportError(cx, "called offThreadCompileScript without calling 
runOffThreadScript"
  +                       " to receive prior off-thread compilation");
  +        return false;
  +    }
  +
  +    if (!JS::CompileOffThread(cx, options, chars, length,
  +                              OffThreadCompileScriptCallback, nullptr))
  +    {
  +        offThreadState.abandon(cx);
  +        return false;
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +runOffThreadScript(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    JSRuntime* rt = cx->runtime();
  +    if (OffThreadParsingMustWaitForGC(rt))
  +        gc::AutoFinishGC finishgc(rt);
  +
  +    void* token = offThreadState.waitUntilDone(cx);
  +    if (!token) {
  +        JS_ReportError(cx, "called runOffThreadScript when no compilation is 
pending");
  +        return false;
  +    }
  +
  +    RootedScript script(cx, JS::FinishOffThreadScript(cx, rt, token));
  +    if (!script)
  +        return false;
  +
  +    return JS_ExecuteScript(cx, script, args.rval());
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +struct MOZ_RAII FreeOnReturn
  +{
  +    JSContext* cx;
  +    const char* ptr;
  +    MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
  +
  +    explicit FreeOnReturn(JSContext* cx, const char* ptr = nullptr
  +                 MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
  +      : cx(cx), ptr(ptr)
  +    {
  +        MOZ_GUARD_OBJECT_NOTIFIER_INIT;
  +    }
  +
  +    void init(const char* ptr) {
  +        MOZ_ASSERT(!this->ptr);
  +        this->ptr = ptr;
  +    }
  +
  +    ~FreeOnReturn() {
  +        JS_free(cx, (void*)ptr);
  +    }
  +};
  +#endif
  +
  +static int sArgc;
  +static char** sArgv;
  +
  +#ifdef       NOTYET
  +class AutoCStringVector
  +{
  +    Vector<char*> argv_;
  +  public:
  +    explicit AutoCStringVector(JSContext* cx) : argv_(cx) {}
  +    ~AutoCStringVector() {
  +        for (size_t i = 0; i < argv_.length(); i++)
  +            js_free(argv_[i]);
  +    }
  +    bool append(char* arg) {
  +        if (!argv_.append(arg)) {
  +            js_free(arg);
  +            return false;
  +        }
  +        return true;
  +    }
  +    char* const* get() const {
  +        return argv_.begin();
  +    }
  +    size_t length() const {
  +        return argv_.length();
  +    }
  +    char* operator[](size_t i) const {
  +        return argv_[i];
  +    }
  +    void replace(size_t i, char* arg) {
  +        js_free(argv_[i]);
  +        argv_[i] = arg;
  +    }
  +    char* back() const {
  +        return argv_.back();
  +    }
  +    void replaceBack(char* arg) {
  +        js_free(argv_.back());
  +        argv_.back() = arg;
  +    }
  +};
  +#endif
  +
  +#if defined(XP_WIN)
  +static bool
  +EscapeForShell(AutoCStringVector& argv)
  +{
  +    // Windows will break arguments in argv by various spaces, so we wrap 
each
  +    // argument in quotes and escape quotes within. Even with quotes, \ will 
be
  +    // treated like an escape character, so inflate each \ to \\.
  +
  +    for (size_t i = 0; i < argv.length(); i++) {
  +        if (!argv[i])
  +            continue;
  +
  +        size_t newLen = 3;  // quotes before and after and null-terminator
  +        for (char* p = argv[i]; *p; p++) {
  +            newLen++;
  +            if (*p == '\"' || *p == '\\')
  +                newLen++;
  +        }
  +
  +        char* escaped = (char*)js_malloc(newLen);
  +        if (!escaped)
  +            return false;
  +
  +        char* src = argv[i];
  +        char* dst = escaped;
  +        *dst++ = '\"';
  +        while (*src) {
  +            if (*src == '\"' || *src == '\\')
  +                *dst++ = '\\';
  +            *dst++ = *src++;
  +        }
  +        *dst++ = '\"';
  +        *dst++ = '\0';
  +        MOZ_ASSERT(escaped + newLen == dst);
  +
  +        argv.replace(i, escaped);
  +    }
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static Vector<const char*, 4, js::SystemAllocPolicy> sPropagatedFlags;
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +PropagateFlagToNestedShells(const char* flag)
  +{
  +    return sPropagatedFlags.append(flag);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +NestedShell(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    AutoCStringVector argv(cx);
  +
  +    // The first argument to the shell is its path, which we assume is our 
own
  +    // argv[0].
  +    if (sArgc < 1) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_NESTED_FAIL);
  +        return false;
  +    }
  +    if (!argv.append(strdup(sArgv[0])))
  +        return false;
  +
  +    // Propagate selected flags from the current shell
  +    for (unsigned i = 0; i < sPropagatedFlags.length(); i++) {
  +        char* cstr = strdup(sPropagatedFlags[i]);
  +        if (!cstr || !argv.append(cstr))
  +            return false;
  +    }
  +
  +    // The arguments to nestedShell are stringified and append to argv.
  +    RootedString str(cx);
  +    for (unsigned i = 0; i < args.length(); i++) {
  +        str = ToString(cx, args[i]);
  +        if (!str || !argv.append(JS_EncodeString(cx, str)))
  +            return false;
  +
  +        // As a special case, if the caller passes "--js-cache", replace that
  +        // with "--js-cache=$(jsCacheDir)"
  +        if (!strcmp(argv.back(), "--js-cache") && jsCacheDir) {
  +            char* newArg = JS_smprintf("--js-cache=%s", jsCacheDir);
  +            if (!newArg)
  +                return false;
  +            argv.replaceBack(newArg);
  +        }
  +    }
  +
  +    // execv assumes argv is null-terminated
  +    if (!argv.append(nullptr))
  +        return false;
  +
  +    int status = 0;
  +#if defined(XP_WIN)
  +    if (!EscapeForShell(argv))
  +        return false;
  +    status = _spawnv(_P_WAIT, sArgv[0], argv.get());
  +#else
  +    pid_t pid = fork();
  +    switch (pid) {
  +      case -1:
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_NESTED_FAIL);
  +        return false;
  +      case 0:
  +        (void)execv(sArgv[0], argv.get());
  +        exit(-1);
  +      default: {
  +        while (waitpid(pid, &status, 0) < 0 && errno == EINTR)
  +            continue;
  +        break;
  +      }
  +    }
  +#endif
  +
  +    if (status != 0) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_NESTED_FAIL);
  +        return false;
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +DecompileFunction(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() < 1 || !args[0].isObject() || 
!args[0].toObject().is<JSFunction>()) {
  +        args.rval().setUndefined();
  +        return true;
  +    }
  +    RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
  +    JSString* result = JS_DecompileFunction(cx, fun, 0);
  +    if (!result)
  +        return false;
  +    args.rval().setString(result);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +DecompileThisScript(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    NonBuiltinScriptFrameIter iter(cx);
  +    if (iter.done()) {
  +        args.rval().setString(cx->runtime()->emptyString);
  +        return true;
  +    }
  +
  +    {
  +        JSAutoCompartment ac(cx, iter.script());
  +
  +        RootedScript script(cx, iter.script());
  +        JSString* result = JS_DecompileScript(cx, script, "test", 0);
  +        if (!result)
  +            return false;
  +
  +        args.rval().setString(result);
  +    }
  +
  +    return JS_WrapValue(cx, args.rval());
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +ThisFilename(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    JS::AutoFilename filename;
  +    if (!DescribeScriptedCaller(cx, &filename) || !filename.get()) {
  +        args.rval().setString(cx->runtime()->emptyString);
  +        return true;
  +    }
  +
  +    JSString* str = JS_NewStringCopyZ(cx, filename.get());
  +    if (!str)
  +        return false;
  +
  +    args.rval().setString(str);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +WrapWithProto(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    Value obj = UndefinedValue(), proto = UndefinedValue();
  +    if (args.length() == 2) {
  +        obj = args[0];
  +        proto = args[1];
  +    }
  +    if (!obj.isObject() || !proto.isObjectOrNull()) {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_INVALID_ARGS,
  +                             "wrapWithProto");
  +        return false;
  +    }
  +
  +    WrapperOptions options(cx);
  +    options.setProto(proto.toObjectOrNull());
  +    JSObject* wrapped = Wrapper::New(cx, &obj.toObject(),
  +                                     &Wrapper::singletonWithPrototype, 
options);
  +    if (!wrapped)
  +        return false;
  +
  +    args.rval().setObject(*wrapped);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +NewGlobal(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    JSPrincipals* principals = nullptr;
  +    JS::CompartmentOptions options;
  +    options.setVersion(JSVERSION_DEFAULT);
  +
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (args.length() == 1 && args[0].isObject()) {
  +        RootedObject opts(cx, &args[0].toObject());
  +        RootedValue v(cx);
  +
  +        if (!JS_GetProperty(cx, opts, "sameZoneAs", &v))
  +            return false;
  +        if (v.isObject())
  +            options.setSameZoneAs(UncheckedUnwrap(&v.toObject()));
  +
  +        if (!JS_GetProperty(cx, opts, "invisibleToDebugger", &v))
  +            return false;
  +        if (v.isBoolean())
  +            options.setInvisibleToDebugger(v.toBoolean());
  +
  +        if (!JS_GetProperty(cx, opts, "cloneSingletons", &v))
  +            return false;
  +        if (v.isBoolean())
  +            options.setCloneSingletons(v.toBoolean());
  +
  +        if (!JS_GetProperty(cx, opts, "disableLazyParsing", &v))
  +            return false;
  +        if (v.isBoolean())
  +            options.setDisableLazyParsing(v.toBoolean());
  +
  +        if (!JS_GetProperty(cx, opts, "principal", &v))
  +            return false;
  +        if (!v.isUndefined()) {
  +            uint32_t bits;
  +            if (!ToUint32(cx, v, &bits))
  +                return false;
  +            principals = cx->new_<ShellPrincipals>(bits);
  +            if (!principals)
  +                return false;
  +            JS_HoldPrincipals(principals);
  +        }
  +    }
  +
  +    RootedObject global(cx, NewGlobalObject(cx, options, principals));
  +    if (principals)
  +        JS_DropPrincipals(cx->runtime(), principals);
  +    if (!global)
  +        return false;
  +
  +    if (!JS_WrapObject(cx, &global))
  +        return false;
  +
  +    args.rval().setObject(*global);
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +NukeCCW(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    if (args.length() != 1 || !args[0].isObject() ||
  +        !IsCrossCompartmentWrapper(&args[0].toObject()))
  +    {
  +        JS_ReportErrorNumber(cx, my_GetErrorMessage, nullptr, 
JSSMSG_INVALID_ARGS,
  +                             "nukeCCW");
  +        return false;
  +    }
  +
  +    NukeCrossCompartmentWrapper(cx, &args[0].toObject());
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +GetMaxArgs(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    args.rval().setInt32(ARGS_LENGTH_MAX);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +ObjectEmulatingUndefined(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    static const JSClass cls = {
  +        "ObjectEmulatingUndefined",
  +        JSCLASS_EMULATES_UNDEFINED
  +    };
  +
  +    RootedObject obj(cx, JS_NewObject(cx, &cls));
  +    if (!obj)
  +        return false;
  +    args.rval().setObject(*obj);
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +GetSelfHostedValue(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,
  +                             "getSelfHostedValue");
  +        return false;
  +    }
  +    RootedAtom srcAtom(cx, ToAtom<CanGC>(cx, args[0]));
  +    if (!srcAtom)
  +        return false;
  +    RootedPropertyName srcName(cx, srcAtom->asPropertyName());
  +    return cx->runtime()->cloneSelfHostedValue(cx, srcName, args.rval());
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +class ShellSourceHook: public SourceHook {
  +    // The function we should call to lazily retrieve source code.
  +    PersistentRootedFunction fun;
  +
  +  public:
  +    ShellSourceHook(JSContext* cx, JSFunction& fun) : fun(cx, &fun) {}
  +
  +    bool load(JSContext* cx, const char* filename, char16_t** src, size_t* 
length) {
  +        RootedString str(cx, JS_NewStringCopyZ(cx, filename));
  +        if (!str)
  +            return false;
  +        RootedValue filenameValue(cx, StringValue(str));
  +
  +        RootedValue result(cx);
  +        if (!Call(cx, UndefinedHandleValue, fun, 
HandleValueArray(filenameValue), &result))
  +            return false;
  +
  +        str = JS::ToString(cx, result);
  +        if (!str)
  +            return false;
  +
  +        *length = JS_GetStringLength(str);
  +        *src = cx->pod_malloc<char16_t>(*length);
  +        if (!*src)
  +            return false;
  +
  +        JSLinearString* linear = str->ensureLinear(cx);
  +        if (!linear)
  +            return false;
  +
  +        CopyChars(*src, *linear);
  +        return true;
  +    }
  +};
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +WithSourceHook(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedObject callee(cx, &args.callee());
  +
  +    if (args.length() != 2) {
  +        ReportUsageError(cx, callee, "Wrong number of arguments.");
  +        return false;
  +    }
  +
  +    if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()
  +        || !args[1].isObject() || !args[1].toObject().is<JSFunction>()) {
  +        ReportUsageError(cx, callee, "First and second arguments must be 
functions.");
  +        return false;
  +    }
  +
  +    UniquePtr<ShellSourceHook> hook =
  +        MakeUnique<ShellSourceHook>(cx, args[0].toObject().as<JSFunction>());
  +    if (!hook)
  +        return false;
  +
  +    UniquePtr<SourceHook> savedHook = js::ForgetSourceHook(cx->runtime());
  +    js::SetSourceHook(cx->runtime(), Move(hook));
  +
  +    RootedObject fun(cx, &args[1].toObject());
  +    bool result = Call(cx, UndefinedHandleValue, fun, 
JS::HandleValueArray::empty(), args.rval());
  +    js::SetSourceHook(cx->runtime(), Move(savedHook));
  +    return result;
  +}
  +#endif
  +
  +static bool
  +IsCachingEnabled(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    args.rval().setBoolean(jsCachingEnabled && jsCacheAsmJSPath != nullptr);
  +    return true;
  +}
  +
  +#ifdef       NOTYET
  +static bool
  +SetCachingEnabled(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (GetShellRuntime(cx)->isWorker) {
  +        JS_ReportError(cx, "Caching is not supported in workers");
  +        return false;
  +    }
  +
  +    jsCachingEnabled = ToBoolean(args.get(0));
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static void
  +PrintProfilerEvents_Callback(const char* msg)
  +{
  +    fprintf(stderr, "PROFILER EVENT: %s\n", msg);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +PrintProfilerEvents(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    if (cx->runtime()->spsProfiler.enabled())
  +        js::RegisterRuntimeProfilingEventMarker(cx->runtime(), 
&PrintProfilerEvents_Callback);
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
  +typedef Vector<char16_t, 0, SystemAllocPolicy> StackChars;
  +Vector<StackChars, 0, SystemAllocPolicy> stacks;
  +
  +static void
  +SingleStepCallback(void* arg, jit::Simulator* sim, void* pc)
  +{
  +    JSRuntime* rt = reinterpret_cast<JSRuntime*>(arg);
  +
  +    // If profiling is not enabled, don't do anything.
  +    if (!rt->spsProfiler.enabled())
  +        return;
  +
  +    JS::ProfilingFrameIterator::RegisterState state;
  +    state.pc = pc;
  +#if defined(JS_SIMULATOR_ARM)
  +    state.sp = (void*)sim->get_register(jit::Simulator::sp);
  +    state.lr = (void*)sim->get_register(jit::Simulator::lr);
  +#elif defined(JS_SIMULATOR_MIPS64)
  +    state.sp = (void*)sim->getRegister(jit::Simulator::sp);
  +    state.lr = (void*)sim->getRegister(jit::Simulator::ra);
  +#endif
  +
  +    mozilla::DebugOnly<void*> lastStackAddress = nullptr;
  +    StackChars stack;
  +    uint32_t frameNo = 0;
  +    for (JS::ProfilingFrameIterator i(rt, state); !i.done(); ++i) {
  +        MOZ_ASSERT(i.stackAddress() != nullptr);
  +        MOZ_ASSERT(lastStackAddress <= i.stackAddress());
  +        lastStackAddress = i.stackAddress();
  +        JS::ProfilingFrameIterator::Frame frames[16];
  +        uint32_t nframes = i.extractStack(frames, 0, 16);
  +        for (uint32_t i = 0; i < nframes; i++) {
  +            if (frameNo > 0)
  +                stack.append(",", 1);
  +            stack.append(frames[i].label, strlen(frames[i].label));
  +            frameNo++;
  +        }
  +    }
  +
  +    // Only append the stack if it differs from the last stack.
  +    if (stacks.empty() ||
  +        stacks.back().length() != stack.length() ||
  +        !PodEqual(stacks.back().begin(), stack.begin(), stack.length()))
  +    {
  +        stacks.append(Move(stack));
  +    }
  +}
  +#endif
  +#endif       /* NOTYET */
  +
  +#ifdef       NOTYET
  +static bool
  +EnableSingleStepProfiling(JSContext* cx, unsigned argc, Value* vp)
  +{
  +#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    jit::Simulator* sim = cx->runtime()->simulator();
  +    sim->enable_single_stepping(SingleStepCallback, cx->runtime());
  +
  +    args.rval().setUndefined();
  +    return true;
  +#else
  +    JS_ReportError(cx, "single-step profiling not enabled on this platform");
  +    return false;
  +#endif
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +DisableSingleStepProfiling(JSContext* cx, unsigned argc, Value* vp)
  +{
  +#if defined(JS_SIMULATOR_ARM) || defined(JS_SIMULATOR_MIPS64)
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +
  +    jit::Simulator* sim = cx->runtime()->simulator();
  +    sim->disable_single_stepping();
  +
  +    AutoValueVector elems(cx);
  +    for (size_t i = 0; i < stacks.length(); i++) {
  +        JSString* stack = JS_NewUCStringCopyN(cx, stacks[i].begin(), 
stacks[i].length());
  +        if (!stack)
  +            return false;
  +        if (!elems.append(StringValue(stack)))
  +            return false;
  +    }
  +
  +    JSObject* array = JS_NewArrayObject(cx, elems);
  +    if (!array)
  +        return false;
  +
  +    stacks.clear();
  +    args.rval().setObject(*array);
  +    return true;
  +#else
  +    JS_ReportError(cx, "single-step profiling not enabled on this platform");
  +    return false;
  +#endif
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +IsLatin1(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    bool isLatin1 = args.get(0).isString() && 
args[0].toString()->hasLatin1Chars();
  +    args.rval().setBoolean(isLatin1);
  +    return true;
  +}
  +#endif
  +
  +// Global mailbox that is used to communicate a SharedArrayBuffer
  +// value from one worker to another.
  +//
  +// For simplicity we store only the SharedArrayRawBuffer; retaining
  +// the SAB object would require per-runtime storage, and would have no
  +// real benefits.
  +//
  +// Invariant: when a SARB is in the mailbox its reference count is at
  +// least 1, accounting for the reference from the mailbox.
  +//
  +// The lock guards the mailbox variable and prevents a race where two
  +// workers try to set the mailbox at the same time to replace a SARB
  +// that is only referenced from the mailbox: the workers will both
  +// decrement the reference count on the old SARB, and one of those
  +// decrements will be on a garbage object.  We could implement this
  +// with atomics and a CAS loop but it's not worth the bother.
  +
  +#ifdef       NOTYET
  +static PRLock* sharedArrayBufferMailboxLock;
  +static SharedArrayRawBuffer* sharedArrayBufferMailbox;
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +InitSharedArrayBufferMailbox()
  +{
  +    sharedArrayBufferMailboxLock = PR_NewLock();
  +    return sharedArrayBufferMailboxLock != nullptr;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static void
  +DestructSharedArrayBufferMailbox()
  +{
  +    // All workers need to have terminated at this point.
  +    if (sharedArrayBufferMailbox)
  +        sharedArrayBufferMailbox->dropReference();
  +    PR_DestroyLock(sharedArrayBufferMailboxLock);
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +GetSharedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    JSObject* newObj = nullptr;
  +    bool rval = true;
  +
  +    PR_Lock(sharedArrayBufferMailboxLock);
  +    SharedArrayRawBuffer* buf = sharedArrayBufferMailbox;
  +    if (buf) {
  +        buf->addReference();
  +        newObj = SharedArrayBufferObject::New(cx, buf);
  +        if (!newObj) {
  +            buf->dropReference();
  +            rval = false;
  +        }
  +    }
  +    PR_Unlock(sharedArrayBufferMailboxLock);
  +
  +    args.rval().setObjectOrNull(newObj);
  +    return rval;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +SetSharedArrayBuffer(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    SharedArrayRawBuffer* newBuffer = nullptr;
  +
  +    if (argc == 0 || args.get(0).isNullOrUndefined()) {
  +        // Clear out the mailbox
  +    }
  +    else if (args.get(0).isObject() && 
args[0].toObject().is<SharedArrayBufferObject>()) {
  +        newBuffer = 
args[0].toObject().as<SharedArrayBufferObject>().rawBufferObject();
  +        newBuffer->addReference();
  +    } else {
  +        JS_ReportError(cx, "Only a SharedArrayBuffer can be installed in the 
global mailbox");
  +        return false;
  +    }
  +
  +    PR_Lock(sharedArrayBufferMailboxLock);
  +    SharedArrayRawBuffer* oldBuffer = sharedArrayBufferMailbox;
  +    if (oldBuffer)
  +        oldBuffer->dropReference();
  +    sharedArrayBufferMailbox = newBuffer;
  +    PR_Unlock(sharedArrayBufferMailboxLock);
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +class SprintOptimizationTypeInfoOp : public 
JS::ForEachTrackedOptimizationTypeInfoOp
  +{
  +    Sprinter* sp;
  +    bool startedTypes_;
  +
  +  public:
  +    explicit SprintOptimizationTypeInfoOp(Sprinter* sp)
  +      : sp(sp),
  +        startedTypes_(false)
  +    { }
  +
  +    void readType(const char* keyedBy, const char* name,
  +                  const char* location, Maybe<unsigned> lineno) override
  +    {
  +        if (!startedTypes_) {
  +            startedTypes_ = true;
  +            Sprint(sp, "{\"typeset\": [");
  +        }
  +        Sprint(sp, "{\"keyedBy\":\"%s\"", keyedBy);
  +        if (name)
  +            Sprint(sp, ",\"name\":\"%s\"", name);
  +        if (location) {
  +            char buf[512];
  +            PutEscapedString(buf, mozilla::ArrayLength(buf), location, 
strlen(location), '"');
  +            Sprint(sp, ",\"location\":%s", buf);
  +        }
  +        if (lineno.isSome())
  +            Sprint(sp, ",\"line\":%u", *lineno);
  +        Sprint(sp, "},");
  +    }
  +
  +    void operator()(JS::TrackedTypeSite site, const char* mirType) override {
  +        if (startedTypes_) {
  +            // Clear trailing ,
  +            if ((*sp)[sp->getOffset() - 1] == ',')
  +                (*sp)[sp->getOffset() - 1] = ' ';
  +            Sprint(sp, "],");
  +            startedTypes_ = false;
  +        } else {
  +            Sprint(sp, "{");
  +        }
  +
  +        Sprint(sp, "\"site\":\"%s\",\"mirType\":\"%s\"},",
  +               TrackedTypeSiteString(site), mirType);
  +    }
  +};
  +#endif
  +
  +#ifdef  NOTYET
  +class SprintOptimizationAttemptsOp : public 
JS::ForEachTrackedOptimizationAttemptOp
  +{
  +    Sprinter* sp;
  +
  +  public:
  +    explicit SprintOptimizationAttemptsOp(Sprinter* sp)
  +      : sp(sp)
  +    { }
  +
  +    void operator()(JS::TrackedStrategy strategy, JS::TrackedOutcome 
outcome) override {
  +        Sprint(sp, "{\"strategy\":\"%s\",\"outcome\":\"%s\"},",
  +               TrackedStrategyString(strategy), 
TrackedOutcomeString(outcome));
  +    }
  +};
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +ReflectTrackedOptimizations(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedObject callee(cx, &args.callee());
  +    JSRuntime* rt = cx->runtime();
  +
  +    if (!rt->hasJitRuntime() || 
!rt->jitRuntime()->isOptimizationTrackingEnabled(rt)) {
  +        JS_ReportError(cx, "Optimization tracking is off.");
  +        return false;
  +    }
  +
  +    if (args.length() != 1) {
  +        ReportUsageError(cx, callee, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    if (!args[0].isObject() || !args[0].toObject().is<JSFunction>()) {
  +        ReportUsageError(cx, callee, "Argument must be a function");
  +        return false;
  +    }
  +
  +    RootedFunction fun(cx, &args[0].toObject().as<JSFunction>());
  +    if (!fun->hasScript() || !fun->nonLazyScript()->hasIonScript()) {
  +        args.rval().setNull();
  +        return true;
  +    }
  +
  +    // Suppress GC for the unrooted JitcodeGlobalEntry below.
  +    gc::AutoSuppressGC suppress(cx);
  +
  +    jit::JitcodeGlobalTable* table = 
rt->jitRuntime()->getJitcodeGlobalTable();
  +    jit::JitcodeGlobalEntry entry;
  +    jit::IonScript* ion = fun->nonLazyScript()->ionScript();
  +    table->lookupInfallible(ion->method()->raw(), &entry, rt);
  +
  +    if (!entry.hasTrackedOptimizations()) {
  +        JSObject* obj = JS_NewPlainObject(cx);
  +        if (!obj)
  +            return false;
  +        args.rval().setObject(*obj);
  +        return true;
  +    }
  +
  +    Sprinter sp(cx);
  +    if (!sp.init())
  +        return false;
  +
  +    const jit::IonTrackedOptimizationsRegionTable* regions =
  +        entry.ionEntry().trackedOptimizationsRegionTable();
  +
  +    Sprint(&sp, "{\"regions\": [");
  +    for (uint32_t i = 0; i < regions->numEntries(); i++) {
  +        jit::IonTrackedOptimizationsRegion region = regions->entry(i);
  +        jit::IonTrackedOptimizationsRegion::RangeIterator iter = 
region.ranges();
  +        while (iter.more()) {
  +            uint32_t startOffset, endOffset;
  +            uint8_t index;
  +            iter.readNext(&startOffset, &endOffset, &index);
  +            JSScript* script;
  +            jsbytecode* pc;
  +            // Use endOffset, as startOffset may be associated with a
  +            // previous, adjacent region ending exactly at startOffset. That
  +            // is, suppose we have two regions [0, startOffset], 
[startOffset,
  +            // endOffset]. Since we are not querying a return address, we 
want
  +            // the second region and not the first.
  +            uint8_t* addr = ion->method()->raw() + endOffset;
  +            entry.youngestFrameLocationAtAddr(rt, addr, &script, &pc);
  +            Sprint(&sp, 
"{\"location\":\"%s:%u\",\"offset\":%u,\"index\":%u}%s",
  +                   script->filename(), script->lineno(), 
script->pcToOffset(pc), index,
  +                   iter.more() ? "," : "");
  +        }
  +    }
  +    Sprint(&sp, "],");
  +
  +    Sprint(&sp, "\"opts\": [");
  +    for (uint8_t i = 0; i < entry.ionEntry().numOptimizationAttempts(); i++) 
{
  +        Sprint(&sp, "%s{\"typeinfo\":[", i == 0 ? "" : ",");
  +        SprintOptimizationTypeInfoOp top(&sp);
  +        jit::IonTrackedOptimizationsTypeInfo::ForEachOpAdapter adapter(top);
  +        entry.trackedOptimizationTypeInfo(i).forEach(adapter, 
entry.allTrackedTypes());
  +        // Clear the trailing ,
  +        if (sp[sp.getOffset() - 1] == ',')
  +            sp[sp.getOffset() - 1] = ' ';
  +        Sprint(&sp, "],\"attempts\":[");
  +        SprintOptimizationAttemptsOp aop(&sp);
  +        entry.trackedOptimizationAttempts(i).forEach(aop);
  +        // Clear the trailing ,
  +        if (sp[sp.getOffset() - 1] == ',')
  +            sp[sp.getOffset() - 1] = ' ';
  +        Sprint(&sp, "]}");
  +    }
  +    Sprint(&sp, "]}");
  +
  +    if (sp.hadOutOfMemory())
  +        return false;
  +
  +    RootedString str(cx, JS_NewStringCopyZ(cx, sp.string()));
  +    if (!str)
  +        return false;
  +    RootedValue jsonVal(cx);
  +    if (!JS_ParseJSON(cx, str, &jsonVal))
  +        return false;
  +
  +    args.rval().set(jsonVal);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +#ifdef DEBUG
  +static bool
  +DumpStaticScopeChain(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    RootedObject callee(cx, &args.callee());
  +
  +    if (args.length() != 1) {
  +        ReportUsageError(cx, callee, "Wrong number of arguments");
  +        return false;
  +    }
  +
  +    if (!args[0].isObject() ||
  +        !(args[0].toObject().is<JSFunction>() || 
args[0].toObject().is<ModuleObject>()))
  +    {
  +        ReportUsageError(cx, callee, "Argument must be an interpreted 
function or a module");
  +        return false;
  +    }
  +
  +    RootedObject obj(cx, &args[0].toObject());
  +    RootedScript script(cx);
  +
  +    if (obj->is<JSFunction>()) {
  +        RootedFunction fun(cx, &obj->as<JSFunction>());
  +        if (!fun->isInterpreted()) {
  +            ReportUsageError(cx, callee, "Argument must be an interpreted 
function");
  +            return false;
  +        }
  +        script = fun->getOrCreateScript(cx);
  +    } else {
  +        script = obj->as<ModuleObject>().script();
  +    }
  +
  +    js::DumpStaticScopeChain(script);
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +#endif       /* NOTYET */
  +
  +#ifdef       NOTYET
  +namespace js {
  +namespace shell {
  +
  +class ShellAutoEntryMonitor : JS::dbg::AutoEntryMonitor {
  +    Vector<UniqueChars, 1, js::SystemAllocPolicy> log;
  +    bool oom;
  +    bool enteredWithoutExit;
  +
  +  public:
  +    explicit ShellAutoEntryMonitor(JSContext *cx)
  +      : AutoEntryMonitor(cx),
  +        oom(false),
  +        enteredWithoutExit(false)
  +    { }
  +
  +    ~ShellAutoEntryMonitor() {
  +        MOZ_ASSERT(!enteredWithoutExit);
  +    }
  +
  +    void Entry(JSContext* cx, JSFunction* function, JS::HandleValue 
asyncStack,
  +               JS::HandleString asyncCause) override {
  +        MOZ_ASSERT(!enteredWithoutExit);
  +        enteredWithoutExit = true;
  +
  +        RootedString displayId(cx, JS_GetFunctionDisplayId(function));
  +        if (displayId) {
  +            UniqueChars displayIdStr(JS_EncodeStringToUTF8(cx, displayId));
  +            oom = !displayIdStr || !log.append(mozilla::Move(displayIdStr));
  +            return;
  +        }
  +
  +        oom = !log.append(make_string_copy("anonymous"));
  +    }
  +
  +    void Entry(JSContext* cx, JSScript* script, JS::HandleValue asyncStack,
  +               JS::HandleString asyncCause) override {
  +        MOZ_ASSERT(!enteredWithoutExit);
  +        enteredWithoutExit = true;
  +
  +        UniqueChars label(JS_smprintf("eval:%s", 
JS_GetScriptFilename(script)));
  +        oom = !label || !log.append(mozilla::Move(label));
  +    }
  +
  +    void Exit(JSContext* cx) override {
  +        MOZ_ASSERT(enteredWithoutExit);
  +        enteredWithoutExit = false;
  +    }
  +
  +    bool buildResult(JSContext *cx, MutableHandleValue resultValue) {
  +        if (oom) {
  +            JS_ReportOutOfMemory(cx);
  +            return false;
  +        }
  +
  +        RootedObject result(cx, JS_NewArrayObject(cx, log.length()));
  +        if (!result)
  +            return false;
  +
  +        for (size_t i = 0; i < log.length(); i++) {
  +            char *name = log[i].get();
  +            RootedString string(cx, Atomize(cx, name, strlen(name)));
  +            if (!string)
  +                return false;
  +            RootedValue value(cx, StringValue(string));
  +            if (!JS_SetElement(cx, result, i, value))
  +                return false;
  +        }
  +
  +        resultValue.setObject(*result.get());
  +        return true;
  +    }
  +};
  +
  +} // namespace shell
  +} // namespace js
  +#endif
  +
  +#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
  +
  +
  +static const JSFunctionSpec global_functions[] = {
  +    JS_FN("version",                 Version,                        0,0),
  +    JS_FN("options",                 Options,                        0,0),
  +    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),
  +#endif       /* NOTYET */
  +    JS_FN("print",                   Print,                          0,0),
  +    JS_FN("printErr",                        PrintErr,                       
0,0),
  +    JS_FN("putstr",                  PutStr,                         0,0),
  +    JS_FN("dateNow",                 Now,                            0,0),
  +#ifdef       NOTYET
  +    JS_FN("help",                    Help,                           0,0),
  +#endif       /* NOTYET */
  +    JS_FN("quit",                    Quit,                           0,0),
  +    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),
  @@ -2221,9 +6023,13 @@
       JS_FN("createMappedArrayBuffer", CreateMappedArrayBuffer,        1,0),
       JS_FN("getMaxArgs",                      GetMaxArgs,                     
0,0),
       JS_FN("objectEmulatingUndefined",        ObjectEmulatingUndefined,       
0,0),
  +#endif       /* NOTYET */
       JS_FN("isCachingEnabled",                IsCachingEnabled,               
0,0),
  +#ifdef       NOTYET
       JS_FN("setCachingEnabled",               SetCachingEnabled,              
1,0),
  +#endif       /* NOTYET */
       JS_FN("cacheEntry",                      CacheEntry,                     
1,0),
  +#ifdef       NOTYET
       JS_FN("printProfilerEvents",     PrintProfilerEvents,            0,0),
       JS_FN("enableSingleStepProfiling",       EnableSingleStepProfiling,      
0,0),
       JS_FN("disableSingleStepProfiling",      DisableSingleStepProfiling,     
0,0),
  @@ -2630,6 +6436,280 @@
   #endif       /* NOTYET */
   
   /*==============================================================*/
  +#ifdef       NOTYET
  +static const JSFunctionSpecWithHelp console_functions[] = {
  +    JS_FN_HELP("log", Print, 0, 0,
  +"log([exp ...])",
  +"  Evaluate and print expressions to stdout.\n"
  +"  This function is an alias of the print() function."),
  +    JS_FS_HELP_END
  +};
  +#endif
  +
  +#ifdef       NOTYET
  +bool
  +DefineConsole(JSContext* cx, HandleObject global)
  +{
  +    RootedObject obj(cx, JS_NewPlainObject(cx));
  +    return obj &&
  +           JS_DefineFunctionsWithHelp(cx, obj, console_functions) &&
  +           JS_DefineProperty(cx, global, "console", obj, 0);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +#ifdef MOZ_PROFILING
  +# define PROFILING_FUNCTION_COUNT 5
  +# ifdef MOZ_CALLGRIND
  +#  define CALLGRIND_FUNCTION_COUNT 3
  +# else
  +#  define CALLGRIND_FUNCTION_COUNT 0
  +# endif
  +# ifdef MOZ_VTUNE
  +#  define VTUNE_FUNCTION_COUNT 4
  +# else
  +#  define VTUNE_FUNCTION_COUNT 0
  +# endif
  +# define EXTERNAL_FUNCTION_COUNT (PROFILING_FUNCTION_COUNT + 
CALLGRIND_FUNCTION_COUNT + VTUNE_FUNCTION_COUNT)
  +#else
  +# define EXTERNAL_FUNCTION_COUNT 0
  +#endif
  +
  +#undef PROFILING_FUNCTION_COUNT
  +#undef CALLGRIND_FUNCTION_COUNT
  +#undef VTUNE_FUNCTION_COUNT
  +#undef EXTERNAL_FUNCTION_COUNT
  +#endif       /* NOTYET */
  +
  +#ifdef       NOTYET
  +static bool
  +PrintHelpString(JSContext* cx, Value v)
  +{
  +    JSString* str = v.toString();
  +
  +    JSLinearString* linear = str->ensureLinear(cx);
  +    if (!linear)
  +        return false;
  +
  +    JS::AutoCheckCannotGC nogc;
  +    if (linear->hasLatin1Chars()) {
  +        for (const Latin1Char* p = linear->latin1Chars(nogc); *p; p++)
  +            fprintf(gOutFile, "%c", char(*p));
  +    } else {
  +        for (const char16_t* p = linear->twoByteChars(nogc); *p; p++)
  +            fprintf(gOutFile, "%c", char(*p));
  +    }
  +    fprintf(gOutFile, "\n");
  +
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +PrintHelp(JSContext* cx, HandleObject obj)
  +{
  +    RootedValue usage(cx);
  +    if (!JS_GetProperty(cx, obj, "usage", &usage))
  +        return false;
  +    RootedValue help(cx);
  +    if (!JS_GetProperty(cx, obj, "help", &help))
  +        return false;
  +
  +    if (usage.isUndefined() || help.isUndefined())
  +        return true;
  +
  +    return PrintHelpString(cx, usage) && PrintHelpString(cx, help);
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +Help(JSContext* cx, unsigned argc, Value* vp)
  +{
  +    CallArgs args = CallArgsFromVp(argc, vp);
  +    fprintf(gOutFile, "%s\n", JS_GetImplementationVersion());
  +
  +    RootedObject obj(cx);
  +    if (args.length() == 0) {
  +        RootedObject global(cx, JS::CurrentGlobalOrNull(cx));
  +        Rooted<IdVector> ida(cx, IdVector(cx));
  +        if (!JS_Enumerate(cx, global, &ida))
  +            return false;
  +
  +        for (size_t i = 0; i < ida.length(); i++) {
  +            RootedValue v(cx);
  +            RootedId id(cx, ida[i]);
  +            if (!JS_GetPropertyById(cx, global, id, &v))
  +                return false;
  +            if (v.isPrimitive()) {
  +                JS_ReportError(cx, "primitive arg");
  +                return false;
  +            }
  +            obj = v.toObjectOrNull();
  +            if (!PrintHelp(cx, obj))
  +                return false;
  +        }
  +    } else {
  +        for (unsigned i = 0; i < args.length(); i++) {
  +            if (args[i].isPrimitive()) {
  +                JS_ReportError(cx, "primitive arg");
  +                return false;
  +            }
  +            obj = args[i].toObjectOrNull();
  +            if (!PrintHelp(cx, obj))
  +                return false;
  +        }
  +    }
  +
  +    args.rval().setUndefined();
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static const JSErrorFormatString jsShell_ErrorFormatString[JSShellErr_Limit] 
= {
  +#define MSG_DEF(name, count, exception, format) \
  +    { format, count, JSEXN_ERR } ,
  +#include "jsshell.msg"
  +#undef MSG_DEF
  +};
  +#endif
  +
  +#ifdef       NOTYET
  +const JSErrorFormatString*
  +js::shell::my_GetErrorMessage(void* userRef, const unsigned errorNumber)
  +{
  +    if (errorNumber == 0 || errorNumber >= JSShellErr_Limit)
  +        return nullptr;
  +
  +    return &jsShell_ErrorFormatString[errorNumber];
  +}
  +#endif
  +
  +#ifdef  NOTYET
  +static bool
  +CreateLastWarningObject(JSContext* cx, JSErrorReport* report)
  +{
  +    RootedObject warningObj(cx, JS_NewObject(cx, nullptr));
  +    if (!warningObj)
  +        return false;
  +
  +    RootedString nameStr(cx);
  +    if (report->exnType == JSEXN_NONE)
  +        nameStr = JS_NewStringCopyZ(cx, "None");
  +    else
  +        nameStr = GetErrorTypeName(cx->runtime(), report->exnType);
  +    if (!nameStr)
  +        return false;
  +    RootedValue nameVal(cx, StringValue(nameStr));
  +    if (!DefineProperty(cx, warningObj, cx->names().name, nameVal))
  +        return false;
  +
  +    RootedString messageStr(cx, JS_NewUCStringCopyZ(cx, report->ucmessage));
  +    if (!messageStr)
  +        return false;
  +    RootedValue messageVal(cx, StringValue(messageStr));
  +    if (!DefineProperty(cx, warningObj, cx->names().message, messageVal))
  +        return false;
  +
  +    RootedValue linenoVal(cx, Int32Value(report->lineno));
  +    if (!DefineProperty(cx, warningObj, cx->names().lineNumber, linenoVal))
  +        return false;
  +
  +    RootedValue columnVal(cx, Int32Value(report->column));
  +    if (!DefineProperty(cx, warningObj, cx->names().columnNumber, columnVal))
  +        return false;
  +
  +    GetShellRuntime(cx)->lastWarning.setObject(*warningObj);
  +    return true;
  +}
  +#endif
  +
  +#ifdef       NOTYET
  +static bool
  +PrintStackTrace(JSContext* cx, HandleValue exn)
  +{
  +    if (!exn.isObject())
  +        return false;
  +
  +    Maybe<JSAutoCompartment> ac;
  +    RootedObject exnObj(cx, &exn.toObject());
  +    if (IsCrossCompartmentWrapper(exnObj)) {
  +        exnObj = UncheckedUnwrap(exnObj);
  +        ac.emplace(cx, exnObj);
  +    }
  +
  +    // Ignore non-ErrorObject thrown by |throw| statement.
  +    if (!exnObj->is<ErrorObject>())
  +        return true;
  +
  +    // Exceptions thrown while compiling top-level script have no stack.
  +    RootedObject stackObj(cx, exnObj->as<ErrorObject>().stack());
  +    if (!stackObj)
  +        return true;
  +
  +    RootedString stackStr(cx);
  +    if (!BuildStackString(cx, stackObj, &stackStr, 2))
  +        return false;
  +
  +    UniquePtr<char[], JS::FreePolicy> stack(JS_EncodeStringToUTF8(cx, 
stackStr));
  +    if (!stack)
  +        return false;
  +
  +    fputs("Stack:\n", gErrFile);
  +    fputs(stack.get(), gErrFile);
  +
  +    return true;
  +}
  +#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 JSObject*
   NewGlobalObject(JSContext* cx, JS::CompartmentOptions& options,
                   JSPrincipals* principals)
  @@ .
  patch -p0 <<'@@ .'
  Index: rpm/rpmio/rpmjss.inp
  ============================================================================
  $ cvs diff -u -r1.1.2.4 -r1.1.2.5 rpmjss.inp
  --- rpm/rpmio/rpmjss.inp      28 Jun 2017 09:54:15 -0000      1.1.2.4
  +++ rpm/rpmio/rpmjss.inp      2 Jul 2017 12:34:29 -0000       1.1.2.5
  @@ -1,3 +1,4 @@
  +'use strict'
   'hello'+'world, it is '+new Date()
   Math.random()
   "string"
  @@ -10,9 +11,70 @@
   version()
   options("strict")
   options()
  -dateNow()
  +load("js/hello.js")
  +loadRelativeToScript("js/hello.js")
  +//evaluate("evaluate")
  +run("js/hello.js")
  +//var foo = readline()
   print("foo")
   var foo = "bar"
   print(foo)
   var foo = "print"; print(foo)
  -load("js/hello.js")
  +var foo = "printErr"; printErr(foo)
  +var foo = "putstr"; putstr(foo)
  +dateNow()
  +//help
  +var foo = 0; assertEq(foo, foo)
  +//startTimingMutator
  +//stopTimingMutator
  +throwError
  +//disassemble
  +//dis
  +//disfile
  +//dissrc
  +//notes
  +//stackDump
  +//intern
  +//getslx
  +//evalcx
  +//evalInWorker
  +//getSharedArrayBuffer
  +//setSharedArrayBuffer
  +//shapeOf
  +//arrayInfo
  +//sleep
  +//compile
  +//parseModule
  +//setModuleResolveHook
  +//getModuleLoadPath
  +//parse
  +//syntaxParse
  +//offThreadCompileScript
  +//runOffThreadScript
  +//timeout
  +//interruptIf
  +//invokeInterruptCallback
  +//setInterruptCallback
  +//enableLastWarnong
  +//disableLastWarnong
  +//clearLastWarnong
  +//elapsed
  +//decompileFunction
  +//decompileThis
  +//thisFilename
  +//newGlobal
  +//nukeCCW
  +createMappedArrayBuffer("js/createMappedArrayBuffer")
  +//getMaxArgs
  +//objectEmulatingUndefined
  +isCachingEnabled()
  +//setCachingEnabled
  +cacheEntry("cacheEntry")
  +//printProfilerEvents
  +//enableSingleStepProfiling
  +//disableSingleStepProfiling
  +isLatin1("isLatin1")
  +//stackPointerInfo
  +//entryPoints
  +//require
  +quit
  @@ .
______________________________________________________________________
RPM Package Manager                                    http://rpm5.org
CVS Sources Repository                                rpm-cvs@rpm5.org

Reply via email to