<!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>[197534] 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/197534">197534</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2016-03-03 17:24:28 -0800 (Thu, 03 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ES6] Make Unicode RegExp pattern parsing conform to the spec
https://bugs.webkit.org/show_bug.cgi?id=154988

Reviewed by Benjamin Poulain.

Source/JavaScriptCore:

Updated RegExp pattern processing with 'u' (Unicode) flag to conform to the
spec (https://tc39.github.io/ecma262/2016/#sec-patterns).  In the spec, the
grammar is annotated with [U] annotations.  Productions that are prefixed with
[+U] are only available with the Unicode flags while productions prefixed with
[~U] are only available without the Unicode flag.
        
Added flags argument to Yarr::checkSyntax() so we can catch Unicode flag related
parsing errors at syntax checking time.  Restricted what escapes are available for
non Unicode patterns.  Most of this is defined in the IdentityEscape rule in the
pattern grammar.

Added \- as a CharacterClass only escape in Unicode patterns.

Updated the tests for these changes.

Made changes suggested in https://bugs.webkit.org/show_bug.cgi?id=154842#c22 after
change set <a href="http://trac.webkit.org/projects/webkit/changeset/197426">r197426</a> was landed.

* parser/ASTBuilder.h:
(JSC::ASTBuilder::createRegExp):
* parser/Parser.cpp:
(JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createRegExp):
* yarr/YarrInterpreter.cpp:
(JSC::Yarr::Interpreter::InputStream::readChecked):
(JSC::Yarr::Interpreter::InputStream::readSurrogatePairChecked):
(JSC::Yarr::Interpreter::InputStream::reread):
(JSC::Yarr::Interpreter::InputStream::uncheckInput):
(JSC::Yarr::Interpreter::InputStream::atStart):
(JSC::Yarr::Interpreter::InputStream::atEnd):
(JSC::Yarr::Interpreter::testCharacterClass):
(JSC::Yarr::Interpreter::backtrackPatternCharacter):
(JSC::Yarr::Interpreter::matchDisjunction):
(JSC::Yarr::ByteCompiler::atomPatternCharacter):
* yarr/YarrParser.h:
(JSC::Yarr::Parser::Parser):
(JSC::Yarr::Parser::isIdentityEscapeAnError):
(JSC::Yarr::Parser::parseEscape):
(JSC::Yarr::Parser::parse):
* yarr/YarrPattern.cpp:
(JSC::Yarr::CharacterClassConstructor::putChar):
(JSC::Yarr::CharacterClassConstructor::putRange):
(JSC::Yarr::CharacterClassConstructor::addSorted):
(JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets):
* yarr/YarrSyntaxChecker.cpp:
(JSC::Yarr::SyntaxChecker::disjunction):
(JSC::Yarr::checkSyntax):
* yarr/YarrSyntaxChecker.h:

LayoutTests:

Added tests cases.

* js/regexp-unicode-expected.txt:
* js/script-tests/regexp-unicode.js:
(shouldThrowInvalidEscape):


[ES6] Add support for Symbol.toPrimitive
https://bugs.webkit.org/show_bug.cgi?id=154877

Reviewed by Saam Barati.

Update test for Symbol.toPrimitive.

* js/Object-getOwnPropertyNames-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsregexpunicodeexpectedtxt">trunk/LayoutTests/js/regexp-unicode-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsregexpunicodejs">trunk/LayoutTests/js/script-tests/regexp-unicode.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserASTBuilderh">trunk/Source/JavaScriptCore/parser/ASTBuilder.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserParsercpp">trunk/Source/JavaScriptCore/parser/Parser.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreparserSyntaxCheckerh">trunk/Source/JavaScriptCore/parser/SyntaxChecker.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpretercpp">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrParserh">trunk/Source/JavaScriptCore/yarr/YarrParser.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrPatterncpp">trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrSyntaxCheckercpp">trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrSyntaxCheckerh">trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/LayoutTests/ChangeLog        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -1,5 +1,17 @@
</span><del>-2016-03-03  Keith Miller  &lt;keith_miller@apple.com&gt;
</del><ins>+2016-03-03  Michael Saboff  &lt;msaboff@apple.com&gt;
</ins><span class="cx"> 
</span><ins>+        [ES6] Make Unicode RegExp pattern parsing conform to the spec
+        https://bugs.webkit.org/show_bug.cgi?id=154988
+
+        Reviewed by Benjamin Poulain.
+
+        Added tests cases.
+
+        * js/regexp-unicode-expected.txt:
+        * js/script-tests/regexp-unicode.js:
+        (shouldThrowInvalidEscape):
+
+
</ins><span class="cx">         [ES6] Add support for Symbol.toPrimitive
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=154877
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsjsregexpunicodeexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/regexp-unicode-expected.txt (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regexp-unicode-expected.txt        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/LayoutTests/js/regexp-unicode-expected.txt        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -3,19 +3,19 @@
</span><span class="cx"> On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
</span><span class="cx"> 
</span><span class="cx"> 
</span><del>-PASS &quot;a&quot;.match(/a/)[0].length is 1
-PASS &quot;a&quot;.match(/A/i)[0].length is 1
</del><span class="cx"> PASS &quot;a&quot;.match(/a/u)[0].length is 1
</span><ins>+PASS &quot;a&quot;.match(/A/ui)[0].length is 1
+PASS &quot;a&quot;.match(/a/u)[0].length is 1
</ins><span class="cx"> PASS &quot;a&quot;.match(/A/iu)[0].length is 1
</span><del>-PASS &quot;Ȓ&quot;.match(/Ȓ/)[0].length is 1
</del><span class="cx"> PASS &quot;Ȓ&quot;.match(/Ȓ/u)[0].length is 1
</span><del>-PASS &quot;ሴ&quot;.match(/ሴ/)[0].length is 1
</del><ins>+PASS &quot;Ȓ&quot;.match(/Ȓ/u)[0].length is 1
</ins><span class="cx"> PASS &quot;ሴ&quot;.match(/ሴ/u)[0].length is 1
</span><del>-PASS &quot;⪼&quot;.match(/⪼/)[0].length is 1
</del><ins>+PASS &quot;ሴ&quot;.match(/ሴ/u)[0].length is 1
+PASS &quot;⪼&quot;.match(/⪼/u)[0].length is 1
</ins><span class="cx"> PASS &quot;㿭&quot;.match(/㿭/u)[0].length is 1
</span><span class="cx"> PASS &quot;𒍅&quot;.match(/𒍅/u)[0].length is 2
</span><span class="cx"> PASS &quot;𒍅&quot;.match(/𒍅/u)[0].length is 2
</span><del>-PASS &quot;𝌆&quot;.match(/𝌆/)[0].length is 2
</del><ins>+PASS &quot;𝌆&quot;.match(/𝌆/u)[0].length is 2
</ins><span class="cx"> PASS /𐑏/u.test(&quot;𐑏&quot;) is true
</span><span class="cx"> PASS /𐑏/u.test(&quot;𐑏&quot;) is true
</span><span class="cx"> PASS &quot;𝌆&quot;.match(/𝌆/u)[0].length is 2
</span><span class="lines">@@ -41,6 +41,8 @@
</span><span class="cx"> PASS &quot;Ťx&quot;.match(/ťx/iu)[0].length is 2
</span><span class="cx"> PASS &quot;𝌆&quot;.match(/^.$/u)[0].length is 2
</span><span class="cx"> PASS &quot;It is 78°&quot;.match(/.*/u)[0].length is 9
</span><ins>+PASS stringWithDanglingFirstSurrogate.match(/.*/u)[0].length is 3
+PASS stringWithDanglingSecondSurrogate.match(/.*/u)[0].length is 3
</ins><span class="cx"> PASS &quot;𝌆&quot;.match(/[𝌆a]/)[0].length is 1
</span><span class="cx"> PASS &quot;𝌆&quot;.match(/[a𝌆]/u)[0].length is 2
</span><span class="cx"> PASS &quot;𝌆&quot;.match(/[𝌆a]/u)[0].length is 2
</span><span class="lines">@@ -91,6 +93,22 @@
</span><span class="cx"> PASS /abc/ui.test(&quot;ẚbc&quot;) is true
</span><span class="cx"> PASS /texẗ/ui.test(&quot;text&quot;) is true
</span><span class="cx"> PASS /text/ui.test(&quot;ẗext&quot;) is true
</span><ins>+PASS /\u{1}/.test(&quot;u&quot;) is true
+PASS /\u{4}/.test(&quot;u&quot;) is false
+PASS /\u{4}/.test(&quot;uuuu&quot;) is true
+PASS &quot;800-555-1212&quot;.match(/[0-9\-]*/u)[0].length is 12
+PASS &quot;this is ba test&quot;.match(/is b\cha test/u)[0].length is 11
+PASS new RegExp(&quot;\\/&quot;, &quot;u&quot;).source is &quot;\\/&quot;
+PASS r = new RegExp(&quot;\\u{110000}&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid unicode {} escape.
+PASS r = new RegExp(&quot;\\-&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;\\a&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;[\\a]&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;[\\b]&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;[\\B]&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;\\x&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;[\\x]&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;\\u&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
+PASS r = new RegExp(&quot;[\\u]&quot;, &quot;u&quot;) threw exception SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern.
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsregexpunicodejs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/regexp-unicode.js (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/regexp-unicode.js        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/LayoutTests/js/script-tests/regexp-unicode.js        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -3,19 +3,19 @@
</span><span class="cx"> );
</span><span class="cx"> 
</span><span class="cx"> // Test \u{} escapes in a regular expression
</span><del>-shouldBe('&quot;a&quot;.match(/\u{61}/)[0].length', '1');
-shouldBe('&quot;a&quot;.match(/\u{41}/i)[0].length', '1');
</del><ins>+shouldBe('&quot;a&quot;.match(/\u{61}/u)[0].length', '1');
+shouldBe('&quot;a&quot;.match(/\u{41}/ui)[0].length', '1');
</ins><span class="cx"> shouldBe('&quot;a&quot;.match(/\u{061}/u)[0].length', '1');
</span><span class="cx"> shouldBe('&quot;a&quot;.match(/\u{041}/iu)[0].length', '1');
</span><del>-shouldBe('&quot;\u{212}&quot;.match(/\u{212}/)[0].length', '1');
</del><ins>+shouldBe('&quot;\u{212}&quot;.match(/\u{212}/u)[0].length', '1');
</ins><span class="cx"> shouldBe('&quot;\u{212}&quot;.match(/\u{0212}/u)[0].length', '1');
</span><del>-shouldBe('&quot;\u{1234}&quot;.match(/\u{1234}/)[0].length', '1');
</del><ins>+shouldBe('&quot;\u{1234}&quot;.match(/\u{1234}/u)[0].length', '1');
</ins><span class="cx"> shouldBe('&quot;\u{1234}&quot;.match(/\u{01234}/u)[0].length', '1');
</span><del>-shouldBe('&quot;\u{2abc}&quot;.match(/\u{2abc}/)[0].length', '1');
</del><ins>+shouldBe('&quot;\u{2abc}&quot;.match(/\u{2abc}/u)[0].length', '1');
</ins><span class="cx"> shouldBe('&quot;\u{03fed}&quot;.match(/\u{03fed}/u)[0].length', '1');
</span><span class="cx"> shouldBe('&quot;\u{12345}&quot;.match(/\u{12345}/u)[0].length', '2');
</span><span class="cx"> shouldBe('&quot;\u{12345}&quot;.match(/\u{012345}/u)[0].length', '2');
</span><del>-shouldBe('&quot;\u{1d306}&quot;.match(/\u{1d306}/)[0].length', '2');
</del><ins>+shouldBe('&quot;\u{1d306}&quot;.match(/\u{1d306}/u)[0].length', '2');
</ins><span class="cx"> shouldBeTrue('/\u{1044f}/u.test(&quot;\ud801\udc4f&quot;)');
</span><span class="cx"> shouldBeTrue('/\ud801\udc4f/u.test(&quot;\u{1044f}&quot;)');
</span><span class="cx"> 
</span><span class="lines">@@ -47,15 +47,16 @@
</span><span class="cx"> // Test . matches with Unicode flag
</span><span class="cx"> shouldBe('&quot;\u{1D306}&quot;.match(/^.$/u)[0].length', '2');
</span><span class="cx"> shouldBe('&quot;It is 78\u00B0&quot;.match(/.*/u)[0].length', '9');
</span><del>-// FIXME: These tests are disabled until https://bugs.webkit.org/show_bug.cgi?id=154863 is fixed
-// shouldBe('&quot;\ud801XXX&quot;.match(/.*/u)[0].length', '4'); // We should match a dangling first surrogate as 1 character
-// shouldBe('&quot;X\udfffXX&quot;.match(/.*/u)[0].length', '4'); // We should match a dangling second surrogate as 1 character
</del><ins>+var stringWithDanglingFirstSurrogate = &quot;X\uD801X&quot;;
+shouldBe('stringWithDanglingFirstSurrogate.match(/.*/u)[0].length', '3'); // We should match a dangling first surrogate as 1 character
+var stringWithDanglingSecondSurrogate = &quot;X\uDF01X&quot;;
+shouldBe('stringWithDanglingSecondSurrogate.match(/.*/u)[0].length', '3'); // We should match a dangling second surrogate as 1 character
</ins><span class="cx"> 
</span><span class="cx"> // Test character classes with unicode characters with and without unicode flag
</span><del>-shouldBe('&quot;\u{1d306}&quot;.match(/[\u{1d306}a]/)[0].length', '1');
</del><ins>+shouldBe('&quot;\u{1d306}&quot;.match(/[\uD834\uDF06a]/)[0].length', '1');
</ins><span class="cx"> shouldBe('&quot;\u{1d306}&quot;.match(/[a\u{1d306}]/u)[0].length', '2');
</span><span class="cx"> shouldBe('&quot;\u{1d306}&quot;.match(/[\u{1d306}a]/u)[0].length', '2');
</span><del>-shouldBe('&quot;\u{1d306}&quot;.match(/[a-\u{1d306}]/)[0].length', '1');
</del><ins>+shouldBe('&quot;\u{1d306}&quot;.match(/[a-\uD834\uDF06]/)[0].length', '1');
</ins><span class="cx"> shouldBe('&quot;\u{1d306}&quot;.match(/[a-\u{1d306}]/u)[0].length', '2');
</span><span class="cx"> 
</span><span class="cx"> // Test a character class that is a range from one UTF16 to a Unicode character
</span><span class="lines">@@ -63,7 +64,7 @@
</span><span class="cx"> shouldBe('&quot;\u1000&quot;.match(/[\u0020-\ud801\udc4f]/u)[0].length', '1');
</span><span class="cx"> shouldBe('&quot;\ud801\udc27&quot;.match(/[\u0020-\ud801\udc4f]/u)[0].length', '2');
</span><span class="cx"> 
</span><del>-var re1 = new RegExp(&quot;[^\u0020-\ud801\udc4f]&quot;, &quot;u&quot;);
</del><ins>+var re1 = new RegExp(&quot;[^\u0020-\uD801\uDC4F]&quot;, &quot;u&quot;);
</ins><span class="cx"> shouldBeFalse('re1.test(&quot;Z&quot;)');
</span><span class="cx"> shouldBeFalse('re1.test(&quot;\u{1000}&quot;)');
</span><span class="cx"> shouldBeFalse('re1.test(&quot;\u{10400}&quot;)');
</span><span class="lines">@@ -135,8 +136,44 @@
</span><span class="cx"> shouldBeUndefined('match6[1]');
</span><span class="cx"> shouldBe('match6[2]', '&quot;\u{10412}\u{10412}&quot;');
</span><span class="cx"> 
</span><del>-// Miscellaneous tests
</del><ins>+// Check unicode case insensitive matches
</ins><span class="cx"> shouldBeTrue('/\u1e9Abc/ui.test(&quot;abc&quot;)');
</span><span class="cx"> shouldBeTrue('/abc/ui.test(&quot;\u1e9Abc&quot;)');
</span><span class="cx"> shouldBeTrue('/tex\u1e97/ui.test(&quot;text&quot;)');
</span><span class="cx"> shouldBeTrue('/text/ui.test(&quot;\u1e97ext&quot;)');
</span><ins>+
+// Verify that without the unicode flag, \u{} doesn't parse to a unicode escapes, but to a counted match of the character 'u'.
+shouldBeTrue('/\\u{1}/.test(&quot;u&quot;)');
+shouldBeFalse('/\\u{4}/.test(&quot;u&quot;)');
+shouldBeTrue('/\\u{4}/.test(&quot;uuuu&quot;)');
+
+// Check that \- escape works in a character class for a unicode pattern
+shouldBe('&quot;800-555-1212&quot;.match(/[0-9\\-]*/u)[0].length', '12');
+
+// Check that control letter escapes work with unicode flag
+shouldBe('&quot;this is b\ba test&quot;.match(/is b\\cha test/u)[0].length', '11');
+
+// Check that invalid unicode patterns throw exceptions
+shouldBe('new RegExp(&quot;\\\\/&quot;, &quot;u&quot;).source', '&quot;\\\\/&quot;');
+shouldThrow('r = new RegExp(&quot;\\\\u{110000}&quot;, &quot;u&quot;)', '&quot;SyntaxError: Invalid regular expression: invalid unicode {} escape&quot;');
+
+var invalidEscapeException = &quot;SyntaxError: Invalid regular expression: invalid escaped character for unicode pattern&quot;;
+var newRegExp;
+
+function shouldThrowInvalidEscape(pattern)
+{
+    newRegExp = 'r = new RegExp(&quot;' + pattern + '&quot;, &quot;u&quot;)';
+
+    shouldThrow(newRegExp, 'invalidEscapeException');
+}
+
+shouldThrowInvalidEscape(&quot;\\\\-&quot;);
+shouldThrowInvalidEscape(&quot;\\\\a&quot;);
+shouldThrowInvalidEscape(&quot;[\\\\a]&quot;);
+shouldThrowInvalidEscape(&quot;[\\\\b]&quot;);
+shouldThrowInvalidEscape(&quot;[\\\\B]&quot;);
+shouldThrowInvalidEscape(&quot;\\\\x&quot;);
+shouldThrowInvalidEscape(&quot;[\\\\x]&quot;);
+shouldThrowInvalidEscape(&quot;\\\\u&quot;);
+shouldThrowInvalidEscape(&quot;[\\\\u]&quot;);
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -1,3 +1,60 @@
</span><ins>+2016-03-03  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        [ES6] Make Unicode RegExp pattern parsing conform to the spec
+        https://bugs.webkit.org/show_bug.cgi?id=154988
+
+        Reviewed by Benjamin Poulain.
+
+        Updated RegExp pattern processing with 'u' (Unicode) flag to conform to the
+        spec (https://tc39.github.io/ecma262/2016/#sec-patterns).  In the spec, the
+        grammar is annotated with [U] annotations.  Productions that are prefixed with
+        [+U] are only available with the Unicode flags while productions prefixed with
+        [~U] are only available without the Unicode flag.
+        
+        Added flags argument to Yarr::checkSyntax() so we can catch Unicode flag related
+        parsing errors at syntax checking time.  Restricted what escapes are available for
+        non Unicode patterns.  Most of this is defined in the IdentityEscape rule in the
+        pattern grammar.
+
+        Added \- as a CharacterClass only escape in Unicode patterns.
+
+        Updated the tests for these changes.
+
+        Made changes suggested in https://bugs.webkit.org/show_bug.cgi?id=154842#c22 after
+        change set r197426 was landed.
+
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createRegExp):
+        * parser/Parser.cpp:
+        (JSC::Parser&lt;LexerType&gt;::parsePrimaryExpression):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createRegExp):
+        * yarr/YarrInterpreter.cpp:
+        (JSC::Yarr::Interpreter::InputStream::readChecked):
+        (JSC::Yarr::Interpreter::InputStream::readSurrogatePairChecked):
+        (JSC::Yarr::Interpreter::InputStream::reread):
+        (JSC::Yarr::Interpreter::InputStream::uncheckInput):
+        (JSC::Yarr::Interpreter::InputStream::atStart):
+        (JSC::Yarr::Interpreter::InputStream::atEnd):
+        (JSC::Yarr::Interpreter::testCharacterClass):
+        (JSC::Yarr::Interpreter::backtrackPatternCharacter):
+        (JSC::Yarr::Interpreter::matchDisjunction):
+        (JSC::Yarr::ByteCompiler::atomPatternCharacter):
+        * yarr/YarrParser.h:
+        (JSC::Yarr::Parser::Parser):
+        (JSC::Yarr::Parser::isIdentityEscapeAnError):
+        (JSC::Yarr::Parser::parseEscape):
+        (JSC::Yarr::Parser::parse):
+        * yarr/YarrPattern.cpp:
+        (JSC::Yarr::CharacterClassConstructor::putChar):
+        (JSC::Yarr::CharacterClassConstructor::putRange):
+        (JSC::Yarr::CharacterClassConstructor::addSorted):
+        (JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets):
+        * yarr/YarrSyntaxChecker.cpp:
+        (JSC::Yarr::SyntaxChecker::disjunction):
+        (JSC::Yarr::checkSyntax):
+        * yarr/YarrSyntaxChecker.h:
+
</ins><span class="cx"> 2016-03-03  Saam barati  &lt;sbarati@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [ES6] Implement Proxy.[[DefineOwnProperty]]
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserASTBuilderh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/ASTBuilder.h (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/parser/ASTBuilder.h        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -311,7 +311,7 @@
</span><span class="cx"> 
</span><span class="cx">     ExpressionNode* createRegExp(const JSTokenLocation&amp; location, const Identifier&amp; pattern, const Identifier&amp; flags, const JSTextPosition&amp; start)
</span><span class="cx">     {
</span><del>-        if (Yarr::checkSyntax(pattern.string()))
</del><ins>+        if (Yarr::checkSyntax(pattern.string(), flags.string()))
</ins><span class="cx">             return 0;
</span><span class="cx">         RegExpNode* node = new (m_parserArena) RegExpNode(location, pattern, flags);
</span><span class="cx">         int size = pattern.length() + 2; // + 2 for the two /'s
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserParsercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/Parser.cpp (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/parser/Parser.cpp        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -3684,7 +3684,7 @@
</span><span class="cx">         next();
</span><span class="cx">         TreeExpression re = context.createRegExp(location, *pattern, *flags, start);
</span><span class="cx">         if (!re) {
</span><del>-            const char* yarrErrorMsg = Yarr::checkSyntax(pattern-&gt;string());
</del><ins>+            const char* yarrErrorMsg = Yarr::checkSyntax(pattern-&gt;string(), flags-&gt;string());
</ins><span class="cx">             regexFail(yarrErrorMsg);
</span><span class="cx">         }
</span><span class="cx">         return re;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreparserSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/parser/SyntaxChecker.h (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/parser/SyntaxChecker.h        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -172,7 +172,7 @@
</span><span class="cx">     ExpressionType createNull(const JSTokenLocation&amp;) { return NullExpr; }
</span><span class="cx">     ExpressionType createBracketAccess(const JSTokenLocation&amp;, ExpressionType, ExpressionType, bool, int, int, int) { return BracketExpr; }
</span><span class="cx">     ExpressionType createDotAccess(const JSTokenLocation&amp;, ExpressionType, const Identifier*, int, int, int) { return DotExpr; }
</span><del>-    ExpressionType createRegExp(const JSTokenLocation&amp;, const Identifier&amp; pattern, const Identifier&amp;, int) { return Yarr::checkSyntax(pattern.string()) ? 0 : RegExpExpr; }
</del><ins>+    ExpressionType createRegExp(const JSTokenLocation&amp;, const Identifier&amp; pattern, const Identifier&amp; flags, int) { return Yarr::checkSyntax(pattern.string(), flags.string()) ? 0 : RegExpExpr; }
</ins><span class="cx">     ExpressionType createNewExpr(const JSTokenLocation&amp;, ExpressionType, int, int, int, int) { return NewExpr; }
</span><span class="cx">     ExpressionType createNewExpr(const JSTokenLocation&amp;, ExpressionType, int, int) { return NewExpr; }
</span><span class="cx">     ExpressionType createConditionalExpr(const JSTokenLocation&amp;, ExpressionType, ExpressionType, ExpressionType) { return ConditionalExpr; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -208,8 +208,7 @@
</span><span class="cx">             unsigned p = pos - negativePositionOffest;
</span><span class="cx">             ASSERT(p &lt; length);
</span><span class="cx">             int result = input[p];
</span><del>-            if (U16_IS_LEAD(result) &amp;&amp; decodeSurrogatePairs &amp;&amp; p + 1 &lt; length
-                &amp;&amp; U16_IS_TRAIL(input[p + 1])) {
</del><ins>+            if (U16_IS_LEAD(result) &amp;&amp; decodeSurrogatePairs &amp;&amp; p + 1 &lt; length &amp;&amp; U16_IS_TRAIL(input[p + 1])) {
</ins><span class="cx">                 if (atEnd())
</span><span class="cx">                     return -1;
</span><span class="cx">                 
</span><span class="lines">@@ -219,17 +218,18 @@
</span><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        int readSurrogatePairChecked(unsigned negativePositionOffest)
</del><ins>+        int readSurrogatePairChecked(unsigned negativePositionOffset)
</ins><span class="cx">         {
</span><del>-            RELEASE_ASSERT(pos &gt;= negativePositionOffest);
-            unsigned p = pos - negativePositionOffest;
</del><ins>+            RELEASE_ASSERT(pos &gt;= negativePositionOffset);
+            unsigned p = pos - negativePositionOffset;
</ins><span class="cx">             ASSERT(p &lt; length);
</span><span class="cx">             if (p + 1 &gt;= length)
</span><span class="cx">                 return -1;
</span><span class="cx"> 
</span><span class="cx">             int first = input[p];
</span><del>-            if (U16_IS_LEAD(first) &amp;&amp; U16_IS_TRAIL(input[p + 1]))
-                return U16_GET_SUPPLEMENTARY(first, input[p + 1]);
</del><ins>+            int second = input[p + 1];
+            if (U16_IS_LEAD(first) &amp;&amp; U16_IS_TRAIL(second))
+                return U16_GET_SUPPLEMENTARY(first, second);
</ins><span class="cx"> 
</span><span class="cx">             return -1;
</span><span class="cx">         }
</span><span class="lines">@@ -238,11 +238,8 @@
</span><span class="cx">         {
</span><span class="cx">             ASSERT(from &lt; length);
</span><span class="cx">             int result = input[from];
</span><del>-            if (U16_IS_LEAD(result) &amp;&amp; decodeSurrogatePairs &amp;&amp; from + 1 &lt; length
-                &amp;&amp; U16_IS_TRAIL(input[from + 1])) {
-                
</del><ins>+            if (U16_IS_LEAD(result) &amp;&amp; decodeSurrogatePairs &amp;&amp; from + 1 &lt; length &amp;&amp; U16_IS_TRAIL(input[from + 1]))
</ins><span class="cx">                 result = U16_GET_SUPPLEMENTARY(result, input[from + 1]);
</span><del>-            }
</del><span class="cx">             return result;
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -294,9 +291,9 @@
</span><span class="cx">             pos -= count;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        bool atStart(unsigned negativePositionOffest)
</del><ins>+        bool atStart(unsigned negativePositionOffset)
</ins><span class="cx">         {
</span><del>-            return pos == negativePositionOffest;
</del><ins>+            return pos == negativePositionOffset;
</ins><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         bool atEnd(unsigned negativePositionOffest)
</span><span class="lines">@@ -319,7 +316,7 @@
</span><span class="cx"> 
</span><span class="cx">     bool testCharacterClass(CharacterClass* characterClass, int ch)
</span><span class="cx">     {
</span><del>-        if (ch &amp; 0x1FFF80) {
</del><ins>+        if (!isASCII(ch)) {
</ins><span class="cx">             for (unsigned i = 0; i &lt; characterClass-&gt;m_matchesUnicode.size(); ++i)
</span><span class="cx">                 if (ch == characterClass-&gt;m_matchesUnicode[i])
</span><span class="cx">                     return true;
</span><span class="lines">@@ -433,10 +430,7 @@
</span><span class="cx">         case QuantifierGreedy:
</span><span class="cx">             if (backTrack-&gt;matchAmount) {
</span><span class="cx">                 --backTrack-&gt;matchAmount;
</span><del>-                if (unicode &amp;&amp; !U_IS_BMP(term.atom.patternCharacter))
-                    input.uncheckInput(2);
-                else
-                    input.uncheckInput(1);
</del><ins>+                input.uncheckInput(U16_LENGTH(term.atom.patternCharacter));
</ins><span class="cx">                 return true;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="lines">@@ -1267,7 +1261,7 @@
</span><span class="cx">         case ByteTerm::TypePatternCasedCharacterOnce:
</span><span class="cx">         case ByteTerm::TypePatternCasedCharacterFixed: {
</span><span class="cx">             if (unicode) {
</span><del>-                // Case insensitive matching of unicode charaters are handled as TypeCharacterClass
</del><ins>+                // Case insensitive matching of unicode characters is handled as TypeCharacterClass.
</ins><span class="cx">                 ASSERT(U_IS_BMP(currentTerm().atom.patternCharacter));
</span><span class="cx"> 
</span><span class="cx">                 unsigned position = input.getPos(); // May need to back out reading a surrogate pair.
</span><span class="lines">@@ -1290,7 +1284,7 @@
</span><span class="cx">         case ByteTerm::TypePatternCasedCharacterGreedy: {
</span><span class="cx">             BackTrackInfoPatternCharacter* backTrack = reinterpret_cast&lt;BackTrackInfoPatternCharacter*&gt;(context-&gt;frame + currentTerm().frameLocation);
</span><span class="cx"> 
</span><del>-            // Case insensitive matching of unicode charaters are handled as TypeCharacterClass
</del><ins>+            // Case insensitive matching of unicode characters is handled as TypeCharacterClass.
</ins><span class="cx">             ASSERT(!unicode || U_IS_BMP(currentTerm().atom.patternCharacter));
</span><span class="cx"> 
</span><span class="cx">             unsigned matchAmount = 0;
</span><span class="lines">@@ -1308,7 +1302,7 @@
</span><span class="cx">         case ByteTerm::TypePatternCasedCharacterNonGreedy: {
</span><span class="cx">             BackTrackInfoPatternCharacter* backTrack = reinterpret_cast&lt;BackTrackInfoPatternCharacter*&gt;(context-&gt;frame + currentTerm().frameLocation);
</span><span class="cx"> 
</span><del>-            // Case insensitive matching of unicode charaters are handled as TypeCharacterClass
</del><ins>+            // Case insensitive matching of unicode characters is handled as TypeCharacterClass.
</ins><span class="cx">             ASSERT(!unicode || U_IS_BMP(currentTerm().atom.patternCharacter));
</span><span class="cx">             
</span><span class="cx">             backTrack-&gt;matchAmount = 0;
</span><span class="lines">@@ -1618,9 +1612,6 @@
</span><span class="cx">     void atomPatternCharacter(UChar32 ch, unsigned inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</span><span class="cx">     {
</span><span class="cx">         if (m_pattern.m_ignoreCase) {
</span><del>-            ASSERT(u_tolower(ch) &lt;= UCHAR_MAX_VALUE);
-            ASSERT(u_toupper(ch) &lt;= UCHAR_MAX_VALUE);
-
</del><span class="cx">             UChar32 lo = u_tolower(ch);
</span><span class="cx">             UChar32 hi = u_toupper(ch);
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrParserh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrParser.h (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrParser.h        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/yarr/YarrParser.h        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -61,6 +61,7 @@
</span><span class="cx">         CharacterClassOutOfOrder,
</span><span class="cx">         EscapeUnterminated,
</span><span class="cx">         InvalidUnicodeEscape,
</span><ins>+        InvalidIdentityEscape,
</ins><span class="cx">         NumberOfErrorCodes
</span><span class="cx">     };
</span><span class="cx"> 
</span><span class="lines">@@ -241,6 +242,19 @@
</span><span class="cx">     {
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // The handling of IdentityEscapes is different depending on the unicode flag.
+    // For Unicode patterns, IdentityEscapes only include SyntaxCharacters or '/'.
+    // For non-unicode patterns, most any character can be escaped.
+    bool isIdentityEscapeAnError(int ch)
+    {
+        if (m_isUnicode &amp;&amp; !strchr(&quot;^$\\.*+?()[]{}|/&quot;, ch)) {
+            m_err = InvalidIdentityEscape;
+            return true;
+        }
+
+        return false;
+    }
+
</ins><span class="cx">     /*
</span><span class="cx">      * parseEscape():
</span><span class="cx">      *
</span><span class="lines">@@ -277,18 +291,24 @@
</span><span class="cx">         // Assertions
</span><span class="cx">         case 'b':
</span><span class="cx">             consume();
</span><del>-            if (inCharacterClass)
</del><ins>+            if (inCharacterClass) {
+                if (isIdentityEscapeAnError('b'))
+                    break;
+
</ins><span class="cx">                 delegate.atomPatternCharacter('\b');
</span><del>-            else {
</del><ins>+            } else {
</ins><span class="cx">                 delegate.assertionWordBoundary(false);
</span><span class="cx">                 return false;
</span><span class="cx">             }
</span><span class="cx">             break;
</span><span class="cx">         case 'B':
</span><span class="cx">             consume();
</span><del>-            if (inCharacterClass)
</del><ins>+            if (inCharacterClass) {
+                if (isIdentityEscapeAnError('B'))
+                    break;
+
</ins><span class="cx">                 delegate.atomPatternCharacter('B');
</span><del>-            else {
</del><ins>+            } else {
</ins><span class="cx">                 delegate.assertionWordBoundary(true);
</span><span class="cx">                 return false;
</span><span class="cx">             }
</span><span class="lines">@@ -403,9 +423,12 @@
</span><span class="cx">         case 'x': {
</span><span class="cx">             consume();
</span><span class="cx">             int x = tryConsumeHex(2);
</span><del>-            if (x == -1)
</del><ins>+            if (x == -1) {
+                if (isIdentityEscapeAnError('x'))
+                    break;
+
</ins><span class="cx">                 delegate.atomPatternCharacter('x');
</span><del>-            else
</del><ins>+            } else
</ins><span class="cx">                 delegate.atomPatternCharacter(x);
</span><span class="cx">             break;
</span><span class="cx">         }
</span><span class="lines">@@ -414,20 +437,23 @@
</span><span class="cx">         case 'u': {
</span><span class="cx">             consume();
</span><span class="cx">             if (atEndOfPattern()) {
</span><ins>+                if (isIdentityEscapeAnError('u'))
+                    break;
+
</ins><span class="cx">                 delegate.atomPatternCharacter('u');
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            if (peek() == '{') {
</del><ins>+            if (m_isUnicode &amp;&amp; peek() == '{') {
</ins><span class="cx">                 consume();
</span><span class="cx">                 UChar32 codePoint = 0;
</span><span class="cx">                 do {
</span><span class="cx">                     if (atEndOfPattern())
</span><span class="cx">                         m_err = InvalidUnicodeEscape;
</span><del>-                    if (!WTF::isASCIIHexDigit(peek()))
</del><ins>+                    if (!isASCIIHexDigit(peek()))
</ins><span class="cx">                         m_err = InvalidUnicodeEscape;
</span><span class="cx"> 
</span><del>-                    codePoint = (codePoint &lt;&lt; 4) | WTF::toASCIIHexValue(consume());
</del><ins>+                    codePoint = (codePoint &lt;&lt; 4) | toASCIIHexValue(consume());
</ins><span class="cx"> 
</span><span class="cx">                     if (codePoint &gt; UCHAR_MAX_VALUE)
</span><span class="cx">                         m_err = InvalidUnicodeEscape;
</span><span class="lines">@@ -441,9 +467,12 @@
</span><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             int u = tryConsumeHex(4);
</span><del>-            if (u == -1)
</del><ins>+            if (u == -1) {
+                if (isIdentityEscapeAnError('u'))
+                    break;
+
</ins><span class="cx">                 delegate.atomPatternCharacter('u');
</span><del>-            else {
</del><ins>+            } else {
</ins><span class="cx">                 // If we have the first of a surrogate pair, look for the second.
</span><span class="cx">                 if (U16_IS_LEAD(u) &amp;&amp; m_isUnicode &amp;&amp; (patternRemaining() &gt;= 6) &amp;&amp; peek() == '\\') {
</span><span class="cx">                     ParseState state = saveState();
</span><span class="lines">@@ -467,6 +496,17 @@
</span><span class="cx"> 
</span><span class="cx">         // IdentityEscape
</span><span class="cx">         default:
</span><ins>+            int ch = peek();
+
+            if (ch == '-' &amp;&amp; m_isUnicode &amp;&amp; inCharacterClass) {
+                // \- is allowed for ClassEscape with unicode flag.
+                delegate.atomPatternCharacter(consume());
+                break;
+            }
+
+            if (isIdentityEscapeAnError(ch))
+                break;
+
</ins><span class="cx">             delegate.atomPatternCharacter(consume());
</span><span class="cx">         }
</span><span class="cx">         
</span><span class="lines">@@ -762,8 +802,9 @@
</span><span class="cx">             REGEXP_ERROR_PREFIX &quot;unrecognized character after (?&quot;,
</span><span class="cx">             REGEXP_ERROR_PREFIX &quot;missing terminating ] for character class&quot;,
</span><span class="cx">             REGEXP_ERROR_PREFIX &quot;range out of order in character class&quot;,
</span><del>-            REGEXP_ERROR_PREFIX &quot;\\ at end of pattern&quot;
-            REGEXP_ERROR_PREFIX &quot;invalid unicode {} escape&quot;
</del><ins>+            REGEXP_ERROR_PREFIX &quot;\\ at end of pattern&quot;,
+            REGEXP_ERROR_PREFIX &quot;invalid unicode {} escape&quot;,
+            REGEXP_ERROR_PREFIX &quot;invalid escaped character for unicode pattern&quot;
</ins><span class="cx">         };
</span><span class="cx"> 
</span><span class="cx">         return errorMessages[m_err];
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrPatterncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -69,7 +69,7 @@
</span><span class="cx">     void putChar(UChar32 ch)
</span><span class="cx">     {
</span><span class="cx">         // Handle ascii cases.
</span><del>-        if (ch &lt;= 0x7f) {
</del><ins>+        if (isASCII(ch)) {
</ins><span class="cx">             if (m_isCaseInsensitive &amp;&amp; isASCIIAlpha(ch)) {
</span><span class="cx">                 addSorted(m_matches, toASCIIUpper(ch));
</span><span class="cx">                 addSorted(m_matches, toASCIILower(ch));
</span><span class="lines">@@ -108,7 +108,7 @@
</span><span class="cx"> 
</span><span class="cx">     void putRange(UChar32 lo, UChar32 hi)
</span><span class="cx">     {
</span><del>-        if (lo &lt;= 0x7f) {
</del><ins>+        if (isASCII(lo)) {
</ins><span class="cx">             char asciiLo = lo;
</span><span class="cx">             char asciiHi = std::min(hi, (UChar32)0x7f);
</span><span class="cx">             addSortedRange(m_ranges, lo, asciiHi);
</span><span class="lines">@@ -120,7 +120,7 @@
</span><span class="cx">                     addSortedRange(m_ranges, std::max(asciiLo, 'a')+('A'-'a'), std::min(asciiHi, 'z')+('A'-'a'));
</span><span class="cx">             }
</span><span class="cx">         }
</span><del>-        if (hi &lt;= 0x7f)
</del><ins>+        if (isASCII(hi))
</ins><span class="cx">             return;
</span><span class="cx"> 
</span><span class="cx">         lo = std::max(lo, (UChar32)0x80);
</span><span class="lines">@@ -190,7 +190,7 @@
</span><span class="cx"> private:
</span><span class="cx">     void addSorted(UChar32 ch)
</span><span class="cx">     {
</span><del>-        addSorted(ch &lt;= 0x7f ? m_matches : m_matchesUnicode, ch);
</del><ins>+        addSorted(isASCII(ch) ? m_matches : m_matchesUnicode, ch);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     void addSorted(Vector&lt;UChar32&gt;&amp; matches, UChar32 ch)
</span><span class="lines">@@ -603,7 +603,7 @@
</span><span class="cx">                     currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter;
</span><span class="cx">                     alternative-&gt;m_hasFixedSize = false;
</span><span class="cx">                 } else if (m_pattern.m_unicode) {
</span><del>-                    currentInputPosition += (!U_IS_BMP(term.patternCharacter) ? 2 : 1) * term.quantityCount;
</del><ins>+                    currentInputPosition += U16_LENGTH(term.patternCharacter) * term.quantityCount;
</ins><span class="cx">                 } else
</span><span class="cx">                     currentInputPosition += term.quantityCount;
</span><span class="cx">                 break;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrSyntaxCheckercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.cpp        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -50,10 +50,10 @@
</span><span class="cx">     void disjunction() {}
</span><span class="cx"> };
</span><span class="cx"> 
</span><del>-const char* checkSyntax(const String&amp; pattern)
</del><ins>+const char* checkSyntax(const String&amp; pattern, const String&amp; flags)
</ins><span class="cx"> {
</span><span class="cx">     SyntaxChecker syntaxChecker;
</span><del>-    return parse(syntaxChecker, pattern, false);
</del><ins>+    return parse(syntaxChecker, pattern, flags.contains('u'));
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> }} // JSC::YARR
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrSyntaxCheckerh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h (197533 => 197534)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h        2016-03-04 01:07:04 UTC (rev 197533)
+++ trunk/Source/JavaScriptCore/yarr/YarrSyntaxChecker.h        2016-03-04 01:24:28 UTC (rev 197534)
</span><span class="lines">@@ -30,7 +30,7 @@
</span><span class="cx"> 
</span><span class="cx"> namespace JSC { namespace Yarr {
</span><span class="cx"> 
</span><del>-const char* checkSyntax(const String&amp; pattern);
</del><ins>+const char* checkSyntax(const String&amp; pattern, const String&amp; flags);
</ins><span class="cx"> 
</span><span class="cx"> }} // JSC::YARR
</span><span class="cx"> 
</span></span></pre>
</div>
</div>

</body>
</html>