LCOV - code coverage report
Current view: top level - src/objects - module.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 267 275 97.1 %
Date: 2019-04-17 Functions: 29 30 96.7 %

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

Generated by: LCOV version 1.10