/*
 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include "AbstractModuleRecord.h"

#include "Error.h"
#include "Interpreter.h"
#include "JSCInlines.h"
#include "JSMap.h"
#include "JSModuleEnvironment.h"
#include "JSModuleNamespaceObject.h"
#include "JSModuleRecord.h"
#include "UnlinkedModuleProgramCodeBlock.h"
#include "WebAssemblyModuleRecord.h"
#include <wtf/Optional.h>

namespace JSC {
namespace AbstractModuleRecordInternal {
static const bool verbose = false;
} // namespace AbstractModuleRecordInternal

const ClassInfo AbstractModuleRecord::s_info = { "AbstractModuleRecord", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(AbstractModuleRecord) };

AbstractModuleRecord::AbstractModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey)
    : Base(vm, structure)
    , m_moduleKey(moduleKey)
{
}

void AbstractModuleRecord::destroy(JSCell* cell)
{
    AbstractModuleRecord* thisObject = static_cast<AbstractModuleRecord*>(cell);
    thisObject->AbstractModuleRecord::~AbstractModuleRecord();
}

void AbstractModuleRecord::finishCreation(ExecState* exec, VM& vm)
{
    Base::finishCreation(vm);
    ASSERT(inherits(vm, info()));

    auto scope = DECLARE_THROW_SCOPE(vm);
    JSMap* map = JSMap::create(exec, vm, globalObject(vm)->mapStructure());
    scope.releaseAssertNoException();
    m_dependenciesMap.set(vm, this, map);
    putDirect(vm, Identifier::fromString(&vm, "dependenciesMap"_s), m_dependenciesMap.get());
}

void AbstractModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
    AbstractModuleRecord* thisObject = jsCast<AbstractModuleRecord*>(cell);
    Base::visitChildren(thisObject, visitor);
    visitor.append(thisObject->m_moduleEnvironment);
    visitor.append(thisObject->m_moduleNamespaceObject);
    visitor.append(thisObject->m_dependenciesMap);
}

void AbstractModuleRecord::appendRequestedModule(const Identifier& moduleName)
{
    m_requestedModules.add(moduleName.impl());
}

void AbstractModuleRecord::addStarExportEntry(const Identifier& moduleName)
{
    m_starExportEntries.add(moduleName.impl());
}

void AbstractModuleRecord::addImportEntry(const ImportEntry& entry)
{
    bool isNewEntry = m_importEntries.add(entry.localName.impl(), entry).isNewEntry;
    ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser.
}

void AbstractModuleRecord::addExportEntry(const ExportEntry& entry)
{
    bool isNewEntry = m_exportEntries.add(entry.exportName.impl(), entry).isNewEntry;
    ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser.
}

auto AbstractModuleRecord::tryGetImportEntry(UniquedStringImpl* localName) -> Optional<ImportEntry>
{
    const auto iterator = m_importEntries.find(localName);
    if (iterator == m_importEntries.end())
        return WTF::nullopt;
    return Optional<ImportEntry>(iterator->value);
}

auto AbstractModuleRecord::tryGetExportEntry(UniquedStringImpl* exportName) -> Optional<ExportEntry>
{
    const auto iterator = m_exportEntries.find(exportName);
    if (iterator == m_exportEntries.end())
        return WTF::nullopt;
    return Optional<ExportEntry>(iterator->value);
}

auto AbstractModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName) -> ExportEntry
{
    return ExportEntry { Type::Local, exportName, Identifier(), Identifier(), localName };
}

auto AbstractModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName) -> ExportEntry
{
    return ExportEntry { Type::Indirect, exportName, moduleName, importName, Identifier() };
}

auto AbstractModuleRecord::Resolution::notFound() -> Resolution
{
    return Resolution { Type::NotFound, nullptr, Identifier() };
}

auto AbstractModuleRecord::Resolution::error() -> Resolution
{
    return Resolution { Type::Error, nullptr, Identifier() };
}

auto AbstractModuleRecord::Resolution::ambiguous() -> Resolution
{
    return Resolution { Type::Ambiguous, nullptr, Identifier() };
}

AbstractModuleRecord* AbstractModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    JSValue moduleNameValue = identifierToJSValue(vm, moduleName);
    JSValue entry = m_dependenciesMap->JSMap::get(exec, moduleNameValue);
    RETURN_IF_EXCEPTION(scope, nullptr);
    RELEASE_AND_RETURN(scope, jsCast<AbstractModuleRecord*>(entry.get(exec, Identifier::fromString(exec, "module"))));
}

auto AbstractModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    Optional<ImportEntry> optionalImportEntry = tryGetImportEntry(localName.impl());
    if (!optionalImportEntry)
        return Resolution::notFound();

    const ImportEntry& importEntry = *optionalImportEntry;
    if (importEntry.type == AbstractModuleRecord::ImportEntryType::Namespace)
        return Resolution::notFound();

    AbstractModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
    RETURN_IF_EXCEPTION(scope, Resolution::error());
    return importedModule->resolveExport(exec, importEntry.importName);
}

struct AbstractModuleRecord::ResolveQuery {
    struct Hash {
        static unsigned hash(const ResolveQuery&);
        static bool equal(const ResolveQuery&, const ResolveQuery&);
        static const bool safeToCompareToEmptyOrDeleted = true;
    };
    using HashTraits = WTF::CustomHashTraits<ResolveQuery>;

    ResolveQuery(AbstractModuleRecord* moduleRecord, UniquedStringImpl* exportName)
        : moduleRecord(moduleRecord)
        , exportName(exportName)
    {
    }

    ResolveQuery(AbstractModuleRecord* moduleRecord, const Identifier& exportName)
        : ResolveQuery(moduleRecord, exportName.impl())
    {
    }

    enum EmptyValueTag { EmptyValue };
    ResolveQuery(EmptyValueTag)
    {
    }

    enum DeletedValueTag { DeletedValue };
    ResolveQuery(DeletedValueTag)
        : moduleRecord(nullptr)
        , exportName(WTF::HashTableDeletedValue)
    {
    }

    bool isEmptyValue() const
    {
        return !exportName;
    }

    bool isDeletedValue() const
    {
        return exportName.isHashTableDeletedValue();
    }

    void dump(PrintStream& out) const
    {
        if (!moduleRecord) {
            out.print("<empty>");
            return;
        }
        out.print(moduleRecord->moduleKey(), " \"", exportName.get(), "\"");
    }

    // The module record is not marked from the GC. But these records are reachable from the JSGlobalObject.
    // So we don't care the reachability to this record.
    AbstractModuleRecord* moduleRecord;
    RefPtr<UniquedStringImpl> exportName;
};

inline unsigned AbstractModuleRecord::ResolveQuery::Hash::hash(const ResolveQuery& query)
{
    return WTF::PtrHash<AbstractModuleRecord*>::hash(query.moduleRecord) + IdentifierRepHash::hash(query.exportName);
}

inline bool AbstractModuleRecord::ResolveQuery::Hash::equal(const ResolveQuery& lhs, const ResolveQuery& rhs)
{
    return lhs.moduleRecord == rhs.moduleRecord && lhs.exportName == rhs.exportName;
}

auto AbstractModuleRecord::tryGetCachedResolution(UniquedStringImpl* exportName) -> Optional<Resolution>
{
    const auto iterator = m_resolutionCache.find(exportName);
    if (iterator == m_resolutionCache.end())
        return WTF::nullopt;
    return Optional<Resolution>(iterator->value);
}

void AbstractModuleRecord::cacheResolution(UniquedStringImpl* exportName, const Resolution& resolution)
{
    m_resolutionCache.add(exportName, resolution);
}

auto AbstractModuleRecord::resolveExportImpl(ExecState* exec, const ResolveQuery& root) -> Resolution
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    if (AbstractModuleRecordInternal::verbose)
        dataLog("Resolving ", root, "\n");

    // https://tc39.github.io/ecma262/#sec-resolveexport

    // How to avoid C++ recursion in this function:
    // This function avoids C++ recursion of the naive ResolveExport implementation.
    // Flatten the recursion to the loop with the task queue and frames.
    //
    // 1. pendingTasks
    //     We enqueue the recursive resolveExport call to this queue to avoid recursive calls in C++.
    //     The task has 3 types. (1) Query, (2) IndirectFallback and (3) GatherStars.
    //     (1) Query
    //         Querying the resolution to the current module.
    //     (2) IndirectFallback
    //         Examine the result of the indirect export resolution. Only when the indirect export resolution fails,
    //         we look into the star exports. (step 5-a-vi).
    //     (3) GatherStars
    //         Examine the result of the star export resolutions.
    //
    // 2. frames
    //     When the spec calls the resolveExport recursively, instead we append the frame
    //     (that holds the result resolution) to the frames and enqueue the task to the pendingTasks.
    //     The entry in the frames means the *local* resolution result of the specific recursive resolveExport.
    //
    // We should maintain the local resolution result instead of holding the global resolution result only.
    // For example,
    //
    //     star
    // (1) ---> (2) "Resolve"
    //      |
    //      |
    //      +-> (3) "NotFound"
    //      |
    //      |       star
    //      +-> (4) ---> (5) "Resolve" [here]
    //               |
    //               |
    //               +-> (6) "Error"
    //
    // Consider the above graph. The numbers represents the modules. Now we are [here].
    // If we only hold the global resolution result during the resolveExport operation, [here],
    // we decide the entire result of resolveExport is "Ambiguous", because there are multiple
    // "Resolve" (in module (2) and (5)). However, this should become "Error" because (6) will
    // propagate "Error" state to the (4), (4) will become "Error" and then, (1) will become
    // "Error". We should aggregate the results at the star exports point ((4) and (1)).
    //
    // Usually, both "Error" and "Ambiguous" states will throw the syntax error. So except for the content of the
    // error message, there are no difference. (And if we fix the (6) that raises "Error", next, it will produce
    // the "Ambiguous" error due to (5). Anyway, user need to fix the both. So which error should be raised at first
    // doesn't matter so much.
    //
    // However, this may become the problem under the module namespace creation.
    // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace
    // section 15.2.1.18, step 3-d-ii
    // Here, we distinguish "Ambiguous" and "Error". When "Error" state is produced, we need to throw the propagated error.
    // But if "Ambiguous" state comes, we just ignore the result.
    // To follow the requirement strictly, in this implementation, we keep the local resolution result to produce the
    // correct result under the above complex cases.

    // Caching strategy:
    // The resolveExport operation is frequently called. So caching results is important.
    // We observe the following aspects and based on them construct the caching strategy.
    // Here, we attempt to cache the resolution by constructing the map in module records.
    // That means  Module -> ExportName -> Maybe<Resolution>.
    // Technically, all the AbstractModuleRecords have the Map<ExportName, Resolution> for caching.
    //
    // The important observations are that,
    //
    //  - *cacheable* means that traversing to this node from a path will produce the same results as starting from this node.
    //
    //    Here, we define the resovling route. We represent [?] as the module that has the local binding.
    //    And (?) as the module without the local binding.
    //
    //      @ -> (A) -> (B) -> [C]
    //
    //    We list the resolving route for each node.
    //
    //    (A): (A) -> (B) -> [C]
    //    (B): (B) -> [C]
    //    [C]: [C]
    //
    //    In this case, if we start the tracing from (B), the resolving route becomes (B) -> [C].
    //    So this is the same. At that time, we can say (B) is cacheable in the first tracing.
    //
    //  - The cache ability of a node depends on the resolving route from this node.
    //
    // 1. The starting point is always cacheable.
    //
    // 2. A module that has resolved a local binding is always cacheable.
    //
    //  @ -> (A) -> [B]
    //
    //  In the above case, we can see the [B] as cacheable.
    //  This is because when starting from [B] node, we immediately resolve with the local binding.
    //  So the resolving route from [B] does not depend on the starting point.
    //
    // 3. If we don't follow any star links during the resolution, we can see all the traced nodes are cacheable.
    //
    //  If there are non star links, it means that there is *no branch* in the module dependency graph.
    //  This *no branch* feature makes all the modules cachable.
    //
    //  I.e, if we traverse one star link (even if we successfully resolve that star link),
    //  we must still traverse all other star links. I would also explain we don't run into
    //  this when resolving a local/indirect link. When resolving a local/indirect link,
    //  we won't traverse any star links.
    //  And since the module can hold only one local/indirect link for the specific export name (if there
    //  are multiple local/indirect links that has the same export name, it should be syntax error in the
    //  parsing phase.), there is no multiple outgoing links from a module.
    //
    //  @ -> (A) --> (B) -> [C] -> (D) -> (E) -+
    //                ^                        |
    //                |                        |
    //                +------------------------+
    //
    //  When starting from @, [C] will be found as the module resolving the given binding.
    //  In this case, (B) can cache this resolution. Since the resolving route is the same to the one when
    //  starting from (B). After caching the above result, we attempt to resolve the same binding from (D).
    //
    //                              @
    //                              |
    //                              v
    //  @ -> (A) --> (B) -> [C] -> (D) -> (E) -+
    //                ^                        |
    //                |                        |
    //                +------------------------+
    //
    //  In this case, we can use the (B)'s cached result. And (E) can be cached.
    //
    //    (E): The resolving route is now (E) -> (B) -> [C]. That is the same when starting from (E).
    //
    //  No branching makes that the problematic *once-visited* node cannot be seen.
    //  The *once-visited* node makes the resolving route changed since when we see the *once-visited* node,
    //  we stop tracing this.
    //
    //  If there is no star links and if we look *once-visited* node under no branching graph, *once-visited*
    //  node cannot resolve the requested binding. If the *once-visited* node can resolve the binding, we
    //  should have already finished the resolution before reaching this *once-visited* node.
    //
    // 4. Once we follow star links, we should not retrieve the result from the cache and should not cache.
    //
    //  Star links are only the way to introduce branch.
    //  Once we follow the star links during the resolution, we cannot cache naively.
    //  This is because the cacheability depends on the resolving route. And branching produces the problematic *once-visited*
    //  nodes. Since we don't follow the *once-visited* node, the resolving route from the node becomes different from
    //  the resolving route when starting from this node.
    //
    //  The following example explains when we should not retrieve the cache and cache the result.
    //
    //               +----> (D) ------+
    //               |                |
    //               |                v
    //      (A) *----+----> (B) ---> [C]
    //                       ^
    //                       |
    //                       @
    //
    //  When starting from (B), we find [C]. In this resolving route, we don't find any star link.
    //  And by definition, (B) and [C] are cachable. (B) is the starting point. And [C] has the local binding.
    //
    //               +----> (D) ------+
    //               |                |
    //               |                v
    //  @-> (A) *----+----> (B) ---> [C]
    //
    //  But when starting from (A), we should not get the value from the cache. Because,
    //
    //    1. When looking (D), we reach [C] and make both resolved.
    //    2. When looking (B), if we retrieved the last cache from (B), (B) becomes resolved.
    //    3. But actually, (B) is not-found in this trial because (C) is already *once-visited*.
    //    4. If we accidentally make (B) resolved, (A) becomes ambiguous. But the correct answer is resolved.
    //
    //  Why is this problem caused? This is because the *once-visited* node makes the result not-found.
    //  In the second trial, (B) -> [C] result is changed from resolved to not-found.
    //
    //  When does this become a problem? If the status of the *once-visited* node group is resolved,
    //  changing the result to not-found makes the result changed.
    //
    //  This problem does not happen when we don't see any star link yet. Now, consider the minimum case.
    //
    //  @-> (A) -> [ some graph ]
    //       ^            |
    //       |            |
    //       +------------+
    //
    //  In (A), we don't see any star link yet. So we can say that all the visited nodes does not have any local
    //  resolution. Because if they had a local/indirect resolution, we should have already finished the tracing.
    //
    //  And even if the some graph will see the *once-visited* node (in this case, (A)), that does not affect the
    //  result of the resolution. Because even if we follow the link to (A) or not follow the link to (A), the status
    //  of the link is always not-found since (A) does not have any local resolution.
    //  In the above case, we can use the result of the [some graph].
    //
    // 5. Once we see star links, even if we have not yet traversed that star link path, we should disable caching.
    //
    //  Here is the reason why:
    //
    //       +-------------+
    //       |             |
    //       v             |
    //      (A) -> (B) -> (C) *-> [E]
    //       *             ^
    //       |             |
    //       v             @
    //      [D]
    //
    //  In the above case, (C) will be resolved with [D].
    //  (C) will see (A) and (A) gives up in (A) -> (B) -> (C) route. So, (A) will fallback to [D].
    //
    //       +-------------+
    //       |             |
    //       v             |
    //  @-> (A) -> (B) -> (C) *-> [E]
    //       *
    //       |
    //       v
    //      [D]
    //
    //  But in this case, (A) will be resolved with [E] (not [D]).
    //  (C) will attempt to follow the link to (A), but it fails.
    //  So (C) will fallback to the star link and found [E]. In this senario,
    //  (C) is now resolved with [E]'s result.
    //
    //  The cause of this problem is also the same to 4.
    //  In the latter case, when looking (C), we cannot use the cached result in (C).
    //  Because the cached result of (C) depends on the *once-visited* node (A) and
    //  (A) has the fallback system with the star link.
    //  In the latter trial, we now assume that (A)'s status is not-found.
    //  But, actually, in the former trial, (A)'s status becomes resolved due to the fallback to the [D].
    //
    // To summarize the observations.
    //
    //  1. The starting point is always cacheable.
    //  2. A module that has resolved a local binding is always cacheable.
    //  3. If we don't follow any star links during the resolution, we can see all the traced nodes are cacheable.
    //  4. Once we follow star links, we should not retrieve the result from the cache and should not cache the result.
    //  5. Once we see star links, even if we have not yet traversed that star link path, we should disable caching.

    using ResolveSet = WTF::HashSet<ResolveQuery, ResolveQuery::Hash, ResolveQuery::HashTraits>;
    enum class Type { Query, IndirectFallback, GatherStars };
    struct Task {
        ResolveQuery query;
        Type type;
    };

    auto typeString = [] (Type type) -> const char* {
        switch (type) {
        case Type::Query:
            return "Query";
        case Type::IndirectFallback:
            return "IndirectFallback";
        case Type::GatherStars:
            return "GatherStars";
        }
        RELEASE_ASSERT_NOT_REACHED();
        return nullptr;
    };

    Vector<Task, 8> pendingTasks;
    ResolveSet resolveSet;

    Vector<Resolution, 8> frames;

    bool foundStarLinks = false;

    frames.append(Resolution::notFound());

    // Call when the query is not resolved in the current module.
    // It will enqueue the star resolution requests. Return "false" if the error occurs.
    auto resolveNonLocal = [&](const ResolveQuery& query) -> bool {
        // https://tc39.github.io/ecma262/#sec-resolveexport
        // section 15.2.1.16.3, step 6
        // If the "default" name is not resolved in the current module, we need to throw an error and stop resolution immediately,
        // Rationale to this error: A default export cannot be provided by an export *.
        VM& vm = exec->vm();
        auto scope = DECLARE_THROW_SCOPE(vm);
        if (query.exportName == vm.propertyNames->defaultKeyword.impl())
            return false;

        // Enqueue the task to gather the results of the stars.
        // And append the new Resolution frame to gather the local result of the stars.
        pendingTasks.append(Task { query, Type::GatherStars });
        foundStarLinks = true;
        frames.append(Resolution::notFound());

        // Enqueue the tasks in reverse order.
        for (auto iterator = query.moduleRecord->starExportEntries().rbegin(), end = query.moduleRecord->starExportEntries().rend(); iterator != end; ++iterator) {
            const RefPtr<UniquedStringImpl>& starModuleName = *iterator;
            AbstractModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));
            RETURN_IF_EXCEPTION(scope, false);
            pendingTasks.append(Task { ResolveQuery(importedModuleRecord, query.exportName.get()), Type::Query });
        }
        return true;
    };

    // Return the current resolution value of the top frame.
    auto currentTop = [&] () -> Resolution& {
        ASSERT(!frames.isEmpty());
        return frames.last();
    };

    // Merge the given resolution to the current resolution value of the top frame.
    // If there is ambiguity, return "false". When the "false" is returned, we should make the result "ambiguous".
    auto mergeToCurrentTop = [&] (const Resolution& resolution) -> bool {
        if (resolution.type == Resolution::Type::NotFound)
            return true;

        if (currentTop().type == Resolution::Type::NotFound) {
            currentTop() = resolution;
            return true;
        }

        if (currentTop().moduleRecord != resolution.moduleRecord || currentTop().localName != resolution.localName)
            return false;

        return true;
    };

    auto cacheResolutionForQuery = [] (const ResolveQuery& query, const Resolution& resolution) {
        ASSERT(resolution.type == Resolution::Type::Resolved);
        query.moduleRecord->cacheResolution(query.exportName.get(), resolution);
    };

    pendingTasks.append(Task { root, Type::Query });
    while (!pendingTasks.isEmpty()) {
        const Task task = pendingTasks.takeLast();
        const ResolveQuery& query = task.query;

        if (AbstractModuleRecordInternal::verbose)
            dataLog("    ", typeString(task.type), " ", task.query, "\n");

        switch (task.type) {
        case Type::Query: {
            AbstractModuleRecord* moduleRecord = query.moduleRecord;

            if (!resolveSet.add(task.query).isNewEntry)
                continue;

            //  5. Once we see star links, even if we have not yet traversed that star link path, we should disable caching.
            if (!moduleRecord->starExportEntries().isEmpty())
                foundStarLinks = true;

            //  4. Once we follow star links, we should not retrieve the result from the cache and should not cache the result.
            if (!foundStarLinks) {
                if (Optional<Resolution> cachedResolution = moduleRecord->tryGetCachedResolution(query.exportName.get())) {
                    if (!mergeToCurrentTop(*cachedResolution))
                        return Resolution::ambiguous();
                    continue;
                }
            }

            const Optional<ExportEntry> optionalExportEntry = moduleRecord->tryGetExportEntry(query.exportName.get());
            if (!optionalExportEntry) {
                // If there is no matched exported binding in the current module,
                // we need to look into the stars.
                bool success = resolveNonLocal(task.query);
                EXCEPTION_ASSERT(!scope.exception() || !success);
                if (!success)
                    return Resolution::error();
                continue;
            }

            const ExportEntry& exportEntry = *optionalExportEntry;
            switch (exportEntry.type) {
            case ExportEntry::Type::Local: {
                ASSERT(!exportEntry.localName.isNull());
                Resolution resolution { Resolution::Type::Resolved, moduleRecord, exportEntry.localName };
                //  2. A module that has resolved a local binding is always cacheable.
                cacheResolutionForQuery(query, resolution);
                if (!mergeToCurrentTop(resolution))
                    return Resolution::ambiguous();
                continue;
            }

            case ExportEntry::Type::Indirect: {
                AbstractModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName);
                RETURN_IF_EXCEPTION(scope, Resolution::error());

                // When the imported module does not produce any resolved binding, we need to look into the stars in the *current*
                // module. To do this, we append the `IndirectFallback` task to the task queue.
                pendingTasks.append(Task { query, Type::IndirectFallback });
                // And append the new Resolution frame to check the indirect export will be resolved or not.
                frames.append(Resolution::notFound());
                pendingTasks.append(Task { ResolveQuery(importedModuleRecord, exportEntry.importName), Type::Query });
                continue;
            }
            }
            break;
        }

        case Type::IndirectFallback: {
            Resolution resolution = frames.takeLast();

            if (resolution.type == Resolution::Type::NotFound) {
                // Indirect export entry does not produce any resolved binding.
                // So we will investigate the stars.
                bool success = resolveNonLocal(task.query);
                EXCEPTION_ASSERT(!scope.exception() || !success);
                if (!success)
                    return Resolution::error();
                continue;
            }

            ASSERT_WITH_MESSAGE(resolution.type == Resolution::Type::Resolved, "When we see Error and Ambiguous, we immediately return from this loop. So here, only Resolved comes.");

            //  3. If we don't follow any star links during the resolution, we can see all the traced nodes are cacheable.
            //  4. Once we follow star links, we should not retrieve the result from the cache and should not cache the result.
            if (!foundStarLinks)
                cacheResolutionForQuery(query, resolution);

            // If indirect export entry produces Resolved, we should merge it to the upper frame.
            // And do not investigate the stars of the current module.
            if (!mergeToCurrentTop(resolution))
                return Resolution::ambiguous();
            break;
        }

        case Type::GatherStars: {
            Resolution resolution = frames.takeLast();
            ASSERT_WITH_MESSAGE(resolution.type == Resolution::Type::Resolved || resolution.type == Resolution::Type::NotFound, "When we see Error and Ambiguous, we immediately return from this loop. So here, only Resolved and NotFound comes.");

            // Merge the star resolution to the upper frame.
            if (!mergeToCurrentTop(resolution))
                return Resolution::ambiguous();
            break;
        }
        }
    }

    ASSERT(frames.size() == 1);
    //  1. The starting point is always cacheable.
    if (frames[0].type == Resolution::Type::Resolved)
        cacheResolutionForQuery(root, frames[0]);
    return frames[0];
}

auto AbstractModuleRecord::resolveExport(ExecState* exec, const Identifier& exportName) -> Resolution
{
    // Look up the cached resolution first before entering the resolving loop, since the loop setup takes some cost.
    if (Optional<Resolution> cachedResolution = tryGetCachedResolution(exportName.impl()))
        return *cachedResolution;
    return resolveExportImpl(exec, ResolveQuery(this, exportName.impl()));
}

static void getExportedNames(ExecState* exec, AbstractModuleRecord* root, IdentifierSet& exportedNames)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    HashSet<AbstractModuleRecord*> exportStarSet;
    Vector<AbstractModuleRecord*, 8> pendingModules;

    pendingModules.append(root);

    while (!pendingModules.isEmpty()) {
        AbstractModuleRecord* moduleRecord = pendingModules.takeLast();
        if (exportStarSet.contains(moduleRecord))
            continue;
        exportStarSet.add(moduleRecord);

        for (const auto& pair : moduleRecord->exportEntries()) {
            const AbstractModuleRecord::ExportEntry& exportEntry = pair.value;
            if (moduleRecord == root || vm.propertyNames->defaultKeyword != exportEntry.exportName)
                exportedNames.add(exportEntry.exportName.impl());
        }

        for (const auto& starModuleName : moduleRecord->starExportEntries()) {
            AbstractModuleRecord* requestedModuleRecord = moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));
            RETURN_IF_EXCEPTION(scope, void());
            pendingModules.append(requestedModuleRecord);
        }
    }
}

JSModuleNamespaceObject* AbstractModuleRecord::getModuleNamespace(ExecState* exec)
{
    VM& vm = exec->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace
    if (m_moduleNamespaceObject)
        return m_moduleNamespaceObject.get();

    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
    IdentifierSet exportedNames;
    getExportedNames(exec, this, exportedNames);
    RETURN_IF_EXCEPTION(scope, nullptr);

    Vector<std::pair<Identifier, Resolution>> resolutions;
    for (auto& name : exportedNames) {
        Identifier ident = Identifier::fromUid(exec, name.get());
        const Resolution resolution = resolveExport(exec, ident);
        RETURN_IF_EXCEPTION(scope, nullptr);
        switch (resolution.type) {
        case Resolution::Type::NotFound:
            throwSyntaxError(exec, scope, makeString("Exported binding name '", String(name.get()), "' is not found."));
            return nullptr;

        case Resolution::Type::Error:
            throwSyntaxError(exec, scope, makeString("Exported binding name 'default' cannot be resolved by star export entries."));
            return nullptr;

        case Resolution::Type::Ambiguous:
            break;

        case Resolution::Type::Resolved:
            resolutions.append({ WTFMove(ident), resolution });
            break;
        }
    }

    auto* moduleNamespaceObject = JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, WTFMove(resolutions));
    RETURN_IF_EXCEPTION(scope, nullptr);
    m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);
    return moduleNamespaceObject;
}

void AbstractModuleRecord::link(ExecState* exec, JSValue scriptFetcher)
{
    VM& vm = exec->vm();
    if (auto* jsModuleRecord = jsDynamicCast<JSModuleRecord*>(vm, this))
        return jsModuleRecord->link(exec, scriptFetcher);
#if ENABLE(WEBASSEMBLY)
    if (auto* wasmModuleRecord = jsDynamicCast<WebAssemblyModuleRecord*>(vm, this))
        return wasmModuleRecord->link(exec, scriptFetcher, nullptr, Wasm::CreationMode::FromModuleLoader);
#endif
    RELEASE_ASSERT_NOT_REACHED();
}

JS_EXPORT_PRIVATE JSValue AbstractModuleRecord::evaluate(ExecState* exec)
{
    VM& vm = exec->vm();
    if (auto* jsModuleRecord = jsDynamicCast<JSModuleRecord*>(vm, this))
        return jsModuleRecord->evaluate(exec);
#if ENABLE(WEBASSEMBLY)
    if (auto* wasmModuleRecord = jsDynamicCast<WebAssemblyModuleRecord*>(vm, this))
        return wasmModuleRecord->evaluate(exec);
#endif
    RELEASE_ASSERT_NOT_REACHED();
    return jsUndefined();
}

static String printableName(const RefPtr<UniquedStringImpl>& uid)
{
    if (uid->isSymbol())
        return uid.get();
    return WTF::makeString("'", String(uid.get()), "'");
}

static String printableName(const Identifier& ident)
{
    return printableName(ident.impl());
}

void AbstractModuleRecord::dump()
{
    dataLog("\nAnalyzing ModuleRecord key(", printableName(m_moduleKey), ")\n");

    dataLog("    Dependencies: ", m_requestedModules.size(), " modules\n");
    for (const auto& moduleName : m_requestedModules)
        dataLog("      module(", printableName(moduleName), ")\n");

    dataLog("    Import: ", m_importEntries.size(), " entries\n");
    for (const auto& pair : m_importEntries) {
        const ImportEntry& importEntry = pair.value;
        dataLog("      import(", printableName(importEntry.importName), "), local(", printableName(importEntry.localName), "), module(", printableName(importEntry.moduleRequest), ")\n");
    }

    dataLog("    Export: ", m_exportEntries.size(), " entries\n");
    for (const auto& pair : m_exportEntries) {
        const ExportEntry& exportEntry = pair.value;
        switch (exportEntry.type) {
        case ExportEntry::Type::Local:
            dataLog("      [Local] ", "export(", printableName(exportEntry.exportName), "), local(", printableName(exportEntry.localName), ")\n");
            break;

        case ExportEntry::Type::Indirect:
            dataLog("      [Indirect] ", "export(", printableName(exportEntry.exportName), "), import(", printableName(exportEntry.importName), "), module(", printableName(exportEntry.moduleName), ")\n");
            break;
        }
    }
    for (const auto& moduleName : m_starExportEntries)
        dataLog("      [Star] module(", printableName(moduleName.get()), ")\n");
}

} // namespace JSC
