diff --git a/.gitignore b/.gitignore index 6704566..b50e8d7 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,5 @@ dist # TernJS port file .tern-port + +.vscode diff --git a/README.md b/README.md index b1ee56c..544cc82 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,14 @@ export default { }; ``` +If the loader supports options, you pass them down like below. + +```js +export default { + loaders: [{ options: { someOption: true }, loader: importMapLoader }], +}; +``` + Then run node with the `--experimental-loader` flag: ```sh diff --git a/lib/node-loader-core.js b/lib/node-loader-core.js index e281036..2c986f4 100644 --- a/lib/node-loader-core.js +++ b/lib/node-loader-core.js @@ -124,8 +124,14 @@ function resolveLoaders(config) { function getLoaders(config, name) { return config.loaders - .filter((loader) => loader[name]) - .map((loader) => loader[name]); + .filter((loader) => (loader.loader ? loader.loader[name] : loader[name])) + .map((loader) => + loader.loader + ? (...args) => { + return loader.loader[name].apply(this, args.concat(loader.options)); + } + : loader[name] + ); } function flattenSequentialLoaders(config, name) { diff --git a/test/fixtures/krool3.js b/test/fixtures/krool3.js new file mode 100644 index 0000000..c41022a --- /dev/null +++ b/test/fixtures/krool3.js @@ -0,0 +1 @@ +export default "King K Rool might actually be a nice guy"; diff --git a/test/fixtures/yoshi-2.js b/test/fixtures/yoshi-2.js new file mode 100644 index 0000000..467cc12 --- /dev/null +++ b/test/fixtures/yoshi-2.js @@ -0,0 +1 @@ +export default "Yoshi doesn't deserve to be subservient to Mario"; diff --git a/test/load.test.js b/test/load.test.js index add002b..850a3b3 100644 --- a/test/load.test.js +++ b/test/load.test.js @@ -90,4 +90,51 @@ describe("load hook", () => { "What if we got it all wrong and DK is the evil one?" ); }); + + it(`supports passing down options to load hook`, async () => { + global.nodeLoader.setConfigPromise( + Promise.resolve({ + loaders: [ + { + options: { + capitalize: true, + }, + loader: { + load: async function (url, context, defaultLoad, loaderOptions) { + if (url.includes("krool3.js")) { + const { source: originalSource } = await defaultLoad( + url, + context + ); + + let str = + "I mean what did he even do to deserve Donkey Kong's wrath?"; + + if (loaderOptions?.capitalize) { + str = str.toUpperCase(); + } + + const finalSource = `${originalSource};\nexport const more = "${str}"`; + return { + format: "module", + source: finalSource, + }; + } else { + return defaultLoad(url, context); + } + }, + }, + }, + ], + }) + ); + + const ns = await import("./fixtures/krool3.js"); + assert.equal(ns.default, "King K Rool might actually be a nice guy"); + + assert.equal( + ns.more, + "I mean what did he even do to deserve Donkey Kong's wrath?".toUpperCase() + ); + }); }); diff --git a/test/resolve.test.js b/test/resolve.test.js index 64b004c..f319fee 100644 --- a/test/resolve.test.js +++ b/test/resolve.test.js @@ -83,4 +83,49 @@ describe("resolve hook", () => { const captainFalcon = await import("captainfalcon"); assert.equal(captainFalcon.default, "Captain Falcon 2"); }); + + it(`supports passing down options to resolve hook`, async () => { + global.nodeLoader.setConfigPromise( + Promise.resolve({ + loaders: [ + { + options: { + nocache: true, + }, + loader: { + resolve: async function ( + specifier, + context, + defaultResolve, + loaderOptions + ) { + const { parentURL = null } = context; + + if (specifier === "yoshi-2") { + const url = new URL("./fixtures/yoshi-2.js", parentURL).href; + + return { + url: loaderOptions?.nocache + ? url + `?${Math.random()}` + : url, + }; + } else { + return defaultResolve(specifier, context); + } + }, + }, + }, + ], + }) + ); + + const ns = await import("yoshi-2"); + assert.equal( + ns.default, + "Yoshi doesn't deserve to be subservient to Mario" + ); + + const ns2 = await import("yoshi-2"); + assert.notEqual(ns2, ns); + }); });