<!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>[193226] branches/safari-601-branch</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/193226">193226</a></dd>
<dt>Author</dt> <dd>timothy@apple.com</dd>
<dt>Date</dt> <dd>2015-12-03 10:59:34 -0800 (Thu, 03 Dec 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Merge <a href="http://trac.webkit.org/projects/webkit/changeset/190110">r190110</a>. rdar://problem/23221163</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#branchessafari601branchLayoutTestsChangeLog">branches/safari-601-branch/LayoutTests/ChangeLog</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectormodelparsescriptsyntaxtreeexpectedtxt">branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt</a></li>
<li><a href="#branchessafari601branchLayoutTestsinspectormodelparsescriptsyntaxtreehtml">branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree.html</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIChangeLog">branches/safari-601-branch/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceExternalEsprimaLICENSE">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/LICENSE</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceExternalEsprimaesprimajs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/esprima.js</a></li>
<li><a href="#branchessafari601branchSourceWebInspectorUIUserInterfaceModelsScriptSyntaxTreejs">branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="branchessafari601branchLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/ChangeLog (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/LayoutTests/ChangeLog        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -1,5 +1,19 @@
</span><span class="cx"> 2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r190110. rdar://problem/23221163
+
+    2015-09-22  Saam barati  &lt;sbarati@apple.com&gt;
+
+            Web Inspector: update Esprima to latest version
+            https://bugs.webkit.org/show_bug.cgi?id=148960
+
+            Reviewed by Joseph Pecoraro.
+
+            * inspector/model/parse-script-syntax-tree-expected.txt:
+            * inspector/model/parse-script-syntax-tree.html:
+
+2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r189761. rdar://problem/23221163
</span><span class="cx"> 
</span><span class="cx">     2015-09-14  Brian Burg  &lt;bburg@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectormodelparsescriptsyntaxtreeexpectedtxt"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree-expected.txt        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -38,5 +38,7 @@
</span><span class="cx"> passed VariableDeclarator
</span><span class="cx"> passed WhileStatement
</span><span class="cx"> passed WithStatement
</span><ins>+passed ClassStatement, Super, MetaProperty
+passed AssignmentPattern
</ins><span class="cx"> passed ALL TESTS
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari601branchLayoutTestsinspectormodelparsescriptsyntaxtreehtml"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree.html (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree.html        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/LayoutTests/inspector/model/parse-script-syntax-tree.html        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -100,8 +100,7 @@
</span><span class="cx">     node = makeNode(&quot;try {} catch(e) {} &quot;, false);
</span><span class="cx">     InspectorTest.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.TryStatement);
</span><span class="cx">     InspectorTest.log(&quot;passed TryStatement&quot;);
</span><del>-    InspectorTest.assert(node.handlers.length === 1);
-    InspectorTest.assert(node.handlers[0].type === WebInspector.ScriptSyntaxTree.NodeType.CatchClause);
</del><ins>+    InspectorTest.assert(node.handler.type === WebInspector.ScriptSyntaxTree.NodeType.CatchClause);
</ins><span class="cx">     InspectorTest.log(&quot;passed CatchClause&quot;);
</span><span class="cx"> 
</span><span class="cx">     node = makeNode(&quot;foo ? bar : baz;&quot;, true);
</span><span class="lines">@@ -447,6 +446,36 @@
</span><span class="cx">     InspectorTest.assert(node.body.type === WebInspector.ScriptSyntaxTree.NodeType.BlockStatement);
</span><span class="cx">     InspectorTest.log(&quot;passed WithStatement&quot;);
</span><span class="cx"> 
</span><ins>+    node = makeNode(&quot;class C { constructor() { super(); new.target; } }&quot;, false);
+    InspectorTest.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.ClassDeclaration);
+    InspectorTest.assert(node.body.type === WebInspector.ScriptSyntaxTree.NodeType.ClassBody);
+    InspectorTest.assert(node.body.body[0].type === WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition);
+    InspectorTest.assert(node.body.body[0].value.type === WebInspector.ScriptSyntaxTree.NodeType.FunctionExpression);
+    InspectorTest.assert(node.body.body[0].value.body.type === WebInspector.ScriptSyntaxTree.NodeType.BlockStatement);
+    InspectorTest.assert(node.body.body[0].value.body.body.length === 2);
+    InspectorTest.assert(node.body.body[0].value.body.body[0].type === WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement);
+    InspectorTest.assert(node.body.body[0].value.body.body[0].expression.type === WebInspector.ScriptSyntaxTree.NodeType.CallExpression);
+    InspectorTest.assert(node.body.body[0].value.body.body[0].expression.callee.type === WebInspector.ScriptSyntaxTree.NodeType.Super);
+    InspectorTest.assert(node.body.body[0].value.body.body[1].type === WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement);
+    InspectorTest.assert(node.body.body[0].value.body.body[1].expression.type === WebInspector.ScriptSyntaxTree.NodeType.MetaProperty);
+    InspectorTest.assert(node.body.body[0].value.body.body[1].expression.meta === &quot;new&quot;);
+    InspectorTest.assert(node.body.body[0].value.body.body[1].expression.property === &quot;target&quot;);
+    InspectorTest.log(&quot;passed ClassStatement, Super, MetaProperty&quot;);
+
+    node = makeNode(&quot;let [x=20] = [];&quot;, false);
+    InspectorTest.assert(node.type === WebInspector.ScriptSyntaxTree.NodeType.VariableDeclaration);
+    InspectorTest.assert(node.kind === &quot;let&quot;);
+    InspectorTest.assert(node.declarations.length === 1);
+    InspectorTest.assert(node.declarations[0].type === WebInspector.ScriptSyntaxTree.NodeType.VariableDeclarator);
+    InspectorTest.assert(node.declarations[0].id.type === WebInspector.ScriptSyntaxTree.NodeType.ArrayPattern);
+    InspectorTest.assert(node.declarations[0].id.elements.length === 1);
+    InspectorTest.assert(node.declarations[0].id.elements[0].type === WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern);
+    InspectorTest.assert(node.declarations[0].id.elements[0].left.type === WebInspector.ScriptSyntaxTree.NodeType.Identifier);
+    InspectorTest.assert(node.declarations[0].id.elements[0].left.name === &quot;x&quot;);
+    InspectorTest.assert(node.declarations[0].id.elements[0].right.type === WebInspector.ScriptSyntaxTree.NodeType.Literal);
+    InspectorTest.assert(node.declarations[0].id.elements[0].right.value === 20);
+    InspectorTest.log(&quot;passed AssignmentPattern&quot;);
+
</ins><span class="cx">     InspectorTest.log(&quot;passed ALL TESTS&quot;);
</span><span class="cx">     InspectorTest.completeTest();
</span><span class="cx"> }
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/ChangeLog (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/ChangeLog        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/Source/WebInspectorUI/ChangeLog        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -1,5 +1,29 @@
</span><span class="cx"> 2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Merge r190110. rdar://problem/23221163
+
+    2015-09-22  Saam barati  &lt;sbarati@apple.com&gt;
+
+            Web Inspector: update Esprima to latest version
+            https://bugs.webkit.org/show_bug.cgi?id=148960
+
+            Reviewed by Joseph Pecoraro.
+
+            Esprima version 2.6 further supports ES6. We're
+            updating to it so we can support more ES6 features
+            in our script syntax tree.
+
+            * UserInterface/External/Esprima/LICENSE:
+            * UserInterface/External/Esprima/esprima.js:
+            * UserInterface/Models/ScriptSyntaxTree.js:
+            (WebInspector.ScriptSyntaxTree.prototype._gatherIdentifiersInDeclaration.gatherIdentifiers):
+            (WebInspector.ScriptSyntaxTree.prototype._gatherIdentifiersInDeclaration):
+            (WebInspector.ScriptSyntaxTree.prototype._recurse):
+            (WebInspector.ScriptSyntaxTree.prototype._createInternalSyntaxTree):
+            (WebInspector.ScriptSyntaxTree):
+
+2015-12-02  Timothy Hatcher  &lt;timothy@apple.com&gt;
+
</ins><span class="cx">         Merge r190058. rdar://problem/23221163
</span><span class="cx"> 
</span><span class="cx">     2015-09-21  Matt Baker  &lt;mattbaker@apple.com&gt;
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceExternalEsprimaLICENSE"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/LICENSE (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/LICENSE        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/LICENSE        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -1,22 +1,13 @@
</span><del>-Copyright (C) 2013 Ariya Hidayat &lt;ariya.hidayat@gmail.com&gt;
-Copyright (C) 2013 Thaddee Tyl &lt;thaddee.tyl@gmail.com&gt;
-Copyright (C) 2013 Mathias Bynens &lt;mathias@qiwi.be&gt;
-Copyright (C) 2012 Ariya Hidayat &lt;ariya.hidayat@gmail.com&gt;
-Copyright (C) 2012 Mathias Bynens &lt;mathias@qiwi.be&gt;
-Copyright (C) 2012 Joost-Wim Boekesteijn &lt;joost-wim@boekesteijn.nl&gt;
-Copyright (C) 2012 Kris Kowal &lt;kris.kowal@cixar.com&gt;
-Copyright (C) 2012 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
-Copyright (C) 2012 Arpad Borsos &lt;arpad.borsos@googlemail.com&gt;
-Copyright (C) 2011 Ariya Hidayat &lt;ariya.hidayat@gmail.com&gt;
</del><ins>+Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
</ins><span class="cx"> 
</span><span class="cx"> Redistribution and use in source and binary forms, with or without
</span><span class="cx"> modification, are permitted provided that the following conditions are met:
</span><span class="cx"> 
</span><del>-* Redistributions of source code must retain the above copyright
-  notice, this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright
-  notice, this list of conditions and the following disclaimer in the
-  documentation and/or other materials provided with the distribution.
</del><ins>+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
</ins><span class="cx"> 
</span><span class="cx"> THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS &quot;AS IS&quot;
</span><span class="cx"> AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceExternalEsprimaesprimajs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/esprima.js (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/esprima.js        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/External/Esprima/esprima.js        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -1,13 +1,5 @@
</span><span class="cx"> /*
</span><del>-  Copyright (C) 2013 Ariya Hidayat &lt;ariya.hidayat@gmail.com&gt;
-  Copyright (C) 2013 Thaddee Tyl &lt;thaddee.tyl@gmail.com&gt;
-  Copyright (C) 2012 Ariya Hidayat &lt;ariya.hidayat@gmail.com&gt;
-  Copyright (C) 2012 Mathias Bynens &lt;mathias@qiwi.be&gt;
-  Copyright (C) 2012 Joost-Wim Boekesteijn &lt;joost-wim@boekesteijn.nl&gt;
-  Copyright (C) 2012 Kris Kowal &lt;kris.kowal@cixar.com&gt;
-  Copyright (C) 2012 Yusuke Suzuki &lt;utatane.tea@gmail.com&gt;
-  Copyright (C) 2012 Arpad Borsos &lt;arpad.borsos@googlemail.com&gt;
-  Copyright (C) 2011 Ariya Hidayat &lt;ariya.hidayat@gmail.com&gt;
</del><ins>+  Copyright (c) jQuery Foundation, Inc. and Contributors, All Rights Reserved.
</ins><span class="cx"> 
</span><span class="cx">   Redistribution and use in source and binary forms, with or without
</span><span class="cx">   modification, are permitted provided that the following conditions are met:
</span><span class="lines">@@ -51,21 +43,29 @@
</span><span class="cx">         TokenName,
</span><span class="cx">         FnExprTokens,
</span><span class="cx">         Syntax,
</span><del>-        PropertyKind,
</del><ins>+        PlaceHolders,
</ins><span class="cx">         Messages,
</span><span class="cx">         Regex,
</span><del>-        SyntaxTreeDelegate,
-        ClassPropertyType,
</del><span class="cx">         source,
</span><span class="cx">         strict,
</span><span class="cx">         index,
</span><span class="cx">         lineNumber,
</span><span class="cx">         lineStart,
</span><ins>+        hasLineTerminator,
+        lastIndex,
+        lastLineNumber,
+        lastLineStart,
+        startIndex,
+        startLineNumber,
+        startLineStart,
+        scanning,
</ins><span class="cx">         length,
</span><del>-        delegate,
</del><span class="cx">         lookahead,
</span><span class="cx">         state,
</span><del>-        extra;
</del><ins>+        extra,
+        isBindingElement,
+        isAssignmentTarget,
+        firstCoverInitializedNameError;
</ins><span class="cx"> 
</span><span class="cx">     Token = {
</span><span class="cx">         BooleanLiteral: 1,
</span><span class="lines">@@ -90,6 +90,7 @@
</span><span class="cx">     TokenName[Token.Punctuator] = 'Punctuator';
</span><span class="cx">     TokenName[Token.StringLiteral] = 'String';
</span><span class="cx">     TokenName[Token.RegularExpression] = 'RegularExpression';
</span><ins>+    TokenName[Token.Template] = 'Template';
</ins><span class="cx"> 
</span><span class="cx">     // A function following one of those tokens is an expression.
</span><span class="cx">     FnExprTokens = ['(', '{', '[', 'in', 'typeof', 'instanceof', 'new',
</span><span class="lines">@@ -103,32 +104,32 @@
</span><span class="cx">                     '&lt;=', '&lt;', '&gt;', '!=', '!=='];
</span><span class="cx"> 
</span><span class="cx">     Syntax = {
</span><ins>+        AssignmentExpression: 'AssignmentExpression',
+        AssignmentPattern: 'AssignmentPattern',
</ins><span class="cx">         ArrayExpression: 'ArrayExpression',
</span><span class="cx">         ArrayPattern: 'ArrayPattern',
</span><span class="cx">         ArrowFunctionExpression: 'ArrowFunctionExpression',
</span><del>-        AssignmentExpression: 'AssignmentExpression',
</del><ins>+        BlockStatement: 'BlockStatement',
</ins><span class="cx">         BinaryExpression: 'BinaryExpression',
</span><del>-        BlockStatement: 'BlockStatement',
</del><span class="cx">         BreakStatement: 'BreakStatement',
</span><span class="cx">         CallExpression: 'CallExpression',
</span><span class="cx">         CatchClause: 'CatchClause',
</span><span class="cx">         ClassBody: 'ClassBody',
</span><span class="cx">         ClassDeclaration: 'ClassDeclaration',
</span><span class="cx">         ClassExpression: 'ClassExpression',
</span><del>-        ComprehensionBlock: 'ComprehensionBlock',
-        ComprehensionExpression: 'ComprehensionExpression',
</del><span class="cx">         ConditionalExpression: 'ConditionalExpression',
</span><span class="cx">         ContinueStatement: 'ContinueStatement',
</span><ins>+        DoWhileStatement: 'DoWhileStatement',
</ins><span class="cx">         DebuggerStatement: 'DebuggerStatement',
</span><del>-        DoWhileStatement: 'DoWhileStatement',
</del><span class="cx">         EmptyStatement: 'EmptyStatement',
</span><del>-        ExportDeclaration: 'ExportDeclaration',
-        ExportBatchSpecifier: 'ExportBatchSpecifier',
</del><ins>+        ExportAllDeclaration: 'ExportAllDeclaration',
+        ExportDefaultDeclaration: 'ExportDefaultDeclaration',
+        ExportNamedDeclaration: 'ExportNamedDeclaration',
</ins><span class="cx">         ExportSpecifier: 'ExportSpecifier',
</span><span class="cx">         ExpressionStatement: 'ExpressionStatement',
</span><ins>+        ForStatement: 'ForStatement',
+        ForOfStatement: 'ForOfStatement',
</ins><span class="cx">         ForInStatement: 'ForInStatement',
</span><del>-        ForOfStatement: 'ForOfStatement',
-        ForStatement: 'ForStatement',
</del><span class="cx">         FunctionDeclaration: 'FunctionDeclaration',
</span><span class="cx">         FunctionExpression: 'FunctionExpression',
</span><span class="cx">         Identifier: 'Identifier',
</span><span class="lines">@@ -137,20 +138,22 @@
</span><span class="cx">         ImportDefaultSpecifier: 'ImportDefaultSpecifier',
</span><span class="cx">         ImportNamespaceSpecifier: 'ImportNamespaceSpecifier',
</span><span class="cx">         ImportSpecifier: 'ImportSpecifier',
</span><ins>+        Literal: 'Literal',
</ins><span class="cx">         LabeledStatement: 'LabeledStatement',
</span><del>-        Literal: 'Literal',
</del><span class="cx">         LogicalExpression: 'LogicalExpression',
</span><span class="cx">         MemberExpression: 'MemberExpression',
</span><ins>+        MetaProperty: 'MetaProperty',
</ins><span class="cx">         MethodDefinition: 'MethodDefinition',
</span><del>-        ModuleSpecifier: 'ModuleSpecifier',
</del><span class="cx">         NewExpression: 'NewExpression',
</span><span class="cx">         ObjectExpression: 'ObjectExpression',
</span><span class="cx">         ObjectPattern: 'ObjectPattern',
</span><span class="cx">         Program: 'Program',
</span><span class="cx">         Property: 'Property',
</span><ins>+        RestElement: 'RestElement',
</ins><span class="cx">         ReturnStatement: 'ReturnStatement',
</span><span class="cx">         SequenceExpression: 'SequenceExpression',
</span><span class="cx">         SpreadElement: 'SpreadElement',
</span><ins>+        Super: 'Super',
</ins><span class="cx">         SwitchCase: 'SwitchCase',
</span><span class="cx">         SwitchStatement: 'SwitchStatement',
</span><span class="cx">         TaggedTemplateExpression: 'TaggedTemplateExpression',
</span><span class="lines">@@ -168,17 +171,10 @@
</span><span class="cx">         YieldExpression: 'YieldExpression'
</span><span class="cx">     };
</span><span class="cx"> 
</span><del>-    PropertyKind = {
-        Data: 1,
-        Get: 2,
-        Set: 4
</del><ins>+    PlaceHolders = {
+        ArrowParameterPlaceHolder: 'ArrowParameterPlaceHolder'
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-    ClassPropertyType = {
-        'static': 'static',
-        prototype: 'prototype'
-    };
-
</del><span class="cx">     // Error messages should be identical to V8.
</span><span class="cx">     Messages = {
</span><span class="cx">         UnexpectedToken: 'Unexpected token %0',
</span><span class="lines">@@ -192,54 +188,50 @@
</span><span class="cx">         InvalidRegExp: 'Invalid regular expression',
</span><span class="cx">         UnterminatedRegExp: 'Invalid regular expression: missing /',
</span><span class="cx">         InvalidLHSInAssignment: 'Invalid left-hand side in assignment',
</span><del>-        InvalidLHSInFormalsList: 'Invalid left-hand side in formals list',
</del><span class="cx">         InvalidLHSInForIn: 'Invalid left-hand side in for-in',
</span><ins>+        InvalidLHSInForLoop: 'Invalid left-hand side in for-loop',
</ins><span class="cx">         MultipleDefaultsInSwitch: 'More than one default clause in switch statement',
</span><span class="cx">         NoCatchOrFinally: 'Missing catch or finally after try',
</span><span class="cx">         UnknownLabel: 'Undefined label \'%0\'',
</span><span class="cx">         Redeclaration: '%0 \'%1\' has already been declared',
</span><span class="cx">         IllegalContinue: 'Illegal continue statement',
</span><span class="cx">         IllegalBreak: 'Illegal break statement',
</span><del>-        IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition',
-        IllegalClassConstructorProperty: 'Illegal constructor property in class definition',
</del><span class="cx">         IllegalReturn: 'Illegal return statement',
</span><del>-        IllegalYield: 'Illegal yield expression',
-        IllegalSpread: 'Illegal spread element',
</del><span class="cx">         StrictModeWith: 'Strict mode code may not include a with statement',
</span><span class="cx">         StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode',
</span><span class="cx">         StrictVarName: 'Variable name may not be eval or arguments in strict mode',
</span><span class="cx">         StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode',
</span><span class="cx">         StrictParamDupe: 'Strict mode function may not have duplicate parameter names',
</span><del>-        ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list',
-        DefaultRestParameter: 'Rest parameter can not have a default value',
-        ElementAfterSpreadElement: 'Spread must be the final element of an element list',
-        ObjectPatternAsRestParameter: 'Invalid rest parameter',
-        ObjectPatternAsSpread: 'Invalid spread argument',
</del><span class="cx">         StrictFunctionName: 'Function name may not be eval or arguments in strict mode',
</span><span class="cx">         StrictOctalLiteral: 'Octal literals are not allowed in strict mode.',
</span><span class="cx">         StrictDelete: 'Delete of an unqualified identifier in strict mode.',
</span><del>-        StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode',
-        AccessorDataProperty: 'Object literal may not have data and accessor property with the same name',
-        AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name',
</del><span class="cx">         StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode',
</span><span class="cx">         StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode',
</span><span class="cx">         StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode',
</span><span class="cx">         StrictReservedWord: 'Use of future reserved word in strict mode',
</span><del>-        MissingFromClause: 'Missing from clause',
-        NoAsAfterImportNamespace: 'Missing as after import *',
-        InvalidModuleSpecifier: 'Invalid module specifier',
-        IllegalImportDeclaration: 'Illegal import declaration',
-        IllegalExportDeclaration: 'Illegal export declaration',
-        NoUnintializedConst: 'Const must be initialized',
-        ComprehensionRequiresBlock: 'Comprehension must have at least one block',
-        ComprehensionError: 'Comprehension Error',
-        EachNotAllowed: 'Each is not supported'
</del><ins>+        TemplateOctalLiteral: 'Octal literals are not allowed in template strings.',
+        ParameterAfterRestParameter: 'Rest parameter must be last formal parameter',
+        DefaultRestParameter: 'Unexpected token =',
+        ObjectPatternAsRestParameter: 'Unexpected token {',
+        DuplicateProtoProperty: 'Duplicate __proto__ fields are not allowed in object literals',
+        ConstructorSpecialMethod: 'Class constructor may not be an accessor',
+        DuplicateConstructor: 'A class may only have one constructor',
+        StaticPrototype: 'Classes may not have static property named prototype',
+        MissingFromClause: 'Unexpected token',
+        NoAsAfterImportNamespace: 'Unexpected token',
+        InvalidModuleSpecifier: 'Unexpected token',
+        IllegalImportDeclaration: 'Unexpected token',
+        IllegalExportDeclaration: 'Unexpected token',
+        DuplicateBinding: 'Duplicate binding %0'
</ins><span class="cx">     };
</span><span class="cx"> 
</span><del>-    // See also tools/generate-unicode-regex.py.
</del><ins>+    // See also tools/generate-unicode-regex.js.
</ins><span class="cx">     Regex = {
</span><del>-        NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32
 \u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u1
 2b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u
 2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa
 6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'),
-        NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a9
 3-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-
 \u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b
 0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u300
 5-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f
 \ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]')
</del><ins>+        // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierStart:
+        NonAsciiIdentifierStart: /[\xAA\xB5\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0-\u08B2\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5
 D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-
 \u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191E\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\
 u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303C\u3041-\u3096\u309B-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA69D\uA6A0-\uA6EF\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uA9E0-\uA9E4\uA9E6-\uA9EF\uA9FA-\uA9FE\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA7E-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF
 900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDE80-\uDE9C\uDEA0-\uDED0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF75\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00\uDE10-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE4\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC03-\uDC37\uDC83-\uDCAF\uDCD0-\uDCE
 8\uDD03-\uDD26\uDD50-\uDD72\uDD76\uDD83-\uDDB2\uDDC1-\uDDC4\uDDDA\uDE00-\uDE11\uDE13-\uDE2B\uDEB0-\uDEDE\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3D\uDF5D-\uDF61]|\uD805[\uDC80-\uDCAF\uDCC4\uDCC5\uDCC7\uDD80-\uDDAE\uDE00-\uDE2F\uDE44\uDE80-\uDEAA]|\uD806[\uDCA0-\uDCDF\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDED0-\uDEED\uDF00-\uDF2F\uDF40-\uDF43\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50\uDF93-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07-\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\
 uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB]|\uD83A[\uDC00-\uDCC4]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]/,
+
+        // ECMAScript 6/Unicode v7.0.0 NonAsciiIdentifierPart:
+        NonAsciiIdentifierPart: /[\xAA\xB5\xB7\xBA\xC0-\xD6\xD8-\xF6\xF8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0300-\u0374\u0376\u0377\u037A-\u037D\u037F\u0386-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u0483-\u0487\u048A-\u052F\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05BD\u05BF\u05C1\u05C2\u05C4\u05C5\u05C7\u05D0-\u05EA\u05F0-\u05F2\u0610-\u061A\u0620-\u0669\u066E-\u06D3\u06D5-\u06DC\u06DF-\u06E8\u06EA-\u06FC\u06FF\u0710-\u074A\u074D-\u07B1\u07C0-\u07F5\u07FA\u0800-\u082D\u0840-\u085B\u08A0-\u08B2\u08E4-\u0963\u0966-\u096F\u0971-\u0983\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BC-\u09C4\u09C7\u09C8\u09CB-\u09CE\u09D7\u09DC\u09DD\u09DF-\u09E3\u09E6-\u09F1\u0A01-\u0A03\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A3C\u0A3E-\u0A42\u0A47\u0A48\u0A4B-\u0A4D\u0A51\u0A59-\u0A5C\u0A5E\u0A66-\u0A75\u0A81-\u0A83\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABC
 -\u0AC5\u0AC7-\u0AC9\u0ACB-\u0ACD\u0AD0\u0AE0-\u0AE3\u0AE6-\u0AEF\u0B01-\u0B03\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3C-\u0B44\u0B47\u0B48\u0B4B-\u0B4D\u0B56\u0B57\u0B5C\u0B5D\u0B5F-\u0B63\u0B66-\u0B6F\u0B71\u0B82\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BBE-\u0BC2\u0BC6-\u0BC8\u0BCA-\u0BCD\u0BD0\u0BD7\u0BE6-\u0BEF\u0C00-\u0C03\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C39\u0C3D-\u0C44\u0C46-\u0C48\u0C4A-\u0C4D\u0C55\u0C56\u0C58\u0C59\u0C60-\u0C63\u0C66-\u0C6F\u0C81-\u0C83\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBC-\u0CC4\u0CC6-\u0CC8\u0CCA-\u0CCD\u0CD5\u0CD6\u0CDE\u0CE0-\u0CE3\u0CE6-\u0CEF\u0CF1\u0CF2\u0D01-\u0D03\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D-\u0D44\u0D46-\u0D48\u0D4A-\u0D4E\u0D57\u0D60-\u0D63\u0D66-\u0D6F\u0D7A-\u0D7F\u0D82\u0D83\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0DCA\u0DCF-\u0DD4\u0DD6
 \u0DD8-\u0DDF\u0DE6-\u0DEF\u0DF2\u0DF3\u0E01-\u0E3A\u0E40-\u0E4E\u0E50-\u0E59\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB9\u0EBB-\u0EBD\u0EC0-\u0EC4\u0EC6\u0EC8-\u0ECD\u0ED0-\u0ED9\u0EDC-\u0EDF\u0F00\u0F18\u0F19\u0F20-\u0F29\u0F35\u0F37\u0F39\u0F3E-\u0F47\u0F49-\u0F6C\u0F71-\u0F84\u0F86-\u0F97\u0F99-\u0FBC\u0FC6\u1000-\u1049\u1050-\u109D\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u135D-\u135F\u1369-\u1371\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u16EE-\u16F8\u1700-\u170C\u170E-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176C\u176E-\u1770\u1772\u1773\u1780-\u17D3\u17D7\u17DC\u17DD\u17E0-\u17E9\u180B-\u180D\u1810-\u1819\u1820-\u1877\u1880-\u18AA\u18B0-\u18F5\u1900-\u191E\u1920-\u192B\u1
 930-\u193B\u1946-\u196D\u1970-\u1974\u1980-\u19AB\u19B0-\u19C9\u19D0-\u19DA\u1A00-\u1A1B\u1A20-\u1A5E\u1A60-\u1A7C\u1A7F-\u1A89\u1A90-\u1A99\u1AA7\u1AB0-\u1ABD\u1B00-\u1B4B\u1B50-\u1B59\u1B6B-\u1B73\u1B80-\u1BF3\u1C00-\u1C37\u1C40-\u1C49\u1C4D-\u1C7D\u1CD0-\u1CD2\u1CD4-\u1CF6\u1CF8\u1CF9\u1D00-\u1DF5\u1DFC-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u200C\u200D\u203F\u2040\u2054\u2071\u207F\u2090-\u209C\u20D0-\u20DC\u20E1\u20E5-\u20F0\u2102\u2107\u210A-\u2113\u2115\u2118-\u211D\u2124\u2126\u2128\u212A-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2160-\u2188\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D7F-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2DE0-\u2DFF\u3005-\u3007\u3021-\u302F\u3031-\u3
 035\u3038-\u303C\u3041-\u3096\u3099-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA62B\uA640-\uA66F\uA674-\uA67D\uA67F-\uA69D\uA69F-\uA6F1\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA7AD\uA7B0\uA7B1\uA7F7-\uA827\uA840-\uA873\uA880-\uA8C4\uA8D0-\uA8D9\uA8E0-\uA8F7\uA8FB\uA900-\uA92D\uA930-\uA953\uA960-\uA97C\uA980-\uA9C0\uA9CF-\uA9D9\uA9E0-\uA9FE\uAA00-\uAA36\uAA40-\uAA4D\uAA50-\uAA59\uAA60-\uAA76\uAA7A-\uAAC2\uAADB-\uAADD\uAAE0-\uAAEF\uAAF2-\uAAF6\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uAB30-\uAB5A\uAB5C-\uAB5F\uAB64\uAB65\uABC0-\uABEA\uABEC\uABED\uABF0-\uABF9\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE00-\uFE0F\uFE20-\uFE2D\uFE33\uFE34\uFE4D-\uFE4F\uFE7
 0-\uFE74\uFE76-\uFEFC\uFF10-\uFF19\uFF21-\uFF3A\uFF3F\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC]|\uD800[\uDC00-\uDC0B\uDC0D-\uDC26\uDC28-\uDC3A\uDC3C\uDC3D\uDC3F-\uDC4D\uDC50-\uDC5D\uDC80-\uDCFA\uDD40-\uDD74\uDDFD\uDE80-\uDE9C\uDEA0-\uDED0\uDEE0\uDF00-\uDF1F\uDF30-\uDF4A\uDF50-\uDF7A\uDF80-\uDF9D\uDFA0-\uDFC3\uDFC8-\uDFCF\uDFD1-\uDFD5]|\uD801[\uDC00-\uDC9D\uDCA0-\uDCA9\uDD00-\uDD27\uDD30-\uDD63\uDE00-\uDF36\uDF40-\uDF55\uDF60-\uDF67]|\uD802[\uDC00-\uDC05\uDC08\uDC0A-\uDC35\uDC37\uDC38\uDC3C\uDC3F-\uDC55\uDC60-\uDC76\uDC80-\uDC9E\uDD00-\uDD15\uDD20-\uDD39\uDD80-\uDDB7\uDDBE\uDDBF\uDE00-\uDE03\uDE05\uDE06\uDE0C-\uDE13\uDE15-\uDE17\uDE19-\uDE33\uDE38-\uDE3A\uDE3F\uDE60-\uDE7C\uDE80-\uDE9C\uDEC0-\uDEC7\uDEC9-\uDEE6\uDF00-\uDF35\uDF40-\uDF55\uDF60-\uDF72\uDF80-\uDF91]|\uD803[\uDC00-\uDC48]|\uD804[\uDC00-\uDC46\uDC66-\uDC6F\uDC7F-\uDCBA\uDCD0-\uDCE8\uDCF0-\uDCF9\uDD00-\uDD34\uDD36-\uDD3F\uDD50-\uDD73\uDD76\uDD80-\uDDC4\uDDD0-\uDDDA\uDE00-\uDE11\
 uDE13-\uDE37\uDEB0-\uDEEA\uDEF0-\uDEF9\uDF01-\uDF03\uDF05-\uDF0C\uDF0F\uDF10\uDF13-\uDF28\uDF2A-\uDF30\uDF32\uDF33\uDF35-\uDF39\uDF3C-\uDF44\uDF47\uDF48\uDF4B-\uDF4D\uDF57\uDF5D-\uDF63\uDF66-\uDF6C\uDF70-\uDF74]|\uD805[\uDC80-\uDCC5\uDCC7\uDCD0-\uDCD9\uDD80-\uDDB5\uDDB8-\uDDC0\uDE00-\uDE40\uDE44\uDE50-\uDE59\uDE80-\uDEB7\uDEC0-\uDEC9]|\uD806[\uDCA0-\uDCE9\uDCFF\uDEC0-\uDEF8]|\uD808[\uDC00-\uDF98]|\uD809[\uDC00-\uDC6E]|[\uD80C\uD840-\uD868\uD86A-\uD86C][\uDC00-\uDFFF]|\uD80D[\uDC00-\uDC2E]|\uD81A[\uDC00-\uDE38\uDE40-\uDE5E\uDE60-\uDE69\uDED0-\uDEED\uDEF0-\uDEF4\uDF00-\uDF36\uDF40-\uDF43\uDF50-\uDF59\uDF63-\uDF77\uDF7D-\uDF8F]|\uD81B[\uDF00-\uDF44\uDF50-\uDF7E\uDF8F-\uDF9F]|\uD82C[\uDC00\uDC01]|\uD82F[\uDC00-\uDC6A\uDC70-\uDC7C\uDC80-\uDC88\uDC90-\uDC99\uDC9D\uDC9E]|\uD834[\uDD65-\uDD69\uDD6D-\uDD72\uDD7B-\uDD82\uDD85-\uDD8B\uDDAA-\uDDAD\uDE42-\uDE44]|\uD835[\uDC00-\uDC54\uDC56-\uDC9C\uDC9E\uDC9F\uDCA2\uDCA5\uDCA6\uDCA9-\uDCAC\uDCAE-\uDCB9\uDCBB\uDCBD-\uDCC3\uDCC5-\uDD05\uDD07
 -\uDD0A\uDD0D-\uDD14\uDD16-\uDD1C\uDD1E-\uDD39\uDD3B-\uDD3E\uDD40-\uDD44\uDD46\uDD4A-\uDD50\uDD52-\uDEA5\uDEA8-\uDEC0\uDEC2-\uDEDA\uDEDC-\uDEFA\uDEFC-\uDF14\uDF16-\uDF34\uDF36-\uDF4E\uDF50-\uDF6E\uDF70-\uDF88\uDF8A-\uDFA8\uDFAA-\uDFC2\uDFC4-\uDFCB\uDFCE-\uDFFF]|\uD83A[\uDC00-\uDCC4\uDCD0-\uDCD6]|\uD83B[\uDE00-\uDE03\uDE05-\uDE1F\uDE21\uDE22\uDE24\uDE27\uDE29-\uDE32\uDE34-\uDE37\uDE39\uDE3B\uDE42\uDE47\uDE49\uDE4B\uDE4D-\uDE4F\uDE51\uDE52\uDE54\uDE57\uDE59\uDE5B\uDE5D\uDE5F\uDE61\uDE62\uDE64\uDE67-\uDE6A\uDE6C-\uDE72\uDE74-\uDE77\uDE79-\uDE7C\uDE7E\uDE80-\uDE89\uDE8B-\uDE9B\uDEA1-\uDEA3\uDEA5-\uDEA9\uDEAB-\uDEBB]|\uD869[\uDC00-\uDED6\uDF00-\uDFFF]|\uD86D[\uDC00-\uDF34\uDF40-\uDFFF]|\uD86E[\uDC00-\uDC1D]|\uD87E[\uDC00-\uDE1D]|\uDB40[\uDD00-\uDDEF]/
</ins><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     // Ensure the condition is true, otherwise throw an error.
</span><span class="lines">@@ -254,33 +246,8 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function StringMap() {
-        this.$data = {};
-    }
-
-    StringMap.prototype.get = function (key) {
-        key = '$' + key;
-        return this.$data[key];
-    };
-
-    StringMap.prototype.set = function (key, value) {
-        key = '$' + key;
-        this.$data[key] = value;
-        return this;
-    };
-
-    StringMap.prototype.has = function (key) {
-        key = '$' + key;
-        return Object.prototype.hasOwnProperty.call(this.$data, key);
-    };
-
-    StringMap.prototype.delete = function (key) {
-        key = '$' + key;
-        return delete this.$data[key];
-    };
-
</del><span class="cx">     function isDecimalDigit(ch) {
</span><del>-        return (ch &gt;= 48 &amp;&amp; ch &lt;= 57);   // 0..9
</del><ins>+        return (ch &gt;= 0x30 &amp;&amp; ch &lt;= 0x39);   // 0..9
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function isHexDigit(ch) {
</span><span class="lines">@@ -291,51 +258,73 @@
</span><span class="cx">         return '01234567'.indexOf(ch) &gt;= 0;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function octalToDecimal(ch) {
+        // \0 is not octal escape sequence
+        var octal = (ch !== '0'), code = '01234567'.indexOf(ch);
</ins><span class="cx"> 
</span><del>-    // 7.2 White Space
</del><ins>+        if (index &lt; length &amp;&amp; isOctalDigit(source[index])) {
+            octal = true;
+            code = code * 8 + '01234567'.indexOf(source[index++]);
</ins><span class="cx"> 
</span><ins>+            // 3 digits are only allowed when string starts
+            // with 0, 1, 2, 3
+            if ('0123'.indexOf(ch) &gt;= 0 &amp;&amp;
+                    index &lt; length &amp;&amp;
+                    isOctalDigit(source[index])) {
+                code = code * 8 + '01234567'.indexOf(source[index++]);
+            }
+        }
+
+        return {
+            code: code,
+            octal: octal
+        };
+    }
+
+    // ECMA-262 11.2 White Space
+
</ins><span class="cx">     function isWhiteSpace(ch) {
</span><del>-        return (ch === 32) ||  // space
-            (ch === 9) ||      // tab
-            (ch === 0xB) ||
-            (ch === 0xC) ||
-            (ch === 0xA0) ||
-            (ch &gt;= 0x1680 &amp;&amp; '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) &gt; 0);
</del><ins>+        return (ch === 0x20) || (ch === 0x09) || (ch === 0x0B) || (ch === 0x0C) || (ch === 0xA0) ||
+            (ch &gt;= 0x1680 &amp;&amp; [0x1680, 0x180E, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202F, 0x205F, 0x3000, 0xFEFF].indexOf(ch) &gt;= 0);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.3 Line Terminators
</del><ins>+    // ECMA-262 11.3 Line Terminators
</ins><span class="cx"> 
</span><span class="cx">     function isLineTerminator(ch) {
</span><del>-        return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029);
</del><ins>+        return (ch === 0x0A) || (ch === 0x0D) || (ch === 0x2028) || (ch === 0x2029);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.6 Identifier Names and Identifiers
</del><ins>+    // ECMA-262 11.6 Identifier Names and Identifiers
</ins><span class="cx"> 
</span><ins>+    function fromCodePoint(cp) {
+        return (cp &lt; 0x10000) ? String.fromCharCode(cp) :
+            String.fromCharCode(0xD800 + ((cp - 0x10000) &gt;&gt; 10)) +
+            String.fromCharCode(0xDC00 + ((cp - 0x10000) &amp; 1023));
+    }
+
</ins><span class="cx">     function isIdentifierStart(ch) {
</span><del>-        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
-            (ch &gt;= 65 &amp;&amp; ch &lt;= 90) ||         // A..Z
-            (ch &gt;= 97 &amp;&amp; ch &lt;= 122) ||        // a..z
-            (ch === 92) ||                    // \ (backslash)
-            ((ch &gt;= 0x80) &amp;&amp; Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch)));
</del><ins>+        return (ch === 0x24) || (ch === 0x5F) ||  // $ (dollar) and _ (underscore)
+            (ch &gt;= 0x41 &amp;&amp; ch &lt;= 0x5A) ||         // A..Z
+            (ch &gt;= 0x61 &amp;&amp; ch &lt;= 0x7A) ||         // a..z
+            (ch === 0x5C) ||                      // \ (backslash)
+            ((ch &gt;= 0x80) &amp;&amp; Regex.NonAsciiIdentifierStart.test(fromCodePoint(ch)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function isIdentifierPart(ch) {
</span><del>-        return (ch === 36) || (ch === 95) ||  // $ (dollar) and _ (underscore)
-            (ch &gt;= 65 &amp;&amp; ch &lt;= 90) ||         // A..Z
-            (ch &gt;= 97 &amp;&amp; ch &lt;= 122) ||        // a..z
-            (ch &gt;= 48 &amp;&amp; ch &lt;= 57) ||         // 0..9
-            (ch === 92) ||                    // \ (backslash)
-            ((ch &gt;= 0x80) &amp;&amp; Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch)));
</del><ins>+        return (ch === 0x24) || (ch === 0x5F) ||  // $ (dollar) and _ (underscore)
+            (ch &gt;= 0x41 &amp;&amp; ch &lt;= 0x5A) ||         // A..Z
+            (ch &gt;= 0x61 &amp;&amp; ch &lt;= 0x7A) ||         // a..z
+            (ch &gt;= 0x30 &amp;&amp; ch &lt;= 0x39) ||         // 0..9
+            (ch === 0x5C) ||                      // \ (backslash)
+            ((ch &gt;= 0x80) &amp;&amp; Regex.NonAsciiIdentifierPart.test(fromCodePoint(ch)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.6.1.2 Future Reserved Words
</del><ins>+    // ECMA-262 11.6.2.2 Future Reserved Words
</ins><span class="cx"> 
</span><span class="cx">     function isFutureReservedWord(id) {
</span><span class="cx">         switch (id) {
</span><del>-        case 'class':
</del><span class="cx">         case 'enum':
</span><span class="cx">         case 'export':
</span><del>-        case 'extends':
</del><span class="cx">         case 'import':
</span><span class="cx">         case 'super':
</span><span class="cx">             return true;
</span><span class="lines">@@ -365,16 +354,12 @@
</span><span class="cx">         return id === 'eval' || id === 'arguments';
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.6.1.1 Keywords
</del><ins>+    // ECMA-262 11.6.2.1 Keywords
</ins><span class="cx"> 
</span><span class="cx">     function isKeyword(id) {
</span><del>-        if (strict &amp;&amp; isStrictModeReservedWord(id)) {
-            return true;
-        }
</del><span class="cx"> 
</span><span class="cx">         // 'const' is specialized as Keyword in V8.
</span><del>-        // 'yield' is only treated as a keyword in strict mode.
-        // 'let' is for compatiblity with SpiderMonkey and ES.next.
</del><ins>+        // 'yield' and 'let' are for compatibility with SpiderMonkey and ES.next.
</ins><span class="cx">         // Some others are from future reserved words.
</span><span class="cx"> 
</span><span class="cx">         switch (id.length) {
</span><span class="lines">@@ -388,7 +373,7 @@
</span><span class="cx">                 (id === 'void') || (id === 'with') || (id === 'enum');
</span><span class="cx">         case 5:
</span><span class="cx">             return (id === 'while') || (id === 'break') || (id === 'catch') ||
</span><del>-                (id === 'throw') || (id === 'const') ||
</del><ins>+                (id === 'throw') || (id === 'const') || (id === 'yield') ||
</ins><span class="cx">                 (id === 'class') || (id === 'super');
</span><span class="cx">         case 6:
</span><span class="cx">             return (id === 'return') || (id === 'typeof') || (id === 'delete') ||
</span><span class="lines">@@ -404,19 +389,13 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.4 Comments
</del><ins>+    // ECMA-262 11.4 Comments
</ins><span class="cx"> 
</span><span class="cx">     function addComment(type, value, start, end, loc) {
</span><span class="cx">         var comment;
</span><ins>+
</ins><span class="cx">         assert(typeof start === 'number', 'Comment must have valid position');
</span><span class="cx"> 
</span><del>-        // Because the way the actual token is scanned, often the comments
-        // (if any) are skipped twice during the lexical analysis.
-        // Thus, we need to skip adding a comment if the comment array already
-        // handled it.
-        if (state.lastCommentStart &gt;= start) {
-            return;
-        }
</del><span class="cx">         state.lastCommentStart = start;
</span><span class="cx"> 
</span><span class="cx">         comment = {
</span><span class="lines">@@ -436,14 +415,14 @@
</span><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function skipSingleLineComment() {
</del><ins>+    function skipSingleLineComment(offset) {
</ins><span class="cx">         var start, loc, ch, comment;
</span><span class="cx"> 
</span><del>-        start = index - 2;
</del><ins>+        start = index - offset;
</ins><span class="cx">         loc = {
</span><span class="cx">             start: {
</span><span class="cx">                 line: lineNumber,
</span><del>-                column: index - lineStart - 2
</del><ins>+                column: index - lineStart - offset
</ins><span class="cx">             }
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="lines">@@ -451,8 +430,9 @@
</span><span class="cx">             ch = source.charCodeAt(index);
</span><span class="cx">             ++index;
</span><span class="cx">             if (isLineTerminator(ch)) {
</span><ins>+                hasLineTerminator = true;
</ins><span class="cx">                 if (extra.comments) {
</span><del>-                    comment = source.slice(start + 2, index - 1);
</del><ins>+                    comment = source.slice(start + offset, index - 1);
</ins><span class="cx">                     loc.end = {
</span><span class="cx">                         line: lineNumber,
</span><span class="cx">                         column: index - lineStart - 1
</span><span class="lines">@@ -469,7 +449,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (extra.comments) {
</span><del>-            comment = source.slice(start + 2, index);
</del><ins>+            comment = source.slice(start + offset, index);
</ins><span class="cx">             loc.end = {
</span><span class="cx">                 line: lineNumber,
</span><span class="cx">                 column: index - lineStart
</span><span class="lines">@@ -494,18 +474,16 @@
</span><span class="cx">         while (index &lt; length) {
</span><span class="cx">             ch = source.charCodeAt(index);
</span><span class="cx">             if (isLineTerminator(ch)) {
</span><del>-                if (ch === 13 &amp;&amp; source.charCodeAt(index + 1) === 10) {
</del><ins>+                if (ch === 0x0D &amp;&amp; source.charCodeAt(index + 1) === 0x0A) {
</ins><span class="cx">                     ++index;
</span><span class="cx">                 }
</span><ins>+                hasLineTerminator = true;
</ins><span class="cx">                 ++lineNumber;
</span><span class="cx">                 ++index;
</span><span class="cx">                 lineStart = index;
</span><del>-                if (index &gt;= length) {
-                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
-                }
-            } else if (ch === 42) {
-                // Block comment ends with '*/' (char #42, char #47).
-                if (source.charCodeAt(index + 1) === 47) {
</del><ins>+            } else if (ch === 0x2A) {
+                // Block comment ends with '*/'.
+                if (source.charCodeAt(index + 1) === 0x2F) {
</ins><span class="cx">                     ++index;
</span><span class="cx">                     ++index;
</span><span class="cx">                     if (extra.comments) {
</span><span class="lines">@@ -524,37 +502,70 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+        // Ran off the end of the file - the whole thing is a comment
+        if (extra.comments) {
+            loc.end = {
+                line: lineNumber,
+                column: index - lineStart
+            };
+            comment = source.slice(start + 2, index);
+            addComment('Block', comment, start, index, loc);
+        }
+        tolerateUnexpectedToken();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function skipComment() {
</span><del>-        var ch;
</del><ins>+        var ch, start;
+        hasLineTerminator = false;
</ins><span class="cx"> 
</span><ins>+        start = (index === 0);
</ins><span class="cx">         while (index &lt; length) {
</span><span class="cx">             ch = source.charCodeAt(index);
</span><span class="cx"> 
</span><span class="cx">             if (isWhiteSpace(ch)) {
</span><span class="cx">                 ++index;
</span><span class="cx">             } else if (isLineTerminator(ch)) {
</span><ins>+                hasLineTerminator = true;
</ins><span class="cx">                 ++index;
</span><del>-                if (ch === 13 &amp;&amp; source.charCodeAt(index) === 10) {
</del><ins>+                if (ch === 0x0D &amp;&amp; source.charCodeAt(index) === 0x0A) {
</ins><span class="cx">                     ++index;
</span><span class="cx">                 }
</span><span class="cx">                 ++lineNumber;
</span><span class="cx">                 lineStart = index;
</span><del>-            } else if (ch === 47) { // 47 is '/'
</del><ins>+                start = true;
+            } else if (ch === 0x2F) { // U+002F is '/'
</ins><span class="cx">                 ch = source.charCodeAt(index + 1);
</span><del>-                if (ch === 47) {
</del><ins>+                if (ch === 0x2F) {
</ins><span class="cx">                     ++index;
</span><span class="cx">                     ++index;
</span><del>-                    skipSingleLineComment();
-                } else if (ch === 42) {  // 42 is '*'
</del><ins>+                    skipSingleLineComment(2);
+                    start = true;
+                } else if (ch === 0x2A) {  // U+002A is '*'
</ins><span class="cx">                     ++index;
</span><span class="cx">                     ++index;
</span><span class="cx">                     skipMultiLineComment();
</span><span class="cx">                 } else {
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><ins>+            } else if (start &amp;&amp; ch === 0x2D) { // U+002D is '-'
+                // U+003E is '&gt;'
+                if ((source.charCodeAt(index + 1) === 0x2D) &amp;&amp; (source.charCodeAt(index + 2) === 0x3E)) {
+                    // '--&gt;' is a single-line comment
+                    index += 3;
+                    skipSingleLineComment(3);
+                } else {
+                    break;
+                }
+            } else if (ch === 0x3C) { // U+003C is '&lt;'
+                if (source.slice(index + 1, index + 4) === '!--') {
+                    ++index; // `&lt;`
+                    ++index; // `!`
+                    ++index; // `-`
+                    ++index; // `-`
+                    skipSingleLineComment(4);
+                } else {
+                    break;
+                }
</ins><span class="cx">             } else {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="lines">@@ -577,14 +588,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function scanUnicodeCodePointEscape() {
</span><del>-        var ch, code, cu1, cu2;
</del><ins>+        var ch, code;
</ins><span class="cx"> 
</span><span class="cx">         ch = source[index];
</span><span class="cx">         code = 0;
</span><span class="cx"> 
</span><span class="cx">         // At least, one hex digit is required.
</span><span class="cx">         if (ch === '}') {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         while (index &lt; length) {
</span><span class="lines">@@ -596,55 +607,78 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (code &gt; 0x10FFFF || ch !== '}') {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // UTF-16 Encoding
-        if (code &lt;= 0xFFFF) {
-            return String.fromCharCode(code);
</del><ins>+        return fromCodePoint(code);
+    }
+
+    function codePointAt(i) {
+        var cp, first, second;
+
+        cp = source.charCodeAt(i);
+        if (cp &gt;= 0xD800 &amp;&amp; cp &lt;= 0xDBFF) {
+            second = source.charCodeAt(i + 1);
+            if (second &gt;= 0xDC00 &amp;&amp; second &lt;= 0xDFFF) {
+                first = cp;
+                cp = (first - 0xD800) * 0x400 + second - 0xDC00 + 0x10000;
+            }
</ins><span class="cx">         }
</span><del>-        cu1 = ((code - 0x10000) &gt;&gt; 10) + 0xD800;
-        cu2 = ((code - 0x10000) &amp; 1023) + 0xDC00;
-        return String.fromCharCode(cu1, cu2);
</del><ins>+
+        return cp;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function getEscapedIdentifier() {
-        var ch, id;
</del><ins>+    function getComplexIdentifier() {
+        var cp, ch, id;
</ins><span class="cx"> 
</span><del>-        ch = source.charCodeAt(index++);
-        id = String.fromCharCode(ch);
</del><ins>+        cp = codePointAt(index);
+        id = fromCodePoint(cp);
+        index += id.length;
</ins><span class="cx"> 
</span><del>-        // '\u' (char #92, char #117) denotes an escaped character.
-        if (ch === 92) {
-            if (source.charCodeAt(index) !== 117) {
-                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+        // '\u' (U+005C, U+0075) denotes an escaped character.
+        if (cp === 0x5C) {
+            if (source.charCodeAt(index) !== 0x75) {
+                throwUnexpectedToken();
</ins><span class="cx">             }
</span><span class="cx">             ++index;
</span><del>-            ch = scanHexEscape('u');
-            if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) {
-                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            if (source[index] === '{') {
+                ++index;
+                ch = scanUnicodeCodePointEscape();
+            } else {
+                ch = scanHexEscape('u');
+                cp = ch.charCodeAt(0);
+                if (!ch || ch === '\\' || !isIdentifierStart(cp)) {
+                    throwUnexpectedToken();
+                }
</ins><span class="cx">             }
</span><span class="cx">             id = ch;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         while (index &lt; length) {
</span><del>-            ch = source.charCodeAt(index);
-            if (!isIdentifierPart(ch)) {
</del><ins>+            cp = codePointAt(index);
+            if (!isIdentifierPart(cp)) {
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            ++index;
-            id += String.fromCharCode(ch);
</del><ins>+            ch = fromCodePoint(cp);
+            id += ch;
+            index += ch.length;
</ins><span class="cx"> 
</span><del>-            // '\u' (char #92, char #117) denotes an escaped character.
-            if (ch === 92) {
</del><ins>+            // '\u' (U+005C, U+0075) denotes an escaped character.
+            if (cp === 0x5C) {
</ins><span class="cx">                 id = id.substr(0, id.length - 1);
</span><del>-                if (source.charCodeAt(index) !== 117) {
-                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+                if (source.charCodeAt(index) !== 0x75) {
+                    throwUnexpectedToken();
</ins><span class="cx">                 }
</span><span class="cx">                 ++index;
</span><del>-                ch = scanHexEscape('u');
-                if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) {
-                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+                if (source[index] === '{') {
+                    ++index;
+                    ch = scanUnicodeCodePointEscape();
+                } else {
+                    ch = scanHexEscape('u');
+                    cp = ch.charCodeAt(0);
+                    if (!ch || ch === '\\' || !isIdentifierPart(cp)) {
+                        throwUnexpectedToken();
+                    }
</ins><span class="cx">                 }
</span><span class="cx">                 id += ch;
</span><span class="cx">             }
</span><span class="lines">@@ -659,10 +693,14 @@
</span><span class="cx">         start = index++;
</span><span class="cx">         while (index &lt; length) {
</span><span class="cx">             ch = source.charCodeAt(index);
</span><del>-            if (ch === 92) {
-                // Blackslash (char #92) marks Unicode escape sequence.
</del><ins>+            if (ch === 0x5C) {
+                // Blackslash (U+005C) marks Unicode escape sequence.
</ins><span class="cx">                 index = start;
</span><del>-                return getEscapedIdentifier();
</del><ins>+                return getComplexIdentifier();
+            } else if (ch &gt;= 0xD800 &amp;&amp; ch &lt; 0xDFFF) {
+                // Need to handle surrogate pairs.
+                index = start;
+                return getComplexIdentifier();
</ins><span class="cx">             }
</span><span class="cx">             if (isIdentifierPart(ch)) {
</span><span class="cx">                 ++index;
</span><span class="lines">@@ -679,8 +717,8 @@
</span><span class="cx"> 
</span><span class="cx">         start = index;
</span><span class="cx"> 
</span><del>-        // Backslash (char #92) starts an escaped character.
-        id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier();
</del><ins>+        // Backslash (U+005C) starts an escaped character.
+        id = (source.charCodeAt(index) === 0x5C) ? getComplexIdentifier() : getIdentifier();
</ins><span class="cx"> 
</span><span class="cx">         // There is no keyword or literal with only one character.
</span><span class="cx">         // Thus, it must be an identifier.
</span><span class="lines">@@ -701,215 +739,113 @@
</span><span class="cx">             value: id,
</span><span class="cx">             lineNumber: lineNumber,
</span><span class="cx">             lineStart: lineStart,
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    // 7.7 Punctuators
</del><ins>+    // ECMA-262 11.7 Punctuators
</ins><span class="cx"> 
</span><span class="cx">     function scanPunctuator() {
</span><del>-        var start = index,
-            code = source.charCodeAt(index),
-            code2,
-            ch1 = source[index],
-            ch2,
-            ch3,
-            ch4;
</del><ins>+        var token, str;
</ins><span class="cx"> 
</span><del>-        switch (code) {
</del><ins>+        token = {
+            type: Token.Punctuator,
+            value: '',
+            lineNumber: lineNumber,
+            lineStart: lineStart,
+            start: index,
+            end: index
+        };
+
</ins><span class="cx">         // Check for most common single-character punctuators.
</span><del>-        case 40:   // ( open bracket
-        case 41:   // ) close bracket
-        case 59:   // ; semicolon
-        case 44:   // , comma
-        case 123:  // { open curly brace
-        case 125:  // } close curly brace
-        case 91:   // [
-        case 93:   // ]
-        case 58:   // :
-        case 63:   // ?
-        case 126:  // ~
</del><ins>+        str = source[index];
+        switch (str) {
+
+        case '(':
+            if (extra.tokenize) {
+                extra.openParenToken = extra.tokens.length;
+            }
</ins><span class="cx">             ++index;
</span><ins>+            break;
+
+        case '{':
</ins><span class="cx">             if (extra.tokenize) {
</span><del>-                if (code === 40) {
-                    extra.openParenToken = extra.tokens.length;
-                } else if (code === 123) {
-                    extra.openCurlyToken = extra.tokens.length;
-                }
</del><ins>+                extra.openCurlyToken = extra.tokens.length;
</ins><span class="cx">             }
</span><del>-            return {
-                type: Token.Punctuator,
-                value: String.fromCharCode(code),
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
</del><ins>+            state.curlyStack.push('{');
+            ++index;
+            break;
</ins><span class="cx"> 
</span><del>-        default:
-            code2 = source.charCodeAt(index + 1);
-
-            // '=' (char #61) marks an assignment or comparison operator.
-            if (code2 === 61) {
-                switch (code) {
-                case 37:  // %
-                case 38:  // &amp;
-                case 42:  // *:
-                case 43:  // +
-                case 45:  // -
-                case 47:  // /
-                case 60:  // &lt;
-                case 62:  // &gt;
-                case 94:  // ^
-                case 124: // |
-                    index += 2;
-                    return {
-                        type: Token.Punctuator,
-                        value: String.fromCharCode(code) + String.fromCharCode(code2),
-                        lineNumber: lineNumber,
-                        lineStart: lineStart,
-                        range: [start, index]
-                    };
-
-                case 33: // !
-                case 61: // =
-                    index += 2;
-
-                    // !== and ===
-                    if (source.charCodeAt(index) === 61) {
-                        ++index;
-                    }
-                    return {
-                        type: Token.Punctuator,
-                        value: source.slice(start, index),
-                        lineNumber: lineNumber,
-                        lineStart: lineStart,
-                        range: [start, index]
-                    };
-                default:
-                    break;
-                }
</del><ins>+        case '.':
+            ++index;
+            if (source[index] === '.' &amp;&amp; source[index + 1] === '.') {
+                // Spread operator: ...
+                index += 2;
+                str = '...';
</ins><span class="cx">             }
</span><span class="cx">             break;
</span><del>-        }
</del><span class="cx"> 
</span><del>-        // Peek more characters.
</del><ins>+        case '}':
+            ++index;
+            state.curlyStack.pop();
+            break;
+        case ')':
+        case ';':
+        case ',':
+        case '[':
+        case ']':
+        case ':':
+        case '?':
+        case '~':
+            ++index;
+            break;
</ins><span class="cx"> 
</span><del>-        ch2 = source[index + 1];
-        ch3 = source[index + 2];
-        ch4 = source[index + 3];
-
-        // 4-character punctuator: &gt;&gt;&gt;=
-
-        if (ch1 === '&gt;' &amp;&amp; ch2 === '&gt;' &amp;&amp; ch3 === '&gt;') {
-            if (ch4 === '=') {
</del><ins>+        default:
+            // 4-character punctuator.
+            str = source.substr(index, 4);
+            if (str === '&gt;&gt;&gt;=') {
</ins><span class="cx">                 index += 4;
</span><del>-                return {
-                    type: Token.Punctuator,
-                    value: '&gt;&gt;&gt;=',
-                    lineNumber: lineNumber,
-                    lineStart: lineStart,
-                    range: [start, index]
-                };
-            }
-        }
</del><ins>+            } else {
</ins><span class="cx"> 
</span><del>-        // 3-character punctuators: === !== &gt;&gt;&gt; &lt;&lt;= &gt;&gt;=
</del><ins>+                // 3-character punctuators.
+                str = str.substr(0, 3);
+                if (str === '===' || str === '!==' || str === '&gt;&gt;&gt;' ||
+                    str === '&lt;&lt;=' || str === '&gt;&gt;=') {
+                    index += 3;
+                } else {
</ins><span class="cx"> 
</span><del>-        if (ch1 === '&gt;' &amp;&amp; ch2 === '&gt;' &amp;&amp; ch3 === '&gt;') {
-            index += 3;
-            return {
-                type: Token.Punctuator,
-                value: '&gt;&gt;&gt;',
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
-        }
</del><ins>+                    // 2-character punctuators.
+                    str = str.substr(0, 2);
+                    if (str === '&amp;&amp;' || str === '||' || str === '==' || str === '!=' ||
+                        str === '+=' || str === '-=' || str === '*=' || str === '/=' ||
+                        str === '++' || str === '--' || str === '&lt;&lt;' || str === '&gt;&gt;' ||
+                        str === '&amp;=' || str === '|=' || str === '^=' || str === '%=' ||
+                        str === '&lt;=' || str === '&gt;=' || str === '=&gt;') {
+                        index += 2;
+                    } else {
</ins><span class="cx"> 
</span><del>-        if (ch1 === '&lt;' &amp;&amp; ch2 === '&lt;' &amp;&amp; ch3 === '=') {
-            index += 3;
-            return {
-                type: Token.Punctuator,
-                value: '&lt;&lt;=',
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
</del><ins>+                        // 1-character punctuators.
+                        str = source[index];
+                        if ('&lt;&gt;=!+-*%&amp;|^/'.indexOf(str) &gt;= 0) {
+                            ++index;
+                        }
+                    }
+                }
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (ch1 === '&gt;' &amp;&amp; ch2 === '&gt;' &amp;&amp; ch3 === '=') {
-            index += 3;
-            return {
-                type: Token.Punctuator,
-                value: '&gt;&gt;=',
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
</del><ins>+        if (index === token.start) {
+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (ch1 === '.' &amp;&amp; ch2 === '.' &amp;&amp; ch3 === '.') {
-            index += 3;
-            return {
-                type: Token.Punctuator,
-                value: '...',
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
-        }
-
-        // Other 2-character punctuators: ++ -- &lt;&lt; &gt;&gt; &amp;&amp; ||
-
-        if (ch1 === ch2 &amp;&amp; ('+-&lt;&gt;&amp;|'.indexOf(ch1) &gt;= 0)) {
-            index += 2;
-            return {
-                type: Token.Punctuator,
-                value: ch1 + ch2,
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
-        }
-
-        if (ch1 === '=' &amp;&amp; ch2 === '&gt;') {
-            index += 2;
-            return {
-                type: Token.Punctuator,
-                value: '=&gt;',
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
-        }
-
-        if ('&lt;&gt;=!+-*%&amp;|^/'.indexOf(ch1) &gt;= 0) {
-            ++index;
-            return {
-                type: Token.Punctuator,
-                value: ch1,
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
-        }
-
-        if (ch1 === '.') {
-            ++index;
-            return {
-                type: Token.Punctuator,
-                value: ch1,
-                lineNumber: lineNumber,
-                lineStart: lineStart,
-                range: [start, index]
-            };
-        }
-
-        throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+        token.end = index;
+        token.value = str;
+        return token;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.8.3 Numeric Literals
</del><ins>+    // ECMA-262 11.8.3 Numeric Literals
</ins><span class="cx"> 
</span><span class="cx">     function scanHexLiteral(start) {
</span><span class="cx">         var number = '';
</span><span class="lines">@@ -922,11 +858,11 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (number.length === 0) {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (isIdentifierStart(source.charCodeAt(index))) {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return {
</span><span class="lines">@@ -934,7 +870,8 @@
</span><span class="cx">             value: parseInt('0x' + number, 16),
</span><span class="cx">             lineNumber: lineNumber,
</span><span class="cx">             lineStart: lineStart,
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -953,14 +890,14 @@
</span><span class="cx"> 
</span><span class="cx">         if (number.length === 0) {
</span><span class="cx">             // only 0b or 0B
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (index &lt; length) {
</span><span class="cx">             ch = source.charCodeAt(index);
</span><span class="cx">             /* istanbul ignore else */
</span><span class="cx">             if (isIdentifierStart(ch) || isDecimalDigit(ch)) {
</span><del>-                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+                throwUnexpectedToken();
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -969,7 +906,8 @@
</span><span class="cx">             value: parseInt(number, 2),
</span><span class="cx">             lineNumber: lineNumber,
</span><span class="cx">             lineStart: lineStart,
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -994,11 +932,11 @@
</span><span class="cx"> 
</span><span class="cx">         if (!octal &amp;&amp; number.length === 0) {
</span><span class="cx">             // only 0o or 0O
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return {
</span><span class="lines">@@ -1007,10 +945,29 @@
</span><span class="cx">             octal: octal,
</span><span class="cx">             lineNumber: lineNumber,
</span><span class="cx">             lineStart: lineStart,
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function isImplicitOctalLiteral() {
+        var i, ch;
+
+        // Implicit octal, unless there is a non-octal digit.
+        // (Annex B.1.1 on Numeric Literals)
+        for (i = index + 1; i &lt; length; ++i) {
+            ch = source[i];
+            if (ch === '8' || ch === '9') {
+                return false;
+            }
+            if (!isOctalDigit(ch)) {
+                return true;
+            }
+        }
+
+        return true;
+    }
+
</ins><span class="cx">     function scanNumericLiteral() {
</span><span class="cx">         var number, start, ch;
</span><span class="cx"> 
</span><span class="lines">@@ -1037,12 +994,14 @@
</span><span class="cx">                     ++index;
</span><span class="cx">                     return scanBinaryLiteral(start);
</span><span class="cx">                 }
</span><del>-                if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) {
</del><ins>+                if (ch === 'o' || ch === 'O') {
</ins><span class="cx">                     return scanOctalLiteral(ch, start);
</span><span class="cx">                 }
</span><del>-                // decimal number starts with '0' such as '09' is illegal.
-                if (ch &amp;&amp; isDecimalDigit(ch.charCodeAt(0))) {
-                    throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+
+                if (isOctalDigit(ch)) {
+                    if (isImplicitOctalLiteral()) {
+                        return scanOctalLiteral(ch, start);
+                    }
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -1072,12 +1031,12 @@
</span><span class="cx">                     number += source[index++];
</span><span class="cx">                 }
</span><span class="cx">             } else {
</span><del>-                throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+                throwUnexpectedToken();
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (isIdentifierStart(source.charCodeAt(index))) {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return {
</span><span class="lines">@@ -1085,14 +1044,15 @@
</span><span class="cx">             value: parseFloat(number),
</span><span class="cx">             lineNumber: lineNumber,
</span><span class="cx">             lineStart: lineStart,
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 7.8.4 String Literals
</del><ins>+    // ECMA-262 11.8.4 String Literals
</ins><span class="cx"> 
</span><span class="cx">     function scanStringLiteral() {
</span><del>-        var str = '', quote, start, ch, code, unescaped, restore, octal = false;
</del><ins>+        var str = '', quote, start, ch, unescaped, octToDec, octal = false;
</ins><span class="cx"> 
</span><span class="cx">         quote = source[index];
</span><span class="cx">         assert((quote === '\'' || quote === '&quot;'),
</span><span class="lines">@@ -1111,31 +1071,28 @@
</span><span class="cx">                 ch = source[index++];
</span><span class="cx">                 if (!ch || !isLineTerminator(ch.charCodeAt(0))) {
</span><span class="cx">                     switch (ch) {
</span><del>-                    case 'n':
-                        str += '\n';
-                        break;
-                    case 'r':
-                        str += '\r';
-                        break;
-                    case 't':
-                        str += '\t';
-                        break;
</del><span class="cx">                     case 'u':
</span><span class="cx">                     case 'x':
</span><span class="cx">                         if (source[index] === '{') {
</span><span class="cx">                             ++index;
</span><span class="cx">                             str += scanUnicodeCodePointEscape();
</span><span class="cx">                         } else {
</span><del>-                            restore = index;
</del><span class="cx">                             unescaped = scanHexEscape(ch);
</span><del>-                            if (unescaped) {
-                                str += unescaped;
-                            } else {
-                                index = restore;
-                                str += ch;
</del><ins>+                            if (!unescaped) {
+                                throw throwUnexpectedToken();
</ins><span class="cx">                             }
</span><ins>+                            str += unescaped;
</ins><span class="cx">                         }
</span><span class="cx">                         break;
</span><ins>+                    case 'n':
+                        str += '\n';
+                        break;
+                    case 'r':
+                        str += '\r';
+                        break;
+                    case 't':
+                        str += '\t';
+                        break;
</ins><span class="cx">                     case 'b':
</span><span class="cx">                         str += '\b';
</span><span class="cx">                         break;
</span><span class="lines">@@ -1145,30 +1102,18 @@
</span><span class="cx">                     case 'v':
</span><span class="cx">                         str += '\x0B';
</span><span class="cx">                         break;
</span><ins>+                    case '8':
+                    case '9':
+                        str += ch;
+                        tolerateUnexpectedToken();
+                        break;
</ins><span class="cx"> 
</span><span class="cx">                     default:
</span><span class="cx">                         if (isOctalDigit(ch)) {
</span><del>-                            code = '01234567'.indexOf(ch);
</del><ins>+                            octToDec = octalToDecimal(ch);
</ins><span class="cx"> 
</span><del>-                            // \0 is not octal escape sequence
-                            if (code !== 0) {
-                                octal = true;
-                            }
-
-                            /* istanbul ignore else */
-                            if (index &lt; length &amp;&amp; isOctalDigit(source[index])) {
-                                octal = true;
-                                code = code * 8 + '01234567'.indexOf(source[index++]);
-
-                                // 3 digits are only allowed when string starts
-                                // with 0, 1, 2, 3
-                                if ('0123'.indexOf(ch) &gt;= 0 &amp;&amp;
-                                        index &lt; length &amp;&amp;
-                                        isOctalDigit(source[index])) {
-                                    code = code * 8 + '01234567'.indexOf(source[index++]);
-                                }
-                            }
-                            str += String.fromCharCode(code);
</del><ins>+                            octal = octToDec.octal || octal;
+                            str += String.fromCharCode(octToDec.code);
</ins><span class="cx">                         } else {
</span><span class="cx">                             str += ch;
</span><span class="cx">                         }
</span><span class="lines">@@ -1189,36 +1134,43 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (quote !== '') {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return {
</span><span class="cx">             type: Token.StringLiteral,
</span><span class="cx">             value: str,
</span><span class="cx">             octal: octal,
</span><del>-            lineNumber: lineNumber,
-            lineStart: lineStart,
-            range: [start, index]
</del><ins>+            lineNumber: startLineNumber,
+            lineStart: startLineStart,
+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // ECMA-262 11.8.6 Template Literal Lexical Components
+
</ins><span class="cx">     function scanTemplate() {
</span><del>-        var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal;
</del><ins>+        var cooked = '', ch, start, rawOffset, terminated, head, tail, restore, unescaped;
</ins><span class="cx"> 
</span><span class="cx">         terminated = false;
</span><span class="cx">         tail = false;
</span><span class="cx">         start = index;
</span><ins>+        head = (source[index] === '`');
+        rawOffset = 2;
</ins><span class="cx"> 
</span><span class="cx">         ++index;
</span><span class="cx"> 
</span><span class="cx">         while (index &lt; length) {
</span><span class="cx">             ch = source[index++];
</span><span class="cx">             if (ch === '`') {
</span><ins>+                rawOffset = 1;
</ins><span class="cx">                 tail = true;
</span><span class="cx">                 terminated = true;
</span><span class="cx">                 break;
</span><span class="cx">             } else if (ch === '$') {
</span><span class="cx">                 if (source[index] === '{') {
</span><ins>+                    state.curlyStack.push('${');
</ins><span class="cx">                     ++index;
</span><span class="cx">                     terminated = true;
</span><span class="cx">                     break;
</span><span class="lines">@@ -1264,28 +1216,15 @@
</span><span class="cx">                         break;
</span><span class="cx"> 
</span><span class="cx">                     default:
</span><del>-                        if (isOctalDigit(ch)) {
-                            code = '01234567'.indexOf(ch);
-
-                            // \0 is not octal escape sequence
-                            if (code !== 0) {
-                                octal = true;
</del><ins>+                        if (ch === '0') {
+                            if (isDecimalDigit(source.charCodeAt(index))) {
+                                // Illegal: \01 \02 and so on
+                                throwError(Messages.TemplateOctalLiteral);
</ins><span class="cx">                             }
</span><del>-
-                            /* istanbul ignore else */
-                            if (index &lt; length &amp;&amp; isOctalDigit(source[index])) {
-                                octal = true;
-                                code = code * 8 + '01234567'.indexOf(source[index++]);
-
-                                // 3 digits are only allowed when string starts
-                                // with 0, 1, 2, 3
-                                if ('0123'.indexOf(ch) &gt;= 0 &amp;&amp;
-                                        index &lt; length &amp;&amp;
-                                        isOctalDigit(source[index])) {
-                                    code = code * 8 + '01234567'.indexOf(source[index++]);
-                                }
-                            }
-                            cooked += String.fromCharCode(code);
</del><ins>+                            cooked += '\0';
+                        } else if (isOctalDigit(ch)) {
+                            // Illegal: \1 \2
+                            throwError(Messages.TemplateOctalLiteral);
</ins><span class="cx">                         } else {
</span><span class="cx">                             cooked += ch;
</span><span class="cx">                         }
</span><span class="lines">@@ -1311,70 +1250,70 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!terminated) {
</span><del>-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (!head) {
+            state.curlyStack.pop();
+        }
+
</ins><span class="cx">         return {
</span><span class="cx">             type: Token.Template,
</span><span class="cx">             value: {
</span><span class="cx">                 cooked: cooked,
</span><del>-                raw: source.slice(start + 1, index - ((tail) ? 1 : 2))
</del><ins>+                raw: source.slice(start + 1, index - rawOffset)
</ins><span class="cx">             },
</span><ins>+            head: head,
</ins><span class="cx">             tail: tail,
</span><del>-            octal: octal,
</del><span class="cx">             lineNumber: lineNumber,
</span><span class="cx">             lineStart: lineStart,
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function scanTemplateElement(option) {
-        var startsWith, template;
</del><ins>+    // ECMA-262 11.8.5 Regular Expression Literals
</ins><span class="cx"> 
</span><del>-        lookahead = null;
-        skipComment();
-
-        startsWith = (option.head) ? '`' : '}';
-
-        if (source[index] !== startsWith) {
-            throwError({}, Messages.UnexpectedToken, 'ILLEGAL');
-        }
-
-        template = scanTemplate();
-
-        peek();
-
-        return template;
-    }
-
</del><span class="cx">     function testRegExp(pattern, flags) {
</span><del>-        var tmp = pattern,
-            value;
</del><ins>+        // The BMP character to use as a replacement for astral symbols when
+        // translating an ES6 &quot;u&quot;-flagged pattern to an ES5-compatible
+        // approximation.
+        // Note: replacing with '\uFFFF' enables false positives in unlikely
+        // scenarios. For example, `[\u{1044f}-\u{10440}]` is an invalid
+        // pattern that would not be detected by this substitution.
+        var astralSubstitute = '\uFFFF',
+            tmp = pattern;
</ins><span class="cx"> 
</span><span class="cx">         if (flags.indexOf('u') &gt;= 0) {
</span><del>-            // Replace each astral symbol and every Unicode code point
-            // escape sequence with a single ASCII symbol to avoid throwing on
-            // regular expressions that are only valid in combination with the
-            // `/u` flag.
-            // Note: replacing with the ASCII symbol `x` might cause false
-            // negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
-            // perfectly valid pattern that is equivalent to `[a-b]`, but it
-            // would be replaced by `[x-b]` which throws an error.
</del><span class="cx">             tmp = tmp
</span><del>-                .replace(/\\u\{([0-9a-fA-F]+)\}/g, function ($0, $1) {
-                    if (parseInt($1, 16) &lt;= 0x10FFFF) {
-                        return 'x';
</del><ins>+                // Replace every Unicode escape sequence with the equivalent
+                // BMP character or a constant ASCII code point in the case of
+                // astral symbols. (See the above note on `astralSubstitute`
+                // for more information.)
+                .replace(/\\u\{([0-9a-fA-F]+)\}|\\u([a-fA-F0-9]{4})/g, function ($0, $1, $2) {
+                    var codePoint = parseInt($1 || $2, 16);
+                    if (codePoint &gt; 0x10FFFF) {
+                        throwUnexpectedToken(null, Messages.InvalidRegExp);
</ins><span class="cx">                     }
</span><del>-                    throwError({}, Messages.InvalidRegExp);
</del><ins>+                    if (codePoint &lt;= 0xFFFF) {
+                        return String.fromCharCode(codePoint);
+                    }
+                    return astralSubstitute;
</ins><span class="cx">                 })
</span><del>-                .replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, 'x');
</del><ins>+                // Replace each paired surrogate with a single ASCII symbol to
+                // avoid throwing on regular expressions that are only valid in
+                // combination with the &quot;u&quot; flag.
+                .replace(
+                    /[\uD800-\uDBFF][\uDC00-\uDFFF]/g,
+                    astralSubstitute
+                );
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // First, detect invalid regular expressions.
</span><span class="cx">         try {
</span><del>-            value = new RegExp(tmp);
</del><ins>+            RegExp(tmp);
</ins><span class="cx">         } catch (e) {
</span><del>-            throwError({}, Messages.InvalidRegExp);
</del><ins>+            throwUnexpectedToken(null, Messages.InvalidRegExp);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Return a regular expression object for this pattern-flag pair, or
</span><span class="lines">@@ -1403,11 +1342,11 @@
</span><span class="cx">                 ch = source[index++];
</span><span class="cx">                 // ECMA-262 7.8.5
</span><span class="cx">                 if (isLineTerminator(ch.charCodeAt(0))) {
</span><del>-                    throwError({}, Messages.UnterminatedRegExp);
</del><ins>+                    throwUnexpectedToken(null, Messages.UnterminatedRegExp);
</ins><span class="cx">                 }
</span><span class="cx">                 str += ch;
</span><span class="cx">             } else if (isLineTerminator(ch.charCodeAt(0))) {
</span><del>-                throwError({}, Messages.UnterminatedRegExp);
</del><ins>+                throwUnexpectedToken(null, Messages.UnterminatedRegExp);
</ins><span class="cx">             } else if (classMarker) {
</span><span class="cx">                 if (ch === ']') {
</span><span class="cx">                     classMarker = false;
</span><span class="lines">@@ -1423,7 +1362,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!terminated) {
</span><del>-            throwError({}, Messages.UnterminatedRegExp);
</del><ins>+            throwUnexpectedToken(null, Messages.UnterminatedRegExp);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // Exclude leading and trailing slash.
</span><span class="lines">@@ -1462,10 +1401,10 @@
</span><span class="cx">                         flags += 'u';
</span><span class="cx">                         str += '\\u';
</span><span class="cx">                     }
</span><del>-                    throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+                    tolerateUnexpectedToken();
</ins><span class="cx">                 } else {
</span><span class="cx">                     str += '\\';
</span><del>-                    throwErrorTolerant({}, Messages.UnexpectedToken, 'ILLEGAL');
</del><ins>+                    tolerateUnexpectedToken();
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 flags += ch;
</span><span class="lines">@@ -1481,6 +1420,7 @@
</span><span class="cx"> 
</span><span class="cx">     function scanRegExp() {
</span><span class="cx">         var start, body, flags, value;
</span><ins>+        scanning = true;
</ins><span class="cx"> 
</span><span class="cx">         lookahead = null;
</span><span class="cx">         skipComment();
</span><span class="lines">@@ -1489,7 +1429,7 @@
</span><span class="cx">         body = scanRegExpBody();
</span><span class="cx">         flags = scanRegExpFlags();
</span><span class="cx">         value = testRegExp(body.value, flags.value);
</span><del>-
</del><ins>+        scanning = false;
</ins><span class="cx">         if (extra.tokenize) {
</span><span class="cx">             return {
</span><span class="cx">                 type: Token.RegularExpression,
</span><span class="lines">@@ -1500,7 +1440,8 @@
</span><span class="cx">                 },
</span><span class="cx">                 lineNumber: lineNumber,
</span><span class="cx">                 lineStart: lineStart,
</span><del>-                range: [start, index]
</del><ins>+                start: start,
+                end: index
</ins><span class="cx">             };
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -1511,10 +1452,55 @@
</span><span class="cx">                 pattern: body.value,
</span><span class="cx">                 flags: flags.value
</span><span class="cx">             },
</span><del>-            range: [start, index]
</del><ins>+            start: start,
+            end: index
</ins><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function collectRegex() {
+        var pos, loc, regex, token;
+
+        skipComment();
+
+        pos = index;
+        loc = {
+            start: {
+                line: lineNumber,
+                column: index - lineStart
+            }
+        };
+
+        regex = scanRegExp();
+
+        loc.end = {
+            line: lineNumber,
+            column: index - lineStart
+        };
+
+        /* istanbul ignore next */
+        if (!extra.tokenize) {
+            // Pop the previous token, which is likely '/' or '/='
+            if (extra.tokens.length &gt; 0) {
+                token = extra.tokens[extra.tokens.length - 1];
+                if (token.range[0] === pos &amp;&amp; token.type === 'Punctuator') {
+                    if (token.value === '/' || token.value === '/=') {
+                        extra.tokens.pop();
+                    }
+                }
+            }
+
+            extra.tokens.push({
+                type: 'RegularExpression',
+                value: regex.literal,
+                regex: regex.regex,
+                range: [pos, index],
+                loc: loc
+            });
+        }
+
+        return regex;
+    }
+
</ins><span class="cx">     function isIdentifierName(token) {
</span><span class="cx">         return token.type === Token.Identifier ||
</span><span class="cx">             token.type === Token.Keyword ||
</span><span class="lines">@@ -1530,9 +1516,12 @@
</span><span class="cx">         prevToken = extra.tokens[extra.tokens.length - 1];
</span><span class="cx">         if (!prevToken) {
</span><span class="cx">             // Nothing before that: it cannot be a division.
</span><del>-            return scanRegExp();
</del><ins>+            return collectRegex();
</ins><span class="cx">         }
</span><span class="cx">         if (prevToken.type === 'Punctuator') {
</span><ins>+            if (prevToken.value === ']') {
+                return scanPunctuator();
+            }
</ins><span class="cx">             if (prevToken.value === ')') {
</span><span class="cx">                 checkToken = extra.tokens[extra.openParenToken - 1];
</span><span class="cx">                 if (checkToken &amp;&amp;
</span><span class="lines">@@ -1541,7 +1530,7 @@
</span><span class="cx">                          checkToken.value === 'while' ||
</span><span class="cx">                          checkToken.value === 'for' ||
</span><span class="cx">                          checkToken.value === 'with')) {
</span><del>-                    return scanRegExp();
</del><ins>+                    return collectRegex();
</ins><span class="cx">                 }
</span><span class="cx">                 return scanPunctuator();
</span><span class="cx">             }
</span><span class="lines">@@ -1560,7 +1549,7 @@
</span><span class="cx">                     // Named function.
</span><span class="cx">                     checkToken = extra.tokens[extra.openCurlyToken - 5];
</span><span class="cx">                     if (!checkToken) {
</span><del>-                        return scanRegExp();
</del><ins>+                        return collectRegex();
</ins><span class="cx">                     }
</span><span class="cx">                 } else {
</span><span class="cx">                     return scanPunctuator();
</span><span class="lines">@@ -1572,838 +1561,981 @@
</span><span class="cx">                     return scanPunctuator();
</span><span class="cx">                 }
</span><span class="cx">                 // It is a declaration.
</span><del>-                return scanRegExp();
</del><ins>+                return collectRegex();
</ins><span class="cx">             }
</span><del>-            return scanRegExp();
</del><ins>+            return collectRegex();
</ins><span class="cx">         }
</span><span class="cx">         if (prevToken.type === 'Keyword' &amp;&amp; prevToken.value !== 'this') {
</span><del>-            return scanRegExp();
</del><ins>+            return collectRegex();
</ins><span class="cx">         }
</span><span class="cx">         return scanPunctuator();
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function advance() {
</span><del>-        var ch;
</del><ins>+        var cp, token;
</ins><span class="cx"> 
</span><del>-        skipComment();
-
</del><span class="cx">         if (index &gt;= length) {
</span><span class="cx">             return {
</span><span class="cx">                 type: Token.EOF,
</span><span class="cx">                 lineNumber: lineNumber,
</span><span class="cx">                 lineStart: lineStart,
</span><del>-                range: [index, index]
</del><ins>+                start: index,
+                end: index
</ins><span class="cx">             };
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        ch = source.charCodeAt(index);
</del><ins>+        cp = source.charCodeAt(index);
</ins><span class="cx"> 
</span><ins>+        if (isIdentifierStart(cp)) {
+            token = scanIdentifier();
+            if (strict &amp;&amp; isStrictModeReservedWord(token.value)) {
+                token.type = Token.Keyword;
+            }
+            return token;
+        }
+
</ins><span class="cx">         // Very common: ( and ) and ;
</span><del>-        if (ch === 40 || ch === 41 || ch === 58) {
</del><ins>+        if (cp === 0x28 || cp === 0x29 || cp === 0x3B) {
</ins><span class="cx">             return scanPunctuator();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // String literal starts with single quote (#39) or double quote (#34).
-        if (ch === 39 || ch === 34) {
</del><ins>+        // String literal starts with single quote (U+0027) or double quote (U+0022).
+        if (cp === 0x27 || cp === 0x22) {
</ins><span class="cx">             return scanStringLiteral();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (ch === 96) {
-            return scanTemplate();
-        }
-        if (isIdentifierStart(ch)) {
-            return scanIdentifier();
-        }
-
-        // Dot (.) char #46 can also start a floating-point number, hence the need
</del><ins>+        // Dot (.) U+002E can also start a floating-point number, hence the need
</ins><span class="cx">         // to check the next character.
</span><del>-        if (ch === 46) {
</del><ins>+        if (cp === 0x2E) {
</ins><span class="cx">             if (isDecimalDigit(source.charCodeAt(index + 1))) {
</span><span class="cx">                 return scanNumericLiteral();
</span><span class="cx">             }
</span><span class="cx">             return scanPunctuator();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (isDecimalDigit(ch)) {
</del><ins>+        if (isDecimalDigit(cp)) {
</ins><span class="cx">             return scanNumericLiteral();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        // Slash (/) char #47 can also start a regex.
-        if (extra.tokenize &amp;&amp; ch === 47) {
</del><ins>+        // Slash (/) U+002F can also start a regex.
+        if (extra.tokenize &amp;&amp; cp === 0x2F) {
</ins><span class="cx">             return advanceSlash();
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        // Template literals start with ` (U+0060) for template head
+        // or } (U+007D) for template middle or template tail.
+        if (cp === 0x60 || (cp === 0x7D &amp;&amp; state.curlyStack[state.curlyStack.length - 1] === '${')) {
+            return scanTemplate();
+        }
+
+        // Possible identifier start in a surrogate pair.
+        if (cp &gt;= 0xD800 &amp;&amp; cp &lt; 0xDFFF) {
+            cp = codePointAt(index);
+            if (isIdentifierStart(cp)) {
+                return scanIdentifier();
+            }
+        }
+
</ins><span class="cx">         return scanPunctuator();
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function collectToken() {
+        var loc, token, value, entry;
+
+        loc = {
+            start: {
+                line: lineNumber,
+                column: index - lineStart
+            }
+        };
+
+        token = advance();
+        loc.end = {
+            line: lineNumber,
+            column: index - lineStart
+        };
+
+        if (token.type !== Token.EOF) {
+            value = source.slice(token.start, token.end);
+            entry = {
+                type: TokenName[token.type],
+                value: value,
+                range: [token.start, token.end],
+                loc: loc
+            };
+            if (token.regex) {
+                entry.regex = {
+                    pattern: token.regex.pattern,
+                    flags: token.regex.flags
+                };
+            }
+            extra.tokens.push(entry);
+        }
+
+        return token;
+    }
+
</ins><span class="cx">     function lex() {
</span><span class="cx">         var token;
</span><ins>+        scanning = true;
</ins><span class="cx"> 
</span><ins>+        lastIndex = index;
+        lastLineNumber = lineNumber;
+        lastLineStart = lineStart;
+
+        skipComment();
+
</ins><span class="cx">         token = lookahead;
</span><del>-        index = token.range[1];
-        lineNumber = token.lineNumber;
-        lineStart = token.lineStart;
</del><span class="cx"> 
</span><del>-        lookahead = advance();
</del><ins>+        startIndex = index;
+        startLineNumber = lineNumber;
+        startLineStart = lineStart;
</ins><span class="cx"> 
</span><del>-        index = token.range[1];
-        lineNumber = token.lineNumber;
-        lineStart = token.lineStart;
-
</del><ins>+        lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+        scanning = false;
</ins><span class="cx">         return token;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function peek() {
</span><del>-        var pos, line, start;
</del><ins>+        scanning = true;
</ins><span class="cx"> 
</span><del>-        pos = index;
-        line = lineNumber;
-        start = lineStart;
-        lookahead = advance();
-        index = pos;
-        lineNumber = line;
-        lineStart = start;
-    }
</del><ins>+        skipComment();
</ins><span class="cx"> 
</span><del>-    function lookahead2() {
-        var adv, pos, line, start, result;
</del><ins>+        lastIndex = index;
+        lastLineNumber = lineNumber;
+        lastLineStart = lineStart;
</ins><span class="cx"> 
</span><del>-        // If we are collecting the tokens, don't grab the next one yet.
-        /* istanbul ignore next */
-        adv = (typeof extra.advance === 'function') ? extra.advance : advance;
</del><ins>+        startIndex = index;
+        startLineNumber = lineNumber;
+        startLineStart = lineStart;
</ins><span class="cx"> 
</span><del>-        pos = index;
-        line = lineNumber;
-        start = lineStart;
</del><ins>+        lookahead = (typeof extra.tokens !== 'undefined') ? collectToken() : advance();
+        scanning = false;
+    }
</ins><span class="cx"> 
</span><del>-        // Scan for the next immediate token.
-        /* istanbul ignore if */
-        if (lookahead === null) {
-            lookahead = adv();
-        }
-        index = lookahead.range[1];
-        lineNumber = lookahead.lineNumber;
-        lineStart = lookahead.lineStart;
</del><ins>+    function Position() {
+        this.line = startLineNumber;
+        this.column = startIndex - startLineStart;
+    }
</ins><span class="cx"> 
</span><del>-        // Grab the token right after.
-        result = adv();
-        index = pos;
-        lineNumber = line;
-        lineStart = start;
</del><ins>+    function SourceLocation() {
+        this.start = new Position();
+        this.end = null;
+    }
</ins><span class="cx"> 
</span><del>-        return result;
</del><ins>+    function WrappingSourceLocation(startToken) {
+        this.start = {
+            line: startToken.lineNumber,
+            column: startToken.start - startToken.lineStart
+        };
+        this.end = null;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function markerCreate() {
-        if (!extra.loc &amp;&amp; !extra.range) {
-            return undefined;
</del><ins>+    function Node() {
+        if (extra.range) {
+            this.range = [startIndex, 0];
</ins><span class="cx">         }
</span><del>-        skipComment();
-        return {offset: index, line: lineNumber, col: index - lineStart};
</del><ins>+        if (extra.loc) {
+            this.loc = new SourceLocation();
+        }
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function processComment(node) {
-        var lastChild,
-            trailingComments,
-            bottomRight = extra.bottomRightStack,
-            last = bottomRight[bottomRight.length - 1];
</del><ins>+    function WrappingNode(startToken) {
+        if (extra.range) {
+            this.range = [startToken.start, 0];
+        }
+        if (extra.loc) {
+            this.loc = new WrappingSourceLocation(startToken);
+        }
+    }
</ins><span class="cx"> 
</span><del>-        if (node.type === Syntax.Program) {
-            /* istanbul ignore else */
-            if (node.body.length &gt; 0) {
-                return;
</del><ins>+    WrappingNode.prototype = Node.prototype = {
+
+        processComment: function () {
+            var lastChild,
+                leadingComments,
+                trailingComments,
+                bottomRight = extra.bottomRightStack,
+                i,
+                comment,
+                last = bottomRight[bottomRight.length - 1];
+
+            if (this.type === Syntax.Program) {
+                if (this.body.length &gt; 0) {
+                    return;
+                }
</ins><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        if (extra.trailingComments.length &gt; 0) {
-            if (extra.trailingComments[0].range[0] &gt;= node.range[1]) {
-                trailingComments = extra.trailingComments;
</del><ins>+            if (extra.trailingComments.length &gt; 0) {
+                trailingComments = [];
+                for (i = extra.trailingComments.length - 1; i &gt;= 0; --i) {
+                    comment = extra.trailingComments[i];
+                    if (comment.range[0] &gt;= this.range[1]) {
+                        trailingComments.unshift(comment);
+                        extra.trailingComments.splice(i, 1);
+                    }
+                }
</ins><span class="cx">                 extra.trailingComments = [];
</span><span class="cx">             } else {
</span><del>-                extra.trailingComments.length = 0;
</del><ins>+                if (last &amp;&amp; last.trailingComments &amp;&amp; last.trailingComments[0].range[0] &gt;= this.range[1]) {
+                    trailingComments = last.trailingComments;
+                    delete last.trailingComments;
+                }
</ins><span class="cx">             }
</span><del>-        } else {
-            if (last &amp;&amp; last.trailingComments &amp;&amp; last.trailingComments[0].range[0] &gt;= node.range[1]) {
-                trailingComments = last.trailingComments;
-                delete last.trailingComments;
</del><ins>+
+            // Eating the stack.
+            while (last &amp;&amp; last.range[0] &gt;= this.range[0]) {
+                lastChild = bottomRight.pop();
+                last = bottomRight[bottomRight.length - 1];
</ins><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        // Eating the stack.
-        if (last) {
-            while (last &amp;&amp; last.range[0] &gt;= node.range[0]) {
-                lastChild = last;
-                last = bottomRight.pop();
</del><ins>+            if (lastChild) {
+                if (lastChild.leadingComments) {
+                    leadingComments = [];
+                    for (i = lastChild.leadingComments.length - 1; i &gt;= 0; --i) {
+                        comment = lastChild.leadingComments[i];
+                        if (comment.range[1] &lt;= this.range[0]) {
+                            leadingComments.unshift(comment);
+                            lastChild.leadingComments.splice(i, 1);
+                        }
+                    }
+
+                    if (!lastChild.leadingComments.length) {
+                        lastChild.leadingComments = undefined;
+                    }
+                }
+            } else if (extra.leadingComments.length &gt; 0) {
+                leadingComments = [];
+                for (i = extra.leadingComments.length - 1; i &gt;= 0; --i) {
+                    comment = extra.leadingComments[i];
+                    if (comment.range[1] &lt;= this.range[0]) {
+                        leadingComments.unshift(comment);
+                        extra.leadingComments.splice(i, 1);
+                    }
+                }
</ins><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        if (lastChild) {
-            if (lastChild.leadingComments &amp;&amp; lastChild.leadingComments[lastChild.leadingComments.length - 1].range[1] &lt;= node.range[0]) {
-                node.leadingComments = lastChild.leadingComments;
-                delete lastChild.leadingComments;
</del><ins>+
+            if (leadingComments &amp;&amp; leadingComments.length &gt; 0) {
+                this.leadingComments = leadingComments;
</ins><span class="cx">             }
</span><del>-        } else if (extra.leadingComments.length &gt; 0 &amp;&amp; extra.leadingComments[extra.leadingComments.length - 1].range[1] &lt;= node.range[0]) {
-            node.leadingComments = extra.leadingComments;
-            extra.leadingComments = [];
-        }
</del><ins>+            if (trailingComments &amp;&amp; trailingComments.length &gt; 0) {
+                this.trailingComments = trailingComments;
+            }
</ins><span class="cx"> 
</span><del>-        if (trailingComments) {
-            node.trailingComments = trailingComments;
-        }
</del><ins>+            bottomRight.push(this);
+        },
</ins><span class="cx"> 
</span><del>-        bottomRight.push(node);
-    }
-
-    function markerApply(marker, node) {
-        if (extra.range) {
-            node.range = [marker.offset, index];
-        }
-        if (extra.loc) {
-            node.loc = {
-                start: {
-                    line: marker.line,
-                    column: marker.col
-                },
-                end: {
-                    line: lineNumber,
-                    column: index - lineStart
</del><ins>+        finish: function () {
+            if (extra.range) {
+                this.range[1] = lastIndex;
+            }
+            if (extra.loc) {
+                this.loc.end = {
+                    line: lastLineNumber,
+                    column: lastIndex - lastLineStart
+                };
+                if (extra.source) {
+                    this.loc.source = extra.source;
</ins><span class="cx">                 }
</span><del>-            };
-            node = delegate.postProcess(node);
-        }
-        if (extra.attachComment) {
-            processComment(node);
-        }
-        return node;
-    }
</del><ins>+            }
</ins><span class="cx"> 
</span><del>-    SyntaxTreeDelegate = {
</del><ins>+            if (extra.attachComment) {
+                this.processComment();
+            }
+        },
</ins><span class="cx"> 
</span><del>-        name: 'SyntaxTree',
</del><ins>+        finishArrayExpression: function (elements) {
+            this.type = Syntax.ArrayExpression;
+            this.elements = elements;
+            this.finish();
+            return this;
+        },
</ins><span class="cx"> 
</span><del>-        postProcess: function (node) {
-            return node;
</del><ins>+        finishArrayPattern: function (elements) {
+            this.type = Syntax.ArrayPattern;
+            this.elements = elements;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createArrayExpression: function (elements) {
-            return {
-                type: Syntax.ArrayExpression,
-                elements: elements
-            };
</del><ins>+        finishArrowFunctionExpression: function (params, defaults, body, expression) {
+            this.type = Syntax.ArrowFunctionExpression;
+            this.id = null;
+            this.params = params;
+            this.defaults = defaults;
+            this.body = body;
+            this.generator = false;
+            this.expression = expression;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createAssignmentExpression: function (operator, left, right) {
-            return {
-                type: Syntax.AssignmentExpression,
-                operator: operator,
-                left: left,
-                right: right
-            };
</del><ins>+        finishAssignmentExpression: function (operator, left, right) {
+            this.type = Syntax.AssignmentExpression;
+            this.operator = operator;
+            this.left = left;
+            this.right = right;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createBinaryExpression: function (operator, left, right) {
-            var type = (operator === '||' || operator === '&amp;&amp;') ? Syntax.LogicalExpression :
-                        Syntax.BinaryExpression;
-            return {
-                type: type,
-                operator: operator,
-                left: left,
-                right: right
-            };
</del><ins>+        finishAssignmentPattern: function (left, right) {
+            this.type = Syntax.AssignmentPattern;
+            this.left = left;
+            this.right = right;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createBlockStatement: function (body) {
-            return {
-                type: Syntax.BlockStatement,
-                body: body
-            };
</del><ins>+        finishBinaryExpression: function (operator, left, right) {
+            this.type = (operator === '||' || operator === '&amp;&amp;') ? Syntax.LogicalExpression : Syntax.BinaryExpression;
+            this.operator = operator;
+            this.left = left;
+            this.right = right;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createBreakStatement: function (label) {
-            return {
-                type: Syntax.BreakStatement,
-                label: label
-            };
</del><ins>+        finishBlockStatement: function (body) {
+            this.type = Syntax.BlockStatement;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createCallExpression: function (callee, args) {
-            return {
-                type: Syntax.CallExpression,
-                callee: callee,
-                'arguments': args
-            };
</del><ins>+        finishBreakStatement: function (label) {
+            this.type = Syntax.BreakStatement;
+            this.label = label;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createCatchClause: function (param, body) {
-            return {
-                type: Syntax.CatchClause,
-                param: param,
-                body: body
-            };
</del><ins>+        finishCallExpression: function (callee, args) {
+            this.type = Syntax.CallExpression;
+            this.callee = callee;
+            this.arguments = args;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createConditionalExpression: function (test, consequent, alternate) {
-            return {
-                type: Syntax.ConditionalExpression,
-                test: test,
-                consequent: consequent,
-                alternate: alternate
-            };
</del><ins>+        finishCatchClause: function (param, body) {
+            this.type = Syntax.CatchClause;
+            this.param = param;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createContinueStatement: function (label) {
-            return {
-                type: Syntax.ContinueStatement,
-                label: label
-            };
</del><ins>+        finishClassBody: function (body) {
+            this.type = Syntax.ClassBody;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createDebuggerStatement: function () {
-            return {
-                type: Syntax.DebuggerStatement
-            };
</del><ins>+        finishClassDeclaration: function (id, superClass, body) {
+            this.type = Syntax.ClassDeclaration;
+            this.id = id;
+            this.superClass = superClass;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createDoWhileStatement: function (body, test) {
-            return {
-                type: Syntax.DoWhileStatement,
-                body: body,
-                test: test
-            };
</del><ins>+        finishClassExpression: function (id, superClass, body) {
+            this.type = Syntax.ClassExpression;
+            this.id = id;
+            this.superClass = superClass;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createEmptyStatement: function () {
-            return {
-                type: Syntax.EmptyStatement
-            };
</del><ins>+        finishConditionalExpression: function (test, consequent, alternate) {
+            this.type = Syntax.ConditionalExpression;
+            this.test = test;
+            this.consequent = consequent;
+            this.alternate = alternate;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createExpressionStatement: function (expression) {
-            return {
-                type: Syntax.ExpressionStatement,
-                expression: expression
-            };
</del><ins>+        finishContinueStatement: function (label) {
+            this.type = Syntax.ContinueStatement;
+            this.label = label;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createForStatement: function (init, test, update, body) {
-            return {
-                type: Syntax.ForStatement,
-                init: init,
-                test: test,
-                update: update,
-                body: body
-            };
</del><ins>+        finishDebuggerStatement: function () {
+            this.type = Syntax.DebuggerStatement;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createForInStatement: function (left, right, body) {
-            return {
-                type: Syntax.ForInStatement,
-                left: left,
-                right: right,
-                body: body,
-                each: false
-            };
</del><ins>+        finishDoWhileStatement: function (body, test) {
+            this.type = Syntax.DoWhileStatement;
+            this.body = body;
+            this.test = test;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createForOfStatement: function (left, right, body) {
-            return {
-                type: Syntax.ForOfStatement,
-                left: left,
-                right: right,
-                body: body
-            };
</del><ins>+        finishEmptyStatement: function () {
+            this.type = Syntax.EmptyStatement;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression) {
-            return {
-                type: Syntax.FunctionDeclaration,
-                id: id,
-                params: params,
-                defaults: defaults,
-                body: body,
-                rest: rest,
-                generator: generator,
-                expression: expression
-            };
</del><ins>+        finishExpressionStatement: function (expression) {
+            this.type = Syntax.ExpressionStatement;
+            this.expression = expression;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createFunctionExpression: function (id, params, defaults, body, rest, generator, expression) {
-            return {
-                type: Syntax.FunctionExpression,
-                id: id,
-                params: params,
-                defaults: defaults,
-                body: body,
-                rest: rest,
-                generator: generator,
-                expression: expression
-            };
</del><ins>+        finishForStatement: function (init, test, update, body) {
+            this.type = Syntax.ForStatement;
+            this.init = init;
+            this.test = test;
+            this.update = update;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createIdentifier: function (name) {
-            return {
-                type: Syntax.Identifier,
-                name: name
-            };
</del><ins>+        finishForOfStatement: function (left, right, body) {
+            this.type = Syntax.ForOfStatement;
+            this.left = left;
+            this.right = right;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createIfStatement: function (test, consequent, alternate) {
-            return {
-                type: Syntax.IfStatement,
-                test: test,
-                consequent: consequent,
-                alternate: alternate
-            };
</del><ins>+        finishForInStatement: function (left, right, body) {
+            this.type = Syntax.ForInStatement;
+            this.left = left;
+            this.right = right;
+            this.body = body;
+            this.each = false;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createLabeledStatement: function (label, body) {
-            return {
-                type: Syntax.LabeledStatement,
-                label: label,
-                body: body
-            };
</del><ins>+        finishFunctionDeclaration: function (id, params, defaults, body, generator) {
+            this.type = Syntax.FunctionDeclaration;
+            this.id = id;
+            this.params = params;
+            this.defaults = defaults;
+            this.body = body;
+            this.generator = generator;
+            this.expression = false;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createLiteral: function (token) {
-            var object = {
-                type: Syntax.Literal,
-                value: token.value,
-                raw: source.slice(token.range[0], token.range[1])
-            };
</del><ins>+        finishFunctionExpression: function (id, params, defaults, body, generator) {
+            this.type = Syntax.FunctionExpression;
+            this.id = id;
+            this.params = params;
+            this.defaults = defaults;
+            this.body = body;
+            this.generator = generator;
+            this.expression = false;
+            this.finish();
+            return this;
+        },
+
+        finishIdentifier: function (name) {
+            this.type = Syntax.Identifier;
+            this.name = name;
+            this.finish();
+            return this;
+        },
+
+        finishIfStatement: function (test, consequent, alternate) {
+            this.type = Syntax.IfStatement;
+            this.test = test;
+            this.consequent = consequent;
+            this.alternate = alternate;
+            this.finish();
+            return this;
+        },
+
+        finishLabeledStatement: function (label, body) {
+            this.type = Syntax.LabeledStatement;
+            this.label = label;
+            this.body = body;
+            this.finish();
+            return this;
+        },
+
+        finishLiteral: function (token) {
+            this.type = Syntax.Literal;
+            this.value = token.value;
+            this.raw = source.slice(token.start, token.end);
</ins><span class="cx">             if (token.regex) {
</span><del>-                object.regex = token.regex;
</del><ins>+                this.regex = token.regex;
</ins><span class="cx">             }
</span><del>-            return object;
</del><ins>+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createMemberExpression: function (accessor, object, property) {
-            return {
-                type: Syntax.MemberExpression,
-                computed: accessor === '[',
-                object: object,
-                property: property
-            };
</del><ins>+        finishMemberExpression: function (accessor, object, property) {
+            this.type = Syntax.MemberExpression;
+            this.computed = accessor === '[';
+            this.object = object;
+            this.property = property;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createNewExpression: function (callee, args) {
-            return {
-                type: Syntax.NewExpression,
-                callee: callee,
-                'arguments': args
-            };
</del><ins>+        finishMetaProperty: function (meta, property) {
+            this.type = Syntax.MetaProperty;
+            this.meta = meta;
+            this.property = property;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createObjectExpression: function (properties) {
-            return {
-                type: Syntax.ObjectExpression,
-                properties: properties
-            };
</del><ins>+        finishNewExpression: function (callee, args) {
+            this.type = Syntax.NewExpression;
+            this.callee = callee;
+            this.arguments = args;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createPostfixExpression: function (operator, argument) {
-            return {
-                type: Syntax.UpdateExpression,
-                operator: operator,
-                argument: argument,
-                prefix: false
-            };
</del><ins>+        finishObjectExpression: function (properties) {
+            this.type = Syntax.ObjectExpression;
+            this.properties = properties;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createProgram: function (body) {
-            return {
-                type: Syntax.Program,
-                body: body
-            };
</del><ins>+        finishObjectPattern: function (properties) {
+            this.type = Syntax.ObjectPattern;
+            this.properties = properties;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createProperty: function (kind, key, value, method, shorthand, computed) {
-            return {
-                type: Syntax.Property,
-                key: key,
-                value: value,
-                kind: kind,
-                method: method,
-                shorthand: shorthand,
-                computed: computed
-            };
</del><ins>+        finishPostfixExpression: function (operator, argument) {
+            this.type = Syntax.UpdateExpression;
+            this.operator = operator;
+            this.argument = argument;
+            this.prefix = false;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createReturnStatement: function (argument) {
-            return {
-                type: Syntax.ReturnStatement,
-                argument: argument
-            };
</del><ins>+        finishProgram: function (body, sourceType) {
+            this.type = Syntax.Program;
+            this.body = body;
+            this.sourceType = sourceType;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createSequenceExpression: function (expressions) {
-            return {
-                type: Syntax.SequenceExpression,
-                expressions: expressions
-            };
</del><ins>+        finishProperty: function (kind, key, computed, value, method, shorthand) {
+            this.type = Syntax.Property;
+            this.key = key;
+            this.computed = computed;
+            this.value = value;
+            this.kind = kind;
+            this.method = method;
+            this.shorthand = shorthand;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createSwitchCase: function (test, consequent) {
-            return {
-                type: Syntax.SwitchCase,
-                test: test,
-                consequent: consequent
-            };
</del><ins>+        finishRestElement: function (argument) {
+            this.type = Syntax.RestElement;
+            this.argument = argument;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createSwitchStatement: function (discriminant, cases) {
-            return {
-                type: Syntax.SwitchStatement,
-                discriminant: discriminant,
-                cases: cases
-            };
</del><ins>+        finishReturnStatement: function (argument) {
+            this.type = Syntax.ReturnStatement;
+            this.argument = argument;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createThisExpression: function () {
-            return {
-                type: Syntax.ThisExpression
-            };
</del><ins>+        finishSequenceExpression: function (expressions) {
+            this.type = Syntax.SequenceExpression;
+            this.expressions = expressions;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createThrowStatement: function (argument) {
-            return {
-                type: Syntax.ThrowStatement,
-                argument: argument
-            };
</del><ins>+        finishSpreadElement: function (argument) {
+            this.type = Syntax.SpreadElement;
+            this.argument = argument;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createTryStatement: function (block, guardedHandlers, handlers, finalizer) {
-            return {
-                type: Syntax.TryStatement,
-                block: block,
-                guardedHandlers: guardedHandlers,
-                handlers: handlers,
-                finalizer: finalizer
-            };
</del><ins>+        finishSwitchCase: function (test, consequent) {
+            this.type = Syntax.SwitchCase;
+            this.test = test;
+            this.consequent = consequent;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createUnaryExpression: function (operator, argument) {
-            if (operator === '++' || operator === '--') {
-                return {
-                    type: Syntax.UpdateExpression,
-                    operator: operator,
-                    argument: argument,
-                    prefix: true
-                };
-            }
-            return {
-                type: Syntax.UnaryExpression,
-                operator: operator,
-                argument: argument,
-                prefix: true
-            };
</del><ins>+        finishSuper: function () {
+            this.type = Syntax.Super;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createVariableDeclaration: function (declarations, kind) {
-            return {
-                type: Syntax.VariableDeclaration,
-                declarations: declarations,
-                kind: kind
-            };
</del><ins>+        finishSwitchStatement: function (discriminant, cases) {
+            this.type = Syntax.SwitchStatement;
+            this.discriminant = discriminant;
+            this.cases = cases;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createVariableDeclarator: function (id, init) {
-            return {
-                type: Syntax.VariableDeclarator,
-                id: id,
-                init: init
-            };
</del><ins>+        finishTaggedTemplateExpression: function (tag, quasi) {
+            this.type = Syntax.TaggedTemplateExpression;
+            this.tag = tag;
+            this.quasi = quasi;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createWhileStatement: function (test, body) {
-            return {
-                type: Syntax.WhileStatement,
-                test: test,
-                body: body
-            };
</del><ins>+        finishTemplateElement: function (value, tail) {
+            this.type = Syntax.TemplateElement;
+            this.value = value;
+            this.tail = tail;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createWithStatement: function (object, body) {
-            return {
-                type: Syntax.WithStatement,
-                object: object,
-                body: body
-            };
</del><ins>+        finishTemplateLiteral: function (quasis, expressions) {
+            this.type = Syntax.TemplateLiteral;
+            this.quasis = quasis;
+            this.expressions = expressions;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createTemplateElement: function (value, tail) {
-            return {
-                type: Syntax.TemplateElement,
-                value: value,
-                tail: tail
-            };
</del><ins>+        finishThisExpression: function () {
+            this.type = Syntax.ThisExpression;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createTemplateLiteral: function (quasis, expressions) {
-            return {
-                type: Syntax.TemplateLiteral,
-                quasis: quasis,
-                expressions: expressions
-            };
</del><ins>+        finishThrowStatement: function (argument) {
+            this.type = Syntax.ThrowStatement;
+            this.argument = argument;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createSpreadElement: function (argument) {
-            return {
-                type: Syntax.SpreadElement,
-                argument: argument
-            };
</del><ins>+        finishTryStatement: function (block, handler, finalizer) {
+            this.type = Syntax.TryStatement;
+            this.block = block;
+            this.guardedHandlers = [];
+            this.handlers = handler ? [handler] : [];
+            this.handler = handler;
+            this.finalizer = finalizer;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createTaggedTemplateExpression: function (tag, quasi) {
-            return {
-                type: Syntax.TaggedTemplateExpression,
-                tag: tag,
-                quasi: quasi
-            };
</del><ins>+        finishUnaryExpression: function (operator, argument) {
+            this.type = (operator === '++' || operator === '--') ? Syntax.UpdateExpression : Syntax.UnaryExpression;
+            this.operator = operator;
+            this.argument = argument;
+            this.prefix = true;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createArrowFunctionExpression: function (params, defaults, body, rest, expression) {
-            return {
-                type: Syntax.ArrowFunctionExpression,
-                id: null,
-                params: params,
-                defaults: defaults,
-                body: body,
-                rest: rest,
-                generator: false,
-                expression: expression
-            };
</del><ins>+        finishVariableDeclaration: function (declarations) {
+            this.type = Syntax.VariableDeclaration;
+            this.declarations = declarations;
+            this.kind = 'var';
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createMethodDefinition: function (propertyType, kind, key, value, computed) {
-            return {
-                type: Syntax.MethodDefinition,
-                key: key,
-                value: value,
-                kind: kind,
-                'static': propertyType === ClassPropertyType.static,
-                computed: computed
-            };
</del><ins>+        finishLexicalDeclaration: function (declarations, kind) {
+            this.type = Syntax.VariableDeclaration;
+            this.declarations = declarations;
+            this.kind = kind;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createClassBody: function (body) {
-            return {
-                type: Syntax.ClassBody,
-                body: body
-            };
</del><ins>+        finishVariableDeclarator: function (id, init) {
+            this.type = Syntax.VariableDeclarator;
+            this.id = id;
+            this.init = init;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createClassExpression: function (id, superClass, body) {
-            return {
-                type: Syntax.ClassExpression,
-                id: id,
-                superClass: superClass,
-                body: body
-            };
</del><ins>+        finishWhileStatement: function (test, body) {
+            this.type = Syntax.WhileStatement;
+            this.test = test;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createClassDeclaration: function (id, superClass, body) {
-            return {
-                type: Syntax.ClassDeclaration,
-                id: id,
-                superClass: superClass,
-                body: body
-            };
</del><ins>+        finishWithStatement: function (object, body) {
+            this.type = Syntax.WithStatement;
+            this.object = object;
+            this.body = body;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createModuleSpecifier: function (token) {
-            return {
-                type: Syntax.ModuleSpecifier,
-                value: token.value,
-                raw: source.slice(token.range[0], token.range[1])
-            };
</del><ins>+        finishExportSpecifier: function (local, exported) {
+            this.type = Syntax.ExportSpecifier;
+            this.exported = exported || local;
+            this.local = local;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createExportSpecifier: function (id, name) {
-            return {
-                type: Syntax.ExportSpecifier,
-                id: id,
-                name: name
-            };
</del><ins>+        finishImportDefaultSpecifier: function (local) {
+            this.type = Syntax.ImportDefaultSpecifier;
+            this.local = local;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createExportBatchSpecifier: function () {
-            return {
-                type: Syntax.ExportBatchSpecifier
-            };
</del><ins>+        finishImportNamespaceSpecifier: function (local) {
+            this.type = Syntax.ImportNamespaceSpecifier;
+            this.local = local;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createImportDefaultSpecifier: function (id) {
-            return {
-                type: Syntax.ImportDefaultSpecifier,
-                id: id
-            };
</del><ins>+        finishExportNamedDeclaration: function (declaration, specifiers, src) {
+            this.type = Syntax.ExportNamedDeclaration;
+            this.declaration = declaration;
+            this.specifiers = specifiers;
+            this.source = src;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createImportNamespaceSpecifier: function (id) {
-            return {
-                type: Syntax.ImportNamespaceSpecifier,
-                id: id
-            };
</del><ins>+        finishExportDefaultDeclaration: function (declaration) {
+            this.type = Syntax.ExportDefaultDeclaration;
+            this.declaration = declaration;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createExportDeclaration: function (isDefault, declaration, specifiers, src) {
-            return {
-                type: Syntax.ExportDeclaration,
-                'default': !!isDefault,
-                declaration: declaration,
-                specifiers: specifiers,
-                source: src
-            };
</del><ins>+        finishExportAllDeclaration: function (src) {
+            this.type = Syntax.ExportAllDeclaration;
+            this.source = src;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createImportSpecifier: function (id, name) {
-            return {
-                type: Syntax.ImportSpecifier,
-                id: id,
-                name: name
-            };
</del><ins>+        finishImportSpecifier: function (local, imported) {
+            this.type = Syntax.ImportSpecifier;
+            this.local = local || imported;
+            this.imported = imported;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createImportDeclaration: function (specifiers, src) {
-            return {
-                type: Syntax.ImportDeclaration,
-                specifiers: specifiers,
-                source: src
-            };
</del><ins>+        finishImportDeclaration: function (specifiers, src) {
+            this.type = Syntax.ImportDeclaration;
+            this.specifiers = specifiers;
+            this.source = src;
+            this.finish();
+            return this;
</ins><span class="cx">         },
</span><span class="cx"> 
</span><del>-        createYieldExpression: function (argument, dlg) {
-            return {
-                type: Syntax.YieldExpression,
-                argument: argument,
-                delegate: dlg
-            };
-        },
-
-        createComprehensionExpression: function (filter, blocks, body) {
-            return {
-                type: Syntax.ComprehensionExpression,
-                filter: filter,
-                blocks: blocks,
-                body: body
-            };
</del><ins>+        finishYieldExpression: function (argument, delegate) {
+            this.type = Syntax.YieldExpression;
+            this.argument = argument;
+            this.delegate = delegate;
+            this.finish();
+            return this;
</ins><span class="cx">         }
</span><del>-
</del><span class="cx">     };
</span><span class="cx"> 
</span><del>-    // Return true if there is a line terminator before the next token.
</del><span class="cx"> 
</span><del>-    function peekLineTerminator() {
-        var pos, line, start, found;
</del><ins>+    function recordError(error) {
+        var e, existing;
</ins><span class="cx"> 
</span><del>-        pos = index;
-        line = lineNumber;
-        start = lineStart;
-        skipComment();
-        found = lineNumber !== line;
-        index = pos;
-        lineNumber = line;
-        lineStart = start;
</del><ins>+        for (e = 0; e &lt; extra.errors.length; e++) {
+            existing = extra.errors[e];
+            // Prevent duplicated error.
+            /* istanbul ignore next */
+            if (existing.index === error.index &amp;&amp; existing.message === error.message) {
+                return;
+            }
+        }
</ins><span class="cx"> 
</span><del>-        return found;
</del><ins>+        extra.errors.push(error);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function constructError(msg, column) {
+        var error = new Error(msg);
+        try {
+            throw error;
+        } catch (base) {
+            /* istanbul ignore else */
+            if (Object.create &amp;&amp; Object.defineProperty) {
+                error = Object.create(base);
+                Object.defineProperty(error, 'column', { value: column });
+            }
+        } finally {
+            return error;
+        }
+    }
+
+    function createError(line, pos, description) {
+        var msg, column, error;
+
+        msg = 'Line ' + line + ': ' + description;
+        column = pos - (scanning ? lineStart : lastLineStart) + 1;
+        error = constructError(msg, column);
+        error.lineNumber = line;
+        error.description = description;
+        error.index = pos;
+        return error;
+    }
+
</ins><span class="cx">     // Throw an exception
</span><span class="cx"> 
</span><del>-    function throwError(token, messageFormat) {
-        var error,
-            args = Array.prototype.slice.call(arguments, 2),
-            msg = messageFormat.replace(
-                /%(\d)/g,
-                function (whole, idx) {
-                    assert(idx &lt; args.length, 'Message reference must be in range');
-                    return args[idx];
-                }
-            );
</del><ins>+    function throwError(messageFormat) {
+        var args, msg;
</ins><span class="cx"> 
</span><del>-        if (typeof token.lineNumber === 'number') {
-            error = new Error('Line ' + token.lineNumber + ': ' + msg);
-            error.index = token.range[0];
-            error.lineNumber = token.lineNumber;
-            error.column = token.range[0] - lineStart + 1;
-        } else {
-            error = new Error('Line ' + lineNumber + ': ' + msg);
-            error.index = index;
-            error.lineNumber = lineNumber;
-            error.column = index - lineStart + 1;
-        }
</del><ins>+        args = Array.prototype.slice.call(arguments, 1);
+        msg = messageFormat.replace(/%(\d)/g,
+            function (whole, idx) {
+                assert(idx &lt; args.length, 'Message reference must be in range');
+                return args[idx];
+            }
+        );
</ins><span class="cx"> 
</span><del>-        error.description = msg;
-        throw error;
</del><ins>+        throw createError(lastLineNumber, lastIndex, msg);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function throwErrorTolerant() {
-        try {
-            throwError.apply(null, arguments);
-        } catch (e) {
-            if (extra.errors) {
-                extra.errors.push(e);
-            } else {
-                throw e;
</del><ins>+    function tolerateError(messageFormat) {
+        var args, msg, error;
+
+        args = Array.prototype.slice.call(arguments, 1);
+        /* istanbul ignore next */
+        msg = messageFormat.replace(/%(\d)/g,
+            function (whole, idx) {
+                assert(idx &lt; args.length, 'Message reference must be in range');
+                return args[idx];
</ins><span class="cx">             }
</span><ins>+        );
+
+        error = createError(lineNumber, lastIndex, msg);
+        if (extra.errors) {
+            recordError(error);
+        } else {
+            throw error;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     // Throw an exception because of the token.
</span><span class="cx"> 
</span><del>-    function throwUnexpected(token) {
-        if (token.type === Token.EOF) {
-            throwError(token, Messages.UnexpectedEOS);
-        }
</del><ins>+    function unexpectedTokenError(token, message) {
+        var value, msg = message || Messages.UnexpectedToken;
</ins><span class="cx"> 
</span><del>-        if (token.type === Token.NumericLiteral) {
-            throwError(token, Messages.UnexpectedNumber);
-        }
</del><ins>+        if (token) {
+            if (!message) {
+                msg = (token.type === Token.EOF) ? Messages.UnexpectedEOS :
+                    (token.type === Token.Identifier) ? Messages.UnexpectedIdentifier :
+                    (token.type === Token.NumericLiteral) ? Messages.UnexpectedNumber :
+                    (token.type === Token.StringLiteral) ? Messages.UnexpectedString :
+                    (token.type === Token.Template) ? Messages.UnexpectedTemplate :
+                    Messages.UnexpectedToken;
</ins><span class="cx"> 
</span><del>-        if (token.type === Token.StringLiteral) {
-            throwError(token, Messages.UnexpectedString);
-        }
</del><ins>+                if (token.type === Token.Keyword) {
+                    if (isFutureReservedWord(token.value)) {
+                        msg = Messages.UnexpectedReserved;
+                    } else if (strict &amp;&amp; isStrictModeReservedWord(token.value)) {
+                        msg = Messages.StrictReservedWord;
+                    }
+                }
+            }
</ins><span class="cx"> 
</span><del>-        if (token.type === Token.Identifier) {
-            throwError(token, Messages.UnexpectedIdentifier);
</del><ins>+            value = (token.type === Token.Template) ? token.value.raw : token.value;
+        } else {
+            value = 'ILLEGAL';
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (token.type === Token.Keyword) {
-            if (isFutureReservedWord(token.value)) {
-                throwError(token, Messages.UnexpectedReserved);
-            } else if (strict &amp;&amp; isStrictModeReservedWord(token.value)) {
-                throwErrorTolerant(token, Messages.StrictReservedWord);
-                return;
-            }
-            throwError(token, Messages.UnexpectedToken, token.value);
-        }
</del><ins>+        msg = msg.replace('%0', value);
</ins><span class="cx"> 
</span><del>-        if (token.type === Token.Template) {
-            throwError(token, Messages.UnexpectedTemplate, token.value.raw);
-        }
</del><ins>+        return (token &amp;&amp; typeof token.lineNumber === 'number') ?
+            createError(token.lineNumber, token.start, msg) :
+            createError(scanning ? lineNumber : lastLineNumber, scanning ? index : lastIndex, msg);
+    }
</ins><span class="cx"> 
</span><del>-        // BooleanLiteral, NullLiteral, or Punctuator.
-        throwError(token, Messages.UnexpectedToken, token.value);
</del><ins>+    function throwUnexpectedToken(token, message) {
+        throw unexpectedTokenError(token, message);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function tolerateUnexpectedToken(token, message) {
+        var error = unexpectedTokenError(token, message);
+        if (extra.errors) {
+            recordError(error);
+        } else {
+            throw error;
+        }
+    }
+
</ins><span class="cx">     // Expect the next token to match the specified punctuator.
</span><span class="cx">     // If not, an exception will be thrown.
</span><span class="cx"> 
</span><span class="cx">     function expect(value) {
</span><span class="cx">         var token = lex();
</span><span class="cx">         if (token.type !== Token.Punctuator || token.value !== value) {
</span><del>-            throwUnexpected(token);
</del><ins>+            throwUnexpectedToken(token);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    /**
+     * @name expectCommaSeparator
+     * @description Quietly expect a comma when in tolerant mode, otherwise delegates
+     * to &lt;code&gt;expect(value)&lt;/code&gt;
+     * @since 2.0
+     */
+    function expectCommaSeparator() {
+        var token;
+
+        if (extra.errors) {
+            token = lookahead;
+            if (token.type === Token.Punctuator &amp;&amp; token.value === ',') {
+                lex();
+            } else if (token.type === Token.Punctuator &amp;&amp; token.value === ';') {
+                lex();
+                tolerateUnexpectedToken(token);
+            } else {
+                tolerateUnexpectedToken(token, Messages.UnexpectedToken);
+            }
+        } else {
+            expect(',');
+        }
+    }
+
</ins><span class="cx">     // Expect the next token to match the specified keyword.
</span><span class="cx">     // If not, an exception will be thrown.
</span><span class="cx"> 
</span><span class="cx">     function expectKeyword(keyword) {
</span><span class="cx">         var token = lex();
</span><span class="cx">         if (token.type !== Token.Keyword || token.value !== keyword) {
</span><del>-            throwUnexpected(token);
</del><ins>+            throwUnexpectedToken(token);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -2419,8 +2551,8 @@
</span><span class="cx">         return lookahead.type === Token.Keyword &amp;&amp; lookahead.value === keyword;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     // Return true if the next token matches the specified contextual keyword
</span><ins>+    // (where an identifier is sometimes a keyword depending on the context)
</ins><span class="cx"> 
</span><span class="cx">     function matchContextualKeyword(keyword) {
</span><span class="cx">         return lookahead.type === Token.Identifier &amp;&amp; lookahead.value === keyword;
</span><span class="lines">@@ -2450,332 +2582,515 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function consumeSemicolon() {
</span><del>-        var line, oldIndex = index, oldLineNumber = lineNumber,
-            oldLineStart = lineStart, oldLookahead = lookahead;
-
-        // Catch the very common case first: immediately a semicolon (char #59).
-        if (source.charCodeAt(index) === 59) {
</del><ins>+        // Catch the very common case first: immediately a semicolon (U+003B).
+        if (source.charCodeAt(startIndex) === 0x3B || match(';')) {
</ins><span class="cx">             lex();
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        line = lineNumber;
-        skipComment();
-        if (lineNumber !== line) {
-            index = oldIndex;
-            lineNumber = oldLineNumber;
-            lineStart = oldLineStart;
-            lookahead = oldLookahead;
</del><ins>+        if (hasLineTerminator) {
</ins><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (match(';')) {
-            lex();
-            return;
-        }
</del><ins>+        // FIXME(ikarienator): this is seemingly an issue in the previous location info convention.
+        lastIndex = startIndex;
+        lastLineNumber = startLineNumber;
+        lastLineStart = startLineStart;
</ins><span class="cx"> 
</span><span class="cx">         if (lookahead.type !== Token.EOF &amp;&amp; !match('}')) {
</span><del>-            throwUnexpected(lookahead);
</del><ins>+            throwUnexpectedToken(lookahead);
</ins><span class="cx">         }
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // Return true if provided expression is LeftHandSideExpression
-
-    function isLeftHandSide(expr) {
-        return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression;
</del><ins>+    // Cover grammar support.
+    //
+    // When an assignment expression position starts with an left parenthesis, the determination of the type
+    // of the syntax is to be deferred arbitrarily long until the end of the parentheses pair (plus a lookahead)
+    // or the first comma. This situation also defers the determination of all the expressions nested in the pair.
+    //
+    // There are three productions that can be parsed in a parentheses pair that needs to be determined
+    // after the outermost pair is closed. They are:
+    //
+    //   1. AssignmentExpression
+    //   2. BindingElements
+    //   3. AssignmentTargets
+    //
+    // In order to avoid exponential backtracking, we use two flags to denote if the production can be
+    // binding element or assignment target.
+    //
+    // The three productions have the relationship:
+    //
+    //   BindingElements âŠ† AssignmentTargets âŠ† AssignmentExpression
+    //
+    // with a single exception that CoverInitializedName when used directly in an Expression, generates
+    // an early error. Therefore, we need the third state, firstCoverInitializedNameError, to track the
+    // first usage of CoverInitializedName and report it when we reached the end of the parentheses pair.
+    //
+    // isolateCoverGrammar function runs the given parser function with a new cover grammar context, and it does not
+    // effect the current flags. This means the production the parser parses is only used as an expression. Therefore
+    // the CoverInitializedName check is conducted.
+    //
+    // inheritCoverGrammar function runs the given parse function with a new cover grammar context, and it propagates
+    // the flags outside of the parser. This means the production the parser parses is used as a part of a potential
+    // pattern. The CoverInitializedName check is deferred.
+    function isolateCoverGrammar(parser) {
+        var oldIsBindingElement = isBindingElement,
+            oldIsAssignmentTarget = isAssignmentTarget,
+            oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
+            result;
+        isBindingElement = true;
+        isAssignmentTarget = true;
+        firstCoverInitializedNameError = null;
+        result = parser();
+        if (firstCoverInitializedNameError !== null) {
+            throwUnexpectedToken(firstCoverInitializedNameError);
+        }
+        isBindingElement = oldIsBindingElement;
+        isAssignmentTarget = oldIsAssignmentTarget;
+        firstCoverInitializedNameError = oldFirstCoverInitializedNameError;
+        return result;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function isAssignableLeftHandSide(expr) {
-        return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern;
</del><ins>+    function inheritCoverGrammar(parser) {
+        var oldIsBindingElement = isBindingElement,
+            oldIsAssignmentTarget = isAssignmentTarget,
+            oldFirstCoverInitializedNameError = firstCoverInitializedNameError,
+            result;
+        isBindingElement = true;
+        isAssignmentTarget = true;
+        firstCoverInitializedNameError = null;
+        result = parser();
+        isBindingElement = isBindingElement &amp;&amp; oldIsBindingElement;
+        isAssignmentTarget = isAssignmentTarget &amp;&amp; oldIsAssignmentTarget;
+        firstCoverInitializedNameError = oldFirstCoverInitializedNameError || firstCoverInitializedNameError;
+        return result;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.1.4 Array Initialiser
</del><ins>+    // ECMA-262 13.3.3 Destructuring Binding Patterns
</ins><span class="cx"> 
</span><del>-    function parseArrayInitialiser() {
-        var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true,
-            marker = markerCreate();
</del><ins>+    function parseArrayPattern(params, kind) {
+        var node = new Node(), elements = [], rest, restNode;
+        expect('[');
</ins><span class="cx"> 
</span><del>-        expect('[');
</del><span class="cx">         while (!match(']')) {
</span><del>-            if (lookahead.value === 'for' &amp;&amp;
-                    lookahead.type === Token.Keyword) {
-                if (!possiblecomprehension) {
-                    throwError({}, Messages.ComprehensionError);
-                }
-                matchKeyword('for');
-                tmp = parseForStatement({ignoreBody: true});
-                tmp.of = tmp.type === Syntax.ForOfStatement;
-                tmp.type = Syntax.ComprehensionBlock;
-                if (tmp.left.kind) { // can't be let or const
-                    throwError({}, Messages.ComprehensionError);
-                }
-                blocks.push(tmp);
-            } else if (lookahead.value === 'if' &amp;&amp;
-                           lookahead.type === Token.Keyword) {
-                if (!possiblecomprehension) {
-                    throwError({}, Messages.ComprehensionError);
-                }
-                expectKeyword('if');
-                expect('(');
-                filter = parseExpression();
-                expect(')');
-            } else if (lookahead.value === ',' &amp;&amp;
-                           lookahead.type === Token.Punctuator) {
-                possiblecomprehension = false; // no longer allowed.
</del><ins>+            if (match(',')) {
</ins><span class="cx">                 lex();
</span><span class="cx">                 elements.push(null);
</span><span class="cx">             } else {
</span><del>-                tmp = parseSpreadOrAssignmentExpression();
-                elements.push(tmp);
-                if (tmp &amp;&amp; tmp.type === Syntax.SpreadElement) {
-                    if (!match(']')) {
-                        throwError({}, Messages.ElementAfterSpreadElement);
-                    }
-                } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) {
-                    expect(','); // this lexes.
-                    possiblecomprehension = false;
</del><ins>+                if (match('...')) {
+                    restNode = new Node();
+                    lex();
+                    params.push(lookahead);
+                    rest = parseVariableIdentifier(params, kind);
+                    elements.push(restNode.finishRestElement(rest));
+                    break;
+                } else {
+                    elements.push(parsePatternWithDefault(params, kind));
</ins><span class="cx">                 }
</span><ins>+                if (!match(']')) {
+                    expect(',');
+                }
</ins><span class="cx">             }
</span><ins>+
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         expect(']');
</span><span class="cx"> 
</span><del>-        if (filter &amp;&amp; !blocks.length) {
-            throwError({}, Messages.ComprehensionRequiresBlock);
-        }
</del><ins>+        return node.finishArrayPattern(elements);
+    }
</ins><span class="cx"> 
</span><del>-        if (blocks.length) {
-            if (elements.length !== 1) {
-                throwError({}, Messages.ComprehensionError);
</del><ins>+    function parsePropertyPattern(params, kind) {
+        var node = new Node(), key, keyToken, computed = match('['), init;
+        if (lookahead.type === Token.Identifier) {
+            keyToken = lookahead;
+            key = parseVariableIdentifier();
+            if (match('=')) {
+                params.push(keyToken);
+                lex();
+                init = parseAssignmentExpression();
+
+                return node.finishProperty(
+                    'init', key, false,
+                    new WrappingNode(keyToken).finishAssignmentPattern(key, init), false, false);
+            } else if (!match(':')) {
+                params.push(keyToken);
+                return node.finishProperty('init', key, false, key, false, true);
</ins><span class="cx">             }
</span><del>-            return markerApply(marker, delegate.createComprehensionExpression(filter, blocks, elements[0]));
</del><ins>+        } else {
+            key = parseObjectPropertyKey(params, kind);
</ins><span class="cx">         }
</span><del>-        return markerApply(marker, delegate.createArrayExpression(elements));
</del><ins>+        expect(':');
+        init = parsePatternWithDefault(params, kind);
+        return node.finishProperty('init', key, computed, init, false, false);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.1.5 Object Initialiser
</del><ins>+    function parseObjectPattern(params, kind) {
+        var node = new Node(), properties = [];
</ins><span class="cx"> 
</span><del>-    function parsePropertyFunction(options) {
-        var previousStrict, previousYieldAllowed, params, defaults, body,
-            marker = markerCreate();
</del><ins>+        expect('{');
</ins><span class="cx"> 
</span><del>-        previousStrict = strict;
-        previousYieldAllowed = state.yieldAllowed;
-        state.yieldAllowed = options.generator;
-        params = options.params || [];
-        defaults = options.defaults || [];
</del><ins>+        while (!match('}')) {
+            properties.push(parsePropertyPattern(params, kind));
+            if (!match('}')) {
+                expect(',');
+            }
+        }
</ins><span class="cx"> 
</span><del>-        body = parseConciseBody();
-        if (options.name &amp;&amp; strict &amp;&amp; isRestrictedWord(params[0].name)) {
-            throwErrorTolerant(options.name, Messages.StrictParamName);
</del><ins>+        lex();
+
+        return node.finishObjectPattern(properties);
+    }
+
+    function parsePattern(params, kind) {
+        if (match('[')) {
+            return parseArrayPattern(params, kind);
+        } else if (match('{')) {
+            return parseObjectPattern(params, kind);
</ins><span class="cx">         }
</span><del>-        strict = previousStrict;
-        state.yieldAllowed = previousYieldAllowed;
</del><ins>+        params.push(lookahead);
+        return parseVariableIdentifier(kind);
+    }
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createFunctionExpression(
-            null,
-            params,
-            defaults,
-            body,
-            options.rest || null,
-            options.generator,
-            body.type !== Syntax.BlockStatement
-        ));
</del><ins>+    function parsePatternWithDefault(params, kind) {
+        var startToken = lookahead, pattern, previousAllowYield, right;
+        pattern = parsePattern(params, kind);
+        if (match('=')) {
+            lex();
+            previousAllowYield = state.allowYield;
+            state.allowYield = true;
+            right = isolateCoverGrammar(parseAssignmentExpression);
+            state.allowYield = previousAllowYield;
+            pattern = new WrappingNode(startToken).finishAssignmentPattern(pattern, right);
+        }
+        return pattern;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // ECMA-262 12.2.5 Array Initializer
</ins><span class="cx"> 
</span><del>-    function parsePropertyMethodFunction(options) {
-        var previousStrict, tmp, method;
</del><ins>+    function parseArrayInitializer() {
+        var elements = [], node = new Node(), restSpread;
</ins><span class="cx"> 
</span><del>-        previousStrict = strict;
-        strict = true;
</del><ins>+        expect('[');
</ins><span class="cx"> 
</span><del>-        tmp = parseParams();
</del><ins>+        while (!match(']')) {
+            if (match(',')) {
+                lex();
+                elements.push(null);
+            } else if (match('...')) {
+                restSpread = new Node();
+                lex();
+                restSpread.finishSpreadElement(inheritCoverGrammar(parseAssignmentExpression));
</ins><span class="cx"> 
</span><del>-        if (tmp.stricted) {
-            throwErrorTolerant(tmp.stricted, tmp.message);
</del><ins>+                if (!match(']')) {
+                    isAssignmentTarget = isBindingElement = false;
+                    expect(',');
+                }
+                elements.push(restSpread);
+            } else {
+                elements.push(inheritCoverGrammar(parseAssignmentExpression));
+
+                if (!match(']')) {
+                    expect(',');
+                }
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        lex();
</ins><span class="cx"> 
</span><del>-        method = parsePropertyFunction({
-            params: tmp.params,
-            defaults: tmp.defaults,
-            rest: tmp.rest,
-            generator: options.generator
-        });
</del><ins>+        return node.finishArrayExpression(elements);
+    }
</ins><span class="cx"> 
</span><ins>+    // ECMA-262 12.2.6 Object Initializer
+
+    function parsePropertyFunction(node, paramInfo, isGenerator) {
+        var previousStrict, body;
+
+        isAssignmentTarget = isBindingElement = false;
+
+        previousStrict = strict;
+        body = isolateCoverGrammar(parseFunctionSourceElements);
+
+        if (strict &amp;&amp; paramInfo.firstRestricted) {
+            tolerateUnexpectedToken(paramInfo.firstRestricted, paramInfo.message);
+        }
+        if (strict &amp;&amp; paramInfo.stricted) {
+            tolerateUnexpectedToken(paramInfo.stricted, paramInfo.message);
+        }
+
</ins><span class="cx">         strict = previousStrict;
</span><ins>+        return node.finishFunctionExpression(null, paramInfo.params, paramInfo.defaults, body, isGenerator);
+    }
</ins><span class="cx"> 
</span><ins>+    function parsePropertyMethodFunction() {
+        var params, method, node = new Node(),
+            previousAllowYield = state.allowYield;
+
+        state.allowYield = false;
+        params = parseParams();
+        state.allowYield = previousAllowYield;
+
+        state.allowYield = false;
+        method = parsePropertyFunction(node, params, false);
+        state.allowYield = previousAllowYield;
+
</ins><span class="cx">         return method;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-
</del><span class="cx">     function parseObjectPropertyKey() {
</span><del>-        var marker = markerCreate(),
-            token = lex(),
-            propertyKey,
-            result;
</del><ins>+        var token, node = new Node(), expr;
</ins><span class="cx"> 
</span><ins>+        token = lex();
+
</ins><span class="cx">         // Note: This function is called only from parseObjectProperty(), where
</span><span class="cx">         // EOF and Punctuator tokens are already filtered out.
</span><span class="cx"> 
</span><del>-        if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) {
</del><ins>+        switch (token.type) {
+        case Token.StringLiteral:
+        case Token.NumericLiteral:
</ins><span class="cx">             if (strict &amp;&amp; token.octal) {
</span><del>-                throwErrorTolerant(token, Messages.StrictOctalLiteral);
</del><ins>+                tolerateUnexpectedToken(token, Messages.StrictOctalLiteral);
</ins><span class="cx">             }
</span><del>-            return markerApply(marker, delegate.createLiteral(token));
</del><ins>+            return node.finishLiteral(token);
+        case Token.Identifier:
+        case Token.BooleanLiteral:
+        case Token.NullLiteral:
+        case Token.Keyword:
+            return node.finishIdentifier(token.value);
+        case Token.Punctuator:
+            if (token.value === '[') {
+                expr = isolateCoverGrammar(parseAssignmentExpression);
+                expect(']');
+                return expr;
+            }
+            break;
</ins><span class="cx">         }
</span><ins>+        throwUnexpectedToken(token);
+    }
</ins><span class="cx"> 
</span><del>-        if (token.type === Token.Punctuator &amp;&amp; token.value === '[') {
-            // For computed properties we should skip the [ and ], and
-            // capture in marker only the assignment expression itself.
-            marker = markerCreate();
-            propertyKey = parseAssignmentExpression();
-            result = markerApply(marker, propertyKey);
-            expect(']');
-            return result;
</del><ins>+    function lookaheadPropertyName() {
+        switch (lookahead.type) {
+        case Token.Identifier:
+        case Token.StringLiteral:
+        case Token.BooleanLiteral:
+        case Token.NullLiteral:
+        case Token.NumericLiteral:
+        case Token.Keyword:
+            return true;
+        case Token.Punctuator:
+            return lookahead.value === '[';
</ins><span class="cx">         }
</span><del>-
-        return markerApply(marker, delegate.createIdentifier(token.value));
</del><ins>+        return false;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseObjectProperty() {
-        var token, key, id, param, computed,
-            marker = markerCreate();
</del><ins>+    // This function is to try to parse a MethodDefinition as defined in 14.3. But in the case of object literals,
+    // it might be called at a position where there is in fact a short hand identifier pattern or a data property.
+    // This can only be determined after we consumed up to the left parentheses.
+    //
+    // In order to avoid back tracking, it returns `null` if the position is not a MethodDefinition and the caller
+    // is responsible to visit other options.
+    function tryParseMethodDefinition(token, key, computed, node) {
+        var value, options, methodNode, params,
+            previousAllowYield = state.allowYield;
</ins><span class="cx"> 
</span><del>-        token = lookahead;
-        computed = (token.value === '[' &amp;&amp; token.type === Token.Punctuator);
</del><ins>+        if (token.type === Token.Identifier) {
+            // check for `get` and `set`;
</ins><span class="cx"> 
</span><del>-        if (token.type === Token.Identifier || computed) {
-
-            id = parseObjectPropertyKey();
-
-            // Property Assignment: Getter and Setter.
-
-            if (token.value === 'get' &amp;&amp; !(match(':') || match('('))) {
-                computed = (lookahead.value === '[');
</del><ins>+            if (token.value === 'get' &amp;&amp; lookaheadPropertyName()) {
+                computed = match('[');
</ins><span class="cx">                 key = parseObjectPropertyKey();
</span><ins>+                methodNode = new Node();
</ins><span class="cx">                 expect('(');
</span><span class="cx">                 expect(')');
</span><del>-                return markerApply(marker, delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false, computed));
-            }
-            if (token.value === 'set' &amp;&amp; !(match(':') || match('('))) {
-                computed = (lookahead.value === '[');
</del><ins>+
+                state.allowYield = false;
+                value = parsePropertyFunction(methodNode, {
+                    params: [],
+                    defaults: [],
+                    stricted: null,
+                    firstRestricted: null,
+                    message: null
+                }, false);
+                state.allowYield = previousAllowYield;
+
+                return node.finishProperty('get', key, computed, value, false, false);
+            } else if (token.value === 'set' &amp;&amp; lookaheadPropertyName()) {
+                computed = match('[');
</ins><span class="cx">                 key = parseObjectPropertyKey();
</span><ins>+                methodNode = new Node();
</ins><span class="cx">                 expect('(');
</span><del>-                token = lookahead;
-                param = [ parseVariableIdentifier() ];
</del><ins>+
+                options = {
+                    params: [],
+                    defaultCount: 0,
+                    defaults: [],
+                    firstRestricted: null,
+                    paramSet: {}
+                };
+                if (match(')')) {
+                    tolerateUnexpectedToken(lookahead);
+                } else {
+                    state.allowYield = false;
+                    parseParam(options);
+                    state.allowYield = previousAllowYield;
+                    if (options.defaultCount === 0) {
+                        options.defaults = [];
+                    }
+                }
</ins><span class="cx">                 expect(')');
</span><del>-                return markerApply(marker, delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false, computed));
</del><ins>+
+                state.allowYield = false;
+                value = parsePropertyFunction(methodNode, options, false);
+                state.allowYield = previousAllowYield;
+
+                return node.finishProperty('set', key, computed, value, false, false);
</ins><span class="cx">             }
</span><del>-            if (match(':')) {
-                lex();
-                return markerApply(marker, delegate.createProperty('init', id, parseAssignmentExpression(), false, false, computed));
-            }
-            if (match('(')) {
-                return markerApply(marker, delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false, computed));
-            }
-            if (computed) {
-                // Computed properties can only be used with full notation.
-                throwUnexpected(lookahead);
-            }
-            return markerApply(marker, delegate.createProperty('init', id, id, false, true, false));
</del><ins>+        } else if (token.type === Token.Punctuator &amp;&amp; token.value === '*' &amp;&amp; lookaheadPropertyName()) {
+            computed = match('[');
+            key = parseObjectPropertyKey();
+            methodNode = new Node();
+
+            state.allowYield = true;
+            params = parseParams();
+            state.allowYield = previousAllowYield;
+
+            state.allowYield = false;
+            value = parsePropertyFunction(methodNode, params, true);
+            state.allowYield = previousAllowYield;
+
+            return node.finishProperty('init', key, computed, value, true, false);
</ins><span class="cx">         }
</span><del>-        if (token.type === Token.EOF || token.type === Token.Punctuator) {
-            if (!match('*')) {
-                throwUnexpected(token);
-            }
</del><ins>+
+        if (key &amp;&amp; match('(')) {
+            value = parsePropertyMethodFunction();
+            return node.finishProperty('init', key, computed, value, true, false);
+        }
+
+        // Not a MethodDefinition.
+        return null;
+    }
+
+    function parseObjectProperty(hasProto) {
+        var token = lookahead, node = new Node(), computed, key, maybeMethod, proto, value;
+
+        computed = match('[');
+        if (match('*')) {
</ins><span class="cx">             lex();
</span><ins>+        } else {
+            key = parseObjectPropertyKey();
+        }
+        maybeMethod = tryParseMethodDefinition(token, key, computed, node);
+        if (maybeMethod) {
+            return maybeMethod;
+        }
</ins><span class="cx"> 
</span><del>-            computed = (lookahead.type === Token.Punctuator &amp;&amp; lookahead.value === '[');
</del><ins>+        if (!key) {
+            throwUnexpectedToken(lookahead);
+        }
</ins><span class="cx"> 
</span><del>-            id = parseObjectPropertyKey();
-
-            if (!match('(')) {
-                throwUnexpected(lex());
</del><ins>+        // Check for duplicated __proto__
+        if (!computed) {
+            proto = (key.type === Syntax.Identifier &amp;&amp; key.name === '__proto__') ||
+                (key.type === Syntax.Literal &amp;&amp; key.value === '__proto__');
+            if (hasProto.value &amp;&amp; proto) {
+                tolerateError(Messages.DuplicateProtoProperty);
</ins><span class="cx">             }
</span><ins>+            hasProto.value |= proto;
+        }
</ins><span class="cx"> 
</span><del>-            return markerApply(marker, delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false, computed));
-        }
-        key = parseObjectPropertyKey();
</del><span class="cx">         if (match(':')) {
</span><span class="cx">             lex();
</span><del>-            return markerApply(marker, delegate.createProperty('init', key, parseAssignmentExpression(), false, false, false));
</del><ins>+            value = inheritCoverGrammar(parseAssignmentExpression);
+            return node.finishProperty('init', key, computed, value, false, false);
</ins><span class="cx">         }
</span><del>-        if (match('(')) {
-            return markerApply(marker, delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false, false));
</del><ins>+
+        if (token.type === Token.Identifier) {
+            if (match('=')) {
+                firstCoverInitializedNameError = lookahead;
+                lex();
+                value = isolateCoverGrammar(parseAssignmentExpression);
+                return node.finishProperty('init', key, computed,
+                    new WrappingNode(token).finishAssignmentPattern(key, value), false, true);
+            }
+            return node.finishProperty('init', key, computed, key, false, true);
</ins><span class="cx">         }
</span><del>-        throwUnexpected(lex());
-    }
</del><span class="cx"> 
</span><del>-    function getFieldName(key) {
-        var toString = String;
-        if (key.type === Syntax.Identifier) {
-            return key.name;
-        }
-        return toString(key.value);
</del><ins>+        throwUnexpectedToken(lookahead);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseObjectInitialiser() {
-        var properties = [], property, name, kind, storedKind, map = new StringMap(),
-            marker = markerCreate();
</del><ins>+    function parseObjectInitializer() {
+        var properties = [], hasProto = {value: false}, node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         expect('{');
</span><span class="cx"> 
</span><span class="cx">         while (!match('}')) {
</span><del>-            property = parseObjectProperty();
</del><ins>+            properties.push(parseObjectProperty(hasProto));
</ins><span class="cx"> 
</span><del>-            if (!property.computed) {
-                name = getFieldName(property.key);
-                kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set;
-
-                if (map.has(name)) {
-                    storedKind = map.get(name);
-                    if (storedKind === PropertyKind.Data) {
-                        if (strict &amp;&amp; kind === PropertyKind.Data) {
-                            throwErrorTolerant({}, Messages.StrictDuplicateProperty);
-                        } else if (kind !== PropertyKind.Data) {
-                            throwErrorTolerant({}, Messages.AccessorDataProperty);
-                        }
-                    } else {
-                        if (kind === PropertyKind.Data) {
-                            throwErrorTolerant({}, Messages.AccessorDataProperty);
-                        } else if (storedKind &amp; kind) {
-                            throwErrorTolerant({}, Messages.AccessorGetSet);
-                        }
-                    }
-                    map.set(name, storedKind | kind);
-                } else {
-                    map.set(name, kind);
-                }
-            }
-
-            properties.push(property);
-
</del><span class="cx">             if (!match('}')) {
</span><del>-                expect(',');
</del><ins>+                expectCommaSeparator();
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         expect('}');
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createObjectExpression(properties));
</del><ins>+        return node.finishObjectExpression(properties);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function reinterpretExpressionAsPattern(expr) {
+        var i;
+        switch (expr.type) {
+        case Syntax.Identifier:
+        case Syntax.MemberExpression:
+        case Syntax.RestElement:
+        case Syntax.AssignmentPattern:
+            break;
+        case Syntax.SpreadElement:
+            expr.type = Syntax.RestElement;
+            reinterpretExpressionAsPattern(expr.argument);
+            break;
+        case Syntax.ArrayExpression:
+            expr.type = Syntax.ArrayPattern;
+            for (i = 0; i &lt; expr.elements.length; i++) {
+                if (expr.elements[i] !== null) {
+                    reinterpretExpressionAsPattern(expr.elements[i]);
+                }
+            }
+            break;
+        case Syntax.ObjectExpression:
+            expr.type = Syntax.ObjectPattern;
+            for (i = 0; i &lt; expr.properties.length; i++) {
+                reinterpretExpressionAsPattern(expr.properties[i].value);
+            }
+            break;
+        case Syntax.AssignmentExpression:
+            expr.type = Syntax.AssignmentPattern;
+            reinterpretExpressionAsPattern(expr.left);
+            break;
+        default:
+            // Allow other node type for tolerant parsing.
+            break;
+        }
+    }
+
+    // ECMA-262 12.2.9 Template Literals
+
</ins><span class="cx">     function parseTemplateElement(option) {
</span><del>-        var marker = markerCreate(),
-            token = scanTemplateElement(option);
-        if (strict &amp;&amp; token.octal) {
-            throwError(token, Messages.StrictOctalLiteral);
</del><ins>+        var node, token;
+
+        if (lookahead.type !== Token.Template || (option.head &amp;&amp; !lookahead.head)) {
+            throwUnexpectedToken();
</ins><span class="cx">         }
</span><del>-        return markerApply(marker, delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail));
</del><ins>+
+        node = new Node();
+        token = lex();
+
+        return node.finishTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseTemplateLiteral() {
</span><del>-        var quasi, quasis, expressions, marker = markerCreate();
</del><ins>+        var quasi, quasis, expressions, node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         quasi = parseTemplateElement({ head: true });
</span><del>-        quasis = [ quasi ];
</del><ins>+        quasis = [quasi];
</ins><span class="cx">         expressions = [];
</span><span class="cx"> 
</span><span class="cx">         while (!quasi.tail) {
</span><span class="lines">@@ -2784,127 +3099,211 @@
</span><span class="cx">             quasis.push(quasi);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createTemplateLiteral(quasis, expressions));
</del><ins>+        return node.finishTemplateLiteral(quasis, expressions);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.1.6 The Grouping Operator
</del><ins>+    // ECMA-262 12.2.10 The Grouping Operator
</ins><span class="cx"> 
</span><span class="cx">     function parseGroupExpression() {
</span><del>-        var expr;
</del><ins>+        var expr, expressions, startToken, i, params = [];
</ins><span class="cx"> 
</span><span class="cx">         expect('(');
</span><span class="cx"> 
</span><del>-        ++state.parenthesizedCount;
</del><ins>+        if (match(')')) {
+            lex();
+            if (!match('=&gt;')) {
+                expect('=&gt;');
+            }
+            return {
+                type: PlaceHolders.ArrowParameterPlaceHolder,
+                params: [],
+                rawParams: []
+            };
+        }
</ins><span class="cx"> 
</span><del>-        expr = parseExpression();
</del><ins>+        startToken = lookahead;
+        if (match('...')) {
+            expr = parseRestElement(params);
+            expect(')');
+            if (!match('=&gt;')) {
+                expect('=&gt;');
+            }
+            return {
+                type: PlaceHolders.ArrowParameterPlaceHolder,
+                params: [expr]
+            };
+        }
</ins><span class="cx"> 
</span><del>-        expect(')');
</del><ins>+        isBindingElement = true;
+        expr = inheritCoverGrammar(parseAssignmentExpression);
</ins><span class="cx"> 
</span><del>-        return expr;
-    }
</del><ins>+        if (match(',')) {
+            isAssignmentTarget = false;
+            expressions = [expr];
</ins><span class="cx"> 
</span><ins>+            while (startIndex &lt; length) {
+                if (!match(',')) {
+                    break;
+                }
+                lex();
</ins><span class="cx"> 
</span><del>-    // 11.1 Primary Expressions
</del><ins>+                if (match('...')) {
+                    if (!isBindingElement) {
+                        throwUnexpectedToken(lookahead);
+                    }
+                    expressions.push(parseRestElement(params));
+                    expect(')');
+                    if (!match('=&gt;')) {
+                        expect('=&gt;');
+                    }
+                    isBindingElement = false;
+                    for (i = 0; i &lt; expressions.length; i++) {
+                        reinterpretExpressionAsPattern(expressions[i]);
+                    }
+                    return {
+                        type: PlaceHolders.ArrowParameterPlaceHolder,
+                        params: expressions
+                    };
+                }
</ins><span class="cx"> 
</span><del>-    function parsePrimaryExpression() {
-        var marker, type, token, expr;
</del><ins>+                expressions.push(inheritCoverGrammar(parseAssignmentExpression));
+            }
</ins><span class="cx"> 
</span><del>-        type = lookahead.type;
-
-        if (type === Token.Identifier) {
-            marker = markerCreate();
-            return markerApply(marker, delegate.createIdentifier(lex().value));
</del><ins>+            expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (type === Token.StringLiteral || type === Token.NumericLiteral) {
-            if (strict &amp;&amp; lookahead.octal) {
-                throwErrorTolerant(lookahead, Messages.StrictOctalLiteral);
-            }
-            marker = markerCreate();
-            return markerApply(marker, delegate.createLiteral(lex()));
-        }
</del><span class="cx"> 
</span><del>-        if (type === Token.Keyword) {
-            if (matchKeyword('this')) {
-                marker = markerCreate();
-                lex();
-                return markerApply(marker, delegate.createThisExpression());
-            }
</del><ins>+        expect(')');
</ins><span class="cx"> 
</span><del>-            if (matchKeyword('function')) {
-                return parseFunctionExpression();
</del><ins>+        if (match('=&gt;')) {
+            if (expr.type === Syntax.Identifier &amp;&amp; expr.name === 'yield') {
+                return {
+                    type: PlaceHolders.ArrowParameterPlaceHolder,
+                    params: [expr]
+                };
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (matchKeyword('class')) {
-                return parseClassExpression();
</del><ins>+            if (!isBindingElement) {
+                throwUnexpectedToken(lookahead);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (matchKeyword('super')) {
-                marker = markerCreate();
-                lex();
-                return markerApply(marker, delegate.createIdentifier('super'));
</del><ins>+            if (expr.type === Syntax.SequenceExpression) {
+                for (i = 0; i &lt; expr.expressions.length; i++) {
+                    reinterpretExpressionAsPattern(expr.expressions[i]);
+                }
+            } else {
+                reinterpretExpressionAsPattern(expr);
</ins><span class="cx">             }
</span><del>-        }
</del><span class="cx"> 
</span><del>-        if (type === Token.BooleanLiteral) {
-            marker = markerCreate();
-            token = lex();
-            token.value = (token.value === 'true');
-            return markerApply(marker, delegate.createLiteral(token));
</del><ins>+            expr = {
+                type: PlaceHolders.ArrowParameterPlaceHolder,
+                params: expr.type === Syntax.SequenceExpression ? expr.expressions : [expr]
+            };
</ins><span class="cx">         }
</span><ins>+        isBindingElement = false;
+        return expr;
+    }
</ins><span class="cx"> 
</span><del>-        if (type === Token.NullLiteral) {
-            marker = markerCreate();
-            token = lex();
-            token.value = null;
-            return markerApply(marker, delegate.createLiteral(token));
</del><ins>+
+    // ECMA-262 12.2 Primary Expressions
+
+    function parsePrimaryExpression() {
+        var type, token, expr, node;
+
+        if (match('(')) {
+            isBindingElement = false;
+            return inheritCoverGrammar(parseGroupExpression);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (match('[')) {
</span><del>-            return parseArrayInitialiser();
</del><ins>+            return inheritCoverGrammar(parseArrayInitializer);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (match('{')) {
</span><del>-            return parseObjectInitialiser();
</del><ins>+            return inheritCoverGrammar(parseObjectInitializer);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (match('(')) {
-            return parseGroupExpression();
-        }
</del><ins>+        type = lookahead.type;
+        node = new Node();
</ins><span class="cx"> 
</span><del>-        if (match('/') || match('/=')) {
-            marker = markerCreate();
-            expr = delegate.createLiteral(scanRegExp());
-            peek();
-            return markerApply(marker, expr);
-        }
</del><ins>+        if (type === Token.Identifier) {
+            if (state.sourceType === 'module' &amp;&amp; lookahead.value === 'await') {
+                tolerateUnexpectedToken(lookahead);
+            }
+            expr = node.finishIdentifier(lex().value);
+        } else if (type === Token.StringLiteral || type === Token.NumericLiteral) {
+            isAssignmentTarget = isBindingElement = false;
+            if (strict &amp;&amp; lookahead.octal) {
+                tolerateUnexpectedToken(lookahead, Messages.StrictOctalLiteral);
+            }
+            expr = node.finishLiteral(lex());
+        } else if (type === Token.Keyword) {
+            if (!strict &amp;&amp; state.allowYield &amp;&amp; matchKeyword('yield')) {
+                return parseNonComputedProperty();
+            }
+            isAssignmentTarget = isBindingElement = false;
+            if (matchKeyword('function')) {
+                return parseFunctionExpression();
+            }
+            if (matchKeyword('this')) {
+                lex();
+                return node.finishThisExpression();
+            }
+            if (matchKeyword('class')) {
+                return parseClassExpression();
+            }
+            throwUnexpectedToken(lex());
+        } else if (type === Token.BooleanLiteral) {
+            isAssignmentTarget = isBindingElement = false;
+            token = lex();
+            token.value = (token.value === 'true');
+            expr = node.finishLiteral(token);
+        } else if (type === Token.NullLiteral) {
+            isAssignmentTarget = isBindingElement = false;
+            token = lex();
+            token.value = null;
+            expr = node.finishLiteral(token);
+        } else if (match('/') || match('/=')) {
+            isAssignmentTarget = isBindingElement = false;
+            index = startIndex;
</ins><span class="cx"> 
</span><del>-        if (type === Token.Template) {
-            return parseTemplateLiteral();
</del><ins>+            if (typeof extra.tokens !== 'undefined') {
+                token = collectRegex();
+            } else {
+                token = scanRegExp();
+            }
+            lex();
+            expr = node.finishLiteral(token);
+        } else if (type === Token.Template) {
+            expr = parseTemplateLiteral();
+        } else {
+            throwUnexpectedToken(lex());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        throwUnexpected(lex());
</del><ins>+        return expr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.2 Left-Hand-Side Expressions
</del><ins>+    // ECMA-262 12.3 Left-Hand-Side Expressions
</ins><span class="cx"> 
</span><span class="cx">     function parseArguments() {
</span><del>-        var args = [], arg;
</del><ins>+        var args = [], expr;
</ins><span class="cx"> 
</span><span class="cx">         expect('(');
</span><span class="cx"> 
</span><span class="cx">         if (!match(')')) {
</span><del>-            while (index &lt; length) {
-                arg = parseSpreadOrAssignmentExpression();
-                args.push(arg);
-
</del><ins>+            while (startIndex &lt; length) {
+                if (match('...')) {
+                    expr = new Node();
+                    lex();
+                    expr.finishSpreadElement(isolateCoverGrammar(parseAssignmentExpression));
+                } else {
+                    expr = isolateCoverGrammar(parseAssignmentExpression);
+                }
+                args.push(expr);
</ins><span class="cx">                 if (match(')')) {
</span><span class="cx">                     break;
</span><del>-                } else if (arg.type === Syntax.SpreadElement) {
-                    throwError({}, Messages.ElementAfterSpreadElement);
</del><span class="cx">                 }
</span><del>-
-                expect(',');
</del><ins>+                expectCommaSeparator();
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -2913,24 +3312,16 @@
</span><span class="cx">         return args;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseSpreadOrAssignmentExpression() {
-        if (match('...')) {
-            var marker = markerCreate();
-            lex();
-            return markerApply(marker, delegate.createSpreadElement(parseAssignmentExpression()));
-        }
-        return parseAssignmentExpression();
-    }
-
</del><span class="cx">     function parseNonComputedProperty() {
</span><del>-        var marker = markerCreate(),
-            token = lex();
</del><ins>+        var token, node = new Node();
</ins><span class="cx"> 
</span><ins>+        token = lex();
+
</ins><span class="cx">         if (!isIdentifierName(token)) {
</span><del>-            throwUnexpected(token);
</del><ins>+            throwUnexpectedToken(token);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createIdentifier(token.value));
</del><ins>+        return node.finishIdentifier(token.value);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseNonComputedMember() {
</span><span class="lines">@@ -2944,134 +3335,195 @@
</span><span class="cx"> 
</span><span class="cx">         expect('[');
</span><span class="cx"> 
</span><del>-        expr = parseExpression();
</del><ins>+        expr = isolateCoverGrammar(parseExpression);
</ins><span class="cx"> 
</span><span class="cx">         expect(']');
</span><span class="cx"> 
</span><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // ECMA-262 12.3.3 The new Operator
+
</ins><span class="cx">     function parseNewExpression() {
</span><del>-        var callee, args, marker = markerCreate();
</del><ins>+        var callee, args, node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('new');
</span><del>-        callee = parseLeftHandSideExpression();
</del><ins>+
+        if (match('.')) {
+            lex();
+            if (lookahead.type === Token.Identifier &amp;&amp; lookahead.value === 'target') {
+                if (state.inFunctionBody) {
+                    lex();
+                    return node.finishMetaProperty('new', 'target');
+                }
+            }
+            throwUnexpectedToken(lookahead);
+        }
+
+        callee = isolateCoverGrammar(parseLeftHandSideExpression);
</ins><span class="cx">         args = match('(') ? parseArguments() : [];
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createNewExpression(callee, args));
</del><ins>+        isAssignmentTarget = isBindingElement = false;
+
+        return node.finishNewExpression(callee, args);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // ECMA-262 12.3.4 Function Calls
+
</ins><span class="cx">     function parseLeftHandSideExpressionAllowCall() {
</span><del>-        var expr, args, marker = markerCreate();
</del><ins>+        var quasi, expr, args, property, startToken, previousAllowIn = state.allowIn;
</ins><span class="cx"> 
</span><del>-        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
</del><ins>+        startToken = lookahead;
+        state.allowIn = true;
</ins><span class="cx"> 
</span><del>-        while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) {
-            if (match('(')) {
</del><ins>+        if (matchKeyword('super') &amp;&amp; state.inFunctionBody) {
+            expr = new Node();
+            lex();
+            expr = expr.finishSuper();
+            if (!match('(') &amp;&amp; !match('.') &amp;&amp; !match('[')) {
+                throwUnexpectedToken(lookahead);
+            }
+        } else {
+            expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
+        }
+
+        for (;;) {
+            if (match('.')) {
+                isBindingElement = false;
+                isAssignmentTarget = true;
+                property = parseNonComputedMember();
+                expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+            } else if (match('(')) {
+                isBindingElement = false;
+                isAssignmentTarget = false;
</ins><span class="cx">                 args = parseArguments();
</span><del>-                expr = markerApply(marker, delegate.createCallExpression(expr, args));
</del><ins>+                expr = new WrappingNode(startToken).finishCallExpression(expr, args);
</ins><span class="cx">             } else if (match('[')) {
</span><del>-                expr = markerApply(marker, delegate.createMemberExpression('[', expr, parseComputedMember()));
-            } else if (match('.')) {
-                expr = markerApply(marker, delegate.createMemberExpression('.', expr, parseNonComputedMember()));
</del><ins>+                isBindingElement = false;
+                isAssignmentTarget = true;
+                property = parseComputedMember();
+                expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
+            } else if (lookahead.type === Token.Template &amp;&amp; lookahead.head) {
+                quasi = parseTemplateLiteral();
+                expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
</ins><span class="cx">             } else {
</span><del>-                expr = markerApply(marker, delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
</del><ins>+                break;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><ins>+        state.allowIn = previousAllowIn;
</ins><span class="cx"> 
</span><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // ECMA-262 12.3 Left-Hand-Side Expressions
+
</ins><span class="cx">     function parseLeftHandSideExpression() {
</span><del>-        var expr, marker = markerCreate();
</del><ins>+        var quasi, expr, property, startToken;
+        assert(state.allowIn, 'callee of new expression always allow in keyword.');
</ins><span class="cx"> 
</span><del>-        expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression();
</del><ins>+        startToken = lookahead;
</ins><span class="cx"> 
</span><del>-        while (match('.') || match('[') || lookahead.type === Token.Template) {
</del><ins>+        if (matchKeyword('super') &amp;&amp; state.inFunctionBody) {
+            expr = new Node();
+            lex();
+            expr = expr.finishSuper();
+            if (!match('[') &amp;&amp; !match('.')) {
+                throwUnexpectedToken(lookahead);
+            }
+        } else {
+            expr = inheritCoverGrammar(matchKeyword('new') ? parseNewExpression : parsePrimaryExpression);
+        }
+
+        for (;;) {
</ins><span class="cx">             if (match('[')) {
</span><del>-                expr = markerApply(marker, delegate.createMemberExpression('[', expr, parseComputedMember()));
</del><ins>+                isBindingElement = false;
+                isAssignmentTarget = true;
+                property = parseComputedMember();
+                expr = new WrappingNode(startToken).finishMemberExpression('[', expr, property);
</ins><span class="cx">             } else if (match('.')) {
</span><del>-                expr = markerApply(marker, delegate.createMemberExpression('.', expr, parseNonComputedMember()));
</del><ins>+                isBindingElement = false;
+                isAssignmentTarget = true;
+                property = parseNonComputedMember();
+                expr = new WrappingNode(startToken).finishMemberExpression('.', expr, property);
+            } else if (lookahead.type === Token.Template &amp;&amp; lookahead.head) {
+                quasi = parseTemplateLiteral();
+                expr = new WrappingNode(startToken).finishTaggedTemplateExpression(expr, quasi);
</ins><span class="cx">             } else {
</span><del>-                expr = markerApply(marker, delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()));
</del><ins>+                break;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.3 Postfix Expressions
</del><ins>+    // ECMA-262 12.4 Postfix Expressions
</ins><span class="cx"> 
</span><span class="cx">     function parsePostfixExpression() {
</span><del>-        var marker = markerCreate(),
-            expr = parseLeftHandSideExpressionAllowCall(),
-            token;
</del><ins>+        var expr, token, startToken = lookahead;
</ins><span class="cx"> 
</span><del>-        if (lookahead.type !== Token.Punctuator) {
-            return expr;
-        }
</del><ins>+        expr = inheritCoverGrammar(parseLeftHandSideExpressionAllowCall);
</ins><span class="cx"> 
</span><del>-        if ((match('++') || match('--')) &amp;&amp; !peekLineTerminator()) {
-            // 11.3.1, 11.3.2
-            if (strict &amp;&amp; expr.type === Syntax.Identifier &amp;&amp; isRestrictedWord(expr.name)) {
-                throwErrorTolerant({}, Messages.StrictLHSPostfix);
-            }
</del><ins>+        if (!hasLineTerminator &amp;&amp; lookahead.type === Token.Punctuator) {
+            if (match('++') || match('--')) {
+                // ECMA-262 11.3.1, 11.3.2
+                if (strict &amp;&amp; expr.type === Syntax.Identifier &amp;&amp; isRestrictedWord(expr.name)) {
+                    tolerateError(Messages.StrictLHSPostfix);
+                }
</ins><span class="cx"> 
</span><del>-            if (!isLeftHandSide(expr)) {
-                throwError({}, Messages.InvalidLHSInAssignment);
</del><ins>+                if (!isAssignmentTarget) {
+                    tolerateError(Messages.InvalidLHSInAssignment);
+                }
+
+                isAssignmentTarget = isBindingElement = false;
+
+                token = lex();
+                expr = new WrappingNode(startToken).finishPostfixExpression(token.value, expr);
</ins><span class="cx">             }
</span><del>-
-            token = lex();
-            expr = markerApply(marker, delegate.createPostfixExpression(token.value, expr));
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.4 Unary Operators
</del><ins>+    // ECMA-262 12.5 Unary Operators
</ins><span class="cx"> 
</span><span class="cx">     function parseUnaryExpression() {
</span><del>-        var marker, token, expr;
</del><ins>+        var token, expr, startToken;
</ins><span class="cx"> 
</span><span class="cx">         if (lookahead.type !== Token.Punctuator &amp;&amp; lookahead.type !== Token.Keyword) {
</span><del>-            return parsePostfixExpression();
-        }
-
-        if (match('++') || match('--')) {
-            marker = markerCreate();
</del><ins>+            expr = parsePostfixExpression();
+        } else if (match('++') || match('--')) {
+            startToken = lookahead;
</ins><span class="cx">             token = lex();
</span><del>-            expr = parseUnaryExpression();
-            // 11.4.4, 11.4.5
</del><ins>+            expr = inheritCoverGrammar(parseUnaryExpression);
+            // ECMA-262 11.4.4, 11.4.5
</ins><span class="cx">             if (strict &amp;&amp; expr.type === Syntax.Identifier &amp;&amp; isRestrictedWord(expr.name)) {
</span><del>-                throwErrorTolerant({}, Messages.StrictLHSPrefix);
</del><ins>+                tolerateError(Messages.StrictLHSPrefix);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (!isLeftHandSide(expr)) {
-                throwError({}, Messages.InvalidLHSInAssignment);
</del><ins>+            if (!isAssignmentTarget) {
+                tolerateError(Messages.InvalidLHSInAssignment);
</ins><span class="cx">             }
</span><del>-
-            return markerApply(marker, delegate.createUnaryExpression(token.value, expr));
-        }
-
-        if (match('+') || match('-') || match('~') || match('!')) {
-            marker = markerCreate();
</del><ins>+            expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+            isAssignmentTarget = isBindingElement = false;
+        } else if (match('+') || match('-') || match('~') || match('!')) {
+            startToken = lookahead;
</ins><span class="cx">             token = lex();
</span><del>-            expr = parseUnaryExpression();
-            return markerApply(marker, delegate.createUnaryExpression(token.value, expr));
-        }
-
-        if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
-            marker = markerCreate();
</del><ins>+            expr = inheritCoverGrammar(parseUnaryExpression);
+            expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
+            isAssignmentTarget = isBindingElement = false;
+        } else if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) {
+            startToken = lookahead;
</ins><span class="cx">             token = lex();
</span><del>-            expr = parseUnaryExpression();
-            expr = markerApply(marker, delegate.createUnaryExpression(token.value, expr));
</del><ins>+            expr = inheritCoverGrammar(parseUnaryExpression);
+            expr = new WrappingNode(startToken).finishUnaryExpression(token.value, expr);
</ins><span class="cx">             if (strict &amp;&amp; expr.operator === 'delete' &amp;&amp; expr.argument.type === Syntax.Identifier) {
</span><del>-                throwErrorTolerant({}, Messages.StrictDelete);
</del><ins>+                tolerateError(Messages.StrictDelete);
</ins><span class="cx">             }
</span><del>-            return expr;
</del><ins>+            isAssignmentTarget = isBindingElement = false;
+        } else {
+            expr = parsePostfixExpression();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return parsePostfixExpression();
</del><ins>+        return expr;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function binaryPrecedence(token, allowIn) {
</span><span class="lines">@@ -3145,219 +3597,189 @@
</span><span class="cx">         return prec;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.5 Multiplicative Operators
-    // 11.6 Additive Operators
-    // 11.7 Bitwise Shift Operators
-    // 11.8 Relational Operators
-    // 11.9 Equality Operators
-    // 11.10 Binary Bitwise Operators
-    // 11.11 Binary Logical Operators
</del><ins>+    // ECMA-262 12.6 Multiplicative Operators
+    // ECMA-262 12.7 Additive Operators
+    // ECMA-262 12.8 Bitwise Shift Operators
+    // ECMA-262 12.9 Relational Operators
+    // ECMA-262 12.10 Equality Operators
+    // ECMA-262 12.11 Binary Bitwise Operators
+    // ECMA-262 12.12 Binary Logical Operators
</ins><span class="cx"> 
</span><span class="cx">     function parseBinaryExpression() {
</span><del>-        var expr, token, prec, previousAllowIn, stack, right, operator, left, i,
-            marker, markers;
</del><ins>+        var marker, markers, expr, token, prec, stack, right, operator, left, i;
</ins><span class="cx"> 
</span><del>-        previousAllowIn = state.allowIn;
-        state.allowIn = true;
</del><ins>+        marker = lookahead;
+        left = inheritCoverGrammar(parseUnaryExpression);
</ins><span class="cx"> 
</span><del>-        marker = markerCreate();
-        left = parseUnaryExpression();
-
</del><span class="cx">         token = lookahead;
</span><del>-        prec = binaryPrecedence(token, previousAllowIn);
</del><ins>+        prec = binaryPrecedence(token, state.allowIn);
</ins><span class="cx">         if (prec === 0) {
</span><span class="cx">             return left;
</span><span class="cx">         }
</span><ins>+        isAssignmentTarget = isBindingElement = false;
</ins><span class="cx">         token.prec = prec;
</span><span class="cx">         lex();
</span><span class="cx"> 
</span><del>-        markers = [marker, markerCreate()];
-        right = parseUnaryExpression();
</del><ins>+        markers = [marker, lookahead];
+        right = isolateCoverGrammar(parseUnaryExpression);
</ins><span class="cx"> 
</span><span class="cx">         stack = [left, token, right];
</span><span class="cx"> 
</span><del>-        while ((prec = binaryPrecedence(lookahead, previousAllowIn)) &gt; 0) {
</del><ins>+        while ((prec = binaryPrecedence(lookahead, state.allowIn)) &gt; 0) {
</ins><span class="cx"> 
</span><span class="cx">             // Reduce: make a binary expression from the three topmost entries.
</span><span class="cx">             while ((stack.length &gt; 2) &amp;&amp; (prec &lt;= stack[stack.length - 2].prec)) {
</span><span class="cx">                 right = stack.pop();
</span><span class="cx">                 operator = stack.pop().value;
</span><span class="cx">                 left = stack.pop();
</span><del>-                expr = delegate.createBinaryExpression(operator, left, right);
</del><span class="cx">                 markers.pop();
</span><del>-                marker = markers.pop();
-                markerApply(marker, expr);
</del><ins>+                expr = new WrappingNode(markers[markers.length - 1]).finishBinaryExpression(operator, left, right);
</ins><span class="cx">                 stack.push(expr);
</span><del>-                markers.push(marker);
</del><span class="cx">             }
</span><span class="cx"> 
</span><span class="cx">             // Shift.
</span><span class="cx">             token = lex();
</span><span class="cx">             token.prec = prec;
</span><span class="cx">             stack.push(token);
</span><del>-            markers.push(markerCreate());
-            expr = parseUnaryExpression();
</del><ins>+            markers.push(lookahead);
+            expr = isolateCoverGrammar(parseUnaryExpression);
</ins><span class="cx">             stack.push(expr);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        state.allowIn = previousAllowIn;
-
</del><span class="cx">         // Final reduce to clean-up the stack.
</span><span class="cx">         i = stack.length - 1;
</span><span class="cx">         expr = stack[i];
</span><span class="cx">         markers.pop();
</span><span class="cx">         while (i &gt; 1) {
</span><del>-            expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
</del><ins>+            expr = new WrappingNode(markers.pop()).finishBinaryExpression(stack[i - 1].value, stack[i - 2], expr);
</ins><span class="cx">             i -= 2;
</span><del>-            marker = markers.pop();
-            markerApply(marker, expr);
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-    // 11.12 Conditional Operator
</del><ins>+    // ECMA-262 12.13 Conditional Operator
</ins><span class="cx"> 
</span><span class="cx">     function parseConditionalExpression() {
</span><del>-        var expr, previousAllowIn, consequent, alternate, marker = markerCreate();
-        expr = parseBinaryExpression();
</del><ins>+        var expr, previousAllowIn, consequent, alternate, startToken;
</ins><span class="cx"> 
</span><ins>+        startToken = lookahead;
+
+        expr = inheritCoverGrammar(parseBinaryExpression);
</ins><span class="cx">         if (match('?')) {
</span><span class="cx">             lex();
</span><span class="cx">             previousAllowIn = state.allowIn;
</span><span class="cx">             state.allowIn = true;
</span><del>-            consequent = parseAssignmentExpression();
</del><ins>+            consequent = isolateCoverGrammar(parseAssignmentExpression);
</ins><span class="cx">             state.allowIn = previousAllowIn;
</span><span class="cx">             expect(':');
</span><del>-            alternate = parseAssignmentExpression();
</del><ins>+            alternate = isolateCoverGrammar(parseAssignmentExpression);
</ins><span class="cx"> 
</span><del>-            expr = markerApply(marker, delegate.createConditionalExpression(expr, consequent, alternate));
</del><ins>+            expr = new WrappingNode(startToken).finishConditionalExpression(expr, consequent, alternate);
+            isAssignmentTarget = isBindingElement = false;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.13 Assignment Operators
</del><ins>+    // ECMA-262 14.2 Arrow Function Definitions
</ins><span class="cx"> 
</span><del>-    // 12.14.5 AssignmentPattern
-
-    function reinterpretAsAssignmentBindingPattern(expr) {
-        var i, len, property, element;
-
-        if (expr.type === Syntax.ObjectExpression) {
-            expr.type = Syntax.ObjectPattern;
-            for (i = 0, len = expr.properties.length; i &lt; len; i += 1) {
-                property = expr.properties[i];
-                if (property.kind !== 'init') {
-                    throwError({}, Messages.InvalidLHSInAssignment);
-                }
-                reinterpretAsAssignmentBindingPattern(property.value);
-            }
-        } else if (expr.type === Syntax.ArrayExpression) {
-            expr.type = Syntax.ArrayPattern;
-            for (i = 0, len = expr.elements.length; i &lt; len; i += 1) {
-                element = expr.elements[i];
-                /* istanbul ignore else */
-                if (element) {
-                    reinterpretAsAssignmentBindingPattern(element);
-                }
-            }
-        } else if (expr.type === Syntax.Identifier) {
-            if (isRestrictedWord(expr.name)) {
-                throwError({}, Messages.InvalidLHSInAssignment);
-            }
-        } else if (expr.type === Syntax.SpreadElement) {
-            reinterpretAsAssignmentBindingPattern(expr.argument);
-            if (expr.argument.type === Syntax.ObjectPattern) {
-                throwError({}, Messages.ObjectPatternAsSpread);
-            }
-        } else {
-            /* istanbul ignore else */
-            if (expr.type !== Syntax.MemberExpression &amp;&amp; expr.type !== Syntax.CallExpression &amp;&amp; expr.type !== Syntax.NewExpression) {
-                throwError({}, Messages.InvalidLHSInAssignment);
-            }
</del><ins>+    function parseConciseBody() {
+        if (match('{')) {
+            return parseFunctionSourceElements();
</ins><span class="cx">         }
</span><ins>+        return isolateCoverGrammar(parseAssignmentExpression);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 13.2.3 BindingPattern
-
-    function reinterpretAsDestructuredParameter(options, expr) {
-        var i, len, property, element;
-
-        if (expr.type === Syntax.ObjectExpression) {
-            expr.type = Syntax.ObjectPattern;
-            for (i = 0, len = expr.properties.length; i &lt; len; i += 1) {
-                property = expr.properties[i];
-                if (property.kind !== 'init') {
-                    throwError({}, Messages.InvalidLHSInFormalsList);
</del><ins>+    function checkPatternParam(options, param) {
+        var i;
+        switch (param.type) {
+        case Syntax.Identifier:
+            validateParam(options, param, param.name);
+            break;
+        case Syntax.RestElement:
+            checkPatternParam(options, param.argument);
+            break;
+        case Syntax.AssignmentPattern:
+            checkPatternParam(options, param.left);
+            break;
+        case Syntax.ArrayPattern:
+            for (i = 0; i &lt; param.elements.length; i++) {
+                if (param.elements[i] !== null) {
+                    checkPatternParam(options, param.elements[i]);
</ins><span class="cx">                 }
</span><del>-                reinterpretAsDestructuredParameter(options, property.value);
</del><span class="cx">             }
</span><del>-        } else if (expr.type === Syntax.ArrayExpression) {
-            expr.type = Syntax.ArrayPattern;
-            for (i = 0, len = expr.elements.length; i &lt; len; i += 1) {
-                element = expr.elements[i];
-                if (element) {
-                    reinterpretAsDestructuredParameter(options, element);
-                }
</del><ins>+            break;
+        case Syntax.YieldExpression:
+            break;
+        default:
+            assert(param.type === Syntax.ObjectPattern, 'Invalid type');
+            for (i = 0; i &lt; param.properties.length; i++) {
+                checkPatternParam(options, param.properties[i].value);
</ins><span class="cx">             }
</span><del>-        } else if (expr.type === Syntax.Identifier) {
-            validateParam(options, expr, expr.name);
-        } else if (expr.type === Syntax.SpreadElement) {
-            // BindingRestElement only allows BindingIdentifier
-            if (expr.argument.type !== Syntax.Identifier) {
-                throwError({}, Messages.InvalidLHSInFormalsList);
-            }
-            validateParam(options, expr.argument, expr.argument.name);
-        } else {
-            throwError({}, Messages.InvalidLHSInFormalsList);
</del><ins>+            break;
</ins><span class="cx">         }
</span><span class="cx">     }
</span><ins>+    function reinterpretAsCoverFormalsList(expr) {
+        var i, len, param, params, defaults, defaultCount, options, token;
</ins><span class="cx"> 
</span><del>-    function reinterpretAsCoverFormalsList(expressions) {
-        var i, len, param, params, defaults, defaultCount, options, rest;
-
-        params = [];
</del><span class="cx">         defaults = [];
</span><span class="cx">         defaultCount = 0;
</span><del>-        rest = null;
</del><ins>+        params = [expr];
+
+        switch (expr.type) {
+        case Syntax.Identifier:
+            break;
+        case PlaceHolders.ArrowParameterPlaceHolder:
+            params = expr.params;
+            break;
+        default:
+            return null;
+        }
+
</ins><span class="cx">         options = {
</span><del>-            paramSet: new StringMap()
</del><ins>+            paramSet: {}
</ins><span class="cx">         };
</span><span class="cx"> 
</span><del>-        for (i = 0, len = expressions.length; i &lt; len; i += 1) {
-            param = expressions[i];
-            if (param.type === Syntax.Identifier) {
-                params.push(param);
-                defaults.push(null);
-                validateParam(options, param, param.name);
-            } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) {
-                reinterpretAsDestructuredParameter(options, param);
-                params.push(param);
-                defaults.push(null);
-            } else if (param.type === Syntax.SpreadElement) {
-                assert(i === len - 1, 'It is guaranteed that SpreadElement is last element by parseExpression');
-                if (param.argument.type !== Syntax.Identifier) {
-                    throwError({}, Messages.InvalidLHSInFormalsList);
</del><ins>+        for (i = 0, len = params.length; i &lt; len; i += 1) {
+            param = params[i];
+            switch (param.type) {
+            case Syntax.AssignmentPattern:
+                params[i] = param.left;
+                if (param.right.type === Syntax.YieldExpression) {
+                    if (param.right.argument) {
+                        throwUnexpectedToken(lookahead);
+                    }
+                    param.right.type = Syntax.Identifier;
+                    param.right.name = 'yield';
+                    delete param.right.argument;
+                    delete param.right.delegate;
</ins><span class="cx">                 }
</span><del>-                reinterpretAsDestructuredParameter(options, param.argument);
-                rest = param.argument;
-            } else if (param.type === Syntax.AssignmentExpression) {
-                params.push(param.left);
</del><span class="cx">                 defaults.push(param.right);
</span><span class="cx">                 ++defaultCount;
</span><del>-                validateParam(options, param.left, param.left.name);
-            } else {
-                return null;
</del><ins>+                checkPatternParam(options, param.left);
+                break;
+            default:
+                checkPatternParam(options, param);
+                params[i] = param;
+                defaults.push(null);
+                break;
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (strict || !state.allowYield) {
+            for (i = 0, len = params.length; i &lt; len; i += 1) {
+                param = params[i];
+                if (param.type === Syntax.YieldExpression) {
+                    throwUnexpectedToken(lookahead);
+                }
+            }
+        }
+
</ins><span class="cx">         if (options.message === Messages.StrictParamDupe) {
</span><del>-            throwError(
-                strict ? options.stricted : options.firstRestricted,
-                options.message
-            );
</del><ins>+            token = strict ? options.stricted : options.firstRestricted;
+            throwUnexpectedToken(token, options.message);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (defaultCount === 0) {
</span><span class="lines">@@ -3367,171 +3789,189 @@
</span><span class="cx">         return {
</span><span class="cx">             params: params,
</span><span class="cx">             defaults: defaults,
</span><del>-            rest: rest,
</del><span class="cx">             stricted: options.stricted,
</span><span class="cx">             firstRestricted: options.firstRestricted,
</span><span class="cx">             message: options.message
</span><span class="cx">         };
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseArrowFunctionExpression(options, marker) {
-        var previousStrict, previousYieldAllowed, body;
</del><ins>+    function parseArrowFunctionExpression(options, node) {
+        var previousStrict, previousAllowYield, body;
</ins><span class="cx"> 
</span><ins>+        if (hasLineTerminator) {
+            tolerateUnexpectedToken(lookahead);
+        }
</ins><span class="cx">         expect('=&gt;');
</span><span class="cx"> 
</span><span class="cx">         previousStrict = strict;
</span><del>-        previousYieldAllowed = state.yieldAllowed;
-        state.yieldAllowed = false;
</del><ins>+        previousAllowYield = state.allowYield;
+        state.allowYield = true;
+
</ins><span class="cx">         body = parseConciseBody();
</span><span class="cx"> 
</span><span class="cx">         if (strict &amp;&amp; options.firstRestricted) {
</span><del>-            throwError(options.firstRestricted, options.message);
</del><ins>+            throwUnexpectedToken(options.firstRestricted, options.message);
</ins><span class="cx">         }
</span><span class="cx">         if (strict &amp;&amp; options.stricted) {
</span><del>-            throwErrorTolerant(options.stricted, options.message);
</del><ins>+            tolerateUnexpectedToken(options.stricted, options.message);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         strict = previousStrict;
</span><del>-        state.yieldAllowed = previousYieldAllowed;
</del><ins>+        state.allowYield = previousAllowYield;
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createArrowFunctionExpression(
-            options.params,
-            options.defaults,
-            body,
-            options.rest,
-            body.type !== Syntax.BlockStatement
-        ));
</del><ins>+        return node.finishArrowFunctionExpression(options.params, options.defaults, body, body.type !== Syntax.BlockStatement);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseAssignmentExpression() {
-        var marker, expr, token, params, oldParenthesizedCount,
-            startsWithParen = false;
</del><ins>+    // ECMA-262 14.4 Yield expression
</ins><span class="cx"> 
</span><del>-        // Note that 'yield' is treated as a keyword in strict mode, but a
-        // contextual keyword (identifier) in non-strict mode, so we need
-        // to use matchKeyword and matchContextualKeyword appropriately.
-        if ((state.yieldAllowed &amp;&amp; matchContextualKeyword('yield')) || (strict &amp;&amp; matchKeyword('yield'))) {
-            return parseYieldExpression();
-        }
</del><ins>+    function parseYieldExpression() {
+        var argument, expr, delegate, previousAllowYield;
</ins><span class="cx"> 
</span><del>-        oldParenthesizedCount = state.parenthesizedCount;
</del><ins>+        argument = null;
+        expr = new Node();
</ins><span class="cx"> 
</span><del>-        marker = markerCreate();
</del><ins>+        expectKeyword('yield');
</ins><span class="cx"> 
</span><del>-        if (match('(')) {
-            token = lookahead2();
-            if ((token.type === Token.Punctuator &amp;&amp; token.value === ')') || token.value === '...') {
-                params = parseParams();
-                if (!match('=&gt;')) {
-                    throwUnexpected(lex());
</del><ins>+        if (!hasLineTerminator) {
+            previousAllowYield = state.allowYield;
+            state.allowYield = false;
+            delegate = match('*');
+            if (delegate) {
+                lex();
+                argument = parseAssignmentExpression();
+            } else {
+                if (!match(';') &amp;&amp; !match('}') &amp;&amp; !match(')') &amp;&amp; lookahead.type !== Token.EOF) {
+                    argument = parseAssignmentExpression();
</ins><span class="cx">                 }
</span><del>-                return parseArrowFunctionExpression(params, marker);
</del><span class="cx">             }
</span><del>-            startsWithParen = true;
</del><ins>+            state.allowYield = previousAllowYield;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        return expr.finishYieldExpression(argument, delegate);
+    }
+
+    // ECMA-262 12.14 Assignment Operators
+
+    function parseAssignmentExpression() {
+        var token, expr, right, list, startToken;
+
+        startToken = lookahead;
</ins><span class="cx">         token = lookahead;
</span><ins>+
+        if (!state.allowYield &amp;&amp; matchKeyword('yield')) {
+            return parseYieldExpression();
+        }
+
</ins><span class="cx">         expr = parseConditionalExpression();
</span><span class="cx"> 
</span><del>-        if (match('=&gt;') &amp;&amp;
-                (state.parenthesizedCount === oldParenthesizedCount ||
-                state.parenthesizedCount === (oldParenthesizedCount + 1))) {
-            if (expr.type === Syntax.Identifier) {
-                params = reinterpretAsCoverFormalsList([ expr ]);
-            } else if (expr.type === Syntax.AssignmentExpression ||
-                    expr.type === Syntax.ArrayExpression ||
-                    expr.type === Syntax.ObjectExpression) {
-                if (!startsWithParen) {
-                    throwUnexpected(lex());
-                }
-                params = reinterpretAsCoverFormalsList([ expr ]);
-            } else if (expr.type === Syntax.SequenceExpression) {
-                params = reinterpretAsCoverFormalsList(expr.expressions);
</del><ins>+        if (expr.type === PlaceHolders.ArrowParameterPlaceHolder || match('=&gt;')) {
+            isAssignmentTarget = isBindingElement = false;
+            list = reinterpretAsCoverFormalsList(expr);
+
+            if (list) {
+                firstCoverInitializedNameError = null;
+                return parseArrowFunctionExpression(list, new WrappingNode(startToken));
</ins><span class="cx">             }
</span><del>-            if (params) {
-                return parseArrowFunctionExpression(params, marker);
-            }
</del><ins>+
+            return expr;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (matchAssign()) {
</span><del>-            // 11.13.1
-            if (strict &amp;&amp; expr.type === Syntax.Identifier &amp;&amp; isRestrictedWord(expr.name)) {
-                throwErrorTolerant(token, Messages.StrictLHSAssignment);
</del><ins>+            if (!isAssignmentTarget) {
+                tolerateError(Messages.InvalidLHSInAssignment);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            // ES.next draf 11.13 Runtime Semantics step 1
-            if (match('=') &amp;&amp; (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) {
-                reinterpretAsAssignmentBindingPattern(expr);
-            } else if (!isLeftHandSide(expr)) {
-                throwError({}, Messages.InvalidLHSInAssignment);
</del><ins>+            // ECMA-262 12.1.1
+            if (strict &amp;&amp; expr.type === Syntax.Identifier) {
+                if (isRestrictedWord(expr.name)) {
+                    tolerateUnexpectedToken(token, Messages.StrictLHSAssignment);
+                }
+                if (isStrictModeReservedWord(expr.name)) {
+                    tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+                }
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            expr = markerApply(marker, delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()));
</del><ins>+            if (!match('=')) {
+                isAssignmentTarget = isBindingElement = false;
+            } else {
+                reinterpretExpressionAsPattern(expr);
+            }
+
+            token = lex();
+            right = isolateCoverGrammar(parseAssignmentExpression);
+            expr = new WrappingNode(startToken).finishAssignmentExpression(token.value, expr, right);
+            firstCoverInitializedNameError = null;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return expr;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 11.14 Comma Operator
</del><ins>+    // ECMA-262 12.15 Comma Operator
</ins><span class="cx"> 
</span><span class="cx">     function parseExpression() {
</span><del>-        var marker, expr, expressions, sequence, spreadFound;
</del><ins>+        var expr, startToken = lookahead, expressions;
</ins><span class="cx"> 
</span><del>-        marker = markerCreate();
-        expr = parseAssignmentExpression();
-        expressions = [ expr ];
</del><ins>+        expr = isolateCoverGrammar(parseAssignmentExpression);
</ins><span class="cx"> 
</span><span class="cx">         if (match(',')) {
</span><del>-            while (index &lt; length) {
</del><ins>+            expressions = [expr];
+
+            while (startIndex &lt; length) {
</ins><span class="cx">                 if (!match(',')) {
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><del>-
</del><span class="cx">                 lex();
</span><del>-                expr = parseSpreadOrAssignmentExpression();
-                expressions.push(expr);
-
-                if (expr.type === Syntax.SpreadElement) {
-                    spreadFound = true;
-                    if (!match(')')) {
-                        throwError({}, Messages.ElementAfterSpreadElement);
-                    }
-                    break;
-                }
</del><ins>+                expressions.push(isolateCoverGrammar(parseAssignmentExpression));
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            sequence = markerApply(marker, delegate.createSequenceExpression(expressions));
</del><ins>+            expr = new WrappingNode(startToken).finishSequenceExpression(expressions);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (spreadFound &amp;&amp; lookahead2().value !== '=&gt;') {
-            throwError({}, Messages.IllegalSpread);
</del><ins>+        return expr;
+    }
+
+    // ECMA-262 13.2 Block
+
+    function parseStatementListItem() {
+        if (lookahead.type === Token.Keyword) {
+            switch (lookahead.value) {
+            case 'export':
+                if (state.sourceType !== 'module') {
+                    tolerateUnexpectedToken(lookahead, Messages.IllegalExportDeclaration);
+                }
+                return parseExportDeclaration();
+            case 'import':
+                if (state.sourceType !== 'module') {
+                    tolerateUnexpectedToken(lookahead, Messages.IllegalImportDeclaration);
+                }
+                return parseImportDeclaration();
+            case 'const':
+            case 'let':
+                return parseLexicalDeclaration({inFor: false});
+            case 'function':
+                return parseFunctionDeclaration(new Node());
+            case 'class':
+                return parseClassDeclaration();
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return sequence || expr;
</del><ins>+        return parseStatement();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.1 Block
-
</del><span class="cx">     function parseStatementList() {
</span><del>-        var list = [],
-            statement;
-
-        while (index &lt; length) {
</del><ins>+        var list = [];
+        while (startIndex &lt; length) {
</ins><span class="cx">             if (match('}')) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            statement = parseSourceElement();
-            if (typeof statement === 'undefined') {
-                break;
-            }
-            list.push(statement);
</del><ins>+            list.push(parseStatementListItem());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         return list;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseBlock() {
</span><del>-        var block, marker = markerCreate();
</del><ins>+        var block, node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         expect('{');
</span><span class="cx"> 
</span><span class="lines">@@ -3539,369 +3979,178 @@
</span><span class="cx"> 
</span><span class="cx">         expect('}');
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createBlockStatement(block));
</del><ins>+        return node.finishBlockStatement(block);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.2 Variable Statement
</del><ins>+    // ECMA-262 13.3.2 Variable Statement
</ins><span class="cx"> 
</span><del>-    function parseVariableIdentifier() {
-        var marker = markerCreate(),
-            token = lex();
</del><ins>+    function parseVariableIdentifier(kind) {
+        var token, node = new Node();
</ins><span class="cx"> 
</span><del>-        if (token.type !== Token.Identifier) {
-            throwUnexpected(token);
</del><ins>+        token = lex();
+
+        if (token.type === Token.Keyword &amp;&amp; token.value === 'yield') {
+            if (strict) {
+                tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+            } if (!state.allowYield) {
+                throwUnexpectedToken(token);
+            }
+        } else if (token.type !== Token.Identifier) {
+            if (strict &amp;&amp; token.type === Token.Keyword &amp;&amp; isStrictModeReservedWord(token.value)) {
+                tolerateUnexpectedToken(token, Messages.StrictReservedWord);
+            } else {
+                if (strict || token.value !== 'let' || kind !== 'var') {
+                    throwUnexpectedToken(token);
+                }
+            }
+        } else if (state.sourceType === 'module' &amp;&amp; token.type === Token.Identifier &amp;&amp; token.value === 'await') {
+            tolerateUnexpectedToken(token);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createIdentifier(token.value));
</del><ins>+        return node.finishIdentifier(token.value);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseVariableDeclaration(kind) {
-        var id,
-            marker = markerCreate(),
-            init = null;
-        if (match('{')) {
-            id = parseObjectInitialiser();
-            reinterpretAsAssignmentBindingPattern(id);
-        } else if (match('[')) {
-            id = parseArrayInitialiser();
-            reinterpretAsAssignmentBindingPattern(id);
-        } else {
-            /* istanbul ignore next */
-            id = state.allowKeyword ? parseNonComputedProperty() : parseVariableIdentifier();
-            // 12.2.1
-            if (strict &amp;&amp; isRestrictedWord(id.name)) {
-                throwErrorTolerant({}, Messages.StrictVarName);
-            }
</del><ins>+    function parseVariableDeclaration(options) {
+        var init = null, id, node = new Node(), params = [];
+
+        id = parsePattern(params, 'var');
+
+        // ECMA-262 12.2.1
+        if (strict &amp;&amp; isRestrictedWord(id.name)) {
+            tolerateError(Messages.StrictVarName);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (kind === 'const') {
-            if (!match('=')) {
-                throwError({}, Messages.NoUnintializedConst);
-            }
</del><ins>+        if (match('=')) {
+            lex();
+            init = isolateCoverGrammar(parseAssignmentExpression);
+        } else if (id.type !== Syntax.Identifier &amp;&amp; !options.inFor) {
</ins><span class="cx">             expect('=');
</span><del>-            init = parseAssignmentExpression();
-        } else if (match('=')) {
-            lex();
-            init = parseAssignmentExpression();
</del><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createVariableDeclarator(id, init));
</del><ins>+        return node.finishVariableDeclarator(id, init);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseVariableDeclarationList(kind) {
</del><ins>+    function parseVariableDeclarationList(options) {
</ins><span class="cx">         var list = [];
</span><span class="cx"> 
</span><span class="cx">         do {
</span><del>-            list.push(parseVariableDeclaration(kind));
</del><ins>+            list.push(parseVariableDeclaration({ inFor: options.inFor }));
</ins><span class="cx">             if (!match(',')) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             lex();
</span><del>-        } while (index &lt; length);
</del><ins>+        } while (startIndex &lt; length);
</ins><span class="cx"> 
</span><span class="cx">         return list;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseVariableStatement() {
-        var declarations, marker = markerCreate();
</del><ins>+    function parseVariableStatement(node) {
+        var declarations;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('var');
</span><span class="cx"> 
</span><del>-        declarations = parseVariableDeclarationList();
</del><ins>+        declarations = parseVariableDeclarationList({ inFor: false });
</ins><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createVariableDeclaration(declarations, 'var'));
</del><ins>+        return node.finishVariableDeclaration(declarations);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // kind may be `const` or `let`
-    // Both are experimental and not in the specification yet.
-    // see http://wiki.ecmascript.org/doku.php?id=harmony:const
-    // and http://wiki.ecmascript.org/doku.php?id=harmony:let
-    function parseConstLetDeclaration(kind) {
-        var declarations, marker = markerCreate();
</del><ins>+    // ECMA-262 13.3.1 Let and Const Declarations
</ins><span class="cx"> 
</span><del>-        expectKeyword(kind);
</del><ins>+    function parseLexicalBinding(kind, options) {
+        var init = null, id, node = new Node(), params = [];
</ins><span class="cx"> 
</span><del>-        declarations = parseVariableDeclarationList(kind);
</del><ins>+        id = parsePattern(params, kind);
</ins><span class="cx"> 
</span><del>-        consumeSemicolon();
-
-        return markerApply(marker, delegate.createVariableDeclaration(declarations, kind));
-    }
-
-    // people.mozilla.org/~jorendorff/es6-draft.html
-
-    function parseModuleSpecifier() {
-        var marker = markerCreate(),
-            specifier;
-
-        if (lookahead.type !== Token.StringLiteral) {
-            throwError({}, Messages.InvalidModuleSpecifier);
</del><ins>+        // ECMA-262 12.2.1
+        if (strict &amp;&amp; id.type === Syntax.Identifier &amp;&amp; isRestrictedWord(id.name)) {
+            tolerateError(Messages.StrictVarName);
</ins><span class="cx">         }
</span><del>-        specifier = delegate.createModuleSpecifier(lookahead);
-        lex();
-        return markerApply(marker, specifier);
-    }
</del><span class="cx"> 
</span><del>-    function parseExportBatchSpecifier() {
-        var marker = markerCreate();
-        expect('*');
-        return markerApply(marker, delegate.createExportBatchSpecifier());
-    }
-
-    function parseExportSpecifier() {
-        var id, name = null, marker = markerCreate(), from;
-        if (matchKeyword('default')) {
-            lex();
-            id = markerApply(marker, delegate.createIdentifier('default'));
-            // export {default} from &quot;something&quot;;
-        } else {
-            id = parseVariableIdentifier();
</del><ins>+        if (kind === 'const') {
+            if (!matchKeyword('in') &amp;&amp; !matchContextualKeyword('of')) {
+                expect('=');
+                init = isolateCoverGrammar(parseAssignmentExpression);
+            }
+        } else if ((!options.inFor &amp;&amp; id.type !== Syntax.Identifier) || match('=')) {
+            expect('=');
+            init = isolateCoverGrammar(parseAssignmentExpression);
</ins><span class="cx">         }
</span><del>-        if (matchContextualKeyword('as')) {
-            lex();
-            name = parseNonComputedProperty();
-        }
</del><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createExportSpecifier(id, name));
</del><ins>+        return node.finishVariableDeclarator(id, init);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseExportDeclaration() {
-        var backtrackToken, id, declaration = null,
-            isExportFromIdentifier,
-            src = null, specifiers = [],
-            marker = markerCreate();
</del><ins>+    function parseBindingList(kind, options) {
+        var list = [];
</ins><span class="cx"> 
</span><del>-        function rewind(token) {
-            index = token.range[0];
-            lineNumber = token.lineNumber;
-            lineStart = token.lineStart;
-            lookahead = token;
-        }
-
-        expectKeyword('export');
-
-        if (matchKeyword('default')) {
-            // covers:
-            // export default ...
-            lex();
-            if (matchKeyword('function') || matchKeyword('class')) {
-                backtrackToken = lookahead;
-                lex();
-                if (isIdentifierName(lookahead)) {
-                    // covers:
-                    // export default function foo () {}
-                    // export default class foo {}
-                    id = parseNonComputedProperty();
-                    rewind(backtrackToken);
-                    return markerApply(marker, delegate.createExportDeclaration(true, parseSourceElement(), [id], null));
-                }
-                // covers:
-                // export default function () {}
-                // export default class {}
-                rewind(backtrackToken);
-                switch (lookahead.value) {
-                case 'class':
-                    return markerApply(marker, delegate.createExportDeclaration(true, parseClassExpression(), [], null));
-                case 'function':
-                    return markerApply(marker, delegate.createExportDeclaration(true, parseFunctionExpression(), [], null));
-                }
</del><ins>+        do {
+            list.push(parseLexicalBinding(kind, options));
+            if (!match(',')) {
+                break;
</ins><span class="cx">             }
</span><del>-
-            if (matchContextualKeyword('from')) {
-                throwError({}, Messages.UnexpectedToken, lookahead.value);
-            }
-
-            // covers:
-            // export default {};
-            // export default [];
-            if (match('{')) {
-                declaration = parseObjectInitialiser();
-            } else if (match('[')) {
-                declaration = parseArrayInitialiser();
-            } else {
-                declaration = parseAssignmentExpression();
-            }
-            consumeSemicolon();
-            return markerApply(marker, delegate.createExportDeclaration(true, declaration, [], null));
-        }
-
-        // non-default export
-        if (lookahead.type === Token.Keyword) {
-            // covers:
-            // export var f = 1;
-            switch (lookahead.value) {
-            case 'let':
-            case 'const':
-            case 'var':
-            case 'class':
-            case 'function':
-                return markerApply(marker, delegate.createExportDeclaration(false, parseSourceElement(), specifiers, null));
-            }
-        }
-
-        if (match('*')) {
-            // covers:
-            // export * from &quot;foo&quot;;
-            specifiers.push(parseExportBatchSpecifier());
-
-            if (!matchContextualKeyword('from')) {
-                throwError({}, lookahead.value ?
-                        Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
-            }
</del><span class="cx">             lex();
</span><del>-            src = parseModuleSpecifier();
-            consumeSemicolon();
</del><ins>+        } while (startIndex &lt; length);
</ins><span class="cx"> 
</span><del>-            return markerApply(marker, delegate.createExportDeclaration(false, null, specifiers, src));
-        }
-
-        expect('{');
-        if (!match('}')) {
-            do {
-                isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
-                specifiers.push(parseExportSpecifier());
-            } while (match(',') &amp;&amp; lex());
-        }
-        expect('}');
-
-        if (matchContextualKeyword('from')) {
-            // covering:
-            // export {default} from &quot;foo&quot;;
-            // export {foo} from &quot;foo&quot;;
-            lex();
-            src = parseModuleSpecifier();
-            consumeSemicolon();
-        } else if (isExportFromIdentifier) {
-            // covering:
-            // export {default}; // missing fromClause
-            throwError({}, lookahead.value ?
-                    Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
-        } else {
-            // cover
-            // export {foo};
-            consumeSemicolon();
-        }
-        return markerApply(marker, delegate.createExportDeclaration(false, declaration, specifiers, src));
</del><ins>+        return list;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    function parseLexicalDeclaration(options) {
+        var kind, declarations, node = new Node();
</ins><span class="cx"> 
</span><del>-    function parseImportSpecifier() {
-        // import {&lt;foo as bar&gt;} ...;
-        var id, name = null, marker = markerCreate();
</del><ins>+        kind = lex().value;
+        assert(kind === 'let' || kind === 'const', 'Lexical declaration must be either let or const');
</ins><span class="cx"> 
</span><del>-        id = parseNonComputedProperty();
-        if (matchContextualKeyword('as')) {
-            lex();
-            name = parseVariableIdentifier();
-        }
</del><ins>+        declarations = parseBindingList(kind, options);
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createImportSpecifier(id, name));
-    }
</del><ins>+        consumeSemicolon();
</ins><span class="cx"> 
</span><del>-    function parseNamedImports() {
-        var specifiers = [];
-        // {foo, bar as bas}
-        expect('{');
-        if (!match('}')) {
-            do {
-                specifiers.push(parseImportSpecifier());
-            } while (match(',') &amp;&amp; lex());
-        }
-        expect('}');
-        return specifiers;
</del><ins>+        return node.finishLexicalDeclaration(declarations, kind);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseImportDefaultSpecifier() {
-        // import &lt;foo&gt; ...;
-        var id, marker = markerCreate();
</del><ins>+    function parseRestElement(params) {
+        var param, node = new Node();
</ins><span class="cx"> 
</span><del>-        id = parseNonComputedProperty();
</del><ins>+        lex();
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createImportDefaultSpecifier(id));
-    }
-
-    function parseImportNamespaceSpecifier() {
-        // import &lt;* as foo&gt; ...;
-        var id, marker = markerCreate();
-
-        expect('*');
-        if (!matchContextualKeyword('as')) {
-            throwError({}, Messages.NoAsAfterImportNamespace);
</del><ins>+        if (match('{')) {
+            throwError(Messages.ObjectPatternAsRestParameter);
</ins><span class="cx">         }
</span><del>-        lex();
-        id = parseNonComputedProperty();
</del><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createImportNamespaceSpecifier(id));
-    }
</del><ins>+        params.push(lookahead);
</ins><span class="cx"> 
</span><del>-    function parseImportDeclaration() {
-        var specifiers, src, marker = markerCreate();
</del><ins>+        param = parseVariableIdentifier();
</ins><span class="cx"> 
</span><del>-        expectKeyword('import');
-        specifiers = [];
-
-        if (lookahead.type === Token.StringLiteral) {
-            // covers:
-            // import &quot;foo&quot;;
-            src = parseModuleSpecifier();
-            consumeSemicolon();
-            return markerApply(marker, delegate.createImportDeclaration(specifiers, src));
</del><ins>+        if (match('=')) {
+            throwError(Messages.DefaultRestParameter);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (!matchKeyword('default') &amp;&amp; isIdentifierName(lookahead)) {
-            // covers:
-            // import foo
-            // import foo, ...
-            specifiers.push(parseImportDefaultSpecifier());
-            if (match(',')) {
-                lex();
-            }
</del><ins>+        if (!match(')')) {
+            throwError(Messages.ParameterAfterRestParameter);
</ins><span class="cx">         }
</span><del>-        if (match('*')) {
-            // covers:
-            // import foo, * as foo
-            // import * as foo
-            specifiers.push(parseImportNamespaceSpecifier());
-        } else if (match('{')) {
-            // covers:
-            // import foo, {bar}
-            // import {bar}
-            specifiers = specifiers.concat(parseNamedImports());
-        }
</del><span class="cx"> 
</span><del>-        if (!matchContextualKeyword('from')) {
-            throwError({}, lookahead.value ?
-                    Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
-        }
-        lex();
-        src = parseModuleSpecifier();
-        consumeSemicolon();
-
-        return markerApply(marker, delegate.createImportDeclaration(specifiers, src));
</del><ins>+        return node.finishRestElement(param);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.3 Empty Statement
</del><ins>+    // ECMA-262 13.4 Empty Statement
</ins><span class="cx"> 
</span><del>-    function parseEmptyStatement() {
-        var marker = markerCreate();
</del><ins>+    function parseEmptyStatement(node) {
</ins><span class="cx">         expect(';');
</span><del>-        return markerApply(marker, delegate.createEmptyStatement());
</del><ins>+        return node.finishEmptyStatement();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.4 Expression Statement
</del><ins>+    // ECMA-262 12.4 Expression Statement
</ins><span class="cx"> 
</span><del>-    function parseExpressionStatement() {
-        var marker = markerCreate(), expr = parseExpression();
</del><ins>+    function parseExpressionStatement(node) {
+        var expr = parseExpression();
</ins><span class="cx">         consumeSemicolon();
</span><del>-        return markerApply(marker, delegate.createExpressionStatement(expr));
</del><ins>+        return node.finishExpressionStatement(expr);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.5 If statement
</del><ins>+    // ECMA-262 13.6 If statement
</ins><span class="cx"> 
</span><del>-    function parseIfStatement() {
-        var test, consequent, alternate, marker = markerCreate();
</del><ins>+    function parseIfStatement(node) {
+        var test, consequent, alternate;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('if');
</span><span class="cx"> 
</span><span class="lines">@@ -3920,13 +4169,13 @@
</span><span class="cx">             alternate = null;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createIfStatement(test, consequent, alternate));
</del><ins>+        return node.finishIfStatement(test, consequent, alternate);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.6 Iteration Statements
</del><ins>+    // ECMA-262 13.7 Iteration Statements
</ins><span class="cx"> 
</span><del>-    function parseDoWhileStatement() {
-        var body, test, oldInIteration, marker = markerCreate();
</del><ins>+    function parseDoWhileStatement(node) {
+        var body, test, oldInIteration;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('do');
</span><span class="cx"> 
</span><span class="lines">@@ -3949,11 +4198,11 @@
</span><span class="cx">             lex();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createDoWhileStatement(body, test));
</del><ins>+        return node.finishDoWhileStatement(body, test);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseWhileStatement() {
-        var test, body, oldInIteration, marker = markerCreate();
</del><ins>+    function parseWhileStatement(node) {
+        var test, body, oldInIteration;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('while');
</span><span class="cx"> 
</span><span class="lines">@@ -3970,74 +4219,112 @@
</span><span class="cx"> 
</span><span class="cx">         state.inIteration = oldInIteration;
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createWhileStatement(test, body));
</del><ins>+        return node.finishWhileStatement(test, body);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseForVariableDeclaration() {
-        var marker = markerCreate(),
-            token = lex(),
-            declarations = parseVariableDeclarationList();
</del><ins>+    function parseForStatement(node) {
+        var init, forIn, initSeq, initStartToken, test, update, left, right, kind, declarations,
+            body, oldInIteration, previousAllowIn = state.allowIn;
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createVariableDeclaration(declarations, token.value));
-    }
</del><ins>+        init = test = update = null;
+        forIn = true;
</ins><span class="cx"> 
</span><del>-    function parseForStatement(opts) {
-        var init, test, update, left, right, body, operator, oldInIteration,
-            marker = markerCreate();
-        init = test = update = null;
</del><span class="cx">         expectKeyword('for');
</span><span class="cx"> 
</span><del>-        // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&amp;s=each
-        if (matchContextualKeyword('each')) {
-            throwError({}, Messages.EachNotAllowed);
-        }
-
</del><span class="cx">         expect('(');
</span><span class="cx"> 
</span><span class="cx">         if (match(';')) {
</span><span class="cx">             lex();
</span><span class="cx">         } else {
</span><del>-            if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) {
</del><ins>+            if (matchKeyword('var')) {
+                init = new Node();
+                lex();
+
</ins><span class="cx">                 state.allowIn = false;
</span><del>-                init = parseForVariableDeclaration();
-                state.allowIn = true;
</del><ins>+                declarations = parseVariableDeclarationList({ inFor: true });
+                state.allowIn = previousAllowIn;
</ins><span class="cx"> 
</span><del>-                if (init.declarations.length === 1) {
-                    if (matchKeyword('in') || matchContextualKeyword('of')) {
-                        operator = lookahead;
-                        if (!((operator.value === 'in' || init.kind !== 'var') &amp;&amp; init.declarations[0].init)) {
-                            lex();
-                            left = init;
-                            right = parseExpression();
-                            init = null;
-                        }
-                    }
</del><ins>+                if (declarations.length === 1 &amp;&amp; matchKeyword('in')) {
+                    init = init.finishVariableDeclaration(declarations);
+                    lex();
+                    left = init;
+                    right = parseExpression();
+                    init = null;
+                } else if (declarations.length === 1 &amp;&amp; declarations[0].init === null &amp;&amp; matchContextualKeyword('of')) {
+                    init = init.finishVariableDeclaration(declarations);
+                    lex();
+                    left = init;
+                    right = parseAssignmentExpression();
+                    init = null;
+                    forIn = false;
+                } else {
+                    init = init.finishVariableDeclaration(declarations);
+                    expect(';');
</ins><span class="cx">                 }
</span><del>-            } else {
</del><ins>+            } else if (matchKeyword('const') || matchKeyword('let')) {
+                init = new Node();
+                kind = lex().value;
+
</ins><span class="cx">                 state.allowIn = false;
</span><del>-                init = parseExpression();
-                state.allowIn = true;
</del><ins>+                declarations = parseBindingList(kind, {inFor: true});
+                state.allowIn = previousAllowIn;
</ins><span class="cx"> 
</span><del>-                if (matchContextualKeyword('of')) {
-                    operator = lex();
</del><ins>+                if (declarations.length === 1 &amp;&amp; declarations[0].init === null &amp;&amp; matchKeyword('in')) {
+                    init = init.finishLexicalDeclaration(declarations, kind);
+                    lex();
</ins><span class="cx">                     left = init;
</span><span class="cx">                     right = parseExpression();
</span><span class="cx">                     init = null;
</span><del>-                } else if (matchKeyword('in')) {
-                    // LeftHandSideExpression
-                    if (!isAssignableLeftHandSide(init)) {
-                        throwError({}, Messages.InvalidLHSInForIn);
</del><ins>+                } else if (declarations.length === 1 &amp;&amp; declarations[0].init === null &amp;&amp; matchContextualKeyword('of')) {
+                    init = init.finishLexicalDeclaration(declarations, kind);
+                    lex();
+                    left = init;
+                    right = parseAssignmentExpression();
+                    init = null;
+                    forIn = false;
+                } else {
+                    consumeSemicolon();
+                    init = init.finishLexicalDeclaration(declarations, kind);
+                }
+            } else {
+                initStartToken = lookahead;
+                state.allowIn = false;
+                init = inheritCoverGrammar(parseAssignmentExpression);
+                state.allowIn = previousAllowIn;
+
+                if (matchKeyword('in')) {
+                    if (!isAssignmentTarget) {
+                        tolerateError(Messages.InvalidLHSInForIn);
</ins><span class="cx">                     }
</span><del>-                    operator = lex();
</del><ins>+
+                    lex();
+                    reinterpretExpressionAsPattern(init);
</ins><span class="cx">                     left = init;
</span><span class="cx">                     right = parseExpression();
</span><span class="cx">                     init = null;
</span><ins>+                } else if (matchContextualKeyword('of')) {
+                    if (!isAssignmentTarget) {
+                        tolerateError(Messages.InvalidLHSInForLoop);
+                    }
+
+                    lex();
+                    reinterpretExpressionAsPattern(init);
+                    left = init;
+                    right = parseAssignmentExpression();
+                    init = null;
+                    forIn = false;
+                } else {
+                    if (match(',')) {
+                        initSeq = [init];
+                        while (match(',')) {
+                            lex();
+                            initSeq.push(isolateCoverGrammar(parseAssignmentExpression));
+                        }
+                        init = new WrappingNode(initStartToken).finishSequenceExpression(initSeq);
+                    }
+                    expect(';');
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><del>-
-            if (typeof left === 'undefined') {
-                expect(';');
-            }
</del><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (typeof left === 'undefined') {
</span><span class="lines">@@ -4057,130 +4344,127 @@
</span><span class="cx">         oldInIteration = state.inIteration;
</span><span class="cx">         state.inIteration = true;
</span><span class="cx"> 
</span><del>-        if (!(opts !== undefined &amp;&amp; opts.ignoreBody)) {
-            body = parseStatement();
-        }
</del><ins>+        body = isolateCoverGrammar(parseStatement);
</ins><span class="cx"> 
</span><span class="cx">         state.inIteration = oldInIteration;
</span><span class="cx"> 
</span><del>-        if (typeof left === 'undefined') {
-            return markerApply(marker, delegate.createForStatement(init, test, update, body));
-        }
-
-        if (operator.value === 'in') {
-            return markerApply(marker, delegate.createForInStatement(left, right, body));
-        }
-        return markerApply(marker, delegate.createForOfStatement(left, right, body));
</del><ins>+        return (typeof left === 'undefined') ?
+                node.finishForStatement(init, test, update, body) :
+                forIn ? node.finishForInStatement(left, right, body) :
+                    node.finishForOfStatement(left, right, body);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.7 The continue statement
</del><ins>+    // ECMA-262 13.8 The continue statement
</ins><span class="cx"> 
</span><del>-    function parseContinueStatement() {
-        var label = null, marker = markerCreate();
</del><ins>+    function parseContinueStatement(node) {
+        var label = null, key;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('continue');
</span><span class="cx"> 
</span><span class="cx">         // Optimize the most common form: 'continue;'.
</span><del>-        if (source.charCodeAt(index) === 59) {
</del><ins>+        if (source.charCodeAt(startIndex) === 0x3B) {
</ins><span class="cx">             lex();
</span><span class="cx"> 
</span><span class="cx">             if (!state.inIteration) {
</span><del>-                throwError({}, Messages.IllegalContinue);
</del><ins>+                throwError(Messages.IllegalContinue);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            return markerApply(marker, delegate.createContinueStatement(null));
</del><ins>+            return node.finishContinueStatement(null);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (peekLineTerminator()) {
</del><ins>+        if (hasLineTerminator) {
</ins><span class="cx">             if (!state.inIteration) {
</span><del>-                throwError({}, Messages.IllegalContinue);
</del><ins>+                throwError(Messages.IllegalContinue);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            return markerApply(marker, delegate.createContinueStatement(null));
</del><ins>+            return node.finishContinueStatement(null);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (lookahead.type === Token.Identifier) {
</span><span class="cx">             label = parseVariableIdentifier();
</span><span class="cx"> 
</span><del>-            if (!state.labelSet.has(label.name)) {
-                throwError({}, Messages.UnknownLabel, label.name);
</del><ins>+            key = '$' + label.name;
+            if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+                throwError(Messages.UnknownLabel, label.name);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><span class="cx">         if (label === null &amp;&amp; !state.inIteration) {
</span><del>-            throwError({}, Messages.IllegalContinue);
</del><ins>+            throwError(Messages.IllegalContinue);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createContinueStatement(label));
</del><ins>+        return node.finishContinueStatement(label);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.8 The break statement
</del><ins>+    // ECMA-262 13.9 The break statement
</ins><span class="cx"> 
</span><del>-    function parseBreakStatement() {
-        var label = null, marker = markerCreate();
</del><ins>+    function parseBreakStatement(node) {
+        var label = null, key;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('break');
</span><span class="cx"> 
</span><del>-        // Catch the very common case first: immediately a semicolon (char #59).
-        if (source.charCodeAt(index) === 59) {
</del><ins>+        // Catch the very common case first: immediately a semicolon (U+003B).
+        if (source.charCodeAt(lastIndex) === 0x3B) {
</ins><span class="cx">             lex();
</span><span class="cx"> 
</span><span class="cx">             if (!(state.inIteration || state.inSwitch)) {
</span><del>-                throwError({}, Messages.IllegalBreak);
</del><ins>+                throwError(Messages.IllegalBreak);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            return markerApply(marker, delegate.createBreakStatement(null));
</del><ins>+            return node.finishBreakStatement(null);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (peekLineTerminator()) {
</del><ins>+        if (hasLineTerminator) {
</ins><span class="cx">             if (!(state.inIteration || state.inSwitch)) {
</span><del>-                throwError({}, Messages.IllegalBreak);
</del><ins>+                throwError(Messages.IllegalBreak);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            return markerApply(marker, delegate.createBreakStatement(null));
</del><ins>+            return node.finishBreakStatement(null);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (lookahead.type === Token.Identifier) {
</span><span class="cx">             label = parseVariableIdentifier();
</span><span class="cx"> 
</span><del>-            if (!state.labelSet.has(label.name)) {
-                throwError({}, Messages.UnknownLabel, label.name);
</del><ins>+            key = '$' + label.name;
+            if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+                throwError(Messages.UnknownLabel, label.name);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><span class="cx">         if (label === null &amp;&amp; !(state.inIteration || state.inSwitch)) {
</span><del>-            throwError({}, Messages.IllegalBreak);
</del><ins>+            throwError(Messages.IllegalBreak);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createBreakStatement(label));
</del><ins>+        return node.finishBreakStatement(label);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.9 The return statement
</del><ins>+    // ECMA-262 13.10 The return statement
</ins><span class="cx"> 
</span><del>-    function parseReturnStatement() {
-        var argument = null, marker = markerCreate();
</del><ins>+    function parseReturnStatement(node) {
+        var argument = null;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('return');
</span><span class="cx"> 
</span><span class="cx">         if (!state.inFunctionBody) {
</span><del>-            throwErrorTolerant({}, Messages.IllegalReturn);
</del><ins>+            tolerateError(Messages.IllegalReturn);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         // 'return' followed by a space and an identifier is very common.
</span><del>-        if (source.charCodeAt(index) === 32) {
-            if (isIdentifierStart(source.charCodeAt(index + 1))) {
</del><ins>+        if (source.charCodeAt(lastIndex) === 0x20) {
+            if (isIdentifierStart(source.charCodeAt(lastIndex + 1))) {
</ins><span class="cx">                 argument = parseExpression();
</span><span class="cx">                 consumeSemicolon();
</span><del>-                return markerApply(marker, delegate.createReturnStatement(argument));
</del><ins>+                return node.finishReturnStatement(argument);
</ins><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (peekLineTerminator()) {
-            return markerApply(marker, delegate.createReturnStatement(null));
</del><ins>+        if (hasLineTerminator) {
+            // HACK
+            return node.finishReturnStatement(null);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (!match(';')) {
</span><span class="lines">@@ -4191,16 +4475,16 @@
</span><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createReturnStatement(argument));
</del><ins>+        return node.finishReturnStatement(argument);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.10 The with statement
</del><ins>+    // ECMA-262 13.11 The with statement
</ins><span class="cx"> 
</span><del>-    function parseWithStatement() {
-        var object, body, marker = markerCreate();
</del><ins>+    function parseWithStatement(node) {
+        var object, body;
</ins><span class="cx"> 
</span><span class="cx">         if (strict) {
</span><del>-            throwErrorTolerant({}, Messages.StrictModeWith);
</del><ins>+            tolerateError(Messages.StrictModeWith);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         expectKeyword('with');
</span><span class="lines">@@ -4213,16 +4497,13 @@
</span><span class="cx"> 
</span><span class="cx">         body = parseStatement();
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createWithStatement(object, body));
</del><ins>+        return node.finishWithStatement(object, body);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.10 The swith statement
</del><ins>+    // ECMA-262 13.12 The switch statement
</ins><span class="cx"> 
</span><span class="cx">     function parseSwitchCase() {
</span><del>-        var test,
-            consequent = [],
-            sourceElement,
-            marker = markerCreate();
</del><ins>+        var test, consequent = [], statement, node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         if (matchKeyword('default')) {
</span><span class="cx">             lex();
</span><span class="lines">@@ -4233,22 +4514,19 @@
</span><span class="cx">         }
</span><span class="cx">         expect(':');
</span><span class="cx"> 
</span><del>-        while (index &lt; length) {
</del><ins>+        while (startIndex &lt; length) {
</ins><span class="cx">             if (match('}') || matchKeyword('default') || matchKeyword('case')) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            sourceElement = parseSourceElement();
-            if (typeof sourceElement === 'undefined') {
-                break;
-            }
-            consequent.push(sourceElement);
</del><ins>+            statement = parseStatementListItem();
+            consequent.push(statement);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createSwitchCase(test, consequent));
</del><ins>+        return node.finishSwitchCase(test, consequent);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseSwitchStatement() {
-        var discriminant, cases, clause, oldInSwitch, defaultFound, marker = markerCreate();
</del><ins>+    function parseSwitchStatement(node) {
+        var discriminant, cases, clause, oldInSwitch, defaultFound;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('switch');
</span><span class="cx"> 
</span><span class="lines">@@ -4264,21 +4542,21 @@
</span><span class="cx"> 
</span><span class="cx">         if (match('}')) {
</span><span class="cx">             lex();
</span><del>-            return markerApply(marker, delegate.createSwitchStatement(discriminant, cases));
</del><ins>+            return node.finishSwitchStatement(discriminant, cases);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         oldInSwitch = state.inSwitch;
</span><span class="cx">         state.inSwitch = true;
</span><span class="cx">         defaultFound = false;
</span><span class="cx"> 
</span><del>-        while (index &lt; length) {
</del><ins>+        while (startIndex &lt; length) {
</ins><span class="cx">             if (match('}')) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             clause = parseSwitchCase();
</span><span class="cx">             if (clause.test === null) {
</span><span class="cx">                 if (defaultFound) {
</span><del>-                    throwError({}, Messages.MultipleDefaultsInSwitch);
</del><ins>+                    throwError(Messages.MultipleDefaultsInSwitch);
</ins><span class="cx">                 }
</span><span class="cx">                 defaultFound = true;
</span><span class="cx">             }
</span><span class="lines">@@ -4289,59 +4567,67 @@
</span><span class="cx"> 
</span><span class="cx">         expect('}');
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createSwitchStatement(discriminant, cases));
</del><ins>+        return node.finishSwitchStatement(discriminant, cases);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.13 The throw statement
</del><ins>+    // ECMA-262 13.14 The throw statement
</ins><span class="cx"> 
</span><del>-    function parseThrowStatement() {
-        var argument, marker = markerCreate();
</del><ins>+    function parseThrowStatement(node) {
+        var argument;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('throw');
</span><span class="cx"> 
</span><del>-        if (peekLineTerminator()) {
-            throwError({}, Messages.NewlineAfterThrow);
</del><ins>+        if (hasLineTerminator) {
+            throwError(Messages.NewlineAfterThrow);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         argument = parseExpression();
</span><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createThrowStatement(argument));
</del><ins>+        return node.finishThrowStatement(argument);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.14 The try statement
</del><ins>+    // ECMA-262 13.15 The try statement
</ins><span class="cx"> 
</span><span class="cx">     function parseCatchClause() {
</span><del>-        var param, body, marker = markerCreate();
</del><ins>+        var param, params = [], paramMap = {}, key, i, body, node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('catch');
</span><span class="cx"> 
</span><span class="cx">         expect('(');
</span><span class="cx">         if (match(')')) {
</span><del>-            throwUnexpected(lookahead);
</del><ins>+            throwUnexpectedToken(lookahead);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        param = parseExpression();
-        // 12.14.1
-        if (strict &amp;&amp; param.type === Syntax.Identifier &amp;&amp; isRestrictedWord(param.name)) {
-            throwErrorTolerant({}, Messages.StrictCatchVariable);
</del><ins>+        param = parsePattern(params);
+        for (i = 0; i &lt; params.length; i++) {
+            key = '$' + params[i].value;
+            if (Object.prototype.hasOwnProperty.call(paramMap, key)) {
+                tolerateError(Messages.DuplicateBinding, params[i].value);
+            }
+            paramMap[key] = true;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        // ECMA-262 12.14.1
+        if (strict &amp;&amp; isRestrictedWord(param.name)) {
+            tolerateError(Messages.StrictCatchVariable);
+        }
+
</ins><span class="cx">         expect(')');
</span><span class="cx">         body = parseBlock();
</span><del>-        return markerApply(marker, delegate.createCatchClause(param, body));
</del><ins>+        return node.finishCatchClause(param, body);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseTryStatement() {
-        var block, handlers = [], finalizer = null, marker = markerCreate();
</del><ins>+    function parseTryStatement(node) {
+        var block, handler = null, finalizer = null;
</ins><span class="cx"> 
</span><span class="cx">         expectKeyword('try');
</span><span class="cx"> 
</span><span class="cx">         block = parseBlock();
</span><span class="cx"> 
</span><span class="cx">         if (matchKeyword('catch')) {
</span><del>-            handlers.push(parseCatchClause());
</del><ins>+            handler = parseCatchClause();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         if (matchKeyword('finally')) {
</span><span class="lines">@@ -4349,141 +4635,134 @@
</span><span class="cx">             finalizer = parseBlock();
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (handlers.length === 0 &amp;&amp; !finalizer) {
-            throwError({}, Messages.NoCatchOrFinally);
</del><ins>+        if (!handler &amp;&amp; !finalizer) {
+            throwError(Messages.NoCatchOrFinally);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createTryStatement(block, [], handlers, finalizer));
</del><ins>+        return node.finishTryStatement(block, handler, finalizer);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12.15 The debugger statement
</del><ins>+    // ECMA-262 13.16 The debugger statement
</ins><span class="cx"> 
</span><del>-    function parseDebuggerStatement() {
-        var marker = markerCreate();
</del><ins>+    function parseDebuggerStatement(node) {
</ins><span class="cx">         expectKeyword('debugger');
</span><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createDebuggerStatement());
</del><ins>+        return node.finishDebuggerStatement();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 12 Statements
</del><ins>+    // 13 Statements
</ins><span class="cx"> 
</span><span class="cx">     function parseStatement() {
</span><span class="cx">         var type = lookahead.type,
</span><del>-            marker,
</del><span class="cx">             expr,
</span><del>-            labeledBody;
</del><ins>+            labeledBody,
+            key,
+            node;
</ins><span class="cx"> 
</span><span class="cx">         if (type === Token.EOF) {
</span><del>-            throwUnexpected(lookahead);
</del><ins>+            throwUnexpectedToken(lookahead);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        if (type === Token.Punctuator &amp;&amp; lookahead.value === '{') {
+            return parseBlock();
+        }
+        isAssignmentTarget = isBindingElement = true;
+        node = new Node();
+
</ins><span class="cx">         if (type === Token.Punctuator) {
</span><span class="cx">             switch (lookahead.value) {
</span><span class="cx">             case ';':
</span><del>-                return parseEmptyStatement();
-            case '{':
-                return parseBlock();
</del><ins>+                return parseEmptyStatement(node);
</ins><span class="cx">             case '(':
</span><del>-                return parseExpressionStatement();
</del><ins>+                return parseExpressionStatement(node);
</ins><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-        }
-
-        if (type === Token.Keyword) {
</del><ins>+        } else if (type === Token.Keyword) {
</ins><span class="cx">             switch (lookahead.value) {
</span><span class="cx">             case 'break':
</span><del>-                return parseBreakStatement();
</del><ins>+                return parseBreakStatement(node);
</ins><span class="cx">             case 'continue':
</span><del>-                return parseContinueStatement();
</del><ins>+                return parseContinueStatement(node);
</ins><span class="cx">             case 'debugger':
</span><del>-                return parseDebuggerStatement();
</del><ins>+                return parseDebuggerStatement(node);
</ins><span class="cx">             case 'do':
</span><del>-                return parseDoWhileStatement();
</del><ins>+                return parseDoWhileStatement(node);
</ins><span class="cx">             case 'for':
</span><del>-                return parseForStatement();
</del><ins>+                return parseForStatement(node);
</ins><span class="cx">             case 'function':
</span><del>-                return parseFunctionDeclaration();
-            case 'class':
-                return parseClassDeclaration();
</del><ins>+                return parseFunctionDeclaration(node);
</ins><span class="cx">             case 'if':
</span><del>-                return parseIfStatement();
</del><ins>+                return parseIfStatement(node);
</ins><span class="cx">             case 'return':
</span><del>-                return parseReturnStatement();
</del><ins>+                return parseReturnStatement(node);
</ins><span class="cx">             case 'switch':
</span><del>-                return parseSwitchStatement();
</del><ins>+                return parseSwitchStatement(node);
</ins><span class="cx">             case 'throw':
</span><del>-                return parseThrowStatement();
</del><ins>+                return parseThrowStatement(node);
</ins><span class="cx">             case 'try':
</span><del>-                return parseTryStatement();
</del><ins>+                return parseTryStatement(node);
</ins><span class="cx">             case 'var':
</span><del>-                return parseVariableStatement();
</del><ins>+                return parseVariableStatement(node);
</ins><span class="cx">             case 'while':
</span><del>-                return parseWhileStatement();
</del><ins>+                return parseWhileStatement(node);
</ins><span class="cx">             case 'with':
</span><del>-                return parseWithStatement();
</del><ins>+                return parseWithStatement(node);
</ins><span class="cx">             default:
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        marker = markerCreate();
</del><span class="cx">         expr = parseExpression();
</span><span class="cx"> 
</span><del>-        // 12.12 Labelled Statements
</del><ins>+        // ECMA-262 12.12 Labelled Statements
</ins><span class="cx">         if ((expr.type === Syntax.Identifier) &amp;&amp; match(':')) {
</span><span class="cx">             lex();
</span><span class="cx"> 
</span><del>-            if (state.labelSet.has(expr.name)) {
-                throwError({}, Messages.Redeclaration, 'Label', expr.name);
</del><ins>+            key = '$' + expr.name;
+            if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) {
+                throwError(Messages.Redeclaration, 'Label', expr.name);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            state.labelSet.set(expr.name, true);
</del><ins>+            state.labelSet[key] = true;
</ins><span class="cx">             labeledBody = parseStatement();
</span><del>-            state.labelSet.delete(expr.name);
-            return markerApply(marker, delegate.createLabeledStatement(expr, labeledBody));
</del><ins>+            delete state.labelSet[key];
+            return node.finishLabeledStatement(expr, labeledBody);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         consumeSemicolon();
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createExpressionStatement(expr));
</del><ins>+        return node.finishExpressionStatement(expr);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 13 Function Definition
</del><ins>+    // ECMA-262 14.1 Function Definition
</ins><span class="cx"> 
</span><del>-    function parseConciseBody() {
-        if (match('{')) {
-            return parseFunctionSourceElements();
-        }
-        return parseAssignmentExpression();
-    }
-
</del><span class="cx">     function parseFunctionSourceElements() {
</span><del>-        var sourceElement, sourceElements = [], token, directive, firstRestricted,
-            oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount,
-            marker = markerCreate();
</del><ins>+        var statement, body = [], token, directive, firstRestricted,
+            oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesisCount,
+            node = new Node();
</ins><span class="cx"> 
</span><span class="cx">         expect('{');
</span><span class="cx"> 
</span><del>-        while (index &lt; length) {
</del><ins>+        while (startIndex &lt; length) {
</ins><span class="cx">             if (lookahead.type !== Token.StringLiteral) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             token = lookahead;
</span><span class="cx"> 
</span><del>-            sourceElement = parseSourceElement();
-            sourceElements.push(sourceElement);
-            if (sourceElement.expression.type !== Syntax.Literal) {
</del><ins>+            statement = parseStatementListItem();
+            body.push(statement);
+            if (statement.expression.type !== Syntax.Literal) {
</ins><span class="cx">                 // this is not directive
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            directive = source.slice(token.range[0] + 1, token.range[1] - 1);
</del><ins>+            directive = source.slice(token.start + 1, token.end - 1);
</ins><span class="cx">             if (directive === 'use strict') {
</span><span class="cx">                 strict = true;
</span><span class="cx">                 if (firstRestricted) {
</span><del>-                    throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
</del><ins>+                    tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 if (!firstRestricted &amp;&amp; token.octal) {
</span><span class="lines">@@ -4496,23 +4775,19 @@
</span><span class="cx">         oldInIteration = state.inIteration;
</span><span class="cx">         oldInSwitch = state.inSwitch;
</span><span class="cx">         oldInFunctionBody = state.inFunctionBody;
</span><del>-        oldParenthesizedCount = state.parenthesizedCount;
</del><ins>+        oldParenthesisCount = state.parenthesizedCount;
</ins><span class="cx"> 
</span><del>-        state.labelSet = new StringMap();
</del><ins>+        state.labelSet = {};
</ins><span class="cx">         state.inIteration = false;
</span><span class="cx">         state.inSwitch = false;
</span><span class="cx">         state.inFunctionBody = true;
</span><span class="cx">         state.parenthesizedCount = 0;
</span><span class="cx"> 
</span><del>-        while (index &lt; length) {
</del><ins>+        while (startIndex &lt; length) {
</ins><span class="cx">             if (match('}')) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            sourceElement = parseSourceElement();
-            if (typeof sourceElement === 'undefined') {
-                break;
-            }
-            sourceElements.push(sourceElement);
</del><ins>+            body.push(parseStatementListItem());
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         expect('}');
</span><span class="lines">@@ -4521,18 +4796,19 @@
</span><span class="cx">         state.inIteration = oldInIteration;
</span><span class="cx">         state.inSwitch = oldInSwitch;
</span><span class="cx">         state.inFunctionBody = oldInFunctionBody;
</span><del>-        state.parenthesizedCount = oldParenthesizedCount;
</del><ins>+        state.parenthesizedCount = oldParenthesisCount;
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createBlockStatement(sourceElements));
</del><ins>+        return node.finishBlockStatement(body);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function validateParam(options, param, name) {
</span><ins>+        var key = '$' + name;
</ins><span class="cx">         if (strict) {
</span><span class="cx">             if (isRestrictedWord(name)) {
</span><span class="cx">                 options.stricted = param;
</span><span class="cx">                 options.message = Messages.StrictParamName;
</span><span class="cx">             }
</span><del>-            if (options.paramSet.has(name)) {
</del><ins>+            if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
</ins><span class="cx">                 options.stricted = param;
</span><span class="cx">                 options.message = Messages.StrictParamDupe;
</span><span class="cx">             }
</span><span class="lines">@@ -4543,75 +4819,58 @@
</span><span class="cx">             } else if (isStrictModeReservedWord(name)) {
</span><span class="cx">                 options.firstRestricted = param;
</span><span class="cx">                 options.message = Messages.StrictReservedWord;
</span><del>-            } else if (options.paramSet.has(name)) {
-                options.firstRestricted = param;
</del><ins>+            } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) {
+                options.stricted = param;
</ins><span class="cx">                 options.message = Messages.StrictParamDupe;
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        options.paramSet.set(name, true);
</del><ins>+        options.paramSet[key] = true;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseParam(options) {
</span><del>-        var token, rest, param, def;
</del><ins>+        var token, param, params = [], i, def;
</ins><span class="cx"> 
</span><span class="cx">         token = lookahead;
</span><span class="cx">         if (token.value === '...') {
</span><del>-            token = lex();
-            rest = true;
</del><ins>+            param = parseRestElement(params);
+            validateParam(options, param.argument, param.argument.name);
+            options.params.push(param);
+            options.defaults.push(null);
+            return false;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (match('[')) {
-            param = parseArrayInitialiser();
-            reinterpretAsDestructuredParameter(options, param);
-        } else if (match('{')) {
-            if (rest) {
-                throwError({}, Messages.ObjectPatternAsRestParameter);
-            }
-            param = parseObjectInitialiser();
-            reinterpretAsDestructuredParameter(options, param);
-        } else {
-            param = parseVariableIdentifier();
-            validateParam(options, token, token.value);
</del><ins>+        param = parsePatternWithDefault(params);
+        for (i = 0; i &lt; params.length; i++) {
+            validateParam(options, params[i], params[i].value);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (match('=')) {
-            if (rest) {
-                throwErrorTolerant(lookahead, Messages.DefaultRestParameter);
-            }
-            lex();
-            def = parseAssignmentExpression();
</del><ins>+        if (param.type === Syntax.AssignmentPattern) {
+            def = param.right;
+            param = param.left;
</ins><span class="cx">             ++options.defaultCount;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (rest) {
-            if (!match(')')) {
-                throwError({}, Messages.ParameterAfterRestParameter);
-            }
-            options.rest = param;
-            return false;
-        }
-
</del><span class="cx">         options.params.push(param);
</span><span class="cx">         options.defaults.push(def);
</span><ins>+
</ins><span class="cx">         return !match(')');
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseParams(firstRestricted) {
</span><del>-        var options, marker = markerCreate();
</del><ins>+        var options;
</ins><span class="cx"> 
</span><span class="cx">         options = {
</span><span class="cx">             params: [],
</span><span class="cx">             defaultCount: 0,
</span><span class="cx">             defaults: [],
</span><del>-            rest: null,
</del><span class="cx">             firstRestricted: firstRestricted
</span><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         expect('(');
</span><span class="cx"> 
</span><span class="cx">         if (!match(')')) {
</span><del>-            options.paramSet = new StringMap();
-            while (index &lt; length) {
</del><ins>+            options.paramSet = {};
+            while (startIndex &lt; length) {
</ins><span class="cx">                 if (!parseParam(options)) {
</span><span class="cx">                     break;
</span><span class="cx">                 }
</span><span class="lines">@@ -4625,82 +4884,93 @@
</span><span class="cx">             options.defaults = [];
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, options);
</del><ins>+        return {
+            params: options.params,
+            defaults: options.defaults,
+            stricted: options.stricted,
+            firstRestricted: options.firstRestricted,
+            message: options.message
+        };
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseFunctionDeclaration() {
-        var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator,
-            marker = markerCreate();
</del><ins>+    function parseFunctionDeclaration(node, identifierIsOptional) {
+        var id = null, params = [], defaults = [], body, token, stricted, tmp, firstRestricted, message, previousStrict,
+            isGenerator, previousAllowYield;
</ins><span class="cx"> 
</span><ins>+        previousAllowYield = state.allowYield;
+
</ins><span class="cx">         expectKeyword('function');
</span><span class="cx"> 
</span><del>-        generator = false;
-        if (match('*')) {
</del><ins>+        isGenerator = match('*');
+        if (isGenerator) {
</ins><span class="cx">             lex();
</span><del>-            generator = true;
</del><span class="cx">         }
</span><span class="cx"> 
</span><del>-        token = lookahead;
-
-        id = parseVariableIdentifier();
-
-        if (strict) {
-            if (isRestrictedWord(token.value)) {
-                throwErrorTolerant(token, Messages.StrictFunctionName);
</del><ins>+        if (!identifierIsOptional || !match('(')) {
+            token = lookahead;
+            id = parseVariableIdentifier();
+            if (strict) {
+                if (isRestrictedWord(token.value)) {
+                    tolerateUnexpectedToken(token, Messages.StrictFunctionName);
+                }
+            } else {
+                if (isRestrictedWord(token.value)) {
+                    firstRestricted = token;
+                    message = Messages.StrictFunctionName;
+                } else if (isStrictModeReservedWord(token.value)) {
+                    firstRestricted = token;
+                    message = Messages.StrictReservedWord;
+                }
</ins><span class="cx">             }
</span><del>-        } else {
-            if (isRestrictedWord(token.value)) {
-                firstRestricted = token;
-                message = Messages.StrictFunctionName;
-            } else if (isStrictModeReservedWord(token.value)) {
-                firstRestricted = token;
-                message = Messages.StrictReservedWord;
-            }
</del><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        state.allowYield = !isGenerator;
</ins><span class="cx">         tmp = parseParams(firstRestricted);
</span><ins>+        params = tmp.params;
+        defaults = tmp.defaults;
+        stricted = tmp.stricted;
</ins><span class="cx">         firstRestricted = tmp.firstRestricted;
</span><span class="cx">         if (tmp.message) {
</span><span class="cx">             message = tmp.message;
</span><span class="cx">         }
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx">         previousStrict = strict;
</span><del>-        previousYieldAllowed = state.yieldAllowed;
-        state.yieldAllowed = generator;
-
</del><span class="cx">         body = parseFunctionSourceElements();
</span><del>-
</del><span class="cx">         if (strict &amp;&amp; firstRestricted) {
</span><del>-            throwError(firstRestricted, message);
</del><ins>+            throwUnexpectedToken(firstRestricted, message);
</ins><span class="cx">         }
</span><del>-        if (strict &amp;&amp; tmp.stricted) {
-            throwErrorTolerant(tmp.stricted, message);
</del><ins>+        if (strict &amp;&amp; stricted) {
+            tolerateUnexpectedToken(stricted, message);
</ins><span class="cx">         }
</span><ins>+
</ins><span class="cx">         strict = previousStrict;
</span><del>-        state.yieldAllowed = previousYieldAllowed;
</del><ins>+        state.allowYield = previousAllowYield;
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false));
</del><ins>+        return node.finishFunctionDeclaration(id, params, defaults, body, isGenerator);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseFunctionExpression() {
</span><del>-        var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator,
-            marker = markerCreate();
</del><ins>+        var token, id = null, stricted, firstRestricted, message, tmp,
+            params = [], defaults = [], body, previousStrict, node = new Node(),
+            isGenerator, previousAllowYield;
</ins><span class="cx"> 
</span><ins>+        previousAllowYield = state.allowYield;
+
</ins><span class="cx">         expectKeyword('function');
</span><span class="cx"> 
</span><del>-        generator = false;
-
-        if (match('*')) {
</del><ins>+        isGenerator = match('*');
+        if (isGenerator) {
</ins><span class="cx">             lex();
</span><del>-            generator = true;
</del><span class="cx">         }
</span><span class="cx"> 
</span><ins>+        state.allowYield = !isGenerator;
</ins><span class="cx">         if (!match('(')) {
</span><span class="cx">             token = lookahead;
</span><del>-            id = parseVariableIdentifier();
</del><ins>+            id = (!strict &amp;&amp; !isGenerator &amp;&amp; matchKeyword('yield')) ? parseNonComputedProperty() : parseVariableIdentifier();
</ins><span class="cx">             if (strict) {
</span><span class="cx">                 if (isRestrictedWord(token.value)) {
</span><del>-                    throwErrorTolerant(token, Messages.StrictFunctionName);
</del><ins>+                    tolerateUnexpectedToken(token, Messages.StrictFunctionName);
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 if (isRestrictedWord(token.value)) {
</span><span class="lines">@@ -4714,280 +4984,420 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         tmp = parseParams(firstRestricted);
</span><ins>+        params = tmp.params;
+        defaults = tmp.defaults;
+        stricted = tmp.stricted;
</ins><span class="cx">         firstRestricted = tmp.firstRestricted;
</span><span class="cx">         if (tmp.message) {
</span><span class="cx">             message = tmp.message;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         previousStrict = strict;
</span><del>-        previousYieldAllowed = state.yieldAllowed;
-        state.yieldAllowed = generator;
-
</del><span class="cx">         body = parseFunctionSourceElements();
</span><del>-
</del><span class="cx">         if (strict &amp;&amp; firstRestricted) {
</span><del>-            throwError(firstRestricted, message);
</del><ins>+            throwUnexpectedToken(firstRestricted, message);
</ins><span class="cx">         }
</span><del>-        if (strict &amp;&amp; tmp.stricted) {
-            throwErrorTolerant(tmp.stricted, message);
</del><ins>+        if (strict &amp;&amp; stricted) {
+            tolerateUnexpectedToken(stricted, message);
</ins><span class="cx">         }
</span><span class="cx">         strict = previousStrict;
</span><del>-        state.yieldAllowed = previousYieldAllowed;
</del><ins>+        state.allowYield = previousAllowYield;
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, false));
</del><ins>+        return node.finishFunctionExpression(id, params, defaults, body, isGenerator);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseYieldExpression() {
-        var yieldToken, delegateFlag, expr, marker = markerCreate();
</del><ins>+    // ECMA-262 14.5 Class Definitions
</ins><span class="cx"> 
</span><del>-        yieldToken = lex();
-        assert(yieldToken.value === 'yield', 'Called parseYieldExpression with non-yield lookahead.');
</del><ins>+    function parseClassBody() {
+        var classBody, token, isStatic, hasConstructor = false, body, method, computed, key;
</ins><span class="cx"> 
</span><del>-        if (!state.yieldAllowed) {
-            throwErrorTolerant({}, Messages.IllegalYield);
-        }
</del><ins>+        classBody = new Node();
</ins><span class="cx"> 
</span><del>-        delegateFlag = false;
-        if (match('*')) {
-            lex();
-            delegateFlag = true;
</del><ins>+        expect('{');
+        body = [];
+        while (!match('}')) {
+            if (match(';')) {
+                lex();
+            } else {
+                method = new Node();
+                token = lookahead;
+                isStatic = false;
+                computed = match('[');
+                if (match('*')) {
+                    lex();
+                } else {
+                    key = parseObjectPropertyKey();
+                    if (key.name === 'static' &amp;&amp; (lookaheadPropertyName() || match('*'))) {
+                        token = lookahead;
+                        isStatic = true;
+                        computed = match('[');
+                        if (match('*')) {
+                            lex();
+                        } else {
+                            key = parseObjectPropertyKey();
+                        }
+                    }
+                }
+                method = tryParseMethodDefinition(token, key, computed, method);
+                if (method) {
+                    method['static'] = isStatic; // jscs:ignore requireDotNotation
+                    if (method.kind === 'init') {
+                        method.kind = 'method';
+                    }
+                    if (!isStatic) {
+                        if (!method.computed &amp;&amp; (method.key.name || method.key.value.toString()) === 'constructor') {
+                            if (method.kind !== 'method' || !method.method || method.value.generator) {
+                                throwUnexpectedToken(token, Messages.ConstructorSpecialMethod);
+                            }
+                            if (hasConstructor) {
+                                throwUnexpectedToken(token, Messages.DuplicateConstructor);
+                            } else {
+                                hasConstructor = true;
+                            }
+                            method.kind = 'constructor';
+                        }
+                    } else {
+                        if (!method.computed &amp;&amp; (method.key.name || method.key.value.toString()) === 'prototype') {
+                            throwUnexpectedToken(token, Messages.StaticPrototype);
+                        }
+                    }
+                    method.type = Syntax.MethodDefinition;
+                    delete method.method;
+                    delete method.shorthand;
+                    body.push(method);
+                } else {
+                    throwUnexpectedToken(lookahead);
+                }
+            }
</ins><span class="cx">         }
</span><ins>+        lex();
+        return classBody.finishClassBody(body);
+    }
</ins><span class="cx"> 
</span><del>-        expr = parseAssignmentExpression();
</del><ins>+    function parseClassDeclaration(identifierIsOptional) {
+        var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
+        strict = true;
</ins><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createYieldExpression(expr, delegateFlag));
-    }
</del><ins>+        expectKeyword('class');
</ins><span class="cx"> 
</span><del>-    // 14 Functions and classes
</del><ins>+        if (!identifierIsOptional || lookahead.type === Token.Identifier) {
+            id = parseVariableIdentifier();
+        }
</ins><span class="cx"> 
</span><del>-    // 14.1 Functions is defined above (13 in ES5)
-    // 14.2 Arrow Functions Definitions is defined in (7.3 assignments)
</del><ins>+        if (matchKeyword('extends')) {
+            lex();
+            superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
+        }
+        classBody = parseClassBody();
+        strict = previousStrict;
</ins><span class="cx"> 
</span><del>-    // 14.3 Method Definitions
-    // 14.3.7
-    function specialMethod(methodDefinition) {
-        return methodDefinition.kind === 'get' ||
-            methodDefinition.kind === 'set' ||
-            methodDefinition.value.generator;
</del><ins>+        return classNode.finishClassDeclaration(id, superClass, classBody);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseMethodDefinition() {
-        var token, key, param, propType, computed,
-            marker = markerCreate();
</del><ins>+    function parseClassExpression() {
+        var id = null, superClass = null, classNode = new Node(), classBody, previousStrict = strict;
+        strict = true;
</ins><span class="cx"> 
</span><del>-        if (lookahead.value === 'static') {
-            propType = ClassPropertyType.static;
-            lex();
-        } else {
-            propType = ClassPropertyType.prototype;
</del><ins>+        expectKeyword('class');
+
+        if (lookahead.type === Token.Identifier) {
+            id = parseVariableIdentifier();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        if (match('*')) {
</del><ins>+        if (matchKeyword('extends')) {
</ins><span class="cx">             lex();
</span><del>-            computed = (lookahead.value === '[');
-            return markerApply(marker, delegate.createMethodDefinition(
-                propType,
-                '',
-                parseObjectPropertyKey(),
-                parsePropertyMethodFunction({ generator: true }),
-                computed
-            ));
</del><ins>+            superClass = isolateCoverGrammar(parseLeftHandSideExpressionAllowCall);
</ins><span class="cx">         }
</span><ins>+        classBody = parseClassBody();
+        strict = previousStrict;
</ins><span class="cx"> 
</span><del>-        token = lookahead;
-        key = parseObjectPropertyKey();
</del><ins>+        return classNode.finishClassExpression(id, superClass, classBody);
+    }
</ins><span class="cx"> 
</span><del>-        if (token.value === 'get' &amp;&amp; !match('(')) {
-            computed = (lookahead.value === '[');
-            key = parseObjectPropertyKey();
</del><ins>+    // ECMA-262 15.2 Modules
</ins><span class="cx"> 
</span><del>-            expect('(');
-            expect(')');
-            return markerApply(marker, delegate.createMethodDefinition(
-                propType,
-                'get',
-                key,
-                parsePropertyFunction({ generator: false }),
-                computed
-            ));
-        }
-        if (token.value === 'set' &amp;&amp; !match('(')) {
-            computed = (lookahead.value === '[');
-            key = parseObjectPropertyKey();
</del><ins>+    function parseModuleSpecifier() {
+        var node = new Node();
</ins><span class="cx"> 
</span><del>-            expect('(');
-            token = lookahead;
-            param = [ parseVariableIdentifier() ];
-            expect(')');
-            return markerApply(marker, delegate.createMethodDefinition(
-                propType,
-                'set',
-                key,
-                parsePropertyFunction({ params: param, generator: false, name: token }),
-                computed
-            ));
</del><ins>+        if (lookahead.type !== Token.StringLiteral) {
+            throwError(Messages.InvalidModuleSpecifier);
</ins><span class="cx">         }
</span><del>-
-        computed = (token.value === '[');
-
-        return markerApply(marker, delegate.createMethodDefinition(
-            propType,
-            '',
-            key,
-            parsePropertyMethodFunction({ generator: false }),
-            computed
-        ));
</del><ins>+        return node.finishLiteral(lex());
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 14.5 Class Definitions
</del><ins>+    // ECMA-262 15.2.3 Exports
</ins><span class="cx"> 
</span><del>-    function parseClassElement() {
-        if (match(';')) {
</del><ins>+    function parseExportSpecifier() {
+        var exported, local, node = new Node(), def;
+        if (matchKeyword('default')) {
+            // export {default} from 'something';
+            def = new Node();
</ins><span class="cx">             lex();
</span><ins>+            local = def.finishIdentifier('default');
</ins><span class="cx">         } else {
</span><del>-            return parseMethodDefinition();
</del><ins>+            local = parseVariableIdentifier();
</ins><span class="cx">         }
</span><ins>+        if (matchContextualKeyword('as')) {
+            lex();
+            exported = parseNonComputedProperty();
+        }
+        return node.finishExportSpecifier(local, exported);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseClassBody() {
-        var classElement, classElements = [], existingProps = {},
-            marker = markerCreate(), propName, propType;
</del><ins>+    function parseExportNamedDeclaration(node) {
+        var declaration = null,
+            isExportFromIdentifier,
+            src = null, specifiers = [];
</ins><span class="cx"> 
</span><del>-        existingProps[ClassPropertyType.static] = new StringMap();
-        existingProps[ClassPropertyType.prototype] = new StringMap();
</del><ins>+        // non-default export
+        if (lookahead.type === Token.Keyword) {
+            // covers:
+            // export var f = 1;
+            switch (lookahead.value) {
+                case 'let':
+                case 'const':
+                case 'var':
+                case 'class':
+                case 'function':
+                    declaration = parseStatementListItem();
+                    return node.finishExportNamedDeclaration(declaration, specifiers, null);
+            }
+        }
</ins><span class="cx"> 
</span><span class="cx">         expect('{');
</span><del>-
-        while (index &lt; length) {
-            if (match('}')) {
-                break;
-            }
-            classElement = parseClassElement(existingProps);
-
-            if (typeof classElement !== 'undefined') {
-                classElements.push(classElement);
-
-                propName = !classElement.computed &amp;&amp; getFieldName(classElement.key);
-                if (propName !== false) {
-                    propType = classElement.static ?
-                                ClassPropertyType.static :
-                                ClassPropertyType.prototype;
-
-                    if (propName === 'constructor' &amp;&amp; !classElement.static) {
-                        if (specialMethod(classElement)) {
-                            throwError(classElement, Messages.IllegalClassConstructorProperty);
-                        }
-                        if (existingProps[ClassPropertyType.prototype].has('constructor')) {
-                            throwError(classElement.key, Messages.IllegalDuplicateClassProperty);
-                        }
-                    }
-                    existingProps[propType].set(propName, true);
</del><ins>+        while (!match('}')) {
+            isExportFromIdentifier = isExportFromIdentifier || matchKeyword('default');
+            specifiers.push(parseExportSpecifier());
+            if (!match('}')) {
+                expect(',');
+                if (match('}')) {
+                    break;
</ins><span class="cx">                 }
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-
</del><span class="cx">         expect('}');
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createClassBody(classElements));
</del><ins>+        if (matchContextualKeyword('from')) {
+            // covering:
+            // export {default} from 'foo';
+            // export {foo} from 'foo';
+            lex();
+            src = parseModuleSpecifier();
+            consumeSemicolon();
+        } else if (isExportFromIdentifier) {
+            // covering:
+            // export {default}; // missing fromClause
+            throwError(lookahead.value ?
+                    Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
+        } else {
+            // cover
+            // export {foo};
+            consumeSemicolon();
+        }
+        return node.finishExportNamedDeclaration(declaration, specifiers, src);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseClassExpression() {
-        var id, previousYieldAllowed, superClass = null, marker = markerCreate();
</del><ins>+    function parseExportDefaultDeclaration(node) {
+        var declaration = null,
+            expression = null;
</ins><span class="cx"> 
</span><del>-        expectKeyword('class');
</del><ins>+        // covers:
+        // export default ...
+        expectKeyword('default');
</ins><span class="cx"> 
</span><del>-        if (!matchKeyword('extends') &amp;&amp; !match('{')) {
-            id = parseVariableIdentifier();
</del><ins>+        if (matchKeyword('function')) {
+            // covers:
+            // export default function foo () {}
+            // export default function () {}
+            declaration = parseFunctionDeclaration(new Node(), true);
+            return node.finishExportDefaultDeclaration(declaration);
</ins><span class="cx">         }
</span><ins>+        if (matchKeyword('class')) {
+            declaration = parseClassDeclaration(true);
+            return node.finishExportDefaultDeclaration(declaration);
+        }
</ins><span class="cx"> 
</span><del>-        if (matchKeyword('extends')) {
-            expectKeyword('extends');
-            previousYieldAllowed = state.yieldAllowed;
-            state.yieldAllowed = false;
-            superClass = parseAssignmentExpression();
-            state.yieldAllowed = previousYieldAllowed;
</del><ins>+        if (matchContextualKeyword('from')) {
+            throwError(Messages.UnexpectedToken, lookahead.value);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createClassExpression(id, superClass, parseClassBody()));
</del><ins>+        // covers:
+        // export default {};
+        // export default [];
+        // export default (1 + 2);
+        if (match('{')) {
+            expression = parseObjectInitializer();
+        } else if (match('[')) {
+            expression = parseArrayInitializer();
+        } else {
+            expression = parseAssignmentExpression();
+        }
+        consumeSemicolon();
+        return node.finishExportDefaultDeclaration(expression);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseClassDeclaration() {
-        var id, previousYieldAllowed, superClass = null, marker = markerCreate();
</del><ins>+    function parseExportAllDeclaration(node) {
+        var src;
</ins><span class="cx"> 
</span><del>-        expectKeyword('class');
</del><ins>+        // covers:
+        // export * from 'foo';
+        expect('*');
+        if (!matchContextualKeyword('from')) {
+            throwError(lookahead.value ?
+                    Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
+        }
+        lex();
+        src = parseModuleSpecifier();
+        consumeSemicolon();
</ins><span class="cx"> 
</span><del>-        id = parseVariableIdentifier();
</del><ins>+        return node.finishExportAllDeclaration(src);
+    }
</ins><span class="cx"> 
</span><del>-        if (matchKeyword('extends')) {
-            expectKeyword('extends');
-            previousYieldAllowed = state.yieldAllowed;
-            state.yieldAllowed = false;
-            superClass = parseAssignmentExpression();
-            state.yieldAllowed = previousYieldAllowed;
</del><ins>+    function parseExportDeclaration() {
+        var node = new Node();
+        if (state.inFunctionBody) {
+            throwError(Messages.IllegalExportDeclaration);
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return markerApply(marker, delegate.createClassDeclaration(id, superClass, parseClassBody()));
</del><ins>+        expectKeyword('export');
+
+        if (matchKeyword('default')) {
+            return parseExportDefaultDeclaration(node);
+        }
+        if (match('*')) {
+            return parseExportAllDeclaration(node);
+        }
+        return parseExportNamedDeclaration(node);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    // 15 Program
</del><ins>+    // ECMA-262 15.2.2 Imports
</ins><span class="cx"> 
</span><del>-    function parseSourceElement() {
-        if (lookahead.type === Token.Keyword) {
-            switch (lookahead.value) {
-            case 'const':
-            case 'let':
-                return parseConstLetDeclaration(lookahead.value);
-            case 'function':
-                return parseFunctionDeclaration();
-            case 'export':
-                throwErrorTolerant({}, Messages.IllegalExportDeclaration);
-                return parseExportDeclaration();
-            case 'import':
-                throwErrorTolerant({}, Messages.IllegalImportDeclaration);
-                return parseImportDeclaration();
-            default:
-                return parseStatement();
</del><ins>+    function parseImportSpecifier() {
+        // import {&lt;foo as bar&gt;} ...;
+        var local, imported, node = new Node();
+
+        imported = parseNonComputedProperty();
+        if (matchContextualKeyword('as')) {
+            lex();
+            local = parseVariableIdentifier();
+        }
+
+        return node.finishImportSpecifier(local, imported);
+    }
+
+    function parseNamedImports() {
+        var specifiers = [];
+        // {foo, bar as bas}
+        expect('{');
+        while (!match('}')) {
+            specifiers.push(parseImportSpecifier());
+            if (!match('}')) {
+                expect(',');
+                if (match('}')) {
+                    break;
+                }
</ins><span class="cx">             }
</span><span class="cx">         }
</span><ins>+        expect('}');
+        return specifiers;
+    }
</ins><span class="cx"> 
</span><del>-        if (lookahead.type !== Token.EOF) {
-            return parseStatement();
</del><ins>+    function parseImportDefaultSpecifier() {
+        // import &lt;foo&gt; ...;
+        var local, node = new Node();
+
+        local = parseNonComputedProperty();
+
+        return node.finishImportDefaultSpecifier(local);
+    }
+
+    function parseImportNamespaceSpecifier() {
+        // import &lt;* as foo&gt; ...;
+        var local, node = new Node();
+
+        expect('*');
+        if (!matchContextualKeyword('as')) {
+            throwError(Messages.NoAsAfterImportNamespace);
</ins><span class="cx">         }
</span><ins>+        lex();
+        local = parseNonComputedProperty();
+
+        return node.finishImportNamespaceSpecifier(local);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseProgramElement() {
-        if (extra.isModule &amp;&amp; lookahead.type === Token.Keyword) {
-            switch (lookahead.value) {
-            case 'export':
-                return parseExportDeclaration();
-            case 'import':
-                return parseImportDeclaration();
</del><ins>+    function parseImportDeclaration() {
+        var specifiers = [], src, node = new Node();
+
+        if (state.inFunctionBody) {
+            throwError(Messages.IllegalImportDeclaration);
+        }
+
+        expectKeyword('import');
+
+        if (lookahead.type === Token.StringLiteral) {
+            // import 'foo';
+            src = parseModuleSpecifier();
+        } else {
+
+            if (match('{')) {
+                // import {bar}
+                specifiers = specifiers.concat(parseNamedImports());
+            } else if (match('*')) {
+                // import * as foo
+                specifiers.push(parseImportNamespaceSpecifier());
+            } else if (isIdentifierName(lookahead) &amp;&amp; !matchKeyword('default')) {
+                // import foo
+                specifiers.push(parseImportDefaultSpecifier());
+                if (match(',')) {
+                    lex();
+                    if (match('*')) {
+                        // import foo, * as foo
+                        specifiers.push(parseImportNamespaceSpecifier());
+                    } else if (match('{')) {
+                        // import foo, {bar}
+                        specifiers = specifiers.concat(parseNamedImports());
+                    } else {
+                        throwUnexpectedToken(lookahead);
+                    }
+                }
+            } else {
+                throwUnexpectedToken(lex());
</ins><span class="cx">             }
</span><ins>+
+            if (!matchContextualKeyword('from')) {
+                throwError(lookahead.value ?
+                        Messages.UnexpectedToken : Messages.MissingFromClause, lookahead.value);
+            }
+            lex();
+            src = parseModuleSpecifier();
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        return parseSourceElement();
</del><ins>+        consumeSemicolon();
+        return node.finishImportDeclaration(specifiers, src);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function parseProgramElements() {
-        var sourceElement, sourceElements = [], token, directive, firstRestricted;
</del><ins>+    // ECMA-262 15.1 Scripts
</ins><span class="cx"> 
</span><del>-        while (index &lt; length) {
</del><ins>+    function parseScriptBody() {
+        var statement, body = [], token, directive, firstRestricted;
+
+        while (startIndex &lt; length) {
</ins><span class="cx">             token = lookahead;
</span><span class="cx">             if (token.type !== Token.StringLiteral) {
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            sourceElement = parseProgramElement();
-            sourceElements.push(sourceElement);
-            if (sourceElement.expression.type !== Syntax.Literal) {
</del><ins>+            statement = parseStatementListItem();
+            body.push(statement);
+            if (statement.expression.type !== Syntax.Literal) {
</ins><span class="cx">                 // this is not directive
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            directive = source.slice(token.range[0] + 1, token.range[1] - 1);
</del><ins>+            directive = source.slice(token.start + 1, token.end - 1);
</ins><span class="cx">             if (directive === 'use strict') {
</span><span class="cx">                 strict = true;
</span><span class="cx">                 if (firstRestricted) {
</span><del>-                    throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral);
</del><ins>+                    tolerateUnexpectedToken(firstRestricted, Messages.StrictOctalLiteral);
</ins><span class="cx">                 }
</span><span class="cx">             } else {
</span><span class="cx">                 if (!firstRestricted &amp;&amp; token.octal) {
</span><span class="lines">@@ -4996,105 +5406,27 @@
</span><span class="cx">             }
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        while (index &lt; length) {
-            sourceElement = parseProgramElement();
-            if (typeof sourceElement === 'undefined') {
</del><ins>+        while (startIndex &lt; length) {
+            statement = parseStatementListItem();
+            /* istanbul ignore if */
+            if (typeof statement === 'undefined') {
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><del>-            sourceElements.push(sourceElement);
</del><ins>+            body.push(statement);
</ins><span class="cx">         }
</span><del>-        return sourceElements;
</del><ins>+        return body;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     function parseProgram() {
</span><del>-        var body, marker = markerCreate();
-        strict = !!extra.isModule;
</del><ins>+        var body, node;
+
</ins><span class="cx">         peek();
</span><del>-        body = parseProgramElements();
-        return markerApply(marker, delegate.createProgram(body));
-    }
</del><ins>+        node = new Node();
</ins><span class="cx"> 
</span><del>-    function collectToken() {
-        var loc, token, range, value, entry;
-
-        skipComment();
-        loc = {
-            start: {
-                line: lineNumber,
-                column: index - lineStart
-            }
-        };
-
-        token = extra.advance();
-        loc.end = {
-            line: lineNumber,
-            column: index - lineStart
-        };
-
-        if (token.type !== Token.EOF) {
-            range = [token.range[0], token.range[1]];
-            value = source.slice(token.range[0], token.range[1]);
-            entry = {
-                type: TokenName[token.type],
-                value: value,
-                range: range,
-                loc: loc
-            };
-            if (token.regex) {
-                entry.regex = {
-                    pattern: token.regex.pattern,
-                    flags: token.regex.flags
-                };
-            }
-            extra.tokens.push(entry);
-        }
-
-        return token;
</del><ins>+        body = parseScriptBody();
+        return node.finishProgram(body, state.sourceType);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function collectRegex() {
-        var pos, loc, regex, token;
-
-        skipComment();
-
-        pos = index;
-        loc = {
-            start: {
-                line: lineNumber,
-                column: index - lineStart
-            }
-        };
-
-        regex = extra.scanRegExp();
-        loc.end = {
-            line: lineNumber,
-            column: index - lineStart
-        };
-
-        if (!extra.tokenize) {
-            /* istanbul ignore next */
-            // Pop the previous token, which is likely '/' or '/='
-            if (extra.tokens.length &gt; 0) {
-                token = extra.tokens[extra.tokens.length - 1];
-                if (token.range[0] === pos &amp;&amp; token.type === 'Punctuator') {
-                    if (token.value === '/' || token.value === '/=') {
-                        extra.tokens.pop();
-                    }
-                }
-            }
-
-            extra.tokens.push({
-                type: 'RegularExpression',
-                value: regex.literal,
-                regex: regex.regex,
-                range: [pos, index],
-                loc: loc
-            });
-        }
-
-        return regex;
-    }
-
</del><span class="cx">     function filterTokenLocation() {
</span><span class="cx">         var i, entry, token, tokens = [];
</span><span class="cx"> 
</span><span class="lines">@@ -5122,48 +5454,8 @@
</span><span class="cx">         extra.tokens = tokens;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    function patch() {
-        if (typeof extra.tokens !== 'undefined') {
-            extra.advance = advance;
-            extra.scanRegExp = scanRegExp;
-
-            advance = collectToken;
-            scanRegExp = collectRegex;
-        }
-    }
-
-    function unpatch() {
-        if (typeof extra.scanRegExp === 'function') {
-            advance = extra.advance;
-            scanRegExp = extra.scanRegExp;
-        }
-    }
-
-    // This is used to modify the delegate.
-
-    function extend(object, properties) {
-        var entry, result = {};
-
-        for (entry in object) {
-            /* istanbul ignore else */
-            if (object.hasOwnProperty(entry)) {
-                result[entry] = object[entry];
-            }
-        }
-
-        for (entry in properties) {
-            /* istanbul ignore else */
-            if (properties.hasOwnProperty(entry)) {
-                result[entry] = properties[entry];
-            }
-        }
-
-        return result;
-    }
-
</del><span class="cx">     function tokenize(code, options) {
</span><span class="cx">         var toString,
</span><del>-            token,
</del><span class="cx">             tokens;
</span><span class="cx"> 
</span><span class="cx">         toString = String;
</span><span class="lines">@@ -5171,21 +5463,24 @@
</span><span class="cx">             code = toString(code);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        delegate = SyntaxTreeDelegate;
</del><span class="cx">         source = code;
</span><span class="cx">         index = 0;
</span><span class="cx">         lineNumber = (source.length &gt; 0) ? 1 : 0;
</span><span class="cx">         lineStart = 0;
</span><ins>+        startIndex = index;
+        startLineNumber = lineNumber;
+        startLineStart = lineStart;
</ins><span class="cx">         length = source.length;
</span><span class="cx">         lookahead = null;
</span><span class="cx">         state = {
</span><del>-            allowKeyword: true,
</del><span class="cx">             allowIn: true,
</span><del>-            labelSet: new StringMap(),
</del><ins>+            allowYield: true,
+            labelSet: {},
</ins><span class="cx">             inFunctionBody: false,
</span><span class="cx">             inIteration: false,
</span><span class="cx">             inSwitch: false,
</span><del>-            lastCommentStart: -1
</del><ins>+            lastCommentStart: -1,
+            curlyStack: []
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         extra = {};
</span><span class="lines">@@ -5211,22 +5506,19 @@
</span><span class="cx">             extra.errors = [];
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        patch();
-
</del><span class="cx">         try {
</span><span class="cx">             peek();
</span><span class="cx">             if (lookahead.type === Token.EOF) {
</span><span class="cx">                 return extra.tokens;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            token = lex();
</del><ins>+            lex();
</ins><span class="cx">             while (lookahead.type !== Token.EOF) {
</span><span class="cx">                 try {
</span><del>-                    token = lex();
</del><ins>+                    lex();
</ins><span class="cx">                 } catch (lexError) {
</span><del>-                    token = lookahead;
</del><span class="cx">                     if (extra.errors) {
</span><del>-                        extra.errors.push(lexError);
</del><ins>+                        recordError(lexError);
</ins><span class="cx">                         // We have to break on the first error
</span><span class="cx">                         // to avoid infinite loops.
</span><span class="cx">                         break;
</span><span class="lines">@@ -5247,7 +5539,6 @@
</span><span class="cx">         } catch (e) {
</span><span class="cx">             throw e;
</span><span class="cx">         } finally {
</span><del>-            unpatch();
</del><span class="cx">             extra = {};
</span><span class="cx">         }
</span><span class="cx">         return tokens;
</span><span class="lines">@@ -5261,24 +5552,27 @@
</span><span class="cx">             code = toString(code);
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        delegate = SyntaxTreeDelegate;
</del><span class="cx">         source = code;
</span><span class="cx">         index = 0;
</span><span class="cx">         lineNumber = (source.length &gt; 0) ? 1 : 0;
</span><span class="cx">         lineStart = 0;
</span><ins>+        startIndex = index;
+        startLineNumber = lineNumber;
+        startLineStart = lineStart;
</ins><span class="cx">         length = source.length;
</span><span class="cx">         lookahead = null;
</span><span class="cx">         state = {
</span><del>-            allowKeyword: false,
</del><span class="cx">             allowIn: true,
</span><del>-            labelSet: new StringMap(),
-            parenthesizedCount: 0,
</del><ins>+            allowYield: true,
+            labelSet: {},
</ins><span class="cx">             inFunctionBody: false,
</span><span class="cx">             inIteration: false,
</span><span class="cx">             inSwitch: false,
</span><span class="cx">             lastCommentStart: -1,
</span><del>-            yieldAllowed: false
</del><ins>+            curlyStack: [],
+            sourceType: 'script'
</ins><span class="cx">         };
</span><ins>+        strict = false;
</ins><span class="cx"> 
</span><span class="cx">         extra = {};
</span><span class="cx">         if (typeof options !== 'undefined') {
</span><span class="lines">@@ -5287,17 +5581,9 @@
</span><span class="cx">             extra.attachComment = (typeof options.attachComment === 'boolean') &amp;&amp; options.attachComment;
</span><span class="cx"> 
</span><span class="cx">             if (extra.loc &amp;&amp; options.source !== null &amp;&amp; options.source !== undefined) {
</span><del>-                delegate = extend(delegate, {
-                    'postProcess': function (node) {
-                        node.loc.source = toString(options.source);
-                        return node;
-                    }
-                });
</del><ins>+                extra.source = toString(options.source);
</ins><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (options.sourceType === 'module') {
-                extra.isModule = true;
-            }
</del><span class="cx">             if (typeof options.tokens === 'boolean' &amp;&amp; options.tokens) {
</span><span class="cx">                 extra.tokens = [];
</span><span class="cx">             }
</span><span class="lines">@@ -5314,9 +5600,13 @@
</span><span class="cx">                 extra.trailingComments = [];
</span><span class="cx">                 extra.leadingComments = [];
</span><span class="cx">             }
</span><ins>+            if (options.sourceType === 'module') {
+                // very restrictive condition for now
+                state.sourceType = options.sourceType;
+                strict = true;
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        patch();
</del><span class="cx">         try {
</span><span class="cx">             program = parseProgram();
</span><span class="cx">             if (typeof extra.comments !== 'undefined') {
</span><span class="lines">@@ -5332,7 +5622,6 @@
</span><span class="cx">         } catch (e) {
</span><span class="cx">             throw e;
</span><span class="cx">         } finally {
</span><del>-            unpatch();
</del><span class="cx">             extra = {};
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -5340,14 +5629,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Sync with *.json manifests.
</span><del>-    exports.version = '1.1.0-dev-harmony';
</del><ins>+    exports.version = '2.6.0';
</ins><span class="cx"> 
</span><span class="cx">     exports.tokenize = tokenize;
</span><span class="cx"> 
</span><span class="cx">     exports.parse = parse;
</span><span class="cx"> 
</span><span class="cx">     // Deep copy.
</span><del>-   /* istanbul ignore next */
</del><ins>+    /* istanbul ignore next */
</ins><span class="cx">     exports.Syntax = (function () {
</span><span class="cx">         var name, types = {};
</span><span class="cx"> 
</span></span></pre></div>
<a id="branchessafari601branchSourceWebInspectorUIUserInterfaceModelsScriptSyntaxTreejs"></a>
<div class="modfile"><h4>Modified: branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js (193225 => 193226)</h4>
<pre class="diff"><span>
<span class="info">--- branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js        2015-12-03 18:59:26 UTC (rev 193225)
+++ branches/safari-601-branch/Source/WebInspectorUI/UserInterface/Models/ScriptSyntaxTree.js        2015-12-03 18:59:34 UTC (rev 193226)
</span><span class="lines">@@ -260,6 +260,8 @@
</span><span class="cx">                             identifiers.push(identifier);
</span><span class="cx">                     }
</span><span class="cx">                     return identifiers;
</span><ins>+                case WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern:
+                    return gatherIdentifiers(node.left);
</ins><span class="cx">                 default:
</span><span class="cx">                     console.assert(false, &quot;Unexpected node type in variable declarator: &quot; + node.type);
</span><span class="cx">                     return [];
</span><span class="lines">@@ -298,6 +300,11 @@
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurseArray(node.elements, callback, state);
</span><span class="cx">             break;
</span><ins>+        case WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern:
+            callback(node, state);
+            this._recurse(node.left, callback, state);
+            this._recurse(node.right, callback, state);
+            break;
</ins><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.BlockStatement:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurseArray(node.body, callback, state);
</span><span class="lines">@@ -341,12 +348,6 @@
</span><span class="cx">             this._recurse(node.body, callback, state);
</span><span class="cx">             this._recurse(node.test, callback, state);
</span><span class="cx">             break;
</span><del>-        case WebInspector.ScriptSyntaxTree.NodeType.DebuggerStatement:
-            callback(node, state);
-            break;
-        case WebInspector.ScriptSyntaxTree.NodeType.EmptyStatement:
-            callback(node, state);
-            break;
</del><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.ExpressionStatement:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurse(node.expression, callback, state);
</span><span class="lines">@@ -373,18 +374,12 @@
</span><span class="cx">             this._recurseArray(node.defaults, callback, state);
</span><span class="cx">             this._recurse(node.body, callback, state);
</span><span class="cx">             break;
</span><del>-        case WebInspector.ScriptSyntaxTree.NodeType.Identifier:
-            callback(node, state);
-            break;
</del><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.IfStatement:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurse(node.test, callback, state);
</span><span class="cx">             this._recurse(node.consequent, callback, state);
</span><span class="cx">             this._recurse(node.alternate, callback, state);
</span><span class="cx">             break;
</span><del>-        case WebInspector.ScriptSyntaxTree.NodeType.Literal:
-            callback(node, state);
-            break;
</del><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.LabeledStatement:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurse(node.label, callback, state);
</span><span class="lines">@@ -457,17 +452,11 @@
</span><span class="cx">             this._recurse(node.tag, callback, state);
</span><span class="cx">             this._recurse(node.quasi, callback, state);
</span><span class="cx">             break;
</span><del>-        case WebInspector.ScriptSyntaxTree.NodeType.TemplateElement:
-            callback(node, state);
-            break;
</del><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.TemplateLiteral:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurseArray(node.quasis, callback, state);
</span><span class="cx">             this._recurseArray(node.expressions, callback, state);
</span><span class="cx">             break;
</span><del>-        case WebInspector.ScriptSyntaxTree.NodeType.ThisExpression:
-            callback(node, state);
-            break;
</del><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.ThrowStatement:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurse(node.argument, callback, state);
</span><span class="lines">@@ -475,8 +464,7 @@
</span><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.TryStatement:
</span><span class="cx">             callback(node, state);
</span><span class="cx">             this._recurse(node.block, callback, state);
</span><del>-            this._recurseArray(node.guardedHandlers, callback, state);
-            this._recurseArray(node.handlers, callback, state);
</del><ins>+            this._recurse(node.handler, callback, state);
</ins><span class="cx">             this._recurse(node.finalizer, callback, state);
</span><span class="cx">             break;
</span><span class="cx">         case WebInspector.ScriptSyntaxTree.NodeType.UnaryExpression:
</span><span class="lines">@@ -506,6 +494,17 @@
</span><span class="cx">             this._recurse(node.object, callback, state);
</span><span class="cx">             this._recurse(node.body, callback, state);
</span><span class="cx">             break;
</span><ins>+        // All the leaf nodes go here.
+        case WebInspector.ScriptSyntaxTree.NodeType.DebuggerStatement:
+        case WebInspector.ScriptSyntaxTree.NodeType.EmptyStatement:
+        case WebInspector.ScriptSyntaxTree.NodeType.Identifier:
+        case WebInspector.ScriptSyntaxTree.NodeType.Literal:
+        case WebInspector.ScriptSyntaxTree.NodeType.MetaProperty:
+        case WebInspector.ScriptSyntaxTree.NodeType.Super:
+        case WebInspector.ScriptSyntaxTree.NodeType.ThisExpression:
+        case WebInspector.ScriptSyntaxTree.NodeType.TemplateElement:
+            callback(node, state);
+            break;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         state.skipChildNodes = false;
</span><span class="lines">@@ -536,6 +535,13 @@
</span><span class="cx">                 right: this._createInternalSyntaxTree(node.right)
</span><span class="cx">             };
</span><span class="cx">             break;
</span><ins>+        case &quot;AssignmentPattern&quot;:
+            result = {
+                type: WebInspector.ScriptSyntaxTree.NodeType.AssignmentPattern,
+                left: this._createInternalSyntaxTree(node.left),
+                right: this._createInternalSyntaxTree(node.right),
+            };
+            break;
</ins><span class="cx">         case &quot;ArrayExpression&quot;:
</span><span class="cx">             result = {
</span><span class="cx">                 type: WebInspector.ScriptSyntaxTree.NodeType.ArrayExpression,
</span><span class="lines">@@ -730,6 +736,14 @@
</span><span class="cx">                 computed: node.computed
</span><span class="cx">             };
</span><span class="cx">             break;
</span><ins>+        case &quot;MetaProperty&quot;:
+            // i.e: new.target produces {meta: &quot;new&quot;, property: &quot;target&quot;}
+            result = {
+                type: WebInspector.ScriptSyntaxTree.NodeType.MetaProperty,
+                meta: node.meta,
+                property: node.property
+            };
+            break;
</ins><span class="cx">         case &quot;MethodDefinition&quot;:
</span><span class="cx">             result = {
</span><span class="cx">                 type: WebInspector.ScriptSyntaxTree.NodeType.MethodDefinition,
</span><span class="lines">@@ -770,6 +784,7 @@
</span><span class="cx">         case &quot;Program&quot;:
</span><span class="cx">             result = {
</span><span class="cx">                 type: WebInspector.ScriptSyntaxTree.NodeType.Program,
</span><ins>+                sourceType: node.sourceType,
</ins><span class="cx">                 body: node.body.map(this._createInternalSyntaxTree.bind(this))
</span><span class="cx">             };
</span><span class="cx">             break;
</span><span class="lines">@@ -803,6 +818,11 @@
</span><span class="cx">                 argument: this._createInternalSyntaxTree(node.argument),
</span><span class="cx">             };
</span><span class="cx">             break;
</span><ins>+        case &quot;Super&quot;:
+            result = {
+                type: WebInspector.ScriptSyntaxTree.NodeType.Super
+            };
+            break;
</ins><span class="cx">         case &quot;SwitchStatement&quot;:
</span><span class="cx">             result = {
</span><span class="cx">                 type: WebInspector.ScriptSyntaxTree.NodeType.SwitchStatement,
</span><span class="lines">@@ -853,9 +873,7 @@
</span><span class="cx">             result = {
</span><span class="cx">                 type: WebInspector.ScriptSyntaxTree.NodeType.TryStatement,
</span><span class="cx">                 block: this._createInternalSyntaxTree(node.block),
</span><del>-                // FIXME: What are guarded handlers?
-                guardedHandlers: node.guardedHandlers.map(this._createInternalSyntaxTree.bind(this)),
-                handlers: node.handlers.map(this._createInternalSyntaxTree.bind(this)),
</del><ins>+                handler: this._createInternalSyntaxTree(node.handler),
</ins><span class="cx">                 finalizer: this._createInternalSyntaxTree(node.finalizer)
</span><span class="cx">             };
</span><span class="cx">             break;
</span><span class="lines">@@ -925,6 +943,7 @@
</span><span class="cx">     ArrayExpression: Symbol(&quot;array-expression&quot;),
</span><span class="cx">     ArrayPattern: Symbol(&quot;array-pattern&quot;),
</span><span class="cx">     AssignmentExpression: Symbol(&quot;assignment-expression&quot;),
</span><ins>+    AssignmentPattern: Symbol(&quot;assignment-pattern&quot;),
</ins><span class="cx">     BinaryExpression: Symbol(&quot;binary-expression&quot;),
</span><span class="cx">     BlockStatement: Symbol(&quot;block-statement&quot;),
</span><span class="cx">     BreakStatement: Symbol(&quot;break-statement&quot;),
</span><span class="lines">@@ -950,6 +969,7 @@
</span><span class="cx">     Literal: Symbol(&quot;literal&quot;),
</span><span class="cx">     LogicalExpression: Symbol(&quot;logical-expression&quot;),
</span><span class="cx">     MemberExpression: Symbol(&quot;member-expression&quot;),
</span><ins>+    MetaProperty: Symbol(&quot;meta-property&quot;),
</ins><span class="cx">     MethodDefinition: Symbol(&quot;method-definition&quot;),
</span><span class="cx">     NewExpression: Symbol(&quot;new-expression&quot;),
</span><span class="cx">     ObjectExpression: Symbol(&quot;object-expression&quot;),
</span><span class="lines">@@ -959,6 +979,7 @@
</span><span class="cx">     ReturnStatement: Symbol(&quot;return-statement&quot;),
</span><span class="cx">     SequenceExpression: Symbol(&quot;sequence-expression&quot;),
</span><span class="cx">     SpreadElement: Symbol(&quot;spread-element&quot;),
</span><ins>+    Super: Symbol(&quot;super&quot;),
</ins><span class="cx">     SwitchCase: Symbol(&quot;switch-case&quot;),
</span><span class="cx">     SwitchStatement: Symbol(&quot;switch-statement&quot;),
</span><span class="cx">     TaggedTemplateExpression: Symbol(&quot;tagged-template-expression&quot;),
</span></span></pre>
</div>
</div>

</body>
</html>