diff options
Diffstat (limited to 'cli')
-rw-r--r-- | cli/args/mod.rs | 11 | ||||
-rw-r--r-- | cli/factory.rs | 1 | ||||
-rw-r--r-- | cli/standalone/mod.rs | 1 | ||||
-rw-r--r-- | cli/tests/node_compat/config.jsonc | 18 | ||||
-rw-r--r-- | cli/tests/node_compat/test/parallel/test-child-process-fork-ref.js | 72 | ||||
-rw-r--r-- | cli/tests/node_compat/test/parallel/test-child-process-fork-ref2.js | 63 | ||||
-rw-r--r-- | cli/tests/node_compat/test/parallel/test-child-process-ipc-next-tick.js | 52 | ||||
-rw-r--r-- | cli/worker.rs | 5 |
8 files changed, 212 insertions, 11 deletions
diff --git a/cli/args/mod.rs b/cli/args/mod.rs index c65745e29..17711371a 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -939,6 +939,17 @@ impl CliOptions { .map(Some) } + pub fn node_ipc_fd(&self) -> Option<i32> { + let maybe_node_channel_fd = std::env::var("DENO_CHANNEL_FD").ok(); + if let Some(node_channel_fd) = maybe_node_channel_fd { + // Remove so that child processes don't inherit this environment variable. + std::env::remove_var("DENO_CHANNEL_FD"); + node_channel_fd.parse::<i32>().ok() + } else { + None + } + } + pub fn resolve_main_module(&self) -> Result<ModuleSpecifier, AnyError> { match &self.flags.subcommand { DenoSubcommand::Bundle(bundle_flags) => { diff --git a/cli/factory.rs b/cli/factory.rs index 5db09767c..0b21f6eca 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -672,6 +672,7 @@ impl CliFactory { self.maybe_lockfile().clone(), self.feature_checker().clone(), self.create_cli_main_worker_options()?, + self.options.node_ipc_fd(), )) } diff --git a/cli/standalone/mod.rs b/cli/standalone/mod.rs index a6bf12862..63f014118 100644 --- a/cli/standalone/mod.rs +++ b/cli/standalone/mod.rs @@ -530,6 +530,7 @@ pub async fn run( unstable: metadata.unstable, maybe_root_package_json_deps: package_json_deps_provider.deps().cloned(), }, + None, ); v8_set_flags(construct_v8_flags(&[], &metadata.v8_flags, vec![])); diff --git a/cli/tests/node_compat/config.jsonc b/cli/tests/node_compat/config.jsonc index 943be9759..a29d75a19 100644 --- a/cli/tests/node_compat/config.jsonc +++ b/cli/tests/node_compat/config.jsonc @@ -38,6 +38,10 @@ "test-child-process-execfile.js", "test-child-process-execsync-maxbuf.js", "test-child-process-exit-code.js", + // TODO(littledivy): windows ipc streams not yet implemented + "test-child-process-fork-ref.js", + "test-child-process-fork-ref2.js", + "test-child-process-ipc-next-tick.js", "test-child-process-ipc.js", "test-child-process-spawnsync-env.js", "test-child-process-stdio-inherit.js", @@ -109,9 +113,7 @@ "test-zlib-zero-windowBits.js" ], "pummel": [], - "sequential": [ - "test-child-process-exit.js" - ] + "sequential": ["test-child-process-exit.js"] }, "tests": { "common": [ @@ -138,11 +140,7 @@ "print-chars.js", "x.txt" ], - "fixtures/keys": [ - "agent1-cert.pem", - "agent1-key.pem", - "ca1-cert.pem" - ], + "fixtures/keys": ["agent1-cert.pem", "agent1-key.pem", "ca1-cert.pem"], "internet": [ "test-dns-any.js", "test-dns-idna2008.js", @@ -695,9 +693,7 @@ "test-tty-stdout-end.js" ], "pummel": [], - "sequential": [ - "test-child-process-exit.js" - ] + "sequential": ["test-child-process-exit.js"] }, "windowsIgnore": { "parallel": [ diff --git a/cli/tests/node_compat/test/parallel/test-child-process-fork-ref.js b/cli/tests/node_compat/test/parallel/test-child-process-fork-ref.js new file mode 100644 index 000000000..37c186af8 --- /dev/null +++ b/cli/tests/node_compat/test/parallel/test-child-process-fork-ref.js @@ -0,0 +1,72 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 18.12.1 +// This file is automatically generated by `tools/node_compat/setup.ts`. Do not modify this file manually. + +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +// Ignore on Windows. +if (process.platform === 'win32') { + process.exit(0); +} + +require('../common'); +const assert = require('assert'); +const fork = require('child_process').fork; + +if (process.argv[2] === 'child') { + process.send('1'); + + // Check that child don't instantly die + setTimeout(function() { + process.send('2'); + }, 200); + + process.on('disconnect', function() { + process.stdout.write('3'); + }); + +} else { + const child = fork(__filename, ['child'], { silent: true }); + + const ipc = []; + let stdout = ''; + + child.on('message', function(msg) { + ipc.push(msg); + + if (msg === '2') child.disconnect(); + }); + + child.stdout.on('data', function(chunk) { + stdout += chunk; + }); + + child.once('exit', function() { + assert.deepStrictEqual(ipc, ['1', '2']); + assert.strictEqual(stdout, '3'); + }); +} diff --git a/cli/tests/node_compat/test/parallel/test-child-process-fork-ref2.js b/cli/tests/node_compat/test/parallel/test-child-process-fork-ref2.js new file mode 100644 index 000000000..da59d9378 --- /dev/null +++ b/cli/tests/node_compat/test/parallel/test-child-process-fork-ref2.js @@ -0,0 +1,63 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 18.12.1 +// This file is automatically generated by `tools/node_compat/setup.ts`. Do not modify this file manually. + +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +'use strict'; + +// Ignore on Windows. +if (process.platform === 'win32') { + process.exit(0); +} + +const { + mustCall, + mustNotCall, + platformTimeout, +} = require('../common'); +const fork = require('child_process').fork; +const debug = require('util').debuglog('test'); + +if (process.argv[2] === 'child') { + debug('child -> call disconnect'); + process.disconnect(); + + setTimeout(() => { + debug('child -> will this keep it alive?'); + process.on('message', mustNotCall()); + }, platformTimeout(400)); + +} else { + const child = fork(__filename, ['child']); + + child.on('disconnect', mustCall(() => { + debug('parent -> disconnect'); + })); + + child.once('exit', mustCall(() => { + debug('parent -> exit'); + })); +} diff --git a/cli/tests/node_compat/test/parallel/test-child-process-ipc-next-tick.js b/cli/tests/node_compat/test/parallel/test-child-process-ipc-next-tick.js new file mode 100644 index 000000000..d255a0a64 --- /dev/null +++ b/cli/tests/node_compat/test/parallel/test-child-process-ipc-next-tick.js @@ -0,0 +1,52 @@ +// deno-fmt-ignore-file +// deno-lint-ignore-file + +// Copyright Joyent and Node contributors. All rights reserved. MIT license. +// Taken from Node 18.12.1 +// This file is automatically generated by `tools/node_compat/setup.ts`. Do not modify this file manually. + +'use strict'; + +// Ignore on Windows. +if (process.platform === 'win32') { + process.exit(0); +} + +const common = require('../common'); +const assert = require('assert'); +const cp = require('child_process'); +const NUM_MESSAGES = 10; +const values = []; + +for (let i = 0; i < NUM_MESSAGES; ++i) { + values[i] = i; +} + +if (process.argv[2] === 'child') { + const received = values.map(() => { return false; }); + + process.on('uncaughtException', common.mustCall((err) => { + received[err] = true; + const done = received.every((element) => { return element === true; }); + + if (done) + process.disconnect(); + }, NUM_MESSAGES)); + + process.on('message', (msg) => { + // If messages are handled synchronously, throwing should break the IPC + // message processing. + throw msg; + }); + + process.send('ready'); +} else { + const child = cp.fork(__filename, ['child']); + + child.on('message', common.mustCall((msg) => { + assert.strictEqual(msg, 'ready'); + values.forEach((value) => { + child.send(value); + }); + })); +} diff --git a/cli/worker.rs b/cli/worker.rs index ce9c05701..22e534e1d 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -124,6 +124,7 @@ struct SharedWorkerState { maybe_inspector_server: Option<Arc<InspectorServer>>, maybe_lockfile: Option<Arc<Mutex<Lockfile>>>, feature_checker: Arc<FeatureChecker>, + node_ipc: Option<i32>, } impl SharedWorkerState { @@ -415,6 +416,7 @@ impl CliMainWorkerFactory { maybe_lockfile: Option<Arc<Mutex<Lockfile>>>, feature_checker: Arc<FeatureChecker>, options: CliMainWorkerOptions, + node_ipc: Option<i32>, ) -> Self { Self { shared: Arc::new(SharedWorkerState { @@ -435,6 +437,7 @@ impl CliMainWorkerFactory { maybe_inspector_server, maybe_lockfile, feature_checker, + node_ipc, }), } } @@ -596,6 +599,7 @@ impl CliMainWorkerFactory { .options .maybe_binary_npm_command_name .clone(), + node_ipc_fd: shared.node_ipc, }, extensions: custom_extensions, startup_snapshot: crate::js::deno_isolate_init(), @@ -793,6 +797,7 @@ fn create_web_worker_callback( .options .maybe_binary_npm_command_name .clone(), + node_ipc_fd: None, }, extensions: vec![], startup_snapshot: crate::js::deno_isolate_init(), |