esbuild icon indicating copy to clipboard operation
esbuild copied to clipboard

feat: check __esModule in dynamic import

Open privatenumber opened this issue 2 years ago • 1 comments

Feature request

Wondering if dynamic imports (eg. import(specifier)) can be transformed to check for the __esModule property on the imported module in case it's ESM to CJS transformed.

Before

import('./esm.js').then(m => console.log(JSON.stringify(m)));

After

import('./esm.js').then((mod) => {
	const exports = Object.keys(mod);
	if (
		exports.length === 1
		&& exports[0] === 'default'
		&& mod.default.__esModule
	) {
		return mod.default;
	}

	return mod;
}).then(m => console.log(JSON.stringify(m)));

Problem

Currently, when transforming a ESM file to CJS via Transform API, import statements are transformed to use require() and wrapped in __toESM. However, dynamic imports are not transformed.

This leads to a discrepancy in what's exported by the module.

esm.js

export default 'default value';
export const dirname = __dirname;

index.js

import defaultValue, { dirname } from './esm.js';
console.log(defaultValue, dirname);
// default value ~/Desktop/test

import('./esm.js').then(m => console.log(JSON.stringify(m)));
// {"default":{"default":"default value","dirname":"~/Desktop/test"}}

Expected behavior

Since import statements are transformed to interop with CJS-transformed ESM files, I would also expect the dynamic imports to as well:

import defaultValue, { dirname } from './esm.js';
console.log(defaultValue, dirname);
// default value ~/Desktop/test

import('./esm.js').then(m => console.log(JSON.stringify(m)));
// {"default":"default value","dirname":"~/Desktop/test"}

privatenumber avatar May 15 '22 17:05 privatenumber

How is it going?

hanayashiki avatar Oct 31 '23 11:10 hanayashiki