<!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>[173761] 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/173761">173761</a></dd>
<dt>Author</dt> <dd>commit-queue@webkit.org</dd>
<dt>Date</dt> <dd>2014-09-19 10:47:50 -0700 (Fri, 19 Sep 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Simple ES6 feature:String prototype additions
https://bugs.webkit.org/show_bug.cgi?id=131704

Patch by Diego Pino Garcia &lt;dpino@igalia.com&gt; on 2014-09-19
Reviewed by Darin Adler.

Source/JavaScriptCore:

* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
(JSC::stringProtoFuncStartsWith): Added.
(JSC::stringProtoFuncEndsWith): Added.
(JSC::stringProtoFuncContains): Added.

Source/WTF:

* wtf/text/StringImpl.cpp:
(WTF::StringImpl::find):
(WTF::equalInner): Added.
(WTF::StringImpl::startsWith): Add implementation that supports
'startOffset' parameter.
(WTF::StringImpl::endsWith): Add implementation that supports
'endOffset' parameter.
* wtf/text/StringImpl.h:
* wtf/text/WTFString.h:
(WTF::String::contains): Modify current implementation to allow
setting a startOffset, 0 by default.
(WTF::String::startsWith):
(WTF::String::endsWith):

LayoutTests:

Test ES6 functions: string.startsWith(), string.endsWith() and
string.contains().

* js/Object-getOwnPropertyNames-expected.txt:
* js/script-tests/Object-getOwnPropertyNames.js:
* js/script-tests/string-contains.js: Added.
(stringToSearchIn.toString):
(startOffset.valueOf):
(matchString.toString):
(endOffset.valueOf):
* js/string-contains-expected.txt: Added.
* js/string-contains.html: Added.</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="#trunkLayoutTestsjsscripttestsObjectgetOwnPropertyNamesjs">trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js</a></li>
<li><a href="#trunkSourceJavaScriptCoreChangeLog">trunk/Source/JavaScriptCore/ChangeLog</a></li>
<li><a href="#trunkSourceJavaScriptCoreruntimeStringPrototypecpp">trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp</a></li>
<li><a href="#trunkSourceWTFChangeLog">trunk/Source/WTF/ChangeLog</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplcpp">trunk/Source/WTF/wtf/text/StringImpl.cpp</a></li>
<li><a href="#trunkSourceWTFwtftextStringImplh">trunk/Source/WTF/wtf/text/StringImpl.h</a></li>
<li><a href="#trunkSourceWTFwtftextWTFStringh">trunk/Source/WTF/wtf/text/WTFString.h</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsscripttestsstringcontainsjs">trunk/LayoutTests/js/script-tests/string-contains.js</a></li>
<li><a href="#trunkLayoutTestsjsstringcontainsexpectedtxt">trunk/LayoutTests/js/string-contains-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsstringcontainshtml">trunk/LayoutTests/js/string-contains.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/LayoutTests/ChangeLog        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2014-09-19  Diego Pino Garcia  &lt;dpino@igalia.com&gt;
+
+        Simple ES6 feature:String prototype additions
+        https://bugs.webkit.org/show_bug.cgi?id=131704
+
+        Reviewed by Darin Adler.
+
+        Test ES6 functions: string.startsWith(), string.endsWith() and
+        string.contains().
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/script-tests/Object-getOwnPropertyNames.js:
+        * js/script-tests/string-contains.js: Added.
+        (stringToSearchIn.toString):
+        (startOffset.valueOf):
+        (matchString.toString):
+        (endOffset.valueOf):
+        * js/string-contains-expected.txt: Added.
+        * js/string-contains.html: Added.
+
</ins><span class="cx"> 2014-09-19  Youenn Fablet  &lt;youenn.fablet@crf.canon.fr&gt;
</span><span class="cx"> 
</span><span class="cx">         WTR and DRT didReceiveAuthenticationChallengeInFrame should print messages consistently
</span></span></pre></div>
<a id="trunkLayoutTestsjsObjectgetOwnPropertyNamesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -47,7 +47,7 @@
</span><span class="cx"> PASS getSortedOwnPropertyNames(Array) is ['isArray', 'length', 'name', 'prototype']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift']
</span><span class="cx"> PASS getSortedOwnPropertyNames(String) is ['fromCharCode', 'length', 'name', 'prototype']
</span><del>-PASS getSortedOwnPropertyNames(String.prototype) is ['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'concat', 'constructor', 'fixed', 'fontcolor', 'fontsize', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'replace', 'search', 'slice', 'small', 'split', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']
</del><ins>+PASS getSortedOwnPropertyNames(String.prototype) is ['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'concat', 'constructor', 'contains', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']
</ins><span class="cx"> PASS getSortedOwnPropertyNames(Boolean) is ['length', 'name', 'prototype']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Boolean.prototype) is ['constructor', 'toString', 'valueOf']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Number) is ['MAX_VALUE', 'MIN_VALUE', 'NEGATIVE_INFINITY', 'NaN', 'POSITIVE_INFINITY', 'length', 'name', 'prototype']
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsObjectgetOwnPropertyNamesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -55,7 +55,7 @@
</span><span class="cx">     &quot;Array&quot;: &quot;['isArray', 'length', 'name', 'prototype']&quot;,
</span><span class="cx">     &quot;Array.prototype&quot;: &quot;['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift']&quot;,
</span><span class="cx">     &quot;String&quot;: &quot;['fromCharCode', 'length', 'name', 'prototype']&quot;,
</span><del>-    &quot;String.prototype&quot;: &quot;['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'concat', 'constructor', 'fixed', 'fontcolor', 'fontsize', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'replace', 'search', 'slice', 'small', 'split', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']&quot;,
</del><ins>+    &quot;String.prototype&quot;: &quot;['anchor', 'big', 'blink', 'bold', 'charAt', 'charCodeAt', 'concat', 'constructor', 'contains', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', 'strike', 'sub', 'substr', 'substring', 'sup', 'toLocaleLowerCase', 'toLocaleUpperCase', 'toLowerCase', 'toString', 'toUpperCase', 'trim', 'trimLeft', 'trimRight', 'valueOf']&quot;,
</ins><span class="cx">     &quot;Boolean&quot;: &quot;['length', 'name', 'prototype']&quot;,
</span><span class="cx">     &quot;Boolean.prototype&quot;: &quot;['constructor', 'toString', 'valueOf']&quot;,
</span><span class="cx">     &quot;Number&quot;: &quot;['MAX_VALUE', 'MIN_VALUE', 'NEGATIVE_INFINITY', 'NaN', 'POSITIVE_INFINITY', 'length', 'name', 'prototype']&quot;,
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsstringcontainsjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/string-contains.js (0 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/string-contains.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/string-contains.js        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -0,0 +1,278 @@
</span><ins>+description(&quot;This test checks the ES6 string functions startsWith(), endsWith() and contains().&quot;);
+
+// Test contains
+shouldBe(&quot;'foo bar'.contains('bar')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains('bar', 4)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains('ar', 5)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains('qux')&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo bar'.contains('foo')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains('foo', 0)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains('foo', -1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains('')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.contains()&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo bar qux'.contains('qux', 7)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar qux'.contains('bar', 7)&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo null bar'.contains()&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo null bar'.contains(null)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo null bar'.contains(null)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined bar'.contains()&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined bar'.contains(undefined)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined bar'.contains()&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined bar'.contains()&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo true bar'.contains(true)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo false bar'.contains(false)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1 bar'.contains(1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1.1 bar'.contains(1.1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo NaN bar'.contains(NaN)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1.0 bar'.contains(1.0)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1e+100 bar'.contains(1e+100)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1e100 bar'.contains(1e100)&quot;, &quot;false&quot;);
+shouldBe(&quot;'フーバー'.contains('ーバ')&quot;, &quot;true&quot;);
+shouldBe(&quot;'フーバー'.contains('クー')&quot;, &quot;false&quot;);
+
+// Test startsWith
+shouldBe(&quot;'foo bar'.startsWith('foo')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.startsWith('foo', 0)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.startsWith('foo', -1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.startsWith('oo', 1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.startsWith('qux')&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo bar'.startsWith('')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.startsWith()&quot;, &quot;false&quot;);
+shouldBe(&quot;'null'.startsWith()&quot;, &quot;false&quot;);
+shouldBe(&quot;'null'.startsWith(null)&quot;, &quot;true&quot;);
+shouldBe(&quot;'null bar'.startsWith(null)&quot;, &quot;true&quot;);
+shouldBe(&quot;'undefined'.startsWith()&quot;, &quot;true&quot;);
+shouldBe(&quot;'undefined'.startsWith(undefined)&quot;, &quot;true&quot;);
+shouldBe(&quot;'undefined bar'.startsWith()&quot;, &quot;true&quot;);
+shouldBe(&quot;'undefined bar'.startsWith()&quot;, &quot;true&quot;);
+shouldBe(&quot;'true bar'.startsWith(true)&quot;, &quot;true&quot;);
+shouldBe(&quot;'false bar'.startsWith(false)&quot;, &quot;true&quot;);
+shouldBe(&quot;'1 bar'.startsWith(1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'1.1 bar'.startsWith(1.1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'NaN bar'.startsWith(NaN)&quot;, &quot;true&quot;);
+shouldBe(&quot;'1e+100 bar'.startsWith(1e+100)&quot;, &quot;true&quot;);
+shouldBe(&quot;'1e100 bar'.startsWith(1e100)&quot;, &quot;false&quot;);
+shouldBe(&quot;'フーバー'.startsWith('フー')&quot;, &quot;true&quot;);
+shouldBe(&quot;'フーバー'.startsWith('バー')&quot;, &quot;false&quot;);
+
+// Test endsWith
+shouldBe(&quot;'foo bar'.endsWith('bar')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith('ba', 6)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith(' ba', 6)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith('foo bar')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith('foo bar', 7)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith('foo bar', 8)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith('foo bar', -1)&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo bar'.endsWith('qux')&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo bar'.endsWith('')&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo bar'.endsWith()&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo null'.endsWith()&quot;, &quot;false&quot;);
+shouldBe(&quot;'foo null'.endsWith(null)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo null'.endsWith(null)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined'.endsWith()&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined'.endsWith(undefined)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined'.endsWith()&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo undefined'.endsWith()&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo true'.endsWith(true)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo false'.endsWith(false)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1'.endsWith(1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1.1'.endsWith(1.1)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo NaN'.endsWith(NaN)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1e+100'.endsWith(1e+100)&quot;, &quot;true&quot;);
+shouldBe(&quot;'foo 1e100'.endsWith(1e100)&quot;, &quot;false&quot;);
+shouldBe(&quot;'フーバー'.endsWith('バー')&quot;, &quot;true&quot;);
+shouldBe(&quot;'フーバー'.endsWith('フー')&quot;, &quot;false&quot;);
+
+// Call functions with an environment record as 'this'.
+shouldThrow(&quot;(function() { var f = String.prototype.startsWith; (function() { f('a'); })(); })()&quot;);
+shouldThrow(&quot;(function() { var f = String.prototype.endsWith; (function() { f('a'); })(); })()&quot;);
+shouldThrow(&quot;(function() { var f = String.prototype.contains; (function() { f('a'); })(); })()&quot;);
+
+// ES6 spec says a regex as argument should throw an Exception.
+shouldThrow(&quot;'foo bar'.startsWith(/\w+/)&quot;);
+shouldThrow(&quot;'foo bar'.endsWith(/\w+/)&quot;);
+shouldThrow(&quot;'foo bar'.contains(/\w+/)&quot;);
+
+// Check side effects in startsWith.
+var sideEffect = &quot;&quot;;
+var stringToSearchIn = new String(&quot;foo bar&quot;);
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+var startOffset = new Number(0);
+startOffset.valueOf = function() {
+    sideEffect += &quot;B&quot;;
+    return this;
+}
+var matchString = new String(&quot;foo&quot;);
+matchString.toString = function() {
+    sideEffect += &quot;C&quot;;
+    return this;
+}
+// Calling stringToSearchIn.startsWith implicitly calls stringToSearchIn.toString(),
+// startOffset.valueOf() and matchString.toString(), in that respective order.
+shouldBe(&quot;stringToSearchIn.startsWith(matchString, startOffset)&quot;, &quot;true&quot;);
+shouldBe(&quot;sideEffect == 'ABC'&quot;, &quot;true&quot;);
+
+// If stringToSearchIn throws an exception startOffset.valueOf() and
+// matchString.toString() are not called.
+stringToSearchIn.toString = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.startsWith(matchString, startOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == ''&quot;, &quot;true&quot;);
+
+// If startOffset throws an exception stringToSearchIn.toString() is called but
+// matchString.toString() is not.
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+startOffset.valueOf = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.startsWith(matchString, startOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == 'A'&quot;, &quot;true&quot;);
+
+// If matchString.toString() throws an exception stringToSearchIn.toString() and
+// startOffset.valueOf() were called.
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+startOffset.valueOf = function() {
+    sideEffect += &quot;B&quot;;
+    return this;
+}
+matchString.toString = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.startsWith(matchString, startOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == 'AB'&quot;, &quot;true&quot;);
+
+// Check side effects in endsWith.
+sideEffect = &quot;&quot;;
+stringToSearchIn = new String('foo bar');
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+var endOffset = new Number(stringToSearchIn.length);
+endOffset.valueOf = function() {
+    sideEffect += &quot;B&quot;;
+    return this;
+}
+matchString = new String('bar');
+matchString.toString = function() {
+    sideEffect += &quot;C&quot;;
+    return this;
+}
+
+// Calling stringToSearchIn.endsWith implicitly calls stringToSearchIn.toString(),
+// endOffset.valueOf() and matchString.toString(), in that respective order.
+shouldBe(&quot;stringToSearchIn.endsWith(matchString, endOffset)&quot;, &quot;true&quot;);
+shouldBe(&quot;sideEffect == 'ABC'&quot;, &quot;true&quot;);
+
+// If stringToSearchIn throws an exception endOffset.valueOf() and
+// matchString.toString() are not called.
+stringToSearchIn.toString = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.endsWith(matchString, endOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == ''&quot;, &quot;true&quot;);
+
+// If endOffset throws an exception stringToSearchIn.toString() is called but
+// matchString.toString() is not.
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+endOffset.valueOf = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.endsWith(matchString, endOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == 'A'&quot;, &quot;true&quot;);
+
+// If matchString.toString() throws an exception stringToSearchIn.toString() and
+// endOffset.valueOf() were called.
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+endOffset.valueOf = function() {
+    sideEffect += &quot;B&quot;;
+    return this;
+}
+matchString.toString = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.endsWith(matchString, endOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == 'AB'&quot;, &quot;true&quot;);
+
+// Check side effects in contains.
+var sideEffect = &quot;&quot;;
+stringToSearchIn = new String(&quot;foo bar&quot;);
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+var startOffset = new Number(0);
+startOffset.valueOf = function() {
+    sideEffect += &quot;B&quot;;
+    return this;
+}
+matchString = new String(&quot;foo&quot;);
+matchString.toString = function() {
+    sideEffect += &quot;C&quot;;
+    return this;
+}
+// Calling stringToSearchIn.contains implicitly calls stringToSearchIn.toString(),
+// startOffset.valueOf() and matchString.toString(), in that respective order.
+shouldBe(&quot;stringToSearchIn.contains(matchString, startOffset)&quot;, &quot;true&quot;);
+shouldBe(&quot;sideEffect == 'ABC'&quot;, &quot;true&quot;);
+
+// If stringToSearchIn throws an exception startOffset.valueOf() and
+// matchString.toString() are not called.
+stringToSearchIn.toString = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.contains(matchString, startOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == ''&quot;, &quot;true&quot;);
+
+// If startOffset throws an exception stringToSearchIn.toString() is called but
+// matchString.toString() is not.
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+startOffset.valueOf = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.contains(matchString, startOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == 'A'&quot;, &quot;true&quot;);
+
+// If matchString.toString() throws an exception stringToSearchIn.toString() and
+// startOffset.valueOf() were called.
+stringToSearchIn.toString = function() {
+    sideEffect += &quot;A&quot;;
+    return this;
+}
+startOffset.valueOf = function() {
+    sideEffect += &quot;B&quot;;
+    return this;
+}
+matchString.toString = function() {
+    throw &quot;error&quot;;
+}
+sideEffect = &quot;&quot;;
+shouldThrow(&quot;stringToSearchIn.contains(matchString, startOffset)&quot;, &quot;'error'&quot;);
+shouldBe(&quot;sideEffect == 'AB'&quot;, &quot;true&quot;);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsstringcontainsexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/string-contains-expected.txt (0 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/string-contains-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/string-contains-expected.txt        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -0,0 +1,116 @@
</span><ins>+This test checks the ES6 string functions startsWith(), endsWith() and contains().
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS 'foo bar'.contains('bar') is true
+PASS 'foo bar'.contains('bar', 4) is true
+PASS 'foo bar'.contains('ar', 5) is true
+PASS 'foo bar'.contains('qux') is false
+PASS 'foo bar'.contains('foo') is true
+PASS 'foo bar'.contains('foo', 0) is true
+PASS 'foo bar'.contains('foo', -1) is true
+PASS 'foo bar'.contains('') is true
+PASS 'foo bar'.contains() is false
+PASS 'foo bar qux'.contains('qux', 7) is true
+PASS 'foo bar qux'.contains('bar', 7) is false
+PASS 'foo null bar'.contains() is false
+PASS 'foo null bar'.contains(null) is true
+PASS 'foo null bar'.contains(null) is true
+PASS 'foo undefined bar'.contains() is true
+PASS 'foo undefined bar'.contains(undefined) is true
+PASS 'foo undefined bar'.contains() is true
+PASS 'foo undefined bar'.contains() is true
+PASS 'foo true bar'.contains(true) is true
+PASS 'foo false bar'.contains(false) is true
+PASS 'foo 1 bar'.contains(1) is true
+PASS 'foo 1.1 bar'.contains(1.1) is true
+PASS 'foo NaN bar'.contains(NaN) is true
+PASS 'foo 1.0 bar'.contains(1.0) is true
+PASS 'foo 1e+100 bar'.contains(1e+100) is true
+PASS 'foo 1e100 bar'.contains(1e100) is false
+PASS 'フーバー'.contains('ーバ') is true
+PASS 'フーバー'.contains('クー') is false
+PASS 'foo bar'.startsWith('foo') is true
+PASS 'foo bar'.startsWith('foo', 0) is true
+PASS 'foo bar'.startsWith('foo', -1) is true
+PASS 'foo bar'.startsWith('oo', 1) is true
+PASS 'foo bar'.startsWith('qux') is false
+PASS 'foo bar'.startsWith('') is true
+PASS 'foo bar'.startsWith() is false
+PASS 'null'.startsWith() is false
+PASS 'null'.startsWith(null) is true
+PASS 'null bar'.startsWith(null) is true
+PASS 'undefined'.startsWith() is true
+PASS 'undefined'.startsWith(undefined) is true
+PASS 'undefined bar'.startsWith() is true
+PASS 'undefined bar'.startsWith() is true
+PASS 'true bar'.startsWith(true) is true
+PASS 'false bar'.startsWith(false) is true
+PASS '1 bar'.startsWith(1) is true
+PASS '1.1 bar'.startsWith(1.1) is true
+PASS 'NaN bar'.startsWith(NaN) is true
+PASS '1e+100 bar'.startsWith(1e+100) is true
+PASS '1e100 bar'.startsWith(1e100) is false
+PASS 'フーバー'.startsWith('フー') is true
+PASS 'フーバー'.startsWith('バー') is false
+PASS 'foo bar'.endsWith('bar') is true
+PASS 'foo bar'.endsWith('ba', 6) is true
+PASS 'foo bar'.endsWith(' ba', 6) is true
+PASS 'foo bar'.endsWith('foo bar') is true
+PASS 'foo bar'.endsWith('foo bar', 7) is true
+PASS 'foo bar'.endsWith('foo bar', 8) is true
+PASS 'foo bar'.endsWith('foo bar', -1) is false
+PASS 'foo bar'.endsWith('qux') is false
+PASS 'foo bar'.endsWith('') is true
+PASS 'foo bar'.endsWith() is false
+PASS 'foo null'.endsWith() is false
+PASS 'foo null'.endsWith(null) is true
+PASS 'foo null'.endsWith(null) is true
+PASS 'foo undefined'.endsWith() is true
+PASS 'foo undefined'.endsWith(undefined) is true
+PASS 'foo undefined'.endsWith() is true
+PASS 'foo undefined'.endsWith() is true
+PASS 'foo true'.endsWith(true) is true
+PASS 'foo false'.endsWith(false) is true
+PASS 'foo 1'.endsWith(1) is true
+PASS 'foo 1.1'.endsWith(1.1) is true
+PASS 'foo NaN'.endsWith(NaN) is true
+PASS 'foo 1e+100'.endsWith(1e+100) is true
+PASS 'foo 1e100'.endsWith(1e100) is false
+PASS 'フーバー'.endsWith('バー') is true
+PASS 'フーバー'.endsWith('フー') is false
+PASS (function() { var f = String.prototype.startsWith; (function() { f('a'); })(); })() threw exception TypeError: Type error.
+PASS (function() { var f = String.prototype.endsWith; (function() { f('a'); })(); })() threw exception TypeError: Type error.
+PASS (function() { var f = String.prototype.contains; (function() { f('a'); })(); })() threw exception TypeError: Type error.
+PASS 'foo bar'.startsWith(/w+/) threw exception TypeError: Type error.
+PASS 'foo bar'.endsWith(/w+/) threw exception TypeError: Type error.
+PASS 'foo bar'.contains(/w+/) threw exception TypeError: Type error.
+PASS stringToSearchIn.startsWith(matchString, startOffset) is true
+PASS sideEffect == 'ABC' is true
+PASS stringToSearchIn.startsWith(matchString, startOffset) threw exception error.
+PASS sideEffect == '' is true
+PASS stringToSearchIn.startsWith(matchString, startOffset) threw exception error.
+PASS sideEffect == 'A' is true
+PASS stringToSearchIn.startsWith(matchString, startOffset) threw exception error.
+PASS sideEffect == 'AB' is true
+PASS stringToSearchIn.endsWith(matchString, endOffset) is true
+PASS sideEffect == 'ABC' is true
+PASS stringToSearchIn.endsWith(matchString, endOffset) threw exception error.
+PASS sideEffect == '' is true
+PASS stringToSearchIn.endsWith(matchString, endOffset) threw exception error.
+PASS sideEffect == 'A' is true
+PASS stringToSearchIn.endsWith(matchString, endOffset) threw exception error.
+PASS sideEffect == 'AB' is true
+PASS stringToSearchIn.contains(matchString, startOffset) is true
+PASS sideEffect == 'ABC' is true
+PASS stringToSearchIn.contains(matchString, startOffset) threw exception error.
+PASS sideEffect == '' is true
+PASS stringToSearchIn.contains(matchString, startOffset) threw exception error.
+PASS sideEffect == 'A' is true
+PASS stringToSearchIn.contains(matchString, startOffset) threw exception error.
+PASS sideEffect == 'AB' is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsstringcontainshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/string-contains.html (0 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/string-contains.html                                (rev 0)
+++ trunk/LayoutTests/js/string-contains.html        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;html&gt;
+&lt;head&gt;
+  &lt;meta charset=&quot;UTF-8&quot;&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/string-contains.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="trunkSourceJavaScriptCoreChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/ChangeLog (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/Source/JavaScriptCore/ChangeLog        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -1,3 +1,16 @@
</span><ins>+2014-09-19  Diego Pino Garcia  &lt;dpino@igalia.com&gt;
+
+        Simple ES6 feature:String prototype additions
+        https://bugs.webkit.org/show_bug.cgi?id=131704
+
+        Reviewed by Darin Adler.
+
+        * runtime/StringPrototype.cpp:
+        (JSC::StringPrototype::finishCreation):
+        (JSC::stringProtoFuncStartsWith): Added.
+        (JSC::stringProtoFuncEndsWith): Added.
+        (JSC::stringProtoFuncContains): Added.
+
</ins><span class="cx"> 2014-09-18  Joseph Pecoraro  &lt;pecoraro@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Unreviewed rollout r173731. Broke multiple builds.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -82,6 +82,9 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncTrim(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimLeft(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncTrimRight(ExecState*);
</span><ins>+EncodedJSValue JSC_HOST_CALL stringProtoFuncStartsWith(ExecState*);
+EncodedJSValue JSC_HOST_CALL stringProtoFuncEndsWith(ExecState*);
+EncodedJSValue JSC_HOST_CALL stringProtoFuncContains(ExecState*);
</ins><span class="cx"> 
</span><span class="cx"> const ClassInfo StringPrototype::s_info = { &quot;String&quot;, &amp;StringObject::s_info, 0, CREATE_METHOD_TABLE(StringPrototype) };
</span><span class="cx"> 
</span><span class="lines">@@ -131,6 +134,9 @@
</span><span class="cx">     JSC_NATIVE_FUNCTION(&quot;trim&quot;, stringProtoFuncTrim, DontEnum, 0);
</span><span class="cx">     JSC_NATIVE_FUNCTION(&quot;trimLeft&quot;, stringProtoFuncTrimLeft, DontEnum, 0);
</span><span class="cx">     JSC_NATIVE_FUNCTION(&quot;trimRight&quot;, stringProtoFuncTrimRight, DontEnum, 0);
</span><ins>+    JSC_NATIVE_FUNCTION(&quot;startsWith&quot;, stringProtoFuncStartsWith, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(&quot;endsWith&quot;, stringProtoFuncEndsWith, DontEnum, 0);
+    JSC_NATIVE_FUNCTION(&quot;contains&quot;, stringProtoFuncContains, DontEnum, 0);
</ins><span class="cx"> 
</span><span class="cx">     // The constructor will be added later, after StringConstructor has been built
</span><span class="cx">     putDirectWithoutTransition(vm, vm.propertyNames-&gt;length, jsNumber(0), DontDelete | ReadOnly | DontEnum);
</span><span class="lines">@@ -1546,6 +1552,77 @@
</span><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span><span class="cx">     return JSValue::encode(trimString(exec, thisValue, TrimRight));
</span><span class="cx"> }
</span><ins>+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncStartsWith(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    if (!checkObjectCoercible(thisValue))
+        return throwVMTypeError(exec);
+
+    String stringToSearchIn = thisValue.toString(exec)-&gt;value(exec);
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue a0 = exec-&gt;argument(0);
+    if (jsDynamicCast&lt;RegExpObject*&gt;(a0))
+        return throwVMTypeError(exec);
+
+    unsigned start = std::max(0, exec-&gt;argument(1).toInt32(exec));
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    String matchString = a0.toString(exec)-&gt;value(exec);
+
+    return JSValue::encode(jsBoolean(stringToSearchIn.startsWith(matchString, start, true)));
+}
+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncEndsWith(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    if (!checkObjectCoercible(thisValue))
+        return throwVMTypeError(exec);
+
+    String stringToSearchIn = thisValue.toString(exec)-&gt;value(exec);
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue a0 = exec-&gt;argument(0);
+    if (jsDynamicCast&lt;RegExpObject*&gt;(a0))
+        return throwVMTypeError(exec);
+
+    unsigned length = stringToSearchIn.length();
+    JSValue a1 = exec-&gt;argument(1);
+    int pos = a1.isUndefined() ? length : a1.toInt32(exec);
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+    unsigned end = std::min&lt;unsigned&gt;(std::max(pos, 0), length);
+
+    String matchString = a0.toString(exec)-&gt;value(exec);
+
+    return JSValue::encode(jsBoolean(stringToSearchIn.endsWith(matchString, end, true)));
+}
+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncContains(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    if (!checkObjectCoercible(thisValue))
+        return throwVMTypeError(exec);
+
+    String stringToSearchIn = thisValue.toString(exec)-&gt;value(exec);
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    JSValue a0 = exec-&gt;argument(0);
+    if (jsDynamicCast&lt;RegExpObject*&gt;(a0))
+        return throwVMTypeError(exec);
+
+    unsigned start = std::max(0, exec-&gt;argument(1).toInt32(exec));
+    if (exec-&gt;hadException())
+        return JSValue::encode(jsUndefined());
+
+    String matchString = a0.toString(exec)-&gt;value(exec);
+
+    return JSValue::encode(jsBoolean(stringToSearchIn.contains(matchString, true, start)));
+}
</ins><span class="cx">     
</span><del>-    
</del><span class="cx"> } // namespace JSC
</span></span></pre></div>
<a id="trunkSourceWTFChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/ChangeLog (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/ChangeLog        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/Source/WTF/ChangeLog        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -1,3 +1,24 @@
</span><ins>+2014-09-19  Diego Pino Garcia  &lt;dpino@igalia.com&gt;
+
+        Simple ES6 feature:String prototype additions
+        https://bugs.webkit.org/show_bug.cgi?id=131704
+
+        Reviewed by Darin Adler.
+
+        * wtf/text/StringImpl.cpp:
+        (WTF::StringImpl::find):
+        (WTF::equalInner): Added.
+        (WTF::StringImpl::startsWith): Add implementation that supports
+        'startOffset' parameter.
+        (WTF::StringImpl::endsWith): Add implementation that supports
+        'endOffset' parameter.
+        * wtf/text/StringImpl.h:
+        * wtf/text/WTFString.h:
+        (WTF::String::contains): Modify current implementation to allow
+        setting a startOffset, 0 by default.
+        (WTF::String::startsWith):
+        (WTF::String::endsWith):
+
</ins><span class="cx"> 2014-09-18  Carlos Garcia Campos  &lt;cgarcia@igalia.com&gt;
</span><span class="cx"> 
</span><span class="cx">         [GTK] Dot not allow to create delete-on-destroy GMainLoopSources
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplcpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.cpp (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.cpp        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/Source/WTF/wtf/text/StringImpl.cpp        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -1368,6 +1368,25 @@
</span><span class="cx">     return equalIgnoringCase(stringImpl-&gt;characters16() + startOffset, reinterpret_cast&lt;const LChar*&gt;(matchString), matchLength);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+ALWAYS_INLINE static bool equalInner(StringImpl&amp; stringImpl, unsigned startOffset, StringImpl&amp; matchString, bool caseSensitive)
+{
+    if (startOffset &gt; stringImpl.length())
+        return false;
+    if (matchString.length() &gt; stringImpl.length())
+        return false;
+    if (matchString.length() + startOffset &gt; stringImpl.length())
+        return false;
+
+    if (caseSensitive) {
+        if (stringImpl.is8Bit())
+            return equal(stringImpl.characters8() + startOffset, matchString.characters8(), matchString.length());
+        return equal(stringImpl.characters16() + startOffset, matchString.characters16(), matchString.length());
+    }
+    if (stringImpl.is8Bit())
+        return equalIgnoringCase(stringImpl.characters8() + startOffset, matchString.characters8(), matchString.length());
+    return equalIgnoringCase(stringImpl.characters16() + startOffset, matchString.characters16(), matchString.length());
+}
+
</ins><span class="cx"> bool StringImpl::startsWith(const StringImpl* str) const
</span><span class="cx"> {
</span><span class="cx">     if (!str)
</span><span class="lines">@@ -1399,6 +1418,11 @@
</span><span class="cx">     return equalInner(this, 0, matchString, matchLength, caseSensitive);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool StringImpl::startsWith(StringImpl&amp; matchString, unsigned startOffset, bool caseSensitive) const
+{
+    return equalInner(const_cast&lt;StringImpl&amp;&gt;(*this), startOffset, matchString, caseSensitive);
+}
+
</ins><span class="cx"> bool StringImpl::endsWith(StringImpl* matchString, bool caseSensitive)
</span><span class="cx"> {
</span><span class="cx">     ASSERT(matchString);
</span><span class="lines">@@ -1423,6 +1447,13 @@
</span><span class="cx">     return equalInner(this, startOffset, matchString, matchLength, caseSensitive);
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+bool StringImpl::endsWith(StringImpl&amp; matchString, unsigned endOffset, bool caseSensitive) const
+{
+    if (endOffset &lt; matchString.length())
+        return false;
+    return equalInner(const_cast&lt;StringImpl&amp;&gt;(*this), endOffset - matchString.length(), matchString, caseSensitive);
+}
+
</ins><span class="cx"> PassRef&lt;StringImpl&gt; StringImpl::replace(UChar oldC, UChar newC)
</span><span class="cx"> {
</span><span class="cx">     if (oldC == newC)
</span></span></pre></div>
<a id="trunkSourceWTFwtftextStringImplh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/StringImpl.h (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/StringImpl.h        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/Source/WTF/wtf/text/StringImpl.h        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -673,12 +673,14 @@
</span><span class="cx">     WTF_EXPORT_STRING_API bool startsWith(const char*, unsigned matchLength, bool caseSensitive) const;
</span><span class="cx">     template&lt;unsigned matchLength&gt;
</span><span class="cx">     bool startsWith(const char (&amp;prefix)[matchLength], bool caseSensitive = true) const { return startsWith(prefix, matchLength - 1, caseSensitive); }
</span><ins>+    WTF_EXPORT_STRING_API bool startsWith(StringImpl&amp;, unsigned startOffset, bool caseSensitive) const;
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_STRING_API bool endsWith(StringImpl*, bool caseSensitive = true);
</span><span class="cx">     WTF_EXPORT_STRING_API bool endsWith(UChar) const;
</span><span class="cx">     WTF_EXPORT_STRING_API bool endsWith(const char*, unsigned matchLength, bool caseSensitive) const;
</span><span class="cx">     template&lt;unsigned matchLength&gt;
</span><span class="cx">     bool endsWith(const char (&amp;prefix)[matchLength], bool caseSensitive = true) const { return endsWith(prefix, matchLength - 1, caseSensitive); }
</span><ins>+    WTF_EXPORT_STRING_API bool endsWith(StringImpl&amp;, unsigned endOffset, bool caseSensitive) const;
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_STRING_API PassRef&lt;StringImpl&gt; replace(UChar, UChar);
</span><span class="cx">     WTF_EXPORT_STRING_API PassRef&lt;StringImpl&gt; replace(UChar, StringImpl*);
</span></span></pre></div>
<a id="trunkSourceWTFwtftextWTFStringh"></a>
<div class="modfile"><h4>Modified: trunk/Source/WTF/wtf/text/WTFString.h (173760 => 173761)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WTF/wtf/text/WTFString.h        2014-09-19 17:38:13 UTC (rev 173760)
+++ trunk/Source/WTF/wtf/text/WTFString.h        2014-09-19 17:47:50 UTC (rev 173761)
</span><span class="lines">@@ -256,8 +256,10 @@
</span><span class="cx">     WTF_EXPORT_STRING_API UChar32 characterStartingAt(unsigned) const; // Ditto.
</span><span class="cx">     
</span><span class="cx">     bool contains(UChar c) const { return find(c) != notFound; }
</span><del>-    bool contains(const LChar* str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
-    bool contains(const String&amp; str, bool caseSensitive = true) const { return find(str, 0, caseSensitive) != notFound; }
</del><ins>+    bool contains(const LChar* str, bool caseSensitive = true, unsigned startOffset = 0) const 
+        { return find(str, startOffset, caseSensitive) != notFound; }
+    bool contains(const String&amp; str, bool caseSensitive = true, unsigned startOffset = 0) const 
+        { return find(str, startOffset, caseSensitive) != notFound; }
</ins><span class="cx"> 
</span><span class="cx">     bool startsWith(const String&amp; s) const
</span><span class="cx">         { return m_impl ? m_impl-&gt;startsWith(s.impl()) : s.isEmpty(); }
</span><span class="lines">@@ -268,6 +270,8 @@
</span><span class="cx">     template&lt;unsigned matchLength&gt;
</span><span class="cx">     bool startsWith(const char (&amp;prefix)[matchLength], bool caseSensitive = true) const
</span><span class="cx">         { return m_impl ? m_impl-&gt;startsWith&lt;matchLength&gt;(prefix, caseSensitive) : !matchLength; }
</span><ins>+    bool startsWith(String&amp; prefix, unsigned startOffset, bool caseSensitive) const
+        { return m_impl &amp;&amp; prefix.impl() ? m_impl-&gt;startsWith(*prefix.impl(), startOffset, caseSensitive) : false; }
</ins><span class="cx"> 
</span><span class="cx">     bool endsWith(const String&amp; s, bool caseSensitive = true) const
</span><span class="cx">         { return m_impl ? m_impl-&gt;endsWith(s.impl(), caseSensitive) : s.isEmpty(); }
</span><span class="lines">@@ -277,6 +281,8 @@
</span><span class="cx">     template&lt;unsigned matchLength&gt;
</span><span class="cx">     bool endsWith(const char (&amp;prefix)[matchLength], bool caseSensitive = true) const
</span><span class="cx">         { return m_impl ? m_impl-&gt;endsWith&lt;matchLength&gt;(prefix, caseSensitive) : !matchLength; }
</span><ins>+    bool endsWith(String&amp; suffix, unsigned endOffset, bool caseSensitive) const
+        { return m_impl &amp;&amp; suffix.impl() ? m_impl-&gt;endsWith(*suffix.impl(), endOffset, caseSensitive) : false; }
</ins><span class="cx"> 
</span><span class="cx">     WTF_EXPORT_STRING_API void append(const String&amp;);
</span><span class="cx">     WTF_EXPORT_STRING_API void append(LChar);
</span></span></pre>
</div>
</div>

</body>
</html>