From b78b2dd99f0bfa149874901d19f087c7adaef628 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 19 Jul 2025 06:49:38 +0200 Subject: [PATCH] Make const reassignments only a warning --- src/ast/nodes/AssignmentExpression.ts | 11 +++++--- .../samples/error-const-reassign/_config.js | 21 --------------- .../samples/warning-const-reassign/_config.js | 27 +++++++++++++++++++ .../main.js | 0 4 files changed, 35 insertions(+), 24 deletions(-) delete mode 100644 test/function/samples/error-const-reassign/_config.js create mode 100644 test/function/samples/warning-const-reassign/_config.js rename test/function/samples/{error-const-reassign => warning-const-reassign}/main.js (100%) diff --git a/src/ast/nodes/AssignmentExpression.ts b/src/ast/nodes/AssignmentExpression.ts index f6e395699ab..baee66bb64e 100644 --- a/src/ast/nodes/AssignmentExpression.ts +++ b/src/ast/nodes/AssignmentExpression.ts @@ -1,5 +1,6 @@ import type MagicString from 'magic-string'; import { BLANK } from '../../utils/blank'; +import { LOGLEVEL_WARN } from '../../utils/logging'; import { logConstVariableReassignError } from '../../utils/logs'; import { findFirstOccurrenceOutsideComment, @@ -48,13 +49,15 @@ export default class AssignmentExpression extends NodeBase { | '??='; declare right: ExpressionNode; declare type: NodeType.tAssignmentExpression; + private isConstReassignment = false; hasEffects(context: HasEffectsContext): boolean { - const { deoptimized, left, operator, right } = this; + const { deoptimized, isConstReassignment, left, operator, right } = this; if (!deoptimized) this.applyDeoptimizations(); // MemberExpressions do not access the property before assignments if the // operator is '='. return ( + isConstReassignment || right.hasEffects(context) || left.hasEffectsAsAssignmentTarget(context, operator !== '=') || this.left.hasEffectsWhenDestructuring?.(context, EMPTY_PATH, right) @@ -70,12 +73,13 @@ export default class AssignmentExpression extends NodeBase { } include(context: InclusionContext, includeChildrenRecursively: IncludeChildren): void { - const { deoptimized, left, right, operator } = this; + const { deoptimized, isConstReassignment, left, right, operator } = this; if (!deoptimized) this.applyDeoptimizations(); if (!this.included) this.includeNode(context); const hasEffectsContext = createHasEffectsContext(); if ( includeChildrenRecursively || + isConstReassignment || operator !== '=' || left.included || left.hasEffectsAsAssignmentTarget(hasEffectsContext, false) || @@ -97,7 +101,8 @@ export default class AssignmentExpression extends NodeBase { if (this.left instanceof Identifier) { const variable = this.scope.variables.get(this.left.name); if (variable?.kind === 'const') { - this.scope.context.error(logConstVariableReassignError(), this.left.start); + this.isConstReassignment = true; + this.scope.context.log(LOGLEVEL_WARN, logConstVariableReassignError(), this.left.start); } } this.left.setAssignedValue(this.right); diff --git a/test/function/samples/error-const-reassign/_config.js b/test/function/samples/error-const-reassign/_config.js deleted file mode 100644 index 6763e27b00d..00000000000 --- a/test/function/samples/error-const-reassign/_config.js +++ /dev/null @@ -1,21 +0,0 @@ -const path = require('node:path'); -const MAIN_ID = path.resolve(__dirname, 'main.js'); - -module.exports = defineTest({ - description: 'Cannot reassign a variable declared with `const`', - error: { - code: 'CONST_REASSIGN', - frame: ` - 1: const foo = 1;\n2: foo = 2;\n ^ - `, - id: MAIN_ID, - loc: { - column: 0, - file: MAIN_ID, - line: 2 - }, - message: 'main.js (2:0): Cannot reassign a variable declared with `const`', - pos: 15, - watchFiles: [MAIN_ID] - } -}); diff --git a/test/function/samples/warning-const-reassign/_config.js b/test/function/samples/warning-const-reassign/_config.js new file mode 100644 index 00000000000..468399c1356 --- /dev/null +++ b/test/function/samples/warning-const-reassign/_config.js @@ -0,0 +1,27 @@ +const path = require('node:path'); +const assert = require('node:assert/strict'); +const MAIN_ID = path.resolve(__dirname, 'main.js'); + +module.exports = defineTest({ + solo: true, + description: 'Cannot reassign a variable declared with `const`', + warnings: [ + { + code: 'CONST_REASSIGN', + frame: ` + 1: const foo = 1;\n2: foo = 2;\n ^ + `, + id: MAIN_ID, + loc: { + column: 0, + file: MAIN_ID, + line: 2 + }, + message: 'main.js (2:0): Cannot reassign a variable declared with `const`', + pos: 15 + } + ], + runtimeError(error) { + assert.equal(error.name, 'TypeError'); + } +}); diff --git a/test/function/samples/error-const-reassign/main.js b/test/function/samples/warning-const-reassign/main.js similarity index 100% rename from test/function/samples/error-const-reassign/main.js rename to test/function/samples/warning-const-reassign/main.js