<!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>[183141] 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/183141">183141</a></dd>
<dt>Author</dt> <dd>benjamin@webkit.org</dd>
<dt>Date</dt> <dd>2015-04-22 15:25:27 -0700 (Wed, 22 Apr 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>Implement String.codePointAt()
https://bugs.webkit.org/show_bug.cgi?id=143934

Reviewed by Darin Adler.

Source/JavaScriptCore:

This patch adds String.codePointAt() as defined by ES6.
I opted for a C++ implementation for now.

* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
(JSC::codePointAt):
(JSC::stringProtoFuncCodePointAt):

LayoutTests:

* js/Object-getOwnPropertyNames-expected.txt:
* js/script-tests/string-code-point-at.js: Added.
(objectWithCustomToString.toString):
(objectThrowingOnToString.toString):
(objectCountingToString.toString):
(testLeadSurrogateOutOfBounds):
(testLeadSurrogateAsLastCharacter):
(testTrailSurrogateOutOfbounds):
(testAccessNullInString):
(testNormalCombinationOfSurrogates):
* js/string-code-point-at-expected.txt: Added.
* js/string-code-point-at.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>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsjsscripttestsstringcodepointatjs">trunk/LayoutTests/js/script-tests/string-code-point-at.js</a></li>
<li><a href="#trunkLayoutTestsjsstringcodepointatexpectedtxt">trunk/LayoutTests/js/string-code-point-at-expected.txt</a></li>
<li><a href="#trunkLayoutTestsjsstringcodepointathtml">trunk/LayoutTests/js/string-code-point-at.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (183140 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/LayoutTests/ChangeLog        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -1,3 +1,23 @@
</span><ins>+2015-04-22  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Implement String.codePointAt()
+        https://bugs.webkit.org/show_bug.cgi?id=143934
+
+        Reviewed by Darin Adler.
+
+        * js/Object-getOwnPropertyNames-expected.txt:
+        * js/script-tests/string-code-point-at.js: Added.
+        (objectWithCustomToString.toString):
+        (objectThrowingOnToString.toString):
+        (objectCountingToString.toString):
+        (testLeadSurrogateOutOfBounds):
+        (testLeadSurrogateAsLastCharacter):
+        (testTrailSurrogateOutOfbounds):
+        (testAccessNullInString):
+        (testNormalCombinationOfSurrogates):
+        * js/string-code-point-at-expected.txt: Added.
+        * js/string-code-point-at.html: Added.
+
</ins><span class="cx"> 2015-04-22  Brent Fulgham  &lt;bfulgham@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Context menu doesn't account for selection semantics
</span></span></pre></div>
<a id="trunkLayoutTestsjsObjectgetOwnPropertyNamesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (183140 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt        2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -48,7 +48,7 @@
</span><span class="cx"> PASS getSortedOwnPropertyNames(Array) is ['from', 'isArray', 'length', 'name', 'of', 'prototype']
</span><span class="cx"> PASS getSortedOwnPropertyNames(Array.prototype) is ['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']
</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', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', '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', 'codePointAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', '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 ['EPSILON', 'MAX_SAFE_INTEGER', 'MAX_VALUE', 'MIN_SAFE_INTEGER', 'MIN_VALUE', 'NEGATIVE_INFINITY', 'NaN', 'POSITIVE_INFINITY', 'isFinite', 'isInteger', 'isNaN', 'isSafeInteger', 'length', 'name', 'parseFloat', 'parseInt', 'prototype']
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsObjectgetOwnPropertyNamesjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (183140 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js        2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -57,7 +57,7 @@
</span><span class="cx">     &quot;Array&quot;: &quot;['from', 'isArray', 'length', 'name', 'of', 'prototype']&quot;,
</span><span class="cx">     &quot;Array.prototype&quot;: &quot;['concat', 'constructor', 'entries', 'every', 'fill', 'filter', 'find', 'findIndex', 'forEach', 'includes', 'indexOf', 'join', 'keys', 'lastIndexOf', 'length', 'map', 'pop', 'push', 'reduce', 'reduceRight', 'reverse', 'shift', 'slice', 'some', 'sort', 'splice', 'toLocaleString', 'toString', 'unshift', 'values']&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', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', 'replace', 'search', 'slice', 'small', 'split', 'startsWith', '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', 'codePointAt', 'concat', 'constructor', 'endsWith', 'fixed', 'fontcolor', 'fontsize', 'includes', 'indexOf', 'italics', 'lastIndexOf', 'length', 'link', 'localeCompare', 'match', 'repeat', '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;['EPSILON', 'MAX_SAFE_INTEGER', 'MAX_VALUE', 'MIN_SAFE_INTEGER', 'MIN_VALUE', 'NEGATIVE_INFINITY', 'NaN', 'POSITIVE_INFINITY', 'isFinite', 'isInteger', 'isNaN', 'isSafeInteger', 'length', 'name', 'parseFloat', 'parseInt', 'prototype']&quot;,
</span></span></pre></div>
<a id="trunkLayoutTestsjsscripttestsstringcodepointatjs"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/script-tests/string-code-point-at.js (0 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/script-tests/string-code-point-at.js                                (rev 0)
+++ trunk/LayoutTests/js/script-tests/string-code-point-at.js        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -0,0 +1,143 @@
</span><ins>+description(&quot;Test the basic behaviors of String.codePointAt&quot;);
+
+shouldBe('String.codePointAt', 'undefined');
+
+shouldBeEqualToString('typeof String.prototype.codePointAt', 'function');
+
+// Function properties.
+shouldBe('String.prototype.codePointAt.length', '1');
+shouldBeEqualToString('String.prototype.codePointAt.name', 'codePointAt')
+shouldBe('Object.getOwnPropertyDescriptor(String.prototype, &quot;codePointAt&quot;).configurable', 'true');
+shouldBe('Object.getOwnPropertyDescriptor(String.prototype, &quot;codePointAt&quot;).enumerable', 'false');
+shouldBe('Object.getOwnPropertyDescriptor(String.prototype, &quot;codePointAt&quot;).writable', 'true');
+
+// The function should only be on the prototype chain, not on the object themselves.
+shouldBeFalse('&quot;foo&quot;.hasOwnProperty(&quot;codePointAt&quot;)');
+shouldBeFalse('(new String(&quot;bar&quot;)).hasOwnProperty(&quot;codePointAt&quot;)');
+
+// Some simple cases.
+shouldBe('&quot;&quot;.codePointAt(0)', 'undefined');
+shouldBe('&quot;&quot;.codePointAt(1)', 'undefined');
+
+shouldBe('&quot;Été&quot;.codePointAt(0)', '201');
+shouldBe('&quot;Été&quot;.codePointAt(1)', '116');
+shouldBe('&quot;Été&quot;.codePointAt(2)', '233');
+shouldBe('&quot;Été&quot;.codePointAt(3)', 'undefined');
+
+shouldBe('&quot;ウェブキット&quot;.codePointAt(0)', '12454');
+shouldBe('&quot;ウェブキット&quot;.codePointAt(1)', '12455');
+shouldBe('&quot;ウェブキット&quot;.codePointAt(2)', '12502');
+shouldBe('&quot;ウェブキット&quot;.codePointAt(3)', '12461');
+shouldBe('&quot;ウェブキット&quot;.codePointAt(4)', '12483');
+shouldBe('&quot;ウェブキット&quot;.codePointAt(5)', '12488');
+shouldBe('&quot;ウェブキット&quot;.codePointAt(6)', 'undefined');
+
+// Object coercion.
+shouldThrow('&quot;&quot;.codePointAt.call(null, 0)');
+shouldThrow('&quot;&quot;.codePointAt.call(undefined, 0)');
+shouldBe('&quot;&quot;.codePointAt.call(0, 0)', '48');
+shouldBe('&quot;&quot;.codePointAt.call(Math.PI, 0)', '51');
+shouldBe('&quot;&quot;.codePointAt.call(Math.PI, 1)', '46');
+shouldBe('&quot;&quot;.codePointAt.call(Math.PI, 3)', '52');
+shouldBe('&quot;&quot;.codePointAt.call(true, 3)', '101');
+shouldBe('&quot;&quot;.codePointAt.call(false, 3)', '115');
+shouldBe('&quot;&quot;.codePointAt.call(new Object, 3)', '106');
+shouldThrow('&quot;&quot;.codePointAt.call(Symbol(&quot;WebKit&quot;), 3)');
+
+// toString.
+var objectWithCustomToString = { toString: function() { return &quot;ø&quot;; } };
+shouldBe('&quot;&quot;.codePointAt.call(objectWithCustomToString, 0)', '248');
+
+var objectThrowingOnToString = { toString: function() { throw &quot;Hehe&quot;; } };
+shouldThrow('&quot;&quot;.codePointAt.call(objectThrowingOnToString, 0)');
+
+var objectCountingToString = { counter: 0, toString: function() { ++this.counter; return this.counter; } };
+shouldBe('&quot;&quot;.codePointAt.call(objectCountingToString, 0)', '49');
+shouldBe('objectCountingToString.counter', '1');
+
+// ToNumber.
+var objectWithCustomValueOf = { toString: function() { return &quot;5&quot;; }, valueOf: function() { return 1; } };
+shouldBe('&quot;abcde&quot;.codePointAt(objectWithCustomValueOf)', '98');
+
+// The second object is never converted to number if the first object did not convert to string.
+var objectRecordsValueOf = { valueOfEvaluated: false, valueOf: function() { this.valueOfEvaluated = true; return 1; } }
+shouldThrow('&quot;&quot;.codePointAt.call(null, objectRecordsValueOf)');
+shouldThrow('&quot;&quot;.codePointAt.call(undefined, objectRecordsValueOf)');
+shouldThrow('&quot;&quot;.codePointAt.call(Symbol(&quot;WebKit&quot;), objectRecordsValueOf)');
+shouldThrow('&quot;&quot;.codePointAt.call(objectThrowingOnToString, objectRecordsValueOf)');
+shouldBeFalse('objectRecordsValueOf.valueOfEvaluated');
+
+// Evaluation order.
+var evaluationOrderRecorder = {
+    methodsCalled: [],
+    toString: function() { this.methodsCalled.push(&quot;toString&quot;); return &quot;foobar&quot;; },
+    valueOf: function() { this.methodsCalled.push(&quot;valueOf&quot;); return 5; }
+}
+shouldBe('&quot;&quot;.codePointAt.call(evaluationOrderRecorder, evaluationOrderRecorder)', '114');
+shouldBeEqualToString('evaluationOrderRecorder.methodsCalled.toString()', 'toString,valueOf');
+
+// Weird positions.
+shouldBe('&quot;abc&quot;.codePointAt(NaN)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(-0)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(-0.0)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(-0.05)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(-0.999)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(0.4)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(0.9)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(2.9999)', '99');
+
+// Out of bound positions.
+shouldBe('&quot;abc&quot;.codePointAt(-1)', 'undefined');
+shouldBe('&quot;abc&quot;.codePointAt(4)', 'undefined');
+shouldBe('var str = &quot;abc&quot;; str.codePointAt(str.length)', 'undefined');
+shouldBe('&quot;abc&quot;.codePointAt(4.1)', 'undefined');
+shouldBe('&quot;abc&quot;.codePointAt(Number.POSITIVE_INFINITY)', 'undefined');
+shouldBe('&quot;abc&quot;.codePointAt(Number.NEGATIVE_INFINITY)', 'undefined');
+
+// Non-number as positions.
+shouldBe('&quot;abc&quot;.codePointAt(null)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(undefined)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(&quot;&quot;)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(&quot;WebKit!&quot;)', '97');
+shouldBe('&quot;abc&quot;.codePointAt(new Object)', '97');
+shouldThrow('&quot;abc&quot;.codePointAt(Symbol(&quot;WebKit&quot;))');
+
+// The following are using special test functions because of limitations of WebKitTestRunner when handling strings with invalid codepoints.
+// When transfering the text of a test, WebKitTestRunner converts it to a UTF-8 C String. Not all invalid code point can be represented.
+
+// If first &lt; 0xD800 or first &gt; 0xDBFF or position+1 = size, return first.
+function testLeadSurrogateOutOfBounds()
+{
+    return (&quot;\uD7FF\uDC00&quot;.codePointAt(0) === 0xd7ff &amp;&amp; &quot;\uD7FF\uDC00&quot;.codePointAt(1) === 0xdc00 &amp;&amp; &quot;\uD7FF\uDC00&quot;.codePointAt(2) === undefined
+            &amp;&amp; &quot;\uDC00\uDC00&quot;.codePointAt(0) === 0xdc00 &amp;&amp; &quot;\uDC00\uDC00&quot;.codePointAt(1) === 0xdc00 &amp;&amp; &quot;\uDC00\uDC00&quot;.codePointAt(2) === undefined)
+}
+shouldBeTrue(&quot;testLeadSurrogateOutOfBounds()&quot;);
+
+function testLeadSurrogateAsLastCharacter()
+{
+    return &quot;abc\uD800&quot;.codePointAt(3) === 0xd800;
+}
+shouldBeTrue(&quot;testLeadSurrogateAsLastCharacter()&quot;);
+
+// If second &lt; 0xDC00 or second &gt; 0xDFFF, return first.
+function testTrailSurrogateOutOfbounds()
+{
+    return (&quot;\uD800\uDBFF&quot;.codePointAt(0) === 0xd800 &amp;&amp; &quot;\uD800\uDBFF&quot;.codePointAt(1) === 0xdbff &amp;&amp; &quot;\uD800\uDBFF&quot;.codePointAt(2) === undefined
+            &amp;&amp; &quot;\uD800\uE000&quot;.codePointAt(0) === 0xd800 &amp;&amp; &quot;\uD800\uE000&quot;.codePointAt(1) === 0xe000 &amp;&amp; &quot;\uD800\uE000&quot;.codePointAt(2) === undefined)
+}
+shouldBeTrue(&quot;testTrailSurrogateOutOfbounds()&quot;);
+
+// Null in a string.
+function testAccessNullInString()
+{
+    return &quot;a\u0000b&quot;.codePointAt(0) === 97 &amp;&amp; &quot;a\u0000b&quot;.codePointAt(1) === 0 &amp;&amp; &quot;a\u0000b&quot;.codePointAt(2) === 98 &amp;&amp; &quot;a\u0000b&quot;.codePointAt(3) === undefined;
+}
+shouldBeTrue(&quot;testAccessNullInString()&quot;);
+
+
+// Normal combinations of surrogates.
+function testNormalCombinationOfSurrogates()
+{
+    return &quot;\uD800\uDC00&quot;.codePointAt(0) === 65536 &amp;&amp; &quot;\uD800\uDC00&quot;.codePointAt(1) === 56320 &amp;&amp; &quot;\uD800\uDC00&quot;.codePointAt(2) === undefined;
+}
+shouldBeTrue(&quot;testNormalCombinationOfSurrogates()&quot;);
</ins></span></pre></div>
<a id="trunkLayoutTestsjsstringcodepointatexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/string-code-point-at-expected.txt (0 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/string-code-point-at-expected.txt                                (rev 0)
+++ trunk/LayoutTests/js/string-code-point-at-expected.txt        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -0,0 +1,78 @@
</span><ins>+Test the basic behaviors of String.codePointAt
+
+On success, you will see a series of &quot;PASS&quot; messages, followed by &quot;TEST COMPLETE&quot;.
+
+
+PASS String.codePointAt is undefined
+PASS typeof String.prototype.codePointAt is &quot;function&quot;
+PASS String.prototype.codePointAt.length is 1
+PASS String.prototype.codePointAt.name is &quot;codePointAt&quot;
+PASS Object.getOwnPropertyDescriptor(String.prototype, &quot;codePointAt&quot;).configurable is true
+PASS Object.getOwnPropertyDescriptor(String.prototype, &quot;codePointAt&quot;).enumerable is false
+PASS Object.getOwnPropertyDescriptor(String.prototype, &quot;codePointAt&quot;).writable is true
+PASS &quot;foo&quot;.hasOwnProperty(&quot;codePointAt&quot;) is false
+PASS (new String(&quot;bar&quot;)).hasOwnProperty(&quot;codePointAt&quot;) is false
+PASS &quot;&quot;.codePointAt(0) is undefined
+PASS &quot;&quot;.codePointAt(1) is undefined
+PASS &quot;Été&quot;.codePointAt(0) is 201
+PASS &quot;Été&quot;.codePointAt(1) is 116
+PASS &quot;Été&quot;.codePointAt(2) is 233
+PASS &quot;Été&quot;.codePointAt(3) is undefined
+PASS &quot;ウェブキット&quot;.codePointAt(0) is 12454
+PASS &quot;ウェブキット&quot;.codePointAt(1) is 12455
+PASS &quot;ウェブキット&quot;.codePointAt(2) is 12502
+PASS &quot;ウェブキット&quot;.codePointAt(3) is 12461
+PASS &quot;ウェブキット&quot;.codePointAt(4) is 12483
+PASS &quot;ウェブキット&quot;.codePointAt(5) is 12488
+PASS &quot;ウェブキット&quot;.codePointAt(6) is undefined
+PASS &quot;&quot;.codePointAt.call(null, 0) threw exception TypeError: Type error.
+PASS &quot;&quot;.codePointAt.call(undefined, 0) threw exception TypeError: Type error.
+PASS &quot;&quot;.codePointAt.call(0, 0) is 48
+PASS &quot;&quot;.codePointAt.call(Math.PI, 0) is 51
+PASS &quot;&quot;.codePointAt.call(Math.PI, 1) is 46
+PASS &quot;&quot;.codePointAt.call(Math.PI, 3) is 52
+PASS &quot;&quot;.codePointAt.call(true, 3) is 101
+PASS &quot;&quot;.codePointAt.call(false, 3) is 115
+PASS &quot;&quot;.codePointAt.call(new Object, 3) is 106
+PASS &quot;&quot;.codePointAt.call(Symbol(&quot;WebKit&quot;), 3) threw exception TypeError: Type error.
+PASS &quot;&quot;.codePointAt.call(objectWithCustomToString, 0) is 248
+PASS &quot;&quot;.codePointAt.call(objectThrowingOnToString, 0) threw exception Hehe.
+PASS &quot;&quot;.codePointAt.call(objectCountingToString, 0) is 49
+PASS objectCountingToString.counter is 1
+PASS &quot;abcde&quot;.codePointAt(objectWithCustomValueOf) is 98
+PASS &quot;&quot;.codePointAt.call(null, objectRecordsValueOf) threw exception TypeError: Type error.
+PASS &quot;&quot;.codePointAt.call(undefined, objectRecordsValueOf) threw exception TypeError: Type error.
+PASS &quot;&quot;.codePointAt.call(Symbol(&quot;WebKit&quot;), objectRecordsValueOf) threw exception TypeError: Type error.
+PASS &quot;&quot;.codePointAt.call(objectThrowingOnToString, objectRecordsValueOf) threw exception Hehe.
+PASS objectRecordsValueOf.valueOfEvaluated is false
+PASS &quot;&quot;.codePointAt.call(evaluationOrderRecorder, evaluationOrderRecorder) is 114
+PASS evaluationOrderRecorder.methodsCalled.toString() is &quot;toString,valueOf&quot;
+PASS &quot;abc&quot;.codePointAt(NaN) is 97
+PASS &quot;abc&quot;.codePointAt(-0) is 97
+PASS &quot;abc&quot;.codePointAt(-0.0) is 97
+PASS &quot;abc&quot;.codePointAt(-0.05) is 97
+PASS &quot;abc&quot;.codePointAt(-0.999) is 97
+PASS &quot;abc&quot;.codePointAt(0.4) is 97
+PASS &quot;abc&quot;.codePointAt(0.9) is 97
+PASS &quot;abc&quot;.codePointAt(2.9999) is 99
+PASS &quot;abc&quot;.codePointAt(-1) is undefined
+PASS &quot;abc&quot;.codePointAt(4) is undefined
+PASS var str = &quot;abc&quot;; str.codePointAt(str.length) is undefined
+PASS &quot;abc&quot;.codePointAt(4.1) is undefined
+PASS &quot;abc&quot;.codePointAt(Number.POSITIVE_INFINITY) is undefined
+PASS &quot;abc&quot;.codePointAt(Number.NEGATIVE_INFINITY) is undefined
+PASS &quot;abc&quot;.codePointAt(null) is 97
+PASS &quot;abc&quot;.codePointAt(undefined) is 97
+PASS &quot;abc&quot;.codePointAt(&quot;&quot;) is 97
+PASS &quot;abc&quot;.codePointAt(&quot;WebKit!&quot;) is 97
+PASS &quot;abc&quot;.codePointAt(new Object) is 97
+PASS &quot;abc&quot;.codePointAt(Symbol(&quot;WebKit&quot;)) threw exception TypeError: Type error.
+PASS testLeadSurrogateOutOfBounds() is true
+PASS testLeadSurrogateAsLastCharacter() is true
+PASS testTrailSurrogateOutOfbounds() is true
+PASS testAccessNullInString() is true
+PASS testNormalCombinationOfSurrogates() is true
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
</ins></span></pre></div>
<a id="trunkLayoutTestsjsstringcodepointathtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/js/string-code-point-at.html (0 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/js/string-code-point-at.html                                (rev 0)
+++ trunk/LayoutTests/js/string-code-point-at.html        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -0,0 +1,11 @@
</span><ins>+&lt;!DOCTYPE HTML PUBLIC &quot;-//IETF//DTD HTML//EN&quot;&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-code-point-at.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 (183140 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/ChangeLog        2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/Source/JavaScriptCore/ChangeLog        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -1,3 +1,18 @@
</span><ins>+2015-04-22  Benjamin Poulain  &lt;benjamin@webkit.org&gt;
+
+        Implement String.codePointAt()
+        https://bugs.webkit.org/show_bug.cgi?id=143934
+
+        Reviewed by Darin Adler.
+
+        This patch adds String.codePointAt() as defined by ES6.
+        I opted for a C++ implementation for now.
+
+        * runtime/StringPrototype.cpp:
+        (JSC::StringPrototype::finishCreation):
+        (JSC::codePointAt):
+        (JSC::stringProtoFuncCodePointAt):
+
</ins><span class="cx"> 2015-04-22  Mark Lam  &lt;mark.lam@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         SparseArrayEntry's write barrier owner should be the SparseArrayValueMap.
</span></span></pre></div>
<a id="trunkSourceJavaScriptCoreruntimeStringPrototypecpp"></a>
<div class="modfile"><h4>Modified: trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp (183140 => 183141)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/Source/JavaScriptCore/runtime/StringPrototype.cpp        2015-04-22 22:25:27 UTC (rev 183141)
</span><span class="lines">@@ -56,6 +56,7 @@
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState*);
</span><ins>+EncodedJSValue JSC_HOST_CALL stringProtoFuncCodePointAt(ExecState*);
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*);
</span><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*);
</span><span class="lines">@@ -108,6 +109,7 @@
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames-&gt;valueOf, stringProtoFuncToString, DontEnum, 0, StringPrototypeValueOfIntrinsic);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION(&quot;charAt&quot;, stringProtoFuncCharAt, DontEnum, 1, CharAtIntrinsic);
</span><span class="cx">     JSC_NATIVE_INTRINSIC_FUNCTION(&quot;charCodeAt&quot;, stringProtoFuncCharCodeAt, DontEnum, 1, CharCodeAtIntrinsic);
</span><ins>+    JSC_NATIVE_FUNCTION(&quot;codePointAt&quot;, stringProtoFuncCodePointAt, DontEnum, 1);
</ins><span class="cx">     JSC_NATIVE_FUNCTION(&quot;concat&quot;, stringProtoFuncConcat, DontEnum, 1);
</span><span class="cx">     JSC_NATIVE_FUNCTION(&quot;indexOf&quot;, stringProtoFuncIndexOf, DontEnum, 1);
</span><span class="cx">     JSC_NATIVE_FUNCTION(&quot;lastIndexOf&quot;, stringProtoFuncLastIndexOf, DontEnum, 1);
</span><span class="lines">@@ -811,6 +813,42 @@
</span><span class="cx">     return JSValue::encode(jsNaN());
</span><span class="cx"> }
</span><span class="cx"> 
</span><ins>+static inline UChar32 codePointAt(const String&amp; string, unsigned position, unsigned length)
+{
+    RELEASE_ASSERT(position &lt; length);
+    if (string.is8Bit())
+        return string.characters8()[position];
+    UChar32 character;
+    U16_NEXT(string.characters16(), position, length, character);
+    return character;
+}
+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncCodePointAt(ExecState* exec)
+{
+    JSValue thisValue = exec-&gt;thisValue();
+    if (!checkObjectCoercible(thisValue))
+        return throwVMTypeError(exec);
+
+    String string = thisValue.toWTFString(exec);
+    unsigned length = string.length();
+
+    JSValue argument0 = exec-&gt;argument(0);
+    if (argument0.isUInt32()) {
+        unsigned position = argument0.asUInt32();
+        if (position &lt; length)
+            return JSValue::encode(jsNumber(codePointAt(string, position, length)));
+        return JSValue::encode(jsUndefined());
+    }
+
+    if (UNLIKELY(exec-&gt;hadException()))
+        return JSValue::encode(jsUndefined());
+
+    double doublePosition = argument0.toInteger(exec);
+    if (doublePosition &gt;= 0 &amp;&amp; doublePosition &lt; length)
+        return JSValue::encode(jsNumber(codePointAt(string, static_cast&lt;unsigned&gt;(doublePosition), length)));
+    return JSValue::encode(jsUndefined());
+}
+
</ins><span class="cx"> EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
</span><span class="cx"> {
</span><span class="cx">     JSValue thisValue = exec-&gt;thisValue();
</span></span></pre>
</div>
</div>

</body>
</html>