From f744113edf2648c775ab72402cac7d683a429c62 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 6 Aug 2014 12:09:27 -0700 Subject: [PATCH 1/6] Scan octal literals --- src/compiler/scanner.ts | 26 +++++++++++++++++-- .../scannerES3NumericLiteral3.errors.txt | 4 +++ .../reference/scannerES3NumericLiteral3.js | 5 ---- .../scannerNumericLiteral3.errors.txt | 4 +++ .../reference/scannerNumericLiteral3.js | 5 ---- 5 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 tests/baselines/reference/scannerES3NumericLiteral3.errors.txt delete mode 100644 tests/baselines/reference/scannerES3NumericLiteral3.js create mode 100644 tests/baselines/reference/scannerNumericLiteral3.errors.txt delete mode 100644 tests/baselines/reference/scannerNumericLiteral3.js diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index 70c1dbee6ac..c04cf3d8c23 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -300,6 +300,10 @@ module ts { return ch >= CharacterCodes._0 && ch <= CharacterCodes._9; } + function isOctalDigit(ch: number): boolean { + return ch >= CharacterCodes._0 && ch <= CharacterCodes._7; + } + export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number { while (true) { var ch = text.charCodeAt(pos); @@ -360,7 +364,9 @@ module ts { var precedingLineBreak: boolean; function error(message: DiagnosticMessage): void { - if (onError) onError(message); + if (onError) { + onError(message); + } } function isIdentifierStart(ch: number): boolean { @@ -398,6 +404,14 @@ module ts { return +(text.substring(start, end)); } + function scanOctalDigits(): number { + var start = pos; + while (isOctalDigit(text.charCodeAt(pos))) { + pos++; + } + return +(text.substring(start, pos)); + } + function scanHexDigits(count: number, exact?: boolean): number { var digits = 0; var value = 0; @@ -681,7 +695,7 @@ module ts { if (!commentClosed) { pos++; - onError(Diagnostics.Asterisk_Slash_expected); + error(Diagnostics.Asterisk_Slash_expected); } if (onComment) { @@ -708,6 +722,14 @@ module ts { tokenValue = "" + value; return SyntaxKind.NumericLiteral; } + // Try to parse as an octal + if (pos + 1 < len && isOctalDigit(text.charCodeAt(pos + 1))) { + tokenValue = "" + scanOctalDigits(); + return SyntaxKind.NumericLiteral; + } + // This fall-through is a deviation from the EcmaScript grammar. The grammar says that a leading zero + // can only be followed by an octal digit, a dot, or the end of the number literal. However, we are being + // permissive and allowing decimal digits of the form 08* and 09* (which many browsers also do). case CharacterCodes._1: case CharacterCodes._2: case CharacterCodes._3: diff --git a/tests/baselines/reference/scannerES3NumericLiteral3.errors.txt b/tests/baselines/reference/scannerES3NumericLiteral3.errors.txt new file mode 100644 index 00000000000..42f7a908a76 --- /dev/null +++ b/tests/baselines/reference/scannerES3NumericLiteral3.errors.txt @@ -0,0 +1,4 @@ +==== tests/cases/conformance/scanner/ecmascript3/scannerES3NumericLiteral3.ts (1 errors) ==== + 01.0 + ~~ +!!! ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/scannerES3NumericLiteral3.js b/tests/baselines/reference/scannerES3NumericLiteral3.js deleted file mode 100644 index 7ecb6c8d377..00000000000 --- a/tests/baselines/reference/scannerES3NumericLiteral3.js +++ /dev/null @@ -1,5 +0,0 @@ -//// [scannerES3NumericLiteral3.ts] -01.0 - -//// [scannerES3NumericLiteral3.js] -01.0; diff --git a/tests/baselines/reference/scannerNumericLiteral3.errors.txt b/tests/baselines/reference/scannerNumericLiteral3.errors.txt new file mode 100644 index 00000000000..6f82581759b --- /dev/null +++ b/tests/baselines/reference/scannerNumericLiteral3.errors.txt @@ -0,0 +1,4 @@ +==== tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts (1 errors) ==== + 01.0 + ~~ +!!! ';' expected. \ No newline at end of file diff --git a/tests/baselines/reference/scannerNumericLiteral3.js b/tests/baselines/reference/scannerNumericLiteral3.js deleted file mode 100644 index 382c0622ac2..00000000000 --- a/tests/baselines/reference/scannerNumericLiteral3.js +++ /dev/null @@ -1,5 +0,0 @@ -//// [scannerNumericLiteral3.ts] -01.0 - -//// [scannerNumericLiteral3.js] -01.0; From 60e7f0850a9cefbaeb8c22a11a29061b4c573340 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 6 Aug 2014 12:16:39 -0700 Subject: [PATCH 2/6] Add es5 directive on scanner es5 tests --- .../conformance/scanner/ecmascript5/scannerNumericLiteral1.ts | 1 + .../conformance/scanner/ecmascript5/scannerNumericLiteral2.ts | 1 + .../conformance/scanner/ecmascript5/scannerNumericLiteral3.ts | 1 + .../conformance/scanner/ecmascript5/scannerNumericLiteral4.ts | 1 + .../conformance/scanner/ecmascript5/scannerNumericLiteral5.ts | 1 + .../conformance/scanner/ecmascript5/scannerNumericLiteral6.ts | 1 + .../conformance/scanner/ecmascript5/scannerNumericLiteral7.ts | 1 + 7 files changed, 7 insertions(+) diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral1.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral1.ts index c227083464f..23206bbe1f5 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral1.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral1.ts @@ -1 +1,2 @@ +// @target: ES5 0 \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral2.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral2.ts index a616ad491b1..60d12a43442 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral2.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral2.ts @@ -1 +1,2 @@ +// @target: ES5 01 \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts index 4df9ec3e7f8..fda0822c2f3 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts @@ -1 +1,2 @@ +// @target: ES5 01.0 \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral4.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral4.ts index 1405ebef530..092e6af6719 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral4.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral4.ts @@ -1 +1,2 @@ +// @target: ES5 1e \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral5.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral5.ts index 8757d5bc883..9a9804b4f0e 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral5.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral5.ts @@ -1 +1,2 @@ +// @target: ES5 1e0 \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral6.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral6.ts index 2ef6dce1b05..7ff2871b001 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral6.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral6.ts @@ -1 +1,2 @@ +// @target: ES5 1e+ \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral7.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral7.ts index e5f1cb60007..2e62350d48c 100644 --- a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral7.ts +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral7.ts @@ -1 +1,2 @@ +// @target: ES5 1e+0 \ No newline at end of file From 72cf78f68163fa86b95d95015c1c1a5f75357064 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 6 Aug 2014 15:41:11 -0700 Subject: [PATCH 3/6] Error on octal literals in ES5 and strict mode --- .../diagnosticInformationMap.generated.ts | 1 + src/compiler/diagnosticMessages.json | 4 ++ src/compiler/parser.ts | 18 ++++- tests/baselines/reference/literals.errors.txt | 6 +- tests/baselines/reference/literals.js | 68 ------------------- .../reference/objectLiteralErrors.errors.txt | 6 +- .../scannerNumericLiteral2.errors.txt | 4 ++ .../reference/scannerNumericLiteral2.js | 5 -- .../scannerNumericLiteral3.errors.txt | 4 +- 9 files changed, 39 insertions(+), 77 deletions(-) delete mode 100644 tests/baselines/reference/literals.js create mode 100644 tests/baselines/reference/scannerNumericLiteral2.errors.txt delete mode 100644 tests/baselines/reference/scannerNumericLiteral2.js diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 55dd45df789..cc789bcca11 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -105,6 +105,7 @@ module ts { An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name: { code: 1118, category: DiagnosticCategory.Error, key: "An object literal cannot have multiple get/set accessors with the same name." }, An_object_literal_cannot_have_property_and_accessor_with_the_same_name: { code: 1119, category: DiagnosticCategory.Error, key: "An object literal cannot have property and accessor with the same name." }, An_export_assignment_cannot_have_modifiers: { code: 1120, category: DiagnosticCategory.Error, key: "An export assignment cannot have modifiers." }, + Octal_literals_are_not_allowed_in_strict_mode: { code: 1121, category: DiagnosticCategory.Error, key: "Octal literals are not allowed in strict mode." }, Duplicate_identifier_0: { code: 2000, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, Extends_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 2018, category: DiagnosticCategory.Error, key: "Extends clause of exported class '{0}' has or is using private name '{1}'." }, Implements_clause_of_exported_class_0_has_or_is_using_private_name_1: { code: 2019, category: DiagnosticCategory.Error, key: "Implements clause of exported class '{0}' has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 30e3489374f..d60fd2e5c4f 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -412,6 +412,10 @@ "category": "Error", "code": 1120 }, + "Octal literals are not allowed in strict mode.": { + "category": "Error", + "code": 1121 + }, "Duplicate identifier '{0}'.": { "category": "Error", "code": 2000 diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 929e676c305..57e23531398 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1056,7 +1056,23 @@ module ts { var node = createNode(token); node.text = scanner.getTokenValue(); nextToken(); - return finishNode(node); + finishNode(node); + + // Octal literals are not allowed in strict mode or ES5 + if (node.kind === SyntaxKind.NumericLiteral && (isInStrictMode || languageVersion >= ScriptTarget.ES5)) { + var numberLiteralSource = getSourceTextOfNodeFromSourceText(sourceText, node); + // This regex checks if the number is written in octal + if (/0[0-7]+/.test(numberLiteralSource)) { + if (isInStrictMode) { + grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode); + } + else { + grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher); + } + } + } + + return node; } function parseStringLiteral(): LiteralExpression { diff --git a/tests/baselines/reference/literals.errors.txt b/tests/baselines/reference/literals.errors.txt index edfdad8c279..3361dfd5c67 100644 --- a/tests/baselines/reference/literals.errors.txt +++ b/tests/baselines/reference/literals.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/expressions/literals/literals.ts (4 errors) ==== +==== tests/cases/conformance/expressions/literals/literals.ts (6 errors) ==== //typeof null is Null //typeof true is Boolean @@ -27,11 +27,15 @@ var n = 1.0; var n = 1e4; var n = 001; // Error in ES5 + ~~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. var n = 0x1; var n = -1; var n = -1.0; var n = -1e-4; var n = -003; // Error in ES5 + ~~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. var n = -0x1; var s: string; diff --git a/tests/baselines/reference/literals.js b/tests/baselines/reference/literals.js deleted file mode 100644 index da11b6cef49..00000000000 --- a/tests/baselines/reference/literals.js +++ /dev/null @@ -1,68 +0,0 @@ -//// [literals.ts] - -//typeof null is Null -//typeof true is Boolean -//typeof false is Boolean -//typeof numeric literal is Number -//typeof string literal is String -//typeof regex literal is Regex - -var nu = null / null; -var u = undefined / undefined; - -var b: boolean; -var b = true; -var b = false; - -var n: number; -var n = 1; -var n = 1.0; -var n = 1e4; -var n = 001; // Error in ES5 -var n = 0x1; -var n = -1; -var n = -1.0; -var n = -1e-4; -var n = -003; // Error in ES5 -var n = -0x1; - -var s: string; -var s = ''; -var s = ""; -var s = 'foo\ - bar'; -var s = "foo\ - bar"; - -var r: RegExp; -var r = /what/; -var r = /\\\\/; - - -//// [literals.js] -var nu = null / null; -var u = undefined / undefined; -var b; -var b = true; -var b = false; -var n; -var n = 1; -var n = 1.0; -var n = 1e4; -var n = 001; -var n = 0x1; -var n = -1; -var n = -1.0; -var n = -1e-4; -var n = -003; -var n = -0x1; -var s; -var s = ''; -var s = ""; -var s = 'foo\ - bar'; -var s = "foo\ - bar"; -var r; -var r = /what/; -var r = /\\\\/; diff --git a/tests/baselines/reference/objectLiteralErrors.errors.txt b/tests/baselines/reference/objectLiteralErrors.errors.txt index 8e1b64f1758..6a36b93edbb 100644 --- a/tests/baselines/reference/objectLiteralErrors.errors.txt +++ b/tests/baselines/reference/objectLiteralErrors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/expressions/objectLiterals/objectLiteralErrors.ts (59 errors) ==== +==== tests/cases/conformance/expressions/objectLiterals/objectLiteralErrors.ts (61 errors) ==== // Multiple properties with the same name var e1 = { a: 0, a: 0 }; @@ -45,6 +45,8 @@ !!! Duplicate identifier '0x0'. var e14 = { 0: 0, 000: 0 }; ~~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. + ~~~ !!! Duplicate identifier '000'. var e15 = { "100": 0, 1e2: 0 }; ~~~ @@ -129,6 +131,8 @@ !!! Duplicate identifier '0x0'. var f14 = { 0: 0, get 000() { return 0; } }; ~~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. + ~~~ !!! An object literal cannot have property and accessor with the same name. ~~~ !!! Duplicate identifier '000'. diff --git a/tests/baselines/reference/scannerNumericLiteral2.errors.txt b/tests/baselines/reference/scannerNumericLiteral2.errors.txt new file mode 100644 index 00000000000..c9160bffdf2 --- /dev/null +++ b/tests/baselines/reference/scannerNumericLiteral2.errors.txt @@ -0,0 +1,4 @@ +==== tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral2.ts (1 errors) ==== + 01 + ~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. \ No newline at end of file diff --git a/tests/baselines/reference/scannerNumericLiteral2.js b/tests/baselines/reference/scannerNumericLiteral2.js deleted file mode 100644 index 382f1e6e4df..00000000000 --- a/tests/baselines/reference/scannerNumericLiteral2.js +++ /dev/null @@ -1,5 +0,0 @@ -//// [scannerNumericLiteral2.ts] -01 - -//// [scannerNumericLiteral2.js] -01; diff --git a/tests/baselines/reference/scannerNumericLiteral3.errors.txt b/tests/baselines/reference/scannerNumericLiteral3.errors.txt index 6f82581759b..ac751dd9089 100644 --- a/tests/baselines/reference/scannerNumericLiteral3.errors.txt +++ b/tests/baselines/reference/scannerNumericLiteral3.errors.txt @@ -1,4 +1,6 @@ -==== tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts (1 errors) ==== +==== tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral3.ts (2 errors) ==== 01.0 + ~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. ~~ !!! ';' expected. \ No newline at end of file From 083815893b1f2b6fa30ae6cfc8ebef340fb09c33 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 6 Aug 2014 16:26:34 -0700 Subject: [PATCH 4/6] Add test for octal literals in es3 strict mode --- .../reference/octalLiteralInStrictModeES3.errors.txt | 5 +++++ .../ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts | 2 ++ 2 files changed, 7 insertions(+) create mode 100644 tests/baselines/reference/octalLiteralInStrictModeES3.errors.txt create mode 100644 tests/cases/conformance/parser/ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts diff --git a/tests/baselines/reference/octalLiteralInStrictModeES3.errors.txt b/tests/baselines/reference/octalLiteralInStrictModeES3.errors.txt new file mode 100644 index 00000000000..c282d871aff --- /dev/null +++ b/tests/baselines/reference/octalLiteralInStrictModeES3.errors.txt @@ -0,0 +1,5 @@ +==== tests/cases/conformance/parser/ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts (1 errors) ==== + "use strict"; + 03; + ~~ +!!! Octal literals are not allowed in strict mode. \ No newline at end of file diff --git a/tests/cases/conformance/parser/ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts b/tests/cases/conformance/parser/ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts new file mode 100644 index 00000000000..9df305d1a26 --- /dev/null +++ b/tests/cases/conformance/parser/ecmascript5/StrictMode/octalLiteralInStrictModeES3.ts @@ -0,0 +1,2 @@ +"use strict"; +03; \ No newline at end of file From b1f71e6504b53cd172906429f34ea36012cb68a5 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 7 Aug 2014 12:08:31 -0700 Subject: [PATCH 5/6] Address feedback --- src/compiler/parser.ts | 5 +++++ tests/baselines/reference/scannerNumericLiteral8.errors.txt | 4 ++++ tests/baselines/reference/scannerNumericLiteral9.errors.txt | 6 ++++++ .../scanner/ecmascript5/scannerNumericLiteral8.ts | 2 ++ .../scanner/ecmascript5/scannerNumericLiteral9.ts | 2 ++ 5 files changed, 19 insertions(+) create mode 100644 tests/baselines/reference/scannerNumericLiteral8.errors.txt create mode 100644 tests/baselines/reference/scannerNumericLiteral9.errors.txt create mode 100644 tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral8.ts create mode 100644 tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral9.ts diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 57e23531398..5ab0dad085f 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1062,6 +1062,11 @@ module ts { if (node.kind === SyntaxKind.NumericLiteral && (isInStrictMode || languageVersion >= ScriptTarget.ES5)) { var numberLiteralSource = getSourceTextOfNodeFromSourceText(sourceText, node); // This regex checks if the number is written in octal + // Note that theoretically would match literals like 009, which is not octal. But because + // of how the scanner separates the tokens, we would never get a token like this. Instead, + // we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. if (/0[0-7]+/.test(numberLiteralSource)) { if (isInStrictMode) { grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode); diff --git a/tests/baselines/reference/scannerNumericLiteral8.errors.txt b/tests/baselines/reference/scannerNumericLiteral8.errors.txt new file mode 100644 index 00000000000..a55568d91e0 --- /dev/null +++ b/tests/baselines/reference/scannerNumericLiteral8.errors.txt @@ -0,0 +1,4 @@ +==== tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral8.ts (1 errors) ==== + -03 + ~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. \ No newline at end of file diff --git a/tests/baselines/reference/scannerNumericLiteral9.errors.txt b/tests/baselines/reference/scannerNumericLiteral9.errors.txt new file mode 100644 index 00000000000..610c1c0a5fc --- /dev/null +++ b/tests/baselines/reference/scannerNumericLiteral9.errors.txt @@ -0,0 +1,6 @@ +==== tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral9.ts (2 errors) ==== + 009 + ~~ +!!! Octal literals are not available when targeting ECMAScript 5 and higher. + ~ +!!! ';' expected. \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral8.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral8.ts new file mode 100644 index 00000000000..858e3eada0f --- /dev/null +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral8.ts @@ -0,0 +1,2 @@ +// @target: ES5 +-03 \ No newline at end of file diff --git a/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral9.ts b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral9.ts new file mode 100644 index 00000000000..cf187b83edf --- /dev/null +++ b/tests/cases/conformance/scanner/ecmascript5/scannerNumericLiteral9.ts @@ -0,0 +1,2 @@ +// @target: ES5 +009 \ No newline at end of file From cc7ca33eefe12bc42a66ad842132bb19475ce647 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 7 Aug 2014 12:49:52 -0700 Subject: [PATCH 6/6] Simplify checking for octal literals in parser --- src/compiler/parser.ts | 30 +++++++++++++++--------------- src/compiler/scanner.ts | 2 +- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index a7b2db64fb4..91a30143047 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1055,25 +1055,25 @@ module ts { function parseLiteralNode(): LiteralExpression { var node = createNode(token); node.text = scanner.getTokenValue(); + var tokenPos = scanner.getTokenPos(); nextToken(); finishNode(node); // Octal literals are not allowed in strict mode or ES5 - if (node.kind === SyntaxKind.NumericLiteral && (isInStrictMode || languageVersion >= ScriptTarget.ES5)) { - var numberLiteralSource = getSourceTextOfNodeFromSourceText(sourceText, node); - // This regex checks if the number is written in octal - // Note that theoretically would match literals like 009, which is not octal. But because - // of how the scanner separates the tokens, we would never get a token like this. Instead, - // we would get 00 and 9 as two separate tokens. - // We also do not need to check for negatives because any prefix operator would be part of a - // parent unary expression. - if (/0[0-7]+/.test(numberLiteralSource)) { - if (isInStrictMode) { - grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode); - } - else { - grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher); - } + // Note that theoretically the following condition would hold true literals like 009, + // which is not octal.But because of how the scanner separates the tokens, we would + // never get a token like this.Instead, we would get 00 and 9 as two separate tokens. + // We also do not need to check for negatives because any prefix operator would be part of a + // parent unary expression. + if (node.kind === SyntaxKind.NumericLiteral + && sourceText.charCodeAt(tokenPos) === CharacterCodes._0 + && isOctalDigit(sourceText.charCodeAt(tokenPos + 1))) { + + if (isInStrictMode) { + grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_allowed_in_strict_mode); + } + else if (languageVersion >= ScriptTarget.ES5) { + grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher); } } diff --git a/src/compiler/scanner.ts b/src/compiler/scanner.ts index c04cf3d8c23..00966b12f2a 100644 --- a/src/compiler/scanner.ts +++ b/src/compiler/scanner.ts @@ -300,7 +300,7 @@ module ts { return ch >= CharacterCodes._0 && ch <= CharacterCodes._9; } - function isOctalDigit(ch: number): boolean { + export function isOctalDigit(ch: number): boolean { return ch >= CharacterCodes._0 && ch <= CharacterCodes._7; }