LCOV - code coverage report
Current view: top level - src/objects - module.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 309 321 96.3 %
Date: 2019-01-20 Functions: 33 34 97.1 %

          Line data    Source code
       1             : // Copyright 2017 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 <unordered_map>
       6             : #include <unordered_set>
       7             : 
       8             : #include "src/objects/module.h"
       9             : 
      10             : #include "src/accessors.h"
      11             : #include "src/api-inl.h"
      12             : #include "src/ast/modules.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/objects/cell-inl.h"
      15             : #include "src/objects/hash-table-inl.h"
      16             : #include "src/objects/js-generator-inl.h"
      17             : #include "src/objects/module-inl.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : struct ModuleHandleHash {
      23             :   V8_INLINE size_t operator()(Handle<Module> module) const {
      24         627 :     return module->hash();
      25             :   }
      26             : };
      27             : 
      28             : struct ModuleHandleEqual {
      29             :   V8_INLINE bool operator()(Handle<Module> lhs, Handle<Module> rhs) const {
      30          36 :     return *lhs == *rhs;
      31             :   }
      32             : };
      33             : 
      34             : struct StringHandleHash {
      35             :   V8_INLINE size_t operator()(Handle<String> string) const {
      36         374 :     return string->Hash();
      37             :   }
      38             : };
      39             : 
      40             : struct StringHandleEqual {
      41             :   V8_INLINE bool operator()(Handle<String> lhs, Handle<String> rhs) const {
      42          27 :     return lhs->Equals(*rhs);
      43             :   }
      44             : };
      45             : 
      46             : class UnorderedStringSet
      47             :     : public std::unordered_set<Handle<String>, StringHandleHash,
      48             :                                 StringHandleEqual,
      49             :                                 ZoneAllocator<Handle<String>>> {
      50             :  public:
      51         230 :   explicit UnorderedStringSet(Zone* zone)
      52             :       : std::unordered_set<Handle<String>, StringHandleHash, StringHandleEqual,
      53             :                            ZoneAllocator<Handle<String>>>(
      54             :             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
      55         230 :             ZoneAllocator<Handle<String>>(zone)) {}
      56             : };
      57             : 
      58             : class UnorderedModuleSet
      59             :     : public std::unordered_set<Handle<Module>, ModuleHandleHash,
      60             :                                 ModuleHandleEqual,
      61             :                                 ZoneAllocator<Handle<Module>>> {
      62             :  public:
      63         334 :   explicit UnorderedModuleSet(Zone* zone)
      64             :       : std::unordered_set<Handle<Module>, ModuleHandleHash, ModuleHandleEqual,
      65             :                            ZoneAllocator<Handle<Module>>>(
      66             :             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
      67         334 :             ZoneAllocator<Handle<Module>>(zone)) {}
      68             : };
      69             : 
      70             : class UnorderedStringMap
      71             :     : public std::unordered_map<
      72             :           Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
      73             :           ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>> {
      74             :  public:
      75         379 :   explicit UnorderedStringMap(Zone* zone)
      76             :       : std::unordered_map<
      77             :             Handle<String>, Handle<Object>, StringHandleHash, StringHandleEqual,
      78             :             ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>>(
      79             :             2 /* bucket count */, StringHandleHash(), StringHandleEqual(),
      80             :             ZoneAllocator<std::pair<const Handle<String>, Handle<Object>>>(
      81         379 :                 zone)) {}
      82             : };
      83             : 
      84             : class Module::ResolveSet
      85             :     : public std::unordered_map<
      86             :           Handle<Module>, UnorderedStringSet*, ModuleHandleHash,
      87             :           ModuleHandleEqual,
      88             :           ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>> {
      89             :  public:
      90         826 :   explicit ResolveSet(Zone* zone)
      91             :       : std::unordered_map<Handle<Module>, UnorderedStringSet*,
      92             :                            ModuleHandleHash, ModuleHandleEqual,
      93             :                            ZoneAllocator<std::pair<const Handle<Module>,
      94             :                                                    UnorderedStringSet*>>>(
      95             :             2 /* bucket count */, ModuleHandleHash(), ModuleHandleEqual(),
      96             :             ZoneAllocator<std::pair<const Handle<Module>, UnorderedStringSet*>>(
      97             :                 zone)),
      98         826 :         zone_(zone) {}
      99             : 
     100             :   Zone* zone() const { return zone_; }
     101             : 
     102             :  private:
     103             :   Zone* zone_;
     104             : };
     105             : 
     106         110 : int Module::ExportIndex(int cell_index) {
     107             :   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
     108             :             ModuleDescriptor::kExport);
     109       32783 :   return cell_index - 1;
     110             : }
     111             : 
     112          31 : int Module::ImportIndex(int cell_index) {
     113             :   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
     114             :             ModuleDescriptor::kImport);
     115        1908 :   return -cell_index - 1;
     116             : }
     117             : 
     118         126 : void Module::CreateIndirectExport(Isolate* isolate, Handle<Module> module,
     119             :                                   Handle<String> name,
     120             :                                   Handle<ModuleInfoEntry> entry) {
     121         252 :   Handle<ObjectHashTable> exports(module->exports(), isolate);
     122             :   DCHECK(exports->Lookup(name)->IsTheHole(isolate));
     123         126 :   exports = ObjectHashTable::Put(exports, name, entry);
     124         126 :   module->set_exports(*exports);
     125         126 : }
     126             : 
     127       31329 : void Module::CreateExport(Isolate* isolate, Handle<Module> module,
     128             :                           int cell_index, Handle<FixedArray> names) {
     129             :   DCHECK_LT(0, names->length());
     130             :   Handle<Cell> cell =
     131       31329 :       isolate->factory()->NewCell(isolate->factory()->undefined_value());
     132       62658 :   module->regular_exports()->set(ExportIndex(cell_index), *cell);
     133             : 
     134       62658 :   Handle<ObjectHashTable> exports(module->exports(), isolate);
     135       62793 :   for (int i = 0, n = names->length(); i < n; ++i) {
     136             :     Handle<String> name(String::cast(names->get(i)), isolate);
     137             :     DCHECK(exports->Lookup(name)->IsTheHole(isolate));
     138       31464 :     exports = ObjectHashTable::Put(exports, name, cell);
     139             :   }
     140       31329 :   module->set_exports(*exports);
     141       31329 : }
     142             : 
     143        2553 : Cell Module::GetCell(int cell_index) {
     144             :   DisallowHeapAllocation no_gc;
     145             :   Object cell;
     146        2553 :   switch (ModuleDescriptor::GetCellIndexKind(cell_index)) {
     147             :     case ModuleDescriptor::kImport:
     148        2418 :       cell = regular_imports()->get(ImportIndex(cell_index));
     149        1209 :       break;
     150             :     case ModuleDescriptor::kExport:
     151        2688 :       cell = regular_exports()->get(ExportIndex(cell_index));
     152        1344 :       break;
     153             :     case ModuleDescriptor::kInvalid:
     154           0 :       UNREACHABLE();
     155             :       break;
     156             :   }
     157        2553 :   return Cell::cast(cell);
     158             : }
     159             : 
     160        2493 : Handle<Object> Module::LoadVariable(Isolate* isolate, Handle<Module> module,
     161             :                                     int cell_index) {
     162        4986 :   return handle(module->GetCell(cell_index)->value(), isolate);
     163             : }
     164             : 
     165          60 : void Module::StoreVariable(Handle<Module> module, int cell_index,
     166             :                            Handle<Object> value) {
     167             :   DCHECK_EQ(ModuleDescriptor::GetCellIndexKind(cell_index),
     168             :             ModuleDescriptor::kExport);
     169          60 :   module->GetCell(cell_index)->set_value(*value);
     170          60 : }
     171             : 
     172             : #ifdef DEBUG
     173             : void Module::PrintStatusTransition(Status new_status) {
     174             :   if (FLAG_trace_module_status) {
     175             :     StdoutStream os;
     176             :     os << "Changing module status from " << status() << " to " << new_status
     177             :        << " for ";
     178             :     script()->GetNameOrSourceURL()->Print(os);
     179             : #ifndef OBJECT_PRINT
     180             :     os << "\n";
     181             : #endif  // OBJECT_PRINT
     182             :   }
     183             : }
     184             : #endif  // DEBUG
     185             : 
     186           0 : void Module::SetStatus(Status new_status) {
     187             :   DisallowHeapAllocation no_alloc;
     188             :   DCHECK_LE(status(), new_status);
     189             :   DCHECK_NE(new_status, Module::kErrored);
     190             : #ifdef DEBUG
     191             :   PrintStatusTransition(new_status);
     192             : #endif  // DEBUG
     193        3035 :   set_status(new_status);
     194           0 : }
     195             : 
     196          45 : void Module::ResetGraph(Isolate* isolate, Handle<Module> module) {
     197             :   DCHECK_NE(module->status(), kInstantiating);
     198             :   DCHECK_NE(module->status(), kEvaluating);
     199          90 :   if (module->status() != kPreInstantiating) return;
     200          70 :   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
     201          35 :   Reset(isolate, module);
     202         170 :   for (int i = 0; i < requested_modules->length(); ++i) {
     203             :     Handle<Object> descendant(requested_modules->get(i), isolate);
     204         100 :     if (descendant->IsModule()) {
     205          25 :       ResetGraph(isolate, Handle<Module>::cast(descendant));
     206             :     } else {
     207             :       DCHECK(descendant->IsUndefined(isolate));
     208             :     }
     209             :   }
     210             : }
     211             : 
     212          72 : void Module::Reset(Isolate* isolate, Handle<Module> module) {
     213             :   Factory* factory = isolate->factory();
     214             : 
     215             :   DCHECK(module->status() == kPreInstantiating ||
     216             :          module->status() == kInstantiating);
     217             :   DCHECK(module->exception()->IsTheHole(isolate));
     218             :   DCHECK(module->import_meta()->IsTheHole(isolate));
     219             :   // The namespace object cannot exist, because it would have been created
     220             :   // by RunInitializationCode, which is called only after this module's SCC
     221             :   // succeeds instantiation.
     222             :   DCHECK(!module->module_namespace()->IsJSModuleNamespace());
     223             : 
     224             :   Handle<ObjectHashTable> exports =
     225          72 :       ObjectHashTable::New(isolate, module->info()->RegularExportCount());
     226             :   Handle<FixedArray> regular_exports =
     227         144 :       factory->NewFixedArray(module->regular_exports()->length());
     228             :   Handle<FixedArray> regular_imports =
     229         144 :       factory->NewFixedArray(module->regular_imports()->length());
     230             :   Handle<FixedArray> requested_modules =
     231         144 :       factory->NewFixedArray(module->requested_modules()->length());
     232             : 
     233          72 :   if (module->status() == kInstantiating) {
     234         111 :     module->set_code(JSFunction::cast(module->code())->shared());
     235             :   }
     236             : #ifdef DEBUG
     237             :   module->PrintStatusTransition(kUninstantiated);
     238             : #endif  // DEBUG
     239             :   module->set_status(kUninstantiated);
     240          72 :   module->set_exports(*exports);
     241          72 :   module->set_regular_exports(*regular_exports);
     242          72 :   module->set_regular_imports(*regular_imports);
     243          72 :   module->set_requested_modules(*requested_modules);
     244             :   module->set_dfs_index(-1);
     245             :   module->set_dfs_ancestor_index(-1);
     246          72 : }
     247             : 
     248          32 : void Module::RecordError(Isolate* isolate) {
     249             :   DisallowHeapAllocation no_alloc;
     250             :   DCHECK(exception()->IsTheHole(isolate));
     251          32 :   Object the_exception = isolate->pending_exception();
     252             :   DCHECK(!the_exception->IsTheHole(isolate));
     253             : 
     254          32 :   set_code(info());
     255             : #ifdef DEBUG
     256             :   PrintStatusTransition(Module::kErrored);
     257             : #endif  // DEBUG
     258             :   set_status(Module::kErrored);
     259          32 :   set_exception(the_exception);
     260          32 : }
     261             : 
     262          10 : Object Module::GetException() {
     263             :   DisallowHeapAllocation no_alloc;
     264             :   DCHECK_EQ(status(), Module::kErrored);
     265             :   DCHECK(!exception()->IsTheHole());
     266          24 :   return exception();
     267             : }
     268             : 
     269        6556 : SharedFunctionInfo Module::GetSharedFunctionInfo() const {
     270             :   DisallowHeapAllocation no_alloc;
     271             :   DCHECK_NE(status(), Module::kEvaluating);
     272             :   DCHECK_NE(status(), Module::kEvaluated);
     273        6556 :   switch (status()) {
     274             :     case kUninstantiated:
     275             :     case kPreInstantiating:
     276             :       DCHECK(code()->IsSharedFunctionInfo());
     277        3715 :       return SharedFunctionInfo::cast(code());
     278             :     case kInstantiating:
     279             :       DCHECK(code()->IsJSFunction());
     280        5174 :       return JSFunction::cast(code())->shared();
     281             :     case kInstantiated:
     282             :       DCHECK(code()->IsJSGeneratorObject());
     283         508 :       return JSGeneratorObject::cast(code())->function()->shared();
     284             :     case kEvaluating:
     285             :     case kEvaluated:
     286             :     case kErrored:
     287           0 :       UNREACHABLE();
     288             :   }
     289             : 
     290           0 :   UNREACHABLE();
     291             : }
     292             : 
     293         916 : MaybeHandle<Cell> Module::ResolveImport(Isolate* isolate, Handle<Module> module,
     294             :                                         Handle<String> name, int module_request,
     295             :                                         MessageLocation loc, bool must_resolve,
     296             :                                         Module::ResolveSet* resolve_set) {
     297             :   Handle<Module> requested_module(
     298        1832 :       Module::cast(module->requested_modules()->get(module_request)), isolate);
     299             :   Handle<String> specifier(
     300        1832 :       String::cast(module->info()->module_requests()->get(module_request)),
     301        1832 :       isolate);
     302             :   MaybeHandle<Cell> result =
     303             :       Module::ResolveExport(isolate, requested_module, specifier, name, loc,
     304         916 :                             must_resolve, resolve_set);
     305             :   DCHECK_IMPLIES(isolate->has_pending_exception(), result.is_null());
     306         916 :   return result;
     307             : }
     308             : 
     309        1042 : MaybeHandle<Cell> Module::ResolveExport(Isolate* isolate, Handle<Module> module,
     310             :                                         Handle<String> module_specifier,
     311             :                                         Handle<String> export_name,
     312             :                                         MessageLocation loc, bool must_resolve,
     313         230 :                                         Module::ResolveSet* resolve_set) {
     314             :   DCHECK_GE(module->status(), kPreInstantiating);
     315             :   DCHECK_NE(module->status(), kEvaluating);
     316        2084 :   Handle<Object> object(module->exports()->Lookup(export_name), isolate);
     317        2084 :   if (object->IsCell()) {
     318             :     // Already resolved (e.g. because it's a local export).
     319         803 :     return Handle<Cell>::cast(object);
     320             :   }
     321             : 
     322             :   // Check for cycle before recursing.
     323             :   {
     324             :     // Attempt insertion with a null string set.
     325         239 :     auto result = resolve_set->insert({module, nullptr});
     326             :     UnorderedStringSet*& name_set = result.first->second;
     327         239 :     if (result.second) {
     328             :       // |module| wasn't in the map previously, so allocate a new name set.
     329             :       Zone* zone = resolve_set->zone();
     330             :       name_set =
     331         230 :           new (zone->New(sizeof(UnorderedStringSet))) UnorderedStringSet(zone);
     332          18 :     } else if (name_set->count(export_name)) {
     333             :       // Cycle detected.
     334           9 :       if (must_resolve) {
     335             :         return isolate->Throw<Cell>(
     336             :             isolate->factory()->NewSyntaxError(
     337             :                 MessageTemplate::kCyclicModuleDependency, export_name,
     338             :                 module_specifier),
     339           0 :             &loc);
     340             :       }
     341           9 :       return MaybeHandle<Cell>();
     342             :     }
     343         230 :     name_set->insert(export_name);
     344             :   }
     345             : 
     346         460 :   if (object->IsModuleInfoEntry()) {
     347             :     // Not yet resolved indirect export.
     348         126 :     Handle<ModuleInfoEntry> entry = Handle<ModuleInfoEntry>::cast(object);
     349         252 :     Handle<String> import_name(String::cast(entry->import_name()), isolate);
     350         252 :     Handle<Script> script(module->script(), isolate);
     351         126 :     MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
     352             : 
     353             :     Handle<Cell> cell;
     354         126 :     if (!ResolveImport(isolate, module, import_name, entry->module_request(),
     355             :                        new_loc, true, resolve_set)
     356         252 :              .ToHandle(&cell)) {
     357             :       DCHECK(isolate->has_pending_exception());
     358           0 :       return MaybeHandle<Cell>();
     359             :     }
     360             : 
     361             :     // The export table may have changed but the entry in question should be
     362             :     // unchanged.
     363         252 :     Handle<ObjectHashTable> exports(module->exports(), isolate);
     364             :     DCHECK(exports->Lookup(export_name)->IsModuleInfoEntry());
     365             : 
     366         126 :     exports = ObjectHashTable::Put(exports, export_name, cell);
     367         126 :     module->set_exports(*exports);
     368         126 :     return cell;
     369             :   }
     370             : 
     371             :   DCHECK(object->IsTheHole(isolate));
     372             :   return Module::ResolveExportUsingStarExports(isolate, module,
     373             :                                                module_specifier, export_name,
     374         104 :                                                loc, must_resolve, resolve_set);
     375             : }
     376             : 
     377         104 : MaybeHandle<Cell> Module::ResolveExportUsingStarExports(
     378             :     Isolate* isolate, Handle<Module> module, Handle<String> module_specifier,
     379             :     Handle<String> export_name, MessageLocation loc, bool must_resolve,
     380             :     Module::ResolveSet* resolve_set) {
     381         104 :   if (!export_name->Equals(ReadOnlyRoots(isolate).default_string())) {
     382             :     // Go through all star exports looking for the given name.  If multiple star
     383             :     // exports provide the name, make sure they all map it to the same cell.
     384             :     Handle<Cell> unique_cell;
     385         190 :     Handle<FixedArray> special_exports(module->info()->special_exports(),
     386         190 :                                        isolate);
     387         239 :     for (int i = 0, n = special_exports->length(); i < n; ++i) {
     388             :       i::Handle<i::ModuleInfoEntry> entry(
     389             :           i::ModuleInfoEntry::cast(special_exports->get(i)), isolate);
     390         288 :       if (!entry->export_name()->IsUndefined(isolate)) {
     391          54 :         continue;  // Indirect export.
     392             :       }
     393             : 
     394         180 :       Handle<Script> script(module->script(), isolate);
     395          90 :       MessageLocation new_loc(script, entry->beg_pos(), entry->end_pos());
     396             : 
     397             :       Handle<Cell> cell;
     398          90 :       if (ResolveImport(isolate, module, export_name, entry->module_request(),
     399             :                         new_loc, false, resolve_set)
     400         180 :               .ToHandle(&cell)) {
     401          54 :         if (unique_cell.is_null()) unique_cell = cell;
     402          54 :         if (*unique_cell != *cell) {
     403             :           return isolate->Throw<Cell>(isolate->factory()->NewSyntaxError(
     404             :                                           MessageTemplate::kAmbiguousExport,
     405             :                                           module_specifier, export_name),
     406           0 :                                       &loc);
     407             :         }
     408          36 :       } else if (isolate->has_pending_exception()) {
     409           0 :         return MaybeHandle<Cell>();
     410             :       }
     411             :     }
     412             : 
     413          95 :     if (!unique_cell.is_null()) {
     414             :       // Found a unique star export for this name.
     415          90 :       Handle<ObjectHashTable> exports(module->exports(), isolate);
     416             :       DCHECK(exports->Lookup(export_name)->IsTheHole(isolate));
     417          45 :       exports = ObjectHashTable::Put(exports, export_name, unique_cell);
     418          45 :       module->set_exports(*exports);
     419          45 :       return unique_cell;
     420             :     }
     421             :   }
     422             : 
     423             :   // Unresolvable.
     424          59 :   if (must_resolve) {
     425             :     return isolate->Throw<Cell>(
     426             :         isolate->factory()->NewSyntaxError(MessageTemplate::kUnresolvableExport,
     427             :                                            module_specifier, export_name),
     428          32 :         &loc);
     429             :   }
     430          27 :   return MaybeHandle<Cell>();
     431             : }
     432             : 
     433        2170 : bool Module::Instantiate(Isolate* isolate, Handle<Module> module,
     434             :                          v8::Local<v8::Context> context,
     435             :                          v8::Module::ResolveCallback callback) {
     436             : #ifdef DEBUG
     437             :   if (FLAG_trace_module_status) {
     438             :     StdoutStream os;
     439             :     os << "Instantiating module ";
     440             :     module->script()->GetNameOrSourceURL()->Print(os);
     441             : #ifndef OBJECT_PRINT
     442             :     os << "\n";
     443             : #endif  // OBJECT_PRINT
     444             :   }
     445             : #endif  // DEBUG
     446             : 
     447        1095 :   if (!PrepareInstantiate(isolate, module, context, callback)) {
     448          20 :     ResetGraph(isolate, module);
     449          20 :     return false;
     450             :   }
     451        1075 :   Zone zone(isolate->allocator(), ZONE_NAME);
     452             :   ZoneForwardList<Handle<Module>> stack(&zone);
     453        1075 :   unsigned dfs_index = 0;
     454        1075 :   if (!FinishInstantiate(isolate, module, &stack, &dfs_index, &zone)) {
     455         101 :     for (auto& descendant : stack) {
     456          37 :       Reset(isolate, descendant);
     457             :     }
     458             :     DCHECK_EQ(module->status(), kUninstantiated);
     459             :     return false;
     460             :   }
     461             :   DCHECK(module->status() == kInstantiated || module->status() == kEvaluated ||
     462             :          module->status() == kErrored);
     463             :   DCHECK(stack.empty());
     464        1075 :   return true;
     465             : }
     466             : 
     467        2043 : bool Module::PrepareInstantiate(Isolate* isolate, Handle<Module> module,
     468             :                                 v8::Local<v8::Context> context,
     469             :                                 v8::Module::ResolveCallback callback) {
     470             :   DCHECK_NE(module->status(), kEvaluating);
     471             :   DCHECK_NE(module->status(), kInstantiating);
     472        2043 :   if (module->status() >= kPreInstantiating) return true;
     473             :   module->SetStatus(kPreInstantiating);
     474        1615 :   STACK_CHECK(isolate, false);
     475             : 
     476             :   // Obtain requested modules.
     477        3230 :   Handle<ModuleInfo> module_info(module->info(), isolate);
     478        3230 :   Handle<FixedArray> module_requests(module_info->module_requests(), isolate);
     479        3230 :   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
     480        2568 :   for (int i = 0, length = module_requests->length(); i < length; ++i) {
     481             :     Handle<String> specifier(String::cast(module_requests->get(i)), isolate);
     482             :     v8::Local<v8::Module> api_requested_module;
     483         973 :     if (!callback(context, v8::Utils::ToLocal(specifier),
     484             :                   v8::Utils::ToLocal(module))
     485         973 :              .ToLocal(&api_requested_module)) {
     486          20 :       isolate->PromoteScheduledException();
     487             :       return false;
     488             :     }
     489             :     Handle<Module> requested_module = Utils::OpenHandle(*api_requested_module);
     490        1906 :     requested_modules->set(i, *requested_module);
     491             :   }
     492             : 
     493             :   // Recurse.
     494        2533 :   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
     495             :     Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
     496             :                                     isolate);
     497         948 :     if (!PrepareInstantiate(isolate, requested_module, context, callback)) {
     498          10 :       return false;
     499             :     }
     500             :   }
     501             : 
     502             :   // Set up local exports.
     503             :   // TODO(neis): Create regular_exports array here instead of in factory method?
     504       32914 :   for (int i = 0, n = module_info->RegularExportCount(); i < n; ++i) {
     505       31329 :     int cell_index = module_info->RegularExportCellIndex(i);
     506             :     Handle<FixedArray> export_names(module_info->RegularExportExportNames(i),
     507       62658 :                                     isolate);
     508       31329 :     CreateExport(isolate, module, cell_index, export_names);
     509             :   }
     510             : 
     511             :   // Partially set up indirect exports.
     512             :   // For each indirect export, we create the appropriate slot in the export
     513             :   // table and store its ModuleInfoEntry there.  When we later find the correct
     514             :   // Cell in the module that actually provides the value, we replace the
     515             :   // ModuleInfoEntry by that Cell (see ResolveExport).
     516        3170 :   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
     517        1838 :   for (int i = 0, n = special_exports->length(); i < n; ++i) {
     518             :     Handle<ModuleInfoEntry> entry(
     519             :         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
     520         506 :     Handle<Object> export_name(entry->export_name(), isolate);
     521         506 :     if (export_name->IsUndefined(isolate)) continue;  // Star export.
     522             :     CreateIndirectExport(isolate, module, Handle<String>::cast(export_name),
     523         126 :                          entry);
     524             :   }
     525             : 
     526             :   DCHECK_EQ(module->status(), kPreInstantiating);
     527             :   return true;
     528             : }
     529             : 
     530        1543 : bool Module::RunInitializationCode(Isolate* isolate, Handle<Module> module) {
     531             :   DCHECK_EQ(module->status(), kInstantiating);
     532        3086 :   Handle<JSFunction> function(JSFunction::cast(module->code()), isolate);
     533             :   DCHECK_EQ(MODULE_SCOPE, function->shared()->scope_info()->scope_type());
     534             :   Handle<Object> receiver = isolate->factory()->undefined_value();
     535             :   Handle<Object> argv[] = {module};
     536             :   MaybeHandle<Object> maybe_generator =
     537        1543 :       Execution::Call(isolate, function, receiver, arraysize(argv), argv);
     538             :   Handle<Object> generator;
     539        1543 :   if (!maybe_generator.ToHandle(&generator)) {
     540             :     DCHECK(isolate->has_pending_exception());
     541             :     return false;
     542             :   }
     543             :   DCHECK_EQ(*function, Handle<JSGeneratorObject>::cast(generator)->function());
     544        1543 :   module->set_code(*generator);
     545        1543 :   return true;
     546             : }
     547             : 
     548        3035 : bool Module::MaybeTransitionComponent(Isolate* isolate, Handle<Module> module,
     549             :                                       ZoneForwardList<Handle<Module>>* stack,
     550             :                                       Status new_status) {
     551             :   DCHECK(new_status == kInstantiated || new_status == kEvaluated);
     552             :   SLOW_DCHECK(
     553             :       // {module} is on the {stack}.
     554             :       std::count_if(stack->begin(), stack->end(),
     555             :                     [&](Handle<Module> m) { return *m == *module; }) == 1);
     556             :   DCHECK_LE(module->dfs_ancestor_index(), module->dfs_index());
     557        3035 :   if (module->dfs_ancestor_index() == module->dfs_index()) {
     558             :     // This is the root of its strongly connected component.
     559             :     Handle<Module> ancestor;
     560        3035 :     do {
     561        3035 :       ancestor = stack->front();
     562             :       stack->pop_front();
     563             :       DCHECK_EQ(ancestor->status(),
     564             :                 new_status == kInstantiated ? kInstantiating : kEvaluating);
     565        3035 :       if (new_status == kInstantiated) {
     566        1543 :         if (!RunInitializationCode(isolate, ancestor)) return false;
     567             :       }
     568             :       ancestor->SetStatus(new_status);
     569             :     } while (*ancestor != *module);
     570             :   }
     571             :   return true;
     572             : }
     573             : 
     574        2003 : bool Module::FinishInstantiate(Isolate* isolate, Handle<Module> module,
     575             :                                ZoneForwardList<Handle<Module>>* stack,
     576             :                                unsigned* dfs_index, Zone* zone) {
     577             :   DCHECK_NE(module->status(), kEvaluating);
     578        2003 :   if (module->status() >= kInstantiating) return true;
     579             :   DCHECK_EQ(module->status(), kPreInstantiating);
     580        1580 :   STACK_CHECK(isolate, false);
     581             : 
     582             :   // Instantiate SharedFunctionInfo and mark module as instantiating for
     583             :   // the recursion.
     584             :   Handle<SharedFunctionInfo> shared(SharedFunctionInfo::cast(module->code()),
     585        3160 :                                     isolate);
     586             :   Handle<JSFunction> function =
     587             :       isolate->factory()->NewFunctionFromSharedFunctionInfo(
     588        3160 :           shared, isolate->native_context());
     589        3160 :   module->set_code(*function);
     590             :   module->SetStatus(kInstantiating);
     591        1580 :   module->set_dfs_index(*dfs_index);
     592        1580 :   module->set_dfs_ancestor_index(*dfs_index);
     593             :   stack->push_front(module);
     594        1580 :   (*dfs_index)++;
     595             : 
     596             :   // Recurse.
     597        3160 :   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
     598        2503 :   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
     599             :     Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
     600             :                                     isolate);
     601         928 :     if (!FinishInstantiate(isolate, requested_module, stack, dfs_index, zone)) {
     602             :       return false;
     603             :     }
     604             : 
     605             :     DCHECK_NE(requested_module->status(), kEvaluating);
     606             :     DCHECK_GE(requested_module->status(), kInstantiating);
     607             :     SLOW_DCHECK(
     608             :         // {requested_module} is instantiating iff it's on the {stack}.
     609             :         (requested_module->status() == kInstantiating) ==
     610             :         std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
     611             :           return *m == *requested_module;
     612             :         }));
     613             : 
     614         923 :     if (requested_module->status() == kInstantiating) {
     615             :       module->set_dfs_ancestor_index(
     616             :           std::min(module->dfs_ancestor_index(),
     617        1228 :                    requested_module->dfs_ancestor_index()));
     618             :     }
     619             :   }
     620             : 
     621        3150 :   Handle<Script> script(module->script(), isolate);
     622        3150 :   Handle<ModuleInfo> module_info(module->info(), isolate);
     623             : 
     624             :   // Resolve imports.
     625        3150 :   Handle<FixedArray> regular_imports(module_info->regular_imports(), isolate);
     626        2243 :   for (int i = 0, n = regular_imports->length(); i < n; ++i) {
     627             :     Handle<ModuleInfoEntry> entry(
     628             :         ModuleInfoEntry::cast(regular_imports->get(i)), isolate);
     629        1400 :     Handle<String> name(String::cast(entry->import_name()), isolate);
     630         700 :     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
     631         700 :     ResolveSet resolve_set(zone);
     632             :     Handle<Cell> cell;
     633         700 :     if (!ResolveImport(isolate, module, name, entry->module_request(), loc,
     634             :                        true, &resolve_set)
     635        1400 :              .ToHandle(&cell)) {
     636             :       return false;
     637             :     }
     638        1336 :     module->regular_imports()->set(ImportIndex(entry->cell_index()), *cell);
     639             :   }
     640             : 
     641             :   // Resolve indirect exports.
     642        3086 :   Handle<FixedArray> special_exports(module_info->special_exports(), isolate);
     643        1796 :   for (int i = 0, n = special_exports->length(); i < n; ++i) {
     644             :     Handle<ModuleInfoEntry> entry(
     645             :         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
     646         506 :     Handle<Object> name(entry->export_name(), isolate);
     647         633 :     if (name->IsUndefined(isolate)) continue;  // Star export.
     648         126 :     MessageLocation loc(script, entry->beg_pos(), entry->end_pos());
     649         126 :     ResolveSet resolve_set(zone);
     650         126 :     if (ResolveExport(isolate, module, Handle<String>(),
     651         252 :                       Handle<String>::cast(name), loc, true, &resolve_set)
     652         252 :             .is_null()) {
     653             :       return false;
     654             :     }
     655             :   }
     656             : 
     657        1543 :   return MaybeTransitionComponent(isolate, module, stack, kInstantiated);
     658             : }
     659             : 
     660        2402 : MaybeHandle<Object> Module::Evaluate(Isolate* isolate, Handle<Module> module) {
     661             : #ifdef DEBUG
     662             :   if (FLAG_trace_module_status) {
     663             :     StdoutStream os;
     664             :     os << "Evaluating module ";
     665             :     module->script()->GetNameOrSourceURL()->Print(os);
     666             : #ifndef OBJECT_PRINT
     667             :     os << "\n";
     668             : #endif  // OBJECT_PRINT
     669             :   }
     670             : #endif  // DEBUG
     671        1208 :   if (module->status() == kErrored) {
     672          28 :     isolate->Throw(module->GetException());
     673          14 :     return MaybeHandle<Object>();
     674             :   }
     675             :   DCHECK_NE(module->status(), kEvaluating);
     676             :   DCHECK_GE(module->status(), kInstantiated);
     677        1194 :   Zone zone(isolate->allocator(), ZONE_NAME);
     678             : 
     679             :   ZoneForwardList<Handle<Module>> stack(&zone);
     680        1194 :   unsigned dfs_index = 0;
     681             :   Handle<Object> result;
     682        2388 :   if (!Evaluate(isolate, module, &stack, &dfs_index).ToHandle(&result)) {
     683          96 :     for (auto& descendant : stack) {
     684             :       DCHECK_EQ(descendant->status(), kEvaluating);
     685          32 :       descendant->RecordError(isolate);
     686             :     }
     687             :     DCHECK_EQ(module->GetException(), isolate->pending_exception());
     688          32 :     return MaybeHandle<Object>();
     689             :   }
     690             :   DCHECK_EQ(module->status(), kEvaluated);
     691             :   DCHECK(stack.empty());
     692        2356 :   return result;
     693             : }
     694             : 
     695        2080 : MaybeHandle<Object> Module::Evaluate(Isolate* isolate, Handle<Module> module,
     696             :                                      ZoneForwardList<Handle<Module>>* stack,
     697             :                                      unsigned* dfs_index) {
     698        2080 :   if (module->status() == kErrored) {
     699           0 :     isolate->Throw(module->GetException());
     700           0 :     return MaybeHandle<Object>();
     701             :   }
     702        2080 :   if (module->status() >= kEvaluating) {
     703         556 :     return isolate->factory()->undefined_value();
     704             :   }
     705             :   DCHECK_EQ(module->status(), kInstantiated);
     706        1524 :   STACK_CHECK(isolate, MaybeHandle<Object>());
     707             : 
     708             :   Handle<JSGeneratorObject> generator(JSGeneratorObject::cast(module->code()),
     709        3048 :                                       isolate);
     710             :   module->set_code(
     711        3048 :       generator->function()->shared()->scope_info()->ModuleDescriptorInfo());
     712             :   module->SetStatus(kEvaluating);
     713        1524 :   module->set_dfs_index(*dfs_index);
     714        1524 :   module->set_dfs_ancestor_index(*dfs_index);
     715             :   stack->push_front(module);
     716        1524 :   (*dfs_index)++;
     717             : 
     718             :   // Recursion.
     719        3048 :   Handle<FixedArray> requested_modules(module->requested_modules(), isolate);
     720        2410 :   for (int i = 0, length = requested_modules->length(); i < length; ++i) {
     721             :     Handle<Module> requested_module(Module::cast(requested_modules->get(i)),
     722             :                                     isolate);
     723        1772 :     RETURN_ON_EXCEPTION(
     724             :         isolate, Evaluate(isolate, requested_module, stack, dfs_index), Object);
     725             : 
     726             :     DCHECK_GE(requested_module->status(), kEvaluating);
     727             :     DCHECK_NE(requested_module->status(), kErrored);
     728             :     SLOW_DCHECK(
     729             :         // {requested_module} is evaluating iff it's on the {stack}.
     730             :         (requested_module->status() == kEvaluating) ==
     731             :         std::count_if(stack->begin(), stack->end(), [&](Handle<Module> m) {
     732             :           return *m == *requested_module;
     733             :         }));
     734             : 
     735         886 :     if (requested_module->status() == kEvaluating) {
     736             :       module->set_dfs_ancestor_index(
     737             :           std::min(module->dfs_ancestor_index(),
     738        1136 :                    requested_module->dfs_ancestor_index()));
     739             :     }
     740             :   }
     741             : 
     742             :   // Evaluation of module body.
     743             :   Handle<JSFunction> resume(
     744        4572 :       isolate->native_context()->generator_next_internal(), isolate);
     745             :   Handle<Object> result;
     746        3048 :   ASSIGN_RETURN_ON_EXCEPTION(
     747             :       isolate, result, Execution::Call(isolate, resume, generator, 0, nullptr),
     748             :       Object);
     749             :   DCHECK(JSIteratorResult::cast(*result)->done()->BooleanValue(isolate));
     750             : 
     751        1492 :   CHECK(MaybeTransitionComponent(isolate, module, stack, kEvaluated));
     752        2984 :   return handle(JSIteratorResult::cast(*result)->value(), isolate);
     753             : }
     754             : 
     755             : namespace {
     756             : 
     757         397 : void FetchStarExports(Isolate* isolate, Handle<Module> module, Zone* zone,
     758             :                       UnorderedModuleSet* visited) {
     759             :   DCHECK_GE(module->status(), Module::kInstantiating);
     760             : 
     761         812 :   if (module->module_namespace()->IsJSModuleNamespace()) return;  // Shortcut.
     762             : 
     763         388 :   bool cycle = !visited->insert(module).second;
     764         388 :   if (cycle) return;
     765         758 :   Handle<ObjectHashTable> exports(module->exports(), isolate);
     766         379 :   UnorderedStringMap more_exports(zone);
     767             : 
     768             :   // TODO(neis): Only allocate more_exports if there are star exports.
     769             :   // Maybe split special_exports into indirect_exports and star_exports.
     770             : 
     771             :   ReadOnlyRoots roots(isolate);
     772         758 :   Handle<FixedArray> special_exports(module->info()->special_exports(),
     773         758 :                                      isolate);
     774         469 :   for (int i = 0, n = special_exports->length(); i < n; ++i) {
     775             :     Handle<ModuleInfoEntry> entry(
     776             :         ModuleInfoEntry::cast(special_exports->get(i)), isolate);
     777         180 :     if (!entry->export_name()->IsUndefined(roots)) {
     778             :       continue;  // Indirect export.
     779             :     }
     780             : 
     781             :     Handle<Module> requested_module(
     782         126 :         Module::cast(module->requested_modules()->get(entry->module_request())),
     783         126 :         isolate);
     784             : 
     785             :     // Recurse.
     786          63 :     FetchStarExports(isolate, requested_module, zone, visited);
     787             : 
     788             :     // Collect all of [requested_module]'s exports that must be added to
     789             :     // [module]'s exports (i.e. to [exports]).  We record these in
     790             :     // [more_exports].  Ambiguities (conflicting exports) are marked by mapping
     791             :     // the name to undefined instead of a Cell.
     792             :     Handle<ObjectHashTable> requested_exports(requested_module->exports(),
     793         126 :                                               isolate);
     794         495 :     for (int i = 0, n = requested_exports->Capacity(); i < n; ++i) {
     795         432 :       Object key;
     796         729 :       if (!requested_exports->ToKey(roots, i, &key)) continue;
     797             :       Handle<String> name(String::cast(key), isolate);
     798             : 
     799         180 :       if (name->Equals(roots.default_string())) continue;
     800         306 :       if (!exports->Lookup(name)->IsTheHole(roots)) continue;
     801             : 
     802         270 :       Handle<Cell> cell(Cell::cast(requested_exports->ValueAt(i)), isolate);
     803         270 :       auto insert_result = more_exports.insert(std::make_pair(name, cell));
     804         135 :       if (!insert_result.second) {
     805             :         auto it = insert_result.first;
     806          36 :         if (*it->second == *cell || it->second->IsUndefined(roots)) {
     807             :           // We already recorded this mapping before, or the name is already
     808             :           // known to be ambiguous.  In either case, there's nothing to do.
     809             :         } else {
     810             :           DCHECK(it->second->IsCell());
     811             :           // Different star exports provide different cells for this name, hence
     812             :           // mark the name as ambiguous.
     813           9 :           it->second = roots.undefined_value_handle();
     814             :         }
     815             :       }
     816             :     }
     817             :   }
     818             : 
     819             :   // Copy [more_exports] into [exports].
     820         875 :   for (const auto& elem : more_exports) {
     821         234 :     if (elem.second->IsUndefined(isolate)) continue;  // Ambiguous export.
     822             :     DCHECK(!elem.first->Equals(ReadOnlyRoots(isolate).default_string()));
     823             :     DCHECK(elem.second->IsCell());
     824         108 :     exports = ObjectHashTable::Put(exports, elem.first, elem.second);
     825             :   }
     826         379 :   module->set_exports(*exports);
     827             : }
     828             : 
     829             : }  // anonymous namespace
     830             : 
     831         225 : Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
     832             :                                                      Handle<Module> module,
     833             :                                                      int module_request) {
     834             :   Handle<Module> requested_module(
     835         450 :       Module::cast(module->requested_modules()->get(module_request)), isolate);
     836         225 :   return Module::GetModuleNamespace(isolate, requested_module);
     837             : }
     838             : 
     839         451 : Handle<JSModuleNamespace> Module::GetModuleNamespace(Isolate* isolate,
     840             :                                                      Handle<Module> module) {
     841        1687 :   Handle<HeapObject> object(module->module_namespace(), isolate);
     842         451 :   ReadOnlyRoots roots(isolate);
     843         902 :   if (!object->IsUndefined(roots)) {
     844             :     // Namespace object already exists.
     845         117 :     return Handle<JSModuleNamespace>::cast(object);
     846             :   }
     847             : 
     848             :   // Collect the export names.
     849         668 :   Zone zone(isolate->allocator(), ZONE_NAME);
     850         334 :   UnorderedModuleSet visited(&zone);
     851         334 :   FetchStarExports(isolate, module, &zone, &visited);
     852        1002 :   Handle<ObjectHashTable> exports(module->exports(), isolate);
     853             :   ZoneVector<Handle<String>> names(&zone);
     854         334 :   names.reserve(exports->NumberOfElements());
     855       57238 :   for (int i = 0, n = exports->Capacity(); i < n; ++i) {
     856       56904 :     Object key;
     857       83457 :     if (!exports->ToKey(roots, i, &key)) continue;
     858       91053 :     names.push_back(handle(String::cast(key), isolate));
     859             :   }
     860             :   DCHECK_EQ(static_cast<int>(names.size()), exports->NumberOfElements());
     861             : 
     862             :   // Sort them alphabetically.
     863             :   std::sort(names.begin(), names.end(),
     864             :             [&isolate](Handle<String> a, Handle<String> b) {
     865      380781 :               return String::Compare(isolate, a, b) ==
     866             :                      ComparisonResult::kLessThan;
     867         668 :             });
     868             : 
     869             :   // Create the namespace object (initially empty).
     870         334 :   Handle<JSModuleNamespace> ns = isolate->factory()->NewJSModuleNamespace();
     871         334 :   ns->set_module(*module);
     872         668 :   module->set_module_namespace(*ns);
     873             : 
     874             :   // Create the properties in the namespace object. Transition the object
     875             :   // to dictionary mode so that property addition is faster.
     876             :   PropertyAttributes attr = DONT_DELETE;
     877             :   JSObject::NormalizeProperties(ns, CLEAR_INOBJECT_PROPERTIES,
     878         334 :                                 static_cast<int>(names.size()),
     879         668 :                                 "JSModuleNamespace");
     880       31019 :   for (const auto& name : names) {
     881             :     JSObject::SetNormalizedProperty(
     882             :         ns, name, Accessors::MakeModuleNamespaceEntryInfo(isolate, name),
     883       60702 :         PropertyDetails(kAccessor, attr, PropertyCellType::kMutable));
     884             :   }
     885         668 :   JSObject::PreventExtensions(ns, kThrowOnError).ToChecked();
     886             : 
     887             :   // Optimize the namespace object as a prototype, for two reasons:
     888             :   // - The object's map is guaranteed not to be shared. ICs rely on this.
     889             :   // - We can store a pointer from the map back to the namespace object.
     890             :   //   Turbofan can use this for inlining the access.
     891         334 :   JSObject::OptimizeAsPrototype(ns);
     892             : 
     893             :   Handle<PrototypeInfo> proto_info =
     894         334 :       Map::GetOrCreatePrototypeInfo(Handle<JSObject>::cast(ns), isolate);
     895         668 :   proto_info->set_module_namespace(*ns);
     896         668 :   return ns;
     897             : }
     898             : 
     899       31478 : MaybeHandle<Object> JSModuleNamespace::GetExport(Isolate* isolate,
     900             :                                                  Handle<String> name) {
     901       62956 :   Handle<Object> object(module()->exports()->Lookup(name), isolate);
     902       62956 :   if (object->IsTheHole(isolate)) {
     903           0 :     return isolate->factory()->undefined_value();
     904             :   }
     905             : 
     906       94434 :   Handle<Object> value(Handle<Cell>::cast(object)->value(), isolate);
     907       62956 :   if (value->IsTheHole(isolate)) {
     908         122 :     THROW_NEW_ERROR(
     909             :         isolate, NewReferenceError(MessageTemplate::kNotDefined, name), Object);
     910             :   }
     911             : 
     912       31356 :   return value;
     913             : }
     914             : 
     915         837 : Maybe<PropertyAttributes> JSModuleNamespace::GetPropertyAttributes(
     916         837 :     LookupIterator* it) {
     917             :   Handle<JSModuleNamespace> object = it->GetHolder<JSModuleNamespace>();
     918         837 :   Handle<String> name = Handle<String>::cast(it->GetName());
     919             :   DCHECK_EQ(it->state(), LookupIterator::ACCESSOR);
     920             : 
     921             :   Isolate* isolate = it->isolate();
     922             : 
     923        1674 :   Handle<Object> lookup(object->module()->exports()->Lookup(name), isolate);
     924        1674 :   if (lookup->IsTheHole(isolate)) {
     925             :     return Just(ABSENT);
     926             :   }
     927             : 
     928        2511 :   Handle<Object> value(Handle<Cell>::cast(lookup)->value(), isolate);
     929        1674 :   if (value->IsTheHole(isolate)) {
     930             :     isolate->Throw(*isolate->factory()->NewReferenceError(
     931         324 :         MessageTemplate::kNotDefined, name));
     932             :     return Nothing<PropertyAttributes>();
     933             :   }
     934             : 
     935             :   return Just(it->property_attributes());
     936             : }
     937             : 
     938             : }  // namespace internal
     939      183867 : }  // namespace v8

Generated by: LCOV version 1.10