fb36428f2a7a7fcf01fd2e5e33322ec25d7ca2e4
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSModuleRecord.cpp
1 /*
2  * Copyright (C) 2015 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "JSModuleRecord.h"
28
29 #include "Error.h"
30 #include "Executable.h"
31 #include "IdentifierInlines.h"
32 #include "JSCJSValueInlines.h"
33 #include "JSCellInlines.h"
34 #include "JSMap.h"
35 #include "JSModuleEnvironment.h"
36 #include "JSModuleNamespaceObject.h"
37 #include "SlotVisitorInlines.h"
38 #include "StructureInlines.h"
39
40 namespace JSC {
41
42 const ClassInfo JSModuleRecord::s_info = { "ModuleRecord", &Base::s_info, 0, CREATE_METHOD_TABLE(JSModuleRecord) };
43
44 void JSModuleRecord::destroy(JSCell* cell)
45 {
46     JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell);
47     thisObject->JSModuleRecord::~JSModuleRecord();
48 }
49
50 void JSModuleRecord::finishCreation(VM& vm)
51 {
52     Base::finishCreation(vm);
53     ASSERT(inherits(info()));
54     putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("registryEntry")), jsUndefined());
55     putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("evaluated")), jsBoolean(false));
56
57     m_dependenciesMap.set(vm, this, JSMap::create(vm, globalObject()->mapStructure()));
58     putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("dependenciesMap")), m_dependenciesMap.get());
59 }
60
61 void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
62 {
63     JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell);
64     Base::visitChildren(thisObject, visitor);
65     visitor.append(&thisObject->m_moduleEnvironment);
66     visitor.append(&thisObject->m_moduleNamespaceObject);
67     visitor.append(&thisObject->m_moduleProgramExecutable);
68     visitor.append(&thisObject->m_dependenciesMap);
69 }
70
71 void JSModuleRecord::appendRequestedModule(const Identifier& moduleName)
72 {
73     m_requestedModules.add(moduleName.impl());
74 }
75
76 void JSModuleRecord::addStarExportEntry(const Identifier& moduleName)
77 {
78     m_starExportEntries.add(moduleName.impl());
79 }
80
81 void JSModuleRecord::addImportEntry(const ImportEntry& entry)
82 {
83     bool isNewEntry = m_importEntries.add(entry.localName.impl(), entry).isNewEntry;
84     ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser.
85 }
86
87 void JSModuleRecord::addExportEntry(const ExportEntry& entry)
88 {
89     bool isNewEntry = m_exportEntries.add(entry.exportName.impl(), entry).isNewEntry;
90     ASSERT_UNUSED(isNewEntry, isNewEntry); // This is guaranteed by the parser.
91 }
92
93 auto JSModuleRecord::tryGetImportEntry(UniquedStringImpl* localName) -> Optional<ImportEntry>
94 {
95     const auto iterator = m_importEntries.find(localName);
96     if (iterator == m_importEntries.end())
97         return Nullopt;
98     return Optional<ImportEntry>(iterator->value);
99 }
100
101 auto JSModuleRecord::tryGetExportEntry(UniquedStringImpl* exportName) -> Optional<ExportEntry>
102 {
103     const auto iterator = m_exportEntries.find(exportName);
104     if (iterator == m_exportEntries.end())
105         return Nullopt;
106     return Optional<ExportEntry>(iterator->value);
107 }
108
109 auto JSModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName, const VariableEnvironmentEntry& variable) -> ExportEntry
110 {
111     return ExportEntry { Type::Local, exportName, Identifier(), Identifier(), localName, variable };
112 }
113
114 auto JSModuleRecord::ExportEntry::createNamespace(const Identifier& exportName, const Identifier& moduleName) -> ExportEntry
115 {
116     return ExportEntry { Type::Namespace, exportName, moduleName, Identifier(), Identifier(), VariableEnvironmentEntry() };
117 }
118
119 auto JSModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, const Identifier& importName, const Identifier& moduleName) -> ExportEntry
120 {
121     return ExportEntry { Type::Indirect, exportName, moduleName, importName, Identifier(), VariableEnvironmentEntry() };
122 }
123
124 auto JSModuleRecord::Resolution::notFound() -> Resolution
125 {
126     return Resolution { Type::NotFound, nullptr, Identifier() };
127 }
128
129 auto JSModuleRecord::Resolution::error() -> Resolution
130 {
131     return Resolution { Type::Error, nullptr, Identifier() };
132 }
133
134 auto JSModuleRecord::Resolution::ambiguous() -> Resolution
135 {
136     return Resolution { Type::Ambiguous, nullptr, Identifier() };
137 }
138
139 static JSValue identifierToJSValue(ExecState* exec, const Identifier& identifier)
140 {
141     if (identifier.isSymbol())
142         return Symbol::create(exec->vm(), static_cast<SymbolImpl&>(*identifier.impl()));
143     return jsString(&exec->vm(), identifier.impl());
144 }
145
146 JSModuleRecord* JSModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)
147 {
148     JSValue moduleNameValue = identifierToJSValue(exec, moduleName);
149     JSValue pair = m_dependenciesMap->JSMap::get(exec, moduleNameValue);
150     return jsCast<JSModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value")));
151 }
152
153 auto JSModuleRecord::resolveImport(ExecState* exec, const Identifier& localName) -> Resolution
154 {
155     Optional<ImportEntry> optionalImportEntry = tryGetImportEntry(localName.impl());
156     if (!optionalImportEntry)
157         return Resolution::notFound();
158
159     const ImportEntry& importEntry = *optionalImportEntry;
160     if (importEntry.isNamespace(exec->vm()))
161         return Resolution::notFound();
162
163     JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
164     return importedModule->resolveExport(exec, importEntry.importName);
165 }
166
167 struct ResolveQuery {
168     ResolveQuery(JSModuleRecord* moduleRecord, UniquedStringImpl* exportName)
169         : moduleRecord(moduleRecord)
170         , exportName(exportName)
171     {
172     }
173
174     ResolveQuery(JSModuleRecord* moduleRecord, const Identifier& exportName)
175         : ResolveQuery(moduleRecord, exportName.impl())
176     {
177     }
178
179     enum EmptyValueTag { EmptyValue };
180     ResolveQuery(EmptyValueTag)
181     {
182     }
183
184     enum DeletedValueTag { DeletedValue };
185     ResolveQuery(DeletedValueTag)
186         : moduleRecord(nullptr)
187         , exportName(WTF::HashTableDeletedValue)
188     {
189     }
190
191     bool isEmptyValue() const
192     {
193         return !exportName;
194     }
195
196     bool isDeletedValue() const
197     {
198         return exportName.isHashTableDeletedValue();
199     }
200
201     // The module record is not marked from the GC. But these records are reachable from the JSGlobalObject.
202     // So we don't care the reachability to this record.
203     JSModuleRecord* moduleRecord;
204     RefPtr<UniquedStringImpl> exportName;
205 };
206
207 struct ResolveQueryHash {
208     static unsigned hash(const ResolveQuery&);
209     static bool equal(const ResolveQuery&, const ResolveQuery&);
210     static const bool safeToCompareToEmptyOrDeleted = true;
211 };
212
213 inline unsigned ResolveQueryHash::hash(const ResolveQuery& query)
214 {
215     return WTF::PtrHash<JSModuleRecord*>::hash(query.moduleRecord) + IdentifierRepHash::hash(query.exportName);
216 }
217
218 inline bool ResolveQueryHash::equal(const ResolveQuery& lhs, const ResolveQuery& rhs)
219 {
220     return lhs.moduleRecord == rhs.moduleRecord && lhs.exportName == rhs.exportName;
221 }
222
223 static JSModuleRecord::Resolution resolveExportLoop(ExecState* exec, const ResolveQuery& root)
224 {
225     // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport
226     // This function avoids C++ recursion of the naive ResolveExport implementation.
227     // Flatten the recursion to the loop with the task queue and frames.
228     //
229     // 1. pendingTasks
230     //     We enqueue the recursive resolveExport call to this queue to avoid recursive calls in C++.
231     //     The task has 3 types. (1) Query, (2) IndirectFallback and (3) GatherStars.
232     //     (1) Query
233     //         Querying the resolution to the current module.
234     //     (2) IndirectFallback
235     //         Examine the result of the indirect export resolution. Only when the indirect export resolution fails,
236     //         we look into the star exports. (step 5-a-vi).
237     //     (3) GatherStars
238     //         Examine the result of the star export resolutions.
239     //
240     // 2. frames
241     //     When the spec calls the resolveExport recursively, instead we append the frame
242     //     (that holds the result resolution) to the frames and enqueue the task to the pendingTasks.
243     //     The entry in the frames means the *local* resolution result of the specific recursive resolveExport.
244     //
245     // We should maintain the local resolution result instead of holding the global resolution result only.
246     // For example,
247     //
248     //     star
249     // (1) ---> (2) "Resolve"
250     //      |
251     //      |
252     //      +-> (3) "NotFound"
253     //      |
254     //      |       star
255     //      +-> (4) ---> (5) "Resolve" [here]
256     //               |
257     //               |
258     //               +-> (6) "Error"
259     //
260     // Consider the above graph. The numbers represents the modules. Now we are [here].
261     // If we only hold the global resolution result during the resolveExport operation, [here],
262     // we decide the entire result of resolveExport is "Ambiguous", because there are multiple
263     // "Reslove" (in module (2) and (5)). However, this should become "Error" because (6) will
264     // propagate "Error" state to the (4), (4) will become "Error" and then, (1) will become
265     // "Error". We should aggregate the results at the star exports point ((4) and (1)).
266     //
267     // Usually, both "Error" and "Ambiguous" states will throw the syntax error. So except for the content of the
268     // error message, there are no difference. (And if we fix the (6) that raises "Error", next, it will produce
269     // the "Ambiguous" error due to (5). Anyway, user need to fix the both. So which error should be raised at first
270     // doesn't matter so much.
271     //
272     // However, this may become the problem under the module namespace creation.
273     // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace
274     // section 15.2.1.18, step 3-d-ii
275     // Here, we distinguish "Ambiguous" and "Error". When "Error" state is produced, we need to throw the propagated error.
276     // But if "Ambiguous" state comes, we just ignore the result.
277     // To follow the requirement strictly, in this implementation, we keep the local resolution result to produce the
278     // correct result under the above complex cases.
279
280     using Resolution = JSModuleRecord::Resolution;
281     typedef WTF::HashSet<ResolveQuery, ResolveQueryHash, WTF::CustomHashTraits<ResolveQuery>> ResolveSet;
282     enum class Type { Query, IndirectFallback, GatherStars };
283     struct Task {
284         ResolveQuery query;
285         Type type;
286     };
287
288     Vector<Task, 8> pendingTasks;
289     ResolveSet resolveSet;
290     HashSet<JSModuleRecord*> starSet;
291     Vector<Resolution, 8> frames;
292
293     frames.append(Resolution::notFound());
294
295     // Call when the query is not resolved in the current module.
296     // It will enqueue the star resolution requests. Return "false" if the error occurs.
297     auto resolveNonLocal = [&](const ResolveQuery& query) -> bool {
298         // http://www.ecma-international.org/ecma-262/6.0/#sec-resolveexport
299         // section 15.2.1.16.3, step 6
300         // If the "default" name is not resolved in the current module, we need to throw an error and stop resolution immediately,
301         // Rationale to this error: A default export cannot be provided by an export *.
302         if (query.exportName == exec->propertyNames().defaultKeyword.impl())
303             return false;
304
305         // step 7, If exportStarSet contains module, then return null.
306         if (!starSet.add(query.moduleRecord).isNewEntry)
307             return true;
308
309         // Enqueue the task to gather the results of the stars.
310         // And append the new Resolution frame to gather the local result of the stars.
311         pendingTasks.append(Task { query, Type::GatherStars });
312         frames.append(Resolution::notFound());
313
314         // Enqueue the tasks in reverse order.
315         for (auto iterator = query.moduleRecord->starExportEntries().rbegin(), end = query.moduleRecord->starExportEntries().rend(); iterator != end; ++iterator) {
316             const RefPtr<UniquedStringImpl>& starModuleName = *iterator;
317             JSModuleRecord* importedModuleRecord = query.moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));
318             pendingTasks.append(Task { ResolveQuery(importedModuleRecord, query.exportName.get()), Type::Query });
319         }
320         return true;
321     };
322
323     // Return the current resolution value of the top frame.
324     auto currentTop = [&] () -> Resolution& {
325         ASSERT(!frames.isEmpty());
326         return frames.last();
327     };
328
329     // Merge the given resolution to the current resolution value of the top frame.
330     // If there is ambiguity, return "false". When the "false" is returned, we should make the result "ambiguous".
331     auto mergeToCurrentTop = [&] (const Resolution& resolution) -> bool {
332         if (resolution.type == Resolution::Type::NotFound)
333             return true;
334
335         if (currentTop().type == Resolution::Type::NotFound) {
336             currentTop() = resolution;
337             return true;
338         }
339
340         if (currentTop().moduleRecord != resolution.moduleRecord || currentTop().localName != resolution.localName)
341             return false;
342
343         return true;
344     };
345
346     pendingTasks.append(Task { root, Type::Query });
347     while (!pendingTasks.isEmpty()) {
348         const Task task = pendingTasks.takeLast();
349         const ResolveQuery& query = task.query;
350
351         switch (task.type) {
352         case Type::Query: {
353             if (!resolveSet.add(task.query).isNewEntry)
354                 continue;
355
356             JSModuleRecord* moduleRecord = query.moduleRecord;
357             const Optional<JSModuleRecord::ExportEntry> optionalExportEntry = moduleRecord->tryGetExportEntry(query.exportName.get());
358             if (!optionalExportEntry) {
359                 // If there is no matched exported binding in the current module,
360                 // we need to look into the stars.
361                 if (!resolveNonLocal(task.query))
362                     return Resolution::error();
363                 continue;
364             }
365
366             const JSModuleRecord::ExportEntry& exportEntry = *optionalExportEntry;
367             switch (exportEntry.type) {
368             case JSModuleRecord::ExportEntry::Type::Local:
369             case JSModuleRecord::ExportEntry::Type::Namespace:
370                 if (!mergeToCurrentTop(Resolution { Resolution::Type::Resolved, moduleRecord, exportEntry.localName }))
371                     return Resolution::ambiguous();
372                 continue;
373
374             case JSModuleRecord::ExportEntry::Type::Indirect: {
375                 JSModuleRecord* importedModuleRecord = moduleRecord->hostResolveImportedModule(exec, exportEntry.moduleName);
376
377                 // When the imported module does not produce any resolved binding, we need to look into the stars in the *current*
378                 // module. To do this, we append the `IndirectFallback` task to the task queue.
379                 pendingTasks.append(Task { query, Type::IndirectFallback });
380                 // And append the new Resolution frame to check the indirect export will be resolved or not.
381                 frames.append(Resolution::notFound());
382                 pendingTasks.append(Task { ResolveQuery(importedModuleRecord, exportEntry.importName), Type::Query });
383                 continue;
384             }
385             }
386             break;
387         }
388
389         case Type::IndirectFallback: {
390             JSModuleRecord::Resolution resolution = frames.takeLast();
391
392             if (resolution.type == Resolution::Type::NotFound) {
393                 // Indirect export entry does not produce any resolved binding.
394                 // So we will investigate the stars.
395                 if (!resolveNonLocal(task.query))
396                     return Resolution::error();
397                 continue;
398             }
399
400             // If indirect export entry produces Resolved, we should merge it to the upper frame.
401             // And do not investigate the stars of the current module.
402             if (!mergeToCurrentTop(resolution))
403                 return Resolution::ambiguous();
404             break;
405         }
406
407         case Type::GatherStars: {
408             // Merge the star resolution to the upper frame.
409             JSModuleRecord::Resolution starResolution = frames.takeLast();
410             if (!mergeToCurrentTop(starResolution))
411                 return Resolution::ambiguous();
412             break;
413         }
414         }
415     }
416
417     ASSERT(frames.size() == 1);
418     return frames[0];
419 }
420
421 auto JSModuleRecord::resolveExport(ExecState* exec, const Identifier& exportName) -> Resolution
422 {
423     return resolveExportLoop(exec, ResolveQuery(this, exportName.impl()));
424 }
425
426 static void getExportedNames(ExecState* exec, JSModuleRecord* root, IdentifierSet& exportedNames)
427 {
428     HashSet<JSModuleRecord*> exportStarSet;
429     Vector<JSModuleRecord*, 8> pendingModules;
430
431     pendingModules.append(root);
432
433     while (!pendingModules.isEmpty()) {
434         JSModuleRecord* moduleRecord = pendingModules.takeLast();
435         if (exportStarSet.contains(moduleRecord))
436             continue;
437         exportStarSet.add(moduleRecord);
438
439         for (const auto& pair : moduleRecord->exportEntries()) {
440             const JSModuleRecord::ExportEntry& exportEntry = pair.value;
441             switch (exportEntry.type) {
442             case JSModuleRecord::ExportEntry::Type::Local:
443             case JSModuleRecord::ExportEntry::Type::Indirect:
444                 if (moduleRecord == root || exec->propertyNames().defaultKeyword != exportEntry.exportName)
445                     exportedNames.add(exportEntry.exportName.impl());
446                 break;
447
448             case JSModuleRecord::ExportEntry::Type::Namespace:
449                 break;
450             }
451         }
452
453         for (const auto& starModuleName : moduleRecord->starExportEntries()) {
454             JSModuleRecord* requestedModuleRecord = moduleRecord->hostResolveImportedModule(exec, Identifier::fromUid(exec, starModuleName.get()));
455             pendingModules.append(requestedModuleRecord);
456         }
457     }
458 }
459
460 JSModuleNamespaceObject* JSModuleRecord::getModuleNamespace(ExecState* exec)
461 {
462     // http://www.ecma-international.org/ecma-262/6.0/#sec-getmodulenamespace
463     if (m_moduleNamespaceObject)
464         return m_moduleNamespaceObject.get();
465
466     JSGlobalObject* globalObject = exec->lexicalGlobalObject();
467     IdentifierSet exportedNames;
468     getExportedNames(exec, this, exportedNames);
469
470     IdentifierSet unambiguousNames;
471     for (auto& name : exportedNames) {
472         const JSModuleRecord::Resolution resolution = resolveExport(exec, Identifier::fromUid(exec, name.get()));
473         switch (resolution.type) {
474         case Resolution::Type::NotFound:
475             throwSyntaxError(exec, makeString("Exported binding name '", String(name.get()), "' is not found."));
476             return nullptr;
477
478         case Resolution::Type::Error:
479             throwSyntaxError(exec, makeString("Exported binding name 'default' cannot be resolved by star export entries."));
480             return nullptr;
481
482         case Resolution::Type::Ambiguous:
483             break;
484
485         case Resolution::Type::Resolved:
486             unambiguousNames.add(name);
487             break;
488         }
489     }
490
491     m_moduleNamespaceObject.set(exec->vm(), this, JSModuleNamespaceObject::create(exec, globalObject, globalObject->moduleNamespaceObjectStructure(), this, unambiguousNames));
492     return m_moduleNamespaceObject.get();
493 }
494
495 void JSModuleRecord::link(ExecState* exec)
496 {
497     ModuleProgramExecutable* executable = ModuleProgramExecutable::create(exec, sourceCode());
498     if (!executable) {
499         throwSyntaxError(exec);
500         return;
501     }
502     m_moduleProgramExecutable.set(exec->vm(), this, executable);
503     instantiateDeclarations(exec, executable);
504 }
505
506 void JSModuleRecord::instantiateDeclarations(ExecState* exec, ModuleProgramExecutable* moduleProgramExecutable)
507 {
508     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
509
510     SymbolTable* symbolTable = moduleProgramExecutable->moduleEnvironmentSymbolTable();
511     JSModuleEnvironment* moduleEnvironment = JSModuleEnvironment::create(exec->vm(), exec->lexicalGlobalObject(), exec->lexicalGlobalObject(), symbolTable, jsTDZValue(), this);
512
513     VM& vm = exec->vm();
514
515     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
516     // section 15.2.1.16.4 step 9.
517     // Ensure all the indirect exports are correctly resolved to unique bindings.
518     // Even if we avoided duplicate exports in the parser, still ambiguous exports occur due to the star export (`export * from "mod"`).
519     // When we see this type of ambiguity for the indirect exports here, throw a syntax error.
520     for (const auto& pair : m_exportEntries) {
521         const ExportEntry& exportEntry = pair.value;
522         if (exportEntry.type == JSModuleRecord::ExportEntry::Type::Indirect) {
523             Resolution resolution = resolveExport(exec, exportEntry.exportName);
524             switch (resolution.type) {
525             case Resolution::Type::NotFound:
526                 throwSyntaxError(exec, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' is not found."));
527                 return;
528
529             case Resolution::Type::Ambiguous:
530                 throwSyntaxError(exec, makeString("Indirectly exported binding name '", String(exportEntry.exportName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));
531                 return;
532
533             case Resolution::Type::Error:
534                 throwSyntaxError(exec, makeString("Indirectly exported binding name 'default' cannot be resolved by star export entries."));
535                 return;
536
537             case Resolution::Type::Resolved:
538                 break;
539             }
540         }
541     }
542
543     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
544     // section 15.2.1.16.4 step 12.
545     // Instantiate namespace objects and initialize the bindings with them if required.
546     // And ensure that all the imports correctly resolved to unique bindings.
547     for (const auto& pair : m_importEntries) {
548         const ImportEntry& importEntry = pair.value;
549         JSModuleRecord* importedModule = hostResolveImportedModule(exec, importEntry.moduleRequest);
550         if (importEntry.isNamespace(vm)) {
551             JSModuleNamespaceObject* namespaceObject = importedModule->getModuleNamespace(exec);
552             if (exec->hadException())
553                 return;
554             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, importEntry.localName, namespaceObject, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true);
555         } else {
556             Resolution resolution = importedModule->resolveExport(exec, importEntry.importName);
557             switch (resolution.type) {
558             case Resolution::Type::NotFound:
559                 throwSyntaxError(exec, makeString("Importing binding name '", String(importEntry.importName.impl()), "' is not found."));
560                 return;
561
562             case Resolution::Type::Ambiguous:
563                 throwSyntaxError(exec, makeString("Importing binding name '", String(importEntry.importName.impl()), "' cannot be resolved due to ambiguous multiple bindings."));
564                 return;
565
566             case Resolution::Type::Error:
567                 throwSyntaxError(exec, makeString("Importing binding name 'default' cannot be resolved by star export entries."));
568                 return;
569
570             case Resolution::Type::Resolved:
571                 break;
572             }
573         }
574     }
575
576     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
577     // section 15.2.1.16.4 step 14.
578     // Module environment contains the heap allocated "var", "function", "let", "const", and "class".
579     // When creating the environment, we initialized all the slots with empty, it's ok for lexical values.
580     // But for "var" and "function", we should initialize it with undefined. They are contained in the declared variables.
581     for (const auto& variable : m_declaredVariables) {
582         SymbolTableEntry entry = symbolTable->get(variable.key.get());
583         VarOffset offset = entry.varOffset();
584         if (!offset.isStack())
585             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, Identifier::fromUid(exec, variable.key.get()), jsUndefined(), /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true);
586     }
587
588     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduledeclarationinstantiation
589     // section 15.2.1.16.4 step 16-a-iv.
590     // Initialize heap allocated function declarations.
591     // They can be called before the body of the module is executed under circular dependencies.
592     UnlinkedModuleProgramCodeBlock* unlinkedCodeBlock = moduleProgramExecutable->unlinkedModuleProgramCodeBlock();
593     for (size_t i = 0, numberOfFunctions = unlinkedCodeBlock->numberOfFunctionDecls(); i < numberOfFunctions; ++i) {
594         UnlinkedFunctionExecutable* unlinkedFunctionExecutable = unlinkedCodeBlock->functionDecl(i);
595         SymbolTableEntry entry = symbolTable->get(unlinkedFunctionExecutable->name().impl());
596         VarOffset offset = entry.varOffset();
597         if (!offset.isStack()) {
598             ASSERT(!unlinkedFunctionExecutable->name().isEmpty());
599             if (vm.typeProfiler() || vm.controlFlowProfiler()) {
600                 vm.functionHasExecutedCache()->insertUnexecutedRange(moduleProgramExecutable->sourceID(),
601                     unlinkedFunctionExecutable->typeProfilingStartOffset(),
602                     unlinkedFunctionExecutable->typeProfilingEndOffset());
603             }
604             JSFunction* function = JSFunction::create(vm, unlinkedFunctionExecutable->link(vm, moduleProgramExecutable->source()), moduleEnvironment);
605             symbolTablePutTouchWatchpointSet(moduleEnvironment, exec, unlinkedFunctionExecutable->name(), function, /* shouldThrowReadOnlyError */ false, /* ignoreReadOnlyErrors */ true);
606         }
607     }
608
609     m_moduleEnvironment.set(vm, this, moduleEnvironment);
610 }
611
612 JSValue JSModuleRecord::execute(ExecState* exec)
613 {
614     if (!m_moduleProgramExecutable)
615         return jsUndefined();
616     JSValue result = exec->interpreter()->execute(m_moduleProgramExecutable.get(), exec, m_moduleEnvironment.get());
617     m_moduleProgramExecutable.clear();
618     return result;
619 }
620
621 static String printableName(const RefPtr<UniquedStringImpl>& uid)
622 {
623     if (uid->isSymbol())
624         return uid.get();
625     return WTF::makeString("'", String(uid.get()), "'");
626 }
627
628 static String printableName(const Identifier& ident)
629 {
630     return printableName(ident.impl());
631 }
632
633 void JSModuleRecord::dump()
634 {
635     dataLog("\nAnalyzing ModuleRecord key(", printableName(m_moduleKey), ")\n");
636
637     dataLog("    Dependencies: ", m_requestedModules.size(), " modules\n");
638     for (const auto& moduleName : m_requestedModules)
639         dataLog("      module(", printableName(moduleName), ")\n");
640
641     dataLog("    Import: ", m_importEntries.size(), " entries\n");
642     for (const auto& pair : m_importEntries) {
643         const ImportEntry& importEntry = pair.value;
644         dataLog("      import(", printableName(importEntry.importName), "), local(", printableName(importEntry.localName), "), module(", printableName(importEntry.moduleRequest), ")\n");
645     }
646
647     dataLog("    Export: ", m_exportEntries.size(), " entries\n");
648     for (const auto& pair : m_exportEntries) {
649         const ExportEntry& exportEntry = pair.value;
650         switch (exportEntry.type) {
651         case ExportEntry::Type::Local:
652             dataLog("      [Local] ", "export(", printableName(exportEntry.exportName), "), local(", printableName(exportEntry.localName), ")\n");
653             break;
654
655         case ExportEntry::Type::Namespace:
656             dataLog("      [Namespace] ", "export(", printableName(exportEntry.exportName), "), module(", printableName(exportEntry.moduleName), ")\n");
657             break;
658
659         case ExportEntry::Type::Indirect:
660             dataLog("      [Indirect] ", "export(", printableName(exportEntry.exportName), "), import(", printableName(exportEntry.importName), "), module(", printableName(exportEntry.moduleName), ")\n");
661             break;
662         }
663     }
664     for (const auto& moduleName : m_starExportEntries)
665         dataLog("      [Star] module(", printableName(moduleName.get()), ")\n");
666 }
667
668 } // namespace JSC