70a190f82c678d1861f506ed1d80f225bcc90e5e
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSModuleRecord.h
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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.
24  */
25
26 #ifndef JSModuleRecord_h
27 #define JSModuleRecord_h
28
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>
36
37 namespace JSC {
38
39 class JSModuleNamespaceObject;
40 class JSModuleEnvironment;
41 class JSMap;
42 class ModuleProgramExecutable;
43
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;
48 public:
49     typedef JSDestructibleObject Base;
50
51     struct ExportEntry {
52         enum class Type {
53             Local,
54             Namespace,
55             Indirect
56         };
57
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);
61
62         Type type;
63         Identifier exportName;
64         Identifier moduleName;
65         Identifier importName;
66         Identifier localName;
67         VariableEnvironmentEntry variable;
68     };
69
70     struct ImportEntry {
71         Identifier moduleRequest;
72         Identifier importName;
73         Identifier localName;
74
75         bool isNamespace(VM& vm) const
76         {
77             return importName == vm.propertyNames->timesIdentifier;
78         }
79     };
80
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;
84
85     DECLARE_EXPORT_INFO;
86
87     static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype)
88     {
89         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
90     }
91
92     static JSModuleRecord* create(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
93     {
94         JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
95         instance->finishCreation(vm);
96         return instance;
97     }
98
99     void appendRequestedModule(const Identifier&);
100     void addStarExportEntry(const Identifier&);
101     void addImportEntry(const ImportEntry&);
102     void addExportEntry(const ExportEntry&);
103
104     Optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName);
105     Optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName);
106
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; }
113
114     const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }
115     const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }
116
117     void dump();
118
119     JSModuleEnvironment* moduleEnvironment()
120     {
121         ASSERT(m_moduleEnvironment);
122         return m_moduleEnvironment.get();
123     }
124
125     void link(ExecState*);
126     JSValue execute(ExecState*);
127
128     ModuleProgramExecutable* moduleProgramExecutable() const { return m_moduleProgramExecutable.get(); }
129
130     struct Resolution {
131         enum class Type { Resolved, NotFound, Ambiguous, Error };
132
133         static Resolution notFound();
134         static Resolution error();
135         static Resolution ambiguous();
136
137         Type type;
138         JSModuleRecord* moduleRecord;
139         Identifier localName;
140     };
141
142     Resolution resolveExport(ExecState*, const Identifier& exportName);
143     Resolution resolveImport(ExecState*, const Identifier& localName);
144
145     JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);
146
147 private:
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)
154     {
155     }
156
157     void finishCreation(VM&);
158
159     JSModuleNamespaceObject* getModuleNamespace(ExecState*);
160
161     static void visitChildren(JSCell*, SlotVisitor&);
162     static void destroy(JSCell*);
163
164     void instantiateDeclarations(ExecState*, ModuleProgramExecutable*);
165
166     // The loader resolves the given module name to the module key. The module key is the unique value to represent this module.
167     Identifier m_moduleKey;
168
169     SourceCode m_sourceCode;
170
171     VariableEnvironment m_declaredVariables;
172     VariableEnvironment m_lexicalVariables;
173
174     // Currently, we don't keep the occurrence order of the import / export entries.
175     // So, we does not guarantee the order of the errors.
176     // e.g. The import declaration that occurr later than the another import declaration may
177     //      throw the error even if the former import declaration also has the invalid content.
178     //
179     //      import ... // (1) this has some invalid content.
180     //      import ... // (2) this also has some invalid content.
181     //
182     //      In the above case, (2) may throw the error earlier than (1)
183     //
184     // But, in the all cases, we will throw the syntax error. So except for the content of the syntax error,
185     // there are no difference.
186
187     // Map localName -> ImportEntry.
188     ImportEntries m_importEntries;
189
190     // Map exportName -> ExportEntry.
191     ExportEntries m_exportEntries;
192
193     // Save the occurrence order since resolveExport requires it.
194     OrderedIdentifierSet m_starExportEntries;
195
196     // Save the occurrence order since the module loader loads and runs the modules in this order.
197     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation
198     OrderedIdentifierSet m_requestedModules;
199
200     WriteBarrier<JSMap> m_dependenciesMap;
201
202     WriteBarrier<ModuleProgramExecutable> m_moduleProgramExecutable;
203     WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;
204     WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
205 };
206
207 } // namespace JSC
208
209 #endif // JSModuleRecord_h