Line data Source code
1 : // Copyright 2012 the V8 project authors. All rights reserved.
2 : // Use of this source code is governed by a BSD-style license that can be
3 : // found in the LICENSE file.
4 :
5 : #ifndef V8_AST_MODULES_H_
6 : #define V8_AST_MODULES_H_
7 :
8 : #include "src/parsing/scanner.h" // Only for Scanner::Location.
9 : #include "src/zone/zone-containers.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 :
14 :
15 : class AstRawString;
16 : class ModuleInfo;
17 : class ModuleInfoEntry;
18 : class PendingCompilationErrorHandler;
19 :
20 : class ModuleDescriptor : public ZoneObject {
21 : public:
22 33608 : explicit ModuleDescriptor(Zone* zone)
23 : : module_requests_(zone),
24 : special_exports_(1, zone),
25 : namespace_imports_(1, zone),
26 : regular_exports_(zone),
27 67216 : regular_imports_(zone) {}
28 :
29 : // The following Add* methods are high-level convenience functions for use by
30 : // the parser.
31 :
32 : // import x from "foo.js";
33 : // import {x} from "foo.js";
34 : // import {x as y} from "foo.js";
35 : void AddImport(
36 : const AstRawString* import_name, const AstRawString* local_name,
37 : const AstRawString* module_request, const Scanner::Location loc,
38 : Zone* zone);
39 :
40 : // import * as x from "foo.js";
41 : void AddStarImport(
42 : const AstRawString* local_name, const AstRawString* module_request,
43 : const Scanner::Location loc, Zone* zone);
44 :
45 : // import "foo.js";
46 : // import {} from "foo.js";
47 : // export {} from "foo.js"; (sic!)
48 : void AddEmptyImport(const AstRawString* module_request);
49 :
50 : // export {x};
51 : // export {x as y};
52 : // export VariableStatement
53 : // export Declaration
54 : // export default ...
55 : void AddExport(
56 : const AstRawString* local_name, const AstRawString* export_name,
57 : const Scanner::Location loc, Zone* zone);
58 :
59 : // export {x} from "foo.js";
60 : // export {x as y} from "foo.js";
61 : void AddExport(
62 : const AstRawString* export_name, const AstRawString* import_name,
63 : const AstRawString* module_request, const Scanner::Location loc,
64 : Zone* zone);
65 :
66 : // export * from "foo.js";
67 : void AddStarExport(
68 : const AstRawString* module_request, const Scanner::Location loc,
69 : Zone* zone);
70 :
71 : // Check if module is well-formed and report error if not.
72 : // Also canonicalize indirect exports.
73 : bool Validate(ModuleScope* module_scope,
74 : PendingCompilationErrorHandler* error_handler, Zone* zone);
75 :
76 : struct Entry : public ZoneObject {
77 : Scanner::Location location;
78 : const AstRawString* export_name;
79 : const AstRawString* local_name;
80 : const AstRawString* import_name;
81 :
82 : // The module_request value records the order in which modules are
83 : // requested. It also functions as an index into the ModuleInfo's array of
84 : // module specifiers and into the Module's array of requested modules. A
85 : // negative value means no module request.
86 : int module_request;
87 :
88 : // Import/export entries that are associated with a MODULE-allocated
89 : // variable (i.e. regular_imports and regular_exports after Validate) use
90 : // the cell_index value to encode the location of their cell. During
91 : // variable allocation, this will be be copied into the variable's index
92 : // field.
93 : // Entries that are not associated with a MODULE-allocated variable have
94 : // GetCellIndexKind(cell_index) == kInvalid.
95 : int cell_index;
96 :
97 : // TODO(neis): Remove local_name component?
98 : explicit Entry(Scanner::Location loc)
99 : : location(loc),
100 : export_name(nullptr),
101 : local_name(nullptr),
102 : import_name(nullptr),
103 : module_request(-1),
104 9310 : cell_index(0) {}
105 :
106 : // (De-)serialization support.
107 : // Note that the location value is not preserved as it's only needed by the
108 : // parser. (A Deserialize'd entry has an invalid location.)
109 : Handle<ModuleInfoEntry> Serialize(Isolate* isolate) const;
110 : static Entry* Deserialize(Isolate* isolate, AstValueFactory* avfactory,
111 : Handle<ModuleInfoEntry> entry);
112 : };
113 :
114 : enum CellIndexKind { kInvalid, kExport, kImport };
115 : static CellIndexKind GetCellIndexKind(int cell_index);
116 :
117 : // Module requests.
118 : const ZoneMap<const AstRawString*, int>& module_requests() const {
119 : return module_requests_;
120 : }
121 :
122 : // Namespace imports.
123 : const ZoneList<const Entry*>& namespace_imports() const {
124 : return namespace_imports_;
125 : }
126 :
127 : // All the remaining imports, indexed by local name.
128 : const ZoneMap<const AstRawString*, Entry*>& regular_imports() const {
129 : return regular_imports_;
130 : }
131 :
132 : // Star exports and explicitly indirect exports.
133 : const ZoneList<const Entry*>& special_exports() const {
134 : return special_exports_;
135 : }
136 :
137 : // All the remaining exports, indexed by local name.
138 : // After canonicalization (see Validate), these are exactly the local exports.
139 : const ZoneMultimap<const AstRawString*, Entry*>& regular_exports() const {
140 : return regular_exports_;
141 : }
142 :
143 : void AddRegularExport(Entry* entry) {
144 : DCHECK_NOT_NULL(entry->export_name);
145 : DCHECK_NOT_NULL(entry->local_name);
146 : DCHECK_NULL(entry->import_name);
147 : DCHECK_LT(entry->module_request, 0);
148 10770 : regular_exports_.insert(std::make_pair(entry->local_name, entry));
149 : }
150 :
151 : void AddSpecialExport(const Entry* entry, Zone* zone) {
152 : DCHECK_NULL(entry->local_name);
153 : DCHECK_LE(0, entry->module_request);
154 : special_exports_.Add(entry, zone);
155 : }
156 :
157 : void AddRegularImport(Entry* entry) {
158 : DCHECK_NOT_NULL(entry->import_name);
159 : DCHECK_NOT_NULL(entry->local_name);
160 : DCHECK_NULL(entry->export_name);
161 : DCHECK_LE(0, entry->module_request);
162 6662 : regular_imports_.insert(std::make_pair(entry->local_name, entry));
163 : // We don't care if there's already an entry for this local name, as in that
164 : // case we will report an error when declaring the variable.
165 : }
166 :
167 : void AddNamespaceImport(const Entry* entry, Zone* zone) {
168 : DCHECK_NULL(entry->import_name);
169 : DCHECK_NULL(entry->export_name);
170 : DCHECK_NOT_NULL(entry->local_name);
171 : DCHECK_LE(0, entry->module_request);
172 : namespace_imports_.Add(entry, zone);
173 : }
174 :
175 : Handle<FixedArray> SerializeRegularExports(Isolate* isolate,
176 : Zone* zone) const;
177 : void DeserializeRegularExports(Isolate* isolate, AstValueFactory* avfactory,
178 : Handle<ModuleInfo> module_info);
179 :
180 : private:
181 : // TODO(neis): Use STL datastructure instead of ZoneList?
182 : ZoneMap<const AstRawString*, int> module_requests_;
183 : ZoneList<const Entry*> special_exports_;
184 : ZoneList<const Entry*> namespace_imports_;
185 : ZoneMultimap<const AstRawString*, Entry*> regular_exports_;
186 : ZoneMap<const AstRawString*, Entry*> regular_imports_;
187 :
188 : // If there are multiple export entries with the same export name, return the
189 : // last of them (in source order). Otherwise return nullptr.
190 : const Entry* FindDuplicateExport(Zone* zone) const;
191 :
192 : // Find any implicitly indirect exports and make them explicit.
193 : //
194 : // An explicitly indirect export is an export entry arising from an export
195 : // statement of the following form:
196 : // export {a as c} from "X";
197 : // An implicitly indirect export corresponds to
198 : // export {b as c};
199 : // in the presence of an import statement of the form
200 : // import {a as b} from "X";
201 : // This function finds such implicitly indirect export entries and rewrites
202 : // them by filling in the import name and module request, as well as nulling
203 : // out the local name. Effectively, it turns
204 : // import {a as b} from "X"; export {b as c};
205 : // into:
206 : // import {a as b} from "X"; export {a as c} from "X";
207 : // (The import entry is never deleted.)
208 : void MakeIndirectExportsExplicit(Zone* zone);
209 :
210 : // Assign a cell_index of -1,-2,... to regular imports.
211 : // Assign a cell_index of +1,+2,... to regular (local) exports.
212 : // Assign a cell_index of 0 to anything else.
213 : void AssignCellIndices();
214 :
215 1203 : int AddModuleRequest(const AstRawString* specifier) {
216 : DCHECK_NOT_NULL(specifier);
217 1203 : int module_requests_count = static_cast<int>(module_requests_.size());
218 : auto it = module_requests_
219 2406 : .insert(std::make_pair(specifier, module_requests_count))
220 : .first;
221 1203 : return it->second;
222 : }
223 : };
224 :
225 : } // namespace internal
226 : } // namespace v8
227 :
228 : #endif // V8_AST_MODULES_H_
|