denoland / deno

A modern runtime for JavaScript and TypeScript.
https://deno.com
MIT License
93.42k stars 5.18k forks source link

Bug: Missing stdio pipes with `node:child_process` #23524

Open marvinhagemeister opened 2 months ago

marvinhagemeister commented 2 months ago

Tried the current state of running playwright in Deno (see https://github.com/denoland/deno/issues/16899) and ran into an issue regarding the pipes set up for node:child_process.spawn(). The launcher code can be found here https://github.com/microsoft/playwright/blob/main/packages/playwright-core/src/utils/processLauncher.ts#L133

They expect to receive 5 streams to be set up, but we only set up the first three. I created a minimal reproduction out of that:

Steps to reproduce

  1. Create file main.mjs with these contents

    import cp from "node:child_process";
    import process from "node:process";
    
    if (import.meta.url.endsWith("main.mjs")) {
    const child = cp.spawn(process.execPath, [import.meta.url], {
      stdio: ["ignore", "pipe", "pipe", "pipe", "pipe"],
    });
    
    console.assert(
      child.stdio.length === 5,
      `Expected stdio length to equal 5 but got ${child.stdio.length}`
    );
    }
  2. Run DENO_FUTURE=1 deno run -A main.mjs

Can also be run in Node for comparison node main.mjs

Version: Deno 1.42.4 (git https://github.com/denoland/deno/commit/5294885a5a411e6b2e9674ce9d8f951c9c011988 2024-04-24)

cowboyd commented 2 months ago

@marvinhagemeister The docs only very briefly mention the ability to open other file descriptors https://nodejs.org/api/child_process.html#optionsstdio Is there any explainer anywhere on how they should behave?

marvinhagemeister commented 2 months ago

I'm not aware of any explainer. I don't know how they're supposed to work either. One would probably look at the Node source code to get an answer to that.

cowboyd commented 2 weeks ago

There isn't almost a day that goes by that I don't wish I had this working so that I could use Playwright from Deno. In fact, it is the only thing keeping my current work project on Node. If I wanted to take a stab at implementing this, do you have any pointers on where I should start?

uasi commented 3 hours ago

@cowboyd See https://github.com/denoland/deno/blob/v1.45.1/ext/node/polyfills/internal/child_process.ts#L178 . Here, the stream specifiers after the first three are discarded. We need to figure out how to handle this and pass it to new Deno.Command(). We also need to make Deno.Command ^1 accept additional streams and pass them down to ops::process::op_spawn_child ^2.

uasi commented 3 hours ago

https://github.com/denoland/deno/pull/24106 introduces changes to enable Deno's node:child_process polyfill to support a new type of stream. This might be useful as a reference when working on Deno.Command.