diff --git a/mixed-format/fixture/cjs.js b/mixed-format/fixture/cjs.js new file mode 100644 index 0000000..b7d3583 --- /dev/null +++ b/mixed-format/fixture/cjs.js @@ -0,0 +1 @@ +exports.qux = require('./cjs2.js'); diff --git a/mixed-format/fixture/cjs2.js b/mixed-format/fixture/cjs2.js new file mode 100644 index 0000000..732f419 --- /dev/null +++ b/mixed-format/fixture/cjs2.js @@ -0,0 +1 @@ +module.exports = 'zed'; diff --git a/mixed-format/fixture/esm.js b/mixed-format/fixture/esm.js new file mode 100644 index 0000000..c155820 --- /dev/null +++ b/mixed-format/fixture/esm.js @@ -0,0 +1 @@ +export const foo = 'bar'; diff --git a/mixed-format/fixture/package.json b/mixed-format/fixture/package.json new file mode 100644 index 0000000..a0df0c8 --- /dev/null +++ b/mixed-format/fixture/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} diff --git a/mixed-format/loader.mjs b/mixed-format/loader.mjs new file mode 100644 index 0000000..afb903a --- /dev/null +++ b/mixed-format/loader.mjs @@ -0,0 +1,34 @@ +export async function load(url, context, nextLoad) { + if (!url.endsWith('.js')) return nextLoad(url); + + const nextResult = await nextLoad(url, { ...context, format: 'module' }) + .then((result) => { + if (containsCJS(result.source)) { throw new Error('CommonJS'); } + + return result; + }) + .catch(async (err) => { + if ( + (err?.message.includes('require') && err.includes('import')) + || err?.message.includes('CommonJS') + ) { + return { format: 'commonjs' }; + } + + throw err; + }); + + return nextResult; +} + +function containsCJS(source) { + const src = '' + source; + + // A realistic version of this loader would use a parser like Acorn to check for actual `module.exports` syntax + if (src.match(/exports[\.( ?=)]/)) { return true }; + + if ( + src.match(/require\(/) + && !src.match(/createRequire\(/) + ) return true; +} diff --git a/mixed-format/test.mjs b/mixed-format/test.mjs new file mode 100644 index 0000000..616dc86 --- /dev/null +++ b/mixed-format/test.mjs @@ -0,0 +1,8 @@ +import assert from 'node:assert'; + +import { foo } from './fixture/esm.js'; +import { qux } from './fixture/cjs.js'; + + +assert.strictEqual(foo, 'bar'); +assert.strictEqual(qux, 'zed');