-
-
Notifications
You must be signed in to change notification settings - Fork 624
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
Promise deadlock when parsing commander actions #2795
Comments
it is private API, what is use case? |
We do double |
We want to programmatically call webpack and pass command-line arguments so that it will parse options and load the config the same way it would as if you called from the CLI. |
It doesn't seem like |
It looks like the
So in this case |
If you have idea how to fix, PR welcome, but it is private API and should not use directly |
Ideally we need this tj/commander.js#1276, but it as closed, maybe v8 solve the problem... |
Commander 8.0.0 just dropped and I'm happy to report the promise now resolves when following the reproduction steps 🎉 |
Awesome! Closing, feel free to open a new issue if you face any other problem. |
Let's keep open until we update |
we need do it once we drop Node 10 👍 |
Yep, I think we can start to work on it in the next branch - drop Node.js 10, drop webpack v4, update commander, simplify logic for options, use |
Describe the bug
I'm currently writing some unit tests for a project I'm working on that includes forwarding CLI arguments to Webpack. We do this by calling the
runCli
function defined inpackages/webpack-cli/lib/bootstrap.js
. Typically this seems to behave as if you were runningnpx webpack
on the command-line but I noticed when writing the tests that I was getting timeouts regardless of how long I set them withjest.setTimeout
.After some investigating I've found that the
Promise
returned byrunCli
never actually resolves, staying in a permanentpending
state. This isn't noticeable when running the command normally as node will exit regardless of whether there are pending promises if nothing is on the event loop. However, in a standard unit test in jest or mocha there is a timer running on the event loop to timeout the test if it takes too long. This means that thePromise
is never silently dropped and, paradoxically, guarantees the test will time out.What is the current behavior?
Calling
runCli
returns with aPromise
that never leaves thepending
state. This means any code after anawait runCli([...])
statement will not be executed.To Reproduce
After initialising a barebones webpack project with
just run
in the Node REPL. You can then observe that
promise
stays asPromise { <pending> }
, regardless of how long you wait. You may note the webpack compile stats are printed to the console and the bundle has been generated indist
but thePromise
remainspending
.Expected behavior
runCli
should resolve after the webpack actions have completedPlease paste the results of
webpack-cli info
here, and mention other relevant informationAdditional context
The reason why the
Promise
never resolves is becausewebpack-cli
recursively callsCommander.Command.parseAsync
. It first callsparseAsync
to execute anaction
for a webpack subcommand (likebuild
orwatch
) and then calls it again on a childCommand
object to interpret the options passed to the subcommand.parseAsync
is a simple function (defined here https://github.com/tj/commander.js/blob/v7.2.0/index.js#L1317) that waits on all the promises in its_actionResults
array. After the firstaction
is defined, it is pushed onto_actionResults
and subsequently waited on whenparseAsync
is called. Thisaction
includes defining anotheraction
, however a new command is first created:webpack-cli/packages/webpack-cli/lib/webpack-cli.js
Lines 103 to 107 in 9c6b341
Command
. Unfortunately,Command.action
actually pushes the action onto the_actionResults
array of the rootCommand
, in this case the original parentCommand
. This looks like behaviour that will change in Commander v8 (see tj/commander.js#1513) but for now means that both the parent and childCommand
calls toparseAsync
end up waiting on the samePromise
: deadlock!The text was updated successfully, but these errors were encountered: