Skip to content

Commit d00056f

Browse files
authored
Support extended unicode escapes in identifiers, per es6 spec (microsoft#32725)
1 parent d757402 commit d00056f

File tree

5 files changed

+78
-0
lines changed

5 files changed

+78
-0
lines changed

src/compiler/scanner.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1342,6 +1342,19 @@ namespace ts {
13421342
return -1;
13431343
}
13441344

1345+
1346+
function peekExtendedUnicodeEscape(): number {
1347+
if (languageVersion >= ScriptTarget.ES2015 && codePointAt(text, pos + 1) === CharacterCodes.u && codePointAt(text, pos + 2) === CharacterCodes.openBrace) {
1348+
const start = pos;
1349+
pos += 3;
1350+
const escapedValueString = scanMinimumNumberOfHexDigits(1, /*canHaveSeparators*/ false);
1351+
const escapedValue = escapedValueString ? parseInt(escapedValueString, 16) : -1;
1352+
pos = start;
1353+
return escapedValue;
1354+
}
1355+
return -1;
1356+
}
1357+
13451358
function scanIdentifierParts(): string {
13461359
let result = "";
13471360
let start = pos;
@@ -1351,6 +1364,14 @@ namespace ts {
13511364
pos += charSize(ch);
13521365
}
13531366
else if (ch === CharacterCodes.backslash) {
1367+
ch = peekExtendedUnicodeEscape();
1368+
if (ch >= 0 && isIdentifierPart(ch, languageVersion)) {
1369+
pos += 3;
1370+
tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
1371+
result += scanExtendedUnicodeEscape();
1372+
start = pos;
1373+
continue;
1374+
}
13541375
ch = peekUnicodeEscape();
13551376
if (!(ch >= 0 && isIdentifierPart(ch, languageVersion))) {
13561377
break;
@@ -1836,12 +1857,21 @@ namespace ts {
18361857
pos++;
18371858
return token = SyntaxKind.AtToken;
18381859
case CharacterCodes.backslash:
1860+
const extendedCookedChar = peekExtendedUnicodeEscape();
1861+
if (extendedCookedChar >= 0 && isIdentifierStart(extendedCookedChar, languageVersion)) {
1862+
pos += 3;
1863+
tokenFlags |= TokenFlags.ExtendedUnicodeEscape;
1864+
tokenValue = scanExtendedUnicodeEscape() + scanIdentifierParts();
1865+
return token = getIdentifierToken();
1866+
}
1867+
18391868
const cookedChar = peekUnicodeEscape();
18401869
if (cookedChar >= 0 && isIdentifierStart(cookedChar, languageVersion)) {
18411870
pos += 6;
18421871
tokenValue = String.fromCharCode(cookedChar) + scanIdentifierParts();
18431872
return token = getIdentifierToken();
18441873
}
1874+
18451875
error(Diagnostics.Invalid_character);
18461876
pos++;
18471877
return token = SyntaxKind.Unknown;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//// [extendedUnicodeEscapeSequenceIdentifiers.ts]
2+
const \u{0061} = 12;
3+
const a\u{0061} = 12;
4+
5+
console.log(a + aa);
6+
7+
8+
//// [extendedUnicodeEscapeSequenceIdentifiers.js]
9+
const \u{0061} = 12;
10+
const a\u{0061} = 12;
11+
console.log(a + aa);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
=== tests/cases/compiler/extendedUnicodeEscapeSequenceIdentifiers.ts ===
2+
const \u{0061} = 12;
3+
>\u{0061} : Symbol(\u{0061}, Decl(extendedUnicodeEscapeSequenceIdentifiers.ts, 0, 5))
4+
5+
const a\u{0061} = 12;
6+
>a\u{0061} : Symbol(a\u{0061}, Decl(extendedUnicodeEscapeSequenceIdentifiers.ts, 1, 5))
7+
8+
console.log(a + aa);
9+
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
10+
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
11+
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
12+
>a : Symbol(\u{0061}, Decl(extendedUnicodeEscapeSequenceIdentifiers.ts, 0, 5))
13+
>aa : Symbol(a\u{0061}, Decl(extendedUnicodeEscapeSequenceIdentifiers.ts, 1, 5))
14+
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/extendedUnicodeEscapeSequenceIdentifiers.ts ===
2+
const \u{0061} = 12;
3+
>\u{0061} : 12
4+
>12 : 12
5+
6+
const a\u{0061} = 12;
7+
>a\u{0061} : 12
8+
>12 : 12
9+
10+
console.log(a + aa);
11+
>console.log(a + aa) : void
12+
>console.log : (message?: any, ...optionalParams: any[]) => void
13+
>console : Console
14+
>log : (message?: any, ...optionalParams: any[]) => void
15+
>a + aa : number
16+
>a : 12
17+
>aa : 12
18+
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// @target: es6
2+
const \u{0061} = 12;
3+
const a\u{0061} = 12;
4+
5+
console.log(a + aa);

0 commit comments

Comments
 (0)