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