<!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>[189371] trunk</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/189371">189371</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2015-09-04 12:48:54 -0700 (Fri, 04 Sep 2015)</dd>
</dl>
<h3>Log Message</h3>
<pre>Web Inspector: Test RuntimeAgent.parse, detecting if a script parse error is recoverable
https://bugs.webkit.org/show_bug.cgi?id=148790
Patch by Joseph Pecoraro <pecoraro@apple.com> on 2015-09-04
Reviewed by Timothy Hatcher.
Source/JavaScriptCore:
* parser/Lexer.cpp:
(JSC::Lexer<T>::lex):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::printUnexpectedTokenText):
* parser/ParserTokens.h:
More consistently name and treat unterminated numeric literals.
* parser/Parser.h:
(JSC::Parser<LexerType>::parse):
Treat multiline capable unterminated literals as recoverable.
LayoutTests:
* inspector/runtime/parse-expected.txt: Added.
* inspector/runtime/parse.html: Added.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserLexercpp">trunk/Source/JavaScriptCore/parser/Lexer.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserh">trunk/Source/JavaScriptCore/parser/Parser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParserTokensh">trunk/Source/JavaScriptCore/parser/ParserTokens.h</a></li>
</ul>
<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsinspectorruntimeparseexpectedtxt">trunk/LayoutTests/inspector/runtime/parse-expected.txt</a></li>
<li><a href="#trunkLayoutTestsinspectorruntimeparsehtml">trunk/LayoutTests/inspector/runtime/parse.html</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (189370 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-09-04 19:24:55 UTC (rev 189370)
+++ trunk/LayoutTests/ChangeLog        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -1,3 +1,13 @@
</span><ins>+2015-09-04 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Test RuntimeAgent.parse, detecting if a script parse error is recoverable
+ https://bugs.webkit.org/show_bug.cgi?id=148790
+
+ Reviewed by Timothy Hatcher.
+
+ * inspector/runtime/parse-expected.txt: Added.
+ * inspector/runtime/parse.html: Added.
+
</ins><span class="cx"> 2015-09-04 Tim Horton <timothy_horton@apple.com>
</span><span class="cx">
</span><span class="cx"> swipe-start-hysteresis-failures is flaky
</span></span></pre></div>
<a id="trunkLayoutTestsinspectorruntimeparseexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/runtime/parse-expected.txt (0 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/runtime/parse-expected.txt         (rev 0)
+++ trunk/LayoutTests/inspector/runtime/parse-expected.txt        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -0,0 +1,474 @@
</span><ins>+Tests for the Runtime.parse command.
+
+
+== Running test suite: Runtime.parse
+-- Running test case: SyntaxErrorType.None
+PASS: Should be SyntaxErrorType None.
+Source:
+
+PASS: Should be SyntaxErrorType None.
+Source: ;
+
+PASS: Should be SyntaxErrorType None.
+Source: myVariable
+
+PASS: Should be SyntaxErrorType None.
+Source: var x = 1; x
+
+PASS: Should be SyntaxErrorType None.
+Source: [1,2,3]
+
+PASS: Should be SyntaxErrorType None.
+Source: ({})
+
+PASS: Should be SyntaxErrorType None.
+Source: ({prop:true}).x.x.x
+
+PASS: Should be SyntaxErrorType None.
+Source: if(1)1
+
+
+-- Running test case: SyntaxErrorType.UnterminatedLiteral
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: 0b
+ ^
+Error Message: No binary digits after '0b'
+Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: 0o
+ ^
+Error Message: No octal digits after '0o'
+Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: 0x
+ ^
+Error Message: No hexadecimal digits after '0x'
+Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: 1e
+ ^~
+Error Message: Non-number found after exponent indicator
+Range: {"startOffset":0,"endOffset":2}
+
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: '
+ ^
+Error Message: Unexpected EOF
+Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: "
+ ^
+Error Message: Unexpected EOF
+Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType UnterminatedLiteral.
+Source: var \u007
+ ^~
+Error Message: Incomplete unicode escape in identifier: '\u'
+Range: {"startOffset":4,"endOffset":6}
+
+
+-- Running test case: SyntaxErrorType.Recoverable
+PASS: Should be SyntaxErrorType Recoverable.
+Source: (
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: {
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: !
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: -
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: +
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: ~
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: 1,
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":1,"endOffset":2}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":3}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: 'use strict'; let
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":14,"endOffset":17}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: const
+ ^~~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":5}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var {x
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":5,"endOffset":6}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var [x
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":5,"endOffset":6}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x,
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":5,"endOffset":6}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: if(1)
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":4,"endOffset":5}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: if(1){
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":5,"endOffset":6}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: if(1){}else
+ ^~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":7,"endOffset":11}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: if(1){}else{
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":11,"endOffset":12}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: while(1)
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":7,"endOffset":8}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: while(1){
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":8,"endOffset":9}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: for(;;)
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":6,"endOffset":7}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: for(;;){
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":7,"endOffset":8}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: ()=>
+ ^~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":2,"endOffset":4}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: ()=>{
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":4,"endOffset":5}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: /*
+ ^~
+Error Message: Multiline comment was not closed properly
+Error Range: {"startOffset":0,"endOffset":2}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: `
+ ^
+Error Message: Unexpected EOF
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: `${1}
+ ^
+Error Message: Unexpected EOF
+Error Range: {"startOffset":4,"endOffset":5}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: `${
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":3}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: function
+ ^~~~~~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":8}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: function foo
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":9,"endOffset":12}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: function foo(
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":12,"endOffset":13}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: function foo(){
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":14,"endOffset":15}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: (function() {
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":12,"endOffset":13}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: (function() {}
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":13,"endOffset":14}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: (function() {})(
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":15,"endOffset":16}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: switch(x)
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":8,"endOffset":9}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: switch(x){
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":9,"endOffset":10}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: switch(x){case
+ ^~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":10,"endOffset":14}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: switch(x){case 1
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":15,"endOffset":16}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: switch(x){case 1:
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":16,"endOffset":17}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: class
+ ^~~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":0,"endOffset":5}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: class Klass
+ ^~~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":6,"endOffset":11}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: class Klass {
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":12,"endOffset":13}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":8,"endOffset":9}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop
+ ^~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":9,"endOffset":13}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":13,"endOffset":14}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":14,"endOffset":17}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":14,"endOffset":17}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123,
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":17,"endOffset":18}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123,
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":17,"endOffset":18}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123, 'prop2'
+ ^~~~~~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":19,"endOffset":26}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123, [12
+ ^~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":20,"endOffset":22}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123, [12]
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":22,"endOffset":23}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123, [12]:
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":23,"endOffset":24}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = {prop:123, [12]:567
+ ^~~
+Error Message: Unexpected end of script
+Error Range: {"startOffset":24,"endOffset":27}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = [
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":8,"endOffset":9}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = [1
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":9,"endOffset":10}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = [1,
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":10,"endOffset":11}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = [1,[]
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":12,"endOffset":13}
+
+PASS: Should be SyntaxErrorType Recoverable.
+Source: var x = [1,{}
+ ^
+Error Message: Unexpected end of script
+Error Range: {"startOffset":12,"endOffset":13}
+
+
+-- Running test case: SyntaxErrorType.Irrecoverable
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: 1$
+ ^
+Error Message: No identifiers allowed directly after numeric literal
+Error Range: {"startOffset":0,"endOffset":1}
+
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: var x = {}}
+ ^
+Error Message: Parser error
+Error Range: {"startOffset":10,"endOffset":11}
+
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: ({}))
+ ^
+Error Message: Unexpected token ')'. Parse error.
+Error Range: {"startOffset":4,"endOffset":5}
+
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: var x = =
+ ^
+Error Message: Unexpected token '='
+Error Range: {"startOffset":8,"endOffset":9}
+
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: const x;
+ ^
+Error Message: Unexpected token ';'. const declared variable 'x' must have an initializer.
+Error Range: {"startOffset":7,"endOffset":8}
+
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: let x = 1; let x = 2;
+ ^
+Error Message: Cannot declare a let variable twice: 'x'.
+Error Range: {"startOffset":17,"endOffset":18}
+
+PASS: Should be SyntaxErrorType Irrecoverable.
+Source: if x(1)
+ ^
+Error Message: Unexpected identifier 'x'. Expected '(' to start a 'if' condition.
+Error Range: {"startOffset":3,"endOffset":4}
+
+
</ins></span></pre></div>
<a id="trunkLayoutTestsinspectorruntimeparsehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/inspector/runtime/parse.html (0 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/inspector/runtime/parse.html         (rev 0)
+++ trunk/LayoutTests/inspector/runtime/parse.html        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -0,0 +1,192 @@
</span><ins>+<!doctype html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+function test()
+{
+ InspectorTest.dumpActivityToSystemConsole = true;
+
+ function outputErrorSourceRange(range) {
+ var str = " ".repeat("Source: ".length);
+ str += " ".repeat(range.startOffset);
+ str += "^";
+ str += "~".repeat(range.endOffset - range.startOffset - 1);
+ InspectorTest.log(str);
+ }
+
+ let suite = InspectorTest.createAsyncSuite("Runtime.parse");
+
+ suite.addTestCase({
+ name: "SyntaxErrorType.None",
+ description: "Test source without an issue.",
+ test: (resolve, reject) => {
+ function testSource(source) {
+ RuntimeAgent.parse(source, (error, result, message, range) => {
+ InspectorTest.assert(!error, "Should not be a protocol error.");
+ InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.None, "Should be SyntaxErrorType None.");
+ InspectorTest.log("Source: " + source);
+ InspectorTest.assert(!message);
+ InspectorTest.assert(!range);
+ InspectorTest.log("");
+ });
+ }
+
+ // Complete programs without syntax errors (could have runtime errors).
+ testSource("");
+ testSource(";");
+ testSource("myVariable");
+ testSource("var x = 1; x");
+ testSource("[1,2,3]");
+ testSource("({})");
+ testSource("({prop:true}).x.x.x");
+ testSource("if(1)1");
+ InspectorBackend.runAfterPendingDispatches(resolve);
+ }
+ });
+
+ suite.addTestCase({
+ name: "SyntaxErrorType.UnterminatedLiteral",
+ description: "Test source with an unterminated literal.",
+ test: (resolve, reject) => {
+ function testSource(source) {
+ RuntimeAgent.parse(source, (error, result, message, range) => {
+ InspectorTest.assert(!error, "Should not be a protocol error.");
+ InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.UnterminatedLiteral, "Should be SyntaxErrorType UnterminatedLiteral.");
+ InspectorTest.log("Source: " + source);
+ outputErrorSourceRange(range);
+ InspectorTest.log("Error Message: " + message);
+ InspectorTest.log("Range: " + JSON.stringify(range));
+ InspectorTest.log("");
+ });
+ }
+
+ // A literal that is not yet complete, but would be a single token.
+ testSource("0b"); // binary
+ testSource("0o"); // octal
+ testSource("0x"); // hex
+ testSource("1e"); // scientific notation number
+ testSource("'"); // string
+ testSource("\""); // string
+ testSource("var \\u007"); // identifier unicode escape
+ // testSource("/r"); // regexp - Not detected by JavaScriptCore.
+ InspectorBackend.runAfterPendingDispatches(resolve);
+ }
+ });
+
+ suite.addTestCase({
+ name: "SyntaxErrorType.Recoverable",
+ description: "Test source with a recoverable error.",
+ test: (resolve, reject) => {
+ function testSource(source) {
+ RuntimeAgent.parse(source, (error, result, message, range) => {
+ InspectorTest.assert(!error, "Should not be a protocol error.");
+ InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.Recoverable, "Should be SyntaxErrorType Recoverable.");
+ InspectorTest.log("Source: " + source);
+ outputErrorSourceRange(range);
+ InspectorTest.log("Error Message: " + message);
+ InspectorTest.log("Error Range: " + JSON.stringify(range));
+ InspectorTest.log("");
+ });
+ }
+
+ // Not yet a syntax error, just an incomplete program.
+ testSource("(");
+ testSource("{");
+ testSource("!");
+ testSource("-"); // unary
+ testSource("+"); // unary
+ testSource("~"); // unary
+ testSource("1,");
+ testSource("var");
+ testSource("'use strict'; let"); // When not in strict mode, let is treated as the start of an identifier, not a keyword!
+ testSource("const");
+ testSource("var {x"); // destructuring
+ testSource("var [x"); // destructuring
+ testSource("var x,");
+ testSource("if(1)");
+ testSource("if(1){");
+ testSource("if(1){}else");
+ testSource("if(1){}else{");
+ testSource("while(1)");
+ testSource("while(1){");
+ testSource("for(;;)");
+ testSource("for(;;){");
+ testSource("()=>"); // arrow function
+ testSource("()=>{"); // arrow function
+ testSource("/*"); // comment
+ testSource("`"); // template string
+ testSource("`${1}"); // template string
+ testSource("`${"); // template string
+ testSource("function");
+ testSource("function foo");
+ testSource("function foo(");
+ testSource("function foo(){");
+ testSource("(function() {");
+ testSource("(function() {}");
+ testSource("(function() {})(");
+ testSource("switch(x)");
+ testSource("switch(x){");
+ testSource("switch(x){case");
+ testSource("switch(x){case 1");
+ testSource("switch(x){case 1:");
+ testSource("class");
+ testSource("class Klass");
+ testSource("class Klass {");
+ testSource("var x = {");
+ testSource("var x = {prop");
+ testSource("var x = {prop:");
+ testSource("var x = {prop:123");
+ testSource("var x = {prop:123 ");
+ testSource("var x = {prop:123,");
+ testSource("var x = {prop:123, ");
+ testSource("var x = {prop:123, 'prop2'");
+ testSource("var x = {prop:123, [12");
+ testSource("var x = {prop:123, [12]");
+ testSource("var x = {prop:123, [12]:");
+ testSource("var x = {prop:123, [12]:567");
+ testSource("var x = [");
+ testSource("var x = [1");
+ testSource("var x = [1,");
+ testSource("var x = [1,[]");
+ testSource("var x = [1,{}");
+ InspectorBackend.runAfterPendingDispatches(resolve);
+ }
+ });
+
+ suite.addTestCase({
+ name: "SyntaxErrorType.Irrecoverable",
+ description: "Test source with an irrecoverable issue.",
+ test: (resolve, reject) => {
+ function testSource(source) {
+ RuntimeAgent.parse(source, (error, result, message, range) => {
+ InspectorTest.assert(!error, "Should not be a protocol error.");
+ InspectorTest.expectThat(result === RuntimeAgent.SyntaxErrorType.Irrecoverable, "Should be SyntaxErrorType Irrecoverable.");
+ InspectorTest.log("Source: " + source);
+ outputErrorSourceRange(range);
+ InspectorTest.log("Error Message: " + message);
+ InspectorTest.log("Error Range: " + JSON.stringify(range));
+ InspectorTest.log("");
+ });
+ }
+
+ // SyntaxErrors. Any typing after the syntax error is detected does not matter.
+ testSource("1$");
+ testSource("var x = {}}");
+ testSource("({}))");
+ testSource("var x = =");
+ testSource("const x;");
+ testSource("let x = 1; let x = 2;");
+ testSource("if x(1)");
+ InspectorBackend.runAfterPendingDispatches(resolve);
+ }
+ });
+
+ suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Tests for the Runtime.parse command.</p>
+</body>
+</html>
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (189370 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-09-04 19:24:55 UTC (rev 189370)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -1,3 +1,21 @@
</span><ins>+2015-09-04 Joseph Pecoraro <pecoraro@apple.com>
+
+ Web Inspector: Test RuntimeAgent.parse, detecting if a script parse error is recoverable
+ https://bugs.webkit.org/show_bug.cgi?id=148790
+
+ Reviewed by Timothy Hatcher.
+
+ * parser/Lexer.cpp:
+ (JSC::Lexer<T>::lex):
+ * parser/Parser.cpp:
+ (JSC::Parser<LexerType>::printUnexpectedTokenText):
+ * parser/ParserTokens.h:
+ More consistently name and treat unterminated numeric literals.
+
+ * parser/Parser.h:
+ (JSC::Parser<LexerType>::parse):
+ Treat multiline capable unterminated literals as recoverable.
+
</ins><span class="cx"> 2015-08-25 Basile Clement <basile_clement@apple.com>
</span><span class="cx">
</span><span class="cx"> Get rid of FTLValueFormat
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserLexercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Lexer.cpp (189370 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Lexer.cpp        2015-09-04 19:24:55 UTC (rev 189370)
+++ trunk/Source/JavaScriptCore/parser/Lexer.cpp        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -2031,7 +2031,7 @@
</span><span class="cx"> if ((m_current | 0x20) == 'x') {
</span><span class="cx"> if (!isASCIIHexDigit(peek(1))) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("No hexadecimal digits after '0x'");
</span><del>- token = INVALID_HEX_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_HEX_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2041,7 +2041,7 @@
</span><span class="cx"> parseHex(tokenData->doubleValue);
</span><span class="cx"> if (isIdentStart(m_current)) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("No space between hexadecimal literal and identifier");
</span><del>- token = INVALID_HEX_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_HEX_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx"> token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
</span><span class="lines">@@ -2051,7 +2051,7 @@
</span><span class="cx"> if ((m_current | 0x20) == 'b') {
</span><span class="cx"> if (!isASCIIBinaryDigit(peek(1))) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("No binary digits after '0b'");
</span><del>- token = INVALID_BINARY_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_BINARY_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2061,7 +2061,7 @@
</span><span class="cx"> parseBinary(tokenData->doubleValue);
</span><span class="cx"> if (isIdentStart(m_current)) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("No space between binary literal and identifier");
</span><del>- token = INVALID_BINARY_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_BINARY_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx"> token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
</span><span class="lines">@@ -2072,7 +2072,7 @@
</span><span class="cx"> if ((m_current | 0x20) == 'o') {
</span><span class="cx"> if (!isASCIIOctalDigit(peek(1))) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("No octal digits after '0o'");
</span><del>- token = INVALID_OCTAL_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_OCTAL_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx">
</span><span class="lines">@@ -2082,7 +2082,7 @@
</span><span class="cx"> parseOctal(tokenData->doubleValue);
</span><span class="cx"> if (isIdentStart(m_current)) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("No space between octal literal and identifier");
</span><del>- token = INVALID_OCTAL_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_OCTAL_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx"> token = tokenTypeForIntegerLikeToken(tokenData->doubleValue);
</span><span class="lines">@@ -2093,7 +2093,7 @@
</span><span class="cx"> record8('0');
</span><span class="cx"> if (strictMode && isASCIIDigit(m_current)) {
</span><span class="cx"> m_lexErrorMessage = ASCIILiteral("Decimal integer literals with a leading zero are forbidden in strict mode");
</span><del>- token = INVALID_OCTAL_NUMBER_ERRORTOK;
</del><ins>+ token = UNTERMINATED_OCTAL_NUMBER_ERRORTOK;
</ins><span class="cx"> goto returnError;
</span><span class="cx"> }
</span><span class="cx"> if (isASCIIOctalDigit(m_current)) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (189370 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-09-04 19:24:55 UTC (rev 189370)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -3661,7 +3661,7 @@
</span><span class="cx"> case INVALID_NUMERIC_LITERAL_ERRORTOK:
</span><span class="cx"> out.print("Invalid numeric literal: '", getToken(), "'");
</span><span class="cx"> return;
</span><del>- case INVALID_OCTAL_NUMBER_ERRORTOK:
</del><ins>+ case UNTERMINATED_OCTAL_NUMBER_ERRORTOK:
</ins><span class="cx"> out.print("Invalid use of octal: '", getToken(), "'");
</span><span class="cx"> return;
</span><span class="cx"> case INVALID_STRING_LITERAL_ERRORTOK:
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.h (189370 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.h        2015-09-04 19:24:55 UTC (rev 189370)
+++ trunk/Source/JavaScriptCore/parser/Parser.h        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -1340,8 +1340,13 @@
</span><span class="cx"> ParserError::SyntaxErrorType errorType = ParserError::SyntaxErrorIrrecoverable;
</span><span class="cx"> if (m_token.m_type == EOFTOK)
</span><span class="cx"> errorType = ParserError::SyntaxErrorRecoverable;
</span><del>- else if (m_token.m_type & UnterminatedErrorTokenFlag)
- errorType = ParserError::SyntaxErrorUnterminatedLiteral;
</del><ins>+ else if (m_token.m_type & UnterminatedErrorTokenFlag) {
+ // Treat multiline capable unterminated literals as recoverable.
+ if (m_token.m_type == UNTERMINATED_MULTILINE_COMMENT_ERRORTOK || m_token.m_type == UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK)
+ errorType = ParserError::SyntaxErrorRecoverable;
+ else
+ errorType = ParserError::SyntaxErrorUnterminatedLiteral;
+ }
</ins><span class="cx">
</span><span class="cx"> if (isEvalNode<ParsedNode>())
</span><span class="cx"> error = ParserError(ParserError::EvalError, errorType, m_token, errMsg, errLine);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParserTokensh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ParserTokens.h (189370 => 189371)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ParserTokens.h        2015-09-04 19:24:55 UTC (rev 189370)
+++ trunk/Source/JavaScriptCore/parser/ParserTokens.h        2015-09-04 19:48:54 UTC (rev 189371)
</span><span class="lines">@@ -162,13 +162,13 @@
</span><span class="cx"> INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK = 3 | ErrorTokenFlag,
</span><span class="cx"> UNTERMINATED_MULTILINE_COMMENT_ERRORTOK = 4 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</span><span class="cx"> UNTERMINATED_NUMERIC_LITERAL_ERRORTOK = 5 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</span><del>- INVALID_OCTAL_NUMBER_ERRORTOK = 6 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</del><ins>+ UNTERMINATED_OCTAL_NUMBER_ERRORTOK = 6 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</ins><span class="cx"> INVALID_NUMERIC_LITERAL_ERRORTOK = 7 | ErrorTokenFlag,
</span><span class="cx"> UNTERMINATED_STRING_LITERAL_ERRORTOK = 8 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</span><span class="cx"> INVALID_STRING_LITERAL_ERRORTOK = 9 | ErrorTokenFlag,
</span><span class="cx"> INVALID_PRIVATE_NAME_ERRORTOK = 10 | ErrorTokenFlag,
</span><del>- INVALID_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag,
- INVALID_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag,
</del><ins>+ UNTERMINATED_HEX_NUMBER_ERRORTOK = 11 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
+ UNTERMINATED_BINARY_NUMBER_ERRORTOK = 12 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</ins><span class="cx"> UNTERMINATED_TEMPLATE_LITERAL_ERRORTOK = 13 | ErrorTokenFlag | UnterminatedErrorTokenFlag,
</span><span class="cx"> INVALID_TEMPLATE_LITERAL_ERRORTOK = 14 | ErrorTokenFlag,
</span><span class="cx"> };
</span></span></pre>
</div>
</div>
</body>
</html>