11cb0ef41Sopenharmony_ci// Copyright 2012 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#ifndef V8_AST_MODULES_H_ 61cb0ef41Sopenharmony_ci#define V8_AST_MODULES_H_ 71cb0ef41Sopenharmony_ci 81cb0ef41Sopenharmony_ci#include "src/parsing/import-assertions.h" 91cb0ef41Sopenharmony_ci#include "src/parsing/scanner.h" // Only for Scanner::Location. 101cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h" 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_cinamespace v8 { 131cb0ef41Sopenharmony_cinamespace internal { 141cb0ef41Sopenharmony_ci 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ciclass AstRawString; 171cb0ef41Sopenharmony_ciclass AstRawStringComparer; 181cb0ef41Sopenharmony_ciclass ModuleRequest; 191cb0ef41Sopenharmony_ciclass SourceTextModuleInfo; 201cb0ef41Sopenharmony_ciclass SourceTextModuleInfoEntry; 211cb0ef41Sopenharmony_ciclass PendingCompilationErrorHandler; 221cb0ef41Sopenharmony_ci 231cb0ef41Sopenharmony_ciclass SourceTextModuleDescriptor : public ZoneObject { 241cb0ef41Sopenharmony_ci public: 251cb0ef41Sopenharmony_ci explicit SourceTextModuleDescriptor(Zone* zone) 261cb0ef41Sopenharmony_ci : module_requests_(zone), 271cb0ef41Sopenharmony_ci special_exports_(zone), 281cb0ef41Sopenharmony_ci namespace_imports_(zone), 291cb0ef41Sopenharmony_ci regular_exports_(zone), 301cb0ef41Sopenharmony_ci regular_imports_(zone) {} 311cb0ef41Sopenharmony_ci 321cb0ef41Sopenharmony_ci // The following Add* methods are high-level convenience functions for use by 331cb0ef41Sopenharmony_ci // the parser. 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ci // import x from "foo.js"; 361cb0ef41Sopenharmony_ci // import {x} from "foo.js"; 371cb0ef41Sopenharmony_ci // import {x as y} from "foo.js"; 381cb0ef41Sopenharmony_ci void AddImport(const AstRawString* import_name, 391cb0ef41Sopenharmony_ci const AstRawString* local_name, 401cb0ef41Sopenharmony_ci const AstRawString* module_request, 411cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, 421cb0ef41Sopenharmony_ci const Scanner::Location loc, 431cb0ef41Sopenharmony_ci const Scanner::Location specifier_loc, Zone* zone); 441cb0ef41Sopenharmony_ci 451cb0ef41Sopenharmony_ci // import * as x from "foo.js"; 461cb0ef41Sopenharmony_ci void AddStarImport(const AstRawString* local_name, 471cb0ef41Sopenharmony_ci const AstRawString* module_request, 481cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, 491cb0ef41Sopenharmony_ci const Scanner::Location loc, 501cb0ef41Sopenharmony_ci const Scanner::Location specifier_loc, Zone* zone); 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ci // import "foo.js"; 531cb0ef41Sopenharmony_ci // import {} from "foo.js"; 541cb0ef41Sopenharmony_ci // export {} from "foo.js"; (sic!) 551cb0ef41Sopenharmony_ci void AddEmptyImport(const AstRawString* module_request, 561cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, 571cb0ef41Sopenharmony_ci const Scanner::Location specifier_loc, Zone* zone); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ci // export {x}; 601cb0ef41Sopenharmony_ci // export {x as y}; 611cb0ef41Sopenharmony_ci // export VariableStatement 621cb0ef41Sopenharmony_ci // export Declaration 631cb0ef41Sopenharmony_ci // export default ... 641cb0ef41Sopenharmony_ci void AddExport( 651cb0ef41Sopenharmony_ci const AstRawString* local_name, const AstRawString* export_name, 661cb0ef41Sopenharmony_ci const Scanner::Location loc, Zone* zone); 671cb0ef41Sopenharmony_ci 681cb0ef41Sopenharmony_ci // export {x} from "foo.js"; 691cb0ef41Sopenharmony_ci // export {x as y} from "foo.js"; 701cb0ef41Sopenharmony_ci void AddExport(const AstRawString* export_name, 711cb0ef41Sopenharmony_ci const AstRawString* import_name, 721cb0ef41Sopenharmony_ci const AstRawString* module_request, 731cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, 741cb0ef41Sopenharmony_ci const Scanner::Location loc, 751cb0ef41Sopenharmony_ci const Scanner::Location specifier_loc, Zone* zone); 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci // export * from "foo.js"; 781cb0ef41Sopenharmony_ci void AddStarExport(const AstRawString* module_request, 791cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, 801cb0ef41Sopenharmony_ci const Scanner::Location loc, 811cb0ef41Sopenharmony_ci const Scanner::Location specifier_loc, Zone* zone); 821cb0ef41Sopenharmony_ci 831cb0ef41Sopenharmony_ci // Check if module is well-formed and report error if not. 841cb0ef41Sopenharmony_ci // Also canonicalize indirect exports. 851cb0ef41Sopenharmony_ci bool Validate(ModuleScope* module_scope, 861cb0ef41Sopenharmony_ci PendingCompilationErrorHandler* error_handler, Zone* zone); 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci struct Entry : public ZoneObject { 891cb0ef41Sopenharmony_ci Scanner::Location location; 901cb0ef41Sopenharmony_ci const AstRawString* export_name; 911cb0ef41Sopenharmony_ci const AstRawString* local_name; 921cb0ef41Sopenharmony_ci const AstRawString* import_name; 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_ci // The module_request value records the order in which modules are 951cb0ef41Sopenharmony_ci // requested. It also functions as an index into the SourceTextModuleInfo's 961cb0ef41Sopenharmony_ci // array of module specifiers and into the Module's array of requested 971cb0ef41Sopenharmony_ci // modules. A negative value means no module request. 981cb0ef41Sopenharmony_ci int module_request; 991cb0ef41Sopenharmony_ci 1001cb0ef41Sopenharmony_ci // Import/export entries that are associated with a MODULE-allocated 1011cb0ef41Sopenharmony_ci // variable (i.e. regular_imports and regular_exports after Validate) use 1021cb0ef41Sopenharmony_ci // the cell_index value to encode the location of their cell. During 1031cb0ef41Sopenharmony_ci // variable allocation, this will be be copied into the variable's index 1041cb0ef41Sopenharmony_ci // field. 1051cb0ef41Sopenharmony_ci // Entries that are not associated with a MODULE-allocated variable have 1061cb0ef41Sopenharmony_ci // GetCellIndexKind(cell_index) == kInvalid. 1071cb0ef41Sopenharmony_ci int cell_index; 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ci // TODO(neis): Remove local_name component? 1101cb0ef41Sopenharmony_ci explicit Entry(Scanner::Location loc) 1111cb0ef41Sopenharmony_ci : location(loc), 1121cb0ef41Sopenharmony_ci export_name(nullptr), 1131cb0ef41Sopenharmony_ci local_name(nullptr), 1141cb0ef41Sopenharmony_ci import_name(nullptr), 1151cb0ef41Sopenharmony_ci module_request(-1), 1161cb0ef41Sopenharmony_ci cell_index(0) {} 1171cb0ef41Sopenharmony_ci 1181cb0ef41Sopenharmony_ci template <typename IsolateT> 1191cb0ef41Sopenharmony_ci Handle<SourceTextModuleInfoEntry> Serialize(IsolateT* isolate) const; 1201cb0ef41Sopenharmony_ci }; 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci enum CellIndexKind { kInvalid, kExport, kImport }; 1231cb0ef41Sopenharmony_ci static CellIndexKind GetCellIndexKind(int cell_index); 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci class AstModuleRequest : public ZoneObject { 1261cb0ef41Sopenharmony_ci public: 1271cb0ef41Sopenharmony_ci AstModuleRequest(const AstRawString* specifier, 1281cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, int position, 1291cb0ef41Sopenharmony_ci int index) 1301cb0ef41Sopenharmony_ci : specifier_(specifier), 1311cb0ef41Sopenharmony_ci import_assertions_(import_assertions), 1321cb0ef41Sopenharmony_ci position_(position), 1331cb0ef41Sopenharmony_ci index_(index) {} 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci template <typename IsolateT> 1361cb0ef41Sopenharmony_ci Handle<v8::internal::ModuleRequest> Serialize(IsolateT* isolate) const; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci const AstRawString* specifier() const { return specifier_; } 1391cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions() const { 1401cb0ef41Sopenharmony_ci return import_assertions_; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci int position() const { return position_; } 1441cb0ef41Sopenharmony_ci int index() const { return index_; } 1451cb0ef41Sopenharmony_ci 1461cb0ef41Sopenharmony_ci private: 1471cb0ef41Sopenharmony_ci const AstRawString* specifier_; 1481cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions_; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci // The JS source code position of the request, used for reporting errors. 1511cb0ef41Sopenharmony_ci int position_; 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci // The index at which we will place the request in SourceTextModuleInfo's 1541cb0ef41Sopenharmony_ci // module_requests FixedArray. 1551cb0ef41Sopenharmony_ci int index_; 1561cb0ef41Sopenharmony_ci }; 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci // Custom content-based comparer for the below maps, to keep them stable 1591cb0ef41Sopenharmony_ci // across parses. 1601cb0ef41Sopenharmony_ci struct V8_EXPORT_PRIVATE AstRawStringComparer { 1611cb0ef41Sopenharmony_ci bool operator()(const AstRawString* lhs, const AstRawString* rhs) const; 1621cb0ef41Sopenharmony_ci }; 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci struct V8_EXPORT_PRIVATE ModuleRequestComparer { 1651cb0ef41Sopenharmony_ci bool operator()(const AstModuleRequest* lhs, 1661cb0ef41Sopenharmony_ci const AstModuleRequest* rhs) const; 1671cb0ef41Sopenharmony_ci }; 1681cb0ef41Sopenharmony_ci 1691cb0ef41Sopenharmony_ci using ModuleRequestMap = 1701cb0ef41Sopenharmony_ci ZoneSet<const AstModuleRequest*, ModuleRequestComparer>; 1711cb0ef41Sopenharmony_ci using RegularExportMap = 1721cb0ef41Sopenharmony_ci ZoneMultimap<const AstRawString*, Entry*, AstRawStringComparer>; 1731cb0ef41Sopenharmony_ci using RegularImportMap = 1741cb0ef41Sopenharmony_ci ZoneMap<const AstRawString*, Entry*, AstRawStringComparer>; 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci // Module requests. 1771cb0ef41Sopenharmony_ci const ModuleRequestMap& module_requests() const { return module_requests_; } 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci // Namespace imports. 1801cb0ef41Sopenharmony_ci const ZoneVector<const Entry*>& namespace_imports() const { 1811cb0ef41Sopenharmony_ci return namespace_imports_; 1821cb0ef41Sopenharmony_ci } 1831cb0ef41Sopenharmony_ci 1841cb0ef41Sopenharmony_ci // All the remaining imports, indexed by local name. 1851cb0ef41Sopenharmony_ci const RegularImportMap& regular_imports() const { return regular_imports_; } 1861cb0ef41Sopenharmony_ci 1871cb0ef41Sopenharmony_ci // Star exports and explicitly indirect exports. 1881cb0ef41Sopenharmony_ci const ZoneVector<const Entry*>& special_exports() const { 1891cb0ef41Sopenharmony_ci return special_exports_; 1901cb0ef41Sopenharmony_ci } 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // All the remaining exports, indexed by local name. 1931cb0ef41Sopenharmony_ci // After canonicalization (see Validate), these are exactly the local exports. 1941cb0ef41Sopenharmony_ci const RegularExportMap& regular_exports() const { return regular_exports_; } 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci void AddRegularExport(Entry* entry) { 1971cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(entry->export_name); 1981cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(entry->local_name); 1991cb0ef41Sopenharmony_ci DCHECK_NULL(entry->import_name); 2001cb0ef41Sopenharmony_ci DCHECK_LT(entry->module_request, 0); 2011cb0ef41Sopenharmony_ci regular_exports_.insert(std::make_pair(entry->local_name, entry)); 2021cb0ef41Sopenharmony_ci } 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ci void AddSpecialExport(const Entry* entry, Zone* zone) { 2051cb0ef41Sopenharmony_ci DCHECK_NULL(entry->local_name); 2061cb0ef41Sopenharmony_ci DCHECK_LE(0, entry->module_request); 2071cb0ef41Sopenharmony_ci special_exports_.push_back(entry); 2081cb0ef41Sopenharmony_ci } 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci void AddRegularImport(Entry* entry) { 2111cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(entry->import_name); 2121cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(entry->local_name); 2131cb0ef41Sopenharmony_ci DCHECK_NULL(entry->export_name); 2141cb0ef41Sopenharmony_ci DCHECK_LE(0, entry->module_request); 2151cb0ef41Sopenharmony_ci regular_imports_.insert(std::make_pair(entry->local_name, entry)); 2161cb0ef41Sopenharmony_ci // We don't care if there's already an entry for this local name, as in that 2171cb0ef41Sopenharmony_ci // case we will report an error when declaring the variable. 2181cb0ef41Sopenharmony_ci } 2191cb0ef41Sopenharmony_ci 2201cb0ef41Sopenharmony_ci void AddNamespaceImport(const Entry* entry, Zone* zone) { 2211cb0ef41Sopenharmony_ci DCHECK_NULL(entry->import_name); 2221cb0ef41Sopenharmony_ci DCHECK_NULL(entry->export_name); 2231cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(entry->local_name); 2241cb0ef41Sopenharmony_ci DCHECK_LE(0, entry->module_request); 2251cb0ef41Sopenharmony_ci namespace_imports_.push_back(entry); 2261cb0ef41Sopenharmony_ci } 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci template <typename IsolateT> 2291cb0ef41Sopenharmony_ci Handle<FixedArray> SerializeRegularExports(IsolateT* isolate, 2301cb0ef41Sopenharmony_ci Zone* zone) const; 2311cb0ef41Sopenharmony_ci 2321cb0ef41Sopenharmony_ci private: 2331cb0ef41Sopenharmony_ci ModuleRequestMap module_requests_; 2341cb0ef41Sopenharmony_ci ZoneVector<const Entry*> special_exports_; 2351cb0ef41Sopenharmony_ci ZoneVector<const Entry*> namespace_imports_; 2361cb0ef41Sopenharmony_ci RegularExportMap regular_exports_; 2371cb0ef41Sopenharmony_ci RegularImportMap regular_imports_; 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci // If there are multiple export entries with the same export name, return the 2401cb0ef41Sopenharmony_ci // last of them (in source order). Otherwise return nullptr. 2411cb0ef41Sopenharmony_ci const Entry* FindDuplicateExport(Zone* zone) const; 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci // Find any implicitly indirect exports and make them explicit. 2441cb0ef41Sopenharmony_ci // 2451cb0ef41Sopenharmony_ci // An explicitly indirect export is an export entry arising from an export 2461cb0ef41Sopenharmony_ci // statement of the following form: 2471cb0ef41Sopenharmony_ci // export {a as c} from "X"; 2481cb0ef41Sopenharmony_ci // An implicitly indirect export corresponds to 2491cb0ef41Sopenharmony_ci // export {b as c}; 2501cb0ef41Sopenharmony_ci // in the presence of an import statement of the form 2511cb0ef41Sopenharmony_ci // import {a as b} from "X"; 2521cb0ef41Sopenharmony_ci // This function finds such implicitly indirect export entries and rewrites 2531cb0ef41Sopenharmony_ci // them by filling in the import name and module request, as well as nulling 2541cb0ef41Sopenharmony_ci // out the local name. Effectively, it turns 2551cb0ef41Sopenharmony_ci // import {a as b} from "X"; export {b as c}; 2561cb0ef41Sopenharmony_ci // into: 2571cb0ef41Sopenharmony_ci // import {a as b} from "X"; export {a as c} from "X"; 2581cb0ef41Sopenharmony_ci // (The import entry is never deleted.) 2591cb0ef41Sopenharmony_ci void MakeIndirectExportsExplicit(Zone* zone); 2601cb0ef41Sopenharmony_ci 2611cb0ef41Sopenharmony_ci // Assign a cell_index of -1,-2,... to regular imports. 2621cb0ef41Sopenharmony_ci // Assign a cell_index of +1,+2,... to regular (local) exports. 2631cb0ef41Sopenharmony_ci // Assign a cell_index of 0 to anything else. 2641cb0ef41Sopenharmony_ci void AssignCellIndices(); 2651cb0ef41Sopenharmony_ci 2661cb0ef41Sopenharmony_ci int AddModuleRequest(const AstRawString* specifier, 2671cb0ef41Sopenharmony_ci const ImportAssertions* import_assertions, 2681cb0ef41Sopenharmony_ci Scanner::Location specifier_loc, Zone* zone) { 2691cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(specifier); 2701cb0ef41Sopenharmony_ci int module_requests_count = static_cast<int>(module_requests_.size()); 2711cb0ef41Sopenharmony_ci auto it = module_requests_ 2721cb0ef41Sopenharmony_ci .insert(zone->New<AstModuleRequest>( 2731cb0ef41Sopenharmony_ci specifier, import_assertions, specifier_loc.beg_pos, 2741cb0ef41Sopenharmony_ci module_requests_count)) 2751cb0ef41Sopenharmony_ci .first; 2761cb0ef41Sopenharmony_ci return (*it)->index(); 2771cb0ef41Sopenharmony_ci } 2781cb0ef41Sopenharmony_ci}; 2791cb0ef41Sopenharmony_ci 2801cb0ef41Sopenharmony_ci} // namespace internal 2811cb0ef41Sopenharmony_ci} // namespace v8 2821cb0ef41Sopenharmony_ci 2831cb0ef41Sopenharmony_ci#endif // V8_AST_MODULES_H_ 284