From 96bef671de3e3faa906f2d3fbdfd80c710357c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Burzy=C5=84ski?= Date: Fri, 8 Dec 2023 00:16:44 +0100 Subject: [PATCH] Disallow negative numbers in create numeric literal (take 2) (#56570) Co-authored-by: Jake Bailey <5341706+jakebailey@users.noreply.github.com> --- src/compiler/checker.ts | 5 +++-- src/compiler/factory/nodeFactory.ts | 5 ++++- src/compiler/transformers/declarations.ts | 6 +++++- src/compiler/transformers/generators.ts | 2 +- src/compiler/transformers/ts.ts | 6 ++++-- 5 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 441a880e0e39f..56c4d8a2114c9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -48149,8 +48149,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (enumResult) return enumResult; const literalValue = (type as LiteralType).value; return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) : - typeof literalValue === "number" ? factory.createNumericLiteral(literalValue) : - factory.createStringLiteral(literalValue); + typeof literalValue === "string" ? factory.createStringLiteral(literalValue) : + literalValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-literalValue)) : + factory.createNumericLiteral(literalValue); } function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker) { diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 0de2b201803d9..907ab3833b672 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -44,6 +44,7 @@ import { CaseOrDefaultClause, cast, CatchClause, + CharacterCodes, ClassDeclaration, ClassElement, ClassExpression, @@ -1254,8 +1255,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { + const text = typeof value === "number" ? value + "" : value; + Debug.assert(text.charCodeAt(0) !== CharacterCodes.minus, "Negative numbers should be created in combination with createPrefixUnaryExpression"); const node = createBaseDeclaration(SyntaxKind.NumericLiteral); - node.text = typeof value === "number" ? value + "" : value; + node.text = text; node.numericLiteralFlags = numericLiteralFlags; if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags.ContainsES2015; return node; diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 45a5df4f0b95d..0f3479133ec55 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -1798,7 +1798,11 @@ export function transformDeclarations(context: TransformationContext) { if (shouldStripInternal(m)) return; // Rewrite enum values to their constants, if available const constValue = resolver.getConstantValue(m); - return preserveJsDoc(factory.updateEnumMember(m, m.name, constValue !== undefined ? typeof constValue === "string" ? factory.createStringLiteral(constValue) : factory.createNumericLiteral(constValue) : undefined), m); + const newInitializer = constValue === undefined ? undefined + : typeof constValue === "string" ? factory.createStringLiteral(constValue) + : constValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-constValue)) + : factory.createNumericLiteral(constValue); + return preserveJsDoc(factory.updateEnumMember(m, m.name, newInitializer), m); })), )); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 39f9a967e0cb3..775075a6e8f6f 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -2524,7 +2524,7 @@ export function transformGenerators(context: TransformationContext): (x: SourceF labelExpressions = []; } - const expression = factory.createNumericLiteral(-1); + const expression = factory.createNumericLiteral(Number.MAX_SAFE_INTEGER); if (labelExpressions[label] === undefined) { labelExpressions[label] = [expression]; } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index ac5855d72c8de..0548a5bf0da9c 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1901,7 +1901,9 @@ export function transformTypeScript(context: TransformationContext) { function transformEnumMemberDeclarationValue(member: EnumMember): Expression { const value = resolver.getConstantValue(member); if (value !== undefined) { - return typeof value === "string" ? factory.createStringLiteral(value) : factory.createNumericLiteral(value); + return typeof value === "string" ? factory.createStringLiteral(value) : + value < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-value)) : + factory.createNumericLiteral(value); } else { enableSubstitutionForNonQualifiedEnumMembers(); @@ -2687,7 +2689,7 @@ export function transformTypeScript(context: TransformationContext) { // track the constant value on the node for the printer in mayNeedDotDotForPropertyAccess setConstantValue(node, constantValue); const substitute = typeof constantValue === "string" ? factory.createStringLiteral(constantValue) : - constantValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(Math.abs(constantValue))) : + constantValue < 0 ? factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, factory.createNumericLiteral(-constantValue)) : factory.createNumericLiteral(constantValue); if (!compilerOptions.removeComments) {