identifiers-with-extended-unicode-escape.js (6068B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 // Simple cases, not using eval. 6 { 7 let \u{61} = 123; 8 assertEq(a, 123); 9 10 let \u{6A} = 123; 11 assertEq(j, 123); 12 13 let a\u{62} = 456; 14 assertEq(ab, 456); 15 16 let \u{63}\u{6b} = 789; 17 assertEq(ck, 789); 18 } 19 20 const leadingZeros = [0, 1, 2, 3, 4, 100].map(c => "0".repeat(c)); 21 22 23 // From DerivedCoreProperties.txt (Unicode 9): 24 // Derived Property: ID_Start 25 // Characters that can start an identifier. 26 // Generated from: 27 // Lu + Ll + Lt + Lm + Lo + Nl 28 // + Other_ID_Start 29 // - Pattern_Syntax 30 // - Pattern_White_Space 31 const idStart = [ 32 0x0041, // LATIN CAPITAL LETTER A, Gc=Lu 33 0x006A, // LATIN SMALL LETTER J, Gc=Ll 34 0x00C9, // LATIN CAPITAL LETTER E WITH ACUTE, Gc=Lu 35 0x00FF, // LATIN SMALL LETTER Y WITH DIAERESIS, Gc=Ll 36 0x01C5, // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON, Gc=Lt 37 0x0294, // LATIN LETTER GLOTTAL STOP, Gc=Lo 38 0x037A, // GREEK YPOGEGRAMMENI, Gc=Lm 39 0x16EE, // RUNIC ARLAUG SYMBOL, Gc=Nl 40 0xFF70, // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK, Gc=Lm 41 ]; 42 43 const idStartSupplemental = [ 44 0x10140, // GREEK ACROPHONIC ATTIC ONE QUARTER, Gc=Nl 45 0x10300, // OLD ITALIC LETTER A, Gc=Lo 46 0x10400, // DESERET CAPITAL LETTER LONG I, Gc=Lu 47 0x10430, // DESERET SMALL LETTER SHORT A, Gc=Ll 48 0x16B40, // PAHAWH HMONG SIGN VOS SEEV, Gc=Lm 49 ]; 50 51 // From PropList.txt (Unicode 9): 52 const otherIdStart = [ 53 0x1885, // MONGOLIAN LETTER ALI GALI BALUDA, Gc=Mn 54 0x1886, // MONGOLIAN LETTER ALI GALI THREE BALUDA, Gc=Mn 55 0x2118, // SCRIPT CAPITAL P, Gc=Sm 56 0x212E, // ESTIMATED SYMBOL, Gc=So 57 0x309B, // KATAKANA-HIRAGANA VOICED SOUND MARK, Gc=Sk 58 0x309C, // KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK, Gc=Sk 59 ]; 60 61 // From DerivedCoreProperties.txt (Unicode 9): 62 // Derived Property: ID_Continue 63 // Characters that can continue an identifier. 64 // Generated from: 65 // ID_Start 66 // + Mn + Mc + Nd + Pc 67 // + Other_ID_Continue 68 // - Pattern_Syntax 69 // - Pattern_White_Space 70 const idContinue = [ 71 0x0030, // DIGIT ZERO, Gc=Nd 72 0x0300, // COMBINING GRAVE ACCENT, Gc=Mn 73 0x0660, // ARABIC-INDIC DIGIT ZERO, Gc=Nd 74 0x0903, // DEVANAGARI SIGN VISARGA, Gc=Mc 75 0xFF10, // FULLWIDTH DIGIT ZERO, Gc=Nd 76 0xFF3F, // FULLWIDTH LOW LINE, Gc=Pc 77 ]; 78 79 const idContinueSupplemental = [ 80 0x101FD, // PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, Gc=Mn 81 0x104A0, // OSMANYA DIGIT ZERO, Gc=Nd 82 0x11000, // BRAHMI SIGN CANDRABINDU, Gc=Mc 83 ]; 84 85 // From PropList.txt (Unicode 9): 86 const otherIdContinue = [ 87 0x00B7, // MIDDLE DOT, Gc=Po 88 0x0387, // GREEK ANO TELEIA, Gc=Po 89 0x1369, // ETHIOPIC DIGIT ONE, Gc=No 90 0x136A, // ETHIOPIC DIGIT TWO, Gc=No 91 0x136B, // ETHIOPIC DIGIT THREE, Gc=No 92 0x136C, // ETHIOPIC DIGIT FOUR, Gc=No 93 0x136D, // ETHIOPIC DIGIT FIVE, Gc=No 94 0x136E, // ETHIOPIC DIGIT SIX, Gc=No 95 0x136F, // ETHIOPIC DIGIT SEVEN, Gc=No 96 0x1370, // ETHIOPIC DIGIT EIGHT, Gc=No 97 0x1371, // ETHIOPIC DIGIT NINE, Gc=No 98 0x19DA, // NEW TAI LUE THAM DIGIT ONE, Gc=No 99 ]; 100 101 for (let ident of [...idStart, ...otherIdStart, ...idStartSupplemental]) { 102 for (let count of leadingZeros) { 103 let zeros = "0".repeat(count); 104 eval(` 105 let \\u{${zeros}${ident.toString(16)}} = 123; 106 assertEq(${String.fromCodePoint(ident)}, 123); 107 `); 108 } 109 } 110 111 for (let ident of [...idContinue, ...idContinueSupplemental, ...otherIdContinue]) { 112 for (let zeros of leadingZeros) { 113 assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError); 114 } 115 } 116 117 for (let ident of [...idStart, ...otherIdStart, ...idContinue, ...otherIdContinue, ...idStartSupplemental, ...idContinueSupplemental]) { 118 for (let zeros of leadingZeros) { 119 eval(` 120 let A\\u{${zeros}${ident.toString(16)}} = 123; 121 assertEq(${String.fromCodePoint(0x41, ident)}, 123); 122 `); 123 } 124 } 125 126 127 const notIdentifiers = [ 128 0x0000, // NULL, Gc=Cc 129 0x000A, // LINE FEED (LF), Gc=Cc 130 0x005E, // CIRCUMFLEX ACCENT, Gc=Sk 131 0x00B1, // PLUS-MINUS SIGN, Gc=Sm 132 0xFF61, // HALFWIDTH IDEOGRAPHIC FULL STOP, Gc=Po 133 0x10061, // Not assigned. 134 0x10100, // AEGEAN WORD SEPARATOR LINE, Gc=Po 135 0x100061, // <Plane 16 Private Use>, Gc=Co 136 ]; 137 138 for (let ident of notIdentifiers) { 139 for (let zeros of leadingZeros) { 140 assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError); 141 } 142 } 143 144 145 const incompleteEscapes = [ 146 "\\u{", 147 "\\u{6", 148 "\\u{61", 149 "\\u{061", 150 "\\u{0061", 151 "\\u{00061", 152 "\\u{000061", 153 "\\u{0000061", 154 155 "\\u}", 156 ]; 157 for (let invalid of incompleteEscapes) { 158 // Ends with EOF. 159 assertThrowsInstanceOf(() => eval(invalid), SyntaxError); 160 161 // Ends with EOL. 162 assertThrowsInstanceOf(() => eval(invalid + "\n"), SyntaxError); 163 164 // Ends with space. 165 assertThrowsInstanceOf(() => eval(invalid + " "), SyntaxError); 166 } 167 168 169 const invalidEscapes = [ 170 // Empty escape. 171 "", 172 173 // Not hexadecimal characters. 174 "\0", 175 "G", 176 "Z", 177 "\uFFFF", 178 "\uDBFF\uDFFF", 179 180 // Has space characters. 181 " 61", 182 "61 ", 183 184 // Has newline characters. 185 "\n61", 186 "61\n", 187 188 // Exceeds 0x10FFFF, six characters. 189 "110000", 190 "110001", 191 "fffffe", 192 "ffffff", 193 194 // Exceeds 0x10FFFF, more than six characters. 195 "10ffff0", 196 "10ffffabcdef", 197 ]; 198 199 for (let invalid of invalidEscapes) { 200 for (let zeros of leadingZeros) { 201 assertThrowsInstanceOf(() => eval(`\\u{${zeros}${invalid}}`), SyntaxError); 202 assertThrowsInstanceOf(() => eval(`var \\u{${zeros}${invalid}}`), SyntaxError); 203 } 204 } 205 206 207 if (typeof reportCompare === "function") 208 reportCompare(0, 0, "ok");