Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[babel 8] Align @babel/node args parsing to Node.js #16706

Merged
merged 8 commits into from
Sep 6, 2024

Conversation

nicolo-ribaudo
Copy link
Member

@nicolo-ribaudo nicolo-ribaudo commented Jul 31, 2024

Q                       A
Fixed Issues? Fixes #16704, fixes #4373, fixes #13730
Patch: Bug Fix?
Major: Breaking Change?
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link babel/website#2950
Any Dependency Changes?
License MIT

This aligns args parsing of @babel/node to how Node.js parses arguments:

  • there is an optional inspect sub-command
  • then, there are all args for Node.js, V8, and Babel, in any order
  • optionally, there is a --
  • if not using the -e or -p flags, there is either - or a filepath
  • then, there are all the arguments to be passed to the script

This means that whether an argument is passed to process.argv or not does not depend on its name/value, but simply on its position.

To properly parse arguments, we need a list of arguments that take a value, so that we can know that in babel-node --require foo bar bar is the script, while in babel-node --expose-gc foo bar foo is the script. This is auto-generated, our CI will check that it includes all the flags from all the Node.js versions, so that it fails as soon as a new Node.js version is released telling us to add the flag if needed.

@nicolo-ribaudo nicolo-ribaudo added pkg: node PR: Bug Fix (next major) 🐛 A type of pull request used for our changelog categories for next major release labels Jul 31, 2024
import type { PluginAPI, PluginObject } from "@babel/core";

const require = createRequire(import.meta.url);

const program = process.env.BABEL_8_BREAKING
Copy link
Member Author

Choose a reason for hiding this comment

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

All the removed lines from this file are just moved to program-setup.ts

process.exitCode = 1;
});
} else {
const args = [babelNodePath];
Copy link
Member Author

Choose a reason for hiding this comment

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

All this else block is indented -- review with hidden whitespace diff

@@ -0,0 +1,4 @@
{
"BABEL_8_BREAKING": false,
"args": ["foo", "-r", "./dep"]
Copy link
Member Author

Choose a reason for hiding this comment

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

This exmaple shows different Babel 7 vs Node.js behavior

@babel-bot
Copy link
Collaborator

babel-bot commented Jul 31, 2024

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/57863

@liuxingbaoyu
Copy link
Member

liuxingbaoyu commented Jul 31, 2024

Amazing!
Given that https://www.npmjs.com/package/kexec only gets a few hundred downloads per week, perhaps we can remove its use in Babel 8.

#11402

@liuxingbaoyu
Copy link
Member

Also fixes #4373 and #13730 !

@nicolo-ribaudo
Copy link
Member Author

Removing kexec sounds good, I'll open a follow up PR for it.

@liuxingbaoyu liuxingbaoyu force-pushed the babel-8-node-args branch 3 times, most recently from 6080ef1 to 38e9fb9 Compare August 2, 2024 18:26
@liuxingbaoyu
Copy link
Member

The problem seems to come from here, but I'm not sure how to fix it elegantly. :)

var _nodeFlagsWithValue2 = require("../data/node-flags-with-value.json");
const nodeFlagsWithValue = new Set(_nodeFlagsWithValue2.default);

@nicolo-ribaudo
Copy link
Member Author

Thanks for investigating! I pushed a change that hopefully fixes this.

@@ -1,4 +1,4 @@
{
"args": ["foo", "--extensions", ".bar"],
"args": ["--extensions", ".bar", "foo"],
Copy link
Contributor

@JLHwung JLHwung Aug 5, 2024

Choose a reason for hiding this comment

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

If we exit the splitArgs program args scan without seeing --, can we scan the userArgs and make sure there is no match in node flags? If we have seen such match, we can print a warning message such as:

--extensions seems to be a babel-node/node option. Did you mean babel-node --extensions .bar foo? If you intend to pass --extensions to your script, please add -- after foo: babel-node foo -- --extensions. bar

Of course please improve the wordings here. This message should help people during their upgrades from 7 to 8.

If there are multiple matches, we can group the messages and provide one final suggestion.

Copy link
Member

Choose a reason for hiding this comment

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

Will this give rise to false positives? If so I would prefer to keep it as is.

Copy link
Member Author

Choose a reason for hiding this comment

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

This will indeed give false positive: for example, if you have a script that accepts an --extensions parameter, it will warn. However, it is easy to suppress the warning (by simply adding --), so it could be ok?

We could also remove the warning, for example, after that Babel 8 downloads surpass Babel 7 downloads, so that it's only there for the migration period.

Copy link
Member

Choose a reason for hiding this comment

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

That sounds good. :)

@@ -8,6 +8,7 @@
"--expose-gc-as=gc2",
"--config-file",
"./config.json",
"--extensions=.js,.ts",
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we print warning if there are only node options after the script name? E.g.

babel-node ./foo.js --expose_gc

Copy link
Member Author

Choose a reason for hiding this comment

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

We do not, because it would require us to keep the v8flags dependency just for that warning.

However, I'm less worried about that case since when using the Node.js CLI you already have to pass Node-specific options before the script name.

Copy link
Contributor

@JLHwung JLHwung Aug 26, 2024

Choose a reason for hiding this comment

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

I think it is fine to keep or inline the v8flags dependency and finally remove it in Babel 9. In Babel 7 the node options after the script name are still passed to node and we align the args parsing only starting from this Babel 8 PR.

For example, I searched babel-node [script name] --max-old-space-size=, while the majority get the ordering right, there are indeed a few usage where node options are after the script name, because it simply works for Babel 7:

https://github.com/Ocelyn/r3f-next-starter/blob/eaa6ad70409943ca6a6cb05e6e502ae994847a0d/package.json#L12

https://github.com/chairemobilite/evolution/blob/0aecdc436411fa15ef9991a3309c8e2898c2700c/example/demo_survey/package.json#L21

https://github.com/adieuadieu/japan-train-data/blob/0a31ec2665475c3e46da7ffc7786c33be9e7ac05/package.json#L38

Imagine if they upgrade to Babel 8, their app may stop working due to insufficient memory size. However, it will be a really confusing error: they might keep increasing the --max-old-space-size until they figure out that --max-old-space-size after the script name are no longer passed to the node. We could save them lots of time if we just keep v8flags for a while and remind them to update their usage.

We can also start printing warnings in Babel 7 if node options after the script name is seen, since they will not be supported in Babel 8.

`Run node ./packages/babel-node/scripts/list-node-flags.js --update to update it.`
);
// eslint-disable-next-line n/no-process-exit
process.exit(1);
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: we can just throw Missing flag as an error so that the process will exit with non-zero code.

@nicolo-ribaudo
Copy link
Member Author

@JLHwung I added the warning for Node.js / V8 options.

`passing the -- separator before the script name:\n` +
` babel-node ${programArgs.join(" ")} -- ${fileName} ${userArgs.join(" ")}\n` +
` If the intention is to pass ${them} to Babel, move ${them} before the filename:\n` +
` babel-node ${programArgs.join(" ")} ${ambiguousArgs.join(" ")} ${fileName} ${unambiguousArgs.join(" ")}\n`,
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Can we swap these two? I assume most people are intended to pass options to Babel / Node so let's offer the majority choice first.

Copy link
Member

@liuxingbaoyu liuxingbaoyu left a comment

Choose a reason for hiding this comment

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

Amazing!

@nicolo-ribaudo nicolo-ribaudo merged commit af1662b into babel:main Sep 6, 2024
52 checks passed
@nicolo-ribaudo nicolo-ribaudo deleted the babel-8-node-args branch September 6, 2024 11:06
@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Dec 7, 2024
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Dec 7, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: node PR: Bug Fix (next major) 🐛 A type of pull request used for our changelog categories for next major release
Projects
None yet
4 participants