2 * Copyright (C) 2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #ifndef JSModuleRecord_h
27 #define JSModuleRecord_h
29 #include "Identifier.h"
30 #include "JSDestructibleObject.h"
31 #include "SourceCode.h"
32 #include "VariableEnvironment.h"
33 #include <wtf/HashMap.h>
34 #include <wtf/ListHashSet.h>
35 #include <wtf/Optional.h>
39 class JSModuleNamespaceObject;
40 class JSModuleEnvironment;
42 class ModuleProgramExecutable;
44 // Based on the Source Text Module Record
45 // http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
46 class JSModuleRecord : public JSDestructibleObject {
47 friend class LLIntOffsetsExtractor;
49 typedef JSDestructibleObject Base;
58 static ExportEntry createLocal(const Identifier& exportName, const Identifier& localName, const VariableEnvironmentEntry&);
59 static ExportEntry createNamespace(const Identifier& exportName, const Identifier& moduleName);
60 static ExportEntry createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName);
63 Identifier exportName;
64 Identifier moduleName;
65 Identifier importName;
67 VariableEnvironmentEntry variable;
71 Identifier moduleRequest;
72 Identifier importName;
75 bool isNamespace(VM& vm) const
77 return importName == vm.propertyNames->timesIdentifier;
81 typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet;
82 typedef HashMap<RefPtr<UniquedStringImpl>, ImportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ImportEntries;
83 typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportEntries;
87 static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
89 return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
92 static JSModuleRecord* create(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
94 JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
95 instance->finishCreation(vm);
99 void appendRequestedModule(const Identifier&);
100 void addStarExportEntry(const Identifier&);
101 void addImportEntry(const ImportEntry&);
102 void addExportEntry(const ExportEntry&);
104 Optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName);
105 Optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName);
107 const SourceCode& sourceCode() const { return m_sourceCode; }
108 const Identifier& moduleKey() const { return m_moduleKey; }
109 const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; }
110 const ExportEntries& exportEntries() const { return m_exportEntries; }
111 const ImportEntries& importEntries() const { return m_importEntries; }
112 const OrderedIdentifierSet& starExportEntries() const { return m_starExportEntries; }
114 const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }
115 const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }
119 JSModuleEnvironment* moduleEnvironment()
121 ASSERT(m_moduleEnvironment);
122 return m_moduleEnvironment.get();
125 void link(ExecState*);
126 JSValue execute(ExecState*);
128 ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); }
131 enum class Type { Resolved, NotFound, Ambiguous, Error };
133 static Resolution notFound();
134 static Resolution error();
135 static Resolution ambiguous();
138 JSModuleRecord* moduleRecord;
139 Identifier localName;
142 Resolution resolveExport(ExecState*, const Identifier& exportName);
143 Resolution resolveImport(ExecState*, const Identifier& localName);
145 JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);
148 JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
149 : Base(vm, structure)
150 , m_moduleKey(moduleKey)
151 , m_sourceCode(sourceCode)
152 , m_declaredVariables(declaredVariables)
153 , m_lexicalVariables(lexicalVariables)
157 void finishCreation(VM&);
159 JSModuleNamespaceObject* getModuleNamespace(ExecState*);
161 static void visitChildren(JSCell*, SlotVisitor&);
162 static void destroy(JSCell*);
164 void instantiateDeclarations(ExecState*, ModuleProgramExecutable*);
167 static Resolution resolveExportImpl(ExecState*, const ResolveQuery&);
168 Optional<Resolution> tryGetCachedResolution(UniquedStringImpl* exportName);
169 void cacheResolution(UniquedStringImpl* exportName, const Resolution&);
171 // The loader resolves the given module name to the module key. The module key is the unique value to represent this module.
172 Identifier m_moduleKey;
174 SourceCode m_sourceCode;
176 VariableEnvironment m_declaredVariables;
177 VariableEnvironment m_lexicalVariables;
179 // Currently, we don't keep the occurrence order of the import / export entries.
180 // So, we does not guarantee the order of the errors.
181 // e.g. The import declaration that occurr later than the another import declaration may
182 // throw the error even if the former import declaration also has the invalid content.
184 // import ... // (1) this has some invalid content.
185 // import ... // (2) this also has some invalid content.
187 // In the above case, (2) may throw the error earlier than (1)
189 // But, in all the cases, we will throw the syntax error. So except for the content of the syntax error,
190 // there are no difference.
192 // Map localName -> ImportEntry.
193 ImportEntries m_importEntries;
195 // Map exportName -> ExportEntry.
196 ExportEntries m_exportEntries;
198 // Save the occurrence order since resolveExport requires it.
199 OrderedIdentifierSet m_starExportEntries;
201 // Save the occurrence order since the module loader loads and runs the modules in this order.
202 // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation
203 OrderedIdentifierSet m_requestedModules;
205 WriteBarrier<JSMap> m_dependenciesMap;
207 WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable;
208 WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;
209 WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
211 // We assume that all the JSModuleRecord are retained by ModuleLoaderObject's registry.
212 // So here, we don't visit each object for GC. The resolution cache map caches the once
213 // looked up correctly resolved resolution, since (1) we rarely looked up the non-resolved one,
214 // and (2) if we cache all the attempts the size of the map becomes infinitely large.
215 typedef HashMap<RefPtr<UniquedStringImpl>, Resolution, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> Resolutions;
216 Resolutions m_resolutionCache;
221 #endif // JSModuleRecord_h