144 lines
6.5 KiB
JavaScript
144 lines
6.5 KiB
JavaScript
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()");
|