/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
 * vim: set ts=8 sts=4 et sw=4 tw=99:
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "frontend/BytecodeCompiler.h"

#include "jscntxt.h"
#include "jsscript.h"

#include "asmjs/AsmJSLink.h"
#include "builtin/ModuleObject.h"
#include "frontend/BytecodeEmitter.h"
#include "frontend/FoldConstants.h"
#include "frontend/NameFunctions.h"
#include "frontend/Parser.h"
#include "vm/GlobalObject.h"
#include "vm/TraceLogging.h"

#include "jsobjinlines.h"
#include "jsscriptinlines.h"

#include "frontend/Parser-inl.h"
#include "vm/ScopeObject-inl.h"

using namespace js;
using namespace js::frontend;
using mozilla::Maybe;

class MOZ_STACK_CLASS AutoCompilationTraceLogger
{
  public:
    AutoCompilationTraceLogger(ExclusiveContext* cx, const TraceLoggerTextId id,
            const ReadOnlyCompileOptions& options);

  private:
    TraceLoggerThread* logger;
    TraceLoggerEvent event;
    AutoTraceLog scriptLogger;
    AutoTraceLog typeLogger;
};

// The BytecodeCompiler class contains resources common to compiling scripts and
// function bodies.
class MOZ_STACK_CLASS BytecodeCompiler
{
  public:
    // Construct an object passing mandatory arguments.
    BytecodeCompiler(ExclusiveContext* cx,
                     LifoAlloc* alloc,
                     const ReadOnlyCompileOptions& options,
                     SourceBufferHolder& sourceBuffer,
                     Handle<ScopeObject*> enclosingStaticScope,
                     TraceLoggerTextId logId);

    // Call setters for optional arguments.
    void maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor);
    void setSourceArgumentsNotIncluded();

    JSScript* compileScript(HandleObject scopeChain, HandleScript evalCaller);
    ModuleObject* compileModule();
    bool compileFunctionBody(MutableHandleFunction fun, Handle<PropertyNameVector> formals,
                             GeneratorKind generatorKind);

    ScriptSourceObject* sourceObjectPtr() const;

  private:
    bool checkLength();
    bool createScriptSource();
    bool maybeCompressSource();
    bool canLazilyParse();
    bool createParser();
    bool createSourceAndParser();
    bool createScript(HandleObject staticScope, bool savedCallerFun = false);
    bool createEmitter(SharedContext* sharedContext, HandleScript evalCaller = nullptr,
                       bool insideNonGlobalEval = false);
    bool isEvalCompilationUnit();
    bool isNonGlobalEvalCompilationUnit();
    bool isNonSyntacticCompilationUnit();
    bool saveCallerFun(HandleScript evalCaller);
    bool handleParseFailure(const Directives& newDirectives);
    bool prepareAndEmitTree(ParseNode** pn);
    bool checkArgumentsWithinEval(JSContext* cx, HandleFunction fun);
    bool maybeCheckEvalFreeVariables(HandleScript evalCaller, HandleObject scopeChain,
                                     ParseContext<FullParseHandler>& pc);
    bool maybeSetDisplayURL(TokenStream& tokenStream);
    bool maybeSetSourceMap(TokenStream& tokenStream);
    bool maybeSetSourceMapFromOptions();
    bool emitFinalReturn();
    bool initGlobalOrEvalBindings(ParseContext<FullParseHandler>& pc);
    bool maybeCompleteCompressSource();

    AutoCompilationTraceLogger traceLogger;
    AutoKeepAtoms keepAtoms;

    ExclusiveContext* cx;
    LifoAlloc* alloc;
    const ReadOnlyCompileOptions& options;
    SourceBufferHolder& sourceBuffer;

    Rooted<ScopeObject*> enclosingStaticScope;
    bool sourceArgumentsNotIncluded;

    RootedScriptSource sourceObject;
    ScriptSource* scriptSource;

    Maybe<SourceCompressionTask> maybeSourceCompressor;
    SourceCompressionTask* sourceCompressor;

    Maybe<Parser<SyntaxParseHandler>> syntaxParser;
    Maybe<Parser<FullParseHandler>> parser;

    Directives directives;
    TokenStream::Position startPosition;

    RootedScript script;
    Maybe<BytecodeEmitter> emitter;
};

AutoCompilationTraceLogger::AutoCompilationTraceLogger(ExclusiveContext* cx,
        const TraceLoggerTextId id, const ReadOnlyCompileOptions& options)
  : logger(cx->isJSContext() ? TraceLoggerForMainThread(cx->asJSContext()->runtime())
                             : TraceLoggerForCurrentThread()),
    event(logger, TraceLogger_AnnotateScripts, options),
    scriptLogger(logger, event),
    typeLogger(logger, id)
{}

BytecodeCompiler::BytecodeCompiler(ExclusiveContext* cx,
                                   LifoAlloc* alloc,
                                   const ReadOnlyCompileOptions& options,
                                   SourceBufferHolder& sourceBuffer,
                                   Handle<ScopeObject*> enclosingStaticScope,
                                   TraceLoggerTextId logId)
  : traceLogger(cx, logId, options),
    keepAtoms(cx->perThreadData),
    cx(cx),
    alloc(alloc),
    options(options),
    sourceBuffer(sourceBuffer),
    enclosingStaticScope(cx, enclosingStaticScope),
    sourceArgumentsNotIncluded(false),
    sourceObject(cx),
    scriptSource(nullptr),
    sourceCompressor(nullptr),
    directives(options.strictOption),
    startPosition(keepAtoms),
    script(cx)
{
}

void
BytecodeCompiler::maybeSetSourceCompressor(SourceCompressionTask* sourceCompressor)
{
    this->sourceCompressor = sourceCompressor;
}

void
BytecodeCompiler::setSourceArgumentsNotIncluded()
{
    sourceArgumentsNotIncluded = true;
}

bool
BytecodeCompiler::checkLength()
{
    // Note this limit is simply so we can store sourceStart and sourceEnd in
    // JSScript as 32-bits. It could be lifted fairly easily, since the compiler
    // is using size_t internally already.
    if (sourceBuffer.length() > UINT32_MAX) {
        if (cx->isJSContext())
            JS_ReportErrorNumber(cx->asJSContext(), GetErrorMessage, nullptr,
                                 JSMSG_SOURCE_TOO_LONG);
        return false;
    }
    return true;
}

bool
BytecodeCompiler::createScriptSource()
{
    if (!checkLength())
        return false;

    sourceObject = CreateScriptSourceObject(cx, options);
    if (!sourceObject)
        return false;

    scriptSource = sourceObject->source();
    return true;
}

bool
BytecodeCompiler::maybeCompressSource()
{
    if (!sourceCompressor) {
        maybeSourceCompressor.emplace(cx);
        sourceCompressor = maybeSourceCompressor.ptr();
    }

    if (!cx->compartment()->options().discardSource()) {
        if (options.sourceIsLazy) {
            scriptSource->setSourceRetrievable();
        } else if (!scriptSource->setSourceCopy(cx, sourceBuffer, sourceArgumentsNotIncluded,
                                                sourceCompressor))
        {
            return false;
        }
    }

    return true;
}

bool
BytecodeCompiler::canLazilyParse()
{
    return options.canLazilyParse &&
           !HasNonSyntacticStaticScopeChain(enclosingStaticScope) &&
           !cx->compartment()->options().disableLazyParsing() &&
           !cx->compartment()->options().discardSource() &&
           !options.sourceIsLazy &&
           !cx->lcovEnabled();
}

bool
BytecodeCompiler::createParser()
{
    if (canLazilyParse()) {
        syntaxParser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
                             /* foldConstants = */ false, (Parser<SyntaxParseHandler>*) nullptr,
                             (LazyScript*) nullptr);

        if (!syntaxParser->checkOptions())
            return false;
    }

    parser.emplace(cx, alloc, options, sourceBuffer.get(), sourceBuffer.length(),
                   /* foldConstants = */ true, syntaxParser.ptrOr(nullptr), nullptr);
    parser->sct = sourceCompressor;
    parser->ss = scriptSource;
    if (!parser->checkOptions())
        return false;

    parser->tokenStream.tell(&startPosition);
    return true;
}

bool
BytecodeCompiler::createSourceAndParser()
{
    return createScriptSource() &&
           maybeCompressSource() &&
           createParser();
}

bool
BytecodeCompiler::createScript(HandleObject staticScope, bool savedCallerFun)
{
    script = JSScript::Create(cx, staticScope, savedCallerFun, options,
                              sourceObject, /* sourceStart = */ 0, sourceBuffer.length());

    return script != nullptr;
}

bool
BytecodeCompiler::createEmitter(SharedContext* sharedContext, HandleScript evalCaller,
                                bool insideNonGlobalEval)
{
    BytecodeEmitter::EmitterMode emitterMode =
        options.selfHostingMode ? BytecodeEmitter::SelfHosting : BytecodeEmitter::Normal;
    emitter.emplace(/* parent = */ nullptr, parser.ptr(), sharedContext, script,
                    /* lazyScript = */ nullptr, options.forEval, evalCaller,
                    insideNonGlobalEval, options.lineno, emitterMode);
    return emitter->init();
}

bool
BytecodeCompiler::isEvalCompilationUnit()
{
    return enclosingStaticScope->is<StaticEvalObject>();
}

bool
BytecodeCompiler::isNonGlobalEvalCompilationUnit()
{
    if (!isEvalCompilationUnit())
        return false;
    StaticEvalObject& eval = enclosingStaticScope->as<StaticEvalObject>();
    JSObject* enclosing = eval.enclosingScopeForStaticScopeIter();
    return !IsStaticGlobalLexicalScope(enclosing);
}

bool
BytecodeCompiler::isNonSyntacticCompilationUnit()
{
    return enclosingStaticScope->is<StaticNonSyntacticScopeObjects>();
}

bool
BytecodeCompiler::saveCallerFun(HandleScript evalCaller)
{
    /*
     * An eval script in a caller frame needs to have its enclosing
     * function captured in case it refers to an upvar, and someone
     * wishes to decompile it while it's running.
     *
     * This ends up as script->objects()->vector[0] in the compiled script.
     */
    RootedFunction fun(cx, evalCaller->functionOrCallerFunction());
    MOZ_ASSERT_IF(fun->strict(), options.strictOption);
    Directives directives(/* strict = */ options.strictOption);
    ObjectBox* funbox = parser->newFunctionBox(/* fn = */ nullptr, fun,
                                               directives, fun->generatorKind(),
                                               enclosingStaticScope);
    if (!funbox)
        return false;

    emitter->objectList.add(funbox);
    return true;
}

bool
BytecodeCompiler::handleParseFailure(const Directives& newDirectives)
{
    if (parser->hadAbortedSyntaxParse()) {
        // Hit some unrecoverable ambiguity during an inner syntax parse.
        // Syntax parsing has now been disabled in the parser, so retry
        // the parse.
        parser->clearAbortedSyntaxParse();
    } else if (parser->tokenStream.hadError() || directives == newDirectives) {
        return false;
    }

    parser->tokenStream.seek(startPosition);

    // Assignment must be monotonic to prevent reparsing iloops
    MOZ_ASSERT_IF(directives.strict(), newDirectives.strict());
    MOZ_ASSERT_IF(directives.asmJS(), newDirectives.asmJS());
    directives = newDirectives;
    return true;
}

bool
BytecodeCompiler::prepareAndEmitTree(ParseNode** ppn)
{
    if (!FoldConstants(cx, ppn, parser.ptr()) ||
        !NameFunctions(cx, *ppn) ||
        !emitter->updateLocalsToFrameSlots() ||
        !emitter->emitTree(*ppn))
    {
        return false;
    }

    return true;
}

bool
BytecodeCompiler::maybeSetDisplayURL(TokenStream& tokenStream)
{
    if (tokenStream.hasDisplayURL()) {
        if (!scriptSource->setDisplayURL(cx, tokenStream.displayURL()))
            return false;
    }
    return true;
}

bool
BytecodeCompiler::maybeSetSourceMap(TokenStream& tokenStream)
{
    if (tokenStream.hasSourceMapURL()) {
        MOZ_ASSERT(!scriptSource->hasSourceMapURL());
        if (!scriptSource->setSourceMapURL(cx, tokenStream.sourceMapURL()))
            return false;
    }
    return true;
}

bool
BytecodeCompiler::maybeSetSourceMapFromOptions()
{
    /*
     * Source map URLs passed as a compile option (usually via a HTTP source map
     * header) override any source map urls passed as comment pragmas.
     */
    if (options.sourceMapURL()) {
        // Warn about the replacement, but use the new one.
        if (scriptSource->hasSourceMapURL()) {
            if(!parser->report(ParseWarning, false, nullptr, JSMSG_ALREADY_HAS_PRAGMA,
                              scriptSource->filename(), "//# sourceMappingURL"))
                return false;
        }

        if (!scriptSource->setSourceMapURL(cx, options.sourceMapURL()))
            return false;
    }

    return true;
}

bool
BytecodeCompiler::checkArgumentsWithinEval(JSContext* cx, HandleFunction fun)
{
    RootedScript script(cx, fun->getOrCreateScript(cx));
    if (!script)
        return false;

    // It's an error to use |arguments| in a legacy generator expression.
    if (script->isGeneratorExp() && script->isLegacyGenerator()) {
        parser->report(ParseError, false, nullptr, JSMSG_BAD_GENEXP_BODY, js_arguments_str);
        return false;
    }

    return true;
}

bool
BytecodeCompiler::maybeCheckEvalFreeVariables(HandleScript evalCaller, HandleObject scopeChain,
                                              ParseContext<FullParseHandler>& pc)
{
    if (!evalCaller || !evalCaller->functionOrCallerFunction())
        return true;

    // Eval scripts are only compiled on the main thread.
    JSContext* cx = this->cx->asJSContext();

    // Watch for uses of 'arguments' within the evaluated script, both as
    // free variables and as variables redeclared with 'var'.
    RootedFunction fun(cx, evalCaller->functionOrCallerFunction());
    HandlePropertyName arguments = cx->names().arguments;
    for (AtomDefnRange r = pc.lexdeps->all(); !r.empty(); r.popFront()) {
        if (r.front().key() == arguments) {
            if (!checkArgumentsWithinEval(cx, fun))
                return false;
        }
    }
    for (AtomDefnListMap::Range r = pc.decls().all(); !r.empty(); r.popFront()) {
        if (r.front().key() == arguments) {
            if (!checkArgumentsWithinEval(cx, fun))
                return false;
        }
    }

    // If the eval'ed script contains any debugger statement, force construction
    // of arguments objects for the caller script and any other scripts it is
    // transitively nested inside. The debugger can access any variable on the
    // scope chain.
    if (pc.sc->hasDebuggerStatement()) {
        RootedObject scope(cx, scopeChain);
        while (scope->is<ScopeObject>() || scope->is<DebugScopeObject>()) {
            if (scope->is<CallObject>() && !scope->as<CallObject>().isForEval()) {
                RootedScript script(cx, scope->as<CallObject>().callee().getOrCreateScript(cx));
                if (!script)
                    return false;
                if (script->argumentsHasVarBinding()) {
                    if (!JSScript::argumentsOptimizationFailed(cx, script))
                        return false;
                }
            }
            scope = scope->enclosingScope();
        }
    }

    return true;
}

bool
BytecodeCompiler::emitFinalReturn()
{
    /*
     * Nowadays the threaded interpreter needs a last return instruction, so we
     * do have to emit that here.
     */
    return emitter->emit1(JSOP_RETRVAL);
}

bool
BytecodeCompiler::initGlobalOrEvalBindings(ParseContext<FullParseHandler>& pc)
{
    Rooted<Bindings> bindings(cx, script->bindings);
    if (!pc.generateBindings(cx, parser->tokenStream, *alloc, &bindings))
        return false;
    script->bindings = bindings;
    return true;
}

bool
BytecodeCompiler::maybeCompleteCompressSource()
{
    return !maybeSourceCompressor || maybeSourceCompressor->complete();
}

JSScript*
BytecodeCompiler::compileScript(HandleObject scopeChain, HandleScript evalCaller)
{
    if (!createSourceAndParser())
        return nullptr;

    RootedFunction savedCallerFun(cx);
    if (evalCaller)
        savedCallerFun = evalCaller->functionOrCallerFunction();

    if (!createScript(enclosingStaticScope, savedCallerFun))
        return nullptr;

    GlobalSharedContext globalsc(cx, enclosingStaticScope, directives, options.extraWarningsOption,
                                 savedCallerFun);
    if (!createEmitter(&globalsc, evalCaller, isNonGlobalEvalCompilationUnit()))
        return nullptr;

    if (savedCallerFun && !saveCallerFun(evalCaller))
        return nullptr;

    for (;;) {
        ParseContext<FullParseHandler> pc(parser.ptr(),
                                          /* parent = */ nullptr,
                                          /* maybeFunction = */ nullptr,
                                          &globalsc,
                                          /* newDirectives = */ nullptr);
        if (!pc.init(*parser))
            return nullptr;

        ParseNode* pn;
        if (isEvalCompilationUnit())
            pn = parser->evalBody();
        else
            pn = parser->globalBody();

        // Successfully parsed. Emit the script.
        if (pn) {
            if (!initGlobalOrEvalBindings(pc))
                return nullptr;
            if (!maybeCheckEvalFreeVariables(evalCaller, scopeChain, pc))
                return nullptr;
            if (!prepareAndEmitTree(&pn))
                return nullptr;
            parser->handler.freeTree(pn);

            break;
        }

        // Maybe we aborted a syntax parse. See if we can try again.
        if (!handleParseFailure(directives))
            return nullptr;
    }

    if (!maybeSetDisplayURL(parser->tokenStream) ||
        !maybeSetSourceMap(parser->tokenStream) ||
        !maybeSetSourceMapFromOptions() ||
        !emitFinalReturn() ||
        !JSScript::fullyInitFromEmitter(cx, script, emitter.ptr()))
    {
        return nullptr;
    }

    emitter->tellDebuggerAboutCompiledScript(cx);

    if (!maybeCompleteCompressSource())
        return nullptr;

    MOZ_ASSERT_IF(cx->isJSContext(), !cx->asJSContext()->isExceptionPending());
    return script;
}

ModuleObject* BytecodeCompiler::compileModule()
{
    if (!createSourceAndParser())
        return nullptr;

    Rooted<ModuleObject*> module(cx, ModuleObject::create(cx, enclosingStaticScope));
    if (!module)
        return nullptr;

    if (!createScript(module))
        return nullptr;

    module->init(script);

    ParseNode* pn = parser->standaloneModule(module);
    if (!pn)
        return nullptr;

    if (!NameFunctions(cx, pn) ||
        !maybeSetDisplayURL(parser->tokenStream) ||
        !maybeSetSourceMap(parser->tokenStream))
    {
        return nullptr;
    }

    script->bindings = pn->pn_modulebox->bindings;

    RootedModuleEnvironmentObject dynamicScope(cx, ModuleEnvironmentObject::create(cx, module));
    if (!dynamicScope)
        return nullptr;

    module->setInitialEnvironment(dynamicScope);

    if (!createEmitter(pn->pn_modulebox) ||
        !emitter->emitModuleScript(pn->pn_body))
    {
        return nullptr;
    }

    ModuleBuilder builder(cx->asJSContext(), module);
    if (!builder.buildAndInit(pn))
        return nullptr;

    parser->handler.freeTree(pn);

    if (!maybeCompleteCompressSource())
        return nullptr;

    MOZ_ASSERT_IF(cx->isJSContext(), !cx->asJSContext()->isExceptionPending());
    return module;
}

bool
BytecodeCompiler::compileFunctionBody(MutableHandleFunction fun,
                                      Handle<PropertyNameVector> formals,
                                      GeneratorKind generatorKind)
{
    MOZ_ASSERT(fun);
    MOZ_ASSERT(fun->isTenured());

    fun->setArgCount(formals.length());

    if (!createSourceAndParser())
        return false;

    // Speculatively parse using the default directives implied by the context.
    // If a directive is encountered (e.g., "use strict") that changes how the
    // function should have been parsed, we backup and reparse with the new set
    // of directives.

    ParseNode* fn;
    do {
        Directives newDirectives = directives;
        fn = parser->standaloneFunctionBody(fun, formals, generatorKind, directives,
                                            &newDirectives, enclosingStaticScope);
        if (!fn && !handleParseFailure(newDirectives))
            return false;
    } while (!fn);

    if (!NameFunctions(cx, fn) ||
        !maybeSetDisplayURL(parser->tokenStream) ||
        !maybeSetSourceMap(parser->tokenStream))
    {
        return false;
    }

    if (fn->pn_funbox->function()->isInterpreted()) {
        MOZ_ASSERT(fun == fn->pn_funbox->function());

        if (!createScript(enclosingStaticScope))
            return false;

        script->bindings = fn->pn_funbox->bindings;

        if (!createEmitter(fn->pn_funbox) ||
            !emitter->emitFunctionScript(fn->pn_body))
        {
            return false;
        }
    } else {
        fun.set(fn->pn_funbox->function());
        MOZ_ASSERT(IsAsmJSModuleNative(fun->native()));
    }

    if (!maybeCompleteCompressSource())
        return false;

    return true;
}

ScriptSourceObject*
BytecodeCompiler::sourceObjectPtr() const
{
    return sourceObject.get();
}

ScriptSourceObject*
frontend::CreateScriptSourceObject(ExclusiveContext* cx, const ReadOnlyCompileOptions& options)
{
    ScriptSource* ss = cx->new_<ScriptSource>();
    if (!ss)
        return nullptr;
    ScriptSourceHolder ssHolder(ss);

    if (!ss->initFromOptions(cx, options))
        return nullptr;

    RootedScriptSource sso(cx, ScriptSourceObject::create(cx, ss));
    if (!sso)
        return nullptr;

    // Off-thread compilations do all their GC heap allocation, including the
    // SSO, in a temporary compartment. Hence, for the SSO to refer to the
    // gc-heap-allocated values in |options|, it would need cross-compartment
    // wrappers from the temporary compartment to the real compartment --- which
    // would then be inappropriate once we merged the temporary and real
    // compartments.
    //
    // Instead, we put off populating those SSO slots in off-thread compilations
    // until after we've merged compartments.
    if (cx->isJSContext()) {
        if (!ScriptSourceObject::initFromOptions(cx->asJSContext(), sso, options))
            return nullptr;
    }

    return sso;
}

JSScript*
frontend::CompileScript(ExclusiveContext* cx, LifoAlloc* alloc, HandleObject scopeChain,
                        Handle<ScopeObject*> enclosingStaticScope,
                        HandleScript evalCaller,
                        const ReadOnlyCompileOptions& options,
                        SourceBufferHolder& srcBuf,
                        JSString* source_ /* = nullptr */,
                        SourceCompressionTask* extraSct /* = nullptr */,
                        ScriptSourceObject** sourceObjectOut /* = nullptr */)
{
    MOZ_ASSERT(srcBuf.get());

    /*
     * The scripted callerFrame can only be given for compile-and-go scripts
     * and non-zero static level requires callerFrame.
     */
    MOZ_ASSERT_IF(evalCaller, options.isRunOnce);
    MOZ_ASSERT_IF(evalCaller, options.forEval);
    MOZ_ASSERT_IF(evalCaller && evalCaller->strict(), options.strictOption);

    MOZ_ASSERT_IF(sourceObjectOut, *sourceObjectOut == nullptr);

    BytecodeCompiler compiler(cx, alloc, options, srcBuf, enclosingStaticScope,
                              TraceLogger_ParserCompileScript);
    compiler.maybeSetSourceCompressor(extraSct);
    JSScript* script = compiler.compileScript(scopeChain, evalCaller);

    // frontend::CompileScript independently returns the
    // ScriptSourceObject (SSO) for the compile.  This is used by
    // off-main-thread script compilation (OMT-SC).
    //
    // OMT-SC cannot initialize the SSO when it is first constructed
    // because the SSO is allocated initially in a separate compartment.
    //
    // After OMT-SC, the separate compartment is merged with the main
    // compartment, at which point the JSScripts created become observable
    // by the debugger via memory-space scanning.
    //
    // Whatever happens to the top-level script compilation (even if it
    // fails and returns null), we must finish initializing the SSO.  This
    // is because there may be valid inner scripts observable by the debugger
    // which reference the partially-initialized SSO.
    if (sourceObjectOut)
        *sourceObjectOut = compiler.sourceObjectPtr();

    return script;
}

ModuleObject*
frontend::CompileModule(JSContext* cx, HandleObject obj,
                        const ReadOnlyCompileOptions& optionsInput,
                        SourceBufferHolder& srcBuf)
{
    MOZ_ASSERT(srcBuf.get());

    CompileOptions options(cx, optionsInput);
    options.maybeMakeStrictMode(true); // ES6 10.2.1 Module code is always strict mode code.
    options.setIsRunOnce(true);

    Rooted<ScopeObject*> staticScope(cx, &cx->global()->lexicalScope().staticBlock());
    BytecodeCompiler compiler(cx, &cx->tempLifoAlloc(), options, srcBuf, staticScope,
                              TraceLogger_ParserCompileModule);
    return compiler.compileModule();
}

bool
frontend::CompileLazyFunction(JSContext* cx, Handle<LazyScript*> lazy, const char16_t* chars, size_t length)
{
    MOZ_ASSERT(cx->compartment() == lazy->functionNonDelazifying()->compartment());

    CompileOptions options(cx, lazy->version());
    options.setMutedErrors(lazy->mutedErrors())
           .setFileAndLine(lazy->filename(), lazy->lineno())
           .setColumn(lazy->column())
           .setNoScriptRval(false)
           .setSelfHostingMode(false);

    AutoCompilationTraceLogger traceLogger(cx, TraceLogger_ParserCompileLazy, options);

    Parser<FullParseHandler> parser(cx, &cx->tempLifoAlloc(), options, chars, length,
                                    /* foldConstants = */ true, nullptr, lazy);
    if (!parser.checkOptions())
        return false;

    Rooted<JSFunction*> fun(cx, lazy->functionNonDelazifying());
    MOZ_ASSERT(!lazy->isLegacyGenerator());
    ParseNode* pn = parser.standaloneLazyFunction(fun, lazy->strict(), lazy->generatorKind());
    if (!pn)
        return false;

    if (!NameFunctions(cx, pn))
        return false;

    RootedObject enclosingScope(cx, lazy->enclosingScope());
    RootedScriptSource sourceObject(cx, lazy->sourceObject());
    MOZ_ASSERT(sourceObject);

    Rooted<JSScript*> script(cx, JSScript::Create(cx, enclosingScope, false, options,
                                                  sourceObject, lazy->begin(), lazy->end()));
    if (!script)
        return false;

    script->bindings = pn->pn_funbox->bindings;

    if (lazy->isLikelyConstructorWrapper())
        script->setLikelyConstructorWrapper();
    if (lazy->hasBeenCloned())
        script->setHasBeenCloned();

    /*
     * We just pass false for insideNonGlobalEval and insideEval, because we
     * don't actually know whether we are or not.  The only consumer of those
     * booleans is TryConvertFreeName, and it has special machinery to avoid
     * doing bad things when a lazy function is inside eval.
     */
    MOZ_ASSERT(!options.forEval);
    BytecodeEmitter bce(/* parent = */ nullptr, &parser, pn->pn_funbox, script, lazy,
                        /* insideEval = */ false, /* evalCaller = */ nullptr,
                        /* insideNonGlobalEval = */ false, options.lineno,
                        BytecodeEmitter::LazyFunction);
    if (!bce.init())
        return false;

    return bce.emitFunctionScript(pn->pn_body);
}

// Compile a JS function body, which might appear as the value of an event
// handler attribute in an HTML <INPUT> tag, or in a Function() constructor.
static bool
CompileFunctionBody(JSContext* cx, MutableHandleFunction fun, const ReadOnlyCompileOptions& options,
                    Handle<PropertyNameVector> formals, SourceBufferHolder& srcBuf,
                    Handle<ScopeObject*> enclosingStaticScope, GeneratorKind generatorKind)
{
    MOZ_ASSERT(!options.isRunOnce);

    // FIXME: make Function pass in two strings and parse them as arguments and
    // ProgramElements respectively.

    BytecodeCompiler compiler(cx, &cx->tempLifoAlloc(), options, srcBuf, enclosingStaticScope,
                              TraceLogger_ParserCompileFunction);
    compiler.setSourceArgumentsNotIncluded();
    return compiler.compileFunctionBody(fun, formals, generatorKind);
}

bool
frontend::CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
                              const ReadOnlyCompileOptions& options,
                              Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf,
                              Handle<ScopeObject*> enclosingStaticScope)
{
    return CompileFunctionBody(cx, fun, options, formals, srcBuf,
                               enclosingStaticScope, NotGenerator);
}

bool
frontend::CompileFunctionBody(JSContext* cx, MutableHandleFunction fun,
                              const ReadOnlyCompileOptions& options,
                              Handle<PropertyNameVector> formals, JS::SourceBufferHolder& srcBuf)
{
    Rooted<ScopeObject*> staticLexical(cx, &cx->global()->lexicalScope().staticBlock());
    return CompileFunctionBody(cx, fun, options, formals, srcBuf, staticLexical, NotGenerator);
}


bool
frontend::CompileStarGeneratorBody(JSContext* cx, MutableHandleFunction fun,
                                   const ReadOnlyCompileOptions& options,
                                   Handle<PropertyNameVector> formals,
                                   JS::SourceBufferHolder& srcBuf)
{
    Rooted<ScopeObject*> staticLexical(cx, &cx->global()->lexicalScope().staticBlock());
    return CompileFunctionBody(cx, fun, options, formals, srcBuf, staticLexical, StarGenerator);
}
