<!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>[211017] 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/211017">211017</a></dd>
<dt>Author</dt> <dd>utatane.tea@gmail.com</dd>
<dt>Date</dt> <dd>2017-01-21 14:10:54 -0800 (Sat, 21 Jan 2017)</dd>
</dl>

<h3>Log Message</h3>
<pre>dynamic import is ambiguous with import declaration at module code
https://bugs.webkit.org/show_bug.cgi?id=167098

Reviewed by Darin Adler.

JSTests:

* modules/import-call.js: Added.
(from.string_appeared_here.import.string_appeared_here.then):
* modules/import-call/main.js: Added.
* stress/import-syntax.js:
(async):

Source/JavaScriptCore:

This patch fixes two syntax issues related to dynamic import.

1. Fix member expression parsing with dynamic import results

We should not return import expression immediately after parsing
it in parseMemberExpression. This prohibits us to parse the following
code,

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

2. dynamic import with import declaration under the module context

Before this patch, we always attempt to parse IMPORT as import declaration
under the module context. It means that import call in the top level
expression statement fails to be parsed since the parser attempts to parse
it as import declaration.

    import(&quot;...&quot;)  // module top level statement.

In this patch, we check the condition `[lookahead != (]` before starting
parsing import declaration. This allows us to put import call in the module
top level statement.

* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parseModuleSourceElements):
(JSC::Parser&lt;LexerType&gt;::parseMemberExpression):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkJSTestsChangeLog">trunk/JSTests/ChangeLog</a></li>
<li><a href="#trunkJSTestsstressimportsyntaxjs">trunk/JSTests/stress/import-syntax.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li>trunk/JSTests/modules/import-call/</li>
<li><a href="#trunkJSTestsmodulesimportcallmainjs">trunk/JSTests/modules/import-call/main.js</a></li>
<li><a href="#trunkJSTestsmodulesimportcalljs">trunk/JSTests/modules/import-call.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkJSTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/ChangeLog (211016 => 211017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/ChangeLog        2017-01-21 20:46:29 UTC (rev 211016)
+++ trunk/JSTests/ChangeLog        2017-01-21 22:10:54 UTC (rev 211017)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2017-01-21  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        dynamic import is ambiguous with import declaration at module code
+        https://bugs.webkit.org/show_bug.cgi?id=167098
+
+        Reviewed by Darin Adler.
+
+        * modules/import-call.js: Added.
+        (from.string_appeared_here.import.string_appeared_here.then):
+        * modules/import-call/main.js: Added.
+        * stress/import-syntax.js:
+        (async):
+
</ins><span class="cx"> 2017-01-19  Skachkov Oleksandr  &lt;gskachkov@gmail.com&gt;
</span><span class="cx"> 
</span><span class="cx">         &quot;this&quot; missing after await in async arrow function
</span></span></pre></div>
<a id="trunkJSTestsmodulesimportcallmainjs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/modules/import-call/main.js (0 => 211017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/modules/import-call/main.js                                (rev 0)
+++ trunk/JSTests/modules/import-call/main.js        2017-01-21 22:10:54 UTC (rev 211017)
</span><span class="lines">@@ -0,0 +1 @@
</span><ins>+export let Cocoa = 42;
</ins></span></pre></div>
<a id="trunkJSTestsmodulesimportcalljs"></a>
<div class="addfile"><h4>Added: trunk/JSTests/modules/import-call.js (0 => 211017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/modules/import-call.js                                (rev 0)
+++ trunk/JSTests/modules/import-call.js        2017-01-21 22:10:54 UTC (rev 211017)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+import { shouldBe } from &quot;./resources/assert.js&quot;
+
+import(&quot;./import-call/main.js&quot;).then((result) =&gt; {
+    shouldBe(result.Cocoa, 42);
+});
</ins></span></pre></div>
<a id="trunkJSTestsstressimportsyntaxjs"></a>
<div class="modfile"><h4>Modified: trunk/JSTests/stress/import-syntax.js (211016 => 211017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/JSTests/stress/import-syntax.js        2017-01-21 20:46:29 UTC (rev 211016)
+++ trunk/JSTests/stress/import-syntax.js        2017-01-21 22:10:54 UTC (rev 211017)
</span><span class="lines">@@ -53,6 +53,11 @@
</span><span class="cx"> (async function () {
</span><span class="cx">     await testSyntax(`import(&quot;./import-tests/cocoa.js&quot;)`);
</span><span class="cx">     await testSyntax(`import(&quot;./import-tests/../import-tests/cocoa.js&quot;)`);
</span><ins>+    await testSyntax(`import(&quot;./import-tests/../import-tests/cocoa.js&quot;).then(() =&gt; { })`);
+    await testSyntax(`(import(&quot;./import-tests/../import-tests/cocoa.js&quot;).then(() =&gt; { }))`);
+    await testSyntax(`(import(&quot;./import-tests/../import-tests/cocoa.js&quot;))`);
+    await testSyntax(`import(&quot;./import-tests/../import-tests/cocoa.js&quot;).catch(() =&gt; { })`);
+    await testSyntax(`(import(&quot;./import-tests/../import-tests/cocoa.js&quot;).catch(() =&gt; { }))`);
</ins><span class="cx"> }()).catch((error) =&gt; {
</span><span class="cx">     print(String(error));
</span><span class="cx">     abort();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (211016 => 211017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2017-01-21 20:46:29 UTC (rev 211016)
+++ trunk/Source/JavaScriptCore/ChangeLog        2017-01-21 22:10:54 UTC (rev 211017)
</span><span class="lines">@@ -1,3 +1,38 @@
</span><ins>+2017-01-21  Yusuke Suzuki  &lt;utatane.tea@gmail.com&gt;
+
+        dynamic import is ambiguous with import declaration at module code
+        https://bugs.webkit.org/show_bug.cgi?id=167098
+
+        Reviewed by Darin Adler.
+
+        This patch fixes two syntax issues related to dynamic import.
+
+        1. Fix member expression parsing with dynamic import results
+
+        We should not return import expression immediately after parsing
+        it in parseMemberExpression. This prohibits us to parse the following
+        code,
+
+            import(&quot;...&quot;).then(function () {
+            });
+
+        2. dynamic import with import declaration under the module context
+
+        Before this patch, we always attempt to parse IMPORT as import declaration
+        under the module context. It means that import call in the top level
+        expression statement fails to be parsed since the parser attempts to parse
+        it as import declaration.
+
+            import(&quot;...&quot;)  // module top level statement.
+
+        In this patch, we check the condition `[lookahead != (]` before starting
+        parsing import declaration. This allows us to put import call in the module
+        top level statement.
+
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parseModuleSourceElements):
+        (JSC::Parser&lt;LexerType&gt;::parseMemberExpression):
+
</ins><span class="cx"> 2017-01-20  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Remove outdated ENABLE(CSP_NEXT) build flag
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (211016 => 211017)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-01-21 20:46:29 UTC (rev 211016)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2017-01-21 22:10:54 UTC (rev 211017)
</span><span class="lines">@@ -375,30 +375,48 @@
</span><span class="cx"> 
</span><span class="cx">     while (true) {
</span><span class="cx">         TreeStatement statement = 0;
</span><del>-        if (match(IMPORT)) {
-            statement = parseImportDeclaration(context);
-            if (statement)
-                recordPauseLocation(context.breakpointLocation(statement));
-        } else if (match(EXPORT)) {
</del><ins>+        switch (m_token.m_type) {
+        case EXPORT:
</ins><span class="cx">             statement = parseExportDeclaration(context);
</span><span class="cx">             if (statement)
</span><span class="cx">                 recordPauseLocation(context.breakpointLocation(statement));
</span><del>-        } else {
</del><ins>+            break;
+
+        case IMPORT: {
+            SavePoint savePoint = createSavePoint();
+            next();
+            bool isImportDeclaration = !match(OPENPAREN);
+            restoreSavePoint(savePoint);
+            if (isImportDeclaration) {
+                statement = parseImportDeclaration(context);
+                if (statement)
+                    recordPauseLocation(context.breakpointLocation(statement));
+                break;
+            }
+
+            // This is `import(&quot;...&quot;)` call case.
+            FALLTHROUGH;
+        }
+
+        default: {
</ins><span class="cx">             const Identifier* directive = 0;
</span><span class="cx">             unsigned directiveLiteralLength = 0;
</span><span class="cx">             if (parseMode == SourceParseMode::ModuleAnalyzeMode) {
</span><span class="cx">                 if (!parseStatementListItem(syntaxChecker, directive, &amp;directiveLiteralLength))
</span><del>-                    break;
</del><ins>+                    goto end;
</ins><span class="cx">                 continue;
</span><span class="cx">             }
</span><span class="cx">             statement = parseStatementListItem(context, directive, &amp;directiveLiteralLength);
</span><ins>+            break;
</ins><span class="cx">         }
</span><ins>+        }
</ins><span class="cx"> 
</span><span class="cx">         if (!statement)
</span><del>-            break;
</del><ins>+            goto end;
</ins><span class="cx">         context.appendStatement(sourceElements, statement);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+end:
</ins><span class="cx">     propagateError();
</span><span class="cx"> 
</span><span class="cx">     for (const auto&amp; pair : m_moduleScopeData-&gt;exportedBindings()) {
</span><span class="lines">@@ -4395,7 +4413,7 @@
</span><span class="cx">         TreeExpression expr = parseAssignmentExpression(context);
</span><span class="cx">         failIfFalse(expr, &quot;Cannot parse expression&quot;);
</span><span class="cx">         consumeOrFail(CLOSEPAREN, &quot;import call expects exactly one argument&quot;);
</span><del>-        return context.createImportExpr(location, expr, expressionStart, expressionEnd, lastTokenEndPosition());
</del><ins>+        base = 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>
</div>

</body>
</html>