/*
 * Copyright (C) 2015-2021 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());
}

template<typename Visitor>
void AbstractModuleRecord::visitChildrenImpl(JSCell* cell, Visitor& 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);
}

DEFINE_VISIT_CHILDREN(AbstractModuleRecord);

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
