[WebAssembly][Modules] Prototype wasm import
[WebKit-https.git] / Source / JavaScriptCore / runtime / AbstractModuleRecord.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 #pragma once
27
28 #include "Identifier.h"
29 #include "JSDestructibleObject.h"
30 #include <wtf/HashMap.h>
31 #include <wtf/ListHashSet.h>
32 #include <wtf/Optional.h>
33
34 namespace JSC {
35
36 class JSModuleEnvironment;
37 class JSModuleNamespaceObject;
38 class JSMap;
39
40 // Based on the Source Text Module Record
41 // http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
42 class AbstractModuleRecord : public JSDestructibleObject {
43     friend class LLIntOffsetsExtractor;
44 public:
45     typedef JSDestructibleObject Base;
46
47     // https://tc39.github.io/ecma262/#sec-source-text-module-records
48     struct ExportEntry {
49         enum class Type {
50             Local,
51             Indirect
52         };
53
54         static ExportEntry createLocal(const Identifier& exportName, const Identifier& localName);
55         static ExportEntry createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName);
56
57         Type type;
58         Identifier exportName;
59         Identifier moduleName;
60         Identifier importName;
61         Identifier localName;
62     };
63
64     struct ImportEntry {
65         Identifier moduleRequest;
66         Identifier importName;
67         Identifier localName;
68
69         bool isNamespace(VM& vm) const
70         {
71             return importName == vm.propertyNames->timesIdentifier;
72         }
73     };
74
75     typedef WTF::ListHashSet<RefPtr<UniquedStringImpl>, IdentifierRepHash> OrderedIdentifierSet;
76     typedef HashMap<RefPtr<UniquedStringImpl>, ImportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ImportEntries;
77     typedef HashMap<RefPtr<UniquedStringImpl>, ExportEntry, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> ExportEntries;
78
79     DECLARE_EXPORT_INFO;
80
81     void appendRequestedModule(const Identifier&);
82     void addStarExportEntry(const Identifier&);
83     void addImportEntry(const ImportEntry&);
84     void addExportEntry(const ExportEntry&);
85
86     std::optional<ImportEntry> tryGetImportEntry(UniquedStringImpl* localName);
87     std::optional<ExportEntry> tryGetExportEntry(UniquedStringImpl* exportName);
88
89     const Identifier& moduleKey() const { return m_moduleKey; }
90     const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; }
91     const ExportEntries& exportEntries() const { return m_exportEntries; }
92     const ImportEntries& importEntries() const { return m_importEntries; }
93     const OrderedIdentifierSet& starExportEntries() const { return m_starExportEntries; }
94
95     void dump();
96
97     struct Resolution {
98         enum class Type { Resolved, NotFound, Ambiguous, Error };
99
100         static Resolution notFound();
101         static Resolution error();
102         static Resolution ambiguous();
103
104         Type type;
105         AbstractModuleRecord* moduleRecord;
106         Identifier localName;
107     };
108
109     Resolution resolveExport(ExecState*, const Identifier& exportName);
110     Resolution resolveImport(ExecState*, const Identifier& localName);
111
112     AbstractModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);
113
114     JSModuleNamespaceObject* getModuleNamespace(ExecState*);
115     
116     JSModuleEnvironment* moduleEnvironment()
117     {
118         ASSERT(m_moduleEnvironment);
119         return m_moduleEnvironment.get();
120     }
121
122     void link(ExecState*, JSValue scriptFetcher);
123     JS_EXPORT_PRIVATE JSValue evaluate(ExecState*);
124
125 protected:
126     AbstractModuleRecord(VM&, Structure*, const Identifier&);
127     void finishCreation(ExecState*, VM&);
128
129     static void visitChildren(JSCell*, SlotVisitor&);
130     static void destroy(JSCell*);
131
132     WriteBarrier<JSModuleEnvironment> m_moduleEnvironment;
133
134 private:
135     struct ResolveQuery;
136     static Resolution resolveExportImpl(ExecState*, const ResolveQuery&);
137     std::optional<Resolution> tryGetCachedResolution(UniquedStringImpl* exportName);
138     void cacheResolution(UniquedStringImpl* exportName, const Resolution&);
139
140     // The loader resolves the given module name to the module key. The module key is the unique value to represent this module.
141     Identifier m_moduleKey;
142
143     // Currently, we don't keep the occurrence order of the import / export entries.
144     // So, we does not guarantee the order of the errors.
145     // e.g. The import declaration that occurr later than the another import declaration may
146     //      throw the error even if the former import declaration also has the invalid content.
147     //
148     //      import ... // (1) this has some invalid content.
149     //      import ... // (2) this also has some invalid content.
150     //
151     //      In the above case, (2) may throw the error earlier than (1)
152     //
153     // But, in all the cases, we will throw the syntax error. So except for the content of the syntax error,
154     // there are no difference.
155
156     // Map localName -> ImportEntry.
157     ImportEntries m_importEntries;
158
159     // Map exportName -> ExportEntry.
160     ExportEntries m_exportEntries;
161
162     // Save the occurrence order since resolveExport requires it.
163     OrderedIdentifierSet m_starExportEntries;
164
165     // Save the occurrence order since the module loader loads and runs the modules in this order.
166     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation
167     OrderedIdentifierSet m_requestedModules;
168
169     WriteBarrier<JSMap> m_dependenciesMap;
170     
171     WriteBarrier<JSModuleNamespaceObject> m_moduleNamespaceObject;
172
173     // We assume that all the AbstractModuleRecord are retained by JSModuleLoader's registry.
174     // So here, we don't visit each object for GC. The resolution cache map caches the once
175     // looked up correctly resolved resolution, since (1) we rarely looked up the non-resolved one,
176     // and (2) if we cache all the attempts the size of the map becomes infinitely large.
177     typedef HashMap<RefPtr<UniquedStringImpl>, Resolution, IdentifierRepHash, HashTraits<RefPtr<UniquedStringImpl>>> Resolutions;
178     Resolutions m_resolutionCache;
179 };
180
181 } // namespace JSC