<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[210522] trunk</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/210522">210522</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2017-01-09 14:02:47 -0800 (Mon, 09 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>[JSC] Prototype dynamic-import
https://bugs.webkit.org/show_bug.cgi?id=165724

Reviewed by Saam Barati.

JSTests:

* stress/import-basic.js: Added.
(async.async.load):
(async):
(catch):
* stress/import-from-eval.js: Added.
(async):
(catch):
* stress/import-syntax.js: Added.
(testSyntaxError):
* stress/import-tests/cocoa.js: Added.
(export.Cocoa):
(export.hello):
* stress/import-tests/multiple.js: Added.
(export.result):
* stress/import-tests/multiple2.js: Added.
(export.ok):
* stress/import-tests/should.js: Added.
(export.shouldBe):
(export.shouldThrow):
* stress/modules-syntax-error.js:

Source/JavaScriptCore:

In this patch, we implement stage3 dynamic-import proposal[1].
This patch adds a new special operator `import`. And by using it, we can import
the module dynamically from modules and scripts. Before this feature, the module
is always imported statically and before executing the modules, importing the modules
needs to be done. And especially, the module can only be imported from the module.
So the classic script cannot import and use the modules. This dynamic-import relaxes
the above restrictions.

The typical dynamic-import form is the following.

    import(&quot;...&quot;).then(function (namespace) { ... });

You can pass any AssignmentExpression for the import operator. So you can determine
the importing modules dynamically.

    import(value).then(function (namespace) { ... });

And previously the module import declaration is only allowed in the top level statements.
But this import operator is just an expression. So you can use it in the function.
And you can use it conditionally.

    async function go(cond)
    {
        if (cond)
            return import(&quot;...&quot;);
        return undefined;
    }
    await go(true);

Currently, this patch just implements this feature only for the JSC shell.
JSC module loader requires a new hook, `importModule`. And the JSC shell implements
this hook. So, for now, this dynamic-import is not available in the browser side.
If you write this `import` call, it always returns the rejected promise.

import is implemented like a special operator similar to `super`.
This is because import is context-sensitive. If you call the `import`, the module
key resolution is done based on the caller's running context.

For example, if you are running the script which filename is &quot;./ok/hello.js&quot;, the module
key for the call`import(&quot;./resource/syntax.js&quot;)` becomes `&quot;./ok/resource/syntax.js&quot;`.
But if you write the completely same import form in the script &quot;./error/hello.js&quot;, the
key becomes &quot;./error/resource/syntax.js&quot;. So exposing this feature as the `import`
function is misleading: this function becomes caller's context-sensitive. That's why
dynamic-import is specified as a special operator.

To resolve the module key, we need the caller's context information like the filename of
the caller. This is provided by the SourceOrigin implemented in <a href="http://trac.webkit.org/projects/webkit/changeset/210149">r210149</a>.
In the JSC shell implementation, this SourceOrigin holds the filename of the caller. So
based on this implementation, the module loader resolve the module key.
In the near future, we will extend this SourceOrigin to hold more information needed for
the browser-side import implementation.

[1]: https://tc39.github.io/proposal-dynamic-import/

* builtins/ModuleLoaderPrototype.js:
(importModule):
* bytecompiler/BytecodeGenerator.cpp:
(JSC::BytecodeGenerator::emitGetTemplateObject):
(JSC::BytecodeGenerator::emitGetGlobalPrivate):
* bytecompiler/BytecodeGenerator.h:
* bytecompiler/NodesCodegen.cpp:
(JSC::ImportNode::emitBytecode):
* jsc.cpp:
(absolutePath):
(GlobalObject::moduleLoaderImportModule):
(functionRun):
(functionLoad):
(functionCheckSyntax):
(runWithScripts):
* parser/ASTBuilder.h:
(JSC::ASTBuilder::createImportExpr):
* parser/NodeConstructors.h:
(JSC::ImportNode::ImportNode):
* parser/Nodes.h:
(JSC::ExpressionNode::isImportNode):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseMemberExpression):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createImportExpr):
* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::init):
* runtime/JSGlobalObject.h:
* runtime/JSGlobalObjectFunctions.cpp:
(JSC::globalFuncImportModule):
* runtime/JSGlobalObjectFunctions.h:
* runtime/JSModuleLoader.cpp:
(JSC::JSModuleLoader::importModule):
(JSC::JSModuleLoader::getModuleNamespaceObject):
* runtime/JSModuleLoader.h:
* runtime/ModuleLoaderPrototype.cpp:
(JSC::moduleLoaderPrototypeGetModuleNamespaceObject):

Source/WebCore:

We do not set a handler for import for now.
So dynamic import feature is only enabled in the JSC shell right now.

* bindings/js/JSDOMWindowBase.cpp:
* bindings/js/JSWorkerGlobalScopeBase.cpp:

LayoutTests:

* sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressmodulessyntaxerrorjs">trunk/JSTests/stress/modules-syntax-error.js</a></li>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestssputnikConformance07_Lexical_Conventions75_Tokens753_Future_Reserved_WordsS753_A116expectedtxt">trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebuiltinsModuleLoaderPrototypejs">trunk/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh">trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecompilerNodesCodegencpp">trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCorejsccpp">trunk/Source/JavaScriptCore/jsc.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodeConstructorsh">trunk/Source/JavaScriptCore/parser/NodeConstructors.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserNodesh">trunk/Source/JavaScriptCore/parser/Nodes.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjecth">trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionscpp">trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionsh">trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSModuleLoadercpp">trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeJSModuleLoaderh">trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeModuleLoaderPrototypecpp">trunk/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp</a></li>
<li><a href="#trunkSourceWebCoreChangeLog">trunk/Source/WebCore/ChangeLog</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSDOMWindowBasecpp">trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp</a></li>
<li><a href="#trunkSourceWebCorebindingsjsJSWorkerGlobalScopeBasecpp">trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkJSTestsstressimportbasicjs">trunk/JSTests/stress/import-basic.js</a></li>
<li><a href="#trunkJSTestsstressimportfromevaljs">trunk/JSTests/stress/import-from-eval.js</a></li>
<li><a href="#trunkJSTestsstressimportsyntaxjs">trunk/JSTests/stress/import-syntax.js</a></li>
<li>trunk/JSTests/stress/import-tests/</li>
<li><a href="#trunkJSTestsstressimporttestscocoajs">trunk/JSTests/stress/import-tests/cocoa.js</a></li>
<li><a href="#trunkJSTestsstressimporttestsmultiplejs">trunk/JSTests/stress/import-tests/multiple.js</a></li>
<li><a href="#trunkJSTestsstressimporttestsmultiple2js">trunk/JSTests/stress/import-tests/multiple2.js</a></li>
<li><a href="#trunkJSTestsstressimporttestsshouldjs">trunk/JSTests/stress/import-tests/should.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/JSTests/ChangeLog        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -1,3 +1,31 @@
</span><ins>+2017-01-09  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [JSC] Prototype dynamic-import
+        https://bugs.webkit.org/show_bug.cgi?id=165724
+
+        Reviewed by Saam Barati.
+
+        * stress/import-basic.js: Added.
+        (async.async.load):
+        (async):
+        (catch):
+        * stress/import-from-eval.js: Added.
+        (async):
+        (catch):
+        * stress/import-syntax.js: Added.
+        (testSyntaxError):
+        * stress/import-tests/cocoa.js: Added.
+        (export.Cocoa):
+        (export.hello):
+        * stress/import-tests/multiple.js: Added.
+        (export.result):
+        * stress/import-tests/multiple2.js: Added.
+        (export.ok):
+        * stress/import-tests/should.js: Added.
+        (export.shouldBe):
+        (export.shouldThrow):
+        * stress/modules-syntax-error.js:
+
</ins><span class="cx"> 2017-01-09  Commit Queue  &lt;commit-queue@webkit.org&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed, rolling out r210476.
</span></span></pre></div>
<a id="trunkJSTestsstressimportbasicjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-basic.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-basic.js                                (rev 0)
+++ trunk/JSTests/stress/import-basic.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,53 @@
</span><ins>+(async function () {
+    const { shouldBe } = await import('./import-tests/should.js');
+    {
+        let a = await import('./import-tests/cocoa.js');
+        let b = await import('./import-tests/cocoa.js');
+        shouldBe(a, b);
+        shouldBe(a.hello(), 42);
+    }
+
+    {
+        let a = await import('./import-tests/multiple.js');
+        let a2 = await a.result();
+        shouldBe(a !== a2, true);
+        shouldBe(a2.ok(), 42);
+        let a3 = await a.result();
+        shouldBe(a2, a3);
+    }
+
+    {
+        let error = null;
+        try {
+            let a = await import({ toString() { throw new Error('out'); } });
+        } catch (e) {
+            error = e;
+        }
+        shouldBe(error !== null, true);
+        shouldBe(String(error), `Error: out`);
+    }
+
+    {
+        async function load(cond) {
+            if (cond)
+                return import('./import-tests/cocoa.js');
+            return undefined;
+        }
+
+        let v = await load(false);
+        shouldBe(v, undefined);
+        let v2 = await load(true);
+        let v3 = await import('./import-tests/cocoa.js');
+        shouldBe(v2, v2);
+    }
+
+    {
+        let value = './import-tests/cocoa.js';
+        let v = await import(value);
+        let v2 = await import('./import-tests/cocoa.js');
+        shouldBe(v, v2);
+    }
+}()).catch((error) =&gt; {
+    print(String(error));
+    abort();
+});
</ins></span></pre></div>
<a id="trunkJSTestsstressimportfromevaljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-from-eval.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-from-eval.js                                (rev 0)
+++ trunk/JSTests/stress/import-from-eval.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,36 @@
</span><ins>+(async function () {
+    const { shouldBe, shouldThrow } = await import(&quot;./import-tests/should.js&quot;);
+
+    {
+        let cocoa = await eval(`import(&quot;./import-tests/cocoa.js&quot;)`);
+        shouldBe(cocoa.hello(), 42);
+    }
+
+    {
+        let cocoa = await (0, eval)(`import(&quot;./import-tests/cocoa.js&quot;)`);
+        shouldBe(cocoa.hello(), 42);
+    }
+
+    {
+        let cocoa = await eval(`eval('import(&quot;./import-tests/cocoa.js&quot;)')`);
+        shouldBe(cocoa.hello(), 42);
+    }
+
+    {
+        let cocoa = await ((new Function(`return eval('import(&quot;./import-tests/cocoa.js&quot;)')`))());
+        shouldBe(cocoa.hello(), 42);
+    }
+
+    {
+        let cocoa = await eval(`(new Function('return import(&quot;./import-tests/cocoa.js&quot;)'))()`);
+        shouldBe(cocoa.hello(), 42);
+    }
+
+    {
+        let cocoa = await [`import(&quot;./import-tests/cocoa.js&quot;)`].map(eval)[0];
+        shouldBe(cocoa.hello(), 42);
+    }
+}()).catch((error) =&gt; {
+    print(String(error));
+    abort();
+});
</ins></span></pre></div>
<a id="trunkJSTestsstressimportsyntaxjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-syntax.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-syntax.js                                (rev 0)
+++ trunk/JSTests/stress/import-syntax.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,59 @@
</span><ins>+function testSyntaxError(script, message) {
+    var error = null;
+    try {
+        eval(script);
+    } catch (e) {
+        error = e;
+    }
+    if (!error)
+        throw new Error(&quot;Expected syntax error not thrown&quot;);
+
+    if (String(error) !== message)
+        throw new Error(`Bad error: ${String(error)}`);
+}
+
+async function testSyntax(script, message) {
+    var error = null;
+    try {
+        await eval(script);
+    } catch (e) {
+        error = e;
+    }
+    if (error) {
+        if (error instanceof SyntaxError)
+            throw new Error(&quot;Syntax error thrown&quot;);
+    }
+}
+
+testSyntaxError(`import)`, `SyntaxError: Unexpected token ')'. import call expects exactly one argument.`);
+testSyntaxError(`new import(`, `SyntaxError: Cannot use new with import.`);
+testSyntaxError(`import.hello()`, `SyntaxError: Unexpected token '.'. import call expects exactly one argument.`);
+testSyntaxError(`import[`, `SyntaxError: Unexpected token '['. import call expects exactly one argument.`);
+testSyntaxError(`import&lt;`, `SyntaxError: Unexpected token '&lt;'. import call expects exactly one argument.`);
+
+testSyntaxError(`import()`, `SyntaxError: Unexpected token ')'`);
+testSyntaxError(`import(a, b)`, `SyntaxError: Unexpected token ','. import call expects exactly one argument.`);
+testSyntaxError(`import(a, b, c)`, `SyntaxError: Unexpected token ','. import call expects exactly one argument.`);
+testSyntaxError(`import(...a)`, `SyntaxError: Unexpected token '...'`);
+testSyntaxError(`import(,a)`, `SyntaxError: Unexpected token ','`);
+testSyntaxError(`import(,)`, `SyntaxError: Unexpected token ','`);
+testSyntaxError(`import(&quot;Hello&quot;;`, `SyntaxError: Unexpected token ';'. import call expects exactly one argument.`);
+testSyntaxError(`import(&quot;Hello&quot;];`, `SyntaxError: Unexpected token ']'. import call expects exactly one argument.`);
+testSyntaxError(`import(&quot;Hello&quot;,;`, `SyntaxError: Unexpected token ','. import call expects exactly one argument.`);
+testSyntaxError(`import(&quot;Hello&quot;, &quot;Hello2&quot;;`, `SyntaxError: Unexpected token ','. import call expects exactly one argument.`);
+
+
+testSyntaxError(`import = 42`, `SyntaxError: Unexpected token '='. import call expects exactly one argument.`);
+testSyntaxError(`[import] = 42`, `SyntaxError: Unexpected token ']'. import call expects exactly one argument.`);
+testSyntaxError(`{import} = 42`, `SyntaxError: Unexpected token '}'. import call expects exactly one argument.`);
+testSyntaxError(`let import = 42`, `SyntaxError: Unexpected keyword 'import'`);
+testSyntaxError(`var import = 42`, `SyntaxError: Cannot use the keyword 'import' as a variable name.`);
+testSyntaxError(`const import = 42`, `SyntaxError: Cannot use the keyword 'import' as a lexical variable name.`);
+
+(async function () {
+    await testSyntax(`import(&quot;./import-tests/cocoa.js&quot;)`);
+    await testSyntax(`import(&quot;./import-tests/../import-tests/cocoa.js&quot;)`);
+}()).catch((error) =&gt; {
+    print(String(error));
+    abort();
+});
</ins></span></pre></div>
<a id="trunkJSTestsstressimporttestscocoajs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-tests/cocoa.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-tests/cocoa.js                                (rev 0)
+++ trunk/JSTests/stress/import-tests/cocoa.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,7 @@
</span><ins>+export class Cocoa {
+}
+
+export function hello()
+{
+    return 42;
+}
</ins></span></pre></div>
<a id="trunkJSTestsstressimporttestsmultiplejs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-tests/multiple.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-tests/multiple.js                                (rev 0)
+++ trunk/JSTests/stress/import-tests/multiple.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+export function result()
+{
+    return import('./multiple2.js');
+}
</ins></span></pre></div>
<a id="trunkJSTestsstressimporttestsmultiple2js"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-tests/multiple2.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-tests/multiple2.js                                (rev 0)
+++ trunk/JSTests/stress/import-tests/multiple2.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,4 @@
</span><ins>+export function ok()
+{
+    return 42;
+}
</ins></span></pre></div>
<a id="trunkJSTestsstressimporttestsshouldjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/stress/import-tests/should.js (0 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-tests/should.js                                (rev 0)
+++ trunk/JSTests/stress/import-tests/should.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -0,0 +1,19 @@
</span><ins>+export function shouldBe(actual, expected) {
+    if (actual !== expected)
+        throw new Error(`bad value: ${String(actual)}`);
+}
+
+export function shouldThrow(func, errorMessage) {
+    var errorThrown = false;
+    var error = null;
+    try {
+        func();
+    } catch (e) {
+        errorThrown = true;
+        error = e;
+    }
+    if (!errorThrown)
+        throw new Error('not thrown');
+    if (String(error) !== errorMessage)
+        throw new Error(`bad error: ${String(error)}`);
+}
</ins></span></pre></div>
<a id="trunkJSTestsstressmodulessyntaxerrorjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/modules-syntax-error.js (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/modules-syntax-error.js        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/JSTests/stress/modules-syntax-error.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -107,25 +107,25 @@
</span><span class="cx"> function noTopLevel() {
</span><span class="cx">     import * as from from &quot;Cocoa&quot;
</span><span class="cx"> }
</span><del>-`, `SyntaxError: Unexpected keyword 'import':3`);
</del><ins>+`, `SyntaxError: Unexpected token '*'. import call expects exactly one argument.:3`);
</ins><span class="cx"> 
</span><span class="cx"> checkModuleSyntaxError(String.raw`
</span><span class="cx"> if (noTopLevel) {
</span><span class="cx">     import * as from from &quot;Cocoa&quot;
</span><span class="cx"> }
</span><del>-`, `SyntaxError: Unexpected keyword 'import':3`);
</del><ins>+`, `SyntaxError: Unexpected token '*'. import call expects exactly one argument.:3`);
</ins><span class="cx"> 
</span><span class="cx"> checkModuleSyntaxError(String.raw`
</span><span class="cx"> {
</span><span class="cx">     import * as from from &quot;Cocoa&quot;
</span><span class="cx"> }
</span><del>-`, `SyntaxError: Unexpected keyword 'import':3`);
</del><ins>+`, `SyntaxError: Unexpected token '*'. import call expects exactly one argument.:3`);
</ins><span class="cx"> 
</span><span class="cx"> checkModuleSyntaxError(String.raw`
</span><span class="cx"> for (var i = 0; i &lt; 1000; ++i) {
</span><span class="cx">     import * as from from &quot;Cocoa&quot;
</span><span class="cx"> }
</span><del>-`, `SyntaxError: Unexpected keyword 'import':3`);
</del><ins>+`, `SyntaxError: Unexpected token '*'. import call expects exactly one argument.:3`);
</ins><span class="cx"> 
</span><span class="cx"> checkModuleSyntaxError(String.raw`
</span><span class="cx"> import for from &quot;Cocoa&quot;;
</span></span></pre></div>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/LayoutTests/ChangeLog        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -1,3 +1,12 @@
</span><ins>+2017-01-09  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [JSC] Prototype dynamic-import
+        https://bugs.webkit.org/show_bug.cgi?id=165724
+
+        Reviewed by Saam Barati.
+
+        * sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt:
+
</ins><span class="cx"> 2017-01-09  Andy Estes  &lt;aestes@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [QuickLook] Add a layout test for webkit.org/b/135651
</span></span></pre></div>
<a id="trunkLayoutTestssputnikConformance07_Lexical_Conventions75_Tokens753_Future_Reserved_WordsS753_A116expectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/LayoutTests/sputnik/Conformance/07_Lexical_Conventions/7.5_Tokens/7.5.3_Future_Reserved_Words/S7.5.3_A1.16-expected.txt        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -1,4 +1,4 @@
</span><del>-CONSOLE MESSAGE: line 76: SyntaxError: Unexpected keyword 'import'
</del><ins>+CONSOLE MESSAGE: line 76: SyntaxError: Unexpected token '='. import call expects exactly one argument.
</ins><span class="cx"> S7.5.3_A1.16
</span><span class="cx"> 
</span><span class="cx"> PASS Expected parsing failure
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -1,3 +1,102 @@
</span><ins>+2017-01-09  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [JSC] Prototype dynamic-import
+        https://bugs.webkit.org/show_bug.cgi?id=165724
+
+        Reviewed by Saam Barati.
+
+        In this patch, we implement stage3 dynamic-import proposal[1].
+        This patch adds a new special operator `import`. And by using it, we can import
+        the module dynamically from modules and scripts. Before this feature, the module
+        is always imported statically and before executing the modules, importing the modules
+        needs to be done. And especially, the module can only be imported from the module.
+        So the classic script cannot import and use the modules. This dynamic-import relaxes
+        the above restrictions.
+
+        The typical dynamic-import form is the following.
+
+            import(&quot;...&quot;).then(function (namespace) { ... });
+
+        You can pass any AssignmentExpression for the import operator. So you can determine
+        the importing modules dynamically.
+
+            import(value).then(function (namespace) { ... });
+
+        And previously the module import declaration is only allowed in the top level statements.
+        But this import operator is just an expression. So you can use it in the function.
+        And you can use it conditionally.
+
+            async function go(cond)
+            {
+                if (cond)
+                    return import(&quot;...&quot;);
+                return undefined;
+            }
+            await go(true);
+
+        Currently, this patch just implements this feature only for the JSC shell.
+        JSC module loader requires a new hook, `importModule`. And the JSC shell implements
+        this hook. So, for now, this dynamic-import is not available in the browser side.
+        If you write this `import` call, it always returns the rejected promise.
+
+        import is implemented like a special operator similar to `super`.
+        This is because import is context-sensitive. If you call the `import`, the module
+        key resolution is done based on the caller's running context.
+
+        For example, if you are running the script which filename is &quot;./ok/hello.js&quot;, the module
+        key for the call`import(&quot;./resource/syntax.js&quot;)` becomes `&quot;./ok/resource/syntax.js&quot;`.
+        But if you write the completely same import form in the script &quot;./error/hello.js&quot;, the
+        key becomes &quot;./error/resource/syntax.js&quot;. So exposing this feature as the `import`
+        function is misleading: this function becomes caller's context-sensitive. That's why
+        dynamic-import is specified as a special operator.
+
+        To resolve the module key, we need the caller's context information like the filename of
+        the caller. This is provided by the SourceOrigin implemented in r210149.
+        In the JSC shell implementation, this SourceOrigin holds the filename of the caller. So
+        based on this implementation, the module loader resolve the module key.
+        In the near future, we will extend this SourceOrigin to hold more information needed for
+        the browser-side import implementation.
+
+        [1]: https://tc39.github.io/proposal-dynamic-import/
+
+        * builtins/ModuleLoaderPrototype.js:
+        (importModule):
+        * bytecompiler/BytecodeGenerator.cpp:
+        (JSC::BytecodeGenerator::emitGetTemplateObject):
+        (JSC::BytecodeGenerator::emitGetGlobalPrivate):
+        * bytecompiler/BytecodeGenerator.h:
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::ImportNode::emitBytecode):
+        * jsc.cpp:
+        (absolutePath):
+        (GlobalObject::moduleLoaderImportModule):
+        (functionRun):
+        (functionLoad):
+        (functionCheckSyntax):
+        (runWithScripts):
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createImportExpr):
+        * parser/NodeConstructors.h:
+        (JSC::ImportNode::ImportNode):
+        * parser/Nodes.h:
+        (JSC::ExpressionNode::isImportNode):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseMemberExpression):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createImportExpr):
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::init):
+        * runtime/JSGlobalObject.h:
+        * runtime/JSGlobalObjectFunctions.cpp:
+        (JSC::globalFuncImportModule):
+        * runtime/JSGlobalObjectFunctions.h:
+        * runtime/JSModuleLoader.cpp:
+        (JSC::JSModuleLoader::importModule):
+        (JSC::JSModuleLoader::getModuleNamespaceObject):
+        * runtime/JSModuleLoader.h:
+        * runtime/ModuleLoaderPrototype.cpp:
+        (JSC::moduleLoaderPrototypeGetModuleNamespaceObject):
+
</ins><span class="cx"> 2017-01-08  Filip Pizlo  &lt;fpizlo@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Make the collector's fixpoint smart about scheduling work
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebuiltinsModuleLoaderPrototypejs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/builtins/ModuleLoaderPrototype.js        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -470,3 +470,19 @@
</span><span class="cx">     this.link(entry, initiator);
</span><span class="cx">     return this.moduleEvaluation(entry.module, initiator);
</span><span class="cx"> }
</span><ins>+
+function importModule(moduleName, referrer, initiator)
+{
+    &quot;use strict&quot;;
+
+    // Loader.resolve hook point.
+    // resolve: moduleName =&gt; Promise(moduleKey)
+    // Take the name and resolve it to the unique identifier for the resource location.
+    // For example, take the &quot;jquery&quot; and return the URL for the resource.
+    return this.resolve(moduleName, referrer, initiator).then((key) =&gt; {
+        return this.requestInstantiateAll(key, initiator);
+    }).then((entry) =&gt; {
+        this.linkAndEvaluateModule(entry.key, initiator);
+        return this.getModuleNamespaceObject(entry.module);
+    });
+}
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -4261,22 +4261,24 @@
</span><span class="cx">         cookedStrings.append(templateString-&gt;value()-&gt;cooked().impl());
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    RefPtr&lt;RegisterID&gt; getTemplateObject = nullptr;
-    Variable var = variable(propertyNames().builtinNames().getTemplateObjectPrivateName());
-    if (RegisterID* local = var.local())
-        getTemplateObject = emitMove(newTemporary(), local);
-    else {
-        getTemplateObject = newTemporary();
-        RefPtr&lt;RegisterID&gt; scope = newTemporary();
-        moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), var));
-        emitGetFromScope(getTemplateObject.get(), scope.get(), var, ThrowIfNotFound);
-    }
-
</del><ins>+    RefPtr&lt;RegisterID&gt; getTemplateObject = emitGetGlobalPrivate(newTemporary(), propertyNames().builtinNames().getTemplateObjectPrivateName());
</ins><span class="cx">     CallArguments arguments(*this, nullptr);
</span><span class="cx">     emitLoad(arguments.thisRegister(), JSValue(addTemplateRegistryKeyConstant(m_vm-&gt;templateRegistryKeyTable().createKey(rawStrings, cookedStrings))));
</span><span class="cx">     return emitCall(dst, getTemplateObject.get(), NoExpectedFunction, arguments, taggedTemplate-&gt;divot(), taggedTemplate-&gt;divotStart(), taggedTemplate-&gt;divotEnd(), DebuggableCall::No);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+RegisterID* BytecodeGenerator::emitGetGlobalPrivate(RegisterID* dst, const Identifier&amp; property)
+{
+    dst = tempDestination(dst);
+    Variable var = variable(property);
+    if (RegisterID* local = var.local())
+        return emitMove(dst, local);
+
+    RefPtr&lt;RegisterID&gt; scope = newTemporary();
+    moveToDestinationIfNeeded(scope.get(), emitResolveScope(scope.get(), var));
+    return emitGetFromScope(dst, scope.get(), var, ThrowIfNotFound);
+}
+
</ins><span class="cx"> RegisterID* BytecodeGenerator::emitGetEnumerableLength(RegisterID* dst, RegisterID* base)
</span><span class="cx"> {
</span><span class="cx">     emitOpcode(op_get_enumerable_length);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerBytecodeGeneratorh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/bytecompiler/BytecodeGenerator.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -678,6 +678,7 @@
</span><span class="cx">         void emitEnumeration(ThrowableExpressionData* enumerationNode, ExpressionNode* subjectNode, const std::function&lt;void(BytecodeGenerator&amp;, RegisterID*)&gt;&amp; callBack, ForOfNode* = nullptr, RegisterID* forLoopSymbolTable = nullptr);
</span><span class="cx"> 
</span><span class="cx">         RegisterID* emitGetTemplateObject(RegisterID* dst, TaggedTemplateNode*);
</span><ins>+        RegisterID* emitGetGlobalPrivate(RegisterID* dst, const Identifier&amp; property);
</ins><span class="cx"> 
</span><span class="cx">         enum class ReturnFrom { Normal, Finally };
</span><span class="cx">         RegisterID* emitReturn(RegisterID* src, ReturnFrom = ReturnFrom::Normal);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecompilerNodesCodegencpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -190,6 +190,17 @@
</span><span class="cx">     return generator.moveToDestinationIfNeeded(generator.finalDestination(dst), result);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+// ------------------------------ ImportNode -------------------------------------
+
+RegisterID* ImportNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
+{
+    RefPtr&lt;RegisterID&gt; importModule = generator.emitGetGlobalPrivate(generator.newTemporary(), generator.propertyNames().builtinNames().importModulePrivateName());
+    CallArguments arguments(generator, nullptr, 1);
+    generator.emitLoad(arguments.thisRegister(), jsUndefined());
+    generator.emitNode(arguments.argumentRegister(0), m_expr);
+    return generator.emitCall(generator.finalDestination(dst, importModule.get()), importModule.get(), NoExpectedFunction, arguments, divot(), divotStart(), divotEnd(), DebuggableCall::No);
+}
+
</ins><span class="cx"> // ------------------------------ NewTargetNode ----------------------------------
</span><span class="cx"> 
</span><span class="cx"> RegisterID* NewTargetNode::emitBytecode(BytecodeGenerator&amp; generator, RegisterID* dst)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorejsccpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/jsc.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/jsc.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/jsc.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -25,6 +25,7 @@
</span><span class="cx"> #include &quot;ArrayBuffer.h&quot;
</span><span class="cx"> #include &quot;ArrayPrototype.h&quot;
</span><span class="cx"> #include &quot;BuiltinExecutableCreator.h&quot;
</span><ins>+#include &quot;BuiltinNames.h&quot;
</ins><span class="cx"> #include &quot;ButterflyInlines.h&quot;
</span><span class="cx"> #include &quot;CodeBlock.h&quot;
</span><span class="cx"> #include &quot;Completion.h&quot;
</span><span class="lines">@@ -48,6 +49,7 @@
</span><span class="cx"> #include &quot;JSInternalPromise.h&quot;
</span><span class="cx"> #include &quot;JSInternalPromiseDeferred.h&quot;
</span><span class="cx"> #include &quot;JSLock.h&quot;
</span><ins>+#include &quot;JSModuleLoader.h&quot;
</ins><span class="cx"> #include &quot;JSNativeStdFunction.h&quot;
</span><span class="cx"> #include &quot;JSONObject.h&quot;
</span><span class="cx"> #include &quot;JSProxy.h&quot;
</span><span class="lines">@@ -1101,10 +1103,10 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> template&lt;typename Vector&gt;
</span><del>-static inline SourceCode jscSource(const Vector&amp; utf8, const String&amp; filename)
</del><ins>+static inline SourceCode jscSource(const Vector&amp; utf8, const SourceOrigin&amp; sourceOrigin, const String&amp; filename)
</ins><span class="cx"> {
</span><span class="cx">     String str = stringFromUTF(utf8);
</span><del>-    return makeSource(str, SourceOrigin { filename }, filename);
</del><ins>+    return makeSource(str, sourceOrigin, filename);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> class GlobalObject : public JSGlobalObject {
</span><span class="lines">@@ -1277,6 +1279,7 @@
</span><span class="cx">         putDirect(vm, identifier, JSFunction::create(vm, this, arguments, identifier.string(), function, NoIntrinsic, function));
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    static JSInternalPromise* moduleLoaderImportModule(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&amp;);
</ins><span class="cx">     static JSInternalPromise* moduleLoaderResolve(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
</span><span class="cx">     static JSInternalPromise* moduleLoaderFetch(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue);
</span><span class="cx"> };
</span><span class="lines">@@ -1288,6 +1291,7 @@
</span><span class="cx">     &amp;javaScriptRuntimeFlags,
</span><span class="cx">     nullptr,
</span><span class="cx">     &amp;shouldInterruptScriptBeforeTimeout,
</span><ins>+    &amp;moduleLoaderImportModule,
</ins><span class="cx">     &amp;moduleLoaderResolve,
</span><span class="cx">     &amp;moduleLoaderFetch,
</span><span class="cx">     nullptr,
</span><span class="lines">@@ -1420,6 +1424,29 @@
</span><span class="cx">     return builder.toString();
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static String absolutePath(const String&amp; fileName)
+{
+    auto directoryName = currentWorkingDirectory();
+    if (!directoryName)
+        return fileName;
+    return resolvePath(directoryName.value(), ModuleName(fileName.impl()));
+}
+
+JSInternalPromise* GlobalObject::moduleLoaderImportModule(JSGlobalObject*, ExecState* exec, JSModuleLoader* moduleLoader, JSString* moduleName, const SourceOrigin&amp; sourceOrigin)
+{
+    auto* function = jsCast&lt;JSObject*&gt;(moduleLoader-&gt;get(exec, exec-&gt;propertyNames().builtinNames().importModulePublicName()));
+    CallData callData;
+    auto callType = JSC::getCallData(function, callData);
+    ASSERT(callType != CallType::None);
+
+    MarkedArgumentBuffer arguments;
+    arguments.append(moduleName);
+    arguments.append(jsString(exec, sourceOrigin.string()));
+    arguments.append(jsUndefined());
+
+    return jsCast&lt;JSInternalPromise*&gt;(call(exec, function, callType, callData, moduleLoader, arguments));
+}
+
</ins><span class="cx"> JSInternalPromise* GlobalObject::moduleLoaderResolve(JSGlobalObject* globalObject, ExecState* exec, JSModuleLoader*, JSValue keyValue, JSValue referrerValue, JSValue)
</span><span class="cx"> {
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><span class="lines">@@ -1924,7 +1951,7 @@
</span><span class="cx">     NakedPtr&lt;Exception&gt; exception;
</span><span class="cx">     StopWatch stopWatch;
</span><span class="cx">     stopWatch.start();
</span><del>-    evaluate(globalObject-&gt;globalExec(), jscSource(script, fileName), JSValue(), exception);
</del><ins>+    evaluate(globalObject-&gt;globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), exception);
</ins><span class="cx">     stopWatch.stop();
</span><span class="cx"> 
</span><span class="cx">     if (exception) {
</span><span class="lines">@@ -1976,7 +2003,7 @@
</span><span class="cx">     JSGlobalObject* globalObject = exec-&gt;lexicalGlobalObject();
</span><span class="cx">     
</span><span class="cx">     NakedPtr&lt;Exception&gt; evaluationException;
</span><del>-    JSValue result = evaluate(globalObject-&gt;globalExec(), jscSource(script, fileName), JSValue(), evaluationException);
</del><ins>+    JSValue result = evaluate(globalObject-&gt;globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
</ins><span class="cx">     if (evaluationException)
</span><span class="cx">         throwException(exec, scope, evaluationException);
</span><span class="cx">     return JSValue::encode(result);
</span><span class="lines">@@ -2047,7 +2074,7 @@
</span><span class="cx">     stopWatch.start();
</span><span class="cx"> 
</span><span class="cx">     JSValue syntaxException;
</span><del>-    bool validSyntax = checkSyntax(globalObject-&gt;globalExec(), jscSource(script, fileName), &amp;syntaxException);
</del><ins>+    bool validSyntax = checkSyntax(globalObject-&gt;globalExec(), jscSource(script, SourceOrigin { absolutePath(fileName) }, fileName), &amp;syntaxException);
</ins><span class="cx">     stopWatch.stop();
</span><span class="cx"> 
</span><span class="cx">     if (!validSyntax)
</span><span class="lines">@@ -2909,7 +2936,7 @@
</span><span class="cx">         bool isLastFile = i == scripts.size() - 1;
</span><span class="cx">         if (isModule) {
</span><span class="cx">             if (!promise)
</span><del>-                promise = loadAndEvaluateModule(globalObject-&gt;globalExec(), jscSource(scriptBuffer, fileName));
</del><ins>+                promise = loadAndEvaluateModule(globalObject-&gt;globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName));
</ins><span class="cx">             scope.clearException();
</span><span class="cx"> 
</span><span class="cx">             JSFunction* fulfillHandler = JSNativeStdFunction::create(vm, globalObject, 1, String(), [&amp;, isLastFile](ExecState* exec) {
</span><span class="lines">@@ -2926,7 +2953,7 @@
</span><span class="cx">             vm.drainMicrotasks();
</span><span class="cx">         } else {
</span><span class="cx">             NakedPtr&lt;Exception&gt; evaluationException;
</span><del>-            JSValue returnValue = evaluate(globalObject-&gt;globalExec(), jscSource(scriptBuffer, fileName), JSValue(), evaluationException);
</del><ins>+            JSValue returnValue = evaluate(globalObject-&gt;globalExec(), jscSource(scriptBuffer, SourceOrigin { absolutePath(fileName) }, fileName), JSValue(), evaluationException);
</ins><span class="cx">             ASSERT(!scope.exception());
</span><span class="cx">             if (evaluationException)
</span><span class="cx">                 returnValue = evaluationException-&gt;value();
</span><span class="lines">@@ -2999,7 +3026,7 @@
</span><span class="cx">             break;
</span><span class="cx"> 
</span><span class="cx">         NakedPtr&lt;Exception&gt; evaluationException;
</span><del>-        JSValue returnValue = evaluate(globalObject-&gt;globalExec(), jscSource(line, sourceOrigin.string()), JSValue(), evaluationException);
</del><ins>+        JSValue returnValue = evaluate(globalObject-&gt;globalExec(), jscSource(line, sourceOrigin, sourceOrigin.string()), JSValue(), evaluationException);
</ins><span class="cx"> #endif
</span><span class="cx">         if (evaluationException)
</span><span class="cx">             printf(&quot;Exception: %s\n&quot;, evaluationException-&gt;value().toWTFString(globalObject-&gt;globalExec()).utf8().data());
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -178,6 +178,12 @@
</span><span class="cx">     {
</span><span class="cx">         return new (m_parserArena) SuperNode(location);
</span><span class="cx">     }
</span><ins>+    ExpressionNode* createImportExpr(const JSTokenLocation&amp; location, ExpressionNode* expr, const JSTextPosition&amp; start, const JSTextPosition&amp; divot, const JSTextPosition&amp; end)
+    {
+        auto* node = new (m_parserArena) ImportNode(location, expr);
+        setExceptionLocation(node, start, divot, end);
+        return node;
+    }
</ins><span class="cx">     ExpressionNode* createNewTargetExpr(const JSTokenLocation location)
</span><span class="cx">     {
</span><span class="cx">         usesNewTarget();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodeConstructorsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/NodeConstructors.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/parser/NodeConstructors.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -167,6 +167,12 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    inline ImportNode::ImportNode(const JSTokenLocation&amp; location, ExpressionNode* expr)
+        : ExpressionNode(location)
+        , m_expr(expr)
+    {
+    }
+
</ins><span class="cx">     inline NewTargetNode::NewTargetNode(const JSTokenLocation&amp; location)
</span><span class="cx">         : ExpressionNode(location)
</span><span class="cx">     {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserNodesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Nodes.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Nodes.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/parser/Nodes.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -186,6 +186,7 @@
</span><span class="cx">         virtual bool isBoolean() const { return false; }
</span><span class="cx">         virtual bool isSpreadExpression() const { return false; }
</span><span class="cx">         virtual bool isSuperNode() const { return false; }
</span><ins>+        virtual bool isImportNode() const { return false; }
</ins><span class="cx">         virtual bool isNewTarget() const { return false; }
</span><span class="cx">         virtual bool isBytecodeIntrinsicNode() const { return false; }
</span><span class="cx"> 
</span><span class="lines">@@ -570,6 +571,17 @@
</span><span class="cx">         RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
</span><span class="cx">     };
</span><span class="cx"> 
</span><ins>+    class ImportNode : public ExpressionNode, public ThrowableExpressionData {
+    public:
+        ImportNode(const JSTokenLocation&amp;, ExpressionNode*);
+
+    private:
+        bool isImportNode() const override { return true; }
+        RegisterID* emitBytecode(BytecodeGenerator&amp;, RegisterID* = 0) override;
+
+        ExpressionNode* m_expr;
+    };
+
</ins><span class="cx">     class NewTargetNode final : public ExpressionNode {
</span><span class="cx">     public:
</span><span class="cx">         NewTargetNode(const JSTokenLocation&amp;);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -4343,7 +4343,8 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool baseIsSuper = match(SUPER);
</span><del>-    semanticFailIfTrue(baseIsSuper &amp;&amp; newCount, &quot;Cannot use new with super&quot;);
</del><ins>+    bool baseIsImport = match(IMPORT);
+    semanticFailIfTrue((baseIsSuper || baseIsImport) &amp;&amp; newCount, &quot;Cannot use new with &quot;, getToken());
</ins><span class="cx"> 
</span><span class="cx">     bool baseIsNewTarget = false;
</span><span class="cx">     if (newCount &amp;&amp; match(DOT)) {
</span><span class="lines">@@ -4383,6 +4384,14 @@
</span><span class="cx">                 semanticFailIfTrue(functionSuperBinding == SuperBinding::NotNeeded, &quot;super is not valid in this context&quot;);
</span><span class="cx">             }
</span><span class="cx">         }
</span><ins>+    } else if (baseIsImport) {
+        JSTextPosition expressionEnd = lastTokenEndPosition();
+        next();
+        consumeOrFail(OPENPAREN, &quot;import call expects exactly one argument&quot;);
+        TreeExpression expr = parseAssignmentExpression(context);
+        failIfFalse(expr, &quot;Cannot parse expression&quot;);
+        consumeOrFail(CLOSEPAREN, &quot;import call expects exactly one argument&quot;);
+        return context.createImportExpr(location, expr, expressionStart, expressionEnd, lastTokenEndPosition());
</ins><span class="cx">     } else if (!baseIsNewTarget) {
</span><span class="cx">         const bool isAsync = match(ASYNC);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -71,7 +71,7 @@
</span><span class="cx">     enum { NoneExpr = 0,
</span><span class="cx">         ResolveEvalExpr, ResolveExpr, IntegerExpr, DoubleExpr, StringExpr,
</span><span class="cx">         ThisExpr, NullExpr, BoolExpr, RegExpExpr, ObjectLiteralExpr,
</span><del>-        FunctionExpr, ClassExpr, SuperExpr, BracketExpr, DotExpr, CallExpr,
</del><ins>+        FunctionExpr, ClassExpr, SuperExpr, ImportExpr, BracketExpr, DotExpr, CallExpr,
</ins><span class="cx">         NewExpr, PreExpr, PostExpr, UnaryExpr, BinaryExpr,
</span><span class="cx">         ConditionalExpr, AssignmentExpr, TypeofExpr, NewTargetExpr,
</span><span class="cx">         DeleteExpr, ArrayLiteralExpr, BindingDestructuring, RestParameter,
</span><span class="lines">@@ -156,6 +156,7 @@
</span><span class="cx">     ExpressionType createLogicalNot(const JSTokenLocation&amp;, ExpressionType) { return UnaryExpr; }
</span><span class="cx">     ExpressionType createUnaryPlus(const JSTokenLocation&amp;, ExpressionType) { return UnaryExpr; }
</span><span class="cx">     ExpressionType createVoid(const JSTokenLocation&amp;, ExpressionType) { return UnaryExpr; }
</span><ins>+    ExpressionType createImportExpr(const JSTokenLocation&amp;, ExpressionType, int, int, int) { return ImportExpr; }
</ins><span class="cx">     ExpressionType createThisExpr(const JSTokenLocation&amp;) { return ThisExpr; }
</span><span class="cx">     ExpressionType createSuperExpr(const JSTokenLocation&amp;) { return SuperExpr; }
</span><span class="cx">     ExpressionType createNewTargetExpr(const JSTokenLocation&amp;) { return NewTargetExpr; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -256,6 +256,7 @@
</span><span class="cx">     nullptr,
</span><span class="cx">     nullptr,
</span><span class="cx">     nullptr,
</span><ins>+    nullptr,
</ins><span class="cx">     nullptr
</span><span class="cx"> };
</span><span class="cx"> 
</span><span class="lines">@@ -732,6 +733,7 @@
</span><span class="cx">     JSFunction* privateFuncTrunc = JSFunction::create(vm, this, 0, String(), mathProtoFuncTrunc, TruncIntrinsic);
</span><span class="cx"> 
</span><span class="cx">     JSFunction* privateFuncGetTemplateObject = JSFunction::create(vm, this, 0, String(), getTemplateObject);
</span><ins>+    JSFunction* privateFuncImportModule = JSFunction::create(vm, this, 0, String(), globalFuncImportModule);
</ins><span class="cx">     JSFunction* privateFuncTypedArrayLength = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncLength);
</span><span class="cx">     JSFunction* privateFuncTypedArrayGetOriginalConstructor = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncGetOriginalConstructor);
</span><span class="cx">     JSFunction* privateFuncTypedArraySort = JSFunction::create(vm, this, 0, String(), typedArrayViewPrivateFuncSort);
</span><span class="lines">@@ -785,6 +787,7 @@
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;undefinedKeyword, jsUndefined(), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().ownEnumerablePropertyKeysPrivateName(), JSFunction::create(vm, this, 0, String(), ownEnumerablePropertyKeys), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().getTemplateObjectPrivateName(), privateFuncGetTemplateObject, DontEnum | DontDelete | ReadOnly),
</span><ins>+        GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().importModulePrivateName(), privateFuncImportModule, DontEnum | DontDelete | ReadOnly),
</ins><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().enqueueJobPrivateName(), JSFunction::create(vm, this, 0, String(), enqueueJob), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().ErrorPrivateName(), m_errorConstructor.get(), DontEnum | DontDelete | ReadOnly),
</span><span class="cx">         GlobalPropertyInfo(vm.propertyNames-&gt;builtinNames().RangeErrorPrivateName(), m_rangeErrorConstructor.get(), DontEnum | DontDelete | ReadOnly),
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjecth"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -184,6 +184,9 @@
</span><span class="cx">     typedef bool (*ShouldInterruptScriptBeforeTimeoutPtr)(const JSGlobalObject*);
</span><span class="cx">     ShouldInterruptScriptBeforeTimeoutPtr shouldInterruptScriptBeforeTimeout;
</span><span class="cx"> 
</span><ins>+    typedef JSInternalPromise* (*ModuleLoaderImportModulePtr)(JSGlobalObject*, ExecState*, JSModuleLoader*, JSString*, const SourceOrigin&amp;);
+    ModuleLoaderImportModulePtr moduleLoaderImportModule;
+
</ins><span class="cx">     typedef JSInternalPromise* (*ModuleLoaderResolvePtr)(JSGlobalObject*, ExecState*, JSModuleLoader*, JSValue, JSValue, JSValue);
</span><span class="cx">     ModuleLoaderResolvePtr moduleLoaderResolve;
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionscpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -27,10 +27,14 @@
</span><span class="cx"> 
</span><span class="cx"> #include &quot;CallFrame.h&quot;
</span><span class="cx"> #include &quot;EvalExecutable.h&quot;
</span><ins>+#include &quot;Exception.h&quot;
</ins><span class="cx"> #include &quot;IndirectEvalExecutable.h&quot;
</span><span class="cx"> #include &quot;Interpreter.h&quot;
</span><span class="cx"> #include &quot;JSFunction.h&quot;
</span><span class="cx"> #include &quot;JSGlobalObject.h&quot;
</span><ins>+#include &quot;JSInternalPromise.h&quot;
+#include &quot;JSModuleLoader.h&quot;
+#include &quot;JSPromiseDeferred.h&quot;
</ins><span class="cx"> #include &quot;JSString.h&quot;
</span><span class="cx"> #include &quot;JSStringBuilder.h&quot;
</span><span class="cx"> #include &quot;Lexer.h&quot;
</span><span class="lines">@@ -925,4 +929,39 @@
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState* exec)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto catchScope = DECLARE_CATCH_SCOPE(vm);
+
+    auto* globalObject = exec-&gt;lexicalGlobalObject();
+
+    auto* promise = JSPromiseDeferred::create(exec, globalObject);
+    RETURN_IF_EXCEPTION(catchScope, { });
+
+    auto sourceOrigin = exec-&gt;callerSourceOrigin();
+    if (sourceOrigin.isNull()) {
+        promise-&gt;reject(exec, createError(exec, ASCIILiteral(&quot;Could not resolve the module specifier.&quot;)));
+        return JSValue::encode(promise-&gt;promise());
+    }
+
+    RELEASE_ASSERT(exec-&gt;argumentCount() == 1);
+    auto* specifier = exec-&gt;uncheckedArgument(0).toString(exec);
+    if (Exception* exception = catchScope.exception()) {
+        catchScope.clearException();
+        promise-&gt;reject(exec, exception);
+        return JSValue::encode(promise-&gt;promise());
+    }
+
+    auto* internalPromise = globalObject-&gt;moduleLoader()-&gt;importModule(exec, specifier, sourceOrigin);
+    if (Exception* exception = catchScope.exception()) {
+        catchScope.clearException();
+        promise-&gt;reject(exec, exception);
+        return JSValue::encode(promise-&gt;promise());
+    }
+    promise-&gt;resolve(exec, internalPromise);
+
+    return JSValue::encode(promise-&gt;promise());
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSGlobalObjectFunctionsh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/JSGlobalObjectFunctions.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -50,6 +50,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncProtoGetter(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncProtoSetter(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL globalFuncBuiltinLog(ExecState*);
</span><ins>+EncodedJSValue JSC_HOST_CALL globalFuncImportModule(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> static const double mantissaOverflowLowerBound = 9007199254740992.0;
</span><span class="cx"> double parseIntOverflow(const LChar*, unsigned length, int radix);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSModuleLoadercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/JSModuleLoader.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -134,6 +134,30 @@
</span><span class="cx">     return call(exec, function, callType, callData, this, arguments);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSInternalPromise* JSModuleLoader::importModule(ExecState* exec, JSString* moduleName, const SourceOrigin&amp; referrer)
+{
+    if (Options::dumpModuleLoadingState())
+        dataLog(&quot;Loader [import] &quot;, printableModuleKey(exec, moduleName), &quot;\n&quot;);
+
+    auto* globalObject = exec-&gt;lexicalGlobalObject();
+    VM&amp; vm = globalObject-&gt;vm();
+    auto scope = DECLARE_CATCH_SCOPE(vm);
+
+    if (globalObject-&gt;globalObjectMethodTable()-&gt;moduleLoaderImportModule)
+        return globalObject-&gt;globalObjectMethodTable()-&gt;moduleLoaderImportModule(globalObject, exec, this, moduleName, referrer);
+
+    auto* deferred = JSInternalPromiseDeferred::create(exec, globalObject);
+    auto moduleNameString = moduleName-&gt;value(exec);
+    if (UNLIKELY(scope.exception())) {
+        JSValue exception = scope.exception()-&gt;value();
+        scope.clearException();
+        deferred-&gt;reject(exec, exception);
+        return deferred-&gt;promise();
+    }
+    deferred-&gt;reject(exec, createError(exec, makeString(&quot;Could not import the module '&quot;, moduleNameString, &quot;'.&quot;)));
+    return deferred-&gt;promise();
+}
+
</ins><span class="cx"> JSInternalPromise* JSModuleLoader::resolve(ExecState* exec, JSValue name, JSValue referrer, JSValue initiator)
</span><span class="cx"> {
</span><span class="cx">     if (Options::dumpModuleLoadingState())
</span><span class="lines">@@ -197,4 +221,19 @@
</span><span class="cx">     return moduleRecord-&gt;evaluate(exec);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+JSModuleNamespaceObject* JSModuleLoader::getModuleNamespaceObject(ExecState* exec, JSValue moduleRecordValue)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* moduleRecord = jsDynamicCast&lt;AbstractModuleRecord*&gt;(moduleRecordValue);
+    if (!moduleRecord) {
+        throwTypeError(exec, scope);
+        return nullptr;
+    }
+
+    scope.release();
+    return moduleRecord-&gt;getModuleNamespace(exec);
+}
+
</ins><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeJSModuleLoaderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/JSModuleLoader.h        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -31,6 +31,7 @@
</span><span class="cx"> namespace JSC {
</span><span class="cx"> 
</span><span class="cx"> class JSInternalPromise;
</span><ins>+class JSModuleNamespaceObject;
</ins><span class="cx"> 
</span><span class="cx"> class JSModuleLoader : public JSNonFinalObject {
</span><span class="cx"> private:
</span><span class="lines">@@ -67,6 +68,7 @@
</span><span class="cx">     JSValue linkAndEvaluateModule(ExecState*, JSValue moduleKey, JSValue initiator);
</span><span class="cx"> 
</span><span class="cx">     // Platform dependent hooked APIs.
</span><ins>+    JSInternalPromise* importModule(ExecState*, JSString* moduleName, const SourceOrigin&amp; referrer);
</ins><span class="cx">     JSInternalPromise* resolve(ExecState*, JSValue name, JSValue referrer, JSValue initiator);
</span><span class="cx">     JSInternalPromise* fetch(ExecState*, JSValue key, JSValue initiator);
</span><span class="cx">     JSInternalPromise* instantiate(ExecState*, JSValue key, JSValue source, JSValue initiator);
</span><span class="lines">@@ -74,6 +76,9 @@
</span><span class="cx">     // Additional platform dependent hooked APIs.
</span><span class="cx">     JSValue evaluate(ExecState*, JSValue key, JSValue moduleRecord, JSValue initiator);
</span><span class="cx"> 
</span><ins>+    // Utility functions.
+    JSModuleNamespaceObject* getModuleNamespaceObject(ExecState*, JSValue moduleRecord);
+
</ins><span class="cx"> protected:
</span><span class="cx">     void finishCreation(ExecState*, VM&amp;, JSGlobalObject*);
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeModuleLoaderPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/JavaScriptCore/runtime/ModuleLoaderPrototype.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -37,6 +37,7 @@
</span><span class="cx"> #include &quot;JSMap.h&quot;
</span><span class="cx"> #include &quot;JSModuleEnvironment.h&quot;
</span><span class="cx"> #include &quot;JSModuleLoader.h&quot;
</span><ins>+#include &quot;JSModuleNamespaceObject.h&quot;
</ins><span class="cx"> #include &quot;JSModuleRecord.h&quot;
</span><span class="cx"> #include &quot;ModuleAnalyzer.h&quot;
</span><span class="cx"> #include &quot;Nodes.h&quot;
</span><span class="lines">@@ -52,6 +53,7 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeResolve(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeFetch(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeInstantiate(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeGetModuleNamespaceObject(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -85,6 +87,8 @@
</span><span class="cx">     loadAndEvaluateModule          JSBuiltin                                           DontEnum|Function 3
</span><span class="cx">     loadModule                     JSBuiltin                                           DontEnum|Function 3
</span><span class="cx">     linkAndEvaluateModule          JSBuiltin                                           DontEnum|Function 2
</span><ins>+    importModule                   JSBuiltin                                           DontEnum|Function 3
+    getModuleNamespaceObject       moduleLoaderPrototypeGetModuleNamespaceObject       DontEnum|Function 1
</ins><span class="cx">     parseModule                    moduleLoaderPrototypeParseModule                    DontEnum|Function 2
</span><span class="cx">     requestedModules               moduleLoaderPrototypeRequestedModules               DontEnum|Function 1
</span><span class="cx">     resolve                        moduleLoaderPrototypeResolve                        DontEnum|Function 2
</span><span class="lines">@@ -211,6 +215,19 @@
</span><span class="cx">     return JSValue::encode(loader-&gt;instantiate(exec, exec-&gt;argument(0), exec-&gt;argument(1), exec-&gt;argument(2)));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeGetModuleNamespaceObject(ExecState* exec)
+{
+    VM&amp; vm = exec-&gt;vm();
+    auto scope = DECLARE_THROW_SCOPE(vm);
+
+    auto* loader = jsDynamicCast&lt;JSModuleLoader*&gt;(exec-&gt;thisValue());
+    if (!loader)
+        return JSValue::encode(jsUndefined());
+    auto* moduleNamespaceObject = loader-&gt;getModuleNamespaceObject(exec, exec-&gt;argument(0));
+    RETURN_IF_EXCEPTION(scope, encodedJSValue());
+    return JSValue::encode(moduleNamespaceObject);
+}
+
</ins><span class="cx"> // ------------------- Additional Hook Functions ---------------------------
</span><span class="cx"> 
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL moduleLoaderPrototypeEvaluate(ExecState* exec)
</span></span></pre></div>
<a id="trunkSourceWebCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/ChangeLog (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/ChangeLog        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/WebCore/ChangeLog        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2017-01-09  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        [JSC] Prototype dynamic-import
+        https://bugs.webkit.org/show_bug.cgi?id=165724
+
+        Reviewed by Saam Barati.
+
+        We do not set a handler for import for now.
+        So dynamic import feature is only enabled in the JSC shell right now.
+
+        * bindings/js/JSDOMWindowBase.cpp:
+        * bindings/js/JSWorkerGlobalScopeBase.cpp:
+
</ins><span class="cx"> 2017-01-09  Youenn Fablet  &lt;youennf@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Merging ThreadableLoader redundant options on filtering responses
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSDOMWindowBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/WebCore/bindings/js/JSDOMWindowBase.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -64,6 +64,7 @@
</span><span class="cx">     &amp;javaScriptRuntimeFlags,
</span><span class="cx">     &amp;queueTaskToEventLoop,
</span><span class="cx">     &amp;shouldInterruptScriptBeforeTimeout,
</span><ins>+    nullptr,
</ins><span class="cx">     &amp;moduleLoaderResolve,
</span><span class="cx">     &amp;moduleLoaderFetch,
</span><span class="cx">     nullptr,
</span></span></pre></div>
<a id="trunkSourceWebCorebindingsjsJSWorkerGlobalScopeBasecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp (210521 => 210522)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp        2017-01-09 21:45:56 UTC (rev 210521)
+++ trunk/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp        2017-01-09 22:02:47 UTC (rev 210522)
</span><span class="lines">@@ -57,6 +57,7 @@
</span><span class="cx">     nullptr,
</span><span class="cx">     nullptr,
</span><span class="cx">     nullptr,
</span><ins>+    nullptr,
</ins><span class="cx">     &amp;defaultLanguage
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>