From a20470e005278ba7409a8f7dc749d3dd0e0a5fb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Sun, 18 Feb 2018 18:33:22 +0800 Subject: [PATCH 1/2] disallow nan and infinity in enum member --- src/compiler/checker.ts | 8 +- .../reference/enumConstantMembers.errors.txt | 85 +++++++++++++++++++ .../reference/enumConstantMembers.js | 33 ++++++- .../reference/enumConstantMembers.symbols | 57 +++++++++++++ .../reference/enumConstantMembers.types | 83 ++++++++++++++++++ .../conformance/enums/enumConstantMembers.ts | 22 ++++- 6 files changed, 284 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/enumConstantMembers.errors.txt diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e8b31f7c9a475..ff8be6a0ba835 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24311,7 +24311,7 @@ namespace ts { const initializer = member.initializer; const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); if (value !== undefined) { - if (isConstEnum && typeof value === "number" && !isFinite(value)) { + if (typeof value === "number" && !isFinite(value)) { error(initializer, isNaN(value) ? Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN : Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); @@ -24376,7 +24376,11 @@ namespace ts { case SyntaxKind.ParenthesizedExpression: return evaluate((expr).expression); case SyntaxKind.Identifier: - return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), (expr).escapedText); + const identifier = expr; + if (isInfinityOrNaNString(identifier.escapedText)) { + return +(identifier.escapedText); + } + return nodeIsMissing(expr) ? 0 : evaluateEnumMember(expr, getSymbolOfNode(member.parent), identifier.escapedText); case SyntaxKind.ElementAccessExpression: case SyntaxKind.PropertyAccessExpression: const ex = expr; diff --git a/tests/baselines/reference/enumConstantMembers.errors.txt b/tests/baselines/reference/enumConstantMembers.errors.txt new file mode 100644 index 0000000000000..16bfa92a76169 --- /dev/null +++ b/tests/baselines/reference/enumConstantMembers.errors.txt @@ -0,0 +1,85 @@ +tests/cases/conformance/enums/enumConstantMembers.ts(22,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(23,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(24,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(25,9): error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. +tests/cases/conformance/enums/enumConstantMembers.ts(26,9): error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. +tests/cases/conformance/enums/enumConstantMembers.ts(27,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(28,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(32,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(33,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(34,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(35,9): error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. +tests/cases/conformance/enums/enumConstantMembers.ts(36,9): error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. +tests/cases/conformance/enums/enumConstantMembers.ts(37,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. +tests/cases/conformance/enums/enumConstantMembers.ts(38,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + + +==== tests/cases/conformance/enums/enumConstantMembers.ts (14 errors) ==== + // Constant members allow negatives, but not decimals. Also hex literals are allowed + enum E1 { + a = 1, + b + } + enum E2 { + a = - 1, + b + } + enum E3 { + a = 0.1, + b // Error because 0.1 is not a constant + } + + declare enum E4 { + a = 1, + b = -1, + c = 0.1 // Not a constant + } + + enum E5 { + a = 1 / 0, + ~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + b = 2 / 0.0, + ~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + c = 1.0 / 0.0, + ~~~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + d = 0.0 / 0.0, + ~~~~~~~~~ +!!! error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. + e = NaN, + ~~~ +!!! error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. + f = Infinity, + ~~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + g = -Infinity + ~~~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + } + + const enum E6 { + a = 1 / 0, + ~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + b = 2 / 0.0, + ~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + c = 1.0 / 0.0, + ~~~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + d = 0.0 / 0.0, + ~~~~~~~~~ +!!! error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. + e = NaN, + ~~~ +!!! error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. + f = Infinity, + ~~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + g = -Infinity + ~~~~~~~~~ +!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. + } + \ No newline at end of file diff --git a/tests/baselines/reference/enumConstantMembers.js b/tests/baselines/reference/enumConstantMembers.js index f58c7d253af08..a74d057063923 100644 --- a/tests/baselines/reference/enumConstantMembers.js +++ b/tests/baselines/reference/enumConstantMembers.js @@ -17,7 +17,28 @@ declare enum E4 { a = 1, b = -1, c = 0.1 // Not a constant -} +} + +enum E5 { + a = 1 / 0, + b = 2 / 0.0, + c = 1.0 / 0.0, + d = 0.0 / 0.0, + e = NaN, + f = Infinity, + g = -Infinity +} + +const enum E6 { + a = 1 / 0, + b = 2 / 0.0, + c = 1.0 / 0.0, + d = 0.0 / 0.0, + e = NaN, + f = Infinity, + g = -Infinity +} + //// [enumConstantMembers.js] // Constant members allow negatives, but not decimals. Also hex literals are allowed @@ -36,3 +57,13 @@ var E3; E3[E3["a"] = 0.1] = "a"; E3[E3["b"] = 1.1] = "b"; // Error because 0.1 is not a constant })(E3 || (E3 = {})); +var E5; +(function (E5) { + E5[E5["a"] = Infinity] = "a"; + E5[E5["b"] = Infinity] = "b"; + E5[E5["c"] = Infinity] = "c"; + E5[E5["d"] = NaN] = "d"; + E5[E5["e"] = NaN] = "e"; + E5[E5["f"] = Infinity] = "f"; + E5[E5["g"] = -Infinity] = "g"; +})(E5 || (E5 = {})); diff --git a/tests/baselines/reference/enumConstantMembers.symbols b/tests/baselines/reference/enumConstantMembers.symbols index 6bf516cceefbe..54a62d8911b49 100644 --- a/tests/baselines/reference/enumConstantMembers.symbols +++ b/tests/baselines/reference/enumConstantMembers.symbols @@ -40,3 +40,60 @@ declare enum E4 { c = 0.1 // Not a constant >c : Symbol(E4.c, Decl(enumConstantMembers.ts, 16, 11)) } + +enum E5 { +>E5 : Symbol(E5, Decl(enumConstantMembers.ts, 18, 1)) + + a = 1 / 0, +>a : Symbol(E5.a, Decl(enumConstantMembers.ts, 20, 9)) + + b = 2 / 0.0, +>b : Symbol(E5.b, Decl(enumConstantMembers.ts, 21, 14)) + + c = 1.0 / 0.0, +>c : Symbol(E5.c, Decl(enumConstantMembers.ts, 22, 16)) + + d = 0.0 / 0.0, +>d : Symbol(E5.d, Decl(enumConstantMembers.ts, 23, 18)) + + e = NaN, +>e : Symbol(E5.e, Decl(enumConstantMembers.ts, 24, 18)) +>NaN : Symbol(NaN, Decl(lib.d.ts, --, --)) + + f = Infinity, +>f : Symbol(E5.f, Decl(enumConstantMembers.ts, 25, 12)) +>Infinity : Symbol(Infinity, Decl(lib.d.ts, --, --)) + + g = -Infinity +>g : Symbol(E5.g, Decl(enumConstantMembers.ts, 26, 17)) +>Infinity : Symbol(Infinity, Decl(lib.d.ts, --, --)) +} + +const enum E6 { +>E6 : Symbol(E6, Decl(enumConstantMembers.ts, 28, 1)) + + a = 1 / 0, +>a : Symbol(E6.a, Decl(enumConstantMembers.ts, 30, 15)) + + b = 2 / 0.0, +>b : Symbol(E6.b, Decl(enumConstantMembers.ts, 31, 14)) + + c = 1.0 / 0.0, +>c : Symbol(E6.c, Decl(enumConstantMembers.ts, 32, 16)) + + d = 0.0 / 0.0, +>d : Symbol(E6.d, Decl(enumConstantMembers.ts, 33, 18)) + + e = NaN, +>e : Symbol(E6.e, Decl(enumConstantMembers.ts, 34, 18)) +>NaN : Symbol(NaN, Decl(lib.d.ts, --, --)) + + f = Infinity, +>f : Symbol(E6.f, Decl(enumConstantMembers.ts, 35, 12)) +>Infinity : Symbol(Infinity, Decl(lib.d.ts, --, --)) + + g = -Infinity +>g : Symbol(E6.g, Decl(enumConstantMembers.ts, 36, 17)) +>Infinity : Symbol(Infinity, Decl(lib.d.ts, --, --)) +} + diff --git a/tests/baselines/reference/enumConstantMembers.types b/tests/baselines/reference/enumConstantMembers.types index bfbf71a6c1738..0015a6debb3f9 100644 --- a/tests/baselines/reference/enumConstantMembers.types +++ b/tests/baselines/reference/enumConstantMembers.types @@ -48,3 +48,86 @@ declare enum E4 { >c : E4.c >0.1 : 0.1 } + +enum E5 { +>E5 : E5 + + a = 1 / 0, +>a : E5 +>1 / 0 : number +>1 : 1 +>0 : 0 + + b = 2 / 0.0, +>b : E5 +>2 / 0.0 : number +>2 : 2 +>0.0 : 0 + + c = 1.0 / 0.0, +>c : E5 +>1.0 / 0.0 : number +>1.0 : 1 +>0.0 : 0 + + d = 0.0 / 0.0, +>d : E5 +>0.0 / 0.0 : number +>0.0 : 0 +>0.0 : 0 + + e = NaN, +>e : E5 +>NaN : number + + f = Infinity, +>f : E5 +>Infinity : number + + g = -Infinity +>g : E5 +>-Infinity : number +>Infinity : number +} + +const enum E6 { +>E6 : E6 + + a = 1 / 0, +>a : E6 +>1 / 0 : number +>1 : 1 +>0 : 0 + + b = 2 / 0.0, +>b : E6 +>2 / 0.0 : number +>2 : 2 +>0.0 : 0 + + c = 1.0 / 0.0, +>c : E6 +>1.0 / 0.0 : number +>1.0 : 1 +>0.0 : 0 + + d = 0.0 / 0.0, +>d : E6 +>0.0 / 0.0 : number +>0.0 : 0 +>0.0 : 0 + + e = NaN, +>e : E6 +>NaN : number + + f = Infinity, +>f : E6 +>Infinity : number + + g = -Infinity +>g : E6 +>-Infinity : number +>Infinity : number +} + diff --git a/tests/cases/conformance/enums/enumConstantMembers.ts b/tests/cases/conformance/enums/enumConstantMembers.ts index e56828db06409..4970879b9c5b0 100644 --- a/tests/cases/conformance/enums/enumConstantMembers.ts +++ b/tests/cases/conformance/enums/enumConstantMembers.ts @@ -16,4 +16,24 @@ declare enum E4 { a = 1, b = -1, c = 0.1 // Not a constant -} \ No newline at end of file +} + +enum E5 { + a = 1 / 0, + b = 2 / 0.0, + c = 1.0 / 0.0, + d = 0.0 / 0.0, + e = NaN, + f = Infinity, + g = -Infinity +} + +const enum E6 { + a = 1 / 0, + b = 2 / 0.0, + c = 1.0 / 0.0, + d = 0.0 / 0.0, + e = NaN, + f = Infinity, + g = -Infinity +} From 45e6df955e6584db10f113c08ff596380006d024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Fri, 4 May 2018 10:33:12 +0800 Subject: [PATCH 2/2] only disallow infinite or nan in const enum --- src/compiler/checker.ts | 2 +- .../reference/enumConstantMembers.errors.txt | 23 +------------------ 2 files changed, 2 insertions(+), 23 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ff8be6a0ba835..5e799376e37c2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -24311,7 +24311,7 @@ namespace ts { const initializer = member.initializer; const value = enumKind === EnumKind.Literal && !isLiteralEnumMember(member) ? undefined : evaluate(initializer); if (value !== undefined) { - if (typeof value === "number" && !isFinite(value)) { + if (isConstEnum && typeof value === "number" && !isFinite(value)) { error(initializer, isNaN(value) ? Diagnostics.const_enum_member_initializer_was_evaluated_to_disallowed_value_NaN : Diagnostics.const_enum_member_initializer_was_evaluated_to_a_non_finite_value); diff --git a/tests/baselines/reference/enumConstantMembers.errors.txt b/tests/baselines/reference/enumConstantMembers.errors.txt index 16bfa92a76169..446f09040f963 100644 --- a/tests/baselines/reference/enumConstantMembers.errors.txt +++ b/tests/baselines/reference/enumConstantMembers.errors.txt @@ -1,10 +1,3 @@ -tests/cases/conformance/enums/enumConstantMembers.ts(22,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. -tests/cases/conformance/enums/enumConstantMembers.ts(23,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. -tests/cases/conformance/enums/enumConstantMembers.ts(24,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. -tests/cases/conformance/enums/enumConstantMembers.ts(25,9): error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. -tests/cases/conformance/enums/enumConstantMembers.ts(26,9): error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. -tests/cases/conformance/enums/enumConstantMembers.ts(27,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. -tests/cases/conformance/enums/enumConstantMembers.ts(28,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. tests/cases/conformance/enums/enumConstantMembers.ts(32,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. tests/cases/conformance/enums/enumConstantMembers.ts(33,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. tests/cases/conformance/enums/enumConstantMembers.ts(34,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. @@ -14,7 +7,7 @@ tests/cases/conformance/enums/enumConstantMembers.ts(37,9): error TS2477: 'const tests/cases/conformance/enums/enumConstantMembers.ts(38,9): error TS2477: 'const' enum member initializer was evaluated to a non-finite value. -==== tests/cases/conformance/enums/enumConstantMembers.ts (14 errors) ==== +==== tests/cases/conformance/enums/enumConstantMembers.ts (7 errors) ==== // Constant members allow negatives, but not decimals. Also hex literals are allowed enum E1 { a = 1, @@ -37,26 +30,12 @@ tests/cases/conformance/enums/enumConstantMembers.ts(38,9): error TS2477: 'const enum E5 { a = 1 / 0, - ~~~~~ -!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. b = 2 / 0.0, - ~~~~~~~ -!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. c = 1.0 / 0.0, - ~~~~~~~~~ -!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. d = 0.0 / 0.0, - ~~~~~~~~~ -!!! error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. e = NaN, - ~~~ -!!! error TS2478: 'const' enum member initializer was evaluated to disallowed value 'NaN'. f = Infinity, - ~~~~~~~~ -!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. g = -Infinity - ~~~~~~~~~ -!!! error TS2477: 'const' enum member initializer was evaluated to a non-finite value. } const enum E6 {