Repository: rollup/rollup
File: src/ast/nodes/SwitchCase.ts (TypeScript)

Code before:
import type MagicString from 'magic-string';
import {
	findFirstOccurrenceOutsideComment,
	type NodeRenderOptions,
	type RenderOptions,
	renderStatementList
} from '../../utils/renderHelpers';
import type { HasEffectsContext, InclusionContext } from '../ExecutionContext';
import type * as NodeType from './NodeType';
import {
	doNotDeoptimize,
	type ExpressionNode,
	type IncludeChildren,
	NodeBase,
	onlyIncludeSelfNoDeoptimize,
	type StatementNode
} from './shared/Node';

export default class SwitchCase extends NodeBase {
	consequent!: readonly StatementNode[];
	needsBoundaries!: true;
	test!: ExpressionNode | null;
	type!: NodeType.tSwitchCase;

	hasEffects(context: HasEffectsContext): boolean {
		if (this.test?.hasEffects(context)) return true;
		for (const node of this.consequent) {
			if (context.brokenFlow) break;
			if (node.hasEffects(context)) return true;
		}
		return false;
	}

	include(context: InclusionContext, includeChildrenRecursively: IncludeChildren): void {
		this.included = true;
		this.test?.include(context, includeChildrenRecursively);
		for (const node of this.consequent) {
			if (includeChildrenRecursively || node.shouldBeIncluded(context))
				node.include(context, includeChildrenRecursively);
		}
	}

	render(code: MagicString, options: RenderOptions, nodeRenderOptions?: NodeRenderOptions): void {
		if (this.test) {
			this.test.render(code, options);
			if (this.test.start === this.start + 4) {
				code.prependLeft(this.test.start, ' ');
			}

Review comment (suggestion):
`SwitchCase.prototype.needsBoundaries = true` is set later in this file. Declaring `needsBoundaries!: true` emits an instance field initialized to `undefined`, which shadows the prototype flag and makes `needsBoundaries` falsy at runtime. This should remain `declare needsBoundaries: true` or be initialized to `true` as a real field.

Code after:
import type MagicString from 'magic-string';
import {
	findFirstOccurrenceOutsideComment,
	type NodeRenderOptions,
	type RenderOptions,
	renderStatementList
} from '../../utils/renderHelpers';
import type { HasEffectsContext, InclusionContext } from '../ExecutionContext';
import type * as NodeType from './NodeType';
import {
	doNotDeoptimize,
	type ExpressionNode,
	type IncludeChildren,
	NodeBase,
	onlyIncludeSelfNoDeoptimize,
	type StatementNode
} from './shared/Node';

export default class SwitchCase extends NodeBase {
	declare consequent: readonly StatementNode[];
	declare needsBoundaries: true;
	declare test: ExpressionNode | null;
	declare type: NodeType.tSwitchCase;

	hasEffects(context: HasEffectsContext): boolean {
		if (this.test?.hasEffects(context)) return true;
		for (const node of this.consequent) {
			if (context.brokenFlow) break;
			if (node.hasEffects(context)) return true;
		}
		return false;
	}

	include(context: InclusionContext, includeChildrenRecursively: IncludeChildren): void {
		this.included = true;
		this.test?.include(context, includeChildrenRecursively);
		for (const node of this.consequent) {
			if (includeChildrenRecursively || node.shouldBeIncluded(context))
				node.include(context, includeChildrenRecursively);
		}
	}

	render(code: MagicString, options: RenderOptions, nodeRenderOptions?: NodeRenderOptions): void {
		if (this.test) {
			this.test.render(code, options);
			if (this.test.start === this.start + 4) {
				code.prependLeft(this.test.start, ' ');
			}