summaryrefslogtreecommitdiffstats
path: root/js/src/tests/test262/intl402
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/tests/test262/intl402')
-rw-r--r--js/src/tests/test262/intl402/browser.js1315
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/6.2.2_a.js40
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/6.2.2_b.js41
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/6.2.2_c.js47
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/6.2.3.js69
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/6.2.4.js19
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/6.2/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/6.3/6.3.1_a.js25
-rw-r--r--js/src/tests/test262/intl402/ch06/6.3/6.3.1_b.js35
-rw-r--r--js/src/tests/test262/intl402/ch06/6.3/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/6.3/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/6.4/6.4_a.js22
-rw-r--r--js/src/tests/test262/intl402/ch06/6.4/6.4_b.js34
-rw-r--r--js/src/tests/test262/intl402/ch06/6.4/6.4_c.js36
-rw-r--r--js/src/tests/test262/intl402/ch06/6.4/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/6.4/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch06/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch08/8.0/8.0.js12
-rw-r--r--js/src/tests/test262/intl402/ch08/8.0/8.0_L15.js15
-rw-r--r--js/src/tests/test262/intl402/ch08/8.0/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch08/8.0/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch08/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch08/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch09/9.1/9.1_a.js18
-rw-r--r--js/src/tests/test262/intl402/ch09/9.1/9.1_b.js32
-rw-r--r--js/src/tests/test262/intl402/ch09/9.1/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch09/9.1/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.1_1.js23
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.1_2.js21
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.1_3.js87
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.1_4.js46
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_ii.js30
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_vi.js18
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.2.js45
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.3_5.js22
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.5_11_g_ii_2.js26
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.5_6.js22
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.6_2.js27
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.6_4.js23
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_b.js47
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_c.js32
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.8_1_c.js36
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/9.2.8_4.js35
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch09/9.2/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch09/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch09/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_1.js43
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_10.js18
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_11.js12
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_13.js13
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_b.js44
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_c.js63
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_20.js13
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_23.js13
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_6.js12
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.1_a.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.2.1_4.js21
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.2_a.js30
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1.3.js19
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/10.1_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.1/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/10.2.1.js22
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/10.2.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/10.2.2_a.js27
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/10.2.2_b.js13
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/10.2.3_b.js52
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.2/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.1.js13
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_a_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_c.js36
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_a.js68
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_b_NN.js22
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_c_NN.js22
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_d_NN.js34
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.3.js47
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3_a.js15
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/10.3_b.js33
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.3/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.4/10.4_a.js15
-rw-r--r--js/src/tests/test262/intl402/ch10/10.4/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/10.4/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch10/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_1.js43
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_15.js13
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_17.js81
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_19.js31
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_20_c.js196
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_21.js15
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_32.js44
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_34.js12
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_6.js18
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_7.js12
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.1_a.js18
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.2.1_4.js21
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.2.js30
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1.3.js19
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/11.1_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.1/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/11.2.1.js22
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/11.2.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/11.2.2_a.js28
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/11.2.2_b.js13
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/11.2.3_b.js46
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.2/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.1.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_ii.js27
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_c.js41
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_1.js19
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_2.js59
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_b.js27
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_e.js47
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRF.js56
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRP.js56
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.3.js31
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3_a.js16
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/11.3_b.js33
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.3/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.4/11.4_a.js15
-rw-r--r--js/src/tests/test262/intl402/ch11/11.4/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/11.4/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch11/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_1.js43
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_18.js15
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_22.js18
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_23.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_25.js12
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_5.js18
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_6.js12
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_TDTO.js107
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.1_a.js18
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.2.1_4.js21
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.2.js30
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1.3.js19
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/12.1_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.1/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/12.2.1.js22
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/12.2.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/12.2.2_a.js28
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/12.2.2_b.js13
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/12.2.3_b.js47
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/12.2.3_c.js52
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.2/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.1.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_a_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_c.js34
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_1.js26
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_7_a_iv.js32
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.2_TLT_2.js16
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.3.js52
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3_a.js16
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/12.3_b.js33
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.3/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.4/12.4_a.js15
-rw-r--r--js/src/tests/test262/intl402/ch12/12.4/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/12.4/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch12/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_1.js24
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_2.js26
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_1.js26
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_2.js22
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_1.js65
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_2.js13
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_7.js33
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/13.1.1_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/13.1/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/13.2.1_1.js37
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_1.js67
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_2.js13
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/13.2.1_5.js41
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/13.2.1_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/13.2/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.0_1.js32
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.0_2.js26
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_1.js74
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_2.js15
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.0_7.js58
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.1_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.2_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/13.3.3_L15.js14
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/13.3/shell.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/browser.js0
-rw-r--r--js/src/tests/test262/intl402/ch13/shell.js0
-rw-r--r--js/src/tests/test262/intl402/shell.js10
211 files changed, 5768 insertions, 0 deletions
diff --git a/js/src/tests/test262/intl402/browser.js b/js/src/tests/test262/intl402/browser.js
new file mode 100644
index 000000000..14dc20639
--- /dev/null
+++ b/js/src/tests/test262/intl402/browser.js
@@ -0,0 +1,1315 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Undo at least the damage done by taintArray so that the jstests
+ * harness won't die. The properties added to Object.prototype by the various
+ * tests have names that are less likely to cause trouble.
+ */
+setRestoreFunction((function () {
+ var Array_indexOf = Array.prototype.indexOf;
+ var Array_join = Array.prototype.join;
+ var Array_push = Array.prototype.push;
+ var Array_slice = Array.prototype.slice;
+ var Array_sort = Array.prototype.sort;
+ return function () {
+ delete Array.prototype["0"];
+ Array.prototype.indexOf = Array_indexOf;
+ Array.prototype.join = Array_join;
+ Array.prototype.push = Array_push;
+ Array.prototype.slice = Array_slice;
+ Array.prototype.sort = Array_sort;
+ };
+}()));
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that obj meets the requirements for built-in objects
+ * defined by the introduction of chapter 15 of the ECMAScript Language Specification.
+ * @param {Object} obj the object to be tested.
+ * @param {boolean} isFunction whether the specification describes obj as a function.
+ * @param {boolean} isConstructor whether the specification describes obj as a constructor.
+ * @param {String[]} properties an array with the names of the built-in properties of obj,
+ * excluding length, prototype, or properties with non-default attributes.
+ * @param {number} length for functions only: the length specified for the function
+ * or derived from the argument list.
+ * @author Norbert Lindenberg
+ */
+
+function testBuiltInObject(obj, isFunction, isConstructor, properties, length) {
+
+ if (obj === undefined) {
+ $ERROR("Object being tested is undefined.");
+ }
+
+ var objString = Object.prototype.toString.call(obj);
+ if (isFunction) {
+ if (objString !== "[object Function]") {
+ $ERROR("The [[Class]] internal property of a built-in function must be " +
+ "\"Function\", but toString() returns " + objString);
+ }
+ } else {
+ if (objString !== "[object Object]") {
+ $ERROR("The [[Class]] internal property of a built-in non-function object must be " +
+ "\"Object\", but toString() returns " + objString);
+ }
+ }
+
+ if (!Object.isExtensible(obj)) {
+ $ERROR("Built-in objects must be extensible.");
+ }
+
+ if (isFunction && Object.getPrototypeOf(obj) !== Function.prototype) {
+ $ERROR("Built-in functions must have Function.prototype as their prototype.");
+ }
+
+ if (isConstructor && Object.getPrototypeOf(obj.prototype) !== Object.prototype) {
+ $ERROR("Built-in prototype objects must have Object.prototype as their prototype.");
+ }
+
+ // verification of the absence of the [[Construct]] internal property has
+ // been moved to the end of the test
+
+ // verification of the absence of the prototype property has
+ // been moved to the end of the test
+
+ if (isFunction) {
+
+ if (typeof obj.length !== "number" || obj.length !== Math.floor(obj.length)) {
+ $ERROR("Built-in functions must have a length property with an integer value.");
+ }
+
+ if (obj.length !== length) {
+ $ERROR("Function's length property doesn't have specified value; expected " +
+ length + ", got " + obj.length + ".");
+ }
+
+ var desc = Object.getOwnPropertyDescriptor(obj, "length");
+ if (desc.writable) {
+ $ERROR("The length property of a built-in function must not be writable.");
+ }
+ if (desc.enumerable) {
+ $ERROR("The length property of a built-in function must not be enumerable.");
+ }
+ if (desc.configurable) {
+ $ERROR("The length property of a built-in function must not be configurable.");
+ }
+ }
+
+ properties.forEach(function(prop) {
+ var desc = Object.getOwnPropertyDescriptor(obj, prop);
+ if (desc === undefined) {
+ $ERROR("Missing property " + prop + ".");
+ }
+ // accessor properties don't have writable attribute
+ if (desc.hasOwnProperty("writable") && !desc.writable) {
+ $ERROR("The " + prop + " property of this built-in function must be writable.");
+ }
+ if (desc.enumerable) {
+ $ERROR("The " + prop + " property of this built-in function must not be enumerable.");
+ }
+ if (!desc.configurable) {
+ $ERROR("The " + prop + " property of this built-in function must be configurable.");
+ }
+ });
+
+ // The remaining sections have been moved to the end of the test because
+ // unbound non-constructor functions written in JavaScript cannot possibly
+ // pass them, and we still want to test JavaScript implementations as much
+ // as possible.
+
+ var exception;
+ if (isFunction && !isConstructor) {
+ // this is not a complete test for the presence of [[Construct]]:
+ // if it's absent, the exception must be thrown, but it may also
+ // be thrown if it's present and just has preconditions related to
+ // arguments or the this value that this statement doesn't meet.
+ try {
+ /*jshint newcap:false*/
+ var instance = new obj();
+ } catch (e) {
+ exception = e;
+ }
+ if (exception === undefined || exception.name !== "TypeError") {
+ $ERROR("Built-in functions that aren't constructors must throw TypeError when " +
+ "used in a \"new\" statement.");
+ }
+ }
+
+ if (isFunction && !isConstructor && obj.hasOwnProperty("prototype")) {
+ $ERROR("Built-in functions that aren't constructors must not have a prototype property.");
+ }
+
+ // passed the complete test!
+ return true;
+}
+
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012-2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * This file contains shared functions for the tests in the conformance test
+ * suite for the ECMAScript Internationalization API.
+ * @author Norbert Lindenberg
+ */
+
+
+/**
+ * @description Calls the provided function for every service constructor in
+ * the Intl object, until f returns a falsy value. It returns the result of the
+ * last call to f, mapped to a boolean.
+ * @param {Function} f the function to call for each service constructor in
+ * the Intl object.
+ * @param {Function} Constructor the constructor object to test with.
+ * @result {Boolean} whether the test succeeded.
+ */
+function testWithIntlConstructors(f) {
+ var constructors = ["Collator", "NumberFormat", "DateTimeFormat"];
+ return constructors.every(function (constructor) {
+ var Constructor = Intl[constructor];
+ var result;
+ try {
+ result = f(Constructor);
+ } catch (e) {
+ e.message += " (Testing with " + constructor + ".)";
+ throw e;
+ }
+ return result;
+ });
+}
+
+
+/**
+ * Returns the name of the given constructor object, which must be one of
+ * Intl.Collator, Intl.NumberFormat, or Intl.DateTimeFormat.
+ * @param {object} Constructor a constructor
+ * @return {string} the name of the constructor
+ */
+function getConstructorName(Constructor) {
+ switch (Constructor) {
+ case Intl.Collator:
+ return "Collator";
+ case Intl.NumberFormat:
+ return "NumberFormat";
+ case Intl.DateTimeFormat:
+ return "DateTimeFormat";
+ default:
+ $ERROR("test internal error: unknown Constructor");
+ }
+}
+
+
+/**
+ * Taints a named data property of the given object by installing
+ * a setter that throws an exception.
+ * @param {object} obj the object whose data property to taint
+ * @param {string} property the property to taint
+ */
+function taintDataProperty(obj, property) {
+ Object.defineProperty(obj, property, {
+ set: function(value) {
+ $ERROR("Client code can adversely affect behavior: setter for " + property + ".");
+ },
+ enumerable: false,
+ configurable: true
+ });
+}
+
+
+/**
+ * Taints a named method of the given object by replacing it with a function
+ * that throws an exception.
+ * @param {object} obj the object whose method to taint
+ * @param {string} property the name of the method to taint
+ */
+function taintMethod(obj, property) {
+ Object.defineProperty(obj, property, {
+ value: function() {
+ $ERROR("Client code can adversely affect behavior: method " + property + ".");
+ },
+ writable: true,
+ enumerable: false,
+ configurable: true
+ });
+}
+
+
+/**
+ * Taints the given properties (and similarly named properties) by installing
+ * setters on Object.prototype that throw exceptions.
+ * @param {Array} properties an array of property names to taint
+ */
+function taintProperties(properties) {
+ properties.forEach(function (property) {
+ var adaptedProperties = [property, "__" + property, "_" + property, property + "_", property + "__"];
+ adaptedProperties.forEach(function (property) {
+ taintDataProperty(Object.prototype, property);
+ });
+ });
+}
+
+
+/**
+ * Taints the Array object by creating a setter for the property "0" and
+ * replacing some key methods with functions that throw exceptions.
+ */
+function taintArray() {
+ taintDataProperty(Array.prototype, "0");
+ taintMethod(Array.prototype, "indexOf");
+ taintMethod(Array.prototype, "join");
+ taintMethod(Array.prototype, "push");
+ taintMethod(Array.prototype, "slice");
+ taintMethod(Array.prototype, "sort");
+}
+
+
+// auxiliary data for getLocaleSupportInfo
+var languages = ["zh", "es", "en", "hi", "ur", "ar", "ja", "pa"];
+var scripts = ["Latn", "Hans", "Deva", "Arab", "Jpan", "Hant"];
+var countries = ["CN", "IN", "US", "PK", "JP", "TW", "HK", "SG"];
+var localeSupportInfo = {};
+
+
+/**
+ * Gets locale support info for the given constructor object, which must be one
+ * of Intl.Collator, Intl.NumberFormat, Intl.DateTimeFormat.
+ * @param {object} Constructor the constructor for which to get locale support info
+ * @return {object} locale support info with the following properties:
+ * supported: array of fully supported language tags
+ * byFallback: array of language tags that are supported through fallbacks
+ * unsupported: array of unsupported language tags
+ */
+function getLocaleSupportInfo(Constructor) {
+ var constructorName = getConstructorName(Constructor);
+ if (localeSupportInfo[constructorName] !== undefined) {
+ return localeSupportInfo[constructorName];
+ }
+
+ var allTags = [];
+ var i, j, k;
+ var language, script, country;
+ for (i = 0; i < languages.length; i++) {
+ language = languages[i];
+ allTags.push(language);
+ for (j = 0; j < scripts.length; j++) {
+ script = scripts[j];
+ allTags.push(language + "-" + script);
+ for (k = 0; k < countries.length; k++) {
+ country = countries[k];
+ allTags.push(language + "-" + script + "-" + country);
+ }
+ }
+ for (k = 0; k < countries.length; k++) {
+ country = countries[k];
+ allTags.push(language + "-" + country);
+ }
+ }
+
+ var supported = [];
+ var byFallback = [];
+ var unsupported = [];
+ for (i = 0; i < allTags.length; i++) {
+ var request = allTags[i];
+ var result = new Constructor([request], {localeMatcher: "lookup"}).resolvedOptions().locale;
+ if (request === result) {
+ supported.push(request);
+ } else if (request.indexOf(result) === 0) {
+ byFallback.push(request);
+ } else {
+ unsupported.push(request);
+ }
+ }
+
+ localeSupportInfo[constructorName] = {
+ supported: supported,
+ byFallback: byFallback,
+ unsupported: unsupported
+ };
+
+ return localeSupportInfo[constructorName];
+}
+
+
+/**
+ * @description Tests whether locale is a String value representing a
+ * structurally valid and canonicalized BCP 47 language tag, as defined in
+ * sections 6.2.2 and 6.2.3 of the ECMAScript Internationalization API
+ * Specification.
+ * @param {String} locale the string to be tested.
+ * @result {Boolean} whether the test succeeded.
+ */
+function isCanonicalizedStructurallyValidLanguageTag(locale) {
+
+ /**
+ * Regular expression defining BCP 47 language tags.
+ *
+ * Spec: RFC 5646 section 2.1.
+ */
+ var alpha = "[a-zA-Z]",
+ digit = "[0-9]",
+ alphanum = "(" + alpha + "|" + digit + ")",
+ regular = "(art-lojban|cel-gaulish|no-bok|no-nyn|zh-guoyu|zh-hakka|zh-min|zh-min-nan|zh-xiang)",
+ irregular = "(en-GB-oed|i-ami|i-bnn|i-default|i-enochian|i-hak|i-klingon|i-lux|i-mingo|i-navajo|i-pwn|i-tao|i-tay|i-tsu|sgn-BE-FR|sgn-BE-NL|sgn-CH-DE)",
+ grandfathered = "(" + irregular + "|" + regular + ")",
+ privateuse = "(x(-[a-z0-9]{1,8})+)",
+ singleton = "(" + digit + "|[A-WY-Za-wy-z])",
+ extension = "(" + singleton + "(-" + alphanum + "{2,8})+)",
+ variant = "(" + alphanum + "{5,8}|(" + digit + alphanum + "{3}))",
+ region = "(" + alpha + "{2}|" + digit + "{3})",
+ script = "(" + alpha + "{4})",
+ extlang = "(" + alpha + "{3}(-" + alpha + "{3}){0,2})",
+ language = "(" + alpha + "{2,3}(-" + extlang + ")?|" + alpha + "{4}|" + alpha + "{5,8})",
+ langtag = language + "(-" + script + ")?(-" + region + ")?(-" + variant + ")*(-" + extension + ")*(-" + privateuse + ")?",
+ languageTag = "^(" + langtag + "|" + privateuse + "|" + grandfathered + ")$",
+ languageTagRE = new RegExp(languageTag, "i");
+ var duplicateSingleton = "-" + singleton + "-(.*-)?\\1(?!" + alphanum + ")",
+ duplicateSingletonRE = new RegExp(duplicateSingleton, "i"),
+ duplicateVariant = "(" + alphanum + "{2,8}-)+" + variant + "-(" + alphanum + "{2,8}-)*\\3(?!" + alphanum + ")",
+ duplicateVariantRE = new RegExp(duplicateVariant, "i");
+
+
+ /**
+ * Verifies that the given string is a well-formed BCP 47 language tag
+ * with no duplicate variant or singleton subtags.
+ *
+ * Spec: ECMAScript Internationalization API Specification, draft, 6.2.2.
+ */
+ function isStructurallyValidLanguageTag(locale) {
+ if (!languageTagRE.test(locale)) {
+ return false;
+ }
+ locale = locale.split(/-x-/)[0];
+ return !duplicateSingletonRE.test(locale) && !duplicateVariantRE.test(locale);
+ }
+
+
+ /**
+ * Mappings from complete tags to preferred values.
+ *
+ * Spec: IANA Language Subtag Registry.
+ */
+ var __tagMappings = {
+ // property names must be in lower case; values in canonical form
+
+ // grandfathered tags from IANA language subtag registry, file date 2011-08-25
+ "art-lojban": "jbo",
+ "cel-gaulish": "cel-gaulish",
+ "en-gb-oed": "en-GB-oed",
+ "i-ami": "ami",
+ "i-bnn": "bnn",
+ "i-default": "i-default",
+ "i-enochian": "i-enochian",
+ "i-hak": "hak",
+ "i-klingon": "tlh",
+ "i-lux": "lb",
+ "i-mingo": "i-mingo",
+ "i-navajo": "nv",
+ "i-pwn": "pwn",
+ "i-tao": "tao",
+ "i-tay": "tay",
+ "i-tsu": "tsu",
+ "no-bok": "nb",
+ "no-nyn": "nn",
+ "sgn-be-fr": "sfb",
+ "sgn-be-nl": "vgt",
+ "sgn-ch-de": "sgg",
+ "zh-guoyu": "cmn",
+ "zh-hakka": "hak",
+ "zh-min": "zh-min",
+ "zh-min-nan": "nan",
+ "zh-xiang": "hsn",
+ // deprecated redundant tags from IANA language subtag registry, file date 2011-08-25
+ "sgn-br": "bzs",
+ "sgn-co": "csn",
+ "sgn-de": "gsg",
+ "sgn-dk": "dsl",
+ "sgn-es": "ssp",
+ "sgn-fr": "fsl",
+ "sgn-gb": "bfi",
+ "sgn-gr": "gss",
+ "sgn-ie": "isg",
+ "sgn-it": "ise",
+ "sgn-jp": "jsl",
+ "sgn-mx": "mfs",
+ "sgn-ni": "ncs",
+ "sgn-nl": "dse",
+ "sgn-no": "nsl",
+ "sgn-pt": "psr",
+ "sgn-se": "swl",
+ "sgn-us": "ase",
+ "sgn-za": "sfs",
+ "zh-cmn": "cmn",
+ "zh-cmn-hans": "cmn-Hans",
+ "zh-cmn-hant": "cmn-Hant",
+ "zh-gan": "gan",
+ "zh-wuu": "wuu",
+ "zh-yue": "yue",
+ // deprecated variant with prefix from IANA language subtag registry, file date 2011-08-25
+ "ja-latn-hepburn-heploc": "ja-Latn-alalc97"
+ };
+
+
+ /**
+ * Mappings from non-extlang subtags to preferred values.
+ *
+ * Spec: IANA Language Subtag Registry.
+ */
+ var __subtagMappings = {
+ // property names and values must be in canonical case
+ // language subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25
+ "in": "id",
+ "iw": "he",
+ "ji": "yi",
+ "jw": "jv",
+ "mo": "ro",
+ "ayx": "nun",
+ "cjr": "mom",
+ "cmk": "xch",
+ "drh": "khk",
+ "drw": "prs",
+ "gav": "dev",
+ "mst": "mry",
+ "myt": "mry",
+ "tie": "ras",
+ "tkk": "twm",
+ "tnf": "prs",
+ // region subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25
+ "BU": "MM",
+ "DD": "DE",
+ "FX": "FR",
+ "TP": "TL",
+ "YD": "YE",
+ "ZR": "CD"
+ };
+
+
+ /**
+ * Mappings from extlang subtags to preferred values.
+ *
+ * Spec: IANA Language Subtag Registry.
+ */
+ var __extlangMappings = {
+ // extlang subtags with Preferred-Value mappings from IANA language subtag registry, file date 2011-08-25
+ // values are arrays with [0] the replacement value, [1] (if present) the prefix to be removed
+ "aao": ["aao", "ar"],
+ "abh": ["abh", "ar"],
+ "abv": ["abv", "ar"],
+ "acm": ["acm", "ar"],
+ "acq": ["acq", "ar"],
+ "acw": ["acw", "ar"],
+ "acx": ["acx", "ar"],
+ "acy": ["acy", "ar"],
+ "adf": ["adf", "ar"],
+ "ads": ["ads", "sgn"],
+ "aeb": ["aeb", "ar"],
+ "aec": ["aec", "ar"],
+ "aed": ["aed", "sgn"],
+ "aen": ["aen", "sgn"],
+ "afb": ["afb", "ar"],
+ "afg": ["afg", "sgn"],
+ "ajp": ["ajp", "ar"],
+ "apc": ["apc", "ar"],
+ "apd": ["apd", "ar"],
+ "arb": ["arb", "ar"],
+ "arq": ["arq", "ar"],
+ "ars": ["ars", "ar"],
+ "ary": ["ary", "ar"],
+ "arz": ["arz", "ar"],
+ "ase": ["ase", "sgn"],
+ "asf": ["asf", "sgn"],
+ "asp": ["asp", "sgn"],
+ "asq": ["asq", "sgn"],
+ "asw": ["asw", "sgn"],
+ "auz": ["auz", "ar"],
+ "avl": ["avl", "ar"],
+ "ayh": ["ayh", "ar"],
+ "ayl": ["ayl", "ar"],
+ "ayn": ["ayn", "ar"],
+ "ayp": ["ayp", "ar"],
+ "bbz": ["bbz", "ar"],
+ "bfi": ["bfi", "sgn"],
+ "bfk": ["bfk", "sgn"],
+ "bjn": ["bjn", "ms"],
+ "bog": ["bog", "sgn"],
+ "bqn": ["bqn", "sgn"],
+ "bqy": ["bqy", "sgn"],
+ "btj": ["btj", "ms"],
+ "bve": ["bve", "ms"],
+ "bvl": ["bvl", "sgn"],
+ "bvu": ["bvu", "ms"],
+ "bzs": ["bzs", "sgn"],
+ "cdo": ["cdo", "zh"],
+ "cds": ["cds", "sgn"],
+ "cjy": ["cjy", "zh"],
+ "cmn": ["cmn", "zh"],
+ "coa": ["coa", "ms"],
+ "cpx": ["cpx", "zh"],
+ "csc": ["csc", "sgn"],
+ "csd": ["csd", "sgn"],
+ "cse": ["cse", "sgn"],
+ "csf": ["csf", "sgn"],
+ "csg": ["csg", "sgn"],
+ "csl": ["csl", "sgn"],
+ "csn": ["csn", "sgn"],
+ "csq": ["csq", "sgn"],
+ "csr": ["csr", "sgn"],
+ "czh": ["czh", "zh"],
+ "czo": ["czo", "zh"],
+ "doq": ["doq", "sgn"],
+ "dse": ["dse", "sgn"],
+ "dsl": ["dsl", "sgn"],
+ "dup": ["dup", "ms"],
+ "ecs": ["ecs", "sgn"],
+ "esl": ["esl", "sgn"],
+ "esn": ["esn", "sgn"],
+ "eso": ["eso", "sgn"],
+ "eth": ["eth", "sgn"],
+ "fcs": ["fcs", "sgn"],
+ "fse": ["fse", "sgn"],
+ "fsl": ["fsl", "sgn"],
+ "fss": ["fss", "sgn"],
+ "gan": ["gan", "zh"],
+ "gom": ["gom", "kok"],
+ "gse": ["gse", "sgn"],
+ "gsg": ["gsg", "sgn"],
+ "gsm": ["gsm", "sgn"],
+ "gss": ["gss", "sgn"],
+ "gus": ["gus", "sgn"],
+ "hab": ["hab", "sgn"],
+ "haf": ["haf", "sgn"],
+ "hak": ["hak", "zh"],
+ "hds": ["hds", "sgn"],
+ "hji": ["hji", "ms"],
+ "hks": ["hks", "sgn"],
+ "hos": ["hos", "sgn"],
+ "hps": ["hps", "sgn"],
+ "hsh": ["hsh", "sgn"],
+ "hsl": ["hsl", "sgn"],
+ "hsn": ["hsn", "zh"],
+ "icl": ["icl", "sgn"],
+ "ils": ["ils", "sgn"],
+ "inl": ["inl", "sgn"],
+ "ins": ["ins", "sgn"],
+ "ise": ["ise", "sgn"],
+ "isg": ["isg", "sgn"],
+ "isr": ["isr", "sgn"],
+ "jak": ["jak", "ms"],
+ "jax": ["jax", "ms"],
+ "jcs": ["jcs", "sgn"],
+ "jhs": ["jhs", "sgn"],
+ "jls": ["jls", "sgn"],
+ "jos": ["jos", "sgn"],
+ "jsl": ["jsl", "sgn"],
+ "jus": ["jus", "sgn"],
+ "kgi": ["kgi", "sgn"],
+ "knn": ["knn", "kok"],
+ "kvb": ["kvb", "ms"],
+ "kvk": ["kvk", "sgn"],
+ "kvr": ["kvr", "ms"],
+ "kxd": ["kxd", "ms"],
+ "lbs": ["lbs", "sgn"],
+ "lce": ["lce", "ms"],
+ "lcf": ["lcf", "ms"],
+ "liw": ["liw", "ms"],
+ "lls": ["lls", "sgn"],
+ "lsg": ["lsg", "sgn"],
+ "lsl": ["lsl", "sgn"],
+ "lso": ["lso", "sgn"],
+ "lsp": ["lsp", "sgn"],
+ "lst": ["lst", "sgn"],
+ "lsy": ["lsy", "sgn"],
+ "ltg": ["ltg", "lv"],
+ "lvs": ["lvs", "lv"],
+ "lzh": ["lzh", "zh"],
+ "max": ["max", "ms"],
+ "mdl": ["mdl", "sgn"],
+ "meo": ["meo", "ms"],
+ "mfa": ["mfa", "ms"],
+ "mfb": ["mfb", "ms"],
+ "mfs": ["mfs", "sgn"],
+ "min": ["min", "ms"],
+ "mnp": ["mnp", "zh"],
+ "mqg": ["mqg", "ms"],
+ "mre": ["mre", "sgn"],
+ "msd": ["msd", "sgn"],
+ "msi": ["msi", "ms"],
+ "msr": ["msr", "sgn"],
+ "mui": ["mui", "ms"],
+ "mzc": ["mzc", "sgn"],
+ "mzg": ["mzg", "sgn"],
+ "mzy": ["mzy", "sgn"],
+ "nan": ["nan", "zh"],
+ "nbs": ["nbs", "sgn"],
+ "ncs": ["ncs", "sgn"],
+ "nsi": ["nsi", "sgn"],
+ "nsl": ["nsl", "sgn"],
+ "nsp": ["nsp", "sgn"],
+ "nsr": ["nsr", "sgn"],
+ "nzs": ["nzs", "sgn"],
+ "okl": ["okl", "sgn"],
+ "orn": ["orn", "ms"],
+ "ors": ["ors", "ms"],
+ "pel": ["pel", "ms"],
+ "pga": ["pga", "ar"],
+ "pks": ["pks", "sgn"],
+ "prl": ["prl", "sgn"],
+ "prz": ["prz", "sgn"],
+ "psc": ["psc", "sgn"],
+ "psd": ["psd", "sgn"],
+ "pse": ["pse", "ms"],
+ "psg": ["psg", "sgn"],
+ "psl": ["psl", "sgn"],
+ "pso": ["pso", "sgn"],
+ "psp": ["psp", "sgn"],
+ "psr": ["psr", "sgn"],
+ "pys": ["pys", "sgn"],
+ "rms": ["rms", "sgn"],
+ "rsi": ["rsi", "sgn"],
+ "rsl": ["rsl", "sgn"],
+ "sdl": ["sdl", "sgn"],
+ "sfb": ["sfb", "sgn"],
+ "sfs": ["sfs", "sgn"],
+ "sgg": ["sgg", "sgn"],
+ "sgx": ["sgx", "sgn"],
+ "shu": ["shu", "ar"],
+ "slf": ["slf", "sgn"],
+ "sls": ["sls", "sgn"],
+ "sqs": ["sqs", "sgn"],
+ "ssh": ["ssh", "ar"],
+ "ssp": ["ssp", "sgn"],
+ "ssr": ["ssr", "sgn"],
+ "svk": ["svk", "sgn"],
+ "swc": ["swc", "sw"],
+ "swh": ["swh", "sw"],
+ "swl": ["swl", "sgn"],
+ "syy": ["syy", "sgn"],
+ "tmw": ["tmw", "ms"],
+ "tse": ["tse", "sgn"],
+ "tsm": ["tsm", "sgn"],
+ "tsq": ["tsq", "sgn"],
+ "tss": ["tss", "sgn"],
+ "tsy": ["tsy", "sgn"],
+ "tza": ["tza", "sgn"],
+ "ugn": ["ugn", "sgn"],
+ "ugy": ["ugy", "sgn"],
+ "ukl": ["ukl", "sgn"],
+ "uks": ["uks", "sgn"],
+ "urk": ["urk", "ms"],
+ "uzn": ["uzn", "uz"],
+ "uzs": ["uzs", "uz"],
+ "vgt": ["vgt", "sgn"],
+ "vkk": ["vkk", "ms"],
+ "vkt": ["vkt", "ms"],
+ "vsi": ["vsi", "sgn"],
+ "vsl": ["vsl", "sgn"],
+ "vsv": ["vsv", "sgn"],
+ "wuu": ["wuu", "zh"],
+ "xki": ["xki", "sgn"],
+ "xml": ["xml", "sgn"],
+ "xmm": ["xmm", "ms"],
+ "xms": ["xms", "sgn"],
+ "yds": ["yds", "sgn"],
+ "ysl": ["ysl", "sgn"],
+ "yue": ["yue", "zh"],
+ "zib": ["zib", "sgn"],
+ "zlm": ["zlm", "ms"],
+ "zmi": ["zmi", "ms"],
+ "zsl": ["zsl", "sgn"],
+ "zsm": ["zsm", "ms"]
+ };
+
+
+ /**
+ * Canonicalizes the given well-formed BCP 47 language tag, including regularized case of subtags.
+ *
+ * Spec: ECMAScript Internationalization API Specification, draft, 6.2.3.
+ * Spec: RFC 5646, section 4.5.
+ */
+ function canonicalizeLanguageTag(locale) {
+
+ // start with lower case for easier processing, and because most subtags will need to be lower case anyway
+ locale = locale.toLowerCase();
+
+ // handle mappings for complete tags
+ if (__tagMappings.hasOwnProperty(locale)) {
+ return __tagMappings[locale];
+ }
+
+ var subtags = locale.split("-");
+ var i = 0;
+
+ // handle standard part: all subtags before first singleton or "x"
+ while (i < subtags.length) {
+ var subtag = subtags[i];
+ if (subtag.length === 1 && (i > 0 || subtag === "x")) {
+ break;
+ } else if (i !== 0 && subtag.length === 2) {
+ subtag = subtag.toUpperCase();
+ } else if (subtag.length === 4) {
+ subtag = subtag[0].toUpperCase() + subtag.substring(1).toLowerCase();
+ }
+ if (__subtagMappings.hasOwnProperty(subtag)) {
+ subtag = __subtagMappings[subtag];
+ } else if (__extlangMappings.hasOwnProperty(subtag)) {
+ subtag = __extlangMappings[subtag][0];
+ if (i === 1 && __extlangMappings[subtag][1] === subtags[0]) {
+ subtags.shift();
+ i--;
+ }
+ }
+ subtags[i] = subtag;
+ i++;
+ }
+ var normal = subtags.slice(0, i).join("-");
+
+ // handle extensions
+ var extensions = [];
+ while (i < subtags.length && subtags[i] !== "x") {
+ var extensionStart = i;
+ i++;
+ while (i < subtags.length && subtags[i].length > 1) {
+ i++;
+ }
+ var extension = subtags.slice(extensionStart, i).join("-");
+ extensions.push(extension);
+ }
+ extensions.sort();
+
+ // handle private use
+ var privateUse;
+ if (i < subtags.length) {
+ privateUse = subtags.slice(i).join("-");
+ }
+
+ // put everything back together
+ var canonical = normal;
+ if (extensions.length > 0) {
+ canonical += "-" + extensions.join("-");
+ }
+ if (privateUse !== undefined) {
+ if (canonical.length > 0) {
+ canonical += "-" + privateUse;
+ } else {
+ canonical = privateUse;
+ }
+ }
+
+ return canonical;
+ }
+
+ return typeof locale === "string" && isStructurallyValidLanguageTag(locale) &&
+ canonicalizeLanguageTag(locale) === locale;
+}
+
+
+/**
+ * Tests whether the named options property is correctly handled by the given constructor.
+ * @param {object} Constructor the constructor to test.
+ * @param {string} property the name of the options property to test.
+ * @param {string} type the type that values of the property are expected to have
+ * @param {Array} [values] an array of allowed values for the property. Not needed for boolean.
+ * @param {any} fallback the fallback value that the property assumes if not provided.
+ * @param {object} testOptions additional options:
+ * @param {boolean} isOptional whether support for this property is optional for implementations.
+ * @param {boolean} noReturn whether the resulting value of the property is not returned.
+ * @param {boolean} isILD whether the resulting value of the property is implementation and locale dependent.
+ * @param {object} extra additional option to pass along, properties are value -> {option: value}.
+ * @return {boolean} whether the test succeeded.
+ */
+function testOption(Constructor, property, type, values, fallback, testOptions) {
+ var isOptional = testOptions !== undefined && testOptions.isOptional === true;
+ var noReturn = testOptions !== undefined && testOptions.noReturn === true;
+ var isILD = testOptions !== undefined && testOptions.isILD === true;
+
+ function addExtraOptions(options, value, testOptions) {
+ if (testOptions !== undefined && testOptions.extra !== undefined) {
+ var extra;
+ if (value !== undefined && testOptions.extra[value] !== undefined) {
+ extra = testOptions.extra[value];
+ } else if (testOptions.extra.any !== undefined) {
+ extra = testOptions.extra.any;
+ }
+ if (extra !== undefined) {
+ Object.getOwnPropertyNames(extra).forEach(function (prop) {
+ options[prop] = extra[prop];
+ });
+ }
+ }
+ }
+
+ var testValues, options, obj, expected, actual, error;
+
+ // test that the specified values are accepted. Also add values that convert to specified values.
+ if (type === "boolean") {
+ if (values === undefined) {
+ values = [true, false];
+ }
+ testValues = values.slice(0);
+ testValues.push(888);
+ testValues.push(0);
+ } else if (type === "string") {
+ testValues = values.slice(0);
+ testValues.push({toString: function () { return values[0]; }});
+ }
+ testValues.forEach(function (value) {
+ options = {};
+ options[property] = value;
+ addExtraOptions(options, value, testOptions);
+ obj = new Constructor(undefined, options);
+ if (noReturn) {
+ if (obj.resolvedOptions().hasOwnProperty(property)) {
+ $ERROR("Option property " + property + " is returned, but shouldn't be.");
+ }
+ } else {
+ actual = obj.resolvedOptions()[property];
+ if (isILD) {
+ if (actual !== undefined && values.indexOf(actual) === -1) {
+ $ERROR("Invalid value " + actual + " returned for property " + property + ".");
+ }
+ } else {
+ if (type === "boolean") {
+ expected = Boolean(value);
+ } else if (type === "string") {
+ expected = String(value);
+ }
+ if (actual !== expected && !(isOptional && actual === undefined)) {
+ $ERROR("Option value " + value + " for property " + property +
+ " was not accepted; got " + actual + " instead.");
+ }
+ }
+ }
+ });
+
+ // test that invalid values are rejected
+ if (type === "string") {
+ var invalidValues = ["invalidValue", -1, null];
+ // assume that we won't have values in caseless scripts
+ if (values[0].toUpperCase() !== values[0]) {
+ invalidValues.push(values[0].toUpperCase());
+ } else {
+ invalidValues.push(values[0].toLowerCase());
+ }
+ invalidValues.forEach(function (value) {
+ options = {};
+ options[property] = value;
+ addExtraOptions(options, value, testOptions);
+ error = undefined;
+ try {
+ obj = new Constructor(undefined, options);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid option value " + value + " for property " + property + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid option value " + value + " for property " + property + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+ }
+
+ // test that fallback value or another valid value is used if no options value is provided
+ if (!noReturn) {
+ options = {};
+ addExtraOptions(options, undefined, testOptions);
+ obj = new Constructor(undefined, options);
+ actual = obj.resolvedOptions()[property];
+ if (!(isOptional && actual === undefined)) {
+ if (fallback !== undefined) {
+ if (actual !== fallback) {
+ $ERROR("Option fallback value " + fallback + " for property " + property +
+ " was not used; got " + actual + " instead.");
+ }
+ } else {
+ if (values.indexOf(actual) === -1 && !(isILD && actual === undefined)) {
+ $ERROR("Invalid value " + actual + " returned for property " + property + ".");
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+/**
+ * Tests whether the named property of the given object has a valid value
+ * and the default attributes of the properties of an object literal.
+ * @param {Object} obj the object to be tested.
+ * @param {string} property the name of the property
+ * @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
+ * an array of valid values.
+ * @exception if the property has an invalid value.
+ */
+function testProperty(obj, property, valid) {
+ var desc = Object.getOwnPropertyDescriptor(obj, property);
+ if (!desc.writable) {
+ $ERROR("Property " + property + " must be writable.");
+ }
+ if (!desc.enumerable) {
+ $ERROR("Property " + property + " must be enumerable.");
+ }
+ if (!desc.configurable) {
+ $ERROR("Property " + property + " must be configurable.");
+ }
+ var value = desc.value;
+ var isValid = (typeof valid === "function") ? valid(value) : (valid.indexOf(value) !== -1);
+ if (!isValid) {
+ $ERROR("Property value " + value + " is not allowed for property " + property + ".");
+ }
+}
+
+
+/**
+ * Tests whether the named property of the given object, if present at all, has a valid value
+ * and the default attributes of the properties of an object literal.
+ * @param {Object} obj the object to be tested.
+ * @param {string} property the name of the property
+ * @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
+ * an array of valid values.
+ * @exception if the property is present and has an invalid value.
+ */
+function mayHaveProperty(obj, property, valid) {
+ if (obj.hasOwnProperty(property)) {
+ testProperty(obj, property, valid);
+ }
+}
+
+
+/**
+ * Tests whether the given object has the named property with a valid value
+ * and the default attributes of the properties of an object literal.
+ * @param {Object} obj the object to be tested.
+ * @param {string} property the name of the property
+ * @param {Function|Array} valid either a function that tests value for validity and returns a boolean,
+ * an array of valid values.
+ * @exception if the property is missing or has an invalid value.
+ */
+function mustHaveProperty(obj, property, valid) {
+ if (!obj.hasOwnProperty(property)) {
+ $ERROR("Object is missing property " + property + ".");
+ }
+ testProperty(obj, property, valid);
+}
+
+
+/**
+ * Tests whether the given object does not have the named property.
+ * @param {Object} obj the object to be tested.
+ * @param {string} property the name of the property
+ * @exception if the property is present.
+ */
+function mustNotHaveProperty(obj, property) {
+ if (obj.hasOwnProperty(property)) {
+ $ERROR("Object has property it mustn't have: " + property + ".");
+ }
+}
+
+
+/**
+ * Properties of the RegExp constructor that may be affected by use of regular
+ * expressions, and the default values of these properties. Properties are from
+ * https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Deprecated_and_obsolete_features#RegExp_Properties
+ */
+var regExpProperties = ["$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9",
+ "$_", "$*", "$&", "$+", "$`", "$'",
+ "input", "lastMatch", "lastParen", "leftContext", "rightContext"
+];
+
+var regExpPropertiesDefaultValues = (function () {
+ var values = Object.create(null);
+ regExpProperties.forEach(function (property) {
+ values[property] = RegExp[property];
+ });
+ return values;
+}());
+
+
+/**
+ * Tests that executing the provided function (which may use regular expressions
+ * in its implementation) does not create or modify unwanted properties on the
+ * RegExp constructor.
+ */
+function testForUnwantedRegExpChanges(testFunc) {
+ regExpProperties.forEach(function (property) {
+ RegExp[property] = regExpPropertiesDefaultValues[property];
+ });
+ testFunc();
+ regExpProperties.forEach(function (property) {
+ if (RegExp[property] !== regExpPropertiesDefaultValues[property]) {
+ $ERROR("RegExp has unexpected property " + property + " with value " +
+ RegExp[property] + ".");
+ }
+ });
+}
+
+
+/**
+ * Tests whether name is a valid BCP 47 numbering system name
+ * and not excluded from use in the ECMAScript Internationalization API.
+ * @param {string} name the name to be tested.
+ * @return {boolean} whether name is a valid BCP 47 numbering system name and
+ * allowed for use in the ECMAScript Internationalization API.
+ */
+
+function isValidNumberingSystem(name) {
+
+ // source: CLDR file common/bcp47/number.xml; version CLDR 21.
+ var numberingSystems = [
+ "arab",
+ "arabext",
+ "armn",
+ "armnlow",
+ "bali",
+ "beng",
+ "brah",
+ "cakm",
+ "cham",
+ "deva",
+ "ethi",
+ "finance",
+ "fullwide",
+ "geor",
+ "grek",
+ "greklow",
+ "gujr",
+ "guru",
+ "hanidec",
+ "hans",
+ "hansfin",
+ "hant",
+ "hantfin",
+ "hebr",
+ "java",
+ "jpan",
+ "jpanfin",
+ "kali",
+ "khmr",
+ "knda",
+ "osma",
+ "lana",
+ "lanatham",
+ "laoo",
+ "latn",
+ "lepc",
+ "limb",
+ "mlym",
+ "mong",
+ "mtei",
+ "mymr",
+ "mymrshan",
+ "native",
+ "nkoo",
+ "olck",
+ "orya",
+ "roman",
+ "romanlow",
+ "saur",
+ "shrd",
+ "sora",
+ "sund",
+ "talu",
+ "takr",
+ "taml",
+ "tamldec",
+ "telu",
+ "thai",
+ "tibt",
+ "traditio",
+ "vaii"
+ ];
+
+ var excluded = [
+ "finance",
+ "native",
+ "traditio"
+ ];
+
+
+ return numberingSystems.indexOf(name) !== -1 && excluded.indexOf(name) === -1;
+}
+
+
+/**
+ * Provides the digits of numbering systems with simple digit mappings,
+ * as specified in 11.3.2.
+ */
+
+var numberingSystemDigits = {
+ arab: "٠١٢٣٤٥٦٧٨٩",
+ arabext: "۰۱۲۳۴۵۶۷۸۹",
+ beng: "০১২৩৪৫৬৭৮৯",
+ deva: "०१२३४५६७८९",
+ fullwide: "0123456789",
+ gujr: "૦૧૨૩૪૫૬૭૮૯",
+ guru: "੦੧੨੩੪੫੬੭੮੯",
+ hanidec: "〇一二三四五六七八九",
+ khmr: "០១២៣៤៥៦៧៨៩",
+ knda: "೦೧೨೩೪೫೬೭೮೯",
+ laoo: "໐໑໒໓໔໕໖໗໘໙",
+ latn: "0123456789",
+ mlym: "൦൧൨൩൪൫൬൭൮൯",
+ mong: "᠐᠑᠒᠓᠔᠕᠖᠗᠘᠙",
+ mymr: "၀၁၂၃၄၅၆၇၈၉",
+ orya: "୦୧୨୩୪୫୬୭୮୯",
+ tamldec: "௦௧௨௩௪௫௬௭௮௯",
+ telu: "౦౧౨౩౪౫౬౭౮౯",
+ thai: "๐๑๒๓๔๕๖๗๘๙",
+ tibt: "༠༡༢༣༤༥༦༧༨༩"
+};
+
+
+/**
+ * Tests that number formatting is handled correctly. The function checks that the
+ * digit sequences in formatted output are as specified, converted to the
+ * selected numbering system, and embedded in consistent localized patterns.
+ * @param {Array} locales the locales to be tested.
+ * @param {Array} numberingSystems the numbering systems to be tested.
+ * @param {Object} options the options to pass to Intl.NumberFormat. Options
+ * must include {useGrouping: false}, and must cause 1.1 to be formatted
+ * pre- and post-decimal digits.
+ * @param {Object} testData maps input data (in ES5 9.3.1 format) to expected output strings
+ * in unlocalized format with Western digits.
+ */
+
+function testNumberFormat(locales, numberingSystems, options, testData) {
+ locales.forEach(function (locale) {
+ numberingSystems.forEach(function (numbering) {
+ var digits = numberingSystemDigits[numbering];
+ var format = new Intl.NumberFormat([locale + "-u-nu-" + numbering], options);
+
+ function getPatternParts(positive) {
+ var n = positive ? 1.1 : -1.1;
+ var formatted = format.format(n);
+ var oneoneRE = "([^" + digits + "]*)[" + digits + "]+([^" + digits + "]+)[" + digits + "]+([^" + digits + "]*)";
+ var match = formatted.match(new RegExp(oneoneRE));
+ if (match === null) {
+ $ERROR("Unexpected formatted " + n + " for " +
+ format.resolvedOptions().locale + " and options " +
+ JSON.stringify(options) + ": " + formatted);
+ }
+ return match;
+ }
+
+ function toNumbering(raw) {
+ return raw.replace(/[0-9]/g, function (digit) {
+ return digits[digit.charCodeAt(0) - "0".charCodeAt(0)];
+ });
+ }
+
+ function buildExpected(raw, patternParts) {
+ var period = raw.indexOf(".");
+ if (period === -1) {
+ return patternParts[1] + toNumbering(raw) + patternParts[3];
+ } else {
+ return patternParts[1] +
+ toNumbering(raw.substring(0, period)) +
+ patternParts[2] +
+ toNumbering(raw.substring(period + 1)) +
+ patternParts[3];
+ }
+ }
+
+ if (format.resolvedOptions().numberingSystem === numbering) {
+ // figure out prefixes, infixes, suffixes for positive and negative values
+ var posPatternParts = getPatternParts(true);
+ var negPatternParts = getPatternParts(false);
+
+ Object.getOwnPropertyNames(testData).forEach(function (input) {
+ var rawExpected = testData[input];
+ var patternParts;
+ if (rawExpected[0] === "-") {
+ patternParts = negPatternParts;
+ rawExpected = rawExpected.substring(1);
+ } else {
+ patternParts = posPatternParts;
+ }
+ var expected = buildExpected(rawExpected, patternParts);
+ var actual = format.format(input);
+ if (actual !== expected) {
+ $ERROR("Formatted value for " + input + ", " +
+ format.resolvedOptions().locale + " and options " +
+ JSON.stringify(options) + " is " + actual + "; expected " + expected + ".");
+ }
+ });
+ }
+ });
+ });
+}
+
+
+/**
+ * Return the components of date-time formats.
+ * @return {Array} an array with all date-time components.
+ */
+
+function getDateTimeComponents() {
+ return ["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZoneName"];
+}
+
+
+/**
+ * Return the valid values for the given date-time component, as specified
+ * by the table in section 12.1.1.
+ * @param {string} component a date-time component.
+ * @return {Array} an array with the valid values for the component.
+ */
+
+function getDateTimeComponentValues(component) {
+
+ var components = {
+ weekday: ["narrow", "short", "long"],
+ era: ["narrow", "short", "long"],
+ year: ["2-digit", "numeric"],
+ month: ["2-digit", "numeric", "narrow", "short", "long"],
+ day: ["2-digit", "numeric"],
+ hour: ["2-digit", "numeric"],
+ minute: ["2-digit", "numeric"],
+ second: ["2-digit", "numeric"],
+ timeZoneName: ["short", "long"]
+ };
+
+ var result = components[component];
+ if (result === undefined) {
+ $ERROR("Internal error: No values defined for date-time component " + component + ".");
+ }
+ return result;
+}
+
+
+/**
+ * Tests that the given value is valid for the given date-time component.
+ * @param {string} component a date-time component.
+ * @param {string} value the value to be tested.
+ * @return {boolean} true if the test succeeds.
+ * @exception if the test fails.
+ */
+
+function testValidDateTimeComponentValue(component, value) {
+ if (getDateTimeComponentValues(component).indexOf(value) === -1) {
+ $ERROR("Invalid value " + value + " for date-time component " + component + ".");
+ }
+ return true;
+}
+
+
+/**
+ * Verifies that the actual array matches the expected one in length, elements,
+ * and element order.
+ * @param {Array} expected the expected array.
+ * @param {Array} actual the actual array.
+ * @return {boolean} true if the test succeeds.
+ * @exception if the test fails.
+ */
+function testArraysAreSame(expected, actual) {
+ for (i = 0; i < Math.max(actual.length, expected.length); i++) {
+ if (actual[i] !== expected[i]) {
+ $ERROR("Result array element at index " + i + " should be \"" +
+ expected[i] + "\" but is \"" + actual[i] + "\".");
+ }
+ }
+ return true;
+}
+
diff --git a/js/src/tests/test262/intl402/ch06/6.2/6.2.2_a.js b/js/src/tests/test262/intl402/ch06/6.2/6.2.2_a.js
new file mode 100644
index 000000000..a56894570
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/6.2.2_a.js
@@ -0,0 +1,40 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that structurally valid language tags are accepted.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var validLanguageTags = [
+ "de", // ISO 639 language code
+ "de-DE", // + ISO 3166-1 country code
+ "DE-de", // tags are case-insensitive
+ "cmn", // ISO 639 language code
+ "cmn-Hans", // + script code
+ "CMN-hANS", // tags are case-insensitive
+ "cmn-hans-cn", // + ISO 3166-1 country code
+ "es-419", // + UN M.49 region code
+ "es-419-u-nu-latn-cu-bob", // + Unicode locale extension sequence
+ "i-klingon", // grandfathered tag
+ "cmn-hans-cn-t-ca-u-ca-x-t-u", // singleton subtags can also be used as private use subtags
+ "enochian-enochian", // language and variant subtags may be the same
+ "de-gregory-u-ca-gregory", // variant and extension subtags may be the same
+ "aa-a-foo-x-a-foo-bar", // variant subtags can also be used as private use subtags
+ "x-en-US-12345", // anything goes in private use tags
+ "x-12345-12345-en-US",
+ "x-en-US-12345-12345",
+ "x-en-u-foo",
+ "x-en-u-foo-u-bar"
+];
+
+testWithIntlConstructors(function (Constructor) {
+ validLanguageTags.forEach(function (tag) {
+ // this must not throw an exception for a valid language tag
+ var obj = new Constructor([tag]);
+ });
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.2/6.2.2_b.js b/js/src/tests/test262/intl402/ch06/6.2/6.2.2_b.js
new file mode 100644
index 000000000..42d69e7c2
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/6.2.2_b.js
@@ -0,0 +1,41 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that language tags with "_" are not accepted.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var invalidLanguageTags = [
+ "de_DE",
+ "DE_de",
+ "cmn_Hans",
+ "cmn-hans_cn",
+ "es_419",
+ "es-419-u-nu-latn-cu_bob",
+ "i_klingon",
+ "cmn-hans-cn-t-ca-u-ca-x_t-u",
+ "enochian_enochian",
+ "de-gregory_u-ca-gregory"
+];
+
+testWithIntlConstructors(function (Constructor) {
+ invalidLanguageTags.forEach(function (tag) {
+ var error;
+ try {
+ // this must throw an exception for an invalid language tag
+ var obj = new Constructor([tag]);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid language tag " + tag + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid language tag " + tag + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.2/6.2.2_c.js b/js/src/tests/test262/intl402/ch06/6.2/6.2.2_c.js
new file mode 100644
index 000000000..6d669ebef
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/6.2.2_c.js
@@ -0,0 +1,47 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that language tags with invalid subtag sequences are not accepted.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var invalidLanguageTags = [
+ "", // empty tag
+ "i", // singleton alone
+ "x", // private use without subtag
+ "u", // extension singleton in first place
+ "419", // region code in first place
+ "u-nu-latn-cu-bob", // extension sequence without language
+ "hans-cmn-cn", // "hans" could theoretically be a 4-letter language code,
+ // but those can't be followed by extlang codes.
+ "cmn-hans-cn-u-u", // duplicate singleton
+ "cmn-hans-cn-t-u-ca-u", // duplicate singleton
+ "de-gregory-gregory", // duplicate variant
+ "*", // language range
+ "de-*", // language range
+ "中文", // non-ASCII letters
+ "en-ß", // non-ASCII letters
+ "ıd" // non-ASCII letters
+];
+
+testWithIntlConstructors(function (Constructor) {
+ invalidLanguageTags.forEach(function (tag) {
+ var error;
+ try {
+ // this must throw an exception for an invalid language tag
+ var obj = new Constructor([tag]);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid language tag " + tag + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid language tag " + tag + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.2/6.2.3.js b/js/src/tests/test262/intl402/ch06/6.2/6.2.3.js
new file mode 100644
index 000000000..4ae15ab27
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/6.2.3.js
@@ -0,0 +1,69 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that language tags are canonicalized in return values.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var canonicalizedTags = {
+ "de": ["de"],
+ "de-DE": ["de-DE", "de"],
+ "DE-de": ["de-DE", "de"],
+ "cmn": ["cmn"],
+ "CMN-hANS": ["cmn-Hans", "cmn"],
+ "cmn-hans-cn": ["cmn-Hans-CN", "cmn-Hans", "cmn"],
+ "es-419": ["es-419", "es"],
+ "es-419-u-nu-latn": ["es-419-u-nu-latn", "es-419", "es", "es-u-nu-latn"],
+ // -u-ca is incomplete, so it will not show up in resolvedOptions().locale
+ "cmn-hans-cn-u-ca-t-ca-x-t-u": ["cmn-Hans-CN-t-ca-u-ca-x-t-u", "cmn-Hans-CN-t-ca-x-t-u", "cmn-Hans-CN-t-ca-x-t", "cmn-Hans-CN-t-ca", "cmn-Hans-CN", "cmn-Hans", "cmn"],
+ "enochian-enochian": ["enochian-enochian", "enochian"],
+ "de-gregory-u-ca-gregory": ["de-gregory-u-ca-gregory", "de-gregory", "de-u-ca-gregory", "de"],
+ "no-nyn": ["nn"],
+ "i-klingon": ["tlh"],
+ "sgn-GR": ["gss"],
+ "ji": ["yi"],
+ "de-DD": ["de-DE", "de"],
+ "zh-hak-CN": ["hak-CN", "hak"],
+ "sgn-ils": ["ils"],
+ "in": ["id"],
+ "x-foo": ["x-foo"]
+};
+
+// make sure the data above is correct
+Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) {
+ canonicalizedTags[tag].forEach(function (canonicalTag) {
+ if (!isCanonicalizedStructurallyValidLanguageTag(canonicalTag)) {
+ $ERROR("Test data \"" + canonicalTag + "\" is not canonicalized and structurally valid language tag.");
+ }
+ });
+});
+
+// now the actual test
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ Object.getOwnPropertyNames(canonicalizedTags).forEach(function (tag) {
+ // use lookup locale matcher to keep the set of possible return values predictable
+
+ // Variant 1: construct an object and see whether its locale is canonicalized.
+ // In this variant, shortened forms or the default locale may be returned
+ var object = new Constructor([tag], {localeMatcher: "lookup"});
+ var locale = object.resolvedOptions().locale;
+ if (canonicalizedTags[tag].indexOf(locale) === -1 && locale !== defaultLocale) {
+ $ERROR("For " + tag + " got " + locale + "; expected one of " +
+ canonicalizedTags[tag].join(", ") + ".");
+ }
+
+ // Variant 2: get the supported locales. If the tag is supported, it should be returned canonicalized but unshortened
+ var supported = Constructor.supportedLocalesOf([tag]);
+ if (supported.length > 0 && supported[0] !== canonicalizedTags[tag][0]) {
+ $ERROR("For " + tag + " got " + supported[0] + "; expected " +
+ canonicalizedTags[tag][0] + ".");
+ }
+ });
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.2/6.2.4.js b/js/src/tests/test262/intl402/ch06/6.2/6.2.4.js
new file mode 100644
index 000000000..6ca47af14
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/6.2.4.js
@@ -0,0 +1,19 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the default locale is a String value representing the
+ * structurally valid and canonicalized BCP 47 language tag.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ if (!isCanonicalizedStructurallyValidLanguageTag(defaultLocale)) {
+ $ERROR("Default locale \"" + defaultLocale + "\" is not canonicalized and structurally valid language tag.");
+ }
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.2/browser.js b/js/src/tests/test262/intl402/ch06/6.2/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/browser.js
diff --git a/js/src/tests/test262/intl402/ch06/6.2/shell.js b/js/src/tests/test262/intl402/ch06/6.2/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.2/shell.js
diff --git a/js/src/tests/test262/intl402/ch06/6.3/6.3.1_a.js b/js/src/tests/test262/intl402/ch06/6.3/6.3.1_a.js
new file mode 100644
index 000000000..01cc18b03
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.3/6.3.1_a.js
@@ -0,0 +1,25 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that well-formed currency codes are accepted.
+ * @author Norbert Lindenberg
+ */
+
+var wellFormedCurrencyCodes = [
+ "BOB",
+ "EUR",
+ "usd", // currency codes are case-insensitive
+ "XdR",
+ "xTs"
+];
+
+wellFormedCurrencyCodes.forEach(function (code) {
+ // this must not throw an exception for a valid currency code
+ var format = new Intl.NumberFormat(["de-de"], {style: "currency", currency: code});
+ if (format.resolvedOptions().currency !== code.toUpperCase()) {
+ $ERROR("Currency " + code + " was not correctly accepted; turned into " +
+ format.resolvedOptions().currency + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.3/6.3.1_b.js b/js/src/tests/test262/intl402/ch06/6.3/6.3.1_b.js
new file mode 100644
index 000000000..038dd1fc4
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.3/6.3.1_b.js
@@ -0,0 +1,35 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that invalid currency codes are not accepted.
+ * @author Norbert Lindenberg
+ */
+
+var invalidCurrencyCodes = [
+ "",
+ "€",
+ "$",
+ "SFr.",
+ "DM",
+ "KR₩",
+ "702",
+ "ßP",
+ "ınr"
+];
+
+invalidCurrencyCodes.forEach(function (code) {
+ var error;
+ try {
+ // this must throw an exception for an invalid currency code
+ var format = new Intl.NumberFormat(["de-de"], {style: "currency", currency: code});
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid currency code '" + code + "' was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid currency code '" + code + "' was rejected with wrong error " + error.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.3/browser.js b/js/src/tests/test262/intl402/ch06/6.3/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.3/browser.js
diff --git a/js/src/tests/test262/intl402/ch06/6.3/shell.js b/js/src/tests/test262/intl402/ch06/6.3/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.3/shell.js
diff --git a/js/src/tests/test262/intl402/ch06/6.4/6.4_a.js b/js/src/tests/test262/intl402/ch06/6.4/6.4_a.js
new file mode 100644
index 000000000..05202353c
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.4/6.4_a.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that valid time zone names are accepted.
+ * @author Norbert Lindenberg
+ */
+
+var validTimeZoneNames = [
+ "UTC",
+ "utc" // time zone names are case-insensitive
+];
+
+validTimeZoneNames.forEach(function (name) {
+ // this must not throw an exception for a valid time zone name
+ var format = new Intl.DateTimeFormat(["de-de"], {timeZone: name});
+ if (format.resolvedOptions().timeZone !== name.toUpperCase()) {
+ $ERROR("Time zone name " + name + " was not correctly accepted; turned into " +
+ format.resolvedOptions().timeZone + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.4/6.4_b.js b/js/src/tests/test262/intl402/ch06/6.4/6.4_b.js
new file mode 100644
index 000000000..847d804e3
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.4/6.4_b.js
@@ -0,0 +1,34 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that invalid time zone names are not accepted.
+ * @author Norbert Lindenberg
+ */
+
+var invalidTimeZoneNames = [
+ "",
+ "MEZ", // localized abbreviation
+ "Pacific Time", // localized long form
+ "cnsha", // BCP 47 time zone code
+ "invalid", // as the name says
+ "Europe/İstanbul", // non-ASCII letter
+ "asıa/baku", // non-ASCII letter
+ "europe/brußels" // non-ASCII letter
+];
+
+invalidTimeZoneNames.forEach(function (name) {
+ var error;
+ try {
+ // this must throw an exception for an invalid time zone name
+ var format = new Intl.DateTimeFormat(["de-de"], {timeZone: name});
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid time zone name " + name + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid time zone name " + name + " was rejected with wrong error " + error.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.4/6.4_c.js b/js/src/tests/test262/intl402/ch06/6.4/6.4_c.js
new file mode 100644
index 000000000..a9969b648
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.4/6.4_c.js
@@ -0,0 +1,36 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that additional time zone names, if accepted, are handled correctly.
+ * @author Norbert Lindenberg
+ */
+
+// canonicalization specified in conformance clause
+var additionalTimeZoneNames = {
+ "Etc/GMT": "UTC",
+ "Greenwich": "UTC",
+ "PRC": "Asia/Shanghai",
+ "AmErIcA/LoS_aNgElEs": "America/Los_Angeles",
+ "etc/gmt+7": "Etc/GMT+7"
+};
+
+Object.getOwnPropertyNames(additionalTimeZoneNames).forEach(function (name) {
+ var format, error;
+ try {
+ format = new Intl.DateTimeFormat([], {timeZone: name});
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ var actual = format.resolvedOptions().timeZone;
+ var expected = additionalTimeZoneNames[name];
+ if (actual !== expected) {
+ $ERROR("Time zone name " + name + " was accepted, but incorrectly canonicalized to " +
+ actual + "; expected " + expected + ".");
+ }
+ } else if (error.name !== "RangeError") {
+ $ERROR("Time zone name " + name + " was rejected with wrong error " + error.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch06/6.4/browser.js b/js/src/tests/test262/intl402/ch06/6.4/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.4/browser.js
diff --git a/js/src/tests/test262/intl402/ch06/6.4/shell.js b/js/src/tests/test262/intl402/ch06/6.4/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/6.4/shell.js
diff --git a/js/src/tests/test262/intl402/ch06/browser.js b/js/src/tests/test262/intl402/ch06/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/browser.js
diff --git a/js/src/tests/test262/intl402/ch06/shell.js b/js/src/tests/test262/intl402/ch06/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch06/shell.js
diff --git a/js/src/tests/test262/intl402/ch08/8.0/8.0.js b/js/src/tests/test262/intl402/ch08/8.0/8.0.js
new file mode 100644
index 000000000..dedda973b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch08/8.0/8.0.js
@@ -0,0 +1,12 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl has Object.prototype as its prototype.
+ * @author Norbert Lindenberg
+ */
+
+if (Object.getPrototypeOf(Intl) !== Object.prototype) {
+ $ERROR("Intl doesn't have Object.prototype as its prototype.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch08/8.0/8.0_L15.js b/js/src/tests/test262/intl402/ch08/8.0/8.0_L15.js
new file mode 100644
index 000000000..0174bef54
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch08/8.0/8.0_L15.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(fnGlobalObject().Intl, false, false, []);
+testBuiltInObject(Intl, false, false, ["Collator", "NumberFormat", "DateTimeFormat"]);
+
diff --git a/js/src/tests/test262/intl402/ch08/8.0/browser.js b/js/src/tests/test262/intl402/ch08/8.0/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch08/8.0/browser.js
diff --git a/js/src/tests/test262/intl402/ch08/8.0/shell.js b/js/src/tests/test262/intl402/ch08/8.0/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch08/8.0/shell.js
diff --git a/js/src/tests/test262/intl402/ch08/browser.js b/js/src/tests/test262/intl402/ch08/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch08/browser.js
diff --git a/js/src/tests/test262/intl402/ch08/shell.js b/js/src/tests/test262/intl402/ch08/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch08/shell.js
diff --git a/js/src/tests/test262/intl402/ch09/9.1/9.1_a.js b/js/src/tests/test262/intl402/ch09/9.1/9.1_a.js
new file mode 100644
index 000000000..b7358304b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.1/9.1_a.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that default locale is available.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ var supportedLocales = Constructor.supportedLocalesOf([defaultLocale]);
+ if (supportedLocales.indexOf(defaultLocale) === -1) {
+ $ERROR("Default locale is not reported as available.");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.1/9.1_b.js b/js/src/tests/test262/intl402/ch09/9.1/9.1_b.js
new file mode 100644
index 000000000..a0abc7fc1
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.1/9.1_b.js
@@ -0,0 +1,32 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that appropriate fallback locales are provided for
+ * supported locales.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var info = getLocaleSupportInfo(Constructor);
+ var fallback;
+ info.supported.forEach(function (locale) {
+ var pos = locale.lastIndexOf("-");
+ if (pos !== -1) {
+ fallback = locale.substring(0, pos);
+ if (info.supported.indexOf(fallback) === -1) {
+ $ERROR("Locale " + locale + " is supported, but fallback " + fallback + " isn't.");
+ }
+ }
+ var match = /([a-z]{2,3})(-[A-Z][a-z]{3})(-[A-Z]{2})/.exec(locale);
+ if (match !== null) {
+ fallback = match[1] + match[3];
+ if (info.supported.indexOf(fallback) === -1) {
+ $ERROR("Locale " + locale + " is supported, but fallback " + fallback + " isn't.");
+ }
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.1/browser.js b/js/src/tests/test262/intl402/ch09/9.1/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.1/browser.js
diff --git a/js/src/tests/test262/intl402/ch09/9.1/shell.js b/js/src/tests/test262/intl402/ch09/9.1/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.1/shell.js
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.1_1.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_1.js
new file mode 100644
index 000000000..7386fdeda
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_1.js
@@ -0,0 +1,23 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that canonicalization of locale lists treats undefined and empty lists the same.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var supportedForUndefined = Constructor.supportedLocalesOf(undefined);
+ var supportedForEmptyList = Constructor.supportedLocalesOf([]);
+ if (supportedForUndefined.length !== supportedForEmptyList.length) {
+ $ERROR("Supported locales differ between undefined and empty list input.");
+ }
+ // we don't compare the elements because length should be 0 - let's just verify that
+ if (supportedForUndefined.length !== 0) {
+ $ERROR("Internal test error: Assumption about length being 0 is invalid.");
+ }
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.1_2.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_2.js
new file mode 100644
index 000000000..e4fb3756d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_2.js
@@ -0,0 +1,21 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a List is not affected by adversarial
+ * changes to Array.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintArray();
+
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ var canonicalized = Constructor.supportedLocalesOf([defaultLocale, defaultLocale]);
+ if (canonicalized.length > 1) {
+ $ERROR("Canonicalization didn't remove duplicate language tags from locale list.");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.1_3.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_3.js
new file mode 100644
index 000000000..e403b1765
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_3.js
@@ -0,0 +1,87 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that a single string instead of a locale list is treated
+ * as the locale list containing that string.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var validAndInvalidLanguageTags = [
+ "de", // ISO 639 language code
+ "de-DE", // + ISO 3166-1 country code
+ "DE-de", // tags are case-insensitive
+ "cmn", // ISO 639 language code
+ "cmn-Hans", // + script code
+ "CMN-hANS", // tags are case-insensitive
+ "cmn-hans-cn", // + ISO 3166-1 country code
+ "es-419", // + UN M.49 region code
+ "es-419-u-nu-latn-cu-bob", // + Unicode locale extension sequence
+ "i-klingon", // grandfathered tag
+ "cmn-hans-cn-t-ca-u-ca-x-t-u", // singleton subtags can also be used as private use subtags
+ "enochian-enochian", // language and variant subtags may be the same
+ "de-gregory-u-ca-gregory", // variant and extension subtags may be the same
+ "de_DE",
+ "DE_de",
+ "cmn_Hans",
+ "cmn-hans_cn",
+ "es_419",
+ "es-419-u-nu-latn-cu_bob",
+ "i_klingon",
+ "cmn-hans-cn-t-ca-u-ca-x_t-u",
+ "enochian_enochian",
+ "de-gregory_u-ca-gregory",
+ "i", // singleton alone
+ "x", // private use without subtag
+ "u", // extension singleton in first place
+ "419", // region code in first place
+ "u-nu-latn-cu-bob", // extension sequence without language
+ "hans-cmn-cn", // "hans" could theoretically be a 4-letter language code,
+ // but those can't be followed by extlang codes.
+ "cmn-hans-cn-u-u", // duplicate singleton
+ "cmn-hans-cn-t-u-ca-u", // duplicate singleton
+ "de-gregory-gregory" // duplicate variant
+];
+
+testWithIntlConstructors(function (Constructor) {
+ validAndInvalidLanguageTags.forEach(function (locale) {
+ var obj1, obj2, locale1, locale2, error1, error2;
+ try {
+ obj1 = new Constructor(locale);
+ locale1 = obj1.resolvedOptions().locale;
+ } catch (e) {
+ error1 = e;
+ }
+ try {
+ obj2 = new Constructor([locale]);
+ locale2 = obj2.resolvedOptions().locale;
+ } catch (e) {
+ error2 = e;
+ }
+
+ if ((error1 === undefined) !== (error2 === undefined)) {
+ if (error1 === undefined) {
+ $ERROR("Single locale string " + locale +
+ " was accepted, but locale list containing that string wasn't.");
+ } else {
+ $ERROR("Single locale string " + locale +
+ " was rejected, but locale list containing that string wasn't.");
+ }
+ } else if (error1 === undefined) {
+ if (locale1 !== locale2) {
+ $ERROR("Single locale string " + locale + " results in " + locale1 +
+ ", but locale list [" + locale + "] results in " + locale2 + ".");
+ }
+ } else {
+ if (error1.name !== error2.name) {
+ $ERROR("Single locale string " + locale + " results in error " + error1.name +
+ ", but locale list [" + locale + "] results in error " + error2.name + ".");
+ }
+ }
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.1_4.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_4.js
new file mode 100644
index 000000000..b9bb9db79
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_4.js
@@ -0,0 +1,46 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that non-objects are converted to objects before canonicalization.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ // undefined is handled separately
+
+ // null should result in a TypeError
+ var error;
+ try {
+ var supportedForNull = Constructor.supportedLocalesOf(null);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Null as locale list was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Null as locale list was rejected with wrong error " + error.name + ".");
+ }
+
+ // let's use an empty list for comparison
+ var supportedForEmptyList = Constructor.supportedLocalesOf([]);
+ // we don't compare the elements because length should be 0 - let's just verify that
+ if (supportedForEmptyList.length !== 0) {
+ $ERROR("Internal test error: Assumption about length being 0 is invalid.");
+ }
+
+ // most non-objects will be interpreted as empty lists because a missing length property is interpreted as 0
+ var supportedForNumber = Constructor.supportedLocalesOf(5);
+ if (supportedForNumber.length !== supportedForEmptyList.length) {
+ $ERROR("Supported locales differ between numeric and empty list input.");
+ }
+ var supportedForBoolean = Constructor.supportedLocalesOf(true);
+ if (supportedForBoolean.length !== supportedForEmptyList.length) {
+ $ERROR("Supported locales differ between boolean and empty list input.");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_ii.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_ii.js
new file mode 100644
index 000000000..8dfb9b7b3
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_ii.js
@@ -0,0 +1,30 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that values other than strings are not accepted as locales.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var notStringOrObject = [undefined, null, true, false, 0, 5, -5, NaN];
+
+testWithIntlConstructors(function (Constructor) {
+ notStringOrObject.forEach(function (value) {
+ var error;
+ try {
+ var supported = Constructor.supportedLocalesOf([value]);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("" + value + " as locale was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("" + value + " as locale was rejected with wrong error " + error.name + ".");
+ }
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_vi.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_vi.js
new file mode 100644
index 000000000..ef78fa97b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.1_8_c_vi.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that canonicalization of locale lists removes duplicate language tags.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ var canonicalized = Constructor.supportedLocalesOf([defaultLocale, defaultLocale]);
+ if (canonicalized.length > 1) {
+ $ERROR("Canonicalization didn't remove duplicate language tags from locale list.");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.2.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.2.js
new file mode 100644
index 000000000..cb74eaad2
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.2.js
@@ -0,0 +1,45 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that locales that are reported by resolvedOptions
+ * are also reported by supportedLocalesOf.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var info = getLocaleSupportInfo(Constructor);
+ // this test should work equally for both matching algorithms
+ ["lookup", "best fit"].forEach(function (matcher) {
+ var supportedByConstructor = info.supported.concat(info.byFallback);
+ var supported = Constructor.supportedLocalesOf(supportedByConstructor,
+ {localeMatcher: matcher});
+ // we could check the length first, but it's probably more interesting which locales are missing
+ var i = 0;
+ var limit = Math.min(supportedByConstructor.length, supported.length);
+ while (i < limit && supportedByConstructor[i] === supported[i]) {
+ i++;
+ }
+ if (i < supportedByConstructor.length) {
+ $ERROR("Locale " + supportedByConstructor[i] +
+ " is returned by resolvedOptions but not by supportedLocalesOf.");
+ } else if (i < supported.length) {
+ $ERROR("Locale " + supported[i] +
+ " is returned by supportedLocalesOf but not by resolvedOptions.");
+ }
+ });
+
+ // this test is only valid for lookup - best fit may find additional locales supported
+ var unsupportedByConstructor = info.unsupported;
+ var supported = Constructor.supportedLocalesOf(unsupportedByConstructor,
+ {localeMatcher: "lookup"});
+ if (supported.length > 0) {
+ $ERROR("Locale " + supported[0] +
+ " is returned by supportedLocalesOf but not by resolvedOptions.");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.3_5.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.3_5.js
new file mode 100644
index 000000000..8ae8a216b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.3_5.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["locale", "extension", "extensionIndex"]);
+
+testWithIntlConstructors(function (Constructor) {
+ var locale = new Constructor(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+ if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
+ $ERROR("Constructor returns invalid locale " + locale + ".");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.5_11_g_ii_2.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.5_11_g_ii_2.js
new file mode 100644
index 000000000..d4213d2da
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.5_11_g_ii_2.js
@@ -0,0 +1,26 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that missing Unicode extension values default to true for
+ * boolean keys.
+ * @author Norbert Lindenberg
+ */
+
+var extensions = ["-u-co-phonebk-kn", "-u-kn-co-phonebk"];
+extensions.forEach(function (extension) {
+ var defaultLocale = new Intl.Collator().resolvedOptions().locale;
+ var collator = new Intl.Collator([defaultLocale + extension], {usage: "sort"});
+ var locale = collator.resolvedOptions().locale;
+ var numeric = collator.resolvedOptions().numeric;
+ if (numeric !== undefined) {
+ if (numeric !== true) {
+ $ERROR("Default value for \"kn\" should be true, but is " + numeric + ".");
+ }
+ if (locale.indexOf("-kn") !== -1) {
+ $ERROR("\"kn\" is returned in locale, but shouldn't be.");
+ }
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.5_6.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.5_6.js
new file mode 100644
index 000000000..4bc904ee1
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.5_6.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["dataLocale", "nu", "ca", "co", "locale"]);
+
+testWithIntlConstructors(function (Constructor) {
+ var locale = new Constructor(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+ if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
+ $ERROR("Constructor returns invalid locale " + locale + ".");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.6_2.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_2.js
new file mode 100644
index 000000000..8d4f7efa9
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_2.js
@@ -0,0 +1,27 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a List is not affected by adversarial
+ * changes to Array.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintArray();
+
+testWithIntlConstructors(function (Constructor) {
+ // this test should work equally for both matching algorithms
+ ["lookup", "best fit"].forEach(function (matcher) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ var canonicalized = Constructor.supportedLocalesOf([defaultLocale, defaultLocale],
+ {localeMatcher: matcher});
+ if (canonicalized.length > 1) {
+ $ERROR("Canonicalization with matcher " + matcher + " didn't remove duplicate language tags from locale list.");
+ }
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4.js
new file mode 100644
index 000000000..7c053a381
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4.js
@@ -0,0 +1,23 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that LookupSupportedLocales returns an empty list when
+ * given an empty list.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ // this test should work equally for both matching algorithms
+ ["lookup", "best fit"].forEach(function (matcher) {
+ var supported = Constructor.supportedLocalesOf([], {localeMatcher: matcher});
+ if (supported.length !== 0) {
+ $ERROR("SupportedLocales with matcher " + matcher + " returned a non-empty list for an empty list.");
+ }
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_b.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_b.js
new file mode 100644
index 000000000..5b9a43157
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_b.js
@@ -0,0 +1,47 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Unicode locale extension sequences do not affect
+ * whether a locale is considered supported, but are reported back.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ // this test should work equally for both matching algorithms
+ ["lookup", "best fit"].forEach(function (matcher) {
+ var info = getLocaleSupportInfo(Constructor);
+ var allLocales = info.supported.concat(info.byFallback, info.unsupported);
+ allLocales.forEach(function (locale) {
+ var validExtension = "-u-co-phonebk-nu-latn";
+ var invalidExtension = "-u-nu-invalid";
+ var supported1 = Constructor.supportedLocalesOf([locale],
+ {localeMatcher: matcher});
+ var supported2 = Constructor.supportedLocalesOf([locale + validExtension],
+ {localeMatcher: matcher});
+ var supported3 = Constructor.supportedLocalesOf([locale + invalidExtension],
+ {localeMatcher: matcher});
+ if (supported1.length === 1) {
+ if (supported2.length !== 1 || supported3.length !== 1) {
+ $ERROR("Presence of Unicode locale extension sequence affects whether locale " +
+ locale + " is considered supported with matcher " + matcher + ".");
+ }
+ if (supported2[0] !== locale + validExtension || supported3[0] !== locale + invalidExtension) {
+ alert(locale + "; " + supported2[0] + "; " + supported3[0]);
+ $ERROR("Unicode locale extension sequence is not correctly returned for locale " +
+ locale + " with matcher " + matcher + ".");
+ }
+ } else {
+ if (supported2.length !== 0 || supported3.length !== 0) {
+ $ERROR("Presence of Unicode locale extension sequence affects whether locale " +
+ locale + " is considered supported with matcher " + matcher + ".");
+ }
+ }
+ });
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_c.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_c.js
new file mode 100644
index 000000000..de68a9b66
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.6_4_c.js
@@ -0,0 +1,32 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that LookupSupportedLocales includes the default locale
+ * and doesn't include the "no linguistic content" locale.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ // this test should work equally for both matching algorithms
+ ["lookup", "best fit"].forEach(function (matcher) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ var noLinguisticContent = "zxx";
+ var supported = Constructor.supportedLocalesOf([defaultLocale, noLinguisticContent],
+ {localeMatcher: matcher});
+ if (supported.indexOf(defaultLocale) === -1) {
+ $ERROR("SupportedLocales didn't return default locale with matcher " + matcher + ".");
+ }
+ if (supported.indexOf(noLinguisticContent) !== -1) {
+ $ERROR("SupportedLocales returned the \"no linguistic content\" locale with matcher " + matcher + ".");
+ }
+ if (supported.length > 1) {
+ $ERROR("SupportedLocales returned stray locales: " + supported.join(", ") + " with matcher " + matcher + ".");
+ }
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.8_1_c.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.8_1_c.js
new file mode 100644
index 000000000..724db1edd
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.8_1_c.js
@@ -0,0 +1,36 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option localeMatcher is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+
+ var validValues = [undefined, "lookup", "best fit", {toString: function () { return "lookup"; }}];
+ validValues.forEach(function (value) {
+ var supported = Constructor.supportedLocalesOf([defaultLocale], {localeMatcher: value});
+ });
+
+ var invalidValues = [null, 0, 5, NaN, true, false, "invalid"];
+ invalidValues.forEach(function (value) {
+ var error;
+ try {
+ var supported = Constructor.supportedLocalesOf([defaultLocale], {localeMatcher: value});
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid localeMatcher value " + value + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid localeMatcher value " + value + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/9.2.8_4.js b/js/src/tests/test262/intl402/ch09/9.2/9.2.8_4.js
new file mode 100644
index 000000000..79c362f62
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/9.2.8_4.js
@@ -0,0 +1,35 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the array returned by SupportedLocales is extensible,
+ * but its properties are non-writable/non-configurable.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+function testFrozenProperty(obj, property) {
+ var desc = Object.getOwnPropertyDescriptor(obj, property);
+ if (desc.writable) {
+ $ERROR("Property " + property + " of object returned by SupportedLocales is writable.");
+ }
+ if (desc.configurable) {
+ $ERROR("Property " + property + " of object returned by SupportedLocales is configurable.");
+ }
+}
+
+testWithIntlConstructors(function (Constructor) {
+ var defaultLocale = new Constructor().resolvedOptions().locale;
+ var supported = Constructor.supportedLocalesOf([defaultLocale]);
+ if (!Object.isExtensible(supported)) {
+ $ERROR("Object returned by SupportedLocales is not extensible.");
+ }
+ for (var i = 0; i < supported.length; i++) {
+ testFrozenProperty(supported, i);
+ }
+ testFrozenProperty(supported, "length");
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch09/9.2/browser.js b/js/src/tests/test262/intl402/ch09/9.2/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/browser.js
diff --git a/js/src/tests/test262/intl402/ch09/9.2/shell.js b/js/src/tests/test262/intl402/ch09/9.2/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/9.2/shell.js
diff --git a/js/src/tests/test262/intl402/ch09/browser.js b/js/src/tests/test262/intl402/ch09/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/browser.js
diff --git a/js/src/tests/test262/intl402/ch09/shell.js b/js/src/tests/test262/intl402/ch09/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch09/shell.js
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_1.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_1.js
new file mode 100644
index 000000000..432e073fc
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_1.js
@@ -0,0 +1,43 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that an object can't be re-initialized as a Collator.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var obj, error;
+
+ // variant 1: use constructor in a "new" expression
+ obj = new Constructor();
+ try {
+ Intl.Collator.call(obj);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Re-initializing object created with \"new\" as Collator was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Re-initializing object created with \"new\" as Collator was rejected with wrong error " + error.name + ".");
+ }
+
+ // variant 2: use constructor as a function
+ obj = Constructor.call({});
+ error = undefined;
+ try {
+ Intl.Collator.call(obj);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Re-initializing object created with constructor as function as Collator was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Re-initializing object created with constructor as function as Collator was rejected with wrong error " + error.name + ".");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_10.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_10.js
new file mode 100644
index 000000000..5c6b657b5
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_10.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["localeMatcher", "kn", "kf"]);
+
+var locale = new Intl.Collator(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
+ $ERROR("Collator returns invalid locale " + locale + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_11.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_11.js
new file mode 100644
index 000000000..447fd8b28
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_11.js
@@ -0,0 +1,12 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option localeMatcher is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.Collator, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_13.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_13.js
new file mode 100644
index 000000000..4129eebd2
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_13.js
@@ -0,0 +1,13 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the options numeric and caseFirst are processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.Collator, "numeric", "boolean", undefined, undefined, {isOptional: true});
+testOption(Intl.Collator, "caseFirst", "string", ["upper", "lower", "false"], undefined, {isOptional: true});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_b.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_b.js
new file mode 100644
index 000000000..f1fef2704
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_b.js
@@ -0,0 +1,44 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests the special handling of the "co" key in Intl.Collator.
+ * @author Norbert Lindenberg
+ */
+
+function checkCollation(extensionCoValue, usageValue, expectedCollations, expectedUsage) {
+ var requestLocale = extensionCoValue !== undefined ? "de-DE-u-co-" + extensionCoValue : "de-DE";
+ var options = usageValue !== undefined ? { usage: usageValue } : undefined;
+ var collator = new Intl.Collator([requestLocale], options);
+
+ var collation = collator.resolvedOptions().collation;
+ if (expectedCollations.indexOf(collation) === -1) {
+ $ERROR((extensionCoValue === undefined ? "Default collation" : "Collation for \"" + extensionCoValue) +
+ "\" should be " + expectedCollations.join(" or ") + ", but is " + collation + ".");
+ }
+
+ var usage = collator.resolvedOptions().usage;
+ if (expectedUsage !== usage) {
+ $ERROR((usageValue === undefined ? "Default usage" : "Usage") +
+ " should be " + expectedUsage + ", but is " + usage + ".");
+ }
+}
+
+checkCollation(undefined, undefined, ["default"], "sort");
+
+checkCollation("phonebk", undefined, ["phonebk", "default"], "sort");
+
+checkCollation("invalid", undefined, ["default"], "sort");
+
+checkCollation("standard", undefined, ["default"], "sort");
+
+checkCollation("standard", "search", ["default"], "search");
+
+checkCollation("standard", "sort", ["default"], "sort");
+
+checkCollation("search", undefined, ["default"], "sort");
+
+checkCollation("search", "search", ["default"], "search");
+
+checkCollation("search", "sort", ["default"], "sort");
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_c.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_c.js
new file mode 100644
index 000000000..4ad76d45b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_19_c.js
@@ -0,0 +1,63 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the options numeric and caseFirst can be
+ * set through either the locale or the options.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var options = [
+ {key: "kn", property: "numeric", type: "boolean", values: [true, false]},
+ {key: "kf", property: "caseFirst", type: "string", values: ["upper", "lower", "false"]}
+];
+
+options.forEach(function (option) {
+ var defaultLocale = new Intl.Collator().resolvedOptions().locale;
+ var collator, opt, result;
+
+ // find out which values are supported for a property in the default locale
+ var supportedValues = [];
+ option.values.forEach(function (value) {
+ opt = {};
+ opt[option.property] = value;
+ collator = new Intl.Collator([defaultLocale], opt);
+ result = collator.resolvedOptions()[option.property];
+ if (result !== undefined && supportedValues.indexOf(result) === -1) {
+ supportedValues.push(result);
+ }
+ });
+
+ // verify that the supported values can also be set through the locale
+ supportedValues.forEach(function (value) {
+ collator = new Intl.Collator([defaultLocale + "-u-" + option.key + "-" + value]);
+ result = collator.resolvedOptions()[option.property];
+ if (result !== value) {
+ $ERROR("Property " + option.property + " couldn't be set through locale extension key " +
+ option.key + "; requested value: " + value + "; actual value: " + result + ".");
+ }
+ });
+
+ // verify that the options setting overrides the locale setting
+ supportedValues.forEach(function (value) {
+ var otherValue;
+ option.values.forEach(function (possibleValue) {
+ if (possibleValue !== value) {
+ otherValue = possibleValue;
+ }
+ });
+ if (otherValue !== undefined) {
+ opt = {};
+ opt[option.property] = value;
+ collator = new Intl.Collator([defaultLocale + "-u-" + option.key + "-" + otherValue], opt);
+ result = collator.resolvedOptions()[option.property];
+ if (result !== value) {
+ $ERROR("Options value for property " + option.property + " doesn't override locale extension key " +
+ option.key + "; requested value: " + value + "; actual value: " + result + ".");
+ }
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_20.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_20.js
new file mode 100644
index 000000000..97d70c0f9
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_20.js
@@ -0,0 +1,13 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option sensitivity is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// the fallback is variant only for usage === sort, but that happens to be the fallback for usage
+testOption(Intl.Collator, "sensitivity", "string", ["base", "accent", "case", "variant"], "variant");
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_23.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_23.js
new file mode 100644
index 000000000..0b5261509
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_23.js
@@ -0,0 +1,13 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option ignorePunctuation is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// the fallback is variant only for usage === sort, but that happens to be the fallback for usage
+testOption(Intl.Collator, "ignorePunctuation", "boolean", undefined, false);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_6.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_6.js
new file mode 100644
index 000000000..bc13436d7
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_6.js
@@ -0,0 +1,12 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option usage is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.Collator, "usage", "string", ["sort", "search"], "sort");
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.1_a.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_a.js
new file mode 100644
index 000000000..56d4b9789
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.1_a.js
@@ -0,0 +1,14 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that constructing a Collator doesn't create or modify
+ * unwanted properties on the RegExp constructor.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.Collator("de-DE-u-co-phonebk");
+});
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.2.1_4.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.2.1_4.js
new file mode 100644
index 000000000..22e69065e
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.2.1_4.js
@@ -0,0 +1,21 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that for non-object values passed as this to Collator a
+ * wrapper object will be initialized and returned.
+ * @author Norbert Lindenberg
+ */
+
+var thisValues = [true, 42, "国際化"];
+
+thisValues.forEach(function (value) {
+ var collator = Intl.Collator.call(value);
+ // check that the returned object functions as a collator
+ var referenceCollator = new Intl.Collator();
+ if (Intl.Collator.prototype.compare.call(collator, "a", "b") !== referenceCollator.compare("a", "b")) {
+ $ERROR("Collator initialized from " + value + " doesn't behave like normal collator.");
+ }
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.2_a.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.2_a.js
new file mode 100644
index 000000000..de69a4809
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.2_a.js
@@ -0,0 +1,30 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator can be subclassed.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// get a collator and have it sort an array for comparison with the subclass
+var locales = ["tlh", "id", "en"];
+var a = ["A", "C", "E", "B", "D", "F"];
+var referenceCollator = new Intl.Collator(locales);
+var referenceSorted = a.slice().sort(referenceCollator.compare);
+
+function MyCollator(locales, options) {
+ Intl.Collator.call(this, locales, options);
+ // could initialize MyCollator properties
+}
+
+MyCollator.prototype = Object.create(Intl.Collator.prototype);
+MyCollator.prototype.constructor = MyCollator;
+// could add methods to MyCollator.prototype
+
+var collator = new MyCollator(locales);
+a.sort(collator.compare);
+testArraysAreSame(referenceSorted, a);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1.3.js b/js/src/tests/test262/intl402/ch10/10.1/10.1.3.js
new file mode 100644
index 000000000..7459d98d6
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1.3.js
@@ -0,0 +1,19 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that objects constructed by Intl.Collator have the specified internal properties.
+ * @author Norbert Lindenberg
+ */
+
+var obj = new Intl.Collator();
+
+var actualPrototype = Object.getPrototypeOf(obj);
+if (actualPrototype !== Intl.Collator.prototype) {
+ $ERROR("Prototype of object constructed by Intl.Collator isn't Intl.Collator.prototype; got " + actualPrototype);
+}
+
+if (!Object.isExtensible(obj)) {
+ $ERROR("Object constructed by Intl.Collator must be extensible.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/10.1_L15.js b/js/src/tests/test262/intl402/ch10/10.1/10.1_L15.js
new file mode 100644
index 000000000..4dbabfd64
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/10.1_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.Collator, true, true, ["supportedLocalesOf"], 0);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.1/browser.js b/js/src/tests/test262/intl402/ch10/10.1/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/browser.js
diff --git a/js/src/tests/test262/intl402/ch10/10.1/shell.js b/js/src/tests/test262/intl402/ch10/10.1/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.1/shell.js
diff --git a/js/src/tests/test262/intl402/ch10/10.2/10.2.1.js b/js/src/tests/test262/intl402/ch10/10.2/10.2.1.js
new file mode 100644
index 000000000..9eccb073c
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/10.2.1.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.prototype has the required attributes.
+ * @author Norbert Lindenberg
+ */
+
+var desc = Object.getOwnPropertyDescriptor(Intl.Collator, "prototype");
+if (desc === undefined) {
+ $ERROR("Intl.Collator.prototype is not defined.");
+}
+if (desc.writable) {
+ $ERROR("Intl.Collator.prototype must not be writable.");
+}
+if (desc.enumerable) {
+ $ERROR("Intl.Collator.prototype must not be enumerable.");
+}
+if (desc.configurable) {
+ $ERROR("Intl.Collator.prototype must not be configurable.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.2/10.2.2_L15.js b/js/src/tests/test262/intl402/ch10/10.2/10.2.2_L15.js
new file mode 100644
index 000000000..6ffcdde84
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/10.2.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.supportedLocalesOf
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.Collator.supportedLocalesOf, true, false, [], 1);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.2/10.2.2_a.js b/js/src/tests/test262/intl402/ch10/10.2/10.2.2_a.js
new file mode 100644
index 000000000..5cf953ce8
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/10.2.2_a.js
@@ -0,0 +1,27 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator has a supportedLocalesOf
+ * property, and it works as planned.
+ */
+
+var defaultLocale = new Intl.Collator().resolvedOptions().locale;
+var notSupported = 'zxx'; // "no linguistic content"
+var requestedLocales = [defaultLocale, notSupported];
+
+var supportedLocales;
+
+if (!Intl.Collator.hasOwnProperty('supportedLocalesOf')) {
+ $ERROR("Intl.Collator doesn't have a supportedLocalesOf property.");
+}
+
+supportedLocales = Intl.Collator.supportedLocalesOf(requestedLocales);
+if (supportedLocales.length !== 1) {
+ $ERROR('The length of supported locales list is not 1.');
+}
+
+if (supportedLocales[0] !== defaultLocale) {
+ $ERROR('The default locale is not returned in the supported list.');
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.2/10.2.2_b.js b/js/src/tests/test262/intl402/ch10/10.2/10.2.2_b.js
new file mode 100644
index 000000000..1b99fd8c5
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/10.2.2_b.js
@@ -0,0 +1,13 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.supportedLocalesOf
+ * doesn't access arguments that it's not given.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintDataProperty(Object.prototype, "1");
+new Intl.Collator("und");
diff --git a/js/src/tests/test262/intl402/ch10/10.2/10.2.3_b.js b/js/src/tests/test262/intl402/ch10/10.2/10.2.3_b.js
new file mode 100644
index 000000000..aef1e746a
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/10.2.3_b.js
@@ -0,0 +1,52 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator does not accept Unicode locale
+ * extension keys and values that are not allowed.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var testArray = [
+ "hello", "你好", "こんにちは",
+ "pêche", "peché", "1", "9", "10",
+ "ụ\u031B", "u\u031B\u0323", "ư\u0323", "u\u0323\u031B",
+ "Å", "Å", "A\u030A"
+];
+
+var defaultCollator = new Intl.Collator();
+var defaultOptions = defaultCollator.resolvedOptions();
+var defaultOptionsJSON = JSON.stringify(defaultOptions);
+var defaultLocale = defaultOptions.locale;
+var defaultSortedArray = testArray.slice(0).sort(defaultCollator.compare);
+
+var keyValues = {
+ "co": ["standard", "search", "invalid"],
+ "ka": ["noignore", "shifted", "invalid"],
+ "kb": ["true", "false", "invalid"],
+ "kc": ["true", "false", "invalid"],
+ "kh": ["true", "false", "invalid"],
+ "kk": ["true", "false", "invalid"],
+ "kr": ["latn-hira-hani", "hani-hira-latn", "invalid"],
+ "ks": ["level1", "level2", "level3", "level4", "identic", "invalid"],
+ "vt": ["1234-5678-9abc-edf0", "invalid"]
+};
+
+Object.getOwnPropertyNames(keyValues).forEach(function (key) {
+ keyValues[key].forEach(function (value) {
+ var collator = new Intl.Collator([defaultLocale + "-u-" + key + "-" + value]);
+ var options = collator.resolvedOptions();
+ if (options.locale !== defaultLocale) {
+ $ERROR("Locale " + options.locale + " is affected by key " +
+ key + "; value " + value + ".");
+ }
+ if (JSON.stringify(options) !== defaultOptionsJSON) {
+ $ERROR("Resolved options " + JSON.stringify(options) + " are affected by key " +
+ key + "; value " + value + ".");
+ }
+ testArraysAreSame(defaultSortedArray, testArray.sort(collator.compare));
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.2/browser.js b/js/src/tests/test262/intl402/ch10/10.2/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/browser.js
diff --git a/js/src/tests/test262/intl402/ch10/10.2/shell.js b/js/src/tests/test262/intl402/ch10/10.2/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.2/shell.js
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.1.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.1.js
new file mode 100644
index 000000000..699949e18
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.1.js
@@ -0,0 +1,13 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.prototype.constructor is the
+ * Intl.Collator.
+ */
+
+if (Intl.Collator.prototype.constructor !== Intl.Collator) {
+ $ERROR("Intl.Collator.prototype.constructor is not the same as " +
+ "Intl.Collator");
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_a_L15.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_a_L15.js
new file mode 100644
index 000000000..3d49601db
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_a_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the function returned by Intl.Collator.prototype.compare
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(new Intl.Collator().compare, true, false, [], 2);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_c.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_c.js
new file mode 100644
index 000000000..73f2bcf09
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_1_c.js
@@ -0,0 +1,36 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that compare function is bound to its Intl.Collator.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var strings = ["d", "O", "od", "oe", "of", "ö", "o\u0308", "X", "y", "Z", "Z.", "𠮷野家", "吉野家", "!A", "A", "b", "C"];
+var locales = [undefined, ["de"], ["de-u-co-phonebk"], ["en"], ["ja"], ["sv"]];
+var options = [
+ undefined,
+ {usage: "search"},
+ {sensitivity: "base", ignorePunctuation: true}
+];
+
+locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var collatorObj = new Intl.Collator(locales, options);
+ var compareFunc = collatorObj.compare;
+ var referenceSorted = strings.slice();
+ referenceSorted.sort(function (a, b) { return collatorObj.compare(a, b); });
+ var sorted = strings;
+ sorted.sort(compareFunc);
+ try {
+ testArraysAreSame(referenceSorted, sorted);
+ } catch (e) {
+ e.message += " (Testing with locales " + locales + "; options " +
+ (options ? JSON.stringify(options) : options) + ".)";
+ throw e;
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_a.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_a.js
new file mode 100644
index 000000000..a946245b4
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_a.js
@@ -0,0 +1,68 @@
+// Copyright 2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the function returned by Intl.Collator.prototype.compare
+ * returns 0 when comparing Strings that are considered canonically equivalent
+ * by the Unicode standard.
+ * @author Norbert Lindenberg
+ */
+
+var collator = new Intl.Collator();
+var pairs = [
+ // example from Unicode 5.0, section 3.7, definition D70
+ ["o\u0308", "ö"],
+ // examples from Unicode 5.0, chapter 3.11
+ ["ä\u0323", "a\u0323\u0308"],
+ ["a\u0308\u0323", "a\u0323\u0308"],
+ ["ạ\u0308", "a\u0323\u0308"],
+ ["ä\u0306", "a\u0308\u0306"],
+ ["ă\u0308", "a\u0306\u0308"],
+ // example from Unicode 5.0, chapter 3.12
+ ["\u1111\u1171\u11B6", "퓛"],
+ // examples from UTS 10, Unicode Collation Algorithm
+ ["Å", "Å"],
+ ["Å", "A\u030A"],
+ ["x\u031B\u0323", "x\u0323\u031B"],
+ ["ự", "ụ\u031B"],
+ ["ự", "u\u031B\u0323"],
+ ["ự", "ư\u0323"],
+ ["ự", "u\u0323\u031B"],
+ // examples from UAX 15, Unicode Normalization Forms
+ ["Ç", "C\u0327"],
+ ["q\u0307\u0323", "q\u0323\u0307"],
+ ["가", "\u1100\u1161"],
+ ["Å", "A\u030A"],
+ ["Ω", "Ω"],
+ ["Å", "A\u030A"],
+ ["ô", "o\u0302"],
+ ["ṩ", "s\u0323\u0307"],
+ ["ḋ\u0323", "d\u0323\u0307"],
+ ["ḋ\u0323", "ḍ\u0307"],
+ ["q\u0307\u0323", "q\u0323\u0307"],
+ // examples involving supplementary characters from UCD NormalizationTest.txt
+ ["\uD834\uDD5E", "\uD834\uDD57\uD834\uDD65"],
+ ["\uD87E\uDC2B", "北"]
+
+];
+var i;
+for (i = 0; i < pairs.length; i++) {
+ var pair = pairs[i];
+ if (collator.compare(pair[0], pair[1]) !== 0) {
+ $ERROR("Collator.compare considers " + pair[0] + " (" + toU(pair[0]) +
+ ") ≠ " + pair[1] + " (" + toU(pair[1]) + ").");
+ }
+}
+
+function toU(s) {
+ var result = "";
+ var escape = "\\u0000";
+ var i;
+ for (i = 0; i < s.length; i++) {
+ var hex = s.charCodeAt(i).toString(16);
+ result += escape.substring(0, escape.length - hex.length) + hex;
+ }
+ return result;
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_b_NN.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_b_NN.js
new file mode 100644
index 000000000..c417d2b8a
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_b_NN.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the compare function isn't entirely unreasonable.
+ * This test is not normative.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// this test should be valid at least for the following locales
+var locales = ["de", "en", "es", "fr", "it"];
+locales = Intl.Collator.supportedLocalesOf(locales, {localeMatcher: "lookup"});
+locales.forEach(function (locale) {
+ var collator = new Intl.Collator([locale], {sensitivity: "variant", localeMatcher: "lookup"});
+ var a = ["L", "X", "C", "k", "Z", "H", "d", "m", "w", "A", "i", "f", "y", "E", "N", "V", "g", "J", "b"];
+ a.sort(collator.compare);
+ var expected = ["A", "b", "C", "d", "E", "f", "g", "H", "i", "J", "k", "L", "m", "N", "V", "w", "X", "y", "Z"];
+ testArraysAreSame(expected, a);
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_c_NN.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_c_NN.js
new file mode 100644
index 000000000..5d5060be5
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_c_NN.js
@@ -0,0 +1,22 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the compare function supports phonebook sorting if it says it does.
+ * This test is not normative.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// this test should be valid at least for the following locales
+var locales = ["de-DE-u-co-phonebk", "de-u-co-phonebk"];
+var collator = new Intl.Collator(locales, {localeMatcher: "lookup"});
+if (locales.indexOf(collator.resolvedOptions().locale) !== -1) {
+ var a = ["A", "b", "Af", "Ab", "od", "off", "Ä", "ö"];
+ a.sort(collator.compare);
+ var expected = ["A", "Ab", "Ä", "Af", "b", "od", "ö", "off"];
+ testArraysAreSame(expected, a);
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_d_NN.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_d_NN.js
new file mode 100644
index 000000000..be5f1aa33
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_CS_d_NN.js
@@ -0,0 +1,34 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the compare function supports different sensitivity settings.
+ * This test is not normative.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// this test should be valid at least for the following locales
+var locales = ["de", "en", "es", "it"];
+locales = Intl.Collator.supportedLocalesOf(locales, {localeMatcher: "lookup"});
+locales.forEach(function (locale) {
+ var target = "Aa";
+ var input = ["Aa", "bA", "E", "b", "aA", "fC", "áÁ", "Aã"];
+ var expected = {
+ "base": ["Aa", "aA", "áÁ", "Aã"],
+ "accent": ["Aa", "aA"],
+ "case": ["Aa", "Aã"],
+ "variant": ["Aa"]
+ };
+ Object.getOwnPropertyNames(expected).forEach(function (sensitivity) {
+ var collator = new Intl.Collator([locale], {usage: "search",
+ sensitivity: sensitivity, localeMatcher: "lookup"});
+ var matches = input.filter(function (v) {
+ return collator.compare(v, target) === 0;
+ });
+ testArraysAreSame(expected[sensitivity], matches);
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.2_L15.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_L15.js
new file mode 100644
index 000000000..5845ea3ca
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the getter for Intl.Collator.prototype.compare
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get , true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.3.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.3.js
new file mode 100644
index 000000000..bc6b4fabb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.3.js
@@ -0,0 +1,47 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the object returned by Intl.Collator.prototype.resolvedOptions
+ * has the right properties.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var actual = new Intl.Collator().resolvedOptions();
+
+var actual2 = new Intl.Collator().resolvedOptions();
+if (actual2 === actual) {
+ $ERROR("resolvedOptions returned the same object twice.");
+}
+
+// source: CLDR file common/bcp47/collation.xml; version CLDR 21.
+var collations = [
+ "default", // added
+ "big5han",
+ "dict",
+ "direct",
+ "ducet",
+ "gb2312",
+ "phonebk",
+ "phonetic",
+ "pinyin",
+ "reformed",
+ // "search", // excluded
+ "searchjl",
+ // "standard", // excluded
+ "stroke",
+ "trad",
+ "unihan"
+];
+
+// this assumes the default values where the specification provides them
+mustHaveProperty(actual, "locale", isCanonicalizedStructurallyValidLanguageTag);
+mustHaveProperty(actual, "usage", ["sort"]);
+mustHaveProperty(actual, "sensitivity", ["variant"]);
+mustHaveProperty(actual, "ignorePunctuation", [false]);
+mustHaveProperty(actual, "collation", collations);
+mayHaveProperty(actual, "numeric", [true, false]);
+mayHaveProperty(actual, "caseFirst", ["upper", "lower", "false"]);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3.3_L15.js b/js/src/tests/test262/intl402/ch10/10.3/10.3.3_L15.js
new file mode 100644
index 000000000..718cc9fea
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.prototype.resolvedOptions
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.Collator.prototype.resolvedOptions, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3_L15.js b/js/src/tests/test262/intl402/ch10/10.3/10.3_L15.js
new file mode 100644
index 000000000..60719736c
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.prototype
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.Collator.prototype, false, false, ["constructor", "compare", "resolvedOptions"]);
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3_a.js b/js/src/tests/test262/intl402/ch10/10.3/10.3_a.js
new file mode 100644
index 000000000..aa2e52845
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3_a.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.prototype is an object that
+ * has been initialized as an Intl.Collator.
+ */
+
+// test by calling a function that would fail if "this" were not an object
+// initialized as an Intl.Collator
+if (Intl.Collator.prototype.compare("aаあ아", "aаあ아") !== 0) {
+ $ERROR("Intl.Collator.prototype is not an object that has been " +
+ "initialized as an Intl.Collator.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/10.3_b.js b/js/src/tests/test262/intl402/ch10/10.3/10.3_b.js
new file mode 100644
index 000000000..9c3c2db32
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/10.3_b.js
@@ -0,0 +1,33 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator.prototype functions throw a
+ * TypeError if called on a non-object value or an object that hasn't been
+ * initialized as a Collator.
+ * @author Norbert Lindenberg
+ */
+
+var functions = {
+ "compare getter": Object.getOwnPropertyDescriptor(Intl.Collator.prototype, "compare").get,
+ resolvedOptions: Intl.Collator.prototype.resolvedOptions
+};
+var invalidTargets = [undefined, null, true, 0, "Collator", [], {}];
+
+Object.getOwnPropertyNames(functions).forEach(function (functionName) {
+ var f = functions[functionName];
+ invalidTargets.forEach(function (target) {
+ var error;
+ try {
+ f.call(target);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Calling " + functionName + " on " + target + " was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Calling " + functionName + " on " + target + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch10/10.3/browser.js b/js/src/tests/test262/intl402/ch10/10.3/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/browser.js
diff --git a/js/src/tests/test262/intl402/ch10/10.3/shell.js b/js/src/tests/test262/intl402/ch10/10.3/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.3/shell.js
diff --git a/js/src/tests/test262/intl402/ch10/10.4/10.4_a.js b/js/src/tests/test262/intl402/ch10/10.4/10.4_a.js
new file mode 100644
index 000000000..7527f65eb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.4/10.4_a.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.Collator instances have the specified properties.
+ * @author Norbert Lindenberg
+ */
+
+var obj = new Intl.Collator();
+
+var toStringValue = Object.prototype.toString.call(obj);
+if (toStringValue !== "[object Object]") {
+ $ERROR("Intl.Collator instance produces wrong [[Class]] - toString returns " + toStringValue + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch10/10.4/browser.js b/js/src/tests/test262/intl402/ch10/10.4/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.4/browser.js
diff --git a/js/src/tests/test262/intl402/ch10/10.4/shell.js b/js/src/tests/test262/intl402/ch10/10.4/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/10.4/shell.js
diff --git a/js/src/tests/test262/intl402/ch10/browser.js b/js/src/tests/test262/intl402/ch10/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/browser.js
diff --git a/js/src/tests/test262/intl402/ch10/shell.js b/js/src/tests/test262/intl402/ch10/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch10/shell.js
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_1.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_1.js
new file mode 100644
index 000000000..33af16975
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_1.js
@@ -0,0 +1,43 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that an object can't be re-initialized as a NumberFormat.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var obj, error;
+
+ // variant 1: use constructor in a "new" expression
+ obj = new Constructor();
+ try {
+ Intl.NumberFormat.call(obj);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Re-initializing object created with \"new\" as NumberFormat was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Re-initializing object created with \"new\" as NumberFormat was rejected with wrong error " + error.name + ".");
+ }
+
+ // variant 2: use constructor as a function
+ obj = Constructor.call({});
+ error = undefined;
+ try {
+ Intl.NumberFormat.call(obj);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Re-initializing object created with constructor as function as NumberFormat was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Re-initializing object created with constructor as function as NumberFormat was rejected with wrong error " + error.name + ".");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_15.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_15.js
new file mode 100644
index 000000000..4d0467428
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_15.js
@@ -0,0 +1,13 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option style is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.NumberFormat, "style", "string", ["decimal", "percent", "currency"], "decimal",
+ {extra: {"currency": {currency: "CNY"}}});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_17.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_17.js
new file mode 100644
index 000000000..08c0e8e5c
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_17.js
@@ -0,0 +1,81 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option currency is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+var validValues = ["CNY", "USD", "EUR", "IDR", "jpy", {toString: function () {return "INR";}}];
+var invalidValues = ["$", "SFr.", "US$", "ßP", {toString: function () {return;}}];
+
+var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+
+validValues.forEach(function (value) {
+ var format, actual, expected;
+
+ // with currency style, we should get the upper case form back
+ format = new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = value.toString().toUpperCase();
+ if (actual !== expected) {
+ $ERROR("Incorrect resolved currency with currency style - expected " +
+ expected + "; got " + actual + ".");
+ }
+
+ // without currency style, we shouldn't get any currency back
+ format = new Intl.NumberFormat([defaultLocale], {currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = undefined;
+ if (actual !== expected) {
+ $ERROR("Incorrect resolved currency with non-currency style - expected " +
+ expected + "; got " + actual + ".");
+ }
+
+ // currencies specified through the locale must be ignored
+ format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = value.toString().toUpperCase();
+ if (actual !== expected) {
+ $ERROR("Incorrect resolved currency with -u-cu- and currency style - expected " +
+ expected + "; got " + actual + ".");
+ }
+
+ format = new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value});
+ actual = format.resolvedOptions().currency;
+ expected = undefined;
+ if (actual !== expected) {
+ $ERROR("Incorrect resolved currency with -u-cu- and non-currency style - expected " +
+ expected + "; got " + actual + ".");
+ }
+});
+
+invalidValues.forEach(function (value) {
+ function expectError(f) {
+ var error;
+ try {
+ f();
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid currency value " + value + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid currency value " + value + " was rejected with wrong error " + error.name + ".");
+ }
+ }
+
+ expectError(function () {
+ return new Intl.NumberFormat([defaultLocale], {style: "currency", currency: value});
+ });
+ expectError(function () {
+ return new Intl.NumberFormat([defaultLocale], {currency: value});
+ });
+ expectError(function () {
+ return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency", currency: value});
+ });
+ expectError(function () {
+ return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {currency: value});
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_19.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_19.js
new file mode 100644
index 000000000..e41ca5bec
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_19.js
@@ -0,0 +1,31 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the currency style can not be used without a specified currency.
+ * @author Norbert Lindenberg
+ */
+
+var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+
+function expectError(f) {
+ var error;
+ try {
+ f();
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid currency value " + value + " was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Invalid currency value " + value + " was rejected with wrong error " + error.name + ".");
+ }
+}
+
+expectError(function () {
+ return new Intl.NumberFormat([defaultLocale], {style: "currency"});
+});
+expectError(function () {
+ return new Intl.NumberFormat([defaultLocale + "-u-cu-krw"], {style: "currency"});
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_20_c.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_20_c.js
new file mode 100644
index 000000000..6a705ab33
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_20_c.js
@@ -0,0 +1,196 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the number of fractional digits is determined correctly for currencies.
+ * @author Norbert Lindenberg
+ */
+
+// data from http://www.currency-iso.org/dl_iso_table_a1.xml, 2013-02-25
+var currencyDigits = {
+ AED: 2,
+ AFN: 2,
+ ALL: 2,
+ AMD: 2,
+ ANG: 2,
+ AOA: 2,
+ ARS: 2,
+ AUD: 2,
+ AWG: 2,
+ AZN: 2,
+ BAM: 2,
+ BBD: 2,
+ BDT: 2,
+ BGN: 2,
+ BHD: 3,
+ BIF: 0,
+ BMD: 2,
+ BND: 2,
+ BOB: 2,
+ BOV: 2,
+ BRL: 2,
+ BSD: 2,
+ BTN: 2,
+ BWP: 2,
+ BYR: 0,
+ BZD: 2,
+ CAD: 2,
+ CDF: 2,
+ CHE: 2,
+ CHF: 2,
+ CHW: 2,
+ CLF: 4,
+ CLP: 0,
+ CNY: 2,
+ COP: 2,
+ COU: 2,
+ CRC: 2,
+ CUC: 2,
+ CUP: 2,
+ CVE: 2,
+ CZK: 2,
+ DJF: 0,
+ DKK: 2,
+ DOP: 2,
+ DZD: 2,
+ EGP: 2,
+ ERN: 2,
+ ETB: 2,
+ EUR: 2,
+ FJD: 2,
+ FKP: 2,
+ GBP: 2,
+ GEL: 2,
+ GHS: 2,
+ GIP: 2,
+ GMD: 2,
+ GNF: 0,
+ GTQ: 2,
+ GYD: 2,
+ HKD: 2,
+ HNL: 2,
+ HRK: 2,
+ HTG: 2,
+ HUF: 2,
+ IDR: 2,
+ ILS: 2,
+ INR: 2,
+ IQD: 3,
+ IRR: 2,
+ ISK: 0,
+ JMD: 2,
+ JOD: 3,
+ JPY: 0,
+ KES: 2,
+ KGS: 2,
+ KHR: 2,
+ KMF: 0,
+ KPW: 2,
+ KRW: 0,
+ KWD: 3,
+ KYD: 2,
+ KZT: 2,
+ LAK: 2,
+ LBP: 2,
+ LKR: 2,
+ LRD: 2,
+ LSL: 2,
+ LTL: 2,
+ LVL: 2,
+ LYD: 3,
+ MAD: 2,
+ MDL: 2,
+ MGA: 2,
+ MKD: 2,
+ MMK: 2,
+ MNT: 2,
+ MOP: 2,
+ MRO: 2,
+ MUR: 2,
+ MVR: 2,
+ MWK: 2,
+ MXN: 2,
+ MXV: 2,
+ MYR: 2,
+ MZN: 2,
+ NAD: 2,
+ NGN: 2,
+ NIO: 2,
+ NOK: 2,
+ NPR: 2,
+ NZD: 2,
+ OMR: 3,
+ PAB: 2,
+ PEN: 2,
+ PGK: 2,
+ PHP: 2,
+ PKR: 2,
+ PLN: 2,
+ PYG: 0,
+ QAR: 2,
+ RON: 2,
+ RSD: 2,
+ RUB: 2,
+ RWF: 0,
+ SAR: 2,
+ SBD: 2,
+ SCR: 2,
+ SDG: 2,
+ SEK: 2,
+ SGD: 2,
+ SHP: 2,
+ SLL: 2,
+ SOS: 2,
+ SRD: 2,
+ SSP: 2,
+ STD: 2,
+ SVC: 2,
+ SYP: 2,
+ SZL: 2,
+ THB: 2,
+ TJS: 2,
+ TMT: 2,
+ TND: 3,
+ TOP: 2,
+ TRY: 2,
+ TTD: 2,
+ TWD: 2,
+ TZS: 2,
+ UAH: 2,
+ UGX: 0,
+ USD: 2,
+ USN: 2,
+ USS: 2,
+ UYI: 0,
+ UYU: 2,
+ UZS: 2,
+ VEF: 2,
+ VND: 0,
+ VUV: 0,
+ WST: 2,
+ XAF: 0,
+ XCD: 2,
+ XOF: 0,
+ XPF: 0,
+ YER: 2,
+ ZAR: 2,
+ ZMW: 2,
+ ZWL: 2
+};
+
+Object.getOwnPropertyNames(currencyDigits).forEach(function (currency) {
+ var digits = currencyDigits[currency];
+ format = Intl.NumberFormat([], {style: "currency", currency: currency});
+ var min = format.resolvedOptions().minimumFractionDigits;
+ var max = format.resolvedOptions().maximumFractionDigits;
+ if (min !== digits) {
+ $ERROR("Didn't get correct minimumFractionDigits for currency " +
+ currency + "; expected " + digits + ", got " + min + ".");
+ }
+ if (max !== digits) {
+ $ERROR("Didn't get correct maximumFractionDigits for currency " +
+ currency + "; expected " + digits + ", got " + max + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_21.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_21.js
new file mode 100644
index 000000000..1751b8b57
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_21.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option currencyDisplay is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"],
+ "symbol", {extra: {any: {style: "currency", currency: "XDR"}}});
+testOption(Intl.NumberFormat, "currencyDisplay", "string", ["code", "symbol", "name"],
+ undefined, {noReturn: true});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_32.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_32.js
new file mode 100644
index 000000000..9196318ef
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_32.js
@@ -0,0 +1,44 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the options minimumSignificantDigits and
+ * maximumSignificantDigits are read in the right sequence.
+ * @author Norbert Lindenberg
+ */
+
+var read = 0;
+
+function readMinimumSignificantDigits() {
+ ++read;
+ if (read === 1) {
+ return 0; // invalid value, but on first read that's OK
+ } else if (read === 3) {
+ return 1; // valid value
+ } else {
+ $ERROR("minimumSignificantDigits read out of sequence: " + read + ".");
+ }
+}
+
+function readMaximumSignificantDigits() {
+ ++read;
+ if (read === 2) {
+ return 0; // invalid value, but on first read that's OK
+ } else if (read === 4) {
+ return 1; // valid value
+ } else {
+ $ERROR("maximumSignificantDigits read out of sequence: " + read + ".");
+ }
+}
+
+var options = {};
+Object.defineProperty(options, "minimumSignificantDigits",
+ { get: readMinimumSignificantDigits });
+Object.defineProperty(options, "maximumSignificantDigits",
+ { get: readMaximumSignificantDigits });
+
+new Intl.NumberFormat("de", options);
+
+if (read !== 4) {
+ $ERROR("insuffient number of property reads: " + read + ".");
+}
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_34.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_34.js
new file mode 100644
index 000000000..98ba9a062
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_34.js
@@ -0,0 +1,12 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option useGrouping is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.NumberFormat, "useGrouping", "boolean", undefined, true);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_6.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_6.js
new file mode 100644
index 000000000..5b9d342eb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_6.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["localeMatcher"]);
+
+var locale = new Intl.NumberFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
+ $ERROR("NumberFormat returns invalid locale " + locale + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_7.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_7.js
new file mode 100644
index 000000000..4b13b245b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_7.js
@@ -0,0 +1,12 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option localeMatcher is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.NumberFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.1_a.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_a.js
new file mode 100644
index 000000000..611816b61
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.1_a.js
@@ -0,0 +1,18 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that constructing a NumberFormat doesn't create or modify
+ * unwanted properties on the RegExp constructor.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.NumberFormat("de-DE-u-nu-latn");
+});
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.NumberFormat("de-DE-u-nu-latn", {style: "currency", currency: "EUR"});
+});
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.2.1_4.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.2.1_4.js
new file mode 100644
index 000000000..18b5b98fa
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.2.1_4.js
@@ -0,0 +1,21 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that for non-object values passed as this to NumberFormat a
+ * wrapper object will be initialized and returned.
+ * @author Norbert Lindenberg
+ */
+
+var thisValues = [true, 42, "国際化"];
+
+thisValues.forEach(function (value) {
+ var format = Intl.NumberFormat.call(value);
+ // check that the returned object functions as a number format
+ var referenceFormat = new Intl.NumberFormat();
+ if (Intl.NumberFormat.prototype.format.call(format, 12.3456) !== referenceFormat.format(12.3456)) {
+ $ERROR("NumberFormat initialized from " + value + " doesn't behave like normal number format.");
+ }
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.2.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.2.js
new file mode 100644
index 000000000..0ca8cbbda
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.2.js
@@ -0,0 +1,30 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat can be subclassed.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// get a number format and have it format an array of numbers for comparison with the subclass
+var locales = ["tlh", "id", "en"];
+var a = [0, 1, -1, -123456.789, -Infinity, NaN];
+var referenceNumberFormat = new Intl.NumberFormat(locales);
+var referenceFormatted = a.map(referenceNumberFormat.format);
+
+function MyNumberFormat(locales, options) {
+ Intl.NumberFormat.call(this, locales, options);
+ // could initialize MyNumberFormat properties
+}
+
+MyNumberFormat.prototype = Object.create(Intl.NumberFormat.prototype);
+MyNumberFormat.prototype.constructor = MyNumberFormat;
+// could add methods to MyNumberFormat.prototype
+
+var format = new MyNumberFormat(locales);
+var actual = a.map(format.format);
+testArraysAreSame(referenceFormatted, actual);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1.3.js b/js/src/tests/test262/intl402/ch11/11.1/11.1.3.js
new file mode 100644
index 000000000..f0bfb5552
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1.3.js
@@ -0,0 +1,19 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that objects constructed by Intl.NumberFormat have the specified internal properties.
+ * @author Norbert Lindenberg
+ */
+
+var obj = new Intl.NumberFormat();
+
+var actualPrototype = Object.getPrototypeOf(obj);
+if (actualPrototype !== Intl.NumberFormat.prototype) {
+ $ERROR("Prototype of object constructed by Intl.NumberFormat isn't Intl.NumberFormat.prototype; got " + actualPrototype);
+}
+
+if (!Object.isExtensible(obj)) {
+ $ERROR("Object constructed by Intl.NumberFormat must be extensible.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/11.1_L15.js b/js/src/tests/test262/intl402/ch11/11.1/11.1_L15.js
new file mode 100644
index 000000000..e40ffc53e
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/11.1_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.NumberFormat, true, true, ["supportedLocalesOf"], 0);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.1/browser.js b/js/src/tests/test262/intl402/ch11/11.1/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/browser.js
diff --git a/js/src/tests/test262/intl402/ch11/11.1/shell.js b/js/src/tests/test262/intl402/ch11/11.1/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.1/shell.js
diff --git a/js/src/tests/test262/intl402/ch11/11.2/11.2.1.js b/js/src/tests/test262/intl402/ch11/11.2/11.2.1.js
new file mode 100644
index 000000000..83bebb283
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/11.2.1.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype has the required attributes.
+ * @author Norbert Lindenberg
+ */
+
+var desc = Object.getOwnPropertyDescriptor(Intl.NumberFormat, "prototype");
+if (desc === undefined) {
+ $ERROR("Intl.NumberFormat.prototype is not defined.");
+}
+if (desc.writable) {
+ $ERROR("Intl.NumberFormat.prototype must not be writable.");
+}
+if (desc.enumerable) {
+ $ERROR("Intl.NumberFormat.prototype must not be enumerable.");
+}
+if (desc.configurable) {
+ $ERROR("Intl.NumberFormat.prototype must not be configurable.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.2/11.2.2_L15.js b/js/src/tests/test262/intl402/ch11/11.2/11.2.2_L15.js
new file mode 100644
index 000000000..49dce3bae
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/11.2.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.supportedLocalesOf
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.NumberFormat.supportedLocalesOf, true, false, [], 1);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.2/11.2.2_a.js b/js/src/tests/test262/intl402/ch11/11.2/11.2.2_a.js
new file mode 100644
index 000000000..c6c9f9a46
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/11.2.2_a.js
@@ -0,0 +1,28 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat has a supportedLocalesOf
+ * property, and it works as planned.
+ * @author: Roozbeh Pournader
+ */
+
+var defaultLocale = new Intl.NumberFormat().resolvedOptions().locale;
+var notSupported = 'zxx'; // "no linguistic content"
+var requestedLocales = [defaultLocale, notSupported];
+
+var supportedLocales;
+
+if (!Intl.NumberFormat.hasOwnProperty('supportedLocalesOf')) {
+ $ERROR("Intl.NumberFormat doesn't have a supportedLocalesOf property.");
+}
+
+supportedLocales = Intl.NumberFormat.supportedLocalesOf(requestedLocales);
+if (supportedLocales.length !== 1) {
+ $ERROR('The length of supported locales list is not 1.');
+}
+
+if (supportedLocales[0] !== defaultLocale) {
+ $ERROR('The default locale is not returned in the supported list.');
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.2/11.2.2_b.js b/js/src/tests/test262/intl402/ch11/11.2/11.2.2_b.js
new file mode 100644
index 000000000..6b4d77e77
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/11.2.2_b.js
@@ -0,0 +1,13 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.supportedLocalesOf
+ * doesn't access arguments that it's not given.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintDataProperty(Object.prototype, "1");
+new Intl.NumberFormat("und");
diff --git a/js/src/tests/test262/intl402/ch11/11.2/11.2.3_b.js b/js/src/tests/test262/intl402/ch11/11.2/11.2.3_b.js
new file mode 100644
index 000000000..70fe7cf11
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/11.2.3_b.js
@@ -0,0 +1,46 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat does not accept Unicode locale
+ * extension keys and values that are not allowed.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"];
+var input = 1234567.89;
+
+locales.forEach(function (locale) {
+ var defaultNumberFormat = new Intl.NumberFormat([locale]);
+ var defaultOptions = defaultNumberFormat.resolvedOptions();
+ var defaultOptionsJSON = JSON.stringify(defaultOptions);
+ var defaultLocale = defaultOptions.locale;
+ var defaultFormatted = defaultNumberFormat.format(input);
+
+ var keyValues = {
+ "cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"],
+ "nu": ["native", "traditio", "finance", "invalid"]
+ };
+
+ Object.getOwnPropertyNames(keyValues).forEach(function (key) {
+ keyValues[key].forEach(function (value) {
+ var numberFormat = new Intl.NumberFormat([locale + "-u-" + key + "-" + value]);
+ var options = numberFormat.resolvedOptions();
+ if (options.locale !== defaultLocale) {
+ $ERROR("Locale " + options.locale + " is affected by key " +
+ key + "; value " + value + ".");
+ }
+ if (JSON.stringify(options) !== defaultOptionsJSON) {
+ $ERROR("Resolved options " + JSON.stringify(options) + " are affected by key " +
+ key + "; value " + value + ".");
+ }
+ if (defaultFormatted !== numberFormat.format(input)) {
+ $ERROR("Formatted value " + numberFormat.format(input) + " is affected by key " +
+ key + "; value " + value + ".");
+ }
+ });
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.2/browser.js b/js/src/tests/test262/intl402/ch11/11.2/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/browser.js
diff --git a/js/src/tests/test262/intl402/ch11/11.2/shell.js b/js/src/tests/test262/intl402/ch11/11.2/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.2/shell.js
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.1.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.1.js
new file mode 100644
index 000000000..46c7fc519
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.1.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.constructor is the
+ * Intl.NumberFormat.
+ * @author: Roozbeh Pournader
+ */
+
+if (Intl.NumberFormat.prototype.constructor !== Intl.NumberFormat) {
+ $ERROR("Intl.NumberFormat.prototype.constructor is not the same as " +
+ "Intl.NumberFormat");
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_L15.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_L15.js
new file mode 100644
index 000000000..8e1c95835
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the function returned by Intl.NumberFormat.prototype.format
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(new Intl.NumberFormat().format, true, false, [], 1);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_ii.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_ii.js
new file mode 100644
index 000000000..cb284f43e
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_a_ii.js
@@ -0,0 +1,27 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.format
+ * converts other types to numbers.
+ * @author: Roozbeh Pournader
+ */
+
+var formatter = new Intl.NumberFormat();
+var testData = [undefined, null, true, '0.6666666', {valueOf: function () { return '0.1234567';}}];
+var number;
+var i, input, correctResult, result;
+
+for (i in testData) {
+ input = testData[i];
+ number = +input;
+ correctResult = formatter.format(number);
+
+ result = formatter.format(input);
+ if (result !== correctResult) {
+ $ERROR('Intl.NumberFormat does not convert other ' +
+ 'types to numbers. Input: "'+input+'" Output: "'+result+'" '+
+ 'Expected output: "'+correctResult+'"');
+ }
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_c.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_c.js
new file mode 100644
index 000000000..3fc877b31
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_1_c.js
@@ -0,0 +1,41 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that format function is bound to its Intl.NumberFormat.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234,
+ -0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501,
+ 123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000,
+ Infinity, -Infinity, NaN];
+var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]];
+var options = [
+ undefined,
+ {style: "percent"},
+ {style: "currency", currency: "EUR", currencyDisplay: "symbol"},
+ {style: "currency", currency: "IQD", currencyDisplay: "symbol"},
+ {style: "currency", currency: "KMF", currencyDisplay: "symbol"},
+ {style: "currency", currency: "CLF", currencyDisplay: "symbol"},
+ {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}
+];
+
+locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var formatObj = new Intl.NumberFormat(locales, options);
+ var formatFunc = formatObj.format;
+ numbers.forEach(function (number) {
+ var referenceFormatted = formatObj.format(number);
+ var formatted = formatFunc(number);
+ if (referenceFormatted !== formatted) {
+ $ERROR("format function produces different result than format method for locales " +
+ locales + "; options: " + (options ? JSON.stringify(options) : options) +
+ " : " + formatted + " vs. " + referenceFormatted + ".");
+ }
+ });
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_1.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_1.js
new file mode 100644
index 000000000..5f14e7772
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_1.js
@@ -0,0 +1,19 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.format
+ * doesn't treat all numbers as negative.
+ * @author: Roozbeh Pournader
+ */
+
+var formatter = new Intl.NumberFormat();
+
+if (formatter.format(1) === formatter.format(-1)) {
+ $ERROR('Intl.NumberFormat is formatting 1 and -1 the same way.');
+}
+
+if (formatter.format(-0) !== formatter.format(0)) {
+ $ERROR('Intl.NumberFormat is formatting signed zeros differently.');
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_2.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_2.js
new file mode 100644
index 000000000..ec11a679d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_2.js
@@ -0,0 +1,59 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.format
+ * handles NaN, Infinity, and -Infinity properly.
+ * @author: Roozbeh Pournader
+ */
+
+// FIXME: We are only listing Numeric_Type=Decimal. May need to add more
+// when the spec clarifies. Current as of Unicode 6.1.
+var hasUnicodeDigits = new RegExp('.*([' +
+ '0-9\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F' +
+ '\u09E6-\u09EF\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0BE6-\u0BEF' +
+ '\u0C66-\u0C6F\u0CE6-\u0CEF\u0D66-\u0D6F\u0E50-\u0E59\u0ED0-\u0ED9' +
+ '\u0F20-\u0F29\u1040-\u1049\u1090-\u1099\u17E0-\u17E9\u1810-\u1819' +
+ '\u1946-\u194F\u19D0-\u19D9\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59' +
+ '\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\uA620-\uA629\uA8D0-\uA8D9' +
+ '\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19' +
+ ']|' +
+ '\uD801[\uDCA0-\uDCA9]|' +
+ '\uD804[\uDC66-\uDC6F\uDCF0-\uDCF9\uDD36-\uDD3F\uDDD0-\uDDD9]|' +
+ '\uD805[\uDEC0-\uDEC9]|' +
+ '\uD835[\uDFCE-\uDFFF])');
+
+var formatter = new Intl.NumberFormat();
+var formattedNaN = formatter.format(NaN);
+var formattedInfinity = formatter.format(Infinity);
+var formattedNegativeInfinity = formatter.format(-Infinity);
+
+if (formattedNaN === formattedInfinity) {
+ $ERROR('Intl.NumberFormat formats NaN and Infinity the ' +
+ 'same way.');
+}
+
+if (formattedNaN === formattedNegativeInfinity) {
+ $ERROR('Intl.NumberFormat formats NaN and negative ' +
+ 'Infinity the same way.');
+}
+
+if (formattedInfinity === formattedNegativeInfinity) {
+ $ERROR('Intl.NumberFormat formats Infinity and ' +
+ 'negative Infinity the same way.');
+}
+
+if (hasUnicodeDigits.test(formattedNaN)) {
+ $ERROR('Intl.NumberFormat formats NaN using a digit.');
+}
+
+if (hasUnicodeDigits.test(formattedInfinity)) {
+ $ERROR('Intl.NumberFormat formats Infinity using a ' +
+ 'digit.');
+}
+
+if (hasUnicodeDigits.test(formattedNegativeInfinity)) {
+ $ERROR('Intl.NumberFormat formats negative Infinity ' +
+ 'using a digit.');
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_b.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_b.js
new file mode 100644
index 000000000..efe15575d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_b.js
@@ -0,0 +1,27 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.format
+ * formats percent values properly.
+ * @author: Roozbeh Pournader
+ */
+
+var numberFormatter = new Intl.NumberFormat();
+var percentFormatter = new Intl.NumberFormat(undefined, {style: 'percent'});
+
+var formattedTwenty = numberFormatter.format(20);
+var formattedTwentyPercent = percentFormatter.format(0.20);
+
+// FIXME: May not work for some theoretical locales where percents and
+// normal numbers are formatted using different numbering systems.
+if (formattedTwentyPercent.indexOf(formattedTwenty) === -1) {
+ $ERROR("Intl.NumberFormat's formatting of 20% does not include a " +
+ "formatting of 20 as a substring.");
+}
+
+// FIXME: Move this to somewhere appropriate
+if (percentFormatter.format(0.011) === percentFormatter.format(0.02)) {
+ $ERROR('Intl.NumberFormat is formatting 1.1% and 2% the same way.');
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_e.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_e.js
new file mode 100644
index 000000000..234ae6325
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_FN_3_e.js
@@ -0,0 +1,47 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.format
+ * supports all alternative numbering systems.
+ * @author: Roozbeh Pournader
+ */
+
+var numberingSystems = {
+ arab: 0x0660,
+ arabext: 0x06F0,
+ beng: 0x09E6,
+ deva: 0x0966,
+ fullwide: 0xFF10,
+ gujr: 0x0AE6,
+ guru: 0x0A66,
+ hanidec: [0x3007, 0x4E00, 0x4E8C, 0x4E09, 0x56DB,
+ 0x4E94, 0x516D, 0x4E03, 0x516B, 0x4E5D],
+ khmr: 0x17E0,
+ knda: 0x0CE6,
+ laoo: 0x0ED0,
+ latn: 0x0030,
+ mlym: 0x0D66,
+ mong: 0x1810,
+ mymr: 0x1040,
+ orya: 0x0B66,
+ tamldec: 0x0BE6,
+ telu: 0x0C66,
+ thai: 0x0E50,
+ tibt: 0x0F20
+};
+
+var options, formatter;
+var s, zeroCode, digitList;
+
+for (s in numberingSystems) {
+ zeroCode = numberingSystems[s];
+ if (typeof zeroCode === 'number') {
+ digitList = [zeroCode, zeroCode+1, zeroCode+2, zeroCode+3, zeroCode+4,
+ zeroCode+5, zeroCode+6, zeroCode+7, zeroCode+8, zeroCode+9];
+ numberingSystems[s] = digitList;
+ }
+}
+
+// FIXME: Unfinished
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_L15.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_L15.js
new file mode 100644
index 000000000..17b688b7a
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the getter for Intl.NumberFormat.prototype.format
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get , true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRF.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRF.js
new file mode 100644
index 000000000..c042a318a
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRF.js
@@ -0,0 +1,56 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the digits are determined correctly when specifying pre/post decimal digits.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale,
+ "ar", "de", "th", "ja"
+];
+var numberingSystems = [
+ "arab",
+ "latn",
+ "thai",
+ "hanidec"
+];
+var testData = {
+ "0": "000.0",
+ "-0": "000.0",
+ "123": "123.0",
+ "-123": "-123.0",
+ "12345": "12345.0",
+ "-12345": "-12345.0",
+ "123.45": "123.45",
+ "-123.45": "-123.45",
+ "123.444499": "123.444",
+ "-123.444499": "-123.444",
+ "123.444500": "123.445",
+ "-123.444500": "-123.445",
+ "123.44501": "123.445",
+ "-123.44501": "-123.445",
+ "0.001234": "000.001",
+ "-0.001234": "-000.001",
+ "0.00000000123": "000.0",
+ "-0.00000000123": "-000.0",
+ "0.00000000000000000000000000000123": "000.0",
+ "-0.00000000000000000000000000000123": "-000.0",
+ "1.2": "001.2",
+ "-1.2": "-001.2",
+ "0.0000000012344501": "000.0",
+ "-0.0000000012344501": "-000.0",
+ "123445.01": "123445.01",
+ "-123445.01": "-123445.01",
+ "12344501000000000000000000000000000": "12344501000000000000000000000000000.0",
+ "-12344501000000000000000000000000000": "-12344501000000000000000000000000000.0"
+};
+
+testNumberFormat(locales, numberingSystems,
+ {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3},
+ testData);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRP.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRP.js
new file mode 100644
index 000000000..9ab6550b6
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.2_TRP.js
@@ -0,0 +1,56 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the digits are determined correctly when specifying significant digits.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var locales = [
+ new Intl.NumberFormat().resolvedOptions().locale,
+ "ar", "de", "th", "ja"
+];
+var numberingSystems = [
+ "arab",
+ "latn",
+ "thai",
+ "hanidec"
+];
+var testData = {
+ "0": "0.00",
+ "-0": "0.00",
+ "123": "123",
+ "-123": "-123",
+ "12345": "12345",
+ "-12345": "-12345",
+ "123.45": "123.45",
+ "-123.45": "-123.45",
+ "123.44499": "123.44",
+ "-123.44499": "-123.44",
+ "123.44500": "123.45",
+ "-123.44500": "-123.45",
+ "123.44501": "123.45",
+ "-123.44501": "-123.45",
+ "0.001234": "0.001234",
+ "-0.001234": "-0.001234",
+ "0.00000000123": "0.00000000123",
+ "-0.00000000123": "-0.00000000123",
+ "0.00000000000000000000000000000123": "0.00000000000000000000000000000123",
+ "-0.00000000000000000000000000000123": "-0.00000000000000000000000000000123",
+ "1.2": "1.20",
+ "-1.2": "-1.20",
+ "0.0000000012344501": "0.0000000012345",
+ "-0.0000000012344501": "-0.0000000012345",
+ "123445.01": "123450",
+ "-123445.01": "-123450",
+ "12344501000000000000000000000000000": "12345000000000000000000000000000000",
+ "-12344501000000000000000000000000000": "-12345000000000000000000000000000000"
+};
+
+testNumberFormat(locales, numberingSystems,
+ {useGrouping: false, minimumSignificantDigits: 3, maximumSignificantDigits: 5},
+ testData);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.3.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.3.js
new file mode 100644
index 000000000..5a220ccc9
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.3.js
@@ -0,0 +1,31 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the object returned by Intl.NumberFormat.prototype.resolvedOptions
+ * has the right properties.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var actual = new Intl.NumberFormat().resolvedOptions();
+
+var actual2 = new Intl.NumberFormat().resolvedOptions();
+if (actual2 === actual) {
+ $ERROR("resolvedOptions returned the same object twice.");
+}
+
+// this assumes the default values where the specification provides them
+mustHaveProperty(actual, "locale", isCanonicalizedStructurallyValidLanguageTag);
+mustHaveProperty(actual, "numberingSystem", isValidNumberingSystem);
+mustHaveProperty(actual, "style", ["decimal"]);
+mustNotHaveProperty(actual, "currency");
+mustNotHaveProperty(actual, "currencyDisplay");
+mustHaveProperty(actual, "minimumIntegerDigits", [1]);
+mustHaveProperty(actual, "minimumFractionDigits", [0]);
+mustHaveProperty(actual, "maximumFractionDigits", [3]);
+mustNotHaveProperty(actual, "minimumSignificantDigits");
+mustNotHaveProperty(actual, "maximumSignificantDigits");
+mustHaveProperty(actual, "useGrouping", [true]);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3.3_L15.js b/js/src/tests/test262/intl402/ch11/11.3/11.3.3_L15.js
new file mode 100644
index 000000000..b9f95866d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype.resolvedOptions
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.NumberFormat.prototype.resolvedOptions, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3_L15.js b/js/src/tests/test262/intl402/ch11/11.3/11.3_L15.js
new file mode 100644
index 000000000..ac1f0c05d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.NumberFormat.prototype, false, false, ["constructor", "format", "resolvedOptions"]);
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3_a.js b/js/src/tests/test262/intl402/ch11/11.3/11.3_a.js
new file mode 100644
index 000000000..282a10bf6
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3_a.js
@@ -0,0 +1,16 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype is an object that
+ * has been initialized as an Intl.NumberFormat.
+ * @author: Roozbeh Pournader
+ */
+
+// test by calling a function that would fail if "this" were not an object
+// initialized as an Intl.NumberFormat
+if (typeof Intl.NumberFormat.prototype.format(0) !== "string") {
+ $ERROR("Intl.NumberFormat's prototype is not an object that has been " +
+ "initialized as an Intl.NumberFormat");
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/11.3_b.js b/js/src/tests/test262/intl402/ch11/11.3/11.3_b.js
new file mode 100644
index 000000000..6d0162b1d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/11.3_b.js
@@ -0,0 +1,33 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat.prototype functions throw a
+ * TypeError if called on a non-object value or an object that hasn't been
+ * initialized as a NumberFormat.
+ * @author Norbert Lindenberg
+ */
+
+var functions = {
+ "format getter": Object.getOwnPropertyDescriptor(Intl.NumberFormat.prototype, "format").get,
+ resolvedOptions: Intl.NumberFormat.prototype.resolvedOptions
+};
+var invalidTargets = [undefined, null, true, 0, "NumberFormat", [], {}];
+
+Object.getOwnPropertyNames(functions).forEach(function (functionName) {
+ var f = functions[functionName];
+ invalidTargets.forEach(function (target) {
+ var error;
+ try {
+ f.call(target);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Calling " + functionName + " on " + target + " was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Calling " + functionName + " on " + target + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch11/11.3/browser.js b/js/src/tests/test262/intl402/ch11/11.3/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/browser.js
diff --git a/js/src/tests/test262/intl402/ch11/11.3/shell.js b/js/src/tests/test262/intl402/ch11/11.3/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.3/shell.js
diff --git a/js/src/tests/test262/intl402/ch11/11.4/11.4_a.js b/js/src/tests/test262/intl402/ch11/11.4/11.4_a.js
new file mode 100644
index 000000000..a562879ec
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.4/11.4_a.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.NumberFormat instances have the specified properties.
+ * @author Norbert Lindenberg
+ */
+
+var obj = new Intl.NumberFormat();
+
+var toStringValue = Object.prototype.toString.call(obj);
+if (toStringValue !== "[object Object]") {
+ $ERROR("Intl.NumberFormat instance produces wrong [[Class]] - toString returns " + toStringValue + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch11/11.4/browser.js b/js/src/tests/test262/intl402/ch11/11.4/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.4/browser.js
diff --git a/js/src/tests/test262/intl402/ch11/11.4/shell.js b/js/src/tests/test262/intl402/ch11/11.4/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/11.4/shell.js
diff --git a/js/src/tests/test262/intl402/ch11/browser.js b/js/src/tests/test262/intl402/ch11/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/browser.js
diff --git a/js/src/tests/test262/intl402/ch11/shell.js b/js/src/tests/test262/intl402/ch11/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch11/shell.js
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_1.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_1.js
new file mode 100644
index 000000000..8136fb421
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_1.js
@@ -0,0 +1,43 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that an object can't be re-initialized as a DateTimeFormat.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testWithIntlConstructors(function (Constructor) {
+ var obj, error;
+
+ // variant 1: use constructor in a "new" expression
+ obj = new Constructor();
+ try {
+ Intl.DateTimeFormat.call(obj);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Re-initializing object created with \"new\" as DateTimeFormat was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Re-initializing object created with \"new\" as DateTimeFormat was rejected with wrong error " + error.name + ".");
+ }
+
+ // variant 2: use constructor as a function
+ obj = Constructor.call({});
+ error = undefined;
+ try {
+ Intl.DateTimeFormat.call(obj);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Re-initializing object created with constructor as function as DateTimeFormat was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Re-initializing object created with constructor as function as DateTimeFormat was rejected with wrong error " + error.name + ".");
+ }
+
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_18.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_18.js
new file mode 100644
index 000000000..f75ea1e32
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_18.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option hour12 is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.DateTimeFormat, "hour12", "boolean", undefined, undefined,
+ {extra: {any: {hour: "numeric", minute: "numeric"}}});
+testOption(Intl.DateTimeFormat, "hour12", "boolean", undefined, undefined,
+ {noReturn: true});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_22.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_22.js
new file mode 100644
index 000000000..5c317c6b9
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_22.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["weekday", "era", "year", "month", "day", "hour", "minute", "second", "timeZone"]);
+
+var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
+ $ERROR("DateTimeFormat returns invalid locale " + locale + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_23.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_23.js
new file mode 100644
index 000000000..d26e1d28c
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_23.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the options for the date and time components are processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+getDateTimeComponents().forEach(function (component) {
+ testOption(Intl.DateTimeFormat, component, "string", getDateTimeComponentValues(component), undefined, {isILD: true});
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_25.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_25.js
new file mode 100644
index 000000000..ccaf7be03
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_25.js
@@ -0,0 +1,12 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option formatMatcher is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.DateTimeFormat, "formatMatcher", "string", ["basic", "best fit"], "best fit", {noReturn: true});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_5.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_5.js
new file mode 100644
index 000000000..c6b166814
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_5.js
@@ -0,0 +1,18 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["localeMatcher"]);
+
+var locale = new Intl.DateTimeFormat(undefined, {localeMatcher: "lookup"}).resolvedOptions().locale;
+if (!isCanonicalizedStructurallyValidLanguageTag(locale)) {
+ $ERROR("DateTimeFormat returns invalid locale " + locale + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_6.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_6.js
new file mode 100644
index 000000000..148ca02f6
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_6.js
@@ -0,0 +1,12 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the option localeMatcher is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testOption(Intl.DateTimeFormat, "localeMatcher", "string", ["lookup", "best fit"], "best fit", {noReturn: true});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_TDTO.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_TDTO.js
new file mode 100644
index 000000000..5df6a1cf2
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_TDTO.js
@@ -0,0 +1,107 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the set of options for the date and time components is processed correctly.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var locales = [[], ["zh-Hans-CN"], ["hi-IN"], ["en-US"], ["id-ID"]];
+var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))];
+
+function testWithDateTimeFormat(options, expected) {
+ locales.forEach(function (locales) {
+ var format = new Intl.DateTimeFormat(locales, options);
+ var resolvedOptions = format.resolvedOptions();
+ getDateTimeComponents().forEach(function (component) {
+ if (resolvedOptions.hasOwnProperty(component)) {
+ if (!expected.hasOwnProperty(component)) {
+ $ERROR("Unrequested component " + component +
+ " added to expected subset " + JSON.stringify(expected) +
+ "; locales " + locales + ", options " +
+ (options ? JSON.stringify(options) : options) + ".");
+ }
+ } else {
+ if (expected.hasOwnProperty(component)) {
+ $ERROR("Missing component " + component +
+ " from expected subset " + JSON.stringify(expected) +
+ "; locales " + locales + ", options " +
+ (options ? JSON.stringify(options) : options) + ".");
+ }
+ }
+ });
+ });
+}
+
+function testWithToLocale(f, options, expected) {
+ // expected can be either one subset or an array of possible subsets
+ if (expected.length === undefined) {
+ expected = [expected];
+ }
+ locales.forEach(function (locales) {
+ dates.forEach(function (date) {
+ var formatted = Date.prototype[f].call(date, locales, options);
+ var expectedStrings = [];
+ expected.forEach(function (expected) {
+ var referenceFormat = new Intl.DateTimeFormat(locales, expected);
+ expectedStrings.push(referenceFormat.format(date));
+ });
+ if (expectedStrings.indexOf(formatted) === -1) {
+ $ERROR("Function " + f + " did not return expected string for locales " +
+ locales + ", options " + (options? JSON.stringify(options) : options) +
+ "; expected " +
+ (expectedStrings.length === 1 ? expectedStrings[0] : "one of " + expectedStrings) +
+ ", got " + formatted + ".");
+ }
+ });
+ });
+}
+
+// any/date: steps 5a, 6a, 7a
+testWithDateTimeFormat(undefined, {year: "numeric", month: "numeric", day: "numeric"});
+
+// any/date: steps 5a, 6a
+testWithDateTimeFormat({year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"});
+
+// any/date: steps 5a, 6a
+testWithDateTimeFormat({hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"});
+
+// any/all: steps 5a, 6a, 7a, 8a
+testWithToLocale("toLocaleString", undefined, [
+ // the first one is not guaranteed to be supported; the second one is
+ {year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"},
+ {weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}
+]);
+
+// any/all: steps 5a, 6a
+testWithToLocale("toLocaleString", {year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"});
+
+// any/all: steps 5a, 6a
+testWithToLocale("toLocaleString", {hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"});
+
+// date/date: steps 5a, 7a
+testWithToLocale("toLocaleDateString", undefined, {year: "numeric", month: "numeric", day: "numeric"});
+
+// date/date: steps 5a
+testWithToLocale("toLocaleDateString", {year: "numeric", month: "numeric"}, {year: "numeric", month: "numeric"});
+
+// date/date: steps 5a, 7a
+testWithToLocale("toLocaleDateString", {hour: "numeric", minute: "numeric", second: "numeric"}, [
+ // the first one is not guaranteed to be supported; the second one is
+ {year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"},
+ {weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}
+]);
+
+// time/time: steps 6a, 8a
+testWithToLocale("toLocaleTimeString", undefined, {hour: "numeric", minute: "numeric", second: "numeric"});
+
+// time/time: steps 6a, 8a
+testWithToLocale("toLocaleTimeString", {weekday: "short", year: "numeric", month: "numeric", day: "numeric"},
+ {weekday: "short", year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"});
+
+// time/time: steps 6a
+testWithToLocale("toLocaleTimeString", {hour: "numeric", minute: "numeric"}, {hour: "numeric", minute: "numeric"});
+
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.1_a.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_a.js
new file mode 100644
index 000000000..4f5f3dbf5
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.1_a.js
@@ -0,0 +1,18 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that constructing a DateTimeFormat doesn't create or modify
+ * unwanted properties on the RegExp constructor.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.DateTimeFormat("de-DE-u-ca-gregory");
+});
+
+testForUnwantedRegExpChanges(function () {
+ new Intl.DateTimeFormat("de-DE-u-ca-gregory", {timeZone: "UTC"});
+});
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.2.1_4.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.2.1_4.js
new file mode 100644
index 000000000..cb22be8f9
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.2.1_4.js
@@ -0,0 +1,21 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that for non-object values passed as this to DateTimeFormat a
+ * wrapper object will be initialized and returned.
+ * @author Norbert Lindenberg
+ */
+
+var thisValues = [true, 42, "国際化"];
+
+thisValues.forEach(function (value) {
+ var format = Intl.DateTimeFormat.call(value);
+ // check that the returned object functions as a date-time format
+ var referenceFormat = new Intl.DateTimeFormat();
+ if (Intl.DateTimeFormat.prototype.format.call(format, new Date(111111111)) !== referenceFormat.format(new Date(111111111))) {
+ $ERROR("DateTimeFormat initialized from " + value + " doesn't behave like normal date-time format.");
+ }
+ return true;
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.2.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.2.js
new file mode 100644
index 000000000..3ffed2ec8
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.2.js
@@ -0,0 +1,30 @@
+// Copyright 2011-2012 Norbert Lindenberg. All rights reserved.
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat can be subclassed.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+// get a date-time format and have it format an array of dates for comparison with the subclass
+var locales = ["tlh", "id", "en"];
+var a = [new Date(0), Date.now(), new Date(Date.parse("1989-11-09T17:57:00Z"))];
+var referenceDateTimeFormat = new Intl.DateTimeFormat(locales);
+var referenceFormatted = a.map(referenceDateTimeFormat.format);
+
+function MyDateTimeFormat(locales, options) {
+ Intl.DateTimeFormat.call(this, locales, options);
+ // could initialize MyDateTimeFormat properties
+}
+
+MyDateTimeFormat.prototype = Object.create(Intl.DateTimeFormat.prototype);
+MyDateTimeFormat.prototype.constructor = MyDateTimeFormat;
+// could add methods to MyDateTimeFormat.prototype
+
+var format = new MyDateTimeFormat(locales);
+var actual = a.map(format.format);
+testArraysAreSame(referenceFormatted, actual);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1.3.js b/js/src/tests/test262/intl402/ch12/12.1/12.1.3.js
new file mode 100644
index 000000000..5e70bbb8f
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1.3.js
@@ -0,0 +1,19 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that objects constructed by Intl.DateTimeFormat have the specified internal properties.
+ * @author Norbert Lindenberg
+ */
+
+var obj = new Intl.DateTimeFormat();
+
+var actualPrototype = Object.getPrototypeOf(obj);
+if (actualPrototype !== Intl.DateTimeFormat.prototype) {
+ $ERROR("Prototype of object constructed by Intl.DateTimeFormat isn't Intl.DateTimeFormat.prototype; got " + actualPrototype);
+}
+
+if (!Object.isExtensible(obj)) {
+ $ERROR("Object constructed by Intl.DateTimeFormat must be extensible.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/12.1_L15.js b/js/src/tests/test262/intl402/ch12/12.1/12.1_L15.js
new file mode 100644
index 000000000..46c4f5f50
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/12.1_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.DateTimeFormat, true, true, ["supportedLocalesOf"], 0);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.1/browser.js b/js/src/tests/test262/intl402/ch12/12.1/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/browser.js
diff --git a/js/src/tests/test262/intl402/ch12/12.1/shell.js b/js/src/tests/test262/intl402/ch12/12.1/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.1/shell.js
diff --git a/js/src/tests/test262/intl402/ch12/12.2/12.2.1.js b/js/src/tests/test262/intl402/ch12/12.2/12.2.1.js
new file mode 100644
index 000000000..3590c0a9d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/12.2.1.js
@@ -0,0 +1,22 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.prototype has the required attributes.
+ * @author Norbert Lindenberg
+ */
+
+var desc = Object.getOwnPropertyDescriptor(Intl.DateTimeFormat, "prototype");
+if (desc === undefined) {
+ $ERROR("Intl.DateTimeFormat.prototype is not defined.");
+}
+if (desc.writable) {
+ $ERROR("Intl.DateTimeFormat.prototype must not be writable.");
+}
+if (desc.enumerable) {
+ $ERROR("Intl.DateTimeFormat.prototype must not be enumerable.");
+}
+if (desc.configurable) {
+ $ERROR("Intl.DateTimeFormat.prototype must not be configurable.");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.2/12.2.2_L15.js b/js/src/tests/test262/intl402/ch12/12.2/12.2.2_L15.js
new file mode 100644
index 000000000..8b21df1fd
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/12.2.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.supportedLocalesOf
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.DateTimeFormat.supportedLocalesOf, true, false, [], 1);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.2/12.2.2_a.js b/js/src/tests/test262/intl402/ch12/12.2/12.2.2_a.js
new file mode 100644
index 000000000..42eedc0a1
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/12.2.2_a.js
@@ -0,0 +1,28 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat has a supportedLocalesOf
+ * property, and it works as planned.
+ * @author: Roozbeh Pournader
+ */
+
+var defaultLocale = new Intl.DateTimeFormat().resolvedOptions().locale;
+var notSupported = 'zxx'; // "no linguistic content"
+var requestedLocales = [defaultLocale, notSupported];
+
+var supportedLocales;
+
+if (!Intl.DateTimeFormat.hasOwnProperty('supportedLocalesOf')) {
+ $ERROR("Intl.DateTimeFormat doesn't have a supportedLocalesOf property.");
+}
+
+supportedLocales = Intl.DateTimeFormat.supportedLocalesOf(requestedLocales);
+if (supportedLocales.length !== 1) {
+ $ERROR('The length of supported locales list is not 1.');
+}
+
+if (supportedLocales[0] !== defaultLocale) {
+ $ERROR('The default locale is not returned in the supported list.');
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.2/12.2.2_b.js b/js/src/tests/test262/intl402/ch12/12.2/12.2.2_b.js
new file mode 100644
index 000000000..06bc8027e
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/12.2.2_b.js
@@ -0,0 +1,13 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.supportedLocalesOf
+ * doesn't access arguments that it's not given.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintDataProperty(Object.prototype, "1");
+new Intl.DateTimeFormat("und");
diff --git a/js/src/tests/test262/intl402/ch12/12.2/12.2.3_b.js b/js/src/tests/test262/intl402/ch12/12.2/12.2.3_b.js
new file mode 100644
index 000000000..65fd9dc5f
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/12.2.3_b.js
@@ -0,0 +1,47 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat does not accept Unicode locale
+ * extension keys and values that are not allowed.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var locales = ["ja-JP", "zh-Hans-CN", "zh-Hant-TW"];
+var input = new Date(Date.parse("1989-11-09T17:57:00Z"));
+
+locales.forEach(function (locale) {
+ var defaultDateTimeFormat = new Intl.DateTimeFormat([locale]);
+ var defaultOptions = defaultDateTimeFormat.resolvedOptions();
+ var defaultOptionsJSON = JSON.stringify(defaultOptions);
+ var defaultLocale = defaultOptions.locale;
+ var defaultFormatted = defaultDateTimeFormat.format(input);
+
+ var keyValues = {
+ "cu": ["USD", "EUR", "JPY", "CNY", "TWD", "invalid"], // DateTimeFormat internally uses NumberFormat
+ "nu": ["native", "traditio", "finance", "invalid"],
+ "tz": ["usnavajo", "utcw01", "aumel", "uslax", "usnyc", "deber", "invalid"]
+ };
+
+ Object.getOwnPropertyNames(keyValues).forEach(function (key) {
+ keyValues[key].forEach(function (value) {
+ var dateTimeFormat = new Intl.DateTimeFormat([locale + "-u-" + key + "-" + value]);
+ var options = dateTimeFormat.resolvedOptions();
+ if (options.locale !== defaultLocale) {
+ $ERROR("Locale " + options.locale + " is affected by key " +
+ key + "; value " + value + ".");
+ }
+ if (JSON.stringify(options) !== defaultOptionsJSON) {
+ $ERROR("Resolved options " + JSON.stringify(options) + " are affected by key " +
+ key + "; value " + value + ".");
+ }
+ if (defaultFormatted !== dateTimeFormat.format(input)) {
+ $ERROR("Formatted value " + dateTimeFormat.format(input) + " is affected by key " +
+ key + "; value " + value + ".");
+ }
+ });
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.2/12.2.3_c.js b/js/src/tests/test262/intl402/ch12/12.2/12.2.3_c.js
new file mode 100644
index 000000000..0aced6ca9
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/12.2.3_c.js
@@ -0,0 +1,52 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat provides the required date-time
+ * format component subsets.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var locales = ["de-DE", "en-US", "hi-IN", "id-ID", "ja-JP", "th-TH", "zh-Hans-CN", "zh-Hant-TW", "zxx"];
+var subsets = [
+ {weekday: "long", year: "numeric", month: "numeric", day: "numeric",
+ hour: "numeric", minute: "numeric", second: "numeric"},
+ {weekday: "long", year: "numeric", month: "numeric", day: "numeric"},
+ {year: "numeric", month: "numeric", day: "numeric"},
+ {year: "numeric", month: "numeric"},
+ {month: "numeric", day: "numeric"},
+ {hour: "numeric", minute: "numeric", second: "numeric"},
+ {hour: "numeric", minute: "numeric"}
+];
+
+locales.forEach(function (locale) {
+ subsets.forEach(function (subset) {
+ var format = new Intl.DateTimeFormat([locale], subset);
+ var actual = format.resolvedOptions();
+ getDateTimeComponents().forEach(function (component) {
+ if (actual.hasOwnProperty(component)) {
+ if (!subset.hasOwnProperty(component)) {
+ $ERROR("Unrequested component " + component +
+ " added to requested subset " + JSON.stringify(subset) +
+ "; locale " + locale + ".");
+ }
+ try {
+ testValidDateTimeComponentValue(component, actual[component]);
+ } catch (e) {
+ e.message += " (Testing locale " + locale + "; subset " +
+ JSON.stringify(subset) + ")";
+ throw e;
+ }
+ } else {
+ if (subset.hasOwnProperty(component)) {
+ $ERROR("Missing component " + component +
+ " from requested subset " + JSON.stringify(subset) +
+ "; locale " + locale + ".");
+ }
+ }
+ });
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.2/browser.js b/js/src/tests/test262/intl402/ch12/12.2/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/browser.js
diff --git a/js/src/tests/test262/intl402/ch12/12.2/shell.js b/js/src/tests/test262/intl402/ch12/12.2/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.2/shell.js
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.1.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.1.js
new file mode 100644
index 000000000..1755dd64b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.1.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.prototype.constructor is the
+ * Intl.DateTimeFormat.
+ * @author: Roozbeh Pournader
+ */
+
+if (Intl.DateTimeFormat.prototype.constructor !== Intl.DateTimeFormat) {
+ $ERROR("Intl.DateTimeFormat.prototype.constructor is not the same as " +
+ "Intl.DateTimeFormat");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_a_L15.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_a_L15.js
new file mode 100644
index 000000000..2fb768d09
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_a_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the function returned by Intl.DateTimeFormat.prototype.format
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(new Intl.DateTimeFormat().format, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_c.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_c.js
new file mode 100644
index 000000000..d4b9f891f
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_1_c.js
@@ -0,0 +1,34 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that format function is bound to its Intl.DateTimeFormat.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))];
+var locales = [undefined, ["de"], ["th-u-ca-gregory-nu-thai"], ["en"], ["ja-u-ca-japanese"], ["ar-u-ca-islamicc-nu-arab"]];
+var options = [
+ undefined,
+ {hour12: false},
+ {month: "long", day: "numeric", hour: "2-digit", minute: "2-digit"}
+];
+
+locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var formatObj = new Intl.DateTimeFormat(locales, options);
+ var formatFunc = formatObj.format;
+ dates.forEach(function (date) {
+ var referenceFormatted = formatObj.format(date);
+ var formatted = formatFunc(date);
+ if (referenceFormatted !== formatted) {
+ $ERROR("format function produces different result than format method for locales " +
+ locales + "; options: " + (options ? JSON.stringify(options) : options) +
+ " : " + formatted + " vs. " + referenceFormatted + ".");
+ }
+ });
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_1.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_1.js
new file mode 100644
index 000000000..d643d7928
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_1.js
@@ -0,0 +1,26 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that format handles non-finite values correctly.
+ * @author Norbert Lindenberg
+ */
+
+var invalidValues = [NaN, Infinity, -Infinity];
+
+var format = new Intl.DateTimeFormat();
+
+invalidValues.forEach(function (value) {
+ var error;
+ try {
+ var result = format.format(value);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Invalid value " + value + " was not rejected.");
+ } else if (error.name !== "RangeError") {
+ $ERROR("Invalid value " + value + " was rejected with wrong error " + error.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_7_a_iv.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_7_a_iv.js
new file mode 100644
index 000000000..f13878403
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_FDT_7_a_iv.js
@@ -0,0 +1,32 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that format uses a proleptic Gregorian calendar with no year 0.
+ * @author Norbert Lindenberg
+ */
+
+var dates = [
+ 0, // January 1, 1970
+ -62151602400000, // in June 1 BC
+ -8640000000000000 // beginning of ECMAScript time
+];
+
+var format = new Intl.DateTimeFormat(["en-US"], {year: "numeric", month: "long", timeZone: "UTC"});
+
+// this test requires a Gregorian calendar, which we usually find in the US
+if (format.resolvedOptions().calendar !== "gregory") {
+ $ERROR("Internal error: Didn't find Gregorian calendar");
+}
+
+dates.forEach(function (date) {
+ var year = new Date(date).getUTCFullYear();
+ var expectedYear = year <= 0 ? 1 - year : year;
+ var expectedYearString = expectedYear.toLocaleString(["en-US"], {useGrouping: false});
+ var dateString = format.format(date);
+ if (dateString.indexOf(expectedYearString) === -1) {
+ $ERROR("Formatted year doesn't contain expected year – expected " +
+ expectedYearString + ", got " + dateString + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.2_L15.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_L15.js
new file mode 100644
index 000000000..73d309e26
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the getter for Intl.DateTimeFormat.prototype.format
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get , true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.2_TLT_2.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_TLT_2.js
new file mode 100644
index 000000000..bf0a8ed36
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.2_TLT_2.js
@@ -0,0 +1,16 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that the behavior of a Record is not affected by adversarial
+ * changes to Object.prototype.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintProperties(["weekday", "era", "year", "month", "day", "hour", "minute", "second", "inDST"]);
+
+var format = new Intl.DateTimeFormat();
+var time = format.format();
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.3.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.3.js
new file mode 100644
index 000000000..b5735c350
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.3.js
@@ -0,0 +1,52 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that the object returned by Intl.DateTimeFormat.prototype.resolvedOptions
+ * has the right properties.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var actual = new Intl.DateTimeFormat().resolvedOptions();
+
+var actual2 = new Intl.DateTimeFormat().resolvedOptions();
+if (actual2 === actual) {
+ $ERROR("resolvedOptions returned the same object twice.");
+}
+
+// source: CLDR file common/bcp47/calendar.xml; version CLDR 21.
+var calendars = [
+ "buddhist",
+ "chinese",
+ "coptic",
+ "ethioaa",
+ "ethiopic",
+ "gregory",
+ "hebrew",
+ "indian",
+ "islamic",
+ "islamicc",
+ "iso8601",
+ "japanese",
+ "persian",
+ "roc"
+];
+
+// this assumes the default values where the specification provides them
+mustHaveProperty(actual, "locale", isCanonicalizedStructurallyValidLanguageTag);
+mustHaveProperty(actual, "calendar", calendars);
+mustHaveProperty(actual, "numberingSystem", isValidNumberingSystem);
+mustHaveProperty(actual, "timeZone", [undefined]);
+mustNotHaveProperty(actual, "weekday");
+mustNotHaveProperty(actual, "era");
+mustHaveProperty(actual, "year", ["2-digit", "numeric"]);
+mustHaveProperty(actual, "month", ["2-digit", "numeric", "narrow", "short", "long"]);
+mustHaveProperty(actual, "day", ["2-digit", "numeric"]);
+mustNotHaveProperty(actual, "hour");
+mustNotHaveProperty(actual, "minute");
+mustNotHaveProperty(actual, "second");
+mustNotHaveProperty(actual, "timeZoneName");
+mustNotHaveProperty(actual, "hour12");
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3.3_L15.js b/js/src/tests/test262/intl402/ch12/12.3/12.3.3_L15.js
new file mode 100644
index 000000000..1b4079ebe
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.prototype.resolvedOptions
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.DateTimeFormat.prototype.resolvedOptions, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3_L15.js b/js/src/tests/test262/intl402/ch12/12.3/12.3_L15.js
new file mode 100644
index 000000000..55f1c16ca
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.prototype
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Intl.DateTimeFormat.prototype, false, false, ["constructor", "format", "resolvedOptions"]);
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3_a.js b/js/src/tests/test262/intl402/ch12/12.3/12.3_a.js
new file mode 100644
index 000000000..e1d795b91
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3_a.js
@@ -0,0 +1,16 @@
+// Copyright 2012 Google Inc. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.prototype is an object that
+ * has been initialized as an Intl.DateTimeFormat.
+ * @author: Roozbeh Pournader
+ */
+
+// test by calling a function that would fail if "this" were not an object
+// initialized as an Intl.DateTimeFormat
+if (typeof Intl.DateTimeFormat.prototype.format(0) !== "string") {
+ $ERROR("Intl.DateTimeFormat's prototype is not an object that has been " +
+ "initialized as an Intl.DateTimeFormat");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/12.3_b.js b/js/src/tests/test262/intl402/ch12/12.3/12.3_b.js
new file mode 100644
index 000000000..d905bf571
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/12.3_b.js
@@ -0,0 +1,33 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat.prototype functions throw a
+ * TypeError if called on a non-object value or an object that hasn't been
+ * initialized as a DateTimeFormat.
+ * @author Norbert Lindenberg
+ */
+
+var functions = {
+ "format getter": Object.getOwnPropertyDescriptor(Intl.DateTimeFormat.prototype, "format").get,
+ resolvedOptions: Intl.DateTimeFormat.prototype.resolvedOptions
+};
+var invalidTargets = [undefined, null, true, 0, "DateTimeFormat", [], {}];
+
+Object.getOwnPropertyNames(functions).forEach(function (functionName) {
+ var f = functions[functionName];
+ invalidTargets.forEach(function (target) {
+ var error;
+ try {
+ f.call(target);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Calling " + functionName + " on " + target + " was not rejected.");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Calling " + functionName + " on " + target + " was rejected with wrong error " + error.name + ".");
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch12/12.3/browser.js b/js/src/tests/test262/intl402/ch12/12.3/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/browser.js
diff --git a/js/src/tests/test262/intl402/ch12/12.3/shell.js b/js/src/tests/test262/intl402/ch12/12.3/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.3/shell.js
diff --git a/js/src/tests/test262/intl402/ch12/12.4/12.4_a.js b/js/src/tests/test262/intl402/ch12/12.4/12.4_a.js
new file mode 100644
index 000000000..8e8d5954c
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.4/12.4_a.js
@@ -0,0 +1,15 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Intl.DateTimeFormat instances have the specified properties.
+ * @author Norbert Lindenberg
+ */
+
+var obj = new Intl.DateTimeFormat();
+
+var toStringValue = Object.prototype.toString.call(obj);
+if (toStringValue !== "[object Object]") {
+ $ERROR("Intl.DateTimeFormat instance produces wrong [[Class]] - toString returns " + toStringValue + ".");
+}
+
diff --git a/js/src/tests/test262/intl402/ch12/12.4/browser.js b/js/src/tests/test262/intl402/ch12/12.4/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.4/browser.js
diff --git a/js/src/tests/test262/intl402/ch12/12.4/shell.js b/js/src/tests/test262/intl402/ch12/12.4/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/12.4/shell.js
diff --git a/js/src/tests/test262/intl402/ch12/browser.js b/js/src/tests/test262/intl402/ch12/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/browser.js
diff --git a/js/src/tests/test262/intl402/ch12/shell.js b/js/src/tests/test262/intl402/ch12/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch12/shell.js
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_1.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_1.js
new file mode 100644
index 000000000..37be9711b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_1.js
@@ -0,0 +1,24 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that localeCompare rejects values that can't be coerced to an object.
+ * @author Norbert Lindenberg
+ */
+
+var invalidValues = [undefined, null];
+
+invalidValues.forEach(function (value) {
+ var error;
+ try {
+ var result = String.prototype.localeCompare.call(value, "");
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("String.prototype.localeCompare did not reject this = " + value + ".");
+ } else if (error.name !== "TypeError") {
+ $ERROR("String.prototype.localeCompare rejected this = " + value + " with wrong error " + error.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_2.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_2.js
new file mode 100644
index 000000000..bad7c0fdd
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_2.js
@@ -0,0 +1,26 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that localeCompare coerces this to a string.
+ * @author Norbert Lindenberg
+ */
+
+var thisValues = [true, 5, "hello", {toString: function () { return "good bye"; }}];
+var thatValues = ["true", "5", "hello", "good bye"];
+
+var i;
+for (i = 0; i < thisValues.length; i++) {
+ var j;
+ for (j = 0; j < thatValues.length; j++) {
+ var result = String.prototype.localeCompare.call(thisValues[i], thatValues[j]);
+ if ((result === 0) !== (i === j)) {
+ if (result === 0) {
+ $ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as equal.");
+ } else {
+ $ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as different.");
+ }
+ }
+ }
+}
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_1.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_1.js
new file mode 100644
index 000000000..113a2d9aa
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_1.js
@@ -0,0 +1,26 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that localeCompare coerces that to a string.
+ * @author Norbert Lindenberg
+ */
+
+var thisValues = ["true", "5", "hello", "good bye"];
+var thatValues = [true, 5, "hello", {toString: function () { return "good bye"; }}];
+
+var i;
+for (i = 0; i < thisValues.length; i++) {
+ var j;
+ for (j = 0; j < thatValues.length; j++) {
+ var result = String.prototype.localeCompare.call(thisValues[i], thatValues[j]);
+ if ((result === 0) !== (i === j)) {
+ if (result === 0) {
+ $ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as equal.");
+ } else {
+ $ERROR("localeCompare treats " + thisValues[i] + " and " + thatValues[j] + " as different.");
+ }
+ }
+ }
+}
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_2.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_2.js
new file mode 100644
index 000000000..441166c9f
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_3_2.js
@@ -0,0 +1,22 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that String.prototype.localeCompare treats a missing
+ * "that" argument, undefined, and "undefined" as equivalent.
+ * @author Norbert Lindenberg
+ */
+
+var thisValues = ["a", "t", "u", "undefined", "UNDEFINED", "nicht definiert", "xyz", "未定义"];
+
+var i;
+for (i = 0; i < thisValues.length; i++) {
+ var thisValue = thisValues[i];
+ if (thisValue.localeCompare() !== thisValue.localeCompare(undefined)) {
+ $ERROR("String.prototype.localeCompare does not treat missing 'that' argument as undefined.");
+ }
+ if (thisValue.localeCompare(undefined) !== thisValue.localeCompare("undefined")) {
+ $ERROR("String.prototype.localeCompare does not treat undefined 'that' argument as \"undefined\".");
+ }
+}
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_1.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_1.js
new file mode 100644
index 000000000..30607d317
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_1.js
@@ -0,0 +1,65 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that String.prototype.localeCompare throws the same exceptions as Intl.Collator.
+ * @author Norbert Lindenberg
+ */
+
+var locales = [null, [NaN], ["i"], ["de_DE"]];
+var options = [
+ {localeMatcher: null},
+ {usage: "invalid"},
+ {sensitivity: "invalid"}
+];
+
+locales.forEach(function (locales) {
+ var referenceError, error;
+ try {
+ var collator = new Intl.Collator(locales);
+ } catch (e) {
+ referenceError = e;
+ }
+ if (referenceError === undefined) {
+ $ERROR("Internal error: Expected exception was not thrown by Intl.Collator for locales " + locales + ".");
+ }
+
+ try {
+ var result = "".localeCompare("", locales);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("String.prototype.localeCompare didn't throw exception for locales " + locales + ".");
+ } else if (error.name !== referenceError.name) {
+ $ERROR("String.prototype.localeCompare threw exception " + error.name +
+ " for locales " + locales + "; expected " + referenceError.name + ".");
+ }
+});
+
+options.forEach(function (options) {
+ var referenceError, error;
+ try {
+ var collator = new Intl.Collator([], options);
+ } catch (e) {
+ referenceError = e;
+ }
+ if (referenceError === undefined) {
+ $ERROR("Internal error: Expected exception was not thrown by Intl.Collator for options " +
+ JSON.stringify(options) + ".");
+ }
+
+ try {
+ var result = "".localeCompare("", [], options);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("String.prototype.localeCompare didn't throw exception for options " +
+ JSON.stringify(options) + ".");
+ } else if (error.name !== referenceError.name) {
+ $ERROR("String.prototype.localeCompare threw exception " + error.name +
+ " for options " + JSON.stringify(options) + "; expected " + referenceError.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_2.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_2.js
new file mode 100644
index 000000000..481a7803b
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_6_2.js
@@ -0,0 +1,13 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that String.prototype.localeCompare uses the standard
+ * built-in Intl.Collator constructor.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintDataProperty(Intl, "Collator");
+"a".localeCompare("b");
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_7.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_7.js
new file mode 100644
index 000000000..f0c588f64
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_7.js
@@ -0,0 +1,33 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that localeCompare produces the same results as Intl.Collator.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var strings = ["d", "O", "od", "oe", "of", "ö", "o\u0308", "X", "y", "Z", "Z.", "𠮷野家", "吉野家", "!A", "A", "b", "C"];
+var locales = [undefined, ["de"], ["de-u-co-phonebk"], ["en"], ["ja"], ["sv"]];
+var options = [
+ undefined,
+ {usage: "search"},
+ {sensitivity: "base", ignorePunctuation: true}
+];
+
+locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var referenceCollator = new Intl.Collator(locales, options);
+ var referenceSorted = strings.slice().sort(referenceCollator.compare);
+
+ strings.sort(function (a, b) { return a.localeCompare(b, locales, options); });
+ try {
+ testArraysAreSame(referenceSorted, strings);
+ } catch (e) {
+ e.message += " (Testing with locales " + locales + "; options " + JSON.stringify(options) + ".)";
+ throw e;
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/13.1.1_L15.js b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_L15.js
new file mode 100644
index 000000000..d921de000
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/13.1.1_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that String.prototype.localeCompare
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(String.prototype.localeCompare, true, false, [], 1);
+
diff --git a/js/src/tests/test262/intl402/ch13/13.1/browser.js b/js/src/tests/test262/intl402/ch13/13.1/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/browser.js
diff --git a/js/src/tests/test262/intl402/ch13/13.1/shell.js b/js/src/tests/test262/intl402/ch13/13.1/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.1/shell.js
diff --git a/js/src/tests/test262/intl402/ch13/13.2/13.2.1_1.js b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_1.js
new file mode 100644
index 000000000..da1ee8fe5
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_1.js
@@ -0,0 +1,37 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that toLocaleString handles "this Number value" correctly.
+ * @author Norbert Lindenberg
+ */
+
+var invalidValues = [undefined, null, "5", false, {valueOf: function () { return 5; }}];
+var validValues = [5, NaN, -1234567.89, -Infinity];
+
+invalidValues.forEach(function (value) {
+ var error;
+ try {
+ var result = Number.prototype.toLocaleString.call(value);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Number.prototype.toLocaleString did not reject this = " + value + ".");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Number.prototype.toLocaleString rejected this = " + value + " with wrong error " + error.name + ".");
+ }
+});
+
+// for valid values, just check that a Number value and the corresponding
+// Number object get the same result.
+validValues.forEach(function (value) {
+ var Constructor = Number; // to keep jshint happy
+ var valueResult = Number.prototype.toLocaleString.call(value);
+ var objectResult = Number.prototype.toLocaleString.call(new Constructor(value));
+ if (valueResult !== objectResult) {
+ $ERROR("Number.prototype.toLocaleString produces different results for Number value " +
+ value + " and corresponding Number object: " + valueResult + " vs. " + objectResult + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_1.js b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_1.js
new file mode 100644
index 000000000..e6e0b1163
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_1.js
@@ -0,0 +1,67 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Number.prototype.toLocaleString throws the same exceptions as Intl.NumberFormat.
+ * @author Norbert Lindenberg
+ */
+
+var locales = [null, [NaN], ["i"], ["de_DE"]];
+var options = [
+ {localeMatcher: null},
+ {style: "invalid"},
+ {style: "currency"},
+ {style: "currency", currency: "ßP"},
+ {maximumSignificantDigits: -Infinity}
+];
+
+locales.forEach(function (locales) {
+ var referenceError, error;
+ try {
+ var format = new Intl.NumberFormat(locales);
+ } catch (e) {
+ referenceError = e;
+ }
+ if (referenceError === undefined) {
+ $ERROR("Internal error: Expected exception was not thrown by Intl.NumberFormat for locales " + locales + ".");
+ }
+
+ try {
+ var result = (0).toLocaleString(locales);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Number.prototype.toLocaleString didn't throw exception for locales " + locales + ".");
+ } else if (error.name !== referenceError.name) {
+ $ERROR("Number.prototype.toLocaleString threw exception " + error.name +
+ " for locales " + locales + "; expected " + referenceError.name + ".");
+ }
+});
+
+options.forEach(function (options) {
+ var referenceError, error;
+ try {
+ var format = new Intl.NumberFormat([], options);
+ } catch (e) {
+ referenceError = e;
+ }
+ if (referenceError === undefined) {
+ $ERROR("Internal error: Expected exception was not thrown by Intl.NumberFormat for options " +
+ JSON.stringify(options) + ".");
+ }
+
+ try {
+ var result = (0).toLocaleString([], options);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Number.prototype.toLocaleString didn't throw exception for options " +
+ JSON.stringify(options) + ".");
+ } else if (error.name !== referenceError.name) {
+ $ERROR("Number.prototype.toLocaleString threw exception " + error.name +
+ " for options " + JSON.stringify(options) + "; expected " + referenceError.name + ".");
+ }
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_2.js b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_2.js
new file mode 100644
index 000000000..a79cfffde
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_4_2.js
@@ -0,0 +1,13 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Number.prototype.toLocaleString uses the standard
+ * built-in Intl.NumberFormat constructor.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintDataProperty(Intl, "NumberFormat");
+(0.0).toLocaleString();
diff --git a/js/src/tests/test262/intl402/ch13/13.2/13.2.1_5.js b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_5.js
new file mode 100644
index 000000000..eb953b64d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_5.js
@@ -0,0 +1,41 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Number.prototype.toLocaleString produces the same results as Intl.NumberFormat.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var numbers = [0, -0, 1, -1, 5.5, 123, -123, -123.45, 123.44501, 0.001234,
+ -0.00000000123, 0.00000000000000000000000000000123, 1.2, 0.0000000012344501,
+ 123445.01, 12344501000000000000000000000000000, -12344501000000000000000000000000000,
+ Infinity, -Infinity, NaN];
+var locales = [undefined, ["de"], ["th-u-nu-thai"], ["en"], ["ja-u-nu-jpanfin"], ["ar-u-nu-arab"]];
+var options = [
+ undefined,
+ {style: "percent"},
+ {style: "currency", currency: "EUR", currencyDisplay: "symbol"},
+ {style: "currency", currency: "IQD", currencyDisplay: "symbol"},
+ {style: "currency", currency: "KMF", currencyDisplay: "symbol"},
+ {style: "currency", currency: "CLF", currencyDisplay: "symbol"},
+ {useGrouping: false, minimumIntegerDigits: 3, minimumFractionDigits: 1, maximumFractionDigits: 3}
+];
+
+locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var referenceNumberFormat = new Intl.NumberFormat(locales, options);
+ var referenceFormatted = numbers.map(referenceNumberFormat.format);
+
+ var formatted = numbers.map(function (a) { return a.toLocaleString(locales, options); });
+ try {
+ testArraysAreSame(referenceFormatted, formatted);
+ } catch (e) {
+ e.message += " (Testing with locales " + locales + "; options " +
+ (options ? JSON.stringify(options) : options) + ".)";
+ throw e;
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.2/13.2.1_L15.js b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_L15.js
new file mode 100644
index 000000000..8b53f7496
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/13.2.1_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Number.prototype.toLocaleString
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Number.prototype.toLocaleString, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch13/13.2/browser.js b/js/src/tests/test262/intl402/ch13/13.2/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/browser.js
diff --git a/js/src/tests/test262/intl402/ch13/13.2/shell.js b/js/src/tests/test262/intl402/ch13/13.2/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.2/shell.js
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.0_1.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_1.js
new file mode 100644
index 000000000..0f2902162
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_1.js
@@ -0,0 +1,32 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleString & Co. handle "this time value" correctly.
+ * @author Norbert Lindenberg
+ */
+
+var functions = {
+ toLocaleString: Date.prototype.toLocaleString,
+ toLocaleDateString: Date.prototype.toLocaleDateString,
+ toLocaleTimeString: Date.prototype.toLocaleTimeString
+};
+var invalidValues = [undefined, null, 5, "5", false, {valueOf: function () { return 5; }}];
+
+Object.getOwnPropertyNames(functions).forEach(function (p) {
+ var f = functions[p];
+ invalidValues.forEach(function (value) {
+ var error;
+ try {
+ var result = f.call(value);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Date.prototype." + p + " did not reject this = " + value + ".");
+ } else if (error.name !== "TypeError") {
+ $ERROR("Date.prototype." + p + " rejected this = " + value + " with wrong error " + error.name + ".");
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.0_2.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_2.js
new file mode 100644
index 000000000..7d5f32fa6
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_2.js
@@ -0,0 +1,26 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleString & Co. handle non-finite values correctly.
+ * @author Norbert Lindenberg
+ */
+
+var functions = {
+ toLocaleString: Date.prototype.toLocaleString,
+ toLocaleDateString: Date.prototype.toLocaleDateString,
+ toLocaleTimeString: Date.prototype.toLocaleTimeString
+};
+var invalidValues = [NaN, Infinity, -Infinity];
+
+Object.getOwnPropertyNames(functions).forEach(function (p) {
+ var f = functions[p];
+ invalidValues.forEach(function (value) {
+ var result = f.call(new Date(value));
+ if (result !== "Invalid Date") {
+ $ERROR("Date.prototype." + p + " did not return \"Invalid Date\" for " +
+ value + " – got " + result + " instead.");
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_1.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_1.js
new file mode 100644
index 000000000..c97b240b4
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_1.js
@@ -0,0 +1,74 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleString & Co. throws the same exceptions as Intl.DateTimeFormat.
+ * @author Norbert Lindenberg
+ */
+
+var functions = {
+ toLocaleString: Date.prototype.toLocaleString,
+ toLocaleDateString: Date.prototype.toLocaleDateString,
+ toLocaleTimeString: Date.prototype.toLocaleTimeString
+};
+var locales = [null, [NaN], ["i"], ["de_DE"]];
+var options = [
+ {localeMatcher: null},
+ {timeZone: "invalid"},
+ {hour: "long"},
+ {formatMatcher: "invalid"}
+];
+
+Object.getOwnPropertyNames(functions).forEach(function (p) {
+ var f = functions[p];
+ locales.forEach(function (locales) {
+ var referenceError, error;
+ try {
+ var format = new Intl.DateTimeFormat(locales);
+ } catch (e) {
+ referenceError = e;
+ }
+ if (referenceError === undefined) {
+ $ERROR("Internal error: Expected exception was not thrown by Intl.DateTimeFormat for locales " + locales + ".");
+ }
+
+ try {
+ var result = f.call(new Date(), locales);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Date.prototype." + p + " didn't throw exception for locales " + locales + ".");
+ } else if (error.name !== referenceError.name) {
+ $ERROR("Date.prototype." + p + " threw exception " + error.name +
+ " for locales " + locales + "; expected " + referenceError.name + ".");
+ }
+ });
+
+ options.forEach(function (options) {
+ var referenceError, error;
+ try {
+ var format = new Intl.DateTimeFormat([], options);
+ } catch (e) {
+ referenceError = e;
+ }
+ if (referenceError === undefined) {
+ $ERROR("Internal error: Expected exception was not thrown by Intl.DateTimeFormat for options " +
+ JSON.stringify(options) + ".");
+ }
+
+ try {
+ var result = f.call(new Date(), [], options);
+ } catch (e) {
+ error = e;
+ }
+ if (error === undefined) {
+ $ERROR("Date.prototype." + p + " didn't throw exception for options " +
+ JSON.stringify(options) + ".");
+ } else if (error.name !== referenceError.name) {
+ $ERROR("Date.prototype." + p + " threw exception " + error.name +
+ " for options " + JSON.stringify(options) + "; expected " + referenceError.name + ".");
+ }
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_2.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_2.js
new file mode 100644
index 000000000..dcce05906
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_6_2.js
@@ -0,0 +1,15 @@
+// Copyright 2013 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleString & Co. use the standard
+ * built-in Intl.DateTimeFormat constructor.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+taintDataProperty(Intl, "DateTimeFormat");
+new Date().toLocaleString();
+new Date().toLocaleDateString();
+new Date().toLocaleTimeString();
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.0_7.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_7.js
new file mode 100644
index 000000000..fe7c9271d
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.0_7.js
@@ -0,0 +1,58 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleString & Co. produces the same results as Intl.DateTimeFormat.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testIntl.js");
+
+var functions = {
+ toLocaleString: [Date.prototype.toLocaleString,
+ {year: "numeric", month: "numeric", day: "numeric", hour: "numeric", minute: "numeric", second: "numeric"}],
+ toLocaleDateString: [Date.prototype.toLocaleDateString,
+ {year: "numeric", month: "numeric", day: "numeric"}],
+ toLocaleTimeString: [Date.prototype.toLocaleTimeString,
+ {hour: "numeric", minute: "numeric", second: "numeric"}]
+};
+var dates = [new Date(), new Date(0), new Date(Date.parse("1989-11-09T17:57:00Z"))];
+var locales = [undefined, ["de"], ["th-u-ca-gregory-nu-thai"], ["en"], ["ja-u-ca-japanese"], ["ar-u-ca-islamicc-nu-arab"]];
+var options = [
+ undefined,
+ {hour12: false},
+ {month: "long", day: "numeric", hour: "2-digit", minute: "2-digit"}
+];
+
+Object.getOwnPropertyNames(functions).forEach(function (p) {
+ var f = functions[p][0];
+ var defaults = functions[p][1];
+ locales.forEach(function (locales) {
+ options.forEach(function (options) {
+ var constructorOptions = options;
+ if (options === undefined) {
+ constructorOptions = defaults;
+ } else if (options.day === undefined) {
+ // for simplicity, our options above have either both date and time or neither
+ constructorOptions = Object.create(defaults);
+ for (var prop in options) {
+ if (options.hasOwnProperty(prop)) {
+ constructorOptions[prop] = options[prop];
+ }
+ }
+ }
+ var referenceDateTimeFormat = new Intl.DateTimeFormat(locales, constructorOptions);
+ var referenceFormatted = dates.map(referenceDateTimeFormat.format);
+
+ var formatted = dates.map(function (a) { return f.call(a, locales, options); });
+ try {
+ testArraysAreSame(referenceFormatted, formatted);
+ } catch (e) {
+ e.message += " (Testing with locales " + locales + "; options " +
+ (options ? JSON.stringify(options) : options) + ".)";
+ throw e;
+ }
+ });
+ });
+});
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.1_L15.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.1_L15.js
new file mode 100644
index 000000000..a8c697c07
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.1_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleString
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Date.prototype.toLocaleString, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.2_L15.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.2_L15.js
new file mode 100644
index 000000000..5eeed944e
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.2_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleDateString
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Date.prototype.toLocaleDateString, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/13.3.3_L15.js b/js/src/tests/test262/intl402/ch13/13.3/13.3.3_L15.js
new file mode 100644
index 000000000..dac7c3513
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/13.3.3_L15.js
@@ -0,0 +1,14 @@
+// Copyright 2012 Mozilla Corporation. All rights reserved.
+// This code is governed by the license found in the LICENSE file.
+
+/**
+ * @description Tests that Date.prototype.toLocaleTimeString
+ * meets the requirements for built-in objects defined by the introduction of
+ * chapter 15 of the ECMAScript Language Specification.
+ * @author Norbert Lindenberg
+ */
+
+$INCLUDE("testBuiltInObject.js");
+
+testBuiltInObject(Date.prototype.toLocaleTimeString, true, false, [], 0);
+
diff --git a/js/src/tests/test262/intl402/ch13/13.3/browser.js b/js/src/tests/test262/intl402/ch13/13.3/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/browser.js
diff --git a/js/src/tests/test262/intl402/ch13/13.3/shell.js b/js/src/tests/test262/intl402/ch13/13.3/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/13.3/shell.js
diff --git a/js/src/tests/test262/intl402/ch13/browser.js b/js/src/tests/test262/intl402/ch13/browser.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/browser.js
diff --git a/js/src/tests/test262/intl402/ch13/shell.js b/js/src/tests/test262/intl402/ch13/shell.js
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/js/src/tests/test262/intl402/ch13/shell.js
diff --git a/js/src/tests/test262/intl402/shell.js b/js/src/tests/test262/intl402/shell.js
new file mode 100644
index 000000000..2e6826e91
--- /dev/null
+++ b/js/src/tests/test262/intl402/shell.js
@@ -0,0 +1,10 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+/*
+ * Test402 tests all pass unless they throw, and there are no @negative tests.
+ * Once Test262 includes @negative support, and this call in test262-shell.js is
+ * removed, this'll need to be uncommented.
+ */
+//testPassesUnlessItThrows();