/*
 * Copyright (C) 2015-2019 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 "JSCInlines.h"
#include "JSMap.h"
#include "JSModuleEnvironment.h"
#include "JSModuleNamespaceObject.h"
#include "JSModuleRecord.h"
#include "WebAssemblyModuleRecord.h"
#include <wtf/Optional.h>

namespace JSC {
namespace AbstractModuleRecordInternal {
static constexpr 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::finishCreation(JSGlobalObject* globalObject, VM& vm)
{
    Base::finishCreation(vm);
    ASSERT(inherits(vm, info()));

    auto scope = DECLARE_THROW_SCOPE(vm);
    JSMap* map = JSMap::create(globalObject, vm, globalObject->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);
    ASSERT_GC_OBJECT_INHERITS(thisObject, info());
    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::ExportEntry::createNamespace(const Identifier& exportName, const Identifier& moduleName) -> ExportEntry
{
    return ExportEntry { Type::Namespace, exportName, moduleName, Identifier(), 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(JSGlobalObject* globalObject, const Identifier& moduleName)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);
    JSValue moduleNameValue = identifierToJSValue(vm, moduleName);
    JSValue entry = m_dependenciesMap->JSMap::get(globalObject, moduleNameValue);
    RETURN_IF_EXCEPTION(scope, nullptr);
    RELEASE_AND_RETURN(scope, jsCast<AbstractModuleRecord*>(entry.get(globalObject, Identifier::fromString(vm, "module"))));
}

auto AbstractModuleRecord::resolveImport(JSGlobalObject* globalObject, const Identifier& localName) -> Resolution
{
    VM& vm = globalObject->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(globalObject, importEntry.moduleRequest);
    RETURN_IF_EXCEPTION(scope, Resolution::error());
    return importedModule->resolveExport(globalObject, importEntry.importName);
}

struct AbstractModuleRecord::ResolveQuery {
    struct Hash {
        static unsigned hash(const ResolveQuery&);
        static bool equal(const ResolveQuery&, const ResolveQuery&);
        static constexpr 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(JSGlobalObject* globalObject, const ResolveQuery& root) -> Resolution
{
    VM& vm = globalObject->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 = globalObject->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(globalObject, Identifier::fromUid(vm, 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(globalObject, 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;
            }

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

                Resolution resolution { Resolution::Type::Resolved, importedModuleRecord, vm.propertyNames->starNamespacePrivateName };
                //  2. A module that has resolved a module namespace binding is always cacheable.
                cacheResolutionForQuery(query, resolution);
                if (!mergeToCurrentTop(resolution))
                    return Resolution::ambiguous();
                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(JSGlobalObject* globalObject, 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(globalObject, ResolveQuery(this, exportName.impl()));
}

static void getExportedNames(JSGlobalObject* globalObject, AbstractModuleRecord* root, IdentifierSet& exportedNames)
{
    VM& vm = globalObject->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(globalObject, Identifier::fromUid(vm, starModuleName.get()));
            RETURN_IF_EXCEPTION(scope, void());
            pendingModules.append(requestedModuleRecord);
        }
    }
}

JSModuleNamespaceObject* AbstractModuleRecord::getModuleNamespace(JSGlobalObject* globalObject)
{
    VM& vm = globalObject->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();

    IdentifierSet exportedNames;
    getExportedNames(globalObject, this, exportedNames);
    RETURN_IF_EXCEPTION(scope, nullptr);

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

        case Resolution::Type::Error:
            throwSyntaxError(globalObject, 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(globalObject, globalObject->moduleNamespaceObjectStructure(), this, WTFMove(resolutions));
    RETURN_IF_EXCEPTION(scope, nullptr);

    // Materialize *namespace* slot with module namespace object unless the module environment is not yet materialized, in which case we'll do it in setModuleEnvironment
    if (m_moduleEnvironment) {
        bool putResult = false;
        constexpr bool shouldThrowReadOnlyError = false;
        constexpr bool ignoreReadOnlyErrors = true;
        symbolTablePutTouchWatchpointSet(m_moduleEnvironment.get(), globalObject, vm.propertyNames->starNamespacePrivateName, moduleNamespaceObject, shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
        RETURN_IF_EXCEPTION(scope, nullptr);
    }
    m_moduleNamespaceObject.set(vm, this, moduleNamespaceObject);

    return moduleNamespaceObject;
}

void AbstractModuleRecord::setModuleEnvironment(JSGlobalObject* globalObject, JSModuleEnvironment* moduleEnvironment)
{
    VM& vm = globalObject->vm();
    auto scope = DECLARE_THROW_SCOPE(vm);

    ASSERT(!m_moduleEnvironment);
    // If module namespace object is materialized, we will materialize *namespace* slot too.
    if (m_moduleNamespaceObject) {
        bool putResult = false;
        constexpr bool shouldThrowReadOnlyError = false;
        constexpr bool ignoreReadOnlyErrors = true;
        symbolTablePutTouchWatchpointSet(moduleEnvironment, globalObject, vm.propertyNames->starNamespacePrivateName, m_moduleNamespaceObject.get(), shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
        RETURN_IF_EXCEPTION(scope, void());
    }
    m_moduleEnvironment.set(vm, this, moduleEnvironment);
}

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

JS_EXPORT_PRIVATE JSValue AbstractModuleRecord::evaluate(JSGlobalObject* globalObject)
{
    VM& vm = globalObject->vm();
    if (auto* jsModuleRecord = jsDynamicCast<JSModuleRecord*>(vm, this))
        return jsModuleRecord->evaluate(globalObject);
#if ENABLE(WEBASSEMBLY)
    if (auto* wasmModuleRecord = jsDynamicCast<WebAssemblyModuleRecord*>(vm, this))
        return wasmModuleRecord->evaluate(globalObject);
#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;

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

} // namespace JSC
