Diff
Modified: trunk/LayoutTests/ChangeLog (183140 => 183141)
--- trunk/LayoutTests/ChangeLog 2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/LayoutTests/ChangeLog 2015-04-22 22:25:27 UTC (rev 183141)
@@ -1,3 +1,23 @@
+2015-04-22 Benjamin Poulain <[email protected]>
+
+ 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.
+
2015-04-22 Brent Fulgham <[email protected]>
Context menu doesn't account for selection semantics
Modified: trunk/LayoutTests/js/Object-getOwnPropertyNames-expected.txt (183140 => 183141)
--- 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)
@@ -48,7 +48,7 @@
PASS getSortedOwnPropertyNames(Array) is ['from', 'isArray', 'length', 'name', 'of', 'prototype']
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']
PASS getSortedOwnPropertyNames(String) is ['fromCharCode', 'length', 'name', 'prototype']
-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']
+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']
PASS getSortedOwnPropertyNames(Boolean) is ['length', 'name', 'prototype']
PASS getSortedOwnPropertyNames(Boolean.prototype) is ['constructor', 'toString', 'valueOf']
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']
Modified: trunk/LayoutTests/js/script-tests/Object-getOwnPropertyNames.js (183140 => 183141)
--- 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)
@@ -57,7 +57,7 @@
"Array": "['from', 'isArray', 'length', 'name', 'of', 'prototype']",
"Array.prototype": "['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']",
"String": "['fromCharCode', 'length', 'name', 'prototype']",
- "String.prototype": "['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']",
+ "String.prototype": "['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']",
"Boolean": "['length', 'name', 'prototype']",
"Boolean.prototype": "['constructor', 'toString', 'valueOf']",
"Number": "['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']",
Added: trunk/LayoutTests/js/script-tests/string-code-point-at.js (0 => 183141)
--- 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)
@@ -0,0 +1,143 @@
+description("Test the basic behaviors of String.codePointAt");
+
+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, "codePointAt").configurable', 'true');
+shouldBe('Object.getOwnPropertyDescriptor(String.prototype, "codePointAt").enumerable', 'false');
+shouldBe('Object.getOwnPropertyDescriptor(String.prototype, "codePointAt").writable', 'true');
+
+// The function should only be on the prototype chain, not on the object themselves.
+shouldBeFalse('"foo".hasOwnProperty("codePointAt")');
+shouldBeFalse('(new String("bar")).hasOwnProperty("codePointAt")');
+
+// Some simple cases.
+shouldBe('"".codePointAt(0)', 'undefined');
+shouldBe('"".codePointAt(1)', 'undefined');
+
+shouldBe('"Été".codePointAt(0)', '201');
+shouldBe('"Été".codePointAt(1)', '116');
+shouldBe('"Été".codePointAt(2)', '233');
+shouldBe('"Été".codePointAt(3)', 'undefined');
+
+shouldBe('"ウェブキット".codePointAt(0)', '12454');
+shouldBe('"ウェブキット".codePointAt(1)', '12455');
+shouldBe('"ウェブキット".codePointAt(2)', '12502');
+shouldBe('"ウェブキット".codePointAt(3)', '12461');
+shouldBe('"ウェブキット".codePointAt(4)', '12483');
+shouldBe('"ウェブキット".codePointAt(5)', '12488');
+shouldBe('"ウェブキット".codePointAt(6)', 'undefined');
+
+// Object coercion.
+shouldThrow('"".codePointAt.call(null, 0)');
+shouldThrow('"".codePointAt.call(undefined, 0)');
+shouldBe('"".codePointAt.call(0, 0)', '48');
+shouldBe('"".codePointAt.call(Math.PI, 0)', '51');
+shouldBe('"".codePointAt.call(Math.PI, 1)', '46');
+shouldBe('"".codePointAt.call(Math.PI, 3)', '52');
+shouldBe('"".codePointAt.call(true, 3)', '101');
+shouldBe('"".codePointAt.call(false, 3)', '115');
+shouldBe('"".codePointAt.call(new Object, 3)', '106');
+shouldThrow('"".codePointAt.call(Symbol("WebKit"), 3)');
+
+// toString.
+var objectWithCustomToString = { toString: function() { return "ø"; } };
+shouldBe('"".codePointAt.call(objectWithCustomToString, 0)', '248');
+
+var objectThrowingOnToString = { toString: function() { throw "Hehe"; } };
+shouldThrow('"".codePointAt.call(objectThrowingOnToString, 0)');
+
+var objectCountingToString = { counter: 0, toString: function() { ++this.counter; return this.counter; } };
+shouldBe('"".codePointAt.call(objectCountingToString, 0)', '49');
+shouldBe('objectCountingToString.counter', '1');
+
+// ToNumber.
+var objectWithCustomValueOf = { toString: function() { return "5"; }, valueOf: function() { return 1; } };
+shouldBe('"abcde".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('"".codePointAt.call(null, objectRecordsValueOf)');
+shouldThrow('"".codePointAt.call(undefined, objectRecordsValueOf)');
+shouldThrow('"".codePointAt.call(Symbol("WebKit"), objectRecordsValueOf)');
+shouldThrow('"".codePointAt.call(objectThrowingOnToString, objectRecordsValueOf)');
+shouldBeFalse('objectRecordsValueOf.valueOfEvaluated');
+
+// Evaluation order.
+var evaluationOrderRecorder = {
+ methodsCalled: [],
+ toString: function() { this.methodsCalled.push("toString"); return "foobar"; },
+ valueOf: function() { this.methodsCalled.push("valueOf"); return 5; }
+}
+shouldBe('"".codePointAt.call(evaluationOrderRecorder, evaluationOrderRecorder)', '114');
+shouldBeEqualToString('evaluationOrderRecorder.methodsCalled.toString()', 'toString,valueOf');
+
+// Weird positions.
+shouldBe('"abc".codePointAt(NaN)', '97');
+shouldBe('"abc".codePointAt(-0)', '97');
+shouldBe('"abc".codePointAt(-0.0)', '97');
+shouldBe('"abc".codePointAt(-0.05)', '97');
+shouldBe('"abc".codePointAt(-0.999)', '97');
+shouldBe('"abc".codePointAt(0.4)', '97');
+shouldBe('"abc".codePointAt(0.9)', '97');
+shouldBe('"abc".codePointAt(2.9999)', '99');
+
+// Out of bound positions.
+shouldBe('"abc".codePointAt(-1)', 'undefined');
+shouldBe('"abc".codePointAt(4)', 'undefined');
+shouldBe('var str = "abc"; str.codePointAt(str.length)', 'undefined');
+shouldBe('"abc".codePointAt(4.1)', 'undefined');
+shouldBe('"abc".codePointAt(Number.POSITIVE_INFINITY)', 'undefined');
+shouldBe('"abc".codePointAt(Number.NEGATIVE_INFINITY)', 'undefined');
+
+// Non-number as positions.
+shouldBe('"abc".codePointAt(null)', '97');
+shouldBe('"abc".codePointAt(undefined)', '97');
+shouldBe('"abc".codePointAt("")', '97');
+shouldBe('"abc".codePointAt("WebKit!")', '97');
+shouldBe('"abc".codePointAt(new Object)', '97');
+shouldThrow('"abc".codePointAt(Symbol("WebKit"))');
+
+// 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 < 0xD800 or first > 0xDBFF or position+1 = size, return first.
+function testLeadSurrogateOutOfBounds()
+{
+ return ("\uD7FF\uDC00".codePointAt(0) === 0xd7ff && "\uD7FF\uDC00".codePointAt(1) === 0xdc00 && "\uD7FF\uDC00".codePointAt(2) === undefined
+ && "\uDC00\uDC00".codePointAt(0) === 0xdc00 && "\uDC00\uDC00".codePointAt(1) === 0xdc00 && "\uDC00\uDC00".codePointAt(2) === undefined)
+}
+shouldBeTrue("testLeadSurrogateOutOfBounds()");
+
+function testLeadSurrogateAsLastCharacter()
+{
+ return "abc\uD800".codePointAt(3) === 0xd800;
+}
+shouldBeTrue("testLeadSurrogateAsLastCharacter()");
+
+// If second < 0xDC00 or second > 0xDFFF, return first.
+function testTrailSurrogateOutOfbounds()
+{
+ return ("\uD800\uDBFF".codePointAt(0) === 0xd800 && "\uD800\uDBFF".codePointAt(1) === 0xdbff && "\uD800\uDBFF".codePointAt(2) === undefined
+ && "\uD800\uE000".codePointAt(0) === 0xd800 && "\uD800\uE000".codePointAt(1) === 0xe000 && "\uD800\uE000".codePointAt(2) === undefined)
+}
+shouldBeTrue("testTrailSurrogateOutOfbounds()");
+
+// Null in a string.
+function testAccessNullInString()
+{
+ return "a\u0000b".codePointAt(0) === 97 && "a\u0000b".codePointAt(1) === 0 && "a\u0000b".codePointAt(2) === 98 && "a\u0000b".codePointAt(3) === undefined;
+}
+shouldBeTrue("testAccessNullInString()");
+
+
+// Normal combinations of surrogates.
+function testNormalCombinationOfSurrogates()
+{
+ return "\uD800\uDC00".codePointAt(0) === 65536 && "\uD800\uDC00".codePointAt(1) === 56320 && "\uD800\uDC00".codePointAt(2) === undefined;
+}
+shouldBeTrue("testNormalCombinationOfSurrogates()");
Added: trunk/LayoutTests/js/string-code-point-at-expected.txt (0 => 183141)
--- 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)
@@ -0,0 +1,78 @@
+Test the basic behaviors of String.codePointAt
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS String.codePointAt is undefined
+PASS typeof String.prototype.codePointAt is "function"
+PASS String.prototype.codePointAt.length is 1
+PASS String.prototype.codePointAt.name is "codePointAt"
+PASS Object.getOwnPropertyDescriptor(String.prototype, "codePointAt").configurable is true
+PASS Object.getOwnPropertyDescriptor(String.prototype, "codePointAt").enumerable is false
+PASS Object.getOwnPropertyDescriptor(String.prototype, "codePointAt").writable is true
+PASS "foo".hasOwnProperty("codePointAt") is false
+PASS (new String("bar")).hasOwnProperty("codePointAt") is false
+PASS "".codePointAt(0) is undefined
+PASS "".codePointAt(1) is undefined
+PASS "Été".codePointAt(0) is 201
+PASS "Été".codePointAt(1) is 116
+PASS "Été".codePointAt(2) is 233
+PASS "Été".codePointAt(3) is undefined
+PASS "ウェブキット".codePointAt(0) is 12454
+PASS "ウェブキット".codePointAt(1) is 12455
+PASS "ウェブキット".codePointAt(2) is 12502
+PASS "ウェブキット".codePointAt(3) is 12461
+PASS "ウェブキット".codePointAt(4) is 12483
+PASS "ウェブキット".codePointAt(5) is 12488
+PASS "ウェブキット".codePointAt(6) is undefined
+PASS "".codePointAt.call(null, 0) threw exception TypeError: Type error.
+PASS "".codePointAt.call(undefined, 0) threw exception TypeError: Type error.
+PASS "".codePointAt.call(0, 0) is 48
+PASS "".codePointAt.call(Math.PI, 0) is 51
+PASS "".codePointAt.call(Math.PI, 1) is 46
+PASS "".codePointAt.call(Math.PI, 3) is 52
+PASS "".codePointAt.call(true, 3) is 101
+PASS "".codePointAt.call(false, 3) is 115
+PASS "".codePointAt.call(new Object, 3) is 106
+PASS "".codePointAt.call(Symbol("WebKit"), 3) threw exception TypeError: Type error.
+PASS "".codePointAt.call(objectWithCustomToString, 0) is 248
+PASS "".codePointAt.call(objectThrowingOnToString, 0) threw exception Hehe.
+PASS "".codePointAt.call(objectCountingToString, 0) is 49
+PASS objectCountingToString.counter is 1
+PASS "abcde".codePointAt(objectWithCustomValueOf) is 98
+PASS "".codePointAt.call(null, objectRecordsValueOf) threw exception TypeError: Type error.
+PASS "".codePointAt.call(undefined, objectRecordsValueOf) threw exception TypeError: Type error.
+PASS "".codePointAt.call(Symbol("WebKit"), objectRecordsValueOf) threw exception TypeError: Type error.
+PASS "".codePointAt.call(objectThrowingOnToString, objectRecordsValueOf) threw exception Hehe.
+PASS objectRecordsValueOf.valueOfEvaluated is false
+PASS "".codePointAt.call(evaluationOrderRecorder, evaluationOrderRecorder) is 114
+PASS evaluationOrderRecorder.methodsCalled.toString() is "toString,valueOf"
+PASS "abc".codePointAt(NaN) is 97
+PASS "abc".codePointAt(-0) is 97
+PASS "abc".codePointAt(-0.0) is 97
+PASS "abc".codePointAt(-0.05) is 97
+PASS "abc".codePointAt(-0.999) is 97
+PASS "abc".codePointAt(0.4) is 97
+PASS "abc".codePointAt(0.9) is 97
+PASS "abc".codePointAt(2.9999) is 99
+PASS "abc".codePointAt(-1) is undefined
+PASS "abc".codePointAt(4) is undefined
+PASS var str = "abc"; str.codePointAt(str.length) is undefined
+PASS "abc".codePointAt(4.1) is undefined
+PASS "abc".codePointAt(Number.POSITIVE_INFINITY) is undefined
+PASS "abc".codePointAt(Number.NEGATIVE_INFINITY) is undefined
+PASS "abc".codePointAt(null) is 97
+PASS "abc".codePointAt(undefined) is 97
+PASS "abc".codePointAt("") is 97
+PASS "abc".codePointAt("WebKit!") is 97
+PASS "abc".codePointAt(new Object) is 97
+PASS "abc".codePointAt(Symbol("WebKit")) 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
+
Added: trunk/LayoutTests/js/string-code-point-at.html (0 => 183141)
--- 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)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<meta charset="utf-8">
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>
Modified: trunk/Source/_javascript_Core/ChangeLog (183140 => 183141)
--- trunk/Source/_javascript_Core/ChangeLog 2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/Source/_javascript_Core/ChangeLog 2015-04-22 22:25:27 UTC (rev 183141)
@@ -1,3 +1,18 @@
+2015-04-22 Benjamin Poulain <[email protected]>
+
+ 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):
+
2015-04-22 Mark Lam <[email protected]>
SparseArrayEntry's write barrier owner should be the SparseArrayValueMap.
Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (183140 => 183141)
--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2015-04-22 22:17:49 UTC (rev 183140)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp 2015-04-22 22:25:27 UTC (rev 183141)
@@ -56,6 +56,7 @@
EncodedJSValue JSC_HOST_CALL stringProtoFuncToString(ExecState*);
EncodedJSValue JSC_HOST_CALL stringProtoFuncCharAt(ExecState*);
EncodedJSValue JSC_HOST_CALL stringProtoFuncCharCodeAt(ExecState*);
+EncodedJSValue JSC_HOST_CALL stringProtoFuncCodePointAt(ExecState*);
EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState*);
EncodedJSValue JSC_HOST_CALL stringProtoFuncIndexOf(ExecState*);
EncodedJSValue JSC_HOST_CALL stringProtoFuncLastIndexOf(ExecState*);
@@ -108,6 +109,7 @@
JSC_NATIVE_INTRINSIC_FUNCTION(vm.propertyNames->valueOf, stringProtoFuncToString, DontEnum, 0, StringPrototypeValueOfIntrinsic);
JSC_NATIVE_INTRINSIC_FUNCTION("charAt", stringProtoFuncCharAt, DontEnum, 1, CharAtIntrinsic);
JSC_NATIVE_INTRINSIC_FUNCTION("charCodeAt", stringProtoFuncCharCodeAt, DontEnum, 1, CharCodeAtIntrinsic);
+ JSC_NATIVE_FUNCTION("codePointAt", stringProtoFuncCodePointAt, DontEnum, 1);
JSC_NATIVE_FUNCTION("concat", stringProtoFuncConcat, DontEnum, 1);
JSC_NATIVE_FUNCTION("indexOf", stringProtoFuncIndexOf, DontEnum, 1);
JSC_NATIVE_FUNCTION("lastIndexOf", stringProtoFuncLastIndexOf, DontEnum, 1);
@@ -811,6 +813,42 @@
return JSValue::encode(jsNaN());
}
+static inline UChar32 codePointAt(const String& string, unsigned position, unsigned length)
+{
+ RELEASE_ASSERT(position < 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->thisValue();
+ if (!checkObjectCoercible(thisValue))
+ return throwVMTypeError(exec);
+
+ String string = thisValue.toWTFString(exec);
+ unsigned length = string.length();
+
+ JSValue argument0 = exec->argument(0);
+ if (argument0.isUInt32()) {
+ unsigned position = argument0.asUInt32();
+ if (position < length)
+ return JSValue::encode(jsNumber(codePointAt(string, position, length)));
+ return JSValue::encode(jsUndefined());
+ }
+
+ if (UNLIKELY(exec->hadException()))
+ return JSValue::encode(jsUndefined());
+
+ double doublePosition = argument0.toInteger(exec);
+ if (doublePosition >= 0 && doublePosition < length)
+ return JSValue::encode(jsNumber(codePointAt(string, static_cast<unsigned>(doublePosition), length)));
+ return JSValue::encode(jsUndefined());
+}
+
EncodedJSValue JSC_HOST_CALL stringProtoFuncConcat(ExecState* exec)
{
JSValue thisValue = exec->thisValue();