Skip to content

Commit f9fbc34

Browse files
Audit child_process externs for Node 24 and Haxe 4 (#248)
* Audit child_process externs for Node 24 and Haxe 4. Align IPC typing with Process, expose Symbol.dispose, fork detached, and narrow shell/windowsHide off fork; refresh docs and copyright through 2026. Co-authored-by: Cursor <cursoragent@cursor.com> * Fix ChildProcess.dispose to call Symbol.dispose. @:native("Symbol.dispose") compiled to a string-key lookup; use extern inline + Syntax.code so callers emit this[Symbol.dispose](). Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 5c2acfe commit f9fbc34

2 files changed

Lines changed: 101 additions & 44 deletions

File tree

src/js/node/ChildProcess.hx

Lines changed: 70 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C)2014-2020 Haxe Foundation
2+
* Copyright (C)2014-2026 Haxe Foundation
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -66,21 +66,6 @@ private typedef ChildProcessCommonOptions = {
6666
**/
6767
@:optional var gid:Int;
6868

69-
/**
70-
Shell to execute the command with.
71-
Default: `'/bin/sh'` on UNIX, `'cmd.exe'` on Windows.
72-
73-
The shell should understand the `-c` switch on UNIX or `/s /c` on Windows.
74-
On Windows, command line parsing should be compatible with `cmd.exe`.
75-
**/
76-
@:optional var shell:EitherType<Bool, String>;
77-
78-
/**
79-
Hide the subprocess console window that would normally be created on Windows.
80-
Default: `false`.
81-
**/
82-
@:optional var windowsHide:Bool;
83-
8469
/**
8570
No quoting or escaping of arguments is done on Windows.
8671
Ignored on Unix. Default: `false`.
@@ -120,13 +105,20 @@ private typedef ChildProcessSpawnOptionsBase = {
120105
Possible values are `'json'` and `'advanced'`. Default: `'json'`.
121106
**/
122107
@:optional var serialization:ChildProcessSerialization;
123-
}
124108

125-
/**
126-
Options for the `spawn` method.
127-
**/
128-
typedef ChildProcessSpawnOptions = {
129-
> ChildProcessSpawnOptionsBase,
109+
/**
110+
If `true`, runs `command` inside a shell.
111+
Uses `'/bin/sh'` on Unix and `process.env.ComSpec` on Windows.
112+
A different shell can be specified as a string.
113+
Default: `false` (no shell).
114+
**/
115+
@:optional var shell:EitherType<Bool, String>;
116+
117+
/**
118+
Hide the subprocess console window that would normally be created on Windows.
119+
Default: `false`.
120+
**/
121+
@:optional var windowsHide:Bool;
130122

131123
/**
132124
The child will be a process group leader / can keep running after parent exits.
@@ -140,14 +132,26 @@ typedef ChildProcessSpawnOptions = {
140132
@:optional var argv0:String;
141133
}
142134

135+
/**
136+
Options for the `spawn` method.
137+
**/
138+
typedef ChildProcessSpawnOptions = {
139+
> ChildProcessSpawnOptionsBase,
140+
}
141+
143142
/**
144143
Options for the `spawnSync` method.
145144
**/
146145
typedef ChildProcessSpawnSyncOptions = {
147146
> ChildProcessSpawnOptionsBase,
148147
> ChildProcessExecOptionsBase,
149148

150-
@:optional var input:EitherType<String, Buffer>;
149+
/**
150+
The value passed as stdin to the spawned process.
151+
Supplying this value overrides `stdio[0]`.
152+
Accepts a string or `ArrayBufferView` (Buffer, TypedArray, or DataView).
153+
**/
154+
@:optional var input:EitherType<String, js.lib.ArrayBufferView>;
151155
}
152156

153157
/**
@@ -165,6 +169,7 @@ typedef ChildProcessSpawnSyncOptions = {
165169
As a shorthand, the stdio argument may also be one of the following strings:
166170
ignore - ['ignore', 'ignore', 'ignore']
167171
pipe - ['pipe', 'pipe', 'pipe']
172+
overlapped - ['overlapped', 'overlapped', 'overlapped']
168173
inherit - [process.stdin, process.stdout, process.stderr] or [0,1,2]
169174
**/
170175
typedef ChildProcessSpawnOptionsStdio = EitherType<ChildProcessSpawnOptionsStdioSimple, ChildProcessSpawnOptionsStdioFull>;
@@ -246,6 +251,22 @@ private typedef ChildProcessExecOptionsBase = {
246251
Default: `1024 * 1024`
247252
**/
248253
@:optional var maxBuffer:Int;
254+
255+
/**
256+
If `true`, runs the command inside a shell.
257+
Uses `'/bin/sh'` on Unix and `process.env.ComSpec` on Windows.
258+
A different shell can be specified as a string.
259+
260+
For `exec`, a shell is always used (default `'/bin/sh'` / `ComSpec`).
261+
For `execFile`, default is `false` (no shell).
262+
**/
263+
@:optional var shell:EitherType<Bool, String>;
264+
265+
/**
266+
Hide the subprocess console window that would normally be created on Windows.
267+
Default: `false`.
268+
**/
269+
@:optional var windowsHide:Bool;
249270
}
250271

251272
/**
@@ -294,6 +315,12 @@ typedef ChildProcessForkOptions = {
294315
Specify the kind of serialization used for sending messages between processes.
295316
**/
296317
@:optional var serialization:ChildProcessSerialization;
318+
319+
/**
320+
Prepare the child to run independently of its parent process.
321+
Platform-specific; see Node.js `options.detached` docs.
322+
**/
323+
@:optional var detached:Bool;
297324
}
298325

299326
/**
@@ -360,7 +387,7 @@ typedef ChildProcessSpawnSyncResult = {
360387
/**
361388
The error object if the child process failed or timed out
362389
**/
363-
var error:Error;
390+
var error:Null<Error>;
364391
}
365392

366393
/**
@@ -373,19 +400,25 @@ extern class ChildProcess {
373400
/**
374401
Launches a new process with the given `command`, with command line arguments in `args`.
375402
If omitted, `args` defaults to an empty `Array`.
403+
404+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processspawncommand-args-options
376405
**/
377406
@:overload(function(command:String, ?options:ChildProcessSpawnOptions):ChildProcessObject {})
378407
@:overload(function(command:String, args:Array<String>, ?options:ChildProcessSpawnOptions):ChildProcessObject {})
379408
static function spawn(command:String, ?args:Array<String>):ChildProcessObject;
380409

381410
/**
382411
Runs a command in a shell and buffers the output.
412+
413+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processexeccommand-options-callback
383414
**/
384-
@:overload(function(command:String, options:ChildProcessExecOptions, callback:ChildProcessExecCallback):ChildProcessObject {})
385-
static function exec(command:String, callback:ChildProcessExecCallback):ChildProcessObject;
415+
@:overload(function(command:String, options:ChildProcessExecOptions, ?callback:ChildProcessExecCallback):ChildProcessObject {})
416+
static function exec(command:String, ?callback:ChildProcessExecCallback):ChildProcessObject;
386417

387418
/**
388419
Similar to `exec` except it does not execute a subshell but rather the specified file directly.
420+
421+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processexecfilefile-args-options-callback
389422
**/
390423
@:overload(function(file:String, args:Array<String>, options:ChildProcessExecFileOptions, ?callback:ChildProcessExecCallback):ChildProcessObject {})
391424
@:overload(function(file:String, options:ChildProcessExecFileOptions, ?callback:ChildProcessExecCallback):ChildProcessObject {})
@@ -394,28 +427,36 @@ extern class ChildProcess {
394427

395428
/**
396429
Special case of `spawn` for spawning Node.js processes with an IPC channel.
430+
431+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processforkmodulepath-args-options
397432
**/
398433
@:overload(function(modulePath:EitherType<String, URL>, args:Array<String>, options:ChildProcessForkOptions):ChildProcessObject {})
399434
@:overload(function(modulePath:EitherType<String, URL>, options:ChildProcessForkOptions):ChildProcessObject {})
400435
static function fork(modulePath:EitherType<String, URL>, ?args:Array<String>):ChildProcessObject;
401436

402437
/**
403438
Synchronous version of `spawn`.
439+
440+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processspawnsynccommand-args-options
404441
**/
405442
@:overload(function(command:String, args:Array<String>, ?options:ChildProcessSpawnSyncOptions):ChildProcessSpawnSyncResult {})
406443
static function spawnSync(command:String, ?options:ChildProcessSpawnSyncOptions):ChildProcessSpawnSyncResult;
407444

408445
/**
409446
Synchronous version of `execFile`.
410447
If the process times out, or has a non-zero exit code, this method will throw.
448+
449+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processexecfilesyncfile-args-options
411450
**/
412-
@:overload(function(command:String, ?options:ChildProcessSpawnSyncOptions):EitherType<String, Buffer> {})
413-
@:overload(function(command:String, args:Array<String>, ?options:ChildProcessSpawnSyncOptions):EitherType<String, Buffer> {})
414-
static function execFileSync(command:String, ?args:Array<String>):EitherType<String, Buffer>;
451+
@:overload(function(file:String, ?options:ChildProcessSpawnSyncOptions):EitherType<String, Buffer> {})
452+
@:overload(function(file:String, args:Array<String>, ?options:ChildProcessSpawnSyncOptions):EitherType<String, Buffer> {})
453+
static function execFileSync(file:String, ?args:Array<String>):EitherType<String, Buffer>;
415454

416455
/**
417456
Synchronous version of `exec`.
418457
If the process times out, or has a non-zero exit code, this method will throw.
458+
459+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#child_processexecsynccommand-options
419460
**/
420461
static function execSync(command:String, ?options:ChildProcessSpawnSyncOptions):EitherType<String, Buffer>;
421462
}

src/js/node/child_process/ChildProcess.hx

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (C)2014-2020 Haxe Foundation
2+
* Copyright (C)2014-2026 Haxe Foundation
33
*
44
* Permission is hereby granted, free of charge, to any person obtaining a
55
* copy of this software and associated documentation files (the "Software"),
@@ -88,15 +88,13 @@ enum abstract ChildProcessEvent<T:haxe.Constraints.Function>(Event<T>) to Event<
8888
var Disconnect:ChildProcessEvent<Void->Void> = "disconnect";
8989

9090
/**
91-
Messages send by `send` are obtained using the message event.
91+
Messages sent by `send` are obtained using the `'message'` event.
9292
9393
Listener arguments:
9494
message - a parsed JSON object or primitive value
95-
sendHandle - a Socket or Server object
96-
97-
// TODO(section-5): tighten message/sendHandle typing beyond Dynamic once IPC handle unions are modeled
95+
sendHandle - a `net.Socket`, `net.Server`, or `dgram.Socket` when one was sent
9896
**/
99-
var Message:ChildProcessEvent<Dynamic->Dynamic->Void> = "message";
97+
var Message:ChildProcessEvent<(message:Dynamic, sendHandle:Null<ChildProcessSendHandle>) -> Void> = "message";
10098

10199
/**
102100
The `'spawn'` event is emitted once the child process has spawned successfully.
@@ -201,10 +199,11 @@ extern class ChildProcess extends EventEmitter<ChildProcess> {
201199

202200
/**
203201
While the IPC channel established by `fork` is open, this is a reference to that channel.
204-
Otherwise `null`.
202+
Otherwise `null` / `undefined`.
203+
204+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocesschannel
205205
**/
206-
// TODO(section-5): type IPC channel pipe more precisely than Null<Dynamic>
207-
var channel(default, null):Null<Dynamic>;
206+
var channel(default, null):Null<ChildProcessChannel>;
208207

209208
/**
210209
Send a signal to the child process.
@@ -213,35 +212,52 @@ extern class ChildProcess extends EventEmitter<ChildProcess> {
213212
See signal(7) for a list of available signals.
214213
215214
Returns `true` if `kill()` succeeded, else `false`.
215+
216+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocesskillsignal
216217
**/
217218
function kill(?signal:EitherType<String, Int>):Bool;
218219

219220
/**
220-
When using `fork` you can write to the child using `send`
221-
and messages are received by a `'message'` event on the child.
221+
Calls `kill('SIGTERM')`. Available as `subprocess[Symbol.dispose]()`
222+
(stable since Node.js 24.2).
223+
224+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocesssymboldispose
225+
**/
226+
extern inline function dispose():Void
227+
js.Syntax.code("{0}[Symbol.dispose]()", this);
228+
229+
/**
230+
When using `fork`, write to the child using `send`;
231+
messages are received via the `'message'` event on the child.
222232
223-
// TODO(section-5): replace Dynamic message/sendHandle with structured IPC types
233+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocesssendmessage-sendhandle-options-callback
224234
**/
225-
@:overload(function(message:Dynamic, sendHandle:Dynamic, options:ChildProcessSendOptions, ?callback:Null<Error>->Void):Bool {})
226-
@:overload(function(message:Dynamic, sendHandle:Dynamic, ?callback:Null<Error>->Void):Bool {})
235+
@:overload(function(message:Dynamic, sendHandle:ChildProcessSendHandle, options:ChildProcessSendOptions, ?callback:Null<Error>->Void):Bool {})
236+
@:overload(function(message:Dynamic, sendHandle:ChildProcessSendHandle, ?callback:Null<Error>->Void):Bool {})
227237
function send(message:Dynamic, ?callback:Null<Error>->Void):Bool;
228238

229239
/**
230240
Close the IPC channel between parent and child, allowing the child to exit gracefully once there are no other
231241
connections keeping it alive.
242+
243+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocessdisconnect
232244
**/
233245
function disconnect():Void;
234246

235247
/**
236248
By default, the parent will wait for the detached child to exit.
237249
To prevent the parent from waiting for a given child, use the `unref` method.
250+
251+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocessunref
238252
**/
239253
function unref():Void;
240254

241255
/**
242-
Opposite of `unref()`. Calls reference the child from the parent's event loop so that
256+
Opposite of `unref()`. References the child from the parent's event loop so that
243257
the parent will wait for the child to exit before exiting itself
244258
(unless there are other references keeping the parent alive).
259+
260+
@see https://nodejs.org/docs/latest-v24.x/api/child_process.html#subprocessref
245261
**/
246262
function ref():Void;
247263
}

0 commit comments

Comments
 (0)