Skip to content

Commit d165d08

Browse files
Bug Fix
1 parent 4bb38a8 commit d165d08

39 files changed

+360
-213
lines changed

src/compiler/emitter.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ import {
408408
TemplateSpan,
409409
TextRange,
410410
ThrowStatement,
411+
TokenFlags,
411412
tokenToString,
412413
tracing,
413414
TransformationResult,
@@ -2989,9 +2990,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
29892990
if (isNumericLiteral(expression)) {
29902991
// check if numeric literal is a decimal literal that was originally written with a dot
29912992
const text = getLiteralTextOfNode(expression as LiteralExpression, /*neverAsciiEscape*/ true, /*jsxAttributeEscape*/ false);
2992-
// If he number will be printed verbatim and it doesn't already contain a dot, add one
2993+
// If the number will be printed verbatim and it doesn't already contain a dot, add one
29932994
// if the expression doesn't have any comments that will be emitted.
2994-
return !expression.numericLiteralFlags && !stringContains(text, tokenToString(SyntaxKind.DotToken)!);
2995+
return !(expression.numericLiteralFlags & ~TokenFlags.OctalOrContainsLeadingZero) && !stringContains(text, tokenToString(SyntaxKind.DotToken)!);
29952996
}
29962997
else if (isAccessExpression(expression)) {
29972998
// check if constant enum value is integer

src/compiler/parser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3606,7 +3606,7 @@ namespace Parser {
36063606
}
36073607

36083608
function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead {
3609-
if (!isTaggedTemplate && scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape) {
3609+
if (!isTaggedTemplate && scanner.getTokenFlags() & TokenFlags.IsInvalid) {
36103610
reScanTemplateHeadOrNoSubstitutionTemplate();
36113611
}
36123612
const fragment = parseLiteralLikeNode(token());
@@ -6414,7 +6414,7 @@ namespace Parser {
64146414
function parsePrimaryExpression(): PrimaryExpression {
64156415
switch (token()) {
64166416
case SyntaxKind.NoSubstitutionTemplateLiteral:
6417-
if (scanner.getTokenFlags() & TokenFlags.ContainsInvalidEscape) {
6417+
if (scanner.getTokenFlags() & TokenFlags.IsInvalid) {
64186418
reScanTemplateHeadOrNoSubstitutionTemplate();
64196419
}
64206420
// falls through

src/compiler/scanner.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,11 +1073,14 @@ export function createScanner(languageVersion: ScriptTarget,
10731073
isPreviousTokenSeparator = true;
10741074
result += text.substring(start, pos);
10751075
}
1076-
else if (isPreviousTokenSeparator) {
1077-
error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1);
1078-
}
10791076
else {
1080-
error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1);
1077+
tokenFlags |= TokenFlags.ContainsInvalidSeparator;
1078+
if (isPreviousTokenSeparator) {
1079+
error(Diagnostics.Multiple_consecutive_numeric_separators_are_not_permitted, pos, 1);
1080+
}
1081+
else {
1082+
error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1);
1083+
}
10811084
}
10821085
pos++;
10831086
start = pos;
@@ -1092,6 +1095,7 @@ export function createScanner(languageVersion: ScriptTarget,
10921095
break;
10931096
}
10941097
if (text.charCodeAt(pos - 1) === CharacterCodes._) {
1098+
tokenFlags |= TokenFlags.ContainsInvalidSeparator;
10951099
error(Diagnostics.Numeric_separators_are_not_allowed_here, pos - 1, 1);
10961100
}
10971101
return result + text.substring(start, pos);
@@ -1120,10 +1124,10 @@ export function createScanner(languageVersion: ScriptTarget,
11201124
function scanNumber(): { type: SyntaxKind, value: string } {
11211125
let start = pos;
11221126
let mainFragment: string;
1123-
let emitLeadingZeroError = false;
11241127
if (text.charCodeAt(pos) === CharacterCodes._0) {
11251128
pos++;
11261129
if (text.charCodeAt(pos) === CharacterCodes._) {
1130+
tokenFlags |= TokenFlags.ContainsSeparator | TokenFlags.ContainsInvalidSeparator;
11271131
error(Diagnostics.Numeric_separators_are_not_allowed_here, pos, 1);
11281132
// treat it as a normal number literal
11291133
pos--;
@@ -1133,20 +1137,21 @@ export function createScanner(languageVersion: ScriptTarget,
11331137
else if (!scanDigits()) {
11341138
// NonOctalDecimalIntegerLiteral, emit error later
11351139
// Separators in decimal and exponent parts are still allowed according to the spec
1136-
emitLeadingZeroError = true;
1137-
mainFragment = tokenValue;
1140+
tokenFlags |= TokenFlags.ContainsLeadingZero;
1141+
mainFragment = "" + +tokenValue;
11381142
}
11391143
else if (!tokenValue) {
11401144
// a single zero
11411145
mainFragment = "0";
11421146
}
11431147
else {
11441148
// LegacyOctalIntegerLiteral
1145-
tokenValue = "0o" + tokenValue;
1149+
tokenValue = "" + parseInt(tokenValue, 8);
11461150
tokenFlags |= TokenFlags.Octal;
11471151
const withMinus = token === SyntaxKind.MinusToken;
1152+
const literal = (withMinus ? "-" : "") + "0o" + (+tokenValue).toString(8);
11481153
start -= +withMinus;
1149-
error(Diagnostics.Octal_literals_are_not_allowed_Use_the_syntax_0, start, pos - start, (withMinus ? "-" : "") + tokenValue);
1154+
error(Diagnostics.Octal_literals_are_not_allowed_Use_the_syntax_0, start, pos - start, literal);
11501155
return { type: SyntaxKind.NumericLiteral, value: tokenValue };
11511156
}
11521157
}
@@ -1188,10 +1193,10 @@ export function createScanner(languageVersion: ScriptTarget,
11881193
result = text.substring(start, end); // No need to use all the fragments; no _ removal needed
11891194
}
11901195

1191-
if (emitLeadingZeroError) {
1196+
if (tokenFlags & TokenFlags.ContainsLeadingZero) {
11921197
error(Diagnostics.Decimals_with_leading_zeros_are_not_allowed, start, end - start);
11931198
// if a literal has a leading zero, it must not be bigint
1194-
return { type: SyntaxKind.NumericLiteral, value: result };
1199+
return { type: SyntaxKind.NumericLiteral, value: "" + +result };
11951200
}
11961201

11971202
if (decimalFragment !== undefined || tokenFlags & TokenFlags.Scientific) {

src/compiler/transformers/taggedTemplate.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ export function processTaggedTemplateExpression(
9494
}
9595

9696
function createTemplateCooked(template: TemplateHead | TemplateMiddle | TemplateTail | NoSubstitutionTemplateLiteral) {
97-
return template.templateFlags! & TokenFlags.ContainsInvalidEscape ? factory.createVoidZero() : factory.createStringLiteral(template.text);
97+
return template.templateFlags! & TokenFlags.IsInvalid ? factory.createVoidZero() : factory.createStringLiteral(template.text);
9898
}
9999

100100
/**

src/compiler/types.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2554,28 +2554,36 @@ export const enum TokenFlags {
25542554
/** @internal */
25552555
Unterminated = 1 << 2,
25562556
/** @internal */
2557-
ExtendedUnicodeEscape = 1 << 3,
2558-
Scientific = 1 << 4, // e.g. `10e2`
2559-
Octal = 1 << 5, // e.g. `0777`
2560-
HexSpecifier = 1 << 6, // e.g. `0x00000000`
2561-
BinarySpecifier = 1 << 7, // e.g. `0b0110010000000000`
2562-
OctalSpecifier = 1 << 8, // e.g. `0o777`
2557+
ExtendedUnicodeEscape = 1 << 3, // e.g. `\u{10ffff}`
2558+
Scientific = 1 << 4, // e.g. `10e2`
2559+
Octal = 1 << 5, // e.g. `0777`
2560+
HexSpecifier = 1 << 6, // e.g. `0x00000000`
2561+
BinarySpecifier = 1 << 7, // e.g. `0b0110010000000000`
2562+
OctalSpecifier = 1 << 8, // e.g. `0o777`
25632563
/** @internal */
2564-
ContainsSeparator = 1 << 9, // e.g. `0b1100_0101`
2564+
ContainsSeparator = 1 << 9, // e.g. `0b1100_0101`
25652565
/** @internal */
2566-
UnicodeEscape = 1 << 10, // e.g. `\u00a0`
2566+
UnicodeEscape = 1 << 10, // e.g. `\u00a0`
25672567
/** @internal */
25682568
ContainsInvalidEscape = 1 << 11, // e.g. `\uhello`
25692569
/** @internal */
2570-
HexEscape = 1 << 12, // e.g. `\xa0`
2570+
HexEscape = 1 << 12, // e.g. `\xa0`
2571+
/** @internal */
2572+
ContainsLeadingZero = 1 << 13, // e.g. `0888`
2573+
/** @internal */
2574+
ContainsInvalidSeparator = 1 << 14, // e.g. `0_1`
25712575
/** @internal */
25722576
BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier,
25732577
/** @internal */
2578+
OctalOrContainsLeadingZero = Octal | ContainsLeadingZero,
2579+
/** @internal */
25742580
StringLiteralFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape,
25752581
/** @internal */
2576-
NumericLiteralFlags = Scientific | Octal | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator,
2582+
NumericLiteralFlags = Scientific | OctalOrContainsLeadingZero | HexSpecifier | BinaryOrOctalSpecifier | ContainsSeparator | ContainsInvalidSeparator,
25772583
/** @internal */
25782584
TemplateLiteralLikeFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape,
2585+
/** @internal */
2586+
IsInvalid = OctalOrContainsLeadingZero | ContainsInvalidSeparator | ContainsInvalidEscape,
25792587
}
25802588

25812589
export interface NumericLiteral extends LiteralExpression, Declaration {

src/compiler/utilities.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,8 +1324,13 @@ function canUseOriginalText(node: LiteralLikeNode, flags: GetLiteralTextFlags):
13241324
return false;
13251325
}
13261326

1327-
if (isNumericLiteral(node) && node.numericLiteralFlags & TokenFlags.ContainsSeparator) {
1328-
return !!(flags & GetLiteralTextFlags.AllowNumericSeparator);
1327+
if (isNumericLiteral(node)) {
1328+
if (node.numericLiteralFlags & TokenFlags.IsInvalid) {
1329+
return false;
1330+
}
1331+
if (node.numericLiteralFlags & TokenFlags.ContainsSeparator) {
1332+
return !!(flags & GetLiteralTextFlags.AllowNumericSeparator);
1333+
}
13291334
}
13301335

13311336
return !isBigIntLiteral(node);

tests/baselines/reference/isLiteral1.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
var x: number = 02343;
33

44
//// [isLiteral1.js]
5-
var x = 02343;
5+
var x = 1251;

tests/baselines/reference/isLiteral2.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
var x: number = 02343
33

44
//// [isLiteral2.js]
5-
var x = 02343;
5+
var x = 1251;

tests/baselines/reference/literals.errors.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ tests/cases/conformance/expressions/literals/literals.ts(8,10): error TS18050: T
22
tests/cases/conformance/expressions/literals/literals.ts(8,17): error TS18050: The value 'null' cannot be used here.
33
tests/cases/conformance/expressions/literals/literals.ts(9,9): error TS18050: The value 'undefined' cannot be used here.
44
tests/cases/conformance/expressions/literals/literals.ts(9,21): error TS18050: The value 'undefined' cannot be used here.
5-
tests/cases/conformance/expressions/literals/literals.ts(19,9): error TS1121: Octal literals are not allowed. Use the syntax '0o01'.
6-
tests/cases/conformance/expressions/literals/literals.ts(24,9): error TS1121: Octal literals are not allowed. Use the syntax '-0o03'.
5+
tests/cases/conformance/expressions/literals/literals.ts(19,9): error TS1121: Octal literals are not allowed. Use the syntax '0o1'.
6+
tests/cases/conformance/expressions/literals/literals.ts(24,9): error TS1121: Octal literals are not allowed. Use the syntax '-0o3'.
77

88

99
==== tests/cases/conformance/expressions/literals/literals.ts (6 errors) ====
@@ -35,14 +35,14 @@ tests/cases/conformance/expressions/literals/literals.ts(24,9): error TS1121: Oc
3535
var n = 1e4;
3636
var n = 001; // Error in ES5
3737
~~~
38-
!!! error TS1121: Octal literals are not allowed. Use the syntax '0o01'.
38+
!!! error TS1121: Octal literals are not allowed. Use the syntax '0o1'.
3939
var n = 0x1;
4040
var n = -1;
4141
var n = -1.0;
4242
var n = -1e-4;
4343
var n = -003; // Error in ES5
4444
~~~~
45-
!!! error TS1121: Octal literals are not allowed. Use the syntax '-0o03'.
45+
!!! error TS1121: Octal literals are not allowed. Use the syntax '-0o3'.
4646
var n = -0x1;
4747

4848
var s: string;

tests/baselines/reference/literals.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,12 @@ var n;
5454
var n = 1;
5555
var n = 1.0;
5656
var n = 1e4;
57-
var n = 001; // Error in ES5
57+
var n = 1; // Error in ES5
5858
var n = 0x1;
5959
var n = -1;
6060
var n = -1.0;
6161
var n = -1e-4;
62-
var n = -003; // Error in ES5
62+
var n = -3; // Error in ES5
6363
var n = -0x1;
6464
var s;
6565
var s = '';

0 commit comments

Comments
 (0)