[ES6] Implement Module execution and Loader's ready / link phase
authorutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Aug 2015 06:22:08 +0000 (06:22 +0000)
committerutatane.tea@gmail.com <utatane.tea@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 28 Aug 2015 06:22:08 +0000 (06:22 +0000)
https://bugs.webkit.org/show_bug.cgi?id=148172

Reviewed by Saam Barati.

This patch adds the link / ready phases to the existing module loader.
They are just the stubs and the actual implementations will be
forthcoming in the subsequnt patch.

And this patch paves the way to instantiate the module environment and
compile the executable code in the link phase. Move declaredVariables /
lexicalVariables from ModuleAnalyzer to JSModuleRecord to use them when
instantiating the module environment. Hold the source code in
JSModuleRecord to construct the executable in the link phase. And to
use HostResolveImportedModule operation from the C++ side, we expose
the JSMap from C++ to JS and use it in the builtin JS module loader
code.

* builtins/ModuleLoaderObject.js:
(requestResolveDependencies.resolveDependenciesPromise.this.requestInstantiate.then.):
(requestLink):
(requestReady):
(link):
(moduleEvaluation):
(loadModule):
* parser/ModuleAnalyzer.cpp:
(JSC::ModuleAnalyzer::ModuleAnalyzer):
(JSC::ModuleAnalyzer::analyze):
* parser/ModuleAnalyzer.h:
* runtime/Completion.cpp:
(JSC::checkModuleSyntax):
* runtime/JSModuleRecord.cpp:
(JSC::JSModuleRecord::finishCreation):
(JSC::JSModuleRecord::visitChildren):
(JSC::identifierToJSValue):
(JSC::JSModuleRecord::hostResolveImportedModule):
(JSC::JSModuleRecord::link):
(JSC::JSModuleRecord::execute):
* runtime/JSModuleRecord.h:
(JSC::JSModuleRecord::create):
(JSC::JSModuleRecord::sourceCode):
(JSC::JSModuleRecord::moduleKey):
(JSC::JSModuleRecord::exportEntries):
(JSC::JSModuleRecord::importEntries):
(JSC::JSModuleRecord::declaredVariables):
(JSC::JSModuleRecord::lexicalVariables):
(JSC::JSModuleRecord::JSModuleRecord):
* runtime/ModuleLoaderObject.cpp:
(JSC::moduleLoaderObjectParseModule):
(JSC::moduleLoaderObjectRequestedModules):
(JSC::moduleLoaderObjectModuleDeclarationInstantiation):
(JSC::moduleLoaderObjectEvaluate):
(JSC::ModuleLoaderObject::requestInstantiateAll): Deleted.
* runtime/ModuleLoaderObject.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@189088 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/builtins/ModuleLoaderObject.js
Source/JavaScriptCore/parser/ModuleAnalyzer.cpp
Source/JavaScriptCore/parser/ModuleAnalyzer.h
Source/JavaScriptCore/runtime/Completion.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.cpp
Source/JavaScriptCore/runtime/JSModuleRecord.h
Source/JavaScriptCore/runtime/ModuleLoaderObject.cpp
Source/JavaScriptCore/runtime/ModuleLoaderObject.h

index adf4448..d35d0e9 100644 (file)
@@ -1,3 +1,60 @@
+2015-08-27  Yusuke Suzuki  <utatane.tea@gmail.com>
+
+        [ES6] Implement Module execution and Loader's ready / link phase
+        https://bugs.webkit.org/show_bug.cgi?id=148172
+
+        Reviewed by Saam Barati.
+
+        This patch adds the link / ready phases to the existing module loader.
+        They are just the stubs and the actual implementations will be
+        forthcoming in the subsequnt patch.
+
+        And this patch paves the way to instantiate the module environment and
+        compile the executable code in the link phase. Move declaredVariables /
+        lexicalVariables from ModuleAnalyzer to JSModuleRecord to use them when
+        instantiating the module environment. Hold the source code in
+        JSModuleRecord to construct the executable in the link phase. And to
+        use HostResolveImportedModule operation from the C++ side, we expose
+        the JSMap from C++ to JS and use it in the builtin JS module loader
+        code.
+
+        * builtins/ModuleLoaderObject.js:
+        (requestResolveDependencies.resolveDependenciesPromise.this.requestInstantiate.then.):
+        (requestLink):
+        (requestReady):
+        (link):
+        (moduleEvaluation):
+        (loadModule):
+        * parser/ModuleAnalyzer.cpp:
+        (JSC::ModuleAnalyzer::ModuleAnalyzer):
+        (JSC::ModuleAnalyzer::analyze):
+        * parser/ModuleAnalyzer.h:
+        * runtime/Completion.cpp:
+        (JSC::checkModuleSyntax):
+        * runtime/JSModuleRecord.cpp:
+        (JSC::JSModuleRecord::finishCreation):
+        (JSC::JSModuleRecord::visitChildren):
+        (JSC::identifierToJSValue):
+        (JSC::JSModuleRecord::hostResolveImportedModule):
+        (JSC::JSModuleRecord::link):
+        (JSC::JSModuleRecord::execute):
+        * runtime/JSModuleRecord.h:
+        (JSC::JSModuleRecord::create):
+        (JSC::JSModuleRecord::sourceCode):
+        (JSC::JSModuleRecord::moduleKey):
+        (JSC::JSModuleRecord::exportEntries):
+        (JSC::JSModuleRecord::importEntries):
+        (JSC::JSModuleRecord::declaredVariables):
+        (JSC::JSModuleRecord::lexicalVariables):
+        (JSC::JSModuleRecord::JSModuleRecord):
+        * runtime/ModuleLoaderObject.cpp:
+        (JSC::moduleLoaderObjectParseModule):
+        (JSC::moduleLoaderObjectRequestedModules):
+        (JSC::moduleLoaderObjectModuleDeclarationInstantiation):
+        (JSC::moduleLoaderObjectEvaluate):
+        (JSC::ModuleLoaderObject::requestInstantiateAll): Deleted.
+        * runtime/ModuleLoaderObject.h:
+
 2015-08-27  Mark Lam  <mark.lam@apple.com>
 
         Add noDFG() to jsc to prevent DFG compilation of a specified function.
index 65a0539..16062e6 100644 (file)
@@ -192,7 +192,7 @@ function commitInstantiated(entry, optionalInstance, source)
     // https://github.com/whatwg/loader/pull/67
 
     var dependencies = [];
-    var dependenciesMap = new @Map();
+    var dependenciesMap = moduleRecord.dependenciesMap;
     moduleRecord.registryEntry = entry;
     var requestedModules = this.requestedModules(moduleRecord);
     for (var i = 0, length = requestedModules.length; i < length; ++i) {
@@ -349,7 +349,7 @@ function requestResolveDependencies(key)
     var resolveDependenciesPromise = this.requestInstantiate(key).then(function (entry) {
         var depLoads = [];
         for (var i = 0, length = entry.dependencies.length; i < length; ++i) {
-            var pair = entry.dependencies[i];
+            let pair = entry.dependencies[i];
 
             // Hook point.
             // 1. Loader.resolve.
@@ -361,15 +361,21 @@ function requestResolveDependencies(key)
 
                 // Recursive resolving. The dependencies of this entry is being resolved or already resolved.
                 // Stop tracing the circular dependencies.
+                // But to retrieve the instantiated module record correctly,
+                // we need to wait for the instantiation for the dependent module.
+                // For example, reaching here, the module is starting resolving the dependencies.
+                // But the module may or may not reach the instantiation phase in the loader's pipeline.
+                // If we wait for the ResolveDependencies for this module, it construct the circular promise chain and
+                // rejected by the Promises runtime. Since only we need is the instantiated module, instead of waiting
+                // the ResolveDependencies for this module, we just wait Instantiate for this.
                 if (depEntry.resolveDependencies) {
-                    pair.value = depEntry.module;
-                    return depEntry;
+                    return depEntry.instantiate.then(function (entry) {
+                        pair.value = entry.module;
+                        return entry;
+                    });
                 }
 
                 return loader.requestResolveDependencies(depKey).then(function (entry) {
-                    // FIXME: The result promise of the requestInstantiateAll should be fulfilled with
-                    // the registry entry.
-                    // https://github.com/whatwg/loader/pull/66
                     pair.value = entry.module;
                     return entry;
                 });
@@ -396,6 +402,90 @@ function requestInstantiateAll(key)
     return this.requestResolveDependencies(key);
 }
 
+function requestLink(key)
+{
+    // https://whatwg.github.io/loader/#request-link
+
+    "use strict";
+
+    var entry = this.ensureRegistered(key);
+    if (entry.state > this.Link) {
+        var deferred = @newPromiseCapability(@InternalPromise);
+        deferred.@resolve.@call(undefined, entry.module);
+        return deferred.@promise;
+    }
+
+    var loader = this;
+    return this.requestInstantiateAll(key).then(function (entry) {
+        loader.link(entry);
+        return entry;
+    });
+}
+
+function requestReady(key)
+{
+    // https://whatwg.github.io/loader/#request-ready
+
+    "use strict";
+
+    var loader = this;
+    return this.requestLink(key).then(function (entry) {
+        loader.moduleEvaluation(entry.module);
+    });
+}
+
+// Linking semantics.
+
+function link(entry)
+{
+    // https://whatwg.github.io/loader/#link
+
+    "use strict";
+
+    // FIXME: Current implementation does not support optionalInstance.
+    // So Link's step 3 is skipped.
+    // https://bugs.webkit.org/show_bug.cgi?id=148171
+
+    if (entry.state === this.Ready)
+        return;
+    this.setStateToMax(entry, this.Ready);
+
+    // Since we already have the "dependencies" field,
+    // we can call moduleDeclarationInstantiation with the correct order
+    // without constructing the dependency graph by calling dependencyGraph.
+    var dependencies = entry.dependencies;
+    for (var i = 0, length = dependencies.length; i < length; ++i) {
+        var pair = dependencies[i];
+        this.link(pair.value.registryEntry);
+    }
+
+    this.moduleDeclarationInstantiation(entry.module);
+}
+
+// Module semantics.
+
+function moduleEvaluation(moduleRecord)
+{
+    // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation
+
+    "use strict";
+
+    if (moduleRecord.evaluated)
+        return;
+    moduleRecord.evaluated = true;
+
+    var entry = moduleRecord.registryEntry;
+
+    // The contents of the [[RequestedModules]] is cloned into entry.dependencies.
+    var dependencies = entry.dependencies;
+    for (var i = 0, length = dependencies.length; i < length; ++i) {
+        var pair = dependencies[i];
+        var requiredModuleRecord = pair.value;
+        this.moduleEvaluation(requiredModuleRecord);
+    }
+    this.evaluate(moduleRecord);
+}
+
 function loadModule(moduleName, referrer)
 {
     "use strict";
@@ -406,11 +496,7 @@ function loadModule(moduleName, referrer)
     // Take the name and resolve it to the unique identifier for the resource location.
     // For example, take the "jquery" and return the URL for the resource.
     return this.resolve(moduleName, referrer).then(function (key) {
-        // FIXME: Now, we don't implement the linking phase yet.
-        // So here, we just call requestInstantiateAll to only perform the module loading.
-        // At last, it should be replaced with requestReady.
-        // https://bugs.webkit.org/show_bug.cgi?id=148172
-        return loader.requestInstantiateAll(key);
+        return loader.requestReady(key);
     });
 }
 
index 3d177ca..2fa81aa 100644 (file)
 namespace JSC {
 
 
-ModuleAnalyzer::ModuleAnalyzer(ExecState* exec, const Identifier& moduleKey, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
+ModuleAnalyzer::ModuleAnalyzer(ExecState* exec, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
     : m_vm(&exec->vm())
-    , m_moduleRecord(exec->vm(), JSModuleRecord::create(exec->vm(), exec->lexicalGlobalObject()->moduleRecordStructure(), moduleKey))
-    , m_declaredVariables(declaredVariables)
-    , m_lexicalVariables(lexicalVariables)
+    , m_moduleRecord(exec->vm(), JSModuleRecord::create(exec->vm(), exec->lexicalGlobalObject()->moduleRecordStructure(), moduleKey, sourceCode, declaredVariables, lexicalVariables))
 {
 }
 
@@ -144,10 +142,10 @@ JSModuleRecord* ModuleAnalyzer::analyze(ModuleProgramNode& moduleProgramNode)
     //     This exports all the names from the specified external module as the current module's name.
     //
     //     export * from "mod"
-    for (const auto& pair : m_declaredVariables)
+    for (const auto& pair : m_moduleRecord->declaredVariables())
         exportVariable(pair.key, pair.value);
 
-    for (const auto& pair : m_lexicalVariables)
+    for (const auto& pair : m_moduleRecord->lexicalVariables())
         exportVariable(pair.key, pair.value);
 
     if (Options::dumpModuleRecord())
index 228a69f..7083ca9 100644 (file)
 namespace JSC {
 
 class JSModuleRecord;
+class SourceCode;
 
 class ModuleAnalyzer {
     WTF_MAKE_NONCOPYABLE(ModuleAnalyzer);
 public:
-    ModuleAnalyzer(ExecState*, const Identifier& moduleKey, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables);
+    ModuleAnalyzer(ExecState*, const Identifier& moduleKey, const SourceCode&, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables);
 
     JSModuleRecord* analyze(ModuleProgramNode&);
 
@@ -54,8 +55,6 @@ private:
 
     VM* m_vm;
     Strong<JSModuleRecord> m_moduleRecord;
-    VariableEnvironment m_declaredVariables;
-    VariableEnvironment m_lexicalVariables;
     IdentifierAliasMap m_aliasMap;
 };
 
index 271178c..b5f623a 100644 (file)
@@ -78,7 +78,7 @@ bool checkModuleSyntax(ExecState* exec, const SourceCode& source, ParserError& e
         return false;
 
     PrivateName privateName(PrivateName::Description, "EntryPointModule");
-    ModuleAnalyzer moduleAnalyzer(exec, Identifier::fromUid(privateName), moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
+    ModuleAnalyzer moduleAnalyzer(exec, Identifier::fromUid(privateName), source, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
     moduleAnalyzer.analyze(*moduleProgramNode);
     return true;
 }
index e702faf..5d15ebc 100644 (file)
@@ -20,7 +20,7 @@
  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "config.h"
@@ -29,6 +29,8 @@
 #include "IdentifierInlines.h"
 #include "JSCJSValueInlines.h"
 #include "JSCellInlines.h"
+#include "JSMap.h"
+#include "SlotVisitorInlines.h"
 #include "StructureInlines.h"
 
 namespace JSC {
@@ -41,12 +43,22 @@ void JSModuleRecord::destroy(JSCell* cell)
     thisObject->JSModuleRecord::~JSModuleRecord();
 }
 
-
 void JSModuleRecord::finishCreation(VM& vm)
 {
     Base::finishCreation(vm);
     ASSERT(inherits(info()));
     putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("registryEntry")), jsUndefined());
+    putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("evaluated")), jsBoolean(false));
+
+    m_dependenciesMap.set(vm, this, JSMap::create(vm, globalObject()->mapStructure()));
+    putDirect(vm, Identifier::fromString(&vm, ASCIILiteral("dependenciesMap")), m_dependenciesMap.get());
+}
+
+void JSModuleRecord::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+    JSModuleRecord* thisObject = jsCast<JSModuleRecord*>(cell);
+    Base::visitChildren(thisObject, visitor);
+    visitor.append(&thisObject->m_dependenciesMap);
 }
 
 auto JSModuleRecord::ExportEntry::createLocal(const Identifier& exportName, const Identifier& localName, const VariableEnvironmentEntry& variable) -> ExportEntry
@@ -64,6 +76,29 @@ auto JSModuleRecord::ExportEntry::createIndirect(const Identifier& exportName, c
     return ExportEntry { Type::Indirect, exportName, moduleName, importName, Identifier(), VariableEnvironmentEntry() };
 }
 
+static JSValue identifierToJSValue(ExecState* exec, const Identifier& identifier)
+{
+    if (identifier.isSymbol())
+        return Symbol::create(exec->vm(), static_cast<SymbolImpl&>(*identifier.impl()));
+    return jsString(&exec->vm(), identifier.impl());
+}
+
+JSModuleRecord* JSModuleRecord::hostResolveImportedModule(ExecState* exec, const Identifier& moduleName)
+{
+    JSValue moduleNameValue = identifierToJSValue(exec, moduleName);
+    JSValue pair = m_dependenciesMap->JSMap::get(exec, moduleNameValue);
+    return jsCast<JSModuleRecord*>(pair.get(exec, Identifier::fromString(exec, "value")));
+}
+
+void JSModuleRecord::link(ExecState*)
+{
+}
+
+JSValue JSModuleRecord::execute(ExecState*)
+{
+    return jsUndefined();
+}
+
 static String printableName(const RefPtr<UniquedStringImpl>& uid)
 {
     if (uid->isSymbol())
@@ -76,7 +111,6 @@ static String printableName(const Identifier& ident)
     return printableName(ident.impl());
 }
 
-
 void JSModuleRecord::dump()
 {
     dataLog("\nAnalyzing ModuleRecord key(", printableName(m_moduleKey), ")\n");
index 05d694d..936263c 100644 (file)
 
 #include "Identifier.h"
 #include "JSDestructibleObject.h"
+#include "SourceCode.h"
 #include "VariableEnvironment.h"
 #include <wtf/HashMap.h>
 #include <wtf/ListHashSet.h>
 
 namespace JSC {
 
+class JSModuleNamespaceObject;
+class JSModuleEnvironment;
+class JSMap;
+class ModuleProgramExecutable;
+
 // Based on the Source Text Module Record
 // http://www.ecma-international.org/ecma-262/6.0/#sec-source-text-module-records
 class JSModuleRecord : public JSDestructibleObject {
+    friend class LLIntOffsetsExtractor;
 public:
     typedef JSDestructibleObject Base;
 
@@ -81,18 +88,13 @@ public:
         return Structure::create(vm, globalObject, prototype, TypeInfo(ObjectType, StructureFlags), info());
     }
 
-    static JSModuleRecord* create(VM& vm, Structure* structure, const Identifier& moduleKey)
+    static JSModuleRecord* create(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
     {
-        JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey);
+        JSModuleRecord* instance = new (NotNull, allocateCell<JSModuleRecord>(vm.heap)) JSModuleRecord(vm, structure, moduleKey, sourceCode, declaredVariables, lexicalVariables);
         instance->finishCreation(vm);
         return instance;
     }
 
-    static JSModuleRecord* create(ExecState* exec, Structure* structure, const Identifier& moduleKey)
-    {
-        return create(exec->vm(), structure, moduleKey);
-    }
-
     void appendRequestedModule(const Identifier&);
     void addStarExportEntry(const Identifier&);
     void addImportEntry(const ImportEntry&);
@@ -100,24 +102,46 @@ public:
 
     const ImportEntry& lookUpImportEntry(const RefPtr<UniquedStringImpl>& localName);
 
+    const SourceCode& sourceCode() const { return m_sourceCode; }
+    const Identifier& moduleKey() const { return m_moduleKey; }
     const OrderedIdentifierSet& requestedModules() const { return m_requestedModules; }
+    const ExportMap& exportEntries() const { return m_exportEntries; }
+    const ImportMap& importEntries() const { return m_importEntries; }
+
+    const VariableEnvironment& declaredVariables() const { return m_declaredVariables; }
+    const VariableEnvironment& lexicalVariables() const { return m_lexicalVariables; }
 
     void dump();
 
+
+    void link(ExecState*);
+    JSValue execute(ExecState*);
+
 private:
-    JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey)
+    JSModuleRecord(VM& vm, Structure* structure, const Identifier& moduleKey, const SourceCode& sourceCode, const VariableEnvironment& declaredVariables, const VariableEnvironment& lexicalVariables)
         : Base(vm, structure)
         , m_moduleKey(moduleKey)
+        , m_sourceCode(sourceCode)
+        , m_declaredVariables(declaredVariables)
+        , m_lexicalVariables(lexicalVariables)
     {
     }
 
     void finishCreation(VM&);
 
+    static void visitChildren(JSCell*, SlotVisitor&);
     static void destroy(JSCell*);
 
+    JSModuleRecord* hostResolveImportedModule(ExecState*, const Identifier& moduleName);
+
     // The loader resolves the given module name to the module key. The module key is the unique value to represent this module.
     Identifier m_moduleKey;
 
+    SourceCode m_sourceCode;
+
+    VariableEnvironment m_declaredVariables;
+    VariableEnvironment m_lexicalVariables;
+
     // Map localName -> ImportEntry.
     ImportMap m_importEntries;
 
@@ -129,6 +153,8 @@ private:
     // Save the occurrence order since the module loader loads and runs the modules in this order.
     // http://www.ecma-international.org/ecma-262/6.0/#sec-moduleevaluation
     OrderedIdentifierSet m_requestedModules;
+
+    WriteBarrier<JSMap> m_dependenciesMap;
 };
 
 inline void JSModuleRecord::appendRequestedModule(const Identifier& moduleName)
index 1d67a4c..e67fa38 100644 (file)
@@ -45,6 +45,8 @@ namespace JSC {
 
 static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectParseModule(ExecState*);
 static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectRequestedModules(ExecState*);
+static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectEvaluate(ExecState*);
+static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectModuleDeclarationInstantiation(ExecState*);
 static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectResolve(ExecState*);
 static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectFetch(ExecState*);
 static EncodedJSValue JSC_HOST_CALL moduleLoaderObjectTranslate(ExecState*);
@@ -62,28 +64,34 @@ const ClassInfo ModuleLoaderObject::s_info = { "ModuleLoader", &Base::s_info, &m
 
 /* Source for ModuleLoaderObject.lut.h
 @begin moduleLoaderObjectTable
-    setStateToMax              moduleLoaderObjectSetStateToMax              DontEnum|Function 2
-    newRegistryEntry           moduleLoaderObjectNewRegistryEntry           DontEnum|Function 1
-    ensureRegistered           moduleLoaderObjectEnsureRegistered           DontEnum|Function 1
-    forceFulfillPromise        moduleLoaderObjectForceFulfillPromise        DontEnum|Function 2
-    fulfillFetch               moduleLoaderObjectFulfillFetch               DontEnum|Function 2
-    fulfillTranslate           moduleLoaderObjectFulfillTranslate           DontEnum|Function 2
-    fulfillInstantiate         moduleLoaderObjectFulfillInstantiate         DontEnum|Function 2
-    commitInstantiated         moduleLoaderObjectCommitInstantiated         DontEnum|Function 3
-    instantiation              moduleLoaderObjectInstantiation              DontEnum|Function 3
-    requestFetch               moduleLoaderObjectRequestFetch               DontEnum|Function 1
-    requestTranslate           moduleLoaderObjectRequestTranslate           DontEnum|Function 1
-    requestInstantiate         moduleLoaderObjectRequestInstantiate         DontEnum|Function 1
-    requestResolveDependencies moduleLoaderObjectRequestResolveDependencies DontEnum|Function 1
-    requestInstantiateAll      moduleLoaderObjectRequestInstantiateAll      DontEnum|Function 1
-    loadModule                 moduleLoaderObjectLoadModule                 DontEnum|Function 2
-    provide                    moduleLoaderObjectProvide                    DontEnum|Function 3
-    parseModule                moduleLoaderObjectParseModule                DontEnum|Function 2
-    requestedModules           moduleLoaderObjectRequestedModules           DontEnum|Function 1
-    resolve                    moduleLoaderObjectResolve                    DontEnum|Function 1
-    fetch                      moduleLoaderObjectFetch                      DontEnum|Function 1
-    translate                  moduleLoaderObjectTranslate                  DontEnum|Function 2
-    instantiate                moduleLoaderObjectInstantiate                DontEnum|Function 2
+    setStateToMax                  moduleLoaderObjectSetStateToMax                  DontEnum|Function 2
+    newRegistryEntry               moduleLoaderObjectNewRegistryEntry               DontEnum|Function 1
+    ensureRegistered               moduleLoaderObjectEnsureRegistered               DontEnum|Function 1
+    forceFulfillPromise            moduleLoaderObjectForceFulfillPromise            DontEnum|Function 2
+    fulfillFetch                   moduleLoaderObjectFulfillFetch                   DontEnum|Function 2
+    fulfillTranslate               moduleLoaderObjectFulfillTranslate               DontEnum|Function 2
+    fulfillInstantiate             moduleLoaderObjectFulfillInstantiate             DontEnum|Function 2
+    commitInstantiated             moduleLoaderObjectCommitInstantiated             DontEnum|Function 3
+    instantiation                  moduleLoaderObjectInstantiation                  DontEnum|Function 3
+    requestFetch                   moduleLoaderObjectRequestFetch                   DontEnum|Function 1
+    requestTranslate               moduleLoaderObjectRequestTranslate               DontEnum|Function 1
+    requestInstantiate             moduleLoaderObjectRequestInstantiate             DontEnum|Function 1
+    requestResolveDependencies     moduleLoaderObjectRequestResolveDependencies     DontEnum|Function 1
+    requestInstantiateAll          moduleLoaderObjectRequestInstantiateAll          DontEnum|Function 1
+    requestLink                    moduleLoaderObjectRequestLink                    DontEnum|Function 1
+    requestReady                   moduleLoaderObjectRequestReady                   DontEnum|Function 1
+    link                           moduleLoaderObjectLink                           DontEnum|Function 1
+    moduleDeclarationInstantiation moduleLoaderObjectModuleDeclarationInstantiation DontEnum|Function 2
+    moduleEvaluation               moduleLoaderObjectModuleEvaluation               DontEnum|Function 2
+    evaluate                       moduleLoaderObjectEvaluate                       DontEnum|Function 2
+    loadModule                     moduleLoaderObjectLoadModule                     DontEnum|Function 2
+    provide                        moduleLoaderObjectProvide                        DontEnum|Function 3
+    parseModule                    moduleLoaderObjectParseModule                    DontEnum|Function 2
+    requestedModules               moduleLoaderObjectRequestedModules               DontEnum|Function 1
+    resolve                        moduleLoaderObjectResolve                        DontEnum|Function 1
+    fetch                          moduleLoaderObjectFetch                          DontEnum|Function 1
+    translate                      moduleLoaderObjectTranslate                      DontEnum|Function 2
+    instantiate                    moduleLoaderObjectInstantiate                    DontEnum|Function 2
 @end
 */
 
@@ -137,19 +145,6 @@ JSValue ModuleLoaderObject::provide(ExecState* exec, JSValue key, Status status,
     return call(exec, function, callType, callData, this, arguments);
 }
 
-JSInternalPromise* ModuleLoaderObject::requestInstantiateAll(ExecState* exec, JSValue key)
-{
-    JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().requestInstantiateAllPublicName()));
-    CallData callData;
-    CallType callType = JSC::getCallData(function, callData);
-    ASSERT(callType != CallTypeNone);
-
-    MarkedArgumentBuffer arguments;
-    arguments.append(key);
-
-    return jsCast<JSInternalPromise*>(call(exec, function, callType, callData, this, arguments));
-}
-
 JSInternalPromise* ModuleLoaderObject::loadModule(ExecState* exec, JSValue moduleName, JSValue referrer)
 {
     JSObject* function = jsCast<JSObject*>(get(exec, exec->propertyNames().builtinNames().loadModulePublicName()));
@@ -249,14 +244,15 @@ EncodedJSValue JSC_HOST_CALL moduleLoaderObjectParseModule(ExecState* exec)
     }
     ASSERT(moduleProgramNode);
 
-    ModuleAnalyzer moduleAnalyzer(exec, moduleKey, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
+    ModuleAnalyzer moduleAnalyzer(exec, moduleKey, sourceCode, moduleProgramNode->varDeclarations(), moduleProgramNode->lexicalVariables());
     JSModuleRecord* moduleRecord = moduleAnalyzer.analyze(*moduleProgramNode);
+
     return JSValue::encode(moduleRecord);
 }
 
 EncodedJSValue JSC_HOST_CALL moduleLoaderObjectRequestedModules(ExecState* exec)
 {
-    JSModuleRecord* moduleRecord = jsCast<JSModuleRecord*>(exec->argument(0));
+    JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->argument(0));
     if (!moduleRecord)
         return JSValue::encode(constructEmptyArray(exec, nullptr));
 
@@ -268,6 +264,31 @@ EncodedJSValue JSC_HOST_CALL moduleLoaderObjectRequestedModules(ExecState* exec)
     return JSValue::encode(result);
 }
 
+EncodedJSValue JSC_HOST_CALL moduleLoaderObjectModuleDeclarationInstantiation(ExecState* exec)
+{
+    JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->argument(0));
+    if (!moduleRecord)
+        return JSValue::encode(jsUndefined());
+
+    if (Options::dumpModuleLoadingState())
+        dataLog("Loader [link] ", moduleRecord->moduleKey(), "\n");
+
+    moduleRecord->link(exec);
+    return JSValue::encode(jsUndefined());
+}
+
+EncodedJSValue JSC_HOST_CALL moduleLoaderObjectEvaluate(ExecState* exec)
+{
+    JSModuleRecord* moduleRecord = jsDynamicCast<JSModuleRecord*>(exec->argument(0));
+    if (!moduleRecord)
+        return JSValue::encode(jsUndefined());
+
+    if (Options::dumpModuleLoadingState())
+        dataLog("Loader [evaluate] ", moduleRecord->moduleKey(), "\n");
+
+    return JSValue::encode(moduleRecord->execute(exec));
+}
+
 // ------------------------------ Hook Functions ---------------------------
 
 EncodedJSValue JSC_HOST_CALL moduleLoaderObjectResolve(ExecState* exec)
index 45b932a..12cfe56 100644 (file)
@@ -64,7 +64,6 @@ public:
 
     // APIs to control the module loader.
     JSValue provide(ExecState*, JSValue key, Status, const String&);
-    JSInternalPromise* requestInstantiateAll(ExecState*, JSValue key);
     JSInternalPromise* loadModule(ExecState*, JSValue moduleName, JSValue referrer);
 
     // Platform dependent hooked APIs.