Title: [193679] trunk
Revision
193679
Author
commit-qu...@webkit.org
Date
2015-12-07 18:14:29 -0800 (Mon, 07 Dec 2015)

Log Message

[INTL] Implement String.prototype.toLocaleUpperCase in ECMA-402
https://bugs.webkit.org/show_bug.cgi?id=147609

Patch by Andy VanWagoner <thetalecraf...@gmail.com> on 2015-12-07
Reviewed by Benjamin Poulain.

Source/_javascript_Core:

Refactor most of toLocaleLowerCase to static function used by both
toLocaleUpperCase and toLocaleLowerCase.
Add toLocaleUpperCase using icu u_strToUpper.

* runtime/StringPrototype.cpp:
(JSC::StringPrototype::finishCreation):
(JSC::toLocaleCase):
(JSC::stringProtoFuncToLocaleLowerCase):
(JSC::stringProtoFuncToLocaleUpperCase):

LayoutTests:

* js/script-tests/string-toLocaleUpperCase.js: Added.
* js/string-toLocaleUpperCase-expected.txt: Added.
* js/string-toLocaleUpperCase.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (193678 => 193679)


--- trunk/LayoutTests/ChangeLog	2015-12-08 01:53:21 UTC (rev 193678)
+++ trunk/LayoutTests/ChangeLog	2015-12-08 02:14:29 UTC (rev 193679)
@@ -1,3 +1,14 @@
+2015-12-07  Andy VanWagoner  <thetalecraf...@gmail.com>
+
+        [INTL] Implement String.prototype.toLocaleUpperCase in ECMA-402
+        https://bugs.webkit.org/show_bug.cgi?id=147609
+
+        Reviewed by Benjamin Poulain.
+
+        * js/script-tests/string-toLocaleUpperCase.js: Added.
+        * js/string-toLocaleUpperCase-expected.txt: Added.
+        * js/string-toLocaleUpperCase.html: Added.
+
 2015-12-07  Myles C. Maxfield  <mmaxfi...@apple.com>
 
         [Mac] Remove Mavericks-specific TestExpectations lines

Added: trunk/LayoutTests/js/script-tests/string-toLocaleUpperCase.js (0 => 193679)


--- trunk/LayoutTests/js/script-tests/string-toLocaleUpperCase.js	                        (rev 0)
+++ trunk/LayoutTests/js/script-tests/string-toLocaleUpperCase.js	2015-12-08 02:14:29 UTC (rev 193679)
@@ -0,0 +1,99 @@
+description("This test checks String.prototype.toLocaleUpperCase().");
+
+shouldBe("String.prototype.toLocaleUpperCase.length", "0");
+
+// Check empty string optimization.
+shouldBe("''.toLocaleUpperCase()", "''");
+
+// Generic
+shouldBe("String.prototype.toLocaleUpperCase.call({ toString() { return 'a' } })", "'A'");
+shouldThrow("String.prototype.toLocaleUpperCase.call({ toString() { throw Error('1') } })", "'Error: 1'");
+shouldThrow("String.prototype.toLocaleUpperCase.call(null)");
+shouldThrow("String.prototype.toLocaleUpperCase.call(undefined)");
+
+// Ignores non-object, non-string locale list.
+shouldBe("'a'.toLocaleUpperCase(9)", "'A'");
+// Handles array-like objects with holes.
+shouldBe("'i'.toLocaleUpperCase({ length: 4, 1: 'az', 3: 'en' })", "'\\u0130'");
+// Doesn't throw, but ignores private tags.
+shouldBe("'a'.toLocaleUpperCase('x-some-thing')", "'A'");
+// Throws on problems with length, get, or toString.
+shouldThrow("'a'.toLocaleUpperCase(Object.create(null, { length: { get() { throw Error('a') } } }))", "'Error: a'");
+shouldThrow("'a'.toLocaleUpperCase(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } }))", "'Error: b'");
+shouldThrow("'a'.toLocaleUpperCase([ { toString() { throw Error('c') } } ])", "'Error: c'");
+// Throws on bad tags.
+shouldThrow("'a'.toLocaleUpperCase([ 5 ])", "'TypeError: locale value must be a string or object'");
+shouldThrow("'a'.toLocaleUpperCase('')", "'RangeError: invalid language tag: '");
+shouldThrow("'a'.toLocaleUpperCase('a')", "'RangeError: invalid language tag: a'");
+shouldThrow("'a'.toLocaleUpperCase('abcdefghij')", "'RangeError: invalid language tag: abcdefghij'");
+shouldThrow("'a'.toLocaleUpperCase('#$')", "'RangeError: invalid language tag: #$'");
+shouldThrow("'a'.toLocaleUpperCase('en-@-abc')", "'RangeError: invalid language tag: en-@-abc'");
+shouldThrow("'a'.toLocaleUpperCase('en-u')", "'RangeError: invalid language tag: en-u'");
+shouldThrow("'a'.toLocaleUpperCase('en-u-kn-true-u-ko-true')", "'RangeError: invalid language tag: en-u-kn-true-u-ko-true'");
+shouldThrow("'a'.toLocaleUpperCase('en-x')", "'RangeError: invalid language tag: en-x'");
+shouldThrow("'a'.toLocaleUpperCase('en-*')", "'RangeError: invalid language tag: en-*'");
+shouldThrow("'a'.toLocaleUpperCase('en-')", "'RangeError: invalid language tag: en-'");
+shouldThrow("'a'.toLocaleUpperCase('en--US')", "'RangeError: invalid language tag: en--US'");
+
+// Check ascii and accents.
+shouldBe("'AbCdEfGhIjKlMnOpQRStuvWXyZ0123456789'.toLocaleUpperCase()", "'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'");
+shouldBe("'àéîöœøūñ'.toLocaleUpperCase()", "'ÀÉÎÖŒØŪÑ'");
+
+// Check non-special case for i.
+shouldBe("'i'.toLocaleUpperCase('und')", "'I'");
+
+// Check for special casing of Azeri.
+shouldBe("'\\u0130'.toLocaleUpperCase('az')", "'\\u0130'");
+shouldBe("'I'.toLocaleUpperCase('az')", "'I'");
+shouldBe("'i'.toLocaleUpperCase('az')", "'\\u0130'");
+shouldBe("'\\u0131'.toLocaleUpperCase('az')", "'I'");
+
+// Check for special casing of Lithuanian.
+shouldBe("'I\\u0307'.toLocaleUpperCase('lt')", "'I\\u0307'");
+shouldBe("'J\\u0307'.toLocaleUpperCase('lt')", "'J\\u0307'");
+// Code points with Soft_Dotted property (Unicode 5.1, PropList.txt)
+var softDotted = [
+    "\\u0069", "\\u006A",  // LATIN SMALL LETTER I..LATIN SMALL LETTER J
+    "\\u012F",             // LATIN SMALL LETTER I WITH OGONEK
+    "\\u0249",             // LATIN SMALL LETTER J WITH STROKE
+    "\\u0268",             // LATIN SMALL LETTER I WITH STROKE
+    "\\u029D",             // LATIN SMALL LETTER J WITH CROSSED-TAIL
+    "\\u02B2",             // MODIFIER LETTER SMALL J
+    "\\u03F3",             // GREEK LETTER YOT
+    "\\u0456",             // CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+    "\\u0458",             // CYRILLIC SMALL LETTER JE
+    "\\u1D62",             // LATIN SUBSCRIPT SMALL LETTER I
+    "\\u1D96",             // LATIN SMALL LETTER I WITH RETROFLEX HOOK
+    "\\u1DA4",             // MODIFIER LETTER SMALL I WITH STROKE
+    "\\u1DA8",             // MODIFIER LETTER SMALL J WITH CROSSED-TAIL
+    "\\u1E2D",             // LATIN SMALL LETTER I WITH TILDE BELOW
+    "\\u1ECB",             // LATIN SMALL LETTER I WITH DOT BELOW
+    "\\u2071",             // SUPERSCRIPT LATIN SMALL LETTER I
+    "\\u2148", "\\u2149",  // DOUBLE-STRUCK ITALIC SMALL I..DOUBLE-STRUCK ITALIC SMALL J
+    "\\u2C7C",             // LATIN SUBSCRIPT SMALL LETTER J
+    "\\uD835\\uDC22", "\\uD835\\uDC23",   // MATHEMATICAL BOLD SMALL I..MATHEMATICAL BOLD SMALL J
+    "\\uD835\\uDC56", "\\uD835\\uDC57",   // MATHEMATICAL ITALIC SMALL I..MATHEMATICAL ITALIC SMALL J
+    "\\uD835\\uDC8A", "\\uD835\\uDC8B",   // MATHEMATICAL BOLD ITALIC SMALL I..MATHEMATICAL BOLD ITALIC SMALL J
+    "\\uD835\\uDCBE", "\\uD835\\uDCBF",   // MATHEMATICAL SCRIPT SMALL I..MATHEMATICAL SCRIPT SMALL J
+    "\\uD835\\uDCF2", "\\uD835\\uDCF3",   // MATHEMATICAL BOLD SCRIPT SMALL I..MATHEMATICAL BOLD SCRIPT SMALL J
+    "\\uD835\\uDD26", "\\uD835\\uDD27",   // MATHEMATICAL FRAKTUR SMALL I..MATHEMATICAL FRAKTUR SMALL J
+    "\\uD835\\uDD5A", "\\uD835\\uDD5B",   // MATHEMATICAL DOUBLE-STRUCK SMALL I..MATHEMATICAL DOUBLE-STRUCK SMALL J
+    "\\uD835\\uDD8E", "\\uD835\\uDD8F",   // MATHEMATICAL BOLD FRAKTUR SMALL I..MATHEMATICAL BOLD FRAKTUR SMALL J
+    "\\uD835\\uDDC2", "\\uD835\\uDDC3",   // MATHEMATICAL SANS-SERIF SMALL I..MATHEMATICAL SANS-SERIF SMALL J
+    "\\uD835\\uDDF6", "\\uD835\\uDDF7",   // MATHEMATICAL SANS-SERIF BOLD SMALL I..MATHEMATICAL SANS-SERIF BOLD SMALL J
+    "\\uD835\\uDE2A", "\\uD835\\uDE2B",   // MATHEMATICAL SANS-SERIF ITALIC SMALL I..MATHEMATICAL SANS-SERIF ITALIC SMALL J
+    "\\uD835\\uDE5E", "\\uD835\\uDE5F",   // MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL I..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL J
+    "\\uD835\\uDE92", "\\uD835\\uDE93",   // MATHEMATICAL MONOSPACE SMALL I..MATHEMATICAL MONOSPACE SMALL J
+];
+// COMBINING DOT ABOVE (U+0307) removed when preceded by Soft_Dotted.
+for (var i = 0; i < softDotted.length; ++i) {
+    shouldBe("'" + softDotted[i] + "\\u0307'.toLocaleUpperCase('lt')", "'" + softDotted[i] + "'.toLocaleUpperCase('und')");
+    shouldBe("'" + softDotted[i] + "\\u0323\\u0307'.toLocaleUpperCase('lt')", "'" + softDotted[i] + "'.toLocaleUpperCase('und') + '\\u0323'");
+    shouldBe("'" + softDotted[i] + "\\uD800\\uDDFD\\u0307'.toLocaleUpperCase('lt')", "'" + softDotted[i] + "'.toLocaleUpperCase('und') + '\\uD800\\uDDFD'");
+}
+
+// Check for special casing of Turkish.
+shouldBe("'\\u0130'.toLocaleUpperCase('tr')", "'\\u0130'");
+shouldBe("'I'.toLocaleUpperCase('tr')", "'I'");
+shouldBe("'i'.toLocaleUpperCase('tr')", "'\\u0130'");
+shouldBe("'\\u0131'.toLocaleUpperCase('tr')", "'I'");

Added: trunk/LayoutTests/js/string-toLocaleUpperCase-expected.txt (0 => 193679)


--- trunk/LayoutTests/js/string-toLocaleUpperCase-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/js/string-toLocaleUpperCase-expected.txt	2015-12-08 02:14:29 UTC (rev 193679)
@@ -0,0 +1,184 @@
+This test checks String.prototype.toLocaleUpperCase().
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS String.prototype.toLocaleUpperCase.length is 0
+PASS ''.toLocaleUpperCase() is ''
+PASS String.prototype.toLocaleUpperCase.call({ toString() { return 'a' } }) is 'A'
+PASS String.prototype.toLocaleUpperCase.call({ toString() { throw Error('1') } }) threw exception Error: 1.
+PASS String.prototype.toLocaleUpperCase.call(null) threw exception TypeError: Type error.
+PASS String.prototype.toLocaleUpperCase.call(undefined) threw exception TypeError: Type error.
+PASS 'a'.toLocaleUpperCase(9) is 'A'
+PASS 'i'.toLocaleUpperCase({ length: 4, 1: 'az', 3: 'en' }) is '\u0130'
+PASS 'a'.toLocaleUpperCase('x-some-thing') is 'A'
+PASS 'a'.toLocaleUpperCase(Object.create(null, { length: { get() { throw Error('a') } } })) threw exception Error: a.
+PASS 'a'.toLocaleUpperCase(Object.create(null, { length: { value: 1 }, 0: { get() { throw Error('b') } } })) threw exception Error: b.
+PASS 'a'.toLocaleUpperCase([ { toString() { throw Error('c') } } ]) threw exception Error: c.
+PASS 'a'.toLocaleUpperCase([ 5 ]) threw exception TypeError: locale value must be a string or object.
+PASS 'a'.toLocaleUpperCase('') threw exception RangeError: invalid language tag: .
+PASS 'a'.toLocaleUpperCase('a') threw exception RangeError: invalid language tag: a.
+PASS 'a'.toLocaleUpperCase('abcdefghij') threw exception RangeError: invalid language tag: abcdefghij.
+PASS 'a'.toLocaleUpperCase('#$') threw exception RangeError: invalid language tag: #$.
+PASS 'a'.toLocaleUpperCase('en-@-abc') threw exception RangeError: invalid language tag: en-@-abc.
+PASS 'a'.toLocaleUpperCase('en-u') threw exception RangeError: invalid language tag: en-u.
+PASS 'a'.toLocaleUpperCase('en-u-kn-true-u-ko-true') threw exception RangeError: invalid language tag: en-u-kn-true-u-ko-true.
+PASS 'a'.toLocaleUpperCase('en-x') threw exception RangeError: invalid language tag: en-x.
+PASS 'a'.toLocaleUpperCase('en-*') threw exception RangeError: invalid language tag: en-*.
+PASS 'a'.toLocaleUpperCase('en-') threw exception RangeError: invalid language tag: en-.
+PASS 'a'.toLocaleUpperCase('en--US') threw exception RangeError: invalid language tag: en--US.
+PASS 'AbCdEfGhIjKlMnOpQRStuvWXyZ0123456789'.toLocaleUpperCase() is 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
+PASS 'àéîöœøūñ'.toLocaleUpperCase() is 'ÀÉÎÖŒØŪÑ'
+PASS 'i'.toLocaleUpperCase('und') is 'I'
+PASS '\u0130'.toLocaleUpperCase('az') is '\u0130'
+PASS 'I'.toLocaleUpperCase('az') is 'I'
+PASS 'i'.toLocaleUpperCase('az') is '\u0130'
+PASS '\u0131'.toLocaleUpperCase('az') is 'I'
+PASS 'I\u0307'.toLocaleUpperCase('lt') is 'I\u0307'
+PASS 'J\u0307'.toLocaleUpperCase('lt') is 'J\u0307'
+PASS '\u0069\u0307'.toLocaleUpperCase('lt') is '\u0069'.toLocaleUpperCase('und')
+PASS '\u0069\u0323\u0307'.toLocaleUpperCase('lt') is '\u0069'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u0069\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u0069'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u006A\u0307'.toLocaleUpperCase('lt') is '\u006A'.toLocaleUpperCase('und')
+PASS '\u006A\u0323\u0307'.toLocaleUpperCase('lt') is '\u006A'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u006A\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u006A'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u012F\u0307'.toLocaleUpperCase('lt') is '\u012F'.toLocaleUpperCase('und')
+PASS '\u012F\u0323\u0307'.toLocaleUpperCase('lt') is '\u012F'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u012F\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u012F'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u0249\u0307'.toLocaleUpperCase('lt') is '\u0249'.toLocaleUpperCase('und')
+PASS '\u0249\u0323\u0307'.toLocaleUpperCase('lt') is '\u0249'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u0249\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u0249'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u0268\u0307'.toLocaleUpperCase('lt') is '\u0268'.toLocaleUpperCase('und')
+PASS '\u0268\u0323\u0307'.toLocaleUpperCase('lt') is '\u0268'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u0268\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u0268'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u029D\u0307'.toLocaleUpperCase('lt') is '\u029D'.toLocaleUpperCase('und')
+PASS '\u029D\u0323\u0307'.toLocaleUpperCase('lt') is '\u029D'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u029D\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u029D'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u02B2\u0307'.toLocaleUpperCase('lt') is '\u02B2'.toLocaleUpperCase('und')
+PASS '\u02B2\u0323\u0307'.toLocaleUpperCase('lt') is '\u02B2'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u02B2\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u02B2'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u03F3\u0307'.toLocaleUpperCase('lt') is '\u03F3'.toLocaleUpperCase('und')
+PASS '\u03F3\u0323\u0307'.toLocaleUpperCase('lt') is '\u03F3'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u03F3\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u03F3'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u0456\u0307'.toLocaleUpperCase('lt') is '\u0456'.toLocaleUpperCase('und')
+PASS '\u0456\u0323\u0307'.toLocaleUpperCase('lt') is '\u0456'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u0456\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u0456'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u0458\u0307'.toLocaleUpperCase('lt') is '\u0458'.toLocaleUpperCase('und')
+PASS '\u0458\u0323\u0307'.toLocaleUpperCase('lt') is '\u0458'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u0458\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u0458'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u1D62\u0307'.toLocaleUpperCase('lt') is '\u1D62'.toLocaleUpperCase('und')
+PASS '\u1D62\u0323\u0307'.toLocaleUpperCase('lt') is '\u1D62'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u1D62\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u1D62'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u1D96\u0307'.toLocaleUpperCase('lt') is '\u1D96'.toLocaleUpperCase('und')
+PASS '\u1D96\u0323\u0307'.toLocaleUpperCase('lt') is '\u1D96'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u1D96\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u1D96'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u1DA4\u0307'.toLocaleUpperCase('lt') is '\u1DA4'.toLocaleUpperCase('und')
+PASS '\u1DA4\u0323\u0307'.toLocaleUpperCase('lt') is '\u1DA4'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u1DA4\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u1DA4'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u1DA8\u0307'.toLocaleUpperCase('lt') is '\u1DA8'.toLocaleUpperCase('und')
+PASS '\u1DA8\u0323\u0307'.toLocaleUpperCase('lt') is '\u1DA8'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u1DA8\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u1DA8'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u1E2D\u0307'.toLocaleUpperCase('lt') is '\u1E2D'.toLocaleUpperCase('und')
+PASS '\u1E2D\u0323\u0307'.toLocaleUpperCase('lt') is '\u1E2D'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u1E2D\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u1E2D'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u1ECB\u0307'.toLocaleUpperCase('lt') is '\u1ECB'.toLocaleUpperCase('und')
+PASS '\u1ECB\u0323\u0307'.toLocaleUpperCase('lt') is '\u1ECB'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u1ECB\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u1ECB'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u2071\u0307'.toLocaleUpperCase('lt') is '\u2071'.toLocaleUpperCase('und')
+PASS '\u2071\u0323\u0307'.toLocaleUpperCase('lt') is '\u2071'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u2071\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u2071'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u2148\u0307'.toLocaleUpperCase('lt') is '\u2148'.toLocaleUpperCase('und')
+PASS '\u2148\u0323\u0307'.toLocaleUpperCase('lt') is '\u2148'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u2148\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u2148'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u2149\u0307'.toLocaleUpperCase('lt') is '\u2149'.toLocaleUpperCase('und')
+PASS '\u2149\u0323\u0307'.toLocaleUpperCase('lt') is '\u2149'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u2149\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u2149'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u2C7C\u0307'.toLocaleUpperCase('lt') is '\u2C7C'.toLocaleUpperCase('und')
+PASS '\u2C7C\u0323\u0307'.toLocaleUpperCase('lt') is '\u2C7C'.toLocaleUpperCase('und') + '\u0323'
+PASS '\u2C7C\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\u2C7C'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDC22\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC22'.toLocaleUpperCase('und')
+PASS '\uD835\uDC22\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC22'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDC22\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC22'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDC23\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC23'.toLocaleUpperCase('und')
+PASS '\uD835\uDC23\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC23'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDC23\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC23'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDC56\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC56'.toLocaleUpperCase('und')
+PASS '\uD835\uDC56\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC56'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDC56\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC56'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDC57\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC57'.toLocaleUpperCase('und')
+PASS '\uD835\uDC57\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC57'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDC57\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC57'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDC8A\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC8A'.toLocaleUpperCase('und')
+PASS '\uD835\uDC8A\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC8A'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDC8A\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC8A'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDC8B\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC8B'.toLocaleUpperCase('und')
+PASS '\uD835\uDC8B\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC8B'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDC8B\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDC8B'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDCBE\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCBE'.toLocaleUpperCase('und')
+PASS '\uD835\uDCBE\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCBE'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDCBE\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCBE'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDCBF\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCBF'.toLocaleUpperCase('und')
+PASS '\uD835\uDCBF\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCBF'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDCBF\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCBF'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDCF2\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCF2'.toLocaleUpperCase('und')
+PASS '\uD835\uDCF2\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCF2'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDCF2\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCF2'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDCF3\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCF3'.toLocaleUpperCase('und')
+PASS '\uD835\uDCF3\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCF3'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDCF3\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDCF3'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDD26\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD26'.toLocaleUpperCase('und')
+PASS '\uD835\uDD26\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD26'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDD26\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD26'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDD27\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD27'.toLocaleUpperCase('und')
+PASS '\uD835\uDD27\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD27'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDD27\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD27'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDD5A\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD5A'.toLocaleUpperCase('und')
+PASS '\uD835\uDD5A\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD5A'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDD5A\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD5A'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDD5B\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD5B'.toLocaleUpperCase('und')
+PASS '\uD835\uDD5B\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD5B'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDD5B\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD5B'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDD8E\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD8E'.toLocaleUpperCase('und')
+PASS '\uD835\uDD8E\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD8E'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDD8E\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD8E'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDD8F\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD8F'.toLocaleUpperCase('und')
+PASS '\uD835\uDD8F\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD8F'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDD8F\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDD8F'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDDC2\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDC2'.toLocaleUpperCase('und')
+PASS '\uD835\uDDC2\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDC2'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDDC2\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDC2'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDDC3\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDC3'.toLocaleUpperCase('und')
+PASS '\uD835\uDDC3\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDC3'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDDC3\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDC3'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDDF6\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDF6'.toLocaleUpperCase('und')
+PASS '\uD835\uDDF6\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDF6'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDDF6\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDF6'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDDF7\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDF7'.toLocaleUpperCase('und')
+PASS '\uD835\uDDF7\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDF7'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDDF7\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDDF7'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDE2A\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE2A'.toLocaleUpperCase('und')
+PASS '\uD835\uDE2A\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE2A'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDE2A\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE2A'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDE2B\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE2B'.toLocaleUpperCase('und')
+PASS '\uD835\uDE2B\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE2B'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDE2B\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE2B'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDE5E\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE5E'.toLocaleUpperCase('und')
+PASS '\uD835\uDE5E\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE5E'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDE5E\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE5E'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDE5F\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE5F'.toLocaleUpperCase('und')
+PASS '\uD835\uDE5F\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE5F'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDE5F\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE5F'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDE92\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE92'.toLocaleUpperCase('und')
+PASS '\uD835\uDE92\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE92'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDE92\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE92'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\uD835\uDE93\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE93'.toLocaleUpperCase('und')
+PASS '\uD835\uDE93\u0323\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE93'.toLocaleUpperCase('und') + '\u0323'
+PASS '\uD835\uDE93\uD800\uDDFD\u0307'.toLocaleUpperCase('lt') is '\uD835\uDE93'.toLocaleUpperCase('und') + '\uD800\uDDFD'
+PASS '\u0130'.toLocaleUpperCase('tr') is '\u0130'
+PASS 'I'.toLocaleUpperCase('tr') is 'I'
+PASS 'i'.toLocaleUpperCase('tr') is '\u0130'
+PASS '\u0131'.toLocaleUpperCase('tr') is 'I'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/js/string-toLocaleUpperCase.html (0 => 193679)


--- trunk/LayoutTests/js/string-toLocaleUpperCase.html	                        (rev 0)
+++ trunk/LayoutTests/js/string-toLocaleUpperCase.html	2015-12-08 02:14:29 UTC (rev 193679)
@@ -0,0 +1,11 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<meta charset="utf8">
+<script src=""
+</head>
+<body>
+<script src=""
+<script src=""
+</body>
+</html>

Modified: trunk/Source/_javascript_Core/ChangeLog (193678 => 193679)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-08 01:53:21 UTC (rev 193678)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-08 02:14:29 UTC (rev 193679)
@@ -1,3 +1,20 @@
+2015-12-07  Andy VanWagoner  <thetalecraf...@gmail.com>
+
+        [INTL] Implement String.prototype.toLocaleUpperCase in ECMA-402
+        https://bugs.webkit.org/show_bug.cgi?id=147609
+
+        Reviewed by Benjamin Poulain.
+
+        Refactor most of toLocaleLowerCase to static function used by both
+        toLocaleUpperCase and toLocaleLowerCase.
+        Add toLocaleUpperCase using icu u_strToUpper.
+
+        * runtime/StringPrototype.cpp:
+        (JSC::StringPrototype::finishCreation):
+        (JSC::toLocaleCase):
+        (JSC::stringProtoFuncToLocaleLowerCase):
+        (JSC::stringProtoFuncToLocaleUpperCase):
+
 2015-12-07  Michael Saboff  <msab...@apple.com>
 
         CRASH: CodeBlock::setOptimizationThresholdBasedOnCompilationResult + 567

Modified: trunk/Source/_javascript_Core/runtime/StringPrototype.cpp (193678 => 193679)


--- trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2015-12-08 01:53:21 UTC (rev 193678)
+++ trunk/Source/_javascript_Core/runtime/StringPrototype.cpp	2015-12-08 02:14:29 UTC (rev 193679)
@@ -76,6 +76,7 @@
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToUpperCase(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncLocaleCompare(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncToLocaleLowerCase(ExecState*);
+EncodedJSValue JSC_HOST_CALL stringProtoFuncToLocaleUpperCase(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncSmall(ExecState*);
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBlink(ExecState*);
@@ -132,10 +133,11 @@
     JSC_NATIVE_FUNCTION("localeCompare", stringProtoFuncLocaleCompare, DontEnum, 1);
 #if ENABLE(INTL)
     JSC_NATIVE_FUNCTION("toLocaleLowerCase", stringProtoFuncToLocaleLowerCase, DontEnum, 0);
+    JSC_NATIVE_FUNCTION("toLocaleUpperCase", stringProtoFuncToLocaleUpperCase, DontEnum, 0);
 #else
     JSC_NATIVE_FUNCTION("toLocaleLowerCase", stringProtoFuncToLowerCase, DontEnum, 0);
+    JSC_NATIVE_FUNCTION("toLocaleUpperCase", stringProtoFuncToUpperCase, DontEnum, 0);
 #endif
-    JSC_NATIVE_FUNCTION("toLocaleUpperCase", stringProtoFuncToUpperCase, DontEnum, 0);
     JSC_NATIVE_FUNCTION("big", stringProtoFuncBig, DontEnum, 0);
     JSC_NATIVE_FUNCTION("small", stringProtoFuncSmall, DontEnum, 0);
     JSC_NATIVE_FUNCTION("blink", stringProtoFuncBlink, DontEnum, 0);
@@ -1446,11 +1448,8 @@
 }
 
 #if ENABLE(INTL)
-EncodedJSValue JSC_HOST_CALL stringProtoFuncToLocaleLowerCase(ExecState* state)
+static EncodedJSValue toLocaleCase(ExecState* state, int32_t (*convertCase)(UChar*, int32_t, const UChar*, int32_t, const char*, UErrorCode*))
 {
-    // 13.1.2 String.prototype.toLocaleLowerCase ([locales])
-    // http://ecma-international.org/publications/standards/Ecma-402.htm
-
     // 1. Let O be RequireObjectCoercible(this value).
     JSValue thisValue = state->thisValue();
     if (!checkObjectCoercible(thisValue))
@@ -1502,25 +1501,25 @@
     const StringView view(s);
     const int32_t viewLength = view.length();
 
-    // Delegate the following steps to u_strToLower.
+    // Delegate the following steps to icu u_strToLower or u_strToUpper.
     // 13. Let cpList be a List containing in order the code points of S as defined in ES2015, 6.1.4, starting at the first element of S.
-    // 14. For each code point c in cpList, if the Unicode Character Database provides a lower case equivalent of c that is either language insensitive or for the language locale, then replace c in cpList with that/those equivalent code point(s).
+    // 14. For each code point c in cpList, if the Unicode Character Database provides a lower(/upper) case equivalent of c that is either language insensitive or for the language locale, then replace c in cpList with that/those equivalent code point(s).
     // 15. Let cuList be a new List.
     // 16. For each code point c in cpList, in order, append to cuList the elements of the UTF-16 Encoding (defined in ES2015, 6.1.4) of c.
     // 17. Let L be a String whose elements are, in order, the elements of cuList.
 
-    // Most strings lower case will be the same size as original, so try that first.
+    // Most strings lower/upper case will be the same size as original, so try that first.
     UErrorCode error(U_ZERO_ERROR);
     Vector<UChar> buffer(viewLength);
     String lower;
-    const int32_t resultLength = u_strToLower(buffer.data(), viewLength, view.upconvertedCharacters(), viewLength, utf8LocaleBuffer.data(), &error);
+    const int32_t resultLength = convertCase(buffer.data(), viewLength, view.upconvertedCharacters(), viewLength, utf8LocaleBuffer.data(), &error);
     if (U_SUCCESS(error))
         lower = String(buffer.data(), resultLength);
     else if (error == U_BUFFER_OVERFLOW_ERROR) {
-        // Lower case needs more space than original. Try again.
+        // Converted case needs more space than original. Try again.
         UErrorCode error(U_ZERO_ERROR);
         Vector<UChar> buffer(resultLength);
-        u_strToLower(buffer.data(), resultLength, view.upconvertedCharacters(), viewLength, utf8LocaleBuffer.data(), &error);
+        convertCase(buffer.data(), resultLength, view.upconvertedCharacters(), viewLength, utf8LocaleBuffer.data(), &error);
         if (U_FAILURE(error))
             return throwVMTypeError(state, u_errorName(error));
         lower = String(buffer.data(), resultLength);
@@ -1530,6 +1529,21 @@
     // 18. Return L.
     return JSValue::encode(jsString(state, lower));
 }
+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncToLocaleLowerCase(ExecState* state)
+{
+    // 13.1.2 String.prototype.toLocaleLowerCase ([locales])
+    // http://ecma-international.org/publications/standards/Ecma-402.htm
+    return toLocaleCase(state, u_strToLower);
+}
+
+EncodedJSValue JSC_HOST_CALL stringProtoFuncToLocaleUpperCase(ExecState* state)
+{
+    // 13.1.3 String.prototype.toLocaleUpperCase ([locales])
+    // http://ecma-international.org/publications/standards/Ecma-402.htm
+    // This function interprets a string value as a sequence of code points, as described in ES2015, 6.1.4. This function behaves in exactly the same way as String.prototype.toLocaleLowerCase, except that characters are mapped to their uppercase equivalents as specified in the Unicode character database.
+    return toLocaleCase(state, u_strToUpper);
+}
 #endif // ENABLE(INTL)
 
 EncodedJSValue JSC_HOST_CALL stringProtoFuncBig(ExecState* exec)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to