Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 13 additions & 5 deletions lib/node-loader-babel.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -19,15 +19,23 @@ function isBabelConfigFile(filename) {

export async function load(url, context, defaultLoad) {
if (useLoader(url)) {
const { source } = await defaultLoad(url, context, defaultLoad);
const { source, format } = await defaultLoad(url, context, defaultLoad);

// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if (format !== "module") {
return { source, format };
}
Comment on lines +24 to +30

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am nitpicking here but other formats include builtin, json, and wasm (see https://nodejs.org/api/esm.html#loadurl-context-defaultload). The logic makes sense. The comment could be improved.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

Suggested change
// Skip transpilation of CommonJS modules.
// These modules are already preprocessed by Node.js,
// so we cannot parse the non-standard syntaxes like JSX and TypeScript.
// Their transpilation is better handled separately by @babel/register or @babel/node.
if(format!=="module"){
return{ source, format };
}
if(format!=="module"&&format!=="commonjs"){
return{ source, format };
}

@make-github-pseudonymous-againmake-github-pseudonymous-againDec 28, 2021

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that skipping compilation of commonjs modules is a good universal assumption, since babel is completely capable of compiling commonjs modules. I agree skipping json, wasm, and builtin formats makes sense. As a separate feature, I think that we could let users of node-loader-babel customize which files are compiled by providing their own useLoader function. But that wouldn't be part of this PR.

Looking forward what you say makes sense. It may be that one day node loader handles the source key for {format: 'commonjs'}. But insisting on commonjs being transpiled now makes little sense. As far as I understand, with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null. Babel gracefully handles null by producing null with little overhead. If one day source is non-null and has meaning for format = 'commonjs' suddenly this loader will start transpiling CJS input without warning. Not sure if this is a real stability threat but I feel like it is a bad idea to leave this open for this code to be general just in the case of "if ...".

I agree this behavior could be configurable by the user of node-loader-babel. I just think the default should be to only process 'module' input.

Note that without this PR, when input format is commonjs, input and output source are null and output format is module which is the reason of the bug described in #7.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know, Babel doesn't change the format of modules by default (unless you add a plugin that does it). Babel preset env doesn't seem to do so by default (see this repl). So I would think it's safe to let babel just compile the file like normal?

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this REPL, enabling @babel/preset-env does transform ESM input into CJS output. How do you configure it so that it does not change format?

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

https://babeljs.io/docs/en/babel-preset-env#modules

I just think the default should be to only process 'module' input.

I can see how that would help solve the immediate problem, but don't think it's actually the proper behavior for node-loader-babel as a whole. If we can get babel to output the correct module format, there's no reason to avoid compilation of CJS files.

with the code of this PR, a commonjs input will have const {format, source} = await defaultLoad(...); such that format = 'commonjs' and source = null

Why would source be null? Does nodejs' default loader not provide commonjs source as a string? If so, then perhaps your suggestion of disabling would make more sense. But I thought that nodejs would give us the source as a string.

@make-github-pseudonymous-againmake-github-pseudonymous-againJan 5, 2022

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set babel preset env's modules option to false. The "auto" value also should work if we have called babel with the proper options

OK. I cannot find how to do this in the REPL, maybe it is not possible.


const filename = urlModule.fileURLToPath(url);
// Babel config files can themselves be ES modules,
// but we cannot transform those since doing so would cause an infinite loop.
if (isBabelConfigFile(filename)) {
return {
source,
format: /\.(c|m)?js$/.test(filename) ? "module" : "json",
format,
};
}

Expand All@@ -43,9 +51,9 @@ export async function load(url, context, defaultLoad) {

return {
source: transformed.code,
// Maybe a shaky assumption
// TODO: look at babel config to see whether it will output ESM/CJS or other formats
format: "module",
// NOTE: transform-modules-commonjs doesn't work properly.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which bug in transform-modules-commonjs you're referring to?

I don't think we ever need to forcibly change the module format - see my comment above about how I don't think babel will change module format unless explicitly told to do so via plugin, which is something controlled via babel config.

// We put a branch here just for consistency.
format: transformed.sourceType === "module" ? "module" : "commonjs",
Comment on lines +54 to +56

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does transformed.sourceType really reflect the output format? Perhaps it makes more sense to assume output is module or fail if it is not given source is not applicable for format: "commonjs" (see https://nodejs.org/api/esm.html#loadurl-context-defaultload).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know why transformed.sourceType would not reflect the real output format. Are there bugs in babel or common plugins that make this wrong?

I do not know, I am just confused as to whether sourceType corresponds to the input sourceType or the output sourceType, since source carries an input meaning to me. Experimental node loader uses the source keyword for both "input" and "output" but the babel equivalent is transformed.code. I could not find the Babel documentation that explains what transformed.sourceType means. If you can find it please share.

};
} else {
return defaultLoad(url, context, defaultLoad);
Expand Down
7 changes: 7 additions & 0 deletions test/basic.test.js
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,6 +10,13 @@ describe(`basic babel usage`, () => {
});
});

it(`allows loading CJS modules`, async () => {
const example = await import("./fixtures/basic/cjs.cjs");
assert.deepEqual(example.default, {
cjs: "cjs",
});
});
Comment on lines +13 to +18

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is neat!


it(`supports ES module babel config files`, async () => {
const mjsConfig = await import("./fixtures/mjs-config/main.js");
assert.deepEqual(mjsConfig.default, {
Expand Down
1 change: 1 addition & 0 deletions test/fixtures/basic/cjs.cjs
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
exports.cjs = "cjs";