1 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
2 /* vim: set sts=2 sw=2 et tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 // This file is loaded into the same context as subprocess_unix.worker.js
9 // and subprocess_win.worker.js
10 /* import-globals-from subprocess_unix.worker.js */
12 /* exported BasePipe, BaseProcess, debug */
14 function debug(message
) {
15 self
.postMessage({ msg
: "debug", message
});
23 this.closedPromise
= new Promise(resolve
=> {
24 this.resolveClosed
= resolve
;
31 let result
= this.pending
.shift();
33 if (this.closing
&& !this.pending
.length
) {
41 let nextProcessId
= 0;
44 constructor(options
) {
45 this.id
= nextProcessId
++;
49 this.exitPromise
= new Promise(resolve
=> {
50 this.resolveExit
= resolve
;
52 this.exitPromise
.then(() => {
53 // The input file descriptors will be closed after poll
54 // reports that their input buffers are empty. If we close
55 // them now, we may lose output.
56 this.pipes
[0].close(true);
66 * Waits for the process to exit and all of its pending IO operations to
69 * @returns {Promise<void>}
74 ...this.pipes
.map(pipe
=> pipe
.closedPromise
),
92 close(pipeId
, force
= false) {
93 let pipe
= io
.getPipe(pipeId
);
95 return pipe
.close(force
).then(() => ({ data
: {} }));
99 let process
= new Process(options
);
100 let processId
= process
.id
;
102 io
.addProcess(process
);
104 let fds
= process
.pipes
.map(pipe
=> pipe
.id
);
106 return { data
: { processId
, fds
, pid
: process
.pid
} };
109 connectRunning(options
) {
110 let process
= new ManagedProcess(options
);
111 let processId
= process
.id
;
113 io
.addProcess(process
);
115 return { data
: { processId
, fds
: process
.pipes
.map(pipe
=> pipe
.id
) } };
118 kill(processId
, force
= false) {
119 let process
= io
.getProcess(processId
);
121 process
.kill(force
? 9 : 15);
127 let process
= io
.getProcess(processId
);
131 process
.awaitFinished().then(() => {
132 io
.cleanupProcess(process
);
135 return process
.exitPromise
.then(exitCode
=> {
136 return { data
: { exitCode
} };
140 read(pipeId
, count
) {
141 let pipe
= io
.getPipe(pipeId
);
143 return pipe
.read(count
).then(buffer
=> {
144 return { data
: { buffer
} };
148 write(pipeId
, buffer
) {
149 let pipe
= io
.getPipe(pipeId
);
151 return pipe
.write(buffer
).then(bytesWritten
=> {
152 return { data
: { bytesWritten
} };
157 return { data
: new Set(io
.pipes
.keys()) };
162 Array
.from(io
.processes
.values())
163 .filter(proc
=> proc
.exitCode
== null)
164 .map(proc
=> [proc
.id
, proc
.pid
])
169 waitForNoProcesses() {
171 Array
.from(io
.processes
.values(), proc
=> proc
.awaitFinished())
175 // It is the caller's responsability to make sure dup() is called on the FDs
178 // fd is a unix.Fd aka CDataFinalizer that wraps the actual integer. We can
179 // retrieve its value via .toString(), if it has not been closed yet.
180 let process
= io
.getProcess(processId
);
181 let pipes
= process
.pipes
.map(p
=> parseInt(p
.fd
.toString(), 10));
183 data
: [pipes
[0], pipes
[1], pipes
[2]],
188 onmessage
= event
=> {
191 let { msg
, msgId
, args
} = event
.data
;
193 new Promise(resolve
=> {
194 resolve(requests
[msg
](...args
));
203 self
.postMessage(response
, result
.transfer
|| []);
206 if (error
instanceof Error
) {
208 message
: error
.message
,
209 fileName
: error
.fileName
,
210 lineNumber
: error
.lineNumber
,
211 column
: error
.column
,
213 errorCode
: error
.errorCode
,
224 console
.error(error
);