Repository: rollup/rollup
File: src/ast/variables/NamespaceVariable.ts (TypeScript)

Code before:
import type { AstContext, default as Module } from '../../Module';
import { stringifyObjectKeyIfNeeded } from '../../utils/identifierHelpers';
import { getToStringTagValue, MERGE_NAMESPACES_VARIABLE } from '../../utils/interopHelpers';
import type { RenderOptions } from '../../utils/renderHelpers';
import { getSystemExportStatement } from '../../utils/systemJsRendering';
import type { HasEffectsContext, InclusionContext } from '../ExecutionContext';
import type { NodeInteraction } from '../NodeInteractions';
import { INTERACTION_ASSIGNED, INTERACTION_CALLED } from '../NodeInteractions';
import type { LiteralValueOrUnknown } from '../nodes/shared/Expression';
import { deoptimizeInteraction, UnknownValue } from '../nodes/shared/Expression';
import type IdentifierBase from '../nodes/shared/IdentifierBase';
import type ChildScope from '../scopes/ChildScope';
import type { EntityPathTracker, ObjectPath } from '../utils/PathTracker';
import { SymbolToStringTag, UNKNOWN_PATH } from '../utils/PathTracker';
import Variable from './Variable';

export default class NamespaceVariable extends Variable {
	readonly context: AstContext;
	isNamespace!: true;
	readonly module: Module;

	private areAllMembersDeoptimized = false;
	private mergedNamespaces: readonly Variable[] = [];
	private nonExplicitNamespacesIncluded = false;
	private referencedEarly = false;
	private readonly references: IdentifierBase[] = [];

	constructor(context: AstContext) {
		super(context.getModuleName());
		this.context = context;
		this.module = context.module;
	}

	addReference(identifier: IdentifierBase): void {
		this.references.push(identifier);
		this.name = identifier.name;
	}

	deoptimizeArgumentsOnInteractionAtPath(
		interaction: NodeInteraction,
		path: ObjectPath,
		recursionTracker: EntityPathTracker
	) {
		if (path.length > 1 || (path.length === 1 && interaction.type === INTERACTION_CALLED)) {
			const key = path[0];

Review comment (suggestion):
This class sets `NamespaceVariable.prototype.isNamespace = true` to enable runtime `isNamespace` checks (e.g. in `MemberExpression`). Declaring `isNamespace!: true` emits an instance field initialized to `undefined`, which shadows the prototype value and makes `isNamespace` falsy at runtime. Keep this as a type-only declaration (e.g. `declare readonly isNamespace: true`) or initialize it to `true` and remove the prototype assignment.

Code after:
import type { AstContext, default as Module } from '../../Module';
import { stringifyObjectKeyIfNeeded } from '../../utils/identifierHelpers';
import { getToStringTagValue, MERGE_NAMESPACES_VARIABLE } from '../../utils/interopHelpers';
import type { RenderOptions } from '../../utils/renderHelpers';
import { getSystemExportStatement } from '../../utils/systemJsRendering';
import type { HasEffectsContext, InclusionContext } from '../ExecutionContext';
import type { NodeInteraction } from '../NodeInteractions';
import { INTERACTION_ASSIGNED, INTERACTION_CALLED } from '../NodeInteractions';
import type { LiteralValueOrUnknown } from '../nodes/shared/Expression';
import { deoptimizeInteraction, UnknownValue } from '../nodes/shared/Expression';
import type IdentifierBase from '../nodes/shared/IdentifierBase';
import type ChildScope from '../scopes/ChildScope';
import type { EntityPathTracker, ObjectPath } from '../utils/PathTracker';
import { SymbolToStringTag, UNKNOWN_PATH } from '../utils/PathTracker';
import Variable from './Variable';

export default class NamespaceVariable extends Variable {
	readonly context: AstContext;
	declare isNamespace: true;
	readonly module: Module;

	private areAllMembersDeoptimized = false;
	private mergedNamespaces: readonly Variable[] = [];
	private nonExplicitNamespacesIncluded = false;
	private referencedEarly = false;
	private readonly references: IdentifierBase[] = [];

	constructor(context: AstContext) {
		super(context.getModuleName());
		this.context = context;
		this.module = context.module;
	}

	addReference(identifier: IdentifierBase): void {
		this.references.push(identifier);
		this.name = identifier.name;
	}

	deoptimizeArgumentsOnInteractionAtPath(
		interaction: NodeInteraction,
		path: ObjectPath,
		recursionTracker: EntityPathTracker
	) {
		if (path.length > 1 || (path.length === 1 && interaction.type === INTERACTION_CALLED)) {
			const key = path[0];