utatane.tea@gmail.com | d19d59c | 2015-04-25 22:00:51 +0000 | [diff] [blame] | 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); |
utatane.tea@gmail.com | 5d80e95 | 2016-05-04 01:21:38 +0000 | [diff] [blame] | 108 | }, "TypeError: Cannot convert a symbol to a number") |
utatane.tea@gmail.com | d19d59c | 2015-04-25 22:00:51 +0000 | [diff] [blame] | 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); |
utatane.tea@gmail.com | 5d80e95 | 2016-05-04 01:21:38 +0000 | [diff] [blame] | 122 | }, "TypeError: Cannot convert a symbol to a number") |
utatane.tea@gmail.com | d19d59c | 2015-04-25 22:00:51 +0000 | [diff] [blame] | 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 | } |