]>
Commit | Line | Data |
---|---|---|
ed1e77d3 A |
1 | function shouldBe(actual, expected) { |
2 | if (actual !== expected) | |
3 | throw new Error("bad value: " + String(actual)); | |
4 | } | |
5 | ||
6 | function shouldThrow(func, message) { | |
7 | var error = null; | |
8 | try { | |
9 | func(); | |
10 | } catch (e) { | |
11 | error = e; | |
12 | } | |
13 | if (!error) | |
14 | throw new Error("not thrown."); | |
15 | if (String(error) !== message) | |
16 | throw new Error("bad error: " + String(error)); | |
17 | } | |
18 | ||
19 | function toCodePoints(string) { | |
20 | var result = []; | |
21 | for (var codePoint of string) { | |
22 | result.push(codePoint.codePointAt(0)); | |
23 | } | |
24 | return result; | |
25 | } | |
26 | ||
27 | shouldBe(String.fromCodePoint(), ""); | |
28 | shouldBe(String.fromCodePoint(0), "\0"); | |
29 | shouldBe(String.fromCodePoint(0, 0), "\0\0"); | |
30 | ||
31 | var tests = [ | |
32 | "", | |
33 | "Hello", | |
34 | "Cocoa", | |
35 | "Cappuccino Cocoa", | |
36 | "日本語", | |
37 | "マルチバイト", | |
38 | "吉野屋", | |
39 | "𠮷野家", // Contain a surrogate pair. | |
40 | ]; | |
41 | ||
42 | for (var test of tests) { | |
43 | shouldBe(String.fromCodePoint.apply(String, toCodePoints(test)), test); | |
44 | } | |
45 | ||
46 | function passThrough(codePoint) { | |
47 | var string = String.fromCodePoint(codePoint); | |
48 | shouldBe(string.codePointAt(0), codePoint); | |
49 | } | |
50 | ||
51 | var numberTests = [ | |
52 | [ 0x10FFFF, "\uDBFF\uDFFF" ], | |
53 | [ 0x10FFFE, "\uDBFF\uDFFE" ], | |
54 | [ 0xFFFF, "\uFFFF" ], | |
55 | [ 0x10000, "\uD800\uDC00" ], | |
56 | [ 0x10001, "\uD800\uDC01" ], | |
57 | [ -0.0, "\u0000" ], | |
58 | [ 0xD800, "\uD800" ], | |
59 | [ 0xDC00, "\uDC00" ], | |
60 | ]; | |
61 | ||
62 | for (var test of numberTests) { | |
63 | shouldBe(String.fromCodePoint(test[0]), test[1]); | |
64 | } | |
65 | ||
66 | shouldBe(String.fromCodePoint(0xD800, 0xDC00).codePointAt(0), 0x10000); | |
67 | ||
68 | // Non-character code points. | |
69 | for (var i = 0; i < 17; ++i) { | |
70 | var plane = 0x10000 * i; | |
71 | passThrough(plane + 0xFFFE); | |
72 | passThrough(plane + 0xFFFF); | |
73 | } | |
74 | ||
75 | for (var start = 0xFDD0; start <= 0xFDEF; ++start) { | |
76 | passThrough(start); | |
77 | } | |
78 | ||
79 | var invalidTests = [ | |
80 | -1, | |
81 | 1.2, | |
82 | 1.5, | |
83 | 30.01, | |
84 | -11.0, | |
85 | NaN, | |
86 | Number.Infinity, | |
87 | -Number.Infinity, | |
88 | 0x10FFFF + 1, | |
89 | 0x7FFFFFFF, | |
90 | 0x7FFFFFFF + 1, | |
91 | 0xFFFFFFFF, | |
92 | 0xFFFFFFFF + 1, | |
93 | 0x100000000 + 32, // String.fromCharCode(0x100000000 + 32) produces a space, but String.fromCodePoint should throw an error. | |
94 | "Hello", | |
95 | undefined, | |
96 | {}, | |
97 | ]; | |
98 | ||
99 | for (var test of invalidTests) { | |
100 | shouldThrow(function () { | |
101 | String.fromCodePoint(test); | |
102 | }, "RangeError: Arguments contain a value that is out of range of code points"); | |
103 | } | |
104 | ||
105 | // toNumber causes errors. | |
106 | shouldThrow(function () { | |
107 | String.fromCodePoint(Symbol.iterator); | |
108 | }, "TypeError: Type error") | |
109 | ||
110 | var toNumberObject = { | |
111 | valueOf() { | |
112 | throw new Error("valueOf is called"); | |
113 | } | |
114 | }; | |
115 | ||
116 | shouldThrow(function () { | |
117 | String.fromCodePoint(toNumberObject); | |
118 | }, "Error: valueOf is called") | |
119 | ||
120 | shouldThrow(function () { | |
121 | String.fromCodePoint(Symbol.iterator, toNumberObject); | |
122 | }, "TypeError: Type error") | |
123 | ||
124 | var convertAndPassTests = [ | |
125 | [ null, "\0" ], | |
126 | [ [], "\0" ], | |
127 | [ "0x41", "A" ], | |
128 | [ "", "\0" ], | |
129 | [ true, "\u0001" ], | |
130 | [ false, "\u0000" ], | |
131 | ]; | |
132 | ||
133 | for (var test of convertAndPassTests) { | |
134 | shouldBe(String.fromCodePoint(test[0]), test[1]); | |
135 | } |