LCOV - code coverage report
Current view: top level - src/ast - modules.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 133 133 100.0 %
Date: 2017-10-20 Functions: 17 17 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             : #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

Generated by: LCOV version 1.10