v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
modules.cc
Go to the documentation of this file.
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#include "src/ast/modules.h"
6
8#include "src/ast/scopes.h"
14
15namespace v8 {
16namespace internal {
17
19 const AstRawString* lhs, const AstRawString* rhs) const {
20 return AstRawString::Compare(lhs, rhs) < 0;
21}
22
24 const AstModuleRequest* lhs, const AstModuleRequest* rhs) const {
25 if (int specifier_comparison =
27 return specifier_comparison < 0;
28 }
29
30 auto lhsIt = lhs->import_attributes()->cbegin();
31 auto rhsIt = rhs->import_attributes()->cbegin();
32 for (; lhsIt != lhs->import_attributes()->cend() &&
33 rhsIt != rhs->import_attributes()->cend();
34 ++lhsIt, ++rhsIt) {
35 if (int assertion_key_comparison =
36 AstRawString::Compare(lhsIt->first, rhsIt->first)) {
37 return assertion_key_comparison < 0;
38 }
39
40 if (int assertion_value_comparison =
41 AstRawString::Compare(lhsIt->second.first, rhsIt->second.first)) {
42 return assertion_value_comparison < 0;
43 }
44 }
45
46 if (lhs->import_attributes()->size() != rhs->import_attributes()->size()) {
47 return (lhs->import_attributes()->size() <
48 rhs->import_attributes()->size());
49 }
50
51 if (lhs->phase() != rhs->phase()) {
52 return lhs->phase() < rhs->phase();
53 }
54
55 return false;
56}
57
59 const AstRawString* import_name, const AstRawString* local_name,
60 const AstRawString* specifier, const ModuleImportPhase import_phase,
61 const ImportAttributes* import_attributes, const Scanner::Location loc,
62 const Scanner::Location specifier_loc, Zone* zone) {
63 Entry* entry = zone->New<Entry>(loc);
64 entry->local_name = local_name;
65 entry->import_name = import_name;
67 specifier, import_phase, import_attributes, specifier_loc, zone);
68 AddRegularImport(entry);
69}
70
72 const AstRawString* local_name, const AstRawString* specifier,
73 const ImportAttributes* import_attributes, const Scanner::Location loc,
74 const Scanner::Location specifier_loc, Zone* zone) {
75 Entry* entry = zone->New<Entry>(loc);
76 entry->local_name = local_name;
77 entry->module_request =
79 import_attributes, specifier_loc, zone);
80 AddNamespaceImport(entry, zone);
81}
82
84 const AstRawString* specifier, const ImportAttributes* import_attributes,
85 const Scanner::Location specifier_loc, Zone* zone) {
86 AddModuleRequest(specifier, ModuleImportPhase::kEvaluation, import_attributes,
87 specifier_loc, zone);
88}
89
91 const AstRawString* export_name,
92 Scanner::Location loc, Zone* zone) {
93 Entry* entry = zone->New<Entry>(loc);
94 entry->export_name = export_name;
95 entry->local_name = local_name;
96 AddRegularExport(entry);
97}
98
100 const AstRawString* import_name, const AstRawString* export_name,
101 const AstRawString* specifier, const ImportAttributes* import_attributes,
102 const Scanner::Location loc, const Scanner::Location specifier_loc,
103 Zone* zone) {
104 DCHECK_NOT_NULL(import_name);
105 DCHECK_NOT_NULL(export_name);
106 Entry* entry = zone->New<Entry>(loc);
107 entry->export_name = export_name;
108 entry->import_name = import_name;
109 entry->module_request =
111 import_attributes, specifier_loc, zone);
112 AddSpecialExport(entry, zone);
113}
114
116 const AstRawString* specifier, const ImportAttributes* import_attributes,
117 const Scanner::Location loc, const Scanner::Location specifier_loc,
118 Zone* zone) {
119 Entry* entry = zone->New<Entry>(loc);
120 entry->module_request =
122 import_attributes, specifier_loc, zone);
123 AddSpecialExport(entry, zone);
124}
125
126namespace {
127template <typename IsolateT>
128Handle<UnionOf<String, Undefined>> ToStringOrUndefined(IsolateT* isolate,
129 const AstRawString* s) {
130 if (s == nullptr) return isolate->factory()->undefined_value();
131 return s->string();
132}
133} // namespace
134
135template <typename IsolateT>
136DirectHandle<ModuleRequest>
138 IsolateT* isolate) const {
139 // The import attributes will be stored in this array in the form:
140 // [key1, value1, location1, key2, value2, location2, ...]
141 DirectHandle<FixedArray> import_attributes_array =
142 isolate->factory()->NewFixedArray(
143 static_cast<int>(import_attributes()->size() *
146 {
148 Tagged<FixedArray> raw_import_attributes = *import_attributes_array;
149 int i = 0;
150 for (auto iter = import_attributes()->cbegin();
151 iter != import_attributes()->cend();
153 raw_import_attributes->set(i, *iter->first->string());
154 raw_import_attributes->set(i + 1, *iter->second.first->string());
155 raw_import_attributes->set(i + 2,
156 Smi::FromInt(iter->second.second.beg_pos));
157 }
158 }
159 return v8::internal::ModuleRequest::New(isolate, specifier()->string(),
160 phase_, import_attributes_array,
161 position());
162}
167 LocalIsolate* isolate) const;
168
169template <typename IsolateT>
172 CHECK(Smi::IsValid(module_request)); // TODO(neis): Check earlier?
174 isolate, ToStringOrUndefined(isolate, export_name),
175 ToStringOrUndefined(isolate, local_name),
176 ToStringOrUndefined(isolate, import_name), module_request, cell_index,
177 location.beg_pos, location.end_pos);
178}
183
184template <typename IsolateT>
186 IsolateT* isolate, Zone* zone) const {
187 // We serialize regular exports in a way that lets us later iterate over their
188 // local names and for each local name immediately access all its export
189 // names. (Regular exports have neither import name nor module request.)
190
193 zone);
194 int index = 0;
195
196 for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
197 // Find out how many export names this local name has.
198 auto next = it;
199 int count = 0;
200 do {
201 DCHECK_EQ(it->second->local_name, next->second->local_name);
202 DCHECK_EQ(it->second->cell_index, next->second->cell_index);
203 ++next;
204 ++count;
205 } while (next != regular_exports_.end() && next->first == it->first);
206
207 Handle<FixedArray> export_names =
208 isolate->factory()->NewFixedArray(count, AllocationType::kOld);
210 it->second->local_name->string();
212 handle(Smi::FromInt(it->second->cell_index), isolate);
214 export_names;
216
217 // Collect the export names.
218 int i = 0;
219 for (; it != next; ++it) {
220 export_names->set(i++, *it->second->export_name->string());
221 }
222 DCHECK_EQ(i, count);
223
224 // Continue with the next distinct key.
225 DCHECK(it == next);
226 }
227 DCHECK_LE(index, static_cast<int>(data.size()));
228 data.resize(index);
229
230 // We cannot create the FixedArray earlier because we only now know the
231 // precise size.
233 isolate->factory()->NewFixedArray(index, AllocationType::kOld);
234 for (int i = 0; i < index; ++i) {
235 result->set(i, *data[i]);
236 }
237 return result;
238}
241 Zone* zone) const;
244 Zone* zone) const;
245
247 for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
248 Entry* entry = it->second;
250 auto import = regular_imports_.find(entry->local_name);
251 if (import != regular_imports_.end()) {
252 // Found an indirect export. Patch export entry and move it from regular
253 // to special.
254 DCHECK_NULL(entry->import_name);
255 DCHECK_LT(entry->module_request, 0);
256 DCHECK_NOT_NULL(import->second->import_name);
257 DCHECK_LE(0, import->second->module_request);
258 DCHECK_LT(import->second->module_request,
259 static_cast<int>(module_requests_.size()));
260 entry->import_name = import->second->import_name;
261 entry->module_request = import->second->module_request;
262 // Hack: When the indirect export cannot be resolved, we want the error
263 // message to point at the import statement, not at the export statement.
264 // Therefore we overwrite [entry]'s location here. Note that Validate()
265 // has already checked for duplicate exports, so it's guaranteed that we
266 // won't need to report any error pointing at the (now lost) export
267 // location.
268 entry->location = import->second->location;
269 entry->local_name = nullptr;
270 AddSpecialExport(entry, zone);
271 it = regular_exports_.erase(it);
272 } else {
273 it++;
274 }
275 }
276}
277
280 if (cell_index > 0) return kExport;
281 if (cell_index < 0) return kImport;
282 return kInvalid;
283}
284
286 int export_index = 1;
287 for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
288 auto current_key = it->first;
289 // This local name may be exported under multiple export names. Assign the
290 // same index to each such entry.
291 do {
292 Entry* entry = it->second;
294 DCHECK_NULL(entry->import_name);
295 DCHECK_LT(entry->module_request, 0);
296 DCHECK_EQ(entry->cell_index, 0);
297 entry->cell_index = export_index;
298 it++;
299 } while (it != regular_exports_.end() && it->first == current_key);
300 export_index++;
301 }
302
303 int import_index = -1;
304 for (const auto& elem : regular_imports_) {
305 Entry* entry = elem.second;
308 DCHECK_LE(0, entry->module_request);
309 DCHECK_EQ(entry->cell_index, 0);
310 entry->cell_index = import_index;
311 import_index--;
312 }
313}
314
315namespace {
316
317const SourceTextModuleDescriptor::Entry* BetterDuplicate(
318 const SourceTextModuleDescriptor::Entry* candidate,
320 export_names,
321 const SourceTextModuleDescriptor::Entry* current_duplicate) {
322 DCHECK_NOT_NULL(candidate->export_name);
323 DCHECK(candidate->location.IsValid());
324 auto insert_result =
325 export_names.insert(std::make_pair(candidate->export_name, candidate));
326 if (insert_result.second) return current_duplicate;
327 if (current_duplicate == nullptr) {
328 current_duplicate = insert_result.first->second;
329 }
330 return (candidate->location.beg_pos > current_duplicate->location.beg_pos)
331 ? candidate
332 : current_duplicate;
333}
334
335} // namespace
336
337const SourceTextModuleDescriptor::Entry*
339 const SourceTextModuleDescriptor::Entry* duplicate = nullptr;
341 export_names(zone);
342 for (const auto& elem : regular_exports_) {
343 duplicate = BetterDuplicate(elem.second, export_names, duplicate);
344 }
345 for (auto entry : special_exports_) {
346 if (entry->export_name == nullptr) continue; // Star export.
347 duplicate = BetterDuplicate(entry, export_names, duplicate);
348 }
349 return duplicate;
350}
351
353 ModuleScope* module_scope, PendingCompilationErrorHandler* error_handler,
354 Zone* zone) {
355 DCHECK_EQ(this, module_scope->module());
356 DCHECK_NOT_NULL(error_handler);
357
358 // Report error iff there are duplicate exports.
359 {
360 const Entry* entry = FindDuplicateExport(zone);
361 if (entry != nullptr) {
362 error_handler->ReportMessageAt(
363 entry->location.beg_pos, entry->location.end_pos,
364 MessageTemplate::kDuplicateExport, entry->export_name);
365 return false;
366 }
367 }
368
369 // Report error iff there are exports of non-existent local names.
370 for (const auto& elem : regular_exports_) {
371 const Entry* entry = elem.second;
373 if (module_scope->LookupLocal(entry->local_name) == nullptr) {
374 error_handler->ReportMessageAt(
375 entry->location.beg_pos, entry->location.end_pos,
376 MessageTemplate::kModuleExportUndefined, entry->local_name);
377 return false;
378 }
379 }
380
383 return true;
384}
385
386} // namespace internal
387} // namespace v8
union v8::internal::@341::BuiltinMetadata::KindSpecificData data
static int Compare(const AstRawString *lhs, const AstRawString *rhs)
static NEVER_READ_ONLY_SPACE Handle< ModuleRequest > New(IsolateT *isolate, DirectHandle< String > specifier, ModuleImportPhase phase, DirectHandle< FixedArray > import_attributes, int position)
static const size_t kAttributeEntrySize
SourceTextModuleDescriptor * module() const
Definition scopes.h:1379
void ReportMessageAt(int start_position, int end_position, MessageTemplate message, const char *arg=nullptr)
Variable * LookupLocal(const AstRawString *name)
Definition scopes.h:200
static constexpr Tagged< Smi > FromInt(int value)
Definition smi.h:38
static bool constexpr IsValid(T value)
Definition smi.h:67
DirectHandle< v8::internal::ModuleRequest > Serialize(IsolateT *isolate) const
const ImportAttributes * import_attributes() const
Definition modules.h:141
void AddStarExport(const AstRawString *specifier, const ImportAttributes *import_attributes, const Scanner::Location loc, const Scanner::Location specifier_loc, Zone *zone)
Definition modules.cc:115
bool Validate(ModuleScope *module_scope, PendingCompilationErrorHandler *error_handler, Zone *zone)
Definition modules.cc:352
void AddNamespaceImport(const Entry *entry, Zone *zone)
Definition modules.h:224
const Entry * FindDuplicateExport(Zone *zone) const
Definition modules.cc:338
void AddStarImport(const AstRawString *local_name, const AstRawString *specifier, const ImportAttributes *import_attributes, const Scanner::Location loc, const Scanner::Location specifier_loc, Zone *zone)
Definition modules.cc:71
static CellIndexKind GetCellIndexKind(int cell_index)
Definition modules.cc:279
int AddModuleRequest(const AstRawString *specifier, const ModuleImportPhase import_phase, const ImportAttributes *import_attributes, Scanner::Location specifier_loc, Zone *zone)
Definition modules.h:270
DirectHandle< FixedArray > SerializeRegularExports(IsolateT *isolate, Zone *zone) const
Definition modules.cc:185
void AddEmptyImport(const AstRawString *specifier, const ImportAttributes *import_attributes, const Scanner::Location specifier_loc, Zone *zone)
Definition modules.cc:83
ZoneVector< const Entry * > special_exports_
Definition modules.h:238
void AddImport(const AstRawString *import_name, const AstRawString *local_name, const AstRawString *specifier, const ModuleImportPhase import_phase, const ImportAttributes *import_attributes, const Scanner::Location loc, const Scanner::Location specifier_loc, Zone *zone)
Definition modules.cc:58
void AddExport(const AstRawString *local_name, const AstRawString *export_name, const Scanner::Location loc, Zone *zone)
Definition modules.cc:90
void AddSpecialExport(const Entry *entry, Zone *zone)
Definition modules.h:208
static Handle< SourceTextModuleInfoEntry > New(IsolateT *isolate, DirectHandle< UnionOf< String, Undefined > > export_name, DirectHandle< UnionOf< String, Undefined > > local_name, DirectHandle< UnionOf< String, Undefined > > import_name, int module_request, int cell_index, int beg_pos, int end_pos)
T * New(Args &&... args)
Definition zone.h:114
uint32_t count
ZoneVector< RpoNumber > & result
int position
Definition liveedit.cc:290
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
Definition handles-inl.h:72
ModuleImportPhase
#define DCHECK_LE(v1, v2)
Definition logging.h:490
#define DCHECK_NULL(val)
Definition logging.h:491
#define CHECK(condition)
Definition logging.h:124
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_LT(v1, v2)
Definition logging.h:489
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
bool operator()(const AstRawString *lhs, const AstRawString *rhs) const
Definition modules.cc:18
DirectHandle< SourceTextModuleInfoEntry > Serialize(IsolateT *isolate) const
Definition modules.cc:171
bool operator()(const AstModuleRequest *lhs, const AstModuleRequest *rhs) const
Definition modules.cc:23