Skip to content

Commit

Permalink
fix(esm): cjs interop to support decorators
Browse files Browse the repository at this point in the history
fixes #582
  • Loading branch information
privatenumber committed Jun 8, 2024
1 parent 02d3856 commit 807f467
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 11 deletions.
13 changes: 5 additions & 8 deletions src/esm/hook/load.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { fileURLToPath } from 'node:url';
import type { LoadHook } from 'node:module';
import { readFile } from 'node:fs/promises';
import type { TransformOptions } from 'esbuild';
import { transform } from '../../utils/transform/index.js';
import { transform, transformSync } from '../../utils/transform/index.js';
import { transformDynamicImport } from '../../utils/transform/transform-dynamic-import.js';
import { inlineSourceMap } from '../../source-map.js';
import { isFeatureSupported, importAttributes, esmLoadReadFile } from '../../utils/node-features.js';
Expand Down Expand Up @@ -83,17 +83,14 @@ export const load: LoadHook = async (
* In fact, the code can't even run because imports cannot be resolved relative
* from the data: URL.
*
* TODO: extract exports only
* This should pre-compile for the CJS loader to have a cache hit
* TODO: extract exports only?
*/
const transformed = await transform(
const transformed = transformSync(
code,
filePath,
{
format: 'cjs',

// CJS Annotations for Node
platform: 'node',
// TODO: disable source maps
tsconfigRaw: fileMatcher?.(filePath) as TransformOptions['tsconfigRaw'],
},
);

Expand Down
4 changes: 4 additions & 0 deletions src/utils/transform/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export const transformSync = (
define,
banner: '(()=>{',
footer: '})()',

// CJS Annotations for Node. Used by ESM loader for CJS interop
platform: 'node',

...extendOptions,
} as const;

Expand Down
20 changes: 17 additions & 3 deletions tests/specs/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,15 @@ const tsFiles = {
export const foo = \`foo \${bar}\` as string
export const async = setTimeout(10).then(() => require('./async')).catch((error) => error);
`,
'exports-no.cts': 'console.log("cts loaded" as string)',
'exports-no.cts': `
// Supports decorators
const log = (target, key, descriptor) => descriptor;
class Example {
@log
greet() {}
}
console.log("cts loaded" as string)
`,
'exports-yes.cts': 'module.exports.cts = require("./esm-syntax.js").default as string',
'esm-syntax.js': 'export default "cts export"',
'bar.ts': 'export type A = 1; export { bar } from "pkg"',
Expand All @@ -36,6 +44,11 @@ const tsFiles = {
}),
'index.js': 'import "node:process"; export const bar = "bar";',
},
'tsconfig.json': createTsconfig({
compilerOptions: {
experimentalDecorators: true,
},
}),
...expectErrors,
};

Expand Down Expand Up @@ -527,7 +540,8 @@ export default testSuite(({ describe }, node: NodeApis) => {
...tsFiles,
});

const { stdout } = await execaNode(fixture.getPath('import.mjs'), [], {
const { stdout } = await execaNode('./import.mjs', [], {
cwd: fixture.path,
nodePath: node.path,
nodeOptions: [],
});
Expand Down Expand Up @@ -658,6 +672,7 @@ export default testSuite(({ describe }, node: NodeApis) => {

test('tsconfig disable', async () => {
await using fixture = await createFixture({
...tsFiles,
'package.json': createPackageJson({ type: 'module' }),
'tsconfig.json': createTsconfig({ extends: 'doesnt-exist' }),
'import.mjs': `
Expand All @@ -668,7 +683,6 @@ export default testSuite(({ describe }, node: NodeApis) => {
tsconfig: false,
});
`,
...tsFiles,
});

await execaNode('import.mjs', [], {
Expand Down

0 comments on commit 807f467

Please sign in to comment.