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

Code before:
	private mechanism: DynamicImportMechanism | null = null;
	private namespaceExportName: string | false | undefined = undefined;
	private resolution: Module | ExternalModule | string | null = null;
	private resolutionString: string | null = null;

	get shouldBindAttributes() {
		return isFlagSet(this.flags, Flag.shouldBindAttributes);
	}

	set shouldBindAttributes(value: boolean) {
		this.flags = setFlag(this.flags, Flag.shouldBindAttributes, value);
	}

	get withinTopLevelAwait() {
		return isFlagSet(this.flags, Flag.withinTopLevelAwait);
	}

	set withinTopLevelAwait(value: boolean) {
		this.flags = setFlag(this.flags, Flag.withinTopLevelAwait, value);
	}

	bind(): void {
		this.source.bind();
		if (this.shouldBindAttributes) {
			this.options?.bind();
		}
	}

	/**
	 * Get imported variables for deterministic usage, valid cases are:
	 *
	 * 1. `const { foo } = await import('bar')`.
	 * 2. `(await import('bar')).foo`
	 * 3. `import('bar').then(({ foo }) => {})`
	 *
	 * Returns empty array if it's side-effect only import.
	 * Returns undefined if it's not fully deterministic.
	 */
	getDeterministicImportedNames(): readonly string[] | undefined {
		const parent1 = this.parent;

		// Side-effect only: import('bar')
		if (parent1 instanceof ExpressionStatement) {
			return EMPTY_ARRAY;
		}

		if (parent1 instanceof AwaitExpression) {
			const parent2 = parent1.parent;

			// Side-effect only: await import('bar')
			if (parent2 instanceof ExpressionStatement) {

Review comment (performance):
I think I would always bind it. There should be little performance impact for plain objects, but it would reduce complexity here.

Code after:
	private mechanism: DynamicImportMechanism | null = null;
	private namespaceExportName: string | false | undefined = undefined;
	private resolution: Module | ExternalModule | string | null = null;
	private resolutionString: string | null = null;

	get shouldIncludeDynamicAttributes() {
		return isFlagSet(this.flags, Flag.shouldIncludeDynamicAttributes);
	}

	set shouldIncludeDynamicAttributes(value: boolean) {
		this.flags = setFlag(this.flags, Flag.shouldIncludeDynamicAttributes, value);
	}

	get withinTopLevelAwait() {
		return isFlagSet(this.flags, Flag.withinTopLevelAwait);
	}

	set withinTopLevelAwait(value: boolean) {
		this.flags = setFlag(this.flags, Flag.withinTopLevelAwait, value);
	}

	bind(): void {
		this.source.bind();
		this.options?.bind();
	}

	/**
	 * Get imported variables for deterministic usage, valid cases are:
	 *
	 * 1. `const { foo } = await import('bar')`.
	 * 2. `(await import('bar')).foo`
	 * 3. `import('bar').then(({ foo }) => {})`
	 *
	 * Returns empty array if it's side-effect only import.
	 * Returns undefined if it's not fully deterministic.
	 */
	getDeterministicImportedNames(): readonly string[] | undefined {
		const parent1 = this.parent;

		// Side-effect only: import('bar')
		if (parent1 instanceof ExpressionStatement) {
			return EMPTY_ARRAY;
		}

		if (parent1 instanceof AwaitExpression) {
			const parent2 = parent1.parent;

			// Side-effect only: await import('bar')
			if (parent2 instanceof ExpressionStatement) {
				return EMPTY_ARRAY;
			}