<!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>[197869] 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/197869">197869</a></dd>
<dt>Author</dt> <dd>msaboff@apple.com</dd>
<dt>Date</dt> <dd>2016-03-09 12:11:46 -0800 (Wed, 09 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>[ES6] Implement RegExp sticky flag and related functionality
https://bugs.webkit.org/show_bug.cgi?id=155177

Reviewed by Saam Barati.

Source/JavaScriptCore:

Implemented the ES6 RegExp sticky functionality.

There are two main behavior changes when the sticky flag is specified.
1) Matching starts at lastIndex and lastIndex is updated after the match.
2) The regular expression is only matched from the start position in the string.
See ES6 section 21.2.5.2.2 for details.

Changed both the Yarr interpreter and jit to not loop to the next character for sticky RegExp's.
Updated RegExp exec and match, and stringProtoFuncMatch to handle lastIndex changes.

Restructured the way flags are passed to and through YarrPatterns to use RegExpFlags instead of
individual bools.

Updated tests for 'y' flag and new behavior.

* bytecode/CodeBlock.cpp:
(JSC::regexpToSourceString):
* inspector/ContentSearchUtilities.cpp:
(Inspector::ContentSearchUtilities::findMagicComment):
* runtime/CommonIdentifiers.h:
* runtime/RegExp.cpp:
(JSC::regExpFlags):
(JSC::RegExpFunctionalTestCollector::outputOneTest):
(JSC::RegExp::finishCreation):
(JSC::RegExp::compile):
(JSC::RegExp::compileMatchOnly):
* runtime/RegExp.h:
* runtime/RegExpKey.h:
* runtime/RegExpObjectInlines.h:
(JSC::RegExpObject::execInline):
(JSC::RegExpObject::matchInline):
* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncCompile):
(JSC::flagsString):
(JSC::regExpProtoGetterMultiline):
(JSC::regExpProtoGetterSticky):
(JSC::regExpProtoGetterUnicode):
* runtime/StringPrototype.cpp:
(JSC::stringProtoFuncMatch):
* tests/es6.yaml:
* tests/stress/static-getter-in-names.js:
(shouldBe):
* yarr/RegularExpression.cpp:
(JSC::Yarr::RegularExpression::Private::compile):
* yarr/YarrInterpreter.cpp:
(JSC::Yarr::Interpreter::tryConsumeBackReference):
(JSC::Yarr::Interpreter::matchAssertionBOL):
(JSC::Yarr::Interpreter::matchAssertionEOL):
(JSC::Yarr::Interpreter::matchAssertionWordBoundary):
(JSC::Yarr::Interpreter::matchDotStarEnclosure):
(JSC::Yarr::Interpreter::matchDisjunction):
(JSC::Yarr::Interpreter::Interpreter):
(JSC::Yarr::ByteCompiler::atomPatternCharacter):
* yarr/YarrInterpreter.h:
(JSC::Yarr::BytecodePattern::BytecodePattern):
(JSC::Yarr::BytecodePattern::estimatedSizeInBytes):
(JSC::Yarr::BytecodePattern::ignoreCase):
(JSC::Yarr::BytecodePattern::multiline):
(JSC::Yarr::BytecodePattern::sticky):
(JSC::Yarr::BytecodePattern::unicode):
* yarr/YarrJIT.cpp:
(JSC::Yarr::YarrGenerator::matchCharacterClass):
(JSC::Yarr::YarrGenerator::jumpIfCharNotEquals):
(JSC::Yarr::YarrGenerator::generateAssertionBOL):
(JSC::Yarr::YarrGenerator::generateAssertionEOL):
(JSC::Yarr::YarrGenerator::generatePatternCharacterOnce):
(JSC::Yarr::YarrGenerator::generatePatternCharacterFixed):
(JSC::Yarr::YarrGenerator::generateDotStarEnclosure):
(JSC::Yarr::YarrGenerator::backtrack):
* yarr/YarrPattern.cpp:
(JSC::Yarr::YarrPatternConstructor::YarrPatternConstructor):
(JSC::Yarr::YarrPatternConstructor::atomPatternCharacter):
(JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets):
(JSC::Yarr::YarrPatternConstructor::optimizeBOL):
(JSC::Yarr::YarrPattern::compile):
(JSC::Yarr::YarrPattern::YarrPattern):
* yarr/YarrPattern.h:
(JSC::Yarr::YarrPattern::reset):
(JSC::Yarr::YarrPattern::nonwordcharCharacterClass):
(JSC::Yarr::YarrPattern::ignoreCase):
(JSC::Yarr::YarrPattern::multiline):
(JSC::Yarr::YarrPattern::sticky):
(JSC::Yarr::YarrPattern::unicode):

LayoutTests:

New and updated tests.

* js/Object-getOwnPropertyNames-expected.txt:
* js/regexp-flags-expected.txt:
* js/regexp-sticky-expected.txt: Added.
* js/regexp-sticky.html: Added.
* js/script-tests/Object-getOwnPropertyNames.js:
* js/script-tests/regexp-flags.js:
(RegExp.prototype.hasOwnProperty): Deleted check for sticky property.
* js/script-tests/regexp-sticky.js: New test.
(asString):
(testStickyExec):
(testStickyMatch):</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsjsObjectgetOwnPropertyNamesexpectedtxt">trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregexpflagsexpectedtxt">trunk/LayoutTests/js/regexp-flags-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsObjectgetOwnPropertyNamesjs">trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsregexpflagsjs">trunk/LayoutTests/js/script-tests/regexp-flags.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCorebytecodeCodeBlockcpp">trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreinspectorContentSearchUtilitiescpp">trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeCommonIdentifiersh">trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpcpp">trunk/Source/JavaScriptCore/runtime/RegExp.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExph">trunk/Source/JavaScriptCore/runtime/RegExp.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpKeyh">trunk/Source/JavaScriptCore/runtime/RegExpKey.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpObjectInlinesh">trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeRegExpPrototypecpp">trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStringPrototypecpp">trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoretestses6yaml">trunk/Source/JavaScriptCore/tests/es6.yaml</a></li>
<li><a href="#trunkSourceJavaScriptCoretestsstressstaticgetterinnamesjs">trunk/Source/JavaScriptCore/tests/stress/static-getter-in-names.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrRegularExpressioncpp">trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpretercpp">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrInterpreterh">trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrJITcpp">trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrPatterncpp">trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp</a></li>
<li><a href="#trunkSourceJavaScriptCoreyarrYarrPatternh">trunk/Source/JavaScriptCore/yarr/YarrPattern.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsregexpstickyexpectedtxt">trunk/LayoutTests/js/regexp-sticky-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsregexpstickyhtml">trunk/LayoutTests/js/regexp-sticky.html</a></li>
<li><a href="#trunkLayoutTestsjsscripttestsregexpstickyjs">trunk/LayoutTests/js/script-tests/regexp-sticky.js</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/LayoutTests/ChangeLog        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2016-03-09  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        [ES6] Implement RegExp sticky flag and related functionality
+        https://bugs.webkit.org/show_bug.cgi?id=155177
+
+        Reviewed by Saam Barati.
+
+        New and updated tests.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/regexp-flags-expected.txt:
+        * js/regexp-sticky-expected.txt: Added.
+        * js/regexp-sticky.html: Added.
+        * js/script-tests/Object-getOwnPropertyNames.js:
+        * js/script-tests/regexp-flags.js:
+        (RegExp.prototype.hasOwnProperty): Deleted check for sticky property.
+        * js/script-tests/regexp-sticky.js: New test.
+        (asString):
+        (testStickyExec):
+        (testStickyMatch):
+
</ins><span class="cx"> 2016-03-09  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         FunctionExecutable::ecmaName() should not be based on inferredName().
</span></span></pre></div>
<a id="trunkLayoutTestsjsObjectgetOwnPropertyNamesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -56,7 +56,7 @@
</span><span class="cx"> PASS getSortedOwnPropertyNames(Date) is ['UTC', 'length', 'name', 'now', 'parse', 'prototype']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Date.prototype) is ['constructor', 'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset', 'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setYear', 'toDateString', 'toGMTString', 'toISOString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString', 'toString', 'toTimeString', 'toUTCString', 'valueOf']
</span><span class="cx"> PASS getSortedOwnPropertyNames(RegExp) is ['$&amp;', &quot;$'&quot;, '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']
</span><del>-PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'test', 'toString', 'unicode']
</del><ins>+PASS getSortedOwnPropertyNames(RegExp.prototype) is ['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']
</ins><span class="cx"> PASS getSortedOwnPropertyNames(Error) is ['length', 'name', 'prototype']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Error.prototype) is ['constructor', 'message', 'name', 'toString']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Math) is ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']
</span></span></pre></div>
<a id="trunkLayoutTestsjsregexpflagsexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/regexp-flags-expected.txt (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regexp-flags-expected.txt        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/LayoutTests/js/regexp-flags-expected.txt        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -27,6 +27,10 @@
</span><span class="cx"> PASS /a/uimg.flags is 'gimu'
</span><span class="cx"> PASS new RegExp('a', 'uimg').flags is 'gimu'
</span><span class="cx"> PASS flags.call({global: true, multiline: true, ignoreCase: true, unicode: true}) is 'gimu'
</span><ins>+sticky flag
+PASS /a/yimg.flags is 'gimy'
+PASS new RegExp('a', 'yimg').flags is 'gimy'
+PASS flags.call({global: true, multiline: true, ignoreCase: true, sticky: true}) is 'gimy'
</ins><span class="cx"> PASS successfullyParsed is true
</span><span class="cx"> 
</span><span class="cx"> TEST COMPLETE
</span></span></pre></div>
<a id="trunkLayoutTestsjsregexpstickyexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regexp-sticky-expected.txt (0 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regexp-sticky-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/regexp-sticky-expected.txt        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -0,0 +1,42 @@
</span><ins>+Test for ES6 sticky flag regular expression processing
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS Repeating Pattern
+PASS Test lastIndex resets
+PASS Ignore Case
+PASS Alternates
+PASS BOL Anchored, starting at 0
+PASS BOL Anchored, starting at 1
+PASS EOL Anchored, not at EOL
+PASS EOL Anchored, at EOL
+PASS Lookahead Assertion
+PASS Lookahead Negative Assertion
+PASS Subpatterns - exec
+PASS Subpatterns - match
+PASS Fixed Count
+PASS Greedy
+PASS Non-greedy
+PASS Greedy/Non-greedy
+PASS Counted Range
+PASS Character Classes
+PASS Unmatched Greedy
+PASS Global Flag - exec
+PASS Global Flag - match
+PASS Unicode Flag - Any Character
+PASS Unicode &amp; Ignore Case Flags
+PASS Multiline
+PASS Multiline with BOL Anchor
+PASS &quot;123 1234 &quot;.search(re) is 0
+PASS &quot;123 1234 &quot;.search(re) is 0
+PASS &quot; 123 1234 &quot;.search(re) is -1
+PASS re.test(&quot;123 1234 &quot;) is true
+PASS re.lastIndex is 4
+PASS re.test(&quot;123 1234 &quot;) is true
+PASS re.lastIndex is 9
+PASS re.test(&quot;123 1234 &quot;) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsregexpstickyhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/regexp-sticky.html (0 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/regexp-sticky.html                                (rev 0)
+++ trunk/LayoutTests/js/regexp-sticky.html        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -0,0 +1,10 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&gt;
+&lt;html&gt;
+&lt;head&gt;
+&lt;script src=&quot;../resources/js-test-pre.js&quot;&gt;&lt;/script&gt;
+&lt;/head&gt;
+&lt;body&gt;
+&lt;script src=&quot;script-tests/regexp-sticky.js&quot;&gt;&lt;/script&gt;
+&lt;script src=&quot;../resources/js-test-post.js&quot;&gt;&lt;/script&gt;
+&lt;/body&gt;
+&lt;/html&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsObjectgetOwnPropertyNamesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -65,7 +65,7 @@
</span><span class="cx">     &quot;Date&quot;: &quot;['UTC', 'length', 'name', 'now', 'parse', 'prototype']&quot;,
</span><span class="cx">     &quot;Date.prototype&quot;: &quot;['constructor', 'getDate', 'getDay', 'getFullYear', 'getHours', 'getMilliseconds', 'getMinutes', 'getMonth', 'getSeconds', 'getTime', 'getTimezoneOffset', 'getUTCDate', 'getUTCDay', 'getUTCFullYear', 'getUTCHours', 'getUTCMilliseconds', 'getUTCMinutes', 'getUTCMonth', 'getUTCSeconds', 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', 'setYear', 'toDateString', 'toGMTString', 'toISOString', 'toJSON', 'toLocaleDateString', 'toLocaleString', 'toLocaleTimeString', 'toString', 'toTimeString', 'toUTCString', 'valueOf']&quot;,
</span><span class="cx">     &quot;RegExp&quot;: &quot;['$&amp;', \&quot;$'\&quot;, '$*', '$+', '$1', '$2', '$3', '$4', '$5', '$6', '$7', '$8', '$9', '$_', '$`', 'input', 'lastMatch', 'lastParen', 'leftContext', 'length', 'multiline', 'name', 'prototype', 'rightContext']&quot;,
</span><del>-    &quot;RegExp.prototype&quot;: &quot;['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'test', 'toString', 'unicode']&quot;,
</del><ins>+    &quot;RegExp.prototype&quot;: &quot;['compile', 'constructor', 'exec', 'flags', 'global', 'ignoreCase', 'lastIndex', 'multiline', 'source', 'sticky', 'test', 'toString', 'unicode']&quot;,
</ins><span class="cx">     &quot;Error&quot;: &quot;['length', 'name', 'prototype']&quot;,
</span><span class="cx">     &quot;Error.prototype&quot;: &quot;['constructor', 'message', 'name', 'toString']&quot;,
</span><span class="cx">     &quot;Math&quot;: &quot;['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2','abs','acos','acosh','asin','asinh','atan','atan2','atanh','cbrt','ceil','clz32','cos','cosh','exp','expm1','floor','fround','hypot','imul','log','log10','log1p','log2','max','min','pow','random','round','sign','sin','sinh','sqrt','tan','tanh','trunc']&quot;,
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsregexpflagsjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/regexp-flags.js (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/regexp-flags.js        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/LayoutTests/js/script-tests/regexp-flags.js        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -33,11 +33,7 @@
</span><span class="cx"> shouldBe(&quot;new RegExp('a', 'uimg').flags&quot;, &quot;'gimu'&quot;);
</span><span class="cx"> shouldBe(&quot;flags.call({global: true, multiline: true, ignoreCase: true, unicode: true})&quot;, &quot;'gimu'&quot;);
</span><span class="cx"> 
</span><del>-if (RegExp.prototype.hasOwnProperty('sticky')) {
-  debug(&quot;sticky flag&quot;);
-  // when the engine supports &quot;sticky&quot;, these tests will fail by design.
-  // Hopefully, only the expected output will need updating.
-  shouldBe(&quot;/a/yimg.flags&quot;, &quot;'gimy'&quot;);
-  shouldBe(&quot;new RegExp('a', 'yimg').flags&quot;, &quot;'gimy'&quot;);
-  shouldBe(&quot;flags.call({global: true, multiline: true, ignoreCase: true, sticky: true})&quot;, &quot;'gimy'&quot;);
-}
</del><ins>+debug(&quot;sticky flag&quot;);
+shouldBe(&quot;/a/yimg.flags&quot;, &quot;'gimy'&quot;);
+shouldBe(&quot;new RegExp('a', 'yimg').flags&quot;, &quot;'gimy'&quot;);
+shouldBe(&quot;flags.call({global: true, multiline: true, ignoreCase: true, sticky: true})&quot;, &quot;'gimy'&quot;);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsregexpstickyjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/regexp-sticky.js (0 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/regexp-sticky.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/regexp-sticky.js        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -0,0 +1,111 @@
</span><ins>+description(
+'Test for ES6 sticky flag regular expression processing'
+);
+
+function asString(o)
+{
+    if (o === null)
+        return &quot;&lt;null&gt;&quot;;
+
+    return o.toString();
+}
+
+function testStickyExec(testDescription, re, str, beginLastIndex, expected)
+{
+    re.lastIndex = beginLastIndex;
+
+    let failures = 0;
+
+    for (let iter = 0; iter &lt; expected.length; iter++) {
+        let lastIndexStart = re.lastIndex;
+
+        let result = re.exec(str);
+
+        if (result != expected[iter]) {
+            testFailed(testDescription + &quot;, iteration &quot; + iter + &quot;, from lastIndex: &quot; + lastIndexStart +
+                       &quot;, expected \&quot;&quot; + asString(expected[iter]) + &quot;\&quot;, got \&quot;&quot; + asString(result) + &quot;\&quot;&quot;);
+            failures++;
+        }
+    }
+
+    if (failures)
+        testFailed(testDescription + &quot; - failed: &quot; + failures + &quot; tests&quot;);
+    else
+        testPassed(testDescription);
+}
+
+function testStickyMatch(testDescription, re, str, beginLastIndex, expected)
+{
+    re.lastIndex = beginLastIndex;
+
+    let failures = 0;
+
+    for (var iter = 0; iter &lt; expected.length; iter++) {
+        let lastIndexStart = re.lastIndex;
+
+        let result = str.match(re);
+        let correctResult = false;
+        if (expected[iter] === null || result === null)
+            correctResult = (expected[iter] === result);
+        else if (result.length == expected[iter].length) {
+            correctResult = true;
+            for (let i = 0; i &lt; result.length; i++) {
+                if (result[i] != expected[iter][i])
+                    correctResult = false;
+            }
+        }
+
+        if (!correctResult) {
+            testFailed(testDescription + &quot;, iteration &quot; + iter + &quot;, from lastIndex: &quot; + lastIndexStart +
+                       &quot;, expected \&quot;&quot; + asString(expected[iter]) + &quot;\&quot;, got \&quot;&quot; + asString(result) + &quot;\&quot;&quot;);
+            failures++;
+        }
+    }
+
+    if (failures)
+        testFailed(testDescription + &quot; - failed: &quot; + failures + &quot; tests&quot;);
+    else
+        testPassed(testDescription);
+}
+
+
+testStickyExec(&quot;Repeating Pattern&quot;, new RegExp(&quot;abc&quot;, &quot;y&quot;), &quot;abcabcabc&quot;, 0, [&quot;abc&quot;, &quot;abc&quot;, &quot;abc&quot;, null]);
+testStickyExec(&quot;Test lastIndex resets&quot;, /\d/y, &quot;12345&quot;, 0, [&quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, null, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;, null]);
+testStickyExec(&quot;Ignore Case&quot;, new RegExp(&quot;test&quot;, &quot;iy&quot;), &quot;TESTtestTest&quot;, 0, [&quot;TEST&quot;, &quot;test&quot;, &quot;Test&quot;, null]);
+testStickyExec(&quot;Alternates&quot;, new RegExp(&quot;Dog |Cat |Mouse &quot;, &quot;y&quot;), &quot;Mouse Dog Cat &quot;, 0, [&quot;Mouse &quot;, &quot;Dog &quot;, &quot;Cat &quot;, null]);
+testStickyExec(&quot;BOL Anchored, starting at 0&quot;, /^X/y, &quot;XXX&quot;, 0, [&quot;X&quot;, null]);
+testStickyExec(&quot;BOL Anchored, starting at 1&quot;, /^X/y, &quot;XXX&quot;, 1, [null, &quot;X&quot;, null]);
+testStickyExec(&quot;EOL Anchored, not at EOL&quot;, /#$/y, &quot;##&quot;, 0, [null]);
+testStickyExec(&quot;EOL Anchored, at EOL&quot;, /#$/y, &quot;##&quot;, 1, [&quot;#&quot;, null]);
+testStickyExec(&quot;Lookahead Assertion&quot;, /\d+(?=-)/y, &quot;212-555-1212&quot;, 0, [&quot;212&quot;, null]);
+testStickyExec(&quot;Lookahead Negative Assertion&quot;, /\d+(?!\d)/y, &quot;212-555-1212&quot;, 0, [&quot;212&quot;, null]);
+testStickyExec(&quot;Subpatterns - exec&quot;, /(\d+)(?:-|$)/y, &quot;212-555-1212&quot;, 0, [&quot;212-,212&quot;, &quot;555-,555&quot;, &quot;1212,1212&quot;], null);
+testStickyMatch(&quot;Subpatterns - match&quot;, /(\d+)(?:-|$)/y, &quot;212-555-1212&quot;, 0, [[&quot;212-&quot;, &quot;212&quot;], [&quot;555-&quot;, &quot;555&quot;], [&quot;1212&quot;, &quot;1212&quot;]], null);
+testStickyExec(&quot;Fixed Count&quot;, /\d{4}/y, &quot;123456789&quot;, 0, [&quot;1234&quot;, &quot;5678&quot;, null]);
+testStickyExec(&quot;Greedy&quot;, /\d*/y, &quot;12345 67890&quot;, 0, [&quot;12345&quot;, &quot;&quot;]);
+testStickyMatch(&quot;Non-greedy&quot;, /\w+?./y, &quot;abcdefg&quot;, 0, [[&quot;ab&quot;], [&quot;cd&quot;], [&quot;ef&quot;], null]);
+testStickyExec(&quot;Greedy/Non-greedy&quot;, /\s*(\d+)/y, &quot;    1234  324512   74352&quot;, 0, [&quot;    1234,1234&quot;, &quot;  324512,324512&quot;, &quot;   74352,74352&quot;, null]);
+testStickyExec(&quot;Counted Range&quot;, /(\w+\s+){1,3}/y, &quot;The quick brown fox jumped over the &quot;, 0, [&quot;The quick brown ,brown &quot;, &quot;fox jumped over ,over &quot;, &quot;the ,the &quot;, null]);
+testStickyMatch(&quot;Character Classes&quot;, /[0-9A-F]/iy, &quot;fEEd123X&quot;, 0, [[&quot;f&quot;], [&quot;E&quot;], [&quot;E&quot;], [&quot;d&quot;], [&quot;1&quot;], [&quot;2&quot;], [&quot;3&quot;], null]);
+testStickyExec(&quot;Unmatched Greedy&quot;, /^\s*|\s*$/y, &quot;ab&quot;, 1, [null]);
+testStickyExec(&quot;Global Flag - exec&quot;, /\s*(\+|[0-9]+)\s*/gy, &quot;3 + 4&quot;, 0, [&quot;3 ,3&quot;, &quot;+ ,+&quot;, &quot;4,4&quot;, null]);
+testStickyMatch(&quot;Global Flag - match&quot;, /\s*(\+|[0-9]+)\s*/gy, &quot;3 + 4&quot;, 0, [[&quot;3 &quot;, &quot;+ &quot;, &quot;4&quot;], [&quot;3 &quot;, &quot;+ &quot;, &quot;4&quot;]]);
+testStickyExec(&quot;Unicode Flag - Any Character&quot;, /./uy, &quot;a@\u{10402}1\u202a\u{12345}&quot;, 0, [&quot;a&quot;, &quot;@&quot;, &quot;\u{10402}&quot;, &quot;1&quot;, &quot;\u202a&quot;, &quot;\u{12345}&quot;, null]);
+testStickyMatch(&quot;Unicode &amp; Ignore Case Flags&quot;, /(?:\u{118c0}|\u{10cb0}|\w):/iuy, &quot;a:\u{118a0}:x:\u{10cb0}&quot;, 0, [[&quot;a:&quot;], [&quot;\u{118a0}:&quot;], [&quot;x:&quot;], null]);
+testStickyExec(&quot;Multiline&quot;, /(?:\w+ *)+(?:\n|$)/my, &quot;Line One\nLine Two&quot;, 0, [&quot;Line One\n&quot;, &quot;Line Two&quot;, null]);
+testStickyMatch(&quot;Multiline with BOL Anchor&quot;, /^\d*\s?/my, &quot;13574\n295\n99&quot;, 0, [[&quot;13574\n&quot;], [&quot;295\n&quot;], [&quot;99&quot;], null]);
+
+// Verify that String.search starts at 0 even with the sticky flag.
+var re = new RegExp(&quot;\\d+\\s&quot;, &quot;y&quot;);
+shouldBe('&quot;123 1234 &quot;.search(re)', '0');
+shouldBe('&quot;123 1234 &quot;.search(re)', '0');
+// Verify that String.search doesn't advance past 0 with the sticky flag.
+shouldBe('&quot; 123 1234 &quot;.search(re)', '-1');
+
+re.lastIndex = 0;
+shouldBeTrue('re.test(&quot;123 1234 &quot;)');
+shouldBe('re.lastIndex', '4');
+shouldBeTrue('re.test(&quot;123 1234 &quot;)');
+shouldBe('re.lastIndex', '9');
+shouldBeFalse('re.test(&quot;123 1234 &quot;)');
+
</ins></span></pre></div>
<a id="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/ChangeLog        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -1,3 +1,94 @@
</span><ins>+2016-03-09  Michael Saboff  &lt;msaboff@apple.com&gt;
+
+        [ES6] Implement RegExp sticky flag and related functionality
+        https://bugs.webkit.org/show_bug.cgi?id=155177
+
+        Reviewed by Saam Barati.
+
+        Implemented the ES6 RegExp sticky functionality.
+
+        There are two main behavior changes when the sticky flag is specified.
+        1) Matching starts at lastIndex and lastIndex is updated after the match.
+        2) The regular expression is only matched from the start position in the string.
+        See ES6 section 21.2.5.2.2 for details.
+
+        Changed both the Yarr interpreter and jit to not loop to the next character for sticky RegExp's.
+        Updated RegExp exec and match, and stringProtoFuncMatch to handle lastIndex changes.
+
+        Restructured the way flags are passed to and through YarrPatterns to use RegExpFlags instead of
+        individual bools.
+
+        Updated tests for 'y' flag and new behavior.
+
+        * bytecode/CodeBlock.cpp:
+        (JSC::regexpToSourceString):
+        * inspector/ContentSearchUtilities.cpp:
+        (Inspector::ContentSearchUtilities::findMagicComment):
+        * runtime/CommonIdentifiers.h:
+        * runtime/RegExp.cpp:
+        (JSC::regExpFlags):
+        (JSC::RegExpFunctionalTestCollector::outputOneTest):
+        (JSC::RegExp::finishCreation):
+        (JSC::RegExp::compile):
+        (JSC::RegExp::compileMatchOnly):
+        * runtime/RegExp.h:
+        * runtime/RegExpKey.h:
+        * runtime/RegExpObjectInlines.h:
+        (JSC::RegExpObject::execInline):
+        (JSC::RegExpObject::matchInline):
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncCompile):
+        (JSC::flagsString):
+        (JSC::regExpProtoGetterMultiline):
+        (JSC::regExpProtoGetterSticky):
+        (JSC::regExpProtoGetterUnicode):
+        * runtime/StringPrototype.cpp:
+        (JSC::stringProtoFuncMatch):
+        * tests/es6.yaml:
+        * tests/stress/static-getter-in-names.js:
+        (shouldBe):
+        * yarr/RegularExpression.cpp:
+        (JSC::Yarr::RegularExpression::Private::compile):
+        * yarr/YarrInterpreter.cpp:
+        (JSC::Yarr::Interpreter::tryConsumeBackReference):
+        (JSC::Yarr::Interpreter::matchAssertionBOL):
+        (JSC::Yarr::Interpreter::matchAssertionEOL):
+        (JSC::Yarr::Interpreter::matchAssertionWordBoundary):
+        (JSC::Yarr::Interpreter::matchDotStarEnclosure):
+        (JSC::Yarr::Interpreter::matchDisjunction):
+        (JSC::Yarr::Interpreter::Interpreter):
+        (JSC::Yarr::ByteCompiler::atomPatternCharacter):
+        * yarr/YarrInterpreter.h:
+        (JSC::Yarr::BytecodePattern::BytecodePattern):
+        (JSC::Yarr::BytecodePattern::estimatedSizeInBytes):
+        (JSC::Yarr::BytecodePattern::ignoreCase):
+        (JSC::Yarr::BytecodePattern::multiline):
+        (JSC::Yarr::BytecodePattern::sticky):
+        (JSC::Yarr::BytecodePattern::unicode):
+        * yarr/YarrJIT.cpp:
+        (JSC::Yarr::YarrGenerator::matchCharacterClass):
+        (JSC::Yarr::YarrGenerator::jumpIfCharNotEquals):
+        (JSC::Yarr::YarrGenerator::generateAssertionBOL):
+        (JSC::Yarr::YarrGenerator::generateAssertionEOL):
+        (JSC::Yarr::YarrGenerator::generatePatternCharacterOnce):
+        (JSC::Yarr::YarrGenerator::generatePatternCharacterFixed):
+        (JSC::Yarr::YarrGenerator::generateDotStarEnclosure):
+        (JSC::Yarr::YarrGenerator::backtrack):
+        * yarr/YarrPattern.cpp:
+        (JSC::Yarr::YarrPatternConstructor::YarrPatternConstructor):
+        (JSC::Yarr::YarrPatternConstructor::atomPatternCharacter):
+        (JSC::Yarr::YarrPatternConstructor::setupAlternativeOffsets):
+        (JSC::Yarr::YarrPatternConstructor::optimizeBOL):
+        (JSC::Yarr::YarrPattern::compile):
+        (JSC::Yarr::YarrPattern::YarrPattern):
+        * yarr/YarrPattern.h:
+        (JSC::Yarr::YarrPattern::reset):
+        (JSC::Yarr::YarrPattern::nonwordcharCharacterClass):
+        (JSC::Yarr::YarrPattern::ignoreCase):
+        (JSC::Yarr::YarrPattern::multiline):
+        (JSC::Yarr::YarrPattern::sticky):
+        (JSC::Yarr::YarrPattern::unicode):
+
</ins><span class="cx"> 2016-03-09  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         FunctionExecutable::ecmaName() should not be based on inferredName().
</span></span></pre></div>
<a id="trunkSourceJavaScriptCorebytecodeCodeBlockcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -274,6 +274,10 @@
</span><span class="cx">         postfix[index++] = 'i';
</span><span class="cx">     if (regExp-&gt;multiline())
</span><span class="cx">         postfix[index] = 'm';
</span><ins>+    if (regExp-&gt;sticky())
+        postfix[index++] = 'y';
+    if (regExp-&gt;unicode())
+        postfix[index++] = 'u';
</ins><span class="cx"> 
</span><span class="cx">     return toCString(&quot;/&quot;, regExp-&gt;pattern().impl(), postfix);
</span><span class="cx"> }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreinspectorContentSearchUtilitiescpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/inspector/ContentSearchUtilities.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -176,7 +176,7 @@
</span><span class="cx"> {
</span><span class="cx">     ASSERT(!content.isNull());
</span><span class="cx">     const char* error = nullptr;
</span><del>-    JSC::Yarr::YarrPattern pattern(patternString, false, true, false, &amp;error);
</del><ins>+    JSC::Yarr::YarrPattern pattern(patternString, JSC::RegExpFlags::FlagMultiline, &amp;error);
</ins><span class="cx">     ASSERT(!error);
</span><span class="cx">     BumpPointerAllocator regexAllocator;
</span><span class="cx">     auto bytecodePattern = JSC::Yarr::byteCompile(pattern, &amp;regexAllocator);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeCommonIdentifiersh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/CommonIdentifiers.h        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -197,6 +197,7 @@
</span><span class="cx">     macro(sourceCode) \
</span><span class="cx">     macro(sourceURL) \
</span><span class="cx">     macro(stack) \
</span><ins>+    macro(sticky) \
</ins><span class="cx">     macro(subarray) \
</span><span class="cx">     macro(target) \
</span><span class="cx">     macro(test) \
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExp.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExp.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/RegExp.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -65,6 +65,12 @@
</span><span class="cx">             flags = static_cast&lt;RegExpFlags&gt;(flags | FlagUnicode);
</span><span class="cx">             break;
</span><span class="cx">                 
</span><ins>+        case 'y':
+            if (flags &amp; FlagSticky)
+                return InvalidFlags;
+            flags = static_cast&lt;RegExpFlags&gt;(flags | FlagSticky);
+            break;
+
</ins><span class="cx">         default:
</span><span class="cx">             return InvalidFlags;
</span><span class="cx">         }
</span><span class="lines">@@ -98,6 +104,8 @@
</span><span class="cx">             fputc('i', m_file);
</span><span class="cx">         if (regExp-&gt;multiline())
</span><span class="cx">             fputc('m', m_file);
</span><ins>+        if (regExp-&gt;sticky())
+            fputc('y', m_file);
</ins><span class="cx">         if (regExp-&gt;unicode())
</span><span class="cx">             fputc('u', m_file);
</span><span class="cx">         fprintf(m_file, &quot;\n&quot;);
</span><span class="lines">@@ -214,7 +222,7 @@
</span><span class="cx"> void RegExp::finishCreation(VM&amp; vm)
</span><span class="cx"> {
</span><span class="cx">     Base::finishCreation(vm);
</span><del>-    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), unicode(), &amp;m_constructionError);
</del><ins>+    Yarr::YarrPattern pattern(m_patternString, m_flags, &amp;m_constructionError);
</ins><span class="cx">     if (m_constructionError)
</span><span class="cx">         m_state = ParseError;
</span><span class="cx">     else
</span><span class="lines">@@ -254,7 +262,7 @@
</span><span class="cx"> 
</span><span class="cx"> void RegExp::compile(VM* vm, Yarr::YarrCharSize charSize)
</span><span class="cx"> {
</span><del>-    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), unicode(), &amp;m_constructionError);
</del><ins>+    Yarr::YarrPattern pattern(m_patternString, m_flags, &amp;m_constructionError);
</ins><span class="cx">     if (m_constructionError) {
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
</span><span class="lines">@@ -293,7 +301,7 @@
</span><span class="cx"> 
</span><span class="cx"> void RegExp::compileMatchOnly(VM* vm, Yarr::YarrCharSize charSize)
</span><span class="cx"> {
</span><del>-    Yarr::YarrPattern pattern(m_patternString, ignoreCase(), multiline(), unicode(), &amp;m_constructionError);
</del><ins>+    Yarr::YarrPattern pattern(m_patternString, m_flags, &amp;m_constructionError);
</ins><span class="cx">     if (m_constructionError) {
</span><span class="cx">         RELEASE_ASSERT_NOT_REACHED();
</span><span class="cx"> #if COMPILER_QUIRK(CONSIDERS_UNREACHABLE_CODE)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExph"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExp.h (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExp.h        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/RegExp.h        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -55,6 +55,7 @@
</span><span class="cx">     bool global() const { return m_flags &amp; FlagGlobal; }
</span><span class="cx">     bool ignoreCase() const { return m_flags &amp; FlagIgnoreCase; }
</span><span class="cx">     bool multiline() const { return m_flags &amp; FlagMultiline; }
</span><ins>+    bool sticky() const { return m_flags &amp; FlagSticky; }
</ins><span class="cx">     bool unicode() const { return m_flags &amp; FlagUnicode; }
</span><span class="cx"> 
</span><span class="cx">     const String&amp; pattern() const { return m_patternString; }
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpKeyh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpKey.h (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpKey.h        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/RegExpKey.h        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -38,8 +38,9 @@
</span><span class="cx">     FlagGlobal = 1,
</span><span class="cx">     FlagIgnoreCase = 2,
</span><span class="cx">     FlagMultiline = 4,
</span><del>-    FlagUnicode = 8,
-    InvalidFlags = 16,
</del><ins>+    FlagSticky = 8,
+    FlagUnicode = 16,
+    InvalidFlags = 32,
</ins><span class="cx">     DeletedValueFlags = -1
</span><span class="cx"> };
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpObjectInlinesh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/RegExpObjectInlines.h        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -63,10 +63,10 @@
</span><span class="cx">     String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><span class="cx"> 
</span><del>-    bool global = regExp-&gt;global();
</del><ins>+    bool globalOrSticky = regExp-&gt;global() || regExp-&gt;sticky();
</ins><span class="cx"> 
</span><span class="cx">     unsigned lastIndex;
</span><del>-    if (global) {
</del><ins>+    if (globalOrSticky) {
</ins><span class="cx">         lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
</span><span class="cx">         if (lastIndex == UINT_MAX)
</span><span class="cx">             return jsNull();
</span><span class="lines">@@ -77,11 +77,12 @@
</span><span class="cx">     JSArray* array =
</span><span class="cx">         createRegExpMatchesArray(vm, globalObject, string, input, regExp, lastIndex, result);
</span><span class="cx">     if (!array) {
</span><del>-        if (global)
</del><ins>+        if (globalOrSticky)
</ins><span class="cx">             setLastIndex(exec, 0);
</span><span class="cx">         return jsNull();
</span><span class="cx">     }
</span><del>-    if (global)
</del><ins>+
+    if (globalOrSticky)
</ins><span class="cx">         setLastIndex(exec, result.end);
</span><span class="cx">     regExpConstructor-&gt;recordMatch(vm, regExp, string, result);
</span><span class="cx">     return array;
</span><span class="lines">@@ -95,7 +96,7 @@
</span><span class="cx">     RegExpConstructor* regExpConstructor = globalObject-&gt;regExpConstructor();
</span><span class="cx">     String input = string-&gt;value(exec); // FIXME: Handle errors. https://bugs.webkit.org/show_bug.cgi?id=155145
</span><span class="cx">     VM&amp; vm = globalObject-&gt;vm();
</span><del>-    if (!regExp-&gt;global())
</del><ins>+    if (!regExp-&gt;global() &amp;&amp; !regExp-&gt;sticky())
</ins><span class="cx">         return regExpConstructor-&gt;performMatch(vm, regExp, string, input, 0);
</span><span class="cx"> 
</span><span class="cx">     unsigned lastIndex = getRegExpObjectLastIndexAsUnsigned(exec, this, input);
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeRegExpPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/RegExpPrototype.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -48,6 +48,7 @@
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL regExpProtoGetterGlobal(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL regExpProtoGetterIgnoreCase(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL regExpProtoGetterMultiline(ExecState*);
</span><ins>+static EncodedJSValue JSC_HOST_CALL regExpProtoGetterSticky(ExecState*);
</ins><span class="cx"> static EncodedJSValue JSC_HOST_CALL regExpProtoGetterUnicode(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL regExpProtoGetterSource(ExecState*);
</span><span class="cx"> static EncodedJSValue JSC_HOST_CALL regExpProtoGetterFlags(ExecState*);
</span><span class="lines">@@ -69,6 +70,7 @@
</span><span class="cx">   global        regExpProtoGetterGlobal     DontEnum|Accessor
</span><span class="cx">   ignoreCase    regExpProtoGetterIgnoreCase DontEnum|Accessor
</span><span class="cx">   multiline     regExpProtoGetterMultiline  DontEnum|Accessor
</span><ins>+  sticky        regExpProtoGetterSticky     DontEnum|Accessor
</ins><span class="cx">   unicode       regExpProtoGetterUnicode    DontEnum|Accessor
</span><span class="cx">   source        regExpProtoGetterSource     DontEnum|Accessor
</span><span class="cx">   flags         regExpProtoGetterFlags      DontEnum|Accessor
</span><span class="lines">@@ -154,22 +156,29 @@
</span><span class="cx">     return JSValue::encode(jsUndefined());
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-typedef std::array&lt;char, 4 + 1&gt; FlagsString; // 4 different flags and a null character terminator.
</del><ins>+typedef std::array&lt;char, 5 + 1&gt; FlagsString; // 5 different flags and a null character terminator.
</ins><span class="cx"> 
</span><span class="cx"> static inline FlagsString flagsString(ExecState* exec, JSObject* regexp)
</span><span class="cx"> {
</span><span class="cx">     FlagsString string;
</span><span class="cx"> 
</span><ins>+    VM&amp; vm = exec-&gt;vm();
+
</ins><span class="cx">     JSValue globalValue = regexp-&gt;get(exec, exec-&gt;propertyNames().global);
</span><del>-    if (exec-&gt;hadException())
</del><ins>+    if (vm.exception())
</ins><span class="cx">         return string;
</span><span class="cx">     JSValue ignoreCaseValue = regexp-&gt;get(exec, exec-&gt;propertyNames().ignoreCase);
</span><del>-    if (exec-&gt;hadException())
</del><ins>+    if (vm.exception())
</ins><span class="cx">         return string;
</span><span class="cx">     JSValue multilineValue = regexp-&gt;get(exec, exec-&gt;propertyNames().multiline);
</span><del>-    if (exec-&gt;hadException())
</del><ins>+    if (vm.exception())
</ins><span class="cx">         return string;
</span><span class="cx">     JSValue unicodeValue = regexp-&gt;get(exec, exec-&gt;propertyNames().unicode);
</span><ins>+    if (vm.exception())
+        return string;
+    JSValue stickyValue = regexp-&gt;get(exec, exec-&gt;propertyNames().sticky);
+    if (vm.exception())
+        return string;
</ins><span class="cx"> 
</span><span class="cx">     unsigned index = 0;
</span><span class="cx">     if (globalValue.toBoolean(exec))
</span><span class="lines">@@ -180,6 +189,8 @@
</span><span class="cx">         string[index++] = 'm';
</span><span class="cx">     if (unicodeValue.toBoolean(exec))
</span><span class="cx">         string[index++] = 'u';
</span><ins>+    if (stickyValue.toBoolean(exec))
+        string[index++] = 'y';
</ins><span class="cx">     ASSERT(index &lt; string.size());
</span><span class="cx">     string[index] = 0;
</span><span class="cx">     return string;
</span><span class="lines">@@ -238,6 +249,15 @@
</span><span class="cx">     return JSValue::encode(jsBoolean(asRegExpObject(thisValue)-&gt;regExp()-&gt;multiline()));
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+EncodedJSValue JSC_HOST_CALL regExpProtoGetterSticky(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    if (!thisValue.inherits(RegExpObject::info()))
+        return throwVMTypeError(exec);
+    
+    return JSValue::encode(jsBoolean(asRegExpObject(thisValue)-&gt;regExp()-&gt;sticky()));
+}
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL regExpProtoGetterUnicode(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -1041,16 +1041,39 @@
</span><span class="cx">     JSValue a0 = exec-&gt;argument(0);
</span><span class="cx"> 
</span><span class="cx">     RegExp* regExp;
</span><ins>+    unsigned startOffset = 0;
</ins><span class="cx">     bool global = false;
</span><ins>+    bool sticky = false;
+    RegExpObject* regExpObject = nullptr;
</ins><span class="cx">     if (a0.inherits(RegExpObject::info())) {
</span><del>-        RegExpObject* regExpObject = asRegExpObject(a0);
</del><ins>+        regExpObject = asRegExpObject(a0);
</ins><span class="cx">         regExp = regExpObject-&gt;regExp();
</span><span class="cx">         if ((global = regExp-&gt;global())) {
</span><del>-            // ES5.1 15.5.4.10 step 8.a.
</del><ins>+            // ES6 21.2.5.6 step 6.b.
</ins><span class="cx">             regExpObject-&gt;setLastIndex(exec, 0);
</span><span class="cx">             if (exec-&gt;hadException())
</span><span class="cx">                 return JSValue::encode(jsUndefined());
</span><span class="cx">         }
</span><ins>+        if ((sticky = regExp-&gt;sticky())) {
+            JSValue jsLastIndex = regExpObject-&gt;getLastIndex();
+            unsigned lastIndex;
+            if (LIKELY(jsLastIndex.isUInt32())) {
+                lastIndex = jsLastIndex.asUInt32();
+                if (lastIndex &gt; s.length()) {
+                    regExpObject-&gt;setLastIndex(exec, 0);
+                    return JSValue::encode(jsUndefined());
+                }
+            } else {
+                double doubleLastIndex = jsLastIndex.toInteger(exec);
+                if (doubleLastIndex &lt; 0 || doubleLastIndex &gt; s.length()) {
+                    regExpObject-&gt;setLastIndex(exec, 0);
+                    return JSValue::encode(jsUndefined());
+                }
+                lastIndex = static_cast&lt;unsigned&gt;(doubleLastIndex);
+            }
+
+            startOffset = lastIndex;
+        }
</ins><span class="cx">     } else {
</span><span class="cx">         /*
</span><span class="cx">          *  ECMA 15.5.4.12 String.prototype.search (regexp)
</span><span class="lines">@@ -1069,13 +1092,18 @@
</span><span class="cx">             return throwVMError(exec, createSyntaxError(exec, regExp-&gt;errorMessage()));
</span><span class="cx">     }
</span><span class="cx">     RegExpConstructor* regExpConstructor = globalObject-&gt;regExpConstructor();
</span><del>-    MatchResult result = regExpConstructor-&gt;performMatch(*vm, regExp, string, s, 0);
</del><ins>+    MatchResult result = regExpConstructor-&gt;performMatch(*vm, regExp, string, s, startOffset);
</ins><span class="cx">     // case without 'g' flag is handled like RegExp.prototype.exec
</span><del>-    if (!global)
</del><ins>+    if (!global) {
+        if (sticky)
+            regExpObject-&gt;setLastIndex(exec, result ? result.end : 0);
+
</ins><span class="cx">         return JSValue::encode(result ? createRegExpMatchesArray(exec, globalObject, string, regExp, result.start) : jsNull());
</span><ins>+    }
</ins><span class="cx"> 
</span><span class="cx">     // return array of matches
</span><span class="cx">     MarkedArgumentBuffer list;
</span><ins>+    size_t end = 0;
</ins><span class="cx">     while (result) {
</span><span class="cx">         // We defend ourselves from crazy.
</span><span class="cx">         const size_t maximumReasonableMatchSize = 1000000000;
</span><span class="lines">@@ -1084,20 +1112,30 @@
</span><span class="cx">             return JSValue::encode(jsUndefined());
</span><span class="cx">         }
</span><span class="cx">         
</span><del>-        size_t end = result.end;
</del><ins>+        end = result.end;
</ins><span class="cx">         size_t length = end - result.start;
</span><span class="cx">         list.append(jsSubstring(exec, s, result.start, length));
</span><span class="cx">         if (!length)
</span><span class="cx">             ++end;
</span><del>-        result = regExpConstructor-&gt;performMatch(*vm, regExp, string, s, end);
</del><ins>+        
+        if (global)
+            result = regExpConstructor-&gt;performMatch(*vm, regExp, string, s, end);
+        else
+            result = MatchResult();
</ins><span class="cx">     }
</span><span class="cx">     if (list.isEmpty()) {
</span><span class="cx">         // if there are no matches at all, it's important to return
</span><span class="cx">         // Null instead of an empty array, because this matches
</span><span class="cx">         // other browsers and because Null is a false value.
</span><ins>+        if (sticky)
+            regExpObject-&gt;setLastIndex(exec, 0);
+        
</ins><span class="cx">         return JSValue::encode(jsNull());
</span><span class="cx">     }
</span><del>-
</del><ins>+    
+    if (sticky)
+        regExpObject-&gt;setLastIndex(exec, end);
+    
</ins><span class="cx">     return JSValue::encode(constructArray(exec, static_cast&lt;ArrayAllocationProfile*&gt;(0), list));
</span><span class="cx"> }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestses6yaml"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/es6.yaml (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/es6.yaml        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/tests/es6.yaml        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -991,7 +991,7 @@
</span><span class="cx"> - path: es6/Proxy_internal_get_calls_Promise_resolve_functions.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/Proxy_internal_get_calls_RegExp.prototype.flags.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/Proxy_internal_get_calls_RegExp.prototype.test.js
</span><span class="cx">   cmd: runES6 :fail
</span><span class="cx"> - path: es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.match].js
</span><span class="lines">@@ -1095,9 +1095,9 @@
</span><span class="cx"> - path: es6/RegExp_y_and_u_flags_u_flag_Unicode_code_point_escapes.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/RegExp_y_and_u_flags_y_flag.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/RegExp_y_and_u_flags_y_flag_lastIndex.js
</span><del>-  cmd: runES6 :fail
</del><ins>+  cmd: runES6 :normal
</ins><span class="cx"> - path: es6/rest_parameters_arguments_object_interaction.js
</span><span class="cx">   cmd: runES6 :normal
</span><span class="cx"> - path: es6/rest_parameters_basic_functionality.js
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoretestsstressstaticgetterinnamesjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/tests/stress/static-getter-in-names.js (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/tests/stress/static-getter-in-names.js        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/tests/stress/static-getter-in-names.js        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -3,5 +3,5 @@
</span><span class="cx">         throw new Error('bad value: ' + actual);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-shouldBe(JSON.stringify(Object.getOwnPropertyNames(RegExp.prototype).sort()), '[&quot;compile&quot;,&quot;constructor&quot;,&quot;exec&quot;,&quot;flags&quot;,&quot;global&quot;,&quot;ignoreCase&quot;,&quot;lastIndex&quot;,&quot;multiline&quot;,&quot;source&quot;,&quot;test&quot;,&quot;toString&quot;,&quot;unicode&quot;]');
</del><ins>+shouldBe(JSON.stringify(Object.getOwnPropertyNames(RegExp.prototype).sort()), '[&quot;compile&quot;,&quot;constructor&quot;,&quot;exec&quot;,&quot;flags&quot;,&quot;global&quot;,&quot;ignoreCase&quot;,&quot;lastIndex&quot;,&quot;multiline&quot;,&quot;source&quot;,&quot;sticky&quot;,&quot;test&quot;,&quot;toString&quot;,&quot;unicode&quot;]');
</ins><span class="cx"> shouldBe(JSON.stringify(Object.getOwnPropertyNames(/Cocoa/).sort()), '[&quot;lastIndex&quot;]');
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrRegularExpressioncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/yarr/RegularExpression.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -57,7 +57,15 @@
</span><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;JSC::Yarr::BytecodePattern&gt; compile(const String&amp; patternString, TextCaseSensitivity caseSensitivity, MultilineMode multilineMode)
</span><span class="cx">     {
</span><del>-        JSC::Yarr::YarrPattern pattern(patternString, (caseSensitivity == TextCaseInsensitive), (multilineMode == MultilineEnabled), false, &amp;m_constructionError);
</del><ins>+        RegExpFlags flags = NoFlags;
+
+        if (caseSensitivity == TextCaseInsensitive)
+            flags = static_cast&lt;RegExpFlags&gt;(flags | FlagIgnoreCase);
+
+        if (multilineMode == MultilineEnabled)
+            flags = static_cast&lt;RegExpFlags&gt;(flags | FlagMultiline);
+
+        JSC::Yarr::YarrPattern pattern(patternString, flags, &amp;m_constructionError);
</ins><span class="cx">         if (m_constructionError) {
</span><span class="cx">             LOG_ERROR(&quot;RegularExpression: YARR compile failed with '%s'&quot;, m_constructionError);
</span><span class="cx">             return nullptr;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrInterpretercpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -376,7 +376,7 @@
</span><span class="cx">             if (oldCh == ch)
</span><span class="cx">                 continue;
</span><span class="cx"> 
</span><del>-            if (pattern-&gt;m_ignoreCase) {
</del><ins>+            if (pattern-&gt;ignoreCase()) {
</ins><span class="cx">                 // See ES 6.0, 21.2.2.8.2 for the definition of Canonicalize(). For non-Unicode
</span><span class="cx">                 // patterns, Unicode values are never allowed to match against ASCII ones.
</span><span class="cx">                 // For Unicode, we need to check all canonical equivalents of a character.
</span><span class="lines">@@ -396,15 +396,15 @@
</span><span class="cx"> 
</span><span class="cx">     bool matchAssertionBOL(ByteTerm&amp; term)
</span><span class="cx">     {
</span><del>-        return (input.atStart(term.inputPosition)) || (pattern-&gt;m_multiline &amp;&amp; testCharacterClass(pattern-&gt;newlineCharacterClass, input.readChecked(term.inputPosition + 1)));
</del><ins>+        return (input.atStart(term.inputPosition)) || (pattern-&gt;multiline() &amp;&amp; testCharacterClass(pattern-&gt;newlineCharacterClass, input.readChecked(term.inputPosition + 1)));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool matchAssertionEOL(ByteTerm&amp; term)
</span><span class="cx">     {
</span><span class="cx">         if (term.inputPosition)
</span><del>-            return (input.atEnd(term.inputPosition)) || (pattern-&gt;m_multiline &amp;&amp; testCharacterClass(pattern-&gt;newlineCharacterClass, input.readChecked(term.inputPosition)));
</del><ins>+            return (input.atEnd(term.inputPosition)) || (pattern-&gt;multiline() &amp;&amp; testCharacterClass(pattern-&gt;newlineCharacterClass, input.readChecked(term.inputPosition)));
</ins><span class="cx"> 
</span><del>-        return (input.atEnd()) || (pattern-&gt;m_multiline &amp;&amp; testCharacterClass(pattern-&gt;newlineCharacterClass, input.read()));
</del><ins>+        return (input.atEnd()) || (pattern-&gt;multiline() &amp;&amp; testCharacterClass(pattern-&gt;newlineCharacterClass, input.read()));
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     bool matchAssertionWordBoundary(ByteTerm&amp; term)
</span><span class="lines">@@ -1153,7 +1153,7 @@
</span><span class="cx"> 
</span><span class="cx">         if (((matchBegin &amp;&amp; term.anchors.m_bol)
</span><span class="cx">              || ((matchEnd != input.end()) &amp;&amp; term.anchors.m_eol))
</span><del>-            &amp;&amp; !pattern-&gt;m_multiline)
</del><ins>+            &amp;&amp; !pattern-&gt;multiline())
</ins><span class="cx">             return false;
</span><span class="cx"> 
</span><span class="cx">         context-&gt;matchBegin = matchBegin;
</span><span class="lines">@@ -1387,7 +1387,7 @@
</span><span class="cx">             if (offset &gt; 0)
</span><span class="cx">                 MATCH_NEXT();
</span><span class="cx"> 
</span><del>-            if (input.atEnd())
</del><ins>+            if (input.atEnd() || pattern-&gt;sticky())
</ins><span class="cx">                 return JSRegExpNoMatch;
</span><span class="cx"> 
</span><span class="cx">             input.next();
</span><span class="lines">@@ -1541,9 +1541,9 @@
</span><span class="cx"> 
</span><span class="cx">     Interpreter(BytecodePattern* pattern, unsigned* output, const CharType* input, unsigned length, unsigned start)
</span><span class="cx">         : pattern(pattern)
</span><del>-        , unicode(pattern-&gt;m_unicode)
</del><ins>+        , unicode(pattern-&gt;unicode())
</ins><span class="cx">         , output(output)
</span><del>-        , input(input, start, length, pattern-&gt;m_unicode)
</del><ins>+        , input(input, start, length, pattern-&gt;unicode())
</ins><span class="cx">         , allocatorPool(0)
</span><span class="cx">         , remainingMatchCount(matchLimit)
</span><span class="cx">     {
</span><span class="lines">@@ -1612,7 +1612,7 @@
</span><span class="cx"> 
</span><span class="cx">     void atomPatternCharacter(UChar32 ch, unsigned inputPosition, unsigned frameLocation, Checked&lt;unsigned&gt; quantityCount, QuantifierType quantityType)
</span><span class="cx">     {
</span><del>-        if (m_pattern.m_ignoreCase) {
</del><ins>+        if (m_pattern.ignoreCase()) {
</ins><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="trunkSourceJavaScriptCoreyarrYarrInterpreterh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/yarr/YarrInterpreter.h        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -339,9 +339,7 @@
</span><span class="cx"> public:
</span><span class="cx">     BytecodePattern(std::unique_ptr&lt;ByteDisjunction&gt; body, Vector&lt;std::unique_ptr&lt;ByteDisjunction&gt;&gt;&amp; parenthesesInfoToAdopt, YarrPattern&amp; pattern, BumpPointerAllocator* allocator)
</span><span class="cx">         : m_body(WTFMove(body))
</span><del>-        , m_ignoreCase(pattern.m_ignoreCase)
-        , m_multiline(pattern.m_multiline)
-        , m_unicode(pattern.m_unicode)
</del><ins>+        , m_flags(pattern.m_flags)
</ins><span class="cx">         , m_allocator(allocator)
</span><span class="cx">     {
</span><span class="cx">         m_body-&gt;terms.shrinkToFit();
</span><span class="lines">@@ -357,11 +355,14 @@
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     size_t estimatedSizeInBytes() const { return m_body-&gt;estimatedSizeInBytes(); }
</span><ins>+    
+    bool ignoreCase() const { return m_flags &amp; FlagIgnoreCase; }
+    bool multiline() const { return m_flags &amp; FlagMultiline; }
+    bool sticky() const { return m_flags &amp; FlagSticky; }
+    bool unicode() const { return m_flags &amp; FlagUnicode; }
</ins><span class="cx"> 
</span><span class="cx">     std::unique_ptr&lt;ByteDisjunction&gt; m_body;
</span><del>-    bool m_ignoreCase;
-    bool m_multiline;
-    bool m_unicode;
</del><ins>+    RegExpFlags m_flags;
</ins><span class="cx">     // Each BytecodePattern is associated with a RegExp, each RegExp is associated
</span><span class="cx">     // with a VM.  Cache a pointer to out VM's m_regExpAllocator.
</span><span class="cx">     BumpPointerAllocator* m_allocator;
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrJITcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/yarr/YarrJIT.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -234,7 +234,7 @@
</span><span class="cx"> 
</span><span class="cx">             for (unsigned i = 0; i &lt; charClass-&gt;m_matches.size(); ++i) {
</span><span class="cx">                 char ch = charClass-&gt;m_matches[i];
</span><del>-                if (m_pattern.m_ignoreCase) {
</del><ins>+                if (m_pattern.ignoreCase()) {
</ins><span class="cx">                     if (isASCIILower(ch)) {
</span><span class="cx">                         matchesAZaz.append(ch);
</span><span class="cx">                         continue;
</span><span class="lines">@@ -291,8 +291,8 @@
</span><span class="cx"> 
</span><span class="cx">         // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">         // upper &amp; lower case representations are converted to a character class.
</span><del>-        ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
-        if (m_pattern.m_ignoreCase &amp;&amp; isASCIIAlpha(ch)) {
</del><ins>+        ASSERT(!m_pattern.ignoreCase() || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
+        if (m_pattern.ignoreCase() &amp;&amp; isASCIIAlpha(ch)) {
</ins><span class="cx">             or32(TrustedImm32(0x20), character);
</span><span class="cx">             ch |= 0x20;
</span><span class="cx">         }
</span><span class="lines">@@ -356,6 +356,13 @@
</span><span class="cx">             addPtr(Imm32(alignCallFrameSizeInBytes(callFrameSize)), stackPointerRegister);
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    void generateFailReturn()
+    {
+        move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
+        move(TrustedImm32(0), returnRegister2);
+        generateReturn();
+    }
+
</ins><span class="cx">     // Used to record subpatters, should only be called if compileMode is IncludeSubpatterns.
</span><span class="cx">     void setSubpatternStart(RegisterID reg, unsigned subpattern)
</span><span class="cx">     {
</span><span class="lines">@@ -633,7 +640,7 @@
</span><span class="cx">         YarrOp&amp; op = m_ops[opIndex];
</span><span class="cx">         PatternTerm* term = op.m_term;
</span><span class="cx"> 
</span><del>-        if (m_pattern.m_multiline) {
</del><ins>+        if (m_pattern.multiline()) {
</ins><span class="cx">             const RegisterID character = regT0;
</span><span class="cx"> 
</span><span class="cx">             JumpList matchDest;
</span><span class="lines">@@ -663,7 +670,7 @@
</span><span class="cx">         YarrOp&amp; op = m_ops[opIndex];
</span><span class="cx">         PatternTerm* term = op.m_term;
</span><span class="cx"> 
</span><del>-        if (m_pattern.m_multiline) {
</del><ins>+        if (m_pattern.multiline()) {
</ins><span class="cx">             const RegisterID character = regT0;
</span><span class="cx"> 
</span><span class="cx">             JumpList matchDest;
</span><span class="lines">@@ -787,9 +794,9 @@
</span><span class="cx"> 
</span><span class="cx">         // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">         // upper &amp; lower case representations are converted to a character class.
</span><del>-        ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
</del><ins>+        ASSERT(!m_pattern.ignoreCase() || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
</ins><span class="cx"> 
</span><del>-        if (m_pattern.m_ignoreCase &amp;&amp; isASCIIAlpha(ch))
</del><ins>+        if (m_pattern.ignoreCase() &amp;&amp; isASCIIAlpha(ch))
</ins><span class="cx"> #if CPU(BIG_ENDIAN)
</span><span class="cx">             ignoreCaseMask |= 32 &lt;&lt; (m_charSize == Char8 ? 24 : 16);
</span><span class="cx"> #else
</span><span class="lines">@@ -823,11 +830,11 @@
</span><span class="cx"> 
</span><span class="cx">             // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">             // upper &amp; lower case representations are converted to a character class.
</span><del>-            ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(currentCharacter) || isCanonicallyUnique(currentCharacter));
</del><ins>+            ASSERT(!m_pattern.ignoreCase() || isASCIIAlpha(currentCharacter) || isCanonicallyUnique(currentCharacter));
</ins><span class="cx"> 
</span><span class="cx">             allCharacters |= (currentCharacter &lt;&lt; shiftAmount);
</span><span class="cx"> 
</span><del>-            if ((m_pattern.m_ignoreCase) &amp;&amp; (isASCIIAlpha(currentCharacter)))
</del><ins>+            if ((m_pattern.ignoreCase()) &amp;&amp; (isASCIIAlpha(currentCharacter)))
</ins><span class="cx">                 ignoreCaseMask |= 32 &lt;&lt; shiftAmount;                    
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="lines">@@ -900,8 +907,8 @@
</span><span class="cx"> 
</span><span class="cx">         // For case-insesitive compares, non-ascii characters that have different
</span><span class="cx">         // upper &amp; lower case representations are converted to a character class.
</span><del>-        ASSERT(!m_pattern.m_ignoreCase || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
-        if (m_pattern.m_ignoreCase &amp;&amp; isASCIIAlpha(ch)) {
</del><ins>+        ASSERT(!m_pattern.ignoreCase() || isASCIIAlpha(ch) || isCanonicallyUnique(ch));
+        if (m_pattern.ignoreCase() &amp;&amp; isASCIIAlpha(ch)) {
</ins><span class="cx">             or32(TrustedImm32(0x20), character);
</span><span class="cx">             ch |= 0x20;
</span><span class="cx">         }
</span><span class="lines">@@ -1195,7 +1202,7 @@
</span><span class="cx">         add32(TrustedImm32(1), matchPos); // Advance past newline
</span><span class="cx">         saveStartIndex.link(this);
</span><span class="cx"> 
</span><del>-        if (!m_pattern.m_multiline &amp;&amp; term-&gt;anchors.bolAnchor)
</del><ins>+        if (!m_pattern.multiline() &amp;&amp; term-&gt;anchors.bolAnchor)
</ins><span class="cx">             op.m_jumps.append(branchTest32(NonZero, matchPos));
</span><span class="cx"> 
</span><span class="cx">         ASSERT(!m_pattern.m_body-&gt;m_hasFixedSize);
</span><span class="lines">@@ -1215,7 +1222,7 @@
</span><span class="cx"> 
</span><span class="cx">         foundEndingNewLine.link(this);
</span><span class="cx"> 
</span><del>-        if (!m_pattern.m_multiline &amp;&amp; term-&gt;anchors.eolAnchor)
</del><ins>+        if (!m_pattern.multiline() &amp;&amp; term-&gt;anchors.eolAnchor)
</ins><span class="cx">             op.m_jumps.append(branch32(NotEqual, matchPos, length));
</span><span class="cx"> 
</span><span class="cx">         move(matchPos, index);
</span><span class="lines">@@ -1750,9 +1757,7 @@
</span><span class="cx"> 
</span><span class="cx">             case OpMatchFailed:
</span><span class="cx">                 removeCallFrame();
</span><del>-                move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
-                move(TrustedImm32(0), returnRegister2);
-                generateReturn();
</del><ins>+                generateFailReturn();
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx"> 
</span><span class="lines">@@ -1843,47 +1848,64 @@
</span><span class="cx">                         // around to the first alternative.
</span><span class="cx">                         m_backtrackingState.link(this);
</span><span class="cx"> 
</span><del>-                        // If the pattern size is not fixed, then store the start index, for use if we match.
-                        if (!m_pattern.m_body-&gt;m_hasFixedSize) {
-                            if (alternative-&gt;m_minimumSize == 1)
-                                setMatchStart(index);
-                            else {
-                                move(index, regT0);
-                                if (alternative-&gt;m_minimumSize)
-                                    sub32(Imm32(alternative-&gt;m_minimumSize - 1), regT0);
-                                else
-                                    add32(TrustedImm32(1), regT0);
-                                setMatchStart(regT0);
</del><ins>+                        // No need to advance and retry for a stick pattern.
+                        if (!m_pattern.sticky()) {
+                            // If the pattern size is not fixed, then store the start index for use if we match.
+                            if (!m_pattern.m_body-&gt;m_hasFixedSize) {
+                                if (alternative-&gt;m_minimumSize == 1)
+                                    setMatchStart(index);
+                                else {
+                                    move(index, regT0);
+                                    if (alternative-&gt;m_minimumSize)
+                                        sub32(Imm32(alternative-&gt;m_minimumSize - 1), regT0);
+                                    else
+                                        add32(TrustedImm32(1), regT0);
+                                    setMatchStart(regT0);
+                                }
</ins><span class="cx">                             }
</span><del>-                        }
</del><span class="cx"> 
</span><del>-                        // Generate code to loop. Check whether the last alternative is longer than the
-                        // first (e.g. /a|xy/ or /a|xyz/).
-                        if (alternative-&gt;m_minimumSize &gt; beginOp-&gt;m_alternative-&gt;m_minimumSize) {
-                            // We want to loop, and increment input position. If the delta is 1, it is
-                            // already correctly incremented, if more than one then decrement as appropriate.
-                            unsigned delta = alternative-&gt;m_minimumSize - beginOp-&gt;m_alternative-&gt;m_minimumSize;
-                            ASSERT(delta);
-                            if (delta != 1)
-                                sub32(Imm32(delta - 1), index);
-                            jump(beginOp-&gt;m_reentry);
-                        } else {
-                            // If the first alternative has minimum size 0xFFFFFFFFu, then there cannot
-                            // be sufficent input available to handle this, so just fall through.
-                            unsigned delta = beginOp-&gt;m_alternative-&gt;m_minimumSize - alternative-&gt;m_minimumSize;
-                            if (delta != 0xFFFFFFFFu) {
-                                // We need to check input because we are incrementing the input.
-                                add32(Imm32(delta + 1), index);
-                                checkInput().linkTo(beginOp-&gt;m_reentry, this);
</del><ins>+                            // Generate code to loop. Check whether the last alternative is longer than the
+                            // first (e.g. /a|xy/ or /a|xyz/).
+                            if (alternative-&gt;m_minimumSize &gt; beginOp-&gt;m_alternative-&gt;m_minimumSize) {
+                                // We want to loop, and increment input position. If the delta is 1, it is
+                                // already correctly incremented, if more than one then decrement as appropriate.
+                                unsigned delta = alternative-&gt;m_minimumSize - beginOp-&gt;m_alternative-&gt;m_minimumSize;
+                                ASSERT(delta);
+                                if (delta != 1)
+                                    sub32(Imm32(delta - 1), index);
+                                jump(beginOp-&gt;m_reentry);
+                            } else {
+                                // If the first alternative has minimum size 0xFFFFFFFFu, then there cannot
+                                // be sufficent input available to handle this, so just fall through.
+                                unsigned delta = beginOp-&gt;m_alternative-&gt;m_minimumSize - alternative-&gt;m_minimumSize;
+                                if (delta != 0xFFFFFFFFu) {
+                                    // We need to check input because we are incrementing the input.
+                                    add32(Imm32(delta + 1), index);
+                                    checkInput().linkTo(beginOp-&gt;m_reentry, this);
+                                }
</ins><span class="cx">                             }
</span><span class="cx">                         }
</span><span class="cx">                     }
</span><span class="cx">                 }
</span><span class="cx"> 
</span><ins>+                if (m_pattern.sticky()) {
+                    // We have failed matching from the initial index and we're a sticky expression.
+                    // We are done matching. Link failures for any reason to here.
+                    YarrOp* tempOp = beginOp;
+                    do {
+                        tempOp-&gt;m_jumps.link(this);
+                        tempOp = &amp;m_ops[tempOp-&gt;m_nextOp];
+                    } while (tempOp-&gt;m_op != OpBodyAlternativeEnd);
+
+                    removeCallFrame();
+                    generateFailReturn();
+                    break;
+                }
+
</ins><span class="cx">                 // We can reach this point in the code in two ways:
</span><span class="cx">                 //  - Fallthrough from the code above (a repeating alternative backtracked out of its
</span><span class="cx">                 //    last alternative, and did not have sufficent input to run the first).
</span><del>-                //  - We will loop back up to the following label when a releating alternative loops,
</del><ins>+                //  - We will loop back up to the following label when a repeating alternative loops,
</ins><span class="cx">                 //    following a failed input check.
</span><span class="cx">                 //
</span><span class="cx">                 // Either way, we have just failed the input check for the first alternative.
</span><span class="lines">@@ -1990,9 +2012,7 @@
</span><span class="cx">                 matchFailed.link(this);
</span><span class="cx"> 
</span><span class="cx">                 removeCallFrame();
</span><del>-                move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
-                move(TrustedImm32(0), returnRegister2);
-                generateReturn();
</del><ins>+                generateFailReturn();
</ins><span class="cx">                 break;
</span><span class="cx">             }
</span><span class="cx">             case OpBodyAlternativeEnd: {
</span><span class="lines">@@ -2631,9 +2651,7 @@
</span><span class="cx">         generateEnter();
</span><span class="cx"> 
</span><span class="cx">         Jump hasInput = checkInput();
</span><del>-        move(TrustedImmPtr((void*)WTF::notFound), returnRegister);
-        move(TrustedImm32(0), returnRegister2);
-        generateReturn();
</del><ins>+        generateFailReturn();
</ins><span class="cx">         hasInput.link(this);
</span><span class="cx"> 
</span><span class="cx">         if (compileMode == IncludeSubpatterns) {
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrPatterncpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/yarr/YarrPattern.cpp        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -276,7 +276,7 @@
</span><span class="cx"> public:
</span><span class="cx">     YarrPatternConstructor(YarrPattern&amp; pattern)
</span><span class="cx">         : m_pattern(pattern)
</span><del>-        , m_characterClassConstructor(pattern.m_ignoreCase, pattern.m_unicode ? CanonicalMode::Unicode : CanonicalMode::UCS2)
</del><ins>+        , m_characterClassConstructor(pattern.ignoreCase(), pattern.unicode() ? CanonicalMode::Unicode : CanonicalMode::UCS2)
</ins><span class="cx">         , m_invertParentheticalAssertion(false)
</span><span class="cx">     {
</span><span class="cx">         auto body = std::make_unique&lt;PatternDisjunction&gt;();
</span><span class="lines">@@ -322,12 +322,12 @@
</span><span class="cx">     {
</span><span class="cx">         // We handle case-insensitive checking of unicode characters which do have both
</span><span class="cx">         // cases by handling them as if they were defined using a CharacterClass.
</span><del>-        if (!m_pattern.m_ignoreCase || (isASCII(ch) &amp;&amp; !m_pattern.m_unicode)) {
</del><ins>+        if (!m_pattern.ignoreCase() || (isASCII(ch) &amp;&amp; !m_pattern.unicode())) {
</ins><span class="cx">             m_alternative-&gt;m_terms.append(PatternTerm(ch));
</span><span class="cx">             return;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        const CanonicalizationRange* info = canonicalRangeInfoFor(ch, m_pattern.m_unicode ? CanonicalMode::Unicode : CanonicalMode::UCS2);
</del><ins>+        const CanonicalizationRange* info = canonicalRangeInfoFor(ch, m_pattern.unicode() ? CanonicalMode::Unicode : CanonicalMode::UCS2);
</ins><span class="cx">         if (info-&gt;type == CanonicalizeUnique) {
</span><span class="cx">             m_alternative-&gt;m_terms.append(PatternTerm(ch));
</span><span class="cx">             return;
</span><span class="lines">@@ -601,7 +601,7 @@
</span><span class="cx">                     term.frameLocation = currentCallFrameSize;
</span><span class="cx">                     currentCallFrameSize += YarrStackSpaceForBackTrackInfoPatternCharacter;
</span><span class="cx">                     alternative-&gt;m_hasFixedSize = false;
</span><del>-                } else if (m_pattern.m_unicode) {
</del><ins>+                } else if (m_pattern.unicode()) {
</ins><span class="cx">                     currentInputPosition += U16_LENGTH(term.patternCharacter) * term.quantityCount;
</span><span class="cx">                 } else
</span><span class="cx">                     currentInputPosition += term.quantityCount;
</span><span class="lines">@@ -613,7 +613,7 @@
</span><span class="cx">                     term.frameLocation = currentCallFrameSize;
</span><span class="cx">                     currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass;
</span><span class="cx">                     alternative-&gt;m_hasFixedSize = false;
</span><del>-                } else if (m_pattern.m_unicode) {
</del><ins>+                } else if (m_pattern.unicode()) {
</ins><span class="cx">                     term.frameLocation = currentCallFrameSize;
</span><span class="cx">                     currentCallFrameSize += YarrStackSpaceForBackTrackInfoCharacterClass;
</span><span class="cx">                     currentInputPosition += term.quantityCount;
</span><span class="lines">@@ -733,7 +733,7 @@
</span><span class="cx">         // At this point, this is only valid for non-multiline expressions.
</span><span class="cx">         PatternDisjunction* disjunction = m_pattern.m_body;
</span><span class="cx">         
</span><del>-        if (!m_pattern.m_containsBOL || m_pattern.m_multiline)
</del><ins>+        if (!m_pattern.m_containsBOL || m_pattern.multiline())
</ins><span class="cx">             return;
</span><span class="cx">         
</span><span class="cx">         PatternDisjunction* loopDisjunction = copyDisjunction(disjunction, true);
</span><span class="lines">@@ -844,7 +844,7 @@
</span><span class="cx"> {
</span><span class="cx">     YarrPatternConstructor constructor(*this);
</span><span class="cx"> 
</span><del>-    if (const char* error = parse(constructor, patternString, m_unicode))
</del><ins>+    if (const char* error = parse(constructor, patternString, unicode()))
</ins><span class="cx">         return error;
</span><span class="cx">     
</span><span class="cx">     // If the pattern contains illegal backreferences reset &amp; reparse.
</span><span class="lines">@@ -858,7 +858,7 @@
</span><span class="cx"> #if !ASSERT_DISABLED
</span><span class="cx">         const char* error =
</span><span class="cx"> #endif
</span><del>-            parse(constructor, patternString, m_unicode, numSubpatterns);
</del><ins>+            parse(constructor, patternString, unicode(), numSubpatterns);
</ins><span class="cx"> 
</span><span class="cx">         ASSERT(!error);
</span><span class="cx">         ASSERT(numSubpatterns == m_numSubpatterns);
</span><span class="lines">@@ -873,13 +873,11 @@
</span><span class="cx">     return 0;
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-YarrPattern::YarrPattern(const String&amp; pattern, bool ignoreCase, bool multiline, bool unicode, const char** error)
-    : m_ignoreCase(ignoreCase)
-    , m_multiline(multiline)
-    , m_unicode(unicode)
-    , m_containsBackreferences(false)
</del><ins>+YarrPattern::YarrPattern(const String&amp; pattern, RegExpFlags flags, const char** error)
+    : m_containsBackreferences(false)
</ins><span class="cx">     , m_containsBOL(false)
</span><span class="cx">     , m_containsUnsignedLengthPattern(false)
</span><ins>+    , m_flags(flags)
</ins><span class="cx">     , m_numSubpatterns(0)
</span><span class="cx">     , m_maxBackReference(0)
</span><span class="cx">     , newlineCached(0)
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreyarrYarrPatternh"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/yarr/YarrPattern.h (197868 => 197869)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/yarr/YarrPattern.h        2016-03-09 19:56:41 UTC (rev 197868)
+++ trunk/Source/JavaScriptCore/yarr/YarrPattern.h        2016-03-09 20:11:46 UTC (rev 197869)
</span><span class="lines">@@ -27,6 +27,7 @@
</span><span class="cx"> #ifndef YarrPattern_h
</span><span class="cx"> #define YarrPattern_h
</span><span class="cx"> 
</span><ins>+#include &quot;RegExpKey.h&quot;
</ins><span class="cx"> #include &lt;wtf/CheckedArithmetic.h&gt;
</span><span class="cx"> #include &lt;wtf/RefCounted.h&gt;
</span><span class="cx"> #include &lt;wtf/Vector.h&gt;
</span><span class="lines">@@ -299,8 +300,9 @@
</span><span class="cx">     Vector&lt;TermChain&gt; hotTerms;
</span><span class="cx"> };
</span><span class="cx"> 
</span><ins>+
</ins><span class="cx"> struct YarrPattern {
</span><del>-    JS_EXPORT_PRIVATE YarrPattern(const String&amp; pattern, bool ignoreCase, bool multiline, bool unicode, const char** error);
</del><ins>+    JS_EXPORT_PRIVATE YarrPattern(const String&amp; pattern, RegExpFlags flags, const char** error);
</ins><span class="cx"> 
</span><span class="cx">     void reset()
</span><span class="cx">     {
</span><span class="lines">@@ -390,12 +392,15 @@
</span><span class="cx">         return nonwordcharCached;
</span><span class="cx">     }
</span><span class="cx"> 
</span><del>-    bool m_ignoreCase : 1;
-    bool m_multiline : 1;
-    bool m_unicode : 1;
</del><ins>+    bool ignoreCase() const { return m_flags &amp; FlagIgnoreCase; }
+    bool multiline() const { return m_flags &amp; FlagMultiline; }
+    bool sticky() const { return m_flags &amp; FlagSticky; }
+    bool unicode() const { return m_flags &amp; FlagUnicode; }
+
</ins><span class="cx">     bool m_containsBackreferences : 1;
</span><span class="cx">     bool m_containsBOL : 1;
</span><span class="cx">     bool m_containsUnsignedLengthPattern : 1; 
</span><ins>+    RegExpFlags m_flags;
</ins><span class="cx">     unsigned m_numSubpatterns;
</span><span class="cx">     unsigned m_maxBackReference;
</span><span class="cx">     PatternDisjunction* m_body;
</span></span></pre>
</div>
</div>

</body>
</html>