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 : #include "src/ast/modules.h"
6 : #include "src/ast/ast-value-factory.h"
7 : #include "src/ast/scopes.h"
8 : #include "src/objects-inl.h"
9 : #include "src/objects/module.h"
10 : #include "src/pending-compilation-error-handler.h"
11 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 1086 : void ModuleDescriptor::AddImport(const AstRawString* import_name,
16 : const AstRawString* local_name,
17 : const AstRawString* module_request,
18 : const Scanner::Location loc,
19 1086 : const Scanner::Location specifier_loc,
20 : Zone* zone) {
21 1086 : Entry* entry = new (zone) Entry(loc);
22 1086 : entry->local_name = local_name;
23 1086 : entry->import_name = import_name;
24 1086 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
25 : AddRegularImport(entry);
26 1086 : }
27 :
28 120 : void ModuleDescriptor::AddStarImport(const AstRawString* local_name,
29 : const AstRawString* module_request,
30 : const Scanner::Location loc,
31 120 : const Scanner::Location specifier_loc,
32 : Zone* zone) {
33 120 : Entry* entry = new (zone) Entry(loc);
34 120 : entry->local_name = local_name;
35 120 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
36 : AddNamespaceImport(entry, zone);
37 120 : }
38 :
39 129 : void ModuleDescriptor::AddEmptyImport(const AstRawString* module_request,
40 129 : const Scanner::Location specifier_loc) {
41 129 : AddModuleRequest(module_request, specifier_loc);
42 129 : }
43 :
44 :
45 18586 : void ModuleDescriptor::AddExport(
46 : const AstRawString* local_name, const AstRawString* export_name,
47 : Scanner::Location loc, Zone* zone) {
48 18586 : Entry* entry = new (zone) Entry(loc);
49 18586 : entry->export_name = export_name;
50 18586 : entry->local_name = local_name;
51 : AddRegularExport(entry);
52 18586 : }
53 :
54 107 : void ModuleDescriptor::AddExport(const AstRawString* import_name,
55 : const AstRawString* export_name,
56 : const AstRawString* module_request,
57 : const Scanner::Location loc,
58 107 : const Scanner::Location specifier_loc,
59 : Zone* zone) {
60 : DCHECK_NOT_NULL(import_name);
61 : DCHECK_NOT_NULL(export_name);
62 107 : Entry* entry = new (zone) Entry(loc);
63 107 : entry->export_name = export_name;
64 107 : entry->import_name = import_name;
65 107 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
66 : AddSpecialExport(entry, zone);
67 107 : }
68 :
69 104 : void ModuleDescriptor::AddStarExport(const AstRawString* module_request,
70 : const Scanner::Location loc,
71 104 : const Scanner::Location specifier_loc,
72 : Zone* zone) {
73 104 : Entry* entry = new (zone) Entry(loc);
74 104 : entry->module_request = AddModuleRequest(module_request, specifier_loc);
75 : AddSpecialExport(entry, zone);
76 104 : }
77 :
78 : namespace {
79 :
80 2212 : Handle<Object> ToStringOrUndefined(Isolate* isolate, const AstRawString* s) {
81 : return (s == nullptr)
82 : ? Handle<Object>::cast(isolate->factory()->undefined_value())
83 3735 : : Handle<Object>::cast(s->string());
84 : }
85 :
86 15942 : const AstRawString* FromStringOrUndefined(Isolate* isolate,
87 : AstValueFactory* avfactory,
88 : Handle<Object> object) {
89 15942 : if (object->IsUndefined(isolate)) return nullptr;
90 10408 : return avfactory->GetString(Handle<String>::cast(object));
91 : }
92 :
93 : } // namespace
94 :
95 1245 : Handle<ModuleInfoEntry> ModuleDescriptor::Entry::Serialize(
96 : Isolate* isolate) const {
97 1245 : CHECK(Smi::IsValid(module_request)); // TODO(neis): Check earlier?
98 : return ModuleInfoEntry::New(
99 : isolate, ToStringOrUndefined(isolate, export_name),
100 : ToStringOrUndefined(isolate, local_name),
101 : ToStringOrUndefined(isolate, import_name), module_request, cell_index,
102 4980 : location.beg_pos, location.end_pos);
103 : }
104 :
105 5314 : ModuleDescriptor::Entry* ModuleDescriptor::Entry::Deserialize(
106 5314 : Isolate* isolate, AstValueFactory* avfactory,
107 : Handle<ModuleInfoEntry> entry) {
108 : Entry* result = new (avfactory->zone()) Entry(Scanner::Location::invalid());
109 : result->export_name = FromStringOrUndefined(
110 5314 : isolate, avfactory, handle(entry->export_name(), isolate));
111 : result->local_name = FromStringOrUndefined(
112 5314 : isolate, avfactory, handle(entry->local_name(), isolate));
113 : result->import_name = FromStringOrUndefined(
114 5314 : isolate, avfactory, handle(entry->import_name(), isolate));
115 5314 : result->module_request = entry->module_request();
116 5314 : result->cell_index = entry->cell_index();
117 5314 : return result;
118 : }
119 :
120 1724 : Handle<FixedArray> ModuleDescriptor::SerializeRegularExports(Isolate* isolate,
121 : Zone* zone) const {
122 : // We serialize regular exports in a way that lets us later iterate over their
123 : // local names and for each local name immediately access all its export
124 : // names. (Regular exports have neither import name nor module request.)
125 :
126 : ZoneVector<Handle<Object>> data(
127 1724 : ModuleInfo::kRegularExportLength * regular_exports_.size(), zone);
128 : int index = 0;
129 :
130 21618 : for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
131 : // Find out how many export names this local name has.
132 : auto next = it;
133 : int count = 0;
134 18248 : do {
135 : DCHECK_EQ(it->second->local_name, next->second->local_name);
136 : DCHECK_EQ(it->second->cell_index, next->second->cell_index);
137 : ++next;
138 18248 : ++count;
139 18248 : } while (next != regular_exports_.end() && next->first == it->first);
140 :
141 18170 : Handle<FixedArray> export_names = isolate->factory()->NewFixedArray(count);
142 18170 : data[index + ModuleInfo::kRegularExportLocalNameOffset] =
143 18170 : it->second->local_name->string();
144 18170 : data[index + ModuleInfo::kRegularExportCellIndexOffset] =
145 36340 : handle(Smi::FromInt(it->second->cell_index), isolate);
146 36340 : data[index + ModuleInfo::kRegularExportExportNamesOffset] = export_names;
147 18170 : index += ModuleInfo::kRegularExportLength;
148 :
149 : // Collect the export names.
150 : int i = 0;
151 54588 : for (; it != next; ++it) {
152 54744 : export_names->set(i++, *it->second->export_name->string());
153 : }
154 : DCHECK_EQ(i, count);
155 :
156 : // Continue with the next distinct key.
157 : DCHECK(it == next);
158 : }
159 : DCHECK_LE(index, static_cast<int>(data.size()));
160 1724 : data.resize(index);
161 :
162 : // We cannot create the FixedArray earlier because we only now know the
163 : // precise size.
164 1724 : Handle<FixedArray> result = isolate->factory()->NewFixedArray(index);
165 56234 : for (int i = 0; i < index; ++i) {
166 109020 : result->set(i, *data[i]);
167 : }
168 1724 : return result;
169 : }
170 :
171 6149 : void ModuleDescriptor::DeserializeRegularExports(
172 7106 : Isolate* isolate, AstValueFactory* avfactory,
173 : Handle<ModuleInfo> module_info) {
174 13013 : for (int i = 0, count = module_info->RegularExportCount(); i < count; ++i) {
175 6864 : Handle<String> local_name(module_info->RegularExportLocalName(i), isolate);
176 6864 : int cell_index = module_info->RegularExportCellIndex(i);
177 : Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
178 6864 : isolate);
179 :
180 13970 : for (int j = 0, length = export_names->length(); j < length; ++j) {
181 : Handle<String> export_name(String::cast(export_names->get(j)), isolate);
182 :
183 : Entry* entry =
184 : new (avfactory->zone()) Entry(Scanner::Location::invalid());
185 7106 : entry->local_name = avfactory->GetString(local_name);
186 7106 : entry->export_name = avfactory->GetString(export_name);
187 7106 : entry->cell_index = cell_index;
188 :
189 : AddRegularExport(entry);
190 : }
191 : }
192 6149 : }
193 :
194 12004 : void ModuleDescriptor::MakeIndirectExportsExplicit(Zone* zone) {
195 42529 : for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
196 18521 : Entry* entry = it->second;
197 : DCHECK_NOT_NULL(entry->local_name);
198 18521 : auto import = regular_imports_.find(entry->local_name);
199 18521 : if (import != regular_imports_.end()) {
200 : // Found an indirect export. Patch export entry and move it from regular
201 : // to special.
202 : DCHECK_NULL(entry->import_name);
203 : DCHECK_LT(entry->module_request, 0);
204 : DCHECK_NOT_NULL(import->second->import_name);
205 : DCHECK_LE(0, import->second->module_request);
206 : DCHECK_LT(import->second->module_request,
207 : static_cast<int>(module_requests_.size()));
208 43 : entry->import_name = import->second->import_name;
209 43 : entry->module_request = import->second->module_request;
210 : // Hack: When the indirect export cannot be resolved, we want the error
211 : // message to point at the import statement, not at the export statement.
212 : // Therefore we overwrite [entry]'s location here. Note that Validate()
213 : // has already checked for duplicate exports, so it's guaranteed that we
214 : // won't need to report any error pointing at the (now lost) export
215 : // location.
216 43 : entry->location = import->second->location;
217 43 : entry->local_name = nullptr;
218 : AddSpecialExport(entry, zone);
219 : it = regular_exports_.erase(it);
220 : } else {
221 : it++;
222 : }
223 : }
224 12004 : }
225 :
226 12384 : ModuleDescriptor::CellIndexKind ModuleDescriptor::GetCellIndexKind(
227 : int cell_index) {
228 12384 : if (cell_index > 0) return kExport;
229 2569 : if (cell_index < 0) return kImport;
230 5 : return kInvalid;
231 : }
232 :
233 12004 : void ModuleDescriptor::AssignCellIndices() {
234 : int export_index = 1;
235 42398 : for (auto it = regular_exports_.begin(); it != regular_exports_.end();) {
236 18390 : auto current_key = it->first;
237 : // This local name may be exported under multiple export names. Assign the
238 : // same index to each such entry.
239 18478 : do {
240 18478 : Entry* entry = it->second;
241 : DCHECK_NOT_NULL(entry->local_name);
242 : DCHECK_NULL(entry->import_name);
243 : DCHECK_LT(entry->module_request, 0);
244 : DCHECK_EQ(entry->cell_index, 0);
245 18478 : entry->cell_index = export_index;
246 : it++;
247 18478 : } while (it != regular_exports_.end() && it->first == current_key);
248 18390 : export_index++;
249 : }
250 :
251 : int import_index = -1;
252 25094 : for (const auto& elem : regular_imports_) {
253 1086 : Entry* entry = elem.second;
254 : DCHECK_NOT_NULL(entry->local_name);
255 : DCHECK_NOT_NULL(entry->import_name);
256 : DCHECK_LE(0, entry->module_request);
257 : DCHECK_EQ(entry->cell_index, 0);
258 1086 : entry->cell_index = import_index;
259 1086 : import_index--;
260 : }
261 12004 : }
262 :
263 : namespace {
264 :
265 18693 : const ModuleDescriptor::Entry* BetterDuplicate(
266 : const ModuleDescriptor::Entry* candidate,
267 : ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*>& export_names,
268 : const ModuleDescriptor::Entry* current_duplicate) {
269 : DCHECK_NOT_NULL(candidate->export_name);
270 : DCHECK(candidate->location.IsValid());
271 : auto insert_result =
272 37386 : export_names.insert(std::make_pair(candidate->export_name, candidate));
273 18693 : if (insert_result.second) return current_duplicate;
274 25 : if (current_duplicate == nullptr) {
275 25 : current_duplicate = insert_result.first->second;
276 : }
277 25 : return (candidate->location.beg_pos > current_duplicate->location.beg_pos)
278 : ? candidate
279 25 : : current_duplicate;
280 : }
281 :
282 : } // namespace
283 :
284 12044 : const ModuleDescriptor::Entry* ModuleDescriptor::FindDuplicateExport(
285 : Zone* zone) const {
286 : const ModuleDescriptor::Entry* duplicate = nullptr;
287 : ZoneMap<const AstRawString*, const ModuleDescriptor::Entry*> export_names(
288 : zone);
289 42674 : for (const auto& elem : regular_exports_) {
290 18586 : duplicate = BetterDuplicate(elem.second, export_names, duplicate);
291 : }
292 24299 : for (auto entry : special_exports_) {
293 211 : if (entry->export_name == nullptr) continue; // Star export.
294 107 : duplicate = BetterDuplicate(entry, export_names, duplicate);
295 : }
296 12044 : return duplicate;
297 : }
298 :
299 12044 : bool ModuleDescriptor::Validate(ModuleScope* module_scope,
300 : PendingCompilationErrorHandler* error_handler,
301 : Zone* zone) {
302 : DCHECK_EQ(this, module_scope->module());
303 : DCHECK_NOT_NULL(error_handler);
304 :
305 : // Report error iff there are duplicate exports.
306 : {
307 12044 : const Entry* entry = FindDuplicateExport(zone);
308 12044 : if (entry != nullptr) {
309 : error_handler->ReportMessageAt(
310 : entry->location.beg_pos, entry->location.end_pos,
311 25 : MessageTemplate::kDuplicateExport, entry->export_name);
312 : return false;
313 : }
314 : }
315 :
316 : // Report error iff there are exports of non-existent local names.
317 42559 : for (const auto& elem : regular_exports_) {
318 18536 : const Entry* entry = elem.second;
319 : DCHECK_NOT_NULL(entry->local_name);
320 18536 : if (module_scope->LookupLocal(entry->local_name) == nullptr) {
321 : error_handler->ReportMessageAt(
322 : entry->location.beg_pos, entry->location.end_pos,
323 15 : MessageTemplate::kModuleExportUndefined, entry->local_name);
324 : return false;
325 : }
326 : }
327 :
328 12004 : MakeIndirectExportsExplicit(zone);
329 12004 : AssignCellIndices();
330 12004 : return true;
331 : }
332 :
333 : } // namespace internal
334 : } // namespace v8
|