LCOV - code coverage report
Current view: top level - src/ast - modules.h (source / functions) Hit Total Coverage
Test: app.info Lines: 11 11 100.0 %
Date: 2019-02-19 Functions: 2 2 100.0 %

          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             : #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       74923 :   explicit ModuleDescriptor(Zone* zone)
      23             :       : module_requests_(zone),
      24             :         special_exports_(zone),
      25             :         namespace_imports_(zone),
      26             :         regular_exports_(zone),
      27       74923 :         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       28508 :           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,
     115             :                               Handle<ModuleInfoEntry> entry);
     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.
     129             :   struct AstRawStringComparer {
     130             :     bool operator()(const AstRawString* lhs, const AstRawString* rhs) const;
     131             :   };
     132             : 
     133             :   typedef ZoneMap<const AstRawString*, ModuleRequest, AstRawStringComparer>
     134             :       ModuleRequestMap;
     135             :   typedef ZoneMultimap<const AstRawString*, Entry*, AstRawStringComparer>
     136             :       RegularExportMap;
     137             :   typedef ZoneMap<const AstRawString*, Entry*, AstRawStringComparer>
     138             :       RegularImportMap;
     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       46006 :     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         380 :     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        9270 :     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         545 :     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        2874 :   int AddModuleRequest(const AstRawString* specifier,
     232             :                        Scanner::Location specifier_loc) {
     233             :     DCHECK_NOT_NULL(specifier);
     234        2874 :     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        5748 :                                                        specifier_loc.beg_pos)))
     239             :                   .first;
     240        2874 :     return it->second.index;
     241             :   }
     242             : };
     243             : 
     244             : }  // namespace internal
     245             : }  // namespace v8
     246             : 
     247             : #endif  // V8_AST_MODULES_H_

Generated by: LCOV version 1.10