#ifndef JSModuleRecord_h
#define JSModuleRecord_h
#include "Identifier.h"
#include "JSDestructibleObject.h"
#include "SourceCode.h"
#include "VariableEnvironment.h"
#include <wtf/HashMap.h>
#include <wtf/ListHashSet.h>
#include <wtf/Optional.h>
namespace JSC {
class JSModuleNamespaceObject;
class JSModuleEnvironment;
class JSMap;
class ModuleProgramExecutable;
class JSModuleRecord : public JSDestructibleObject {
friend class LLIntOffsetsExtractor;
public:
typedef JSDestructibleObject Base;
struct ExportEntry {
enum class Type {
Local,
Indirect
};
static ExportEntry createLocal(const Identifier& exportName, const Identifier& localName);
static ExportEntry createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName);
Type type;
Identifier exportName;
Identifier moduleName;
Identifier importName;
Identifier localName;
};
struct ImportEntry {
Identifier moduleRequest;
Identifier importName;
Identifier localName;
bool isNamespace(VM& vm) const
{
return importName == vm.propertyNames->timesIdentifier;
}
};
typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet;
typedef HashMap<RefPtr<UniquedStringImpl>, ImportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ImportEntries;
typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportEntries;
DECLARE_EXPORT_INFO;
static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
{
return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
}
static JSModuleRecord* create(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
{
JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
instance->finishCreation(vm);
return instance;
}
void appendRequestedModule(const Identifier&);
void addStarExportEntry(const Identifier&);
void addImportEntry(const ImportEntry&);
void addExportEntry(const ExportEntry&);
Optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName);
Optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName);
const SourceCode& sourceCode() const { return m_sourceCode; }
const Identifier& moduleKey() const { return m_moduleKey; }
const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; }
const ExportEntries& exportEntries() const { return m_exportEntries; }
const ImportEntries& importEntries() const { return m_importEntries; }
const OrderedIdentifierSet& starExportEntries() const { return m_starExportEntries; }
const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }
const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }
void dump();
JSModuleEnvironment* moduleEnvironment()
{
ASSERT(m_moduleEnvironment);
return m_moduleEnvironment.get();
}
void link(ExecState*);
JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); }
struct Resolution {
enum class Type { Resolved, NotFound, Ambiguous, Error };
static Resolution notFound();
static Resolution error();
static Resolution ambiguous();
Type type;
JSModuleRecord* moduleRecord;
Identifier localName;
};
Resolution resolveExport(ExecState*, const Identifier& exportName);
Resolution resolveImport(ExecState*, const Identifier& localName);
JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);
private:
JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
: Base(vm, structure)
, m_moduleKey(moduleKey)
, m_sourceCode(sourceCode)
, m_declaredVariables(declaredVariables)
, m_lexicalVariables(lexicalVariables)
{
}
void finishCreation(VM&);
JSModuleNamespaceObject* getModuleNamespace(ExecState*);
static void visitChildren(JSCell*, SlotVisitor&);
static void destroy(JSCell*);
void instantiateDeclarations(ExecState*, ModuleProgramExecutable*);
struct ResolveQuery;
static Resolution resolveExportImpl(ExecState*, const ResolveQuery&);
Optional<Resolution> tryGetCachedResolution(UniquedStringImpl* exportName);
void cacheResolution(UniquedStringImpl* exportName, const Resolution&);
Identifier m_moduleKey;
SourceCode m_sourceCode;
VariableEnvironment m_declaredVariables;
VariableEnvironment m_lexicalVariables;
ImportEntries m_importEntries;
ExportEntries m_exportEntries;
OrderedIdentifierSet m_starExportEntries;
OrderedIdentifierSet m_requestedModules;
WriteBarrier<JSMap> m_dependenciesMap;
WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable;
WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;
WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
typedef HashMap<RefPtr<UniquedStringImpl>, Resolution, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> Resolutions;
Resolutions m_resolutionCache;
};
}
#endif // JSModuleRecord_h