V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
modules.h
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  explicit ModuleDescriptor(Zone* zone)
23  : module_requests_(zone),
24  special_exports_(zone),
25  namespace_imports_(zone),
26  regular_exports_(zone),
27  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(const AstRawString* import_name,
36  const AstRawString* local_name,
37  const AstRawString* module_request,
38  const Scanner::Location loc,
39  const Scanner::Location specifier_loc, Zone* zone);
40 
41  // import * as x from "foo.js";
42  void AddStarImport(const AstRawString* local_name,
43  const AstRawString* module_request,
44  const Scanner::Location loc,
45  const Scanner::Location specifier_loc, Zone* zone);
46 
47  // import "foo.js";
48  // import {} from "foo.js";
49  // export {} from "foo.js"; (sic!)
50  void AddEmptyImport(const AstRawString* module_request,
51  const Scanner::Location specifier_loc);
52 
53  // export {x};
54  // export {x as y};
55  // export VariableStatement
56  // export Declaration
57  // export default ...
58  void AddExport(
59  const AstRawString* local_name, const AstRawString* export_name,
60  const Scanner::Location loc, Zone* zone);
61 
62  // export {x} from "foo.js";
63  // export {x as y} from "foo.js";
64  void AddExport(const AstRawString* export_name,
65  const AstRawString* import_name,
66  const AstRawString* module_request,
67  const Scanner::Location loc,
68  const Scanner::Location specifier_loc, Zone* zone);
69 
70  // export * from "foo.js";
71  void AddStarExport(const AstRawString* module_request,
72  const Scanner::Location loc,
73  const Scanner::Location specifier_loc, Zone* zone);
74 
75  // Check if module is well-formed and report error if not.
76  // Also canonicalize indirect exports.
77  bool Validate(ModuleScope* module_scope,
78  PendingCompilationErrorHandler* error_handler, Zone* zone);
79 
80  struct Entry : public ZoneObject {
81  Scanner::Location location;
82  const AstRawString* export_name;
83  const AstRawString* local_name;
84  const AstRawString* import_name;
85 
86  // The module_request value records the order in which modules are
87  // requested. It also functions as an index into the ModuleInfo's array of
88  // module specifiers and into the Module's array of requested modules. A
89  // negative value means no module request.
90  int module_request;
91 
92  // Import/export entries that are associated with a MODULE-allocated
93  // variable (i.e. regular_imports and regular_exports after Validate) use
94  // the cell_index value to encode the location of their cell. During
95  // variable allocation, this will be be copied into the variable's index
96  // field.
97  // Entries that are not associated with a MODULE-allocated variable have
98  // GetCellIndexKind(cell_index) == kInvalid.
99  int cell_index;
100 
101  // TODO(neis): Remove local_name component?
102  explicit Entry(Scanner::Location loc)
103  : location(loc),
104  export_name(nullptr),
105  local_name(nullptr),
106  import_name(nullptr),
107  module_request(-1),
108  cell_index(0) {}
109 
110  // (De-)serialization support.
111  // Note that the location value is not preserved as it's only needed by the
112  // parser. (A Deserialize'd entry has an invalid location.)
113  Handle<ModuleInfoEntry> Serialize(Isolate* isolate) const;
114  static Entry* Deserialize(Isolate* isolate, AstValueFactory* avfactory,
116  };
117 
118  enum CellIndexKind { kInvalid, kExport, kImport };
119  static CellIndexKind GetCellIndexKind(int cell_index);
120 
121  struct ModuleRequest {
122  int index;
123  int position;
124  ModuleRequest(int index, int position) : index(index), position(position) {}
125  };
126 
127  // Custom content-based comparer for the below maps, to keep them stable
128  // across parses.
130  bool operator()(const AstRawString* lhs, const AstRawString* rhs) const;
131  };
132 
139 
140  // Module requests.
141  const ModuleRequestMap& module_requests() const { return module_requests_; }
142 
143  // Namespace imports.
144  const ZoneVector<const Entry*>& namespace_imports() const {
145  return namespace_imports_;
146  }
147 
148  // All the remaining imports, indexed by local name.
149  const RegularImportMap& regular_imports() const { return regular_imports_; }
150 
151  // Star exports and explicitly indirect exports.
152  const ZoneVector<const Entry*>& special_exports() const {
153  return special_exports_;
154  }
155 
156  // All the remaining exports, indexed by local name.
157  // After canonicalization (see Validate), these are exactly the local exports.
158  const RegularExportMap& regular_exports() const { return regular_exports_; }
159 
160  void AddRegularExport(Entry* entry) {
161  DCHECK_NOT_NULL(entry->export_name);
162  DCHECK_NOT_NULL(entry->local_name);
163  DCHECK_NULL(entry->import_name);
164  DCHECK_LT(entry->module_request, 0);
165  regular_exports_.insert(std::make_pair(entry->local_name, entry));
166  }
167 
168  void AddSpecialExport(const Entry* entry, Zone* zone) {
169  DCHECK_NULL(entry->local_name);
170  DCHECK_LE(0, entry->module_request);
171  special_exports_.push_back(entry);
172  }
173 
174  void AddRegularImport(Entry* entry) {
175  DCHECK_NOT_NULL(entry->import_name);
176  DCHECK_NOT_NULL(entry->local_name);
177  DCHECK_NULL(entry->export_name);
178  DCHECK_LE(0, entry->module_request);
179  regular_imports_.insert(std::make_pair(entry->local_name, entry));
180  // We don't care if there's already an entry for this local name, as in that
181  // case we will report an error when declaring the variable.
182  }
183 
184  void AddNamespaceImport(const Entry* entry, Zone* zone) {
185  DCHECK_NULL(entry->import_name);
186  DCHECK_NULL(entry->export_name);
187  DCHECK_NOT_NULL(entry->local_name);
188  DCHECK_LE(0, entry->module_request);
189  namespace_imports_.push_back(entry);
190  }
191 
192  Handle<FixedArray> SerializeRegularExports(Isolate* isolate,
193  Zone* zone) const;
194  void DeserializeRegularExports(Isolate* isolate, AstValueFactory* avfactory,
195  Handle<ModuleInfo> module_info);
196 
197  private:
198  ModuleRequestMap module_requests_;
199  ZoneVector<const Entry*> special_exports_;
200  ZoneVector<const Entry*> namespace_imports_;
201  RegularExportMap regular_exports_;
202  RegularImportMap regular_imports_;
203 
204  // If there are multiple export entries with the same export name, return the
205  // last of them (in source order). Otherwise return nullptr.
206  const Entry* FindDuplicateExport(Zone* zone) const;
207 
208  // Find any implicitly indirect exports and make them explicit.
209  //
210  // An explicitly indirect export is an export entry arising from an export
211  // statement of the following form:
212  // export {a as c} from "X";
213  // An implicitly indirect export corresponds to
214  // export {b as c};
215  // in the presence of an import statement of the form
216  // import {a as b} from "X";
217  // This function finds such implicitly indirect export entries and rewrites
218  // them by filling in the import name and module request, as well as nulling
219  // out the local name. Effectively, it turns
220  // import {a as b} from "X"; export {b as c};
221  // into:
222  // import {a as b} from "X"; export {a as c} from "X";
223  // (The import entry is never deleted.)
224  void MakeIndirectExportsExplicit(Zone* zone);
225 
226  // Assign a cell_index of -1,-2,... to regular imports.
227  // Assign a cell_index of +1,+2,... to regular (local) exports.
228  // Assign a cell_index of 0 to anything else.
229  void AssignCellIndices();
230 
231  int AddModuleRequest(const AstRawString* specifier,
232  Scanner::Location specifier_loc) {
233  DCHECK_NOT_NULL(specifier);
234  int module_requests_count = static_cast<int>(module_requests_.size());
235  auto it = module_requests_
236  .insert(std::make_pair(specifier,
237  ModuleRequest(module_requests_count,
238  specifier_loc.beg_pos)))
239  .first;
240  return it->second.index;
241  }
242 };
243 
244 } // namespace internal
245 } // namespace v8
246 
247 #endif // V8_AST_MODULES_H_
Definition: libplatform.h:13