@php-wasm/node 1.1.1 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/asyncify/7_2_34/php_7_2.wasm +0 -0
- package/asyncify/7_3_33/php_7_3.wasm +0 -0
- package/asyncify/7_4_33/php_7_4.wasm +0 -0
- package/asyncify/8_0_30/php_8_0.wasm +0 -0
- package/asyncify/8_1_23/php_8_1.wasm +0 -0
- package/asyncify/8_2_10/php_8_2.wasm +0 -0
- package/asyncify/8_3_0/php_8_3.wasm +0 -0
- package/asyncify/8_4_0/php_8_4.wasm +0 -0
- package/asyncify/php_7_2.js +179 -39
- package/asyncify/php_7_3.js +179 -39
- package/asyncify/php_7_4.js +179 -39
- package/asyncify/php_8_0.js +179 -39
- package/asyncify/php_8_1.js +179 -39
- package/asyncify/php_8_2.js +179 -39
- package/asyncify/php_8_3.js +179 -39
- package/asyncify/php_8_4.js +179 -39
- package/index.cjs +2710 -1213
- package/index.js +2710 -1213
- package/jspi/7_2_34/php_7_2.wasm +0 -0
- package/jspi/7_3_33/php_7_3.wasm +0 -0
- package/jspi/7_4_33/php_7_4.wasm +0 -0
- package/jspi/8_0_30/php_8_0.wasm +0 -0
- package/jspi/8_1_23/php_8_1.wasm +0 -0
- package/jspi/8_2_10/php_8_2.wasm +0 -0
- package/jspi/8_3_0/php_8_3.wasm +0 -0
- package/jspi/8_4_0/php_8_4.wasm +0 -0
- package/jspi/php_7_2.js +176 -36
- package/jspi/php_7_3.js +176 -36
- package/jspi/php_7_4.js +7703 -8484
- package/jspi/php_8_0.js +176 -36
- package/jspi/php_8_1.js +176 -36
- package/jspi/php_8_2.js +176 -36
- package/jspi/php_8_3.js +176 -36
- package/jspi/php_8_4.js +176 -36
- package/package.json +8 -8
package/jspi/php_8_0.js
CHANGED
|
@@ -3,26 +3,12 @@
|
|
|
3
3
|
// this code in Node.js as an ES module.
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* __filename and __dirname are not available in ES modules, so we need to
|
|
10
|
-
* polyfill them to ensure the debug command (npx nx debug playground-cli)
|
|
11
|
-
* works.
|
|
12
|
-
*
|
|
13
|
-
* @see https://nodejs.org/api/esm.html#no-__filename-or-__dirname
|
|
14
|
-
*/
|
|
6
|
+
// Note: The path module is currently needed by code injected by the php-wasm Dockerfile.
|
|
15
7
|
import path from 'path';
|
|
16
|
-
if (typeof __filename === 'undefined') {
|
|
17
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
}
|
|
19
|
-
if (typeof __dirname === 'undefined') {
|
|
20
|
-
var __dirname = path.dirname(__filename);
|
|
21
|
-
}
|
|
22
8
|
|
|
23
9
|
const dependencyFilename = path.join(__dirname, '8_0_30', 'php_8_0.wasm');
|
|
24
10
|
export { dependencyFilename };
|
|
25
|
-
export const dependenciesTotalSize =
|
|
11
|
+
export const dependenciesTotalSize = 17167885;
|
|
26
12
|
export function init(RuntimeName, PHPLoader) {
|
|
27
13
|
// The rest of the code comes from the built php.js file and esm-suffix.js
|
|
28
14
|
// include: shell.js
|
|
@@ -6982,6 +6968,44 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
6982
6968
|
// The files from the preload directory are preloaded using the
|
|
6983
6969
|
// auto_prepend_file php.ini directive.
|
|
6984
6970
|
FS.mkdir('/internal/shared/preload');
|
|
6971
|
+
// Create stdout and stderr devices. We can't just use Emscripten's
|
|
6972
|
+
// default stdout and stderr devices because they stop processing data
|
|
6973
|
+
// on the first null byte. However, when dealing with binary data,
|
|
6974
|
+
// null bytes are valid and common.
|
|
6975
|
+
FS.registerDevice(FS.makedev(64, 0), {
|
|
6976
|
+
open: () => {},
|
|
6977
|
+
close: () => {},
|
|
6978
|
+
read: () => 0,
|
|
6979
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
6980
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
6981
|
+
PHPWASM.onStdout(chunk);
|
|
6982
|
+
return length;
|
|
6983
|
+
},
|
|
6984
|
+
});
|
|
6985
|
+
FS.mkdev('/internal/stdout', FS.makedev(64, 0));
|
|
6986
|
+
FS.registerDevice(FS.makedev(63, 0), {
|
|
6987
|
+
open: () => {},
|
|
6988
|
+
close: () => {},
|
|
6989
|
+
read: () => 0,
|
|
6990
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
6991
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
6992
|
+
PHPWASM.onStderr(chunk);
|
|
6993
|
+
return length;
|
|
6994
|
+
},
|
|
6995
|
+
});
|
|
6996
|
+
FS.mkdev('/internal/stderr', FS.makedev(63, 0));
|
|
6997
|
+
FS.registerDevice(FS.makedev(62, 0), {
|
|
6998
|
+
open: () => {},
|
|
6999
|
+
close: () => {},
|
|
7000
|
+
read: () => 0,
|
|
7001
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
7002
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
7003
|
+
PHPWASM.onHeaders(chunk);
|
|
7004
|
+
return length;
|
|
7005
|
+
},
|
|
7006
|
+
});
|
|
7007
|
+
FS.mkdev('/internal/headers', FS.makedev(62, 0));
|
|
7008
|
+
// Handle events.
|
|
6985
7009
|
PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
|
|
6986
7010
|
? require('events').EventEmitter
|
|
6987
7011
|
: class EventEmitter {
|
|
@@ -7022,9 +7046,71 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7022
7046
|
}
|
|
7023
7047
|
}
|
|
7024
7048
|
};
|
|
7049
|
+
// Clean up the fd -> childProcess mapping when the fd is closed:
|
|
7050
|
+
const originalClose = FS.close;
|
|
7051
|
+
FS.close = function (stream) {
|
|
7052
|
+
originalClose(stream);
|
|
7053
|
+
delete PHPWASM.child_proc_by_fd[stream.fd];
|
|
7054
|
+
};
|
|
7025
7055
|
PHPWASM.child_proc_by_fd = {};
|
|
7026
7056
|
PHPWASM.child_proc_by_pid = {};
|
|
7027
7057
|
PHPWASM.input_devices = {};
|
|
7058
|
+
const originalWrite = TTY.stream_ops.write;
|
|
7059
|
+
TTY.stream_ops.write = function (stream, ...rest) {
|
|
7060
|
+
const retval = originalWrite(stream, ...rest);
|
|
7061
|
+
// Implicit flush since PHP's fflush() doesn't seem to trigger the fsync event
|
|
7062
|
+
// @TODO: Fix this at the wasm level
|
|
7063
|
+
stream.tty.ops.fsync(stream.tty);
|
|
7064
|
+
return retval;
|
|
7065
|
+
};
|
|
7066
|
+
const originalPutChar = TTY.stream_ops.put_char;
|
|
7067
|
+
TTY.stream_ops.put_char = function (tty, val) {
|
|
7068
|
+
/**
|
|
7069
|
+
* Buffer newlines that Emscripten normally ignores.
|
|
7070
|
+
*
|
|
7071
|
+
* Emscripten doesn't do it by default because its default
|
|
7072
|
+
* print function is console.log that implicitly adds a newline. We are overwriting
|
|
7073
|
+
* it with an environment-specific function that outputs exaclty what it was given,
|
|
7074
|
+
* e.g. in Node.js it's process.stdout.write(). Therefore, we need to mak sure
|
|
7075
|
+
* all the newlines make it to the output buffer.
|
|
7076
|
+
*/ if (val === 10) tty.output.push(val);
|
|
7077
|
+
return originalPutChar(tty, val);
|
|
7078
|
+
};
|
|
7079
|
+
},
|
|
7080
|
+
onHeaders: function (chunk) {
|
|
7081
|
+
if (Module['onHeaders']) {
|
|
7082
|
+
Module['onHeaders'](chunk);
|
|
7083
|
+
return;
|
|
7084
|
+
}
|
|
7085
|
+
console.log('headers', {
|
|
7086
|
+
chunk,
|
|
7087
|
+
});
|
|
7088
|
+
},
|
|
7089
|
+
onStdout: function (chunk) {
|
|
7090
|
+
if (Module['onStdout']) {
|
|
7091
|
+
Module['onStdout'](chunk);
|
|
7092
|
+
return;
|
|
7093
|
+
}
|
|
7094
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
7095
|
+
process.stdout.write(chunk);
|
|
7096
|
+
} else {
|
|
7097
|
+
console.log('stdout', {
|
|
7098
|
+
chunk,
|
|
7099
|
+
});
|
|
7100
|
+
}
|
|
7101
|
+
},
|
|
7102
|
+
onStderr: function (chunk) {
|
|
7103
|
+
if (Module['onStderr']) {
|
|
7104
|
+
Module['onStderr'](chunk);
|
|
7105
|
+
return;
|
|
7106
|
+
}
|
|
7107
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
7108
|
+
process.stderr.write(chunk);
|
|
7109
|
+
} else {
|
|
7110
|
+
console.warn('stderr', {
|
|
7111
|
+
chunk,
|
|
7112
|
+
});
|
|
7113
|
+
}
|
|
7028
7114
|
},
|
|
7029
7115
|
getAllWebSockets: function (sock) {
|
|
7030
7116
|
const webSockets = new Set();
|
|
@@ -7206,7 +7292,7 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7206
7292
|
argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2]));
|
|
7207
7293
|
}
|
|
7208
7294
|
}
|
|
7209
|
-
const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) :
|
|
7295
|
+
const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : FS.cwd();
|
|
7210
7296
|
let envObject = null;
|
|
7211
7297
|
if (envLength) {
|
|
7212
7298
|
envObject = {};
|
|
@@ -7279,6 +7365,15 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7279
7365
|
PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo;
|
|
7280
7366
|
PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo;
|
|
7281
7367
|
cp.on('exit', function (code) {
|
|
7368
|
+
for (const fd of [
|
|
7369
|
+
// The child process exited. Let's clean up its output streams:
|
|
7370
|
+
ProcInfo.stdoutChildFd,
|
|
7371
|
+
ProcInfo.stderrChildFd,
|
|
7372
|
+
]) {
|
|
7373
|
+
if (FS.streams[fd] && !FS.isClosed(FS.streams[fd])) {
|
|
7374
|
+
FS.close(FS.streams[fd]);
|
|
7375
|
+
}
|
|
7376
|
+
}
|
|
7282
7377
|
ProcInfo.exitCode = code;
|
|
7283
7378
|
ProcInfo.exited = true;
|
|
7284
7379
|
// Emit events for the wasm_poll_socket function.
|
|
@@ -7329,12 +7424,52 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7329
7424
|
* listen to the 'exit' event.
|
|
7330
7425
|
*/ try {
|
|
7331
7426
|
await new Promise((resolve, reject) => {
|
|
7332
|
-
|
|
7333
|
-
|
|
7427
|
+
/**
|
|
7428
|
+
* There was no `await` between the `spawnProcess` call
|
|
7429
|
+
* and the `await` below so the process haven't had a chance
|
|
7430
|
+
* to run any of the exit-related callbacks yet.
|
|
7431
|
+
*
|
|
7432
|
+
* Good.
|
|
7433
|
+
*
|
|
7434
|
+
* Let's listen to all the lifecycle events and resolve
|
|
7435
|
+
* the promise when the process starts or immediately crashes.
|
|
7436
|
+
*/ let resolved = false;
|
|
7437
|
+
cp.on('spawn', () => {
|
|
7438
|
+
if (resolved) return;
|
|
7439
|
+
resolved = true;
|
|
7440
|
+
resolve();
|
|
7441
|
+
});
|
|
7442
|
+
cp.on('error', (e) => {
|
|
7443
|
+
if (resolved) return;
|
|
7444
|
+
resolved = true;
|
|
7445
|
+
reject(e);
|
|
7446
|
+
});
|
|
7447
|
+
cp.on('exit', function (code) {
|
|
7448
|
+
if (resolved) return;
|
|
7449
|
+
resolved = true;
|
|
7450
|
+
if (code === 0) {
|
|
7451
|
+
resolve();
|
|
7452
|
+
} else {
|
|
7453
|
+
reject(
|
|
7454
|
+
new Error(`Process exited with code ${code}`)
|
|
7455
|
+
);
|
|
7456
|
+
}
|
|
7457
|
+
});
|
|
7458
|
+
/**
|
|
7459
|
+
* If the process haven't even started after 5 seconds, something
|
|
7460
|
+
* is wrong. Perhaps we're missing an event listener, or perhaps
|
|
7461
|
+
* the `spawnProcess` implementation failed to dispatch the relevant
|
|
7462
|
+
* event. Either way, let's crash to avoid blocking the proc_open()
|
|
7463
|
+
* call indefinitely.
|
|
7464
|
+
*/ setTimeout(() => {
|
|
7465
|
+
if (resolved) return;
|
|
7466
|
+
resolved = true;
|
|
7467
|
+
reject(new Error('Process timed out'));
|
|
7468
|
+
}, 5e3);
|
|
7334
7469
|
});
|
|
7335
7470
|
} catch (e) {
|
|
7336
7471
|
console.error(e);
|
|
7337
|
-
wakeUp(
|
|
7472
|
+
wakeUp(ProcInfo.pid);
|
|
7338
7473
|
return;
|
|
7339
7474
|
}
|
|
7340
7475
|
// Now we want to pass data from the STDIN source supplied by PHP
|
|
@@ -8044,14 +8179,7 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8044
8179
|
const POLLNVAL = 32;
|
|
8045
8180
|
return returnCallback((wakeUp) => {
|
|
8046
8181
|
const polls = [];
|
|
8047
|
-
if (socketd
|
|
8048
|
-
const procInfo = PHPWASM.child_proc_by_fd[socketd];
|
|
8049
|
-
if (procInfo.exited) {
|
|
8050
|
-
wakeUp(0);
|
|
8051
|
-
return;
|
|
8052
|
-
}
|
|
8053
|
-
polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data'));
|
|
8054
|
-
} else if (FS.isSocket(FS.getStream(socketd)?.node.mode)) {
|
|
8182
|
+
if (FS.isSocket(FS.getStream(socketd)?.node.mode)) {
|
|
8055
8183
|
const sock = getSocketFromFD(socketd);
|
|
8056
8184
|
if (!sock) {
|
|
8057
8185
|
wakeUp(0);
|
|
@@ -8085,7 +8213,12 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8085
8213
|
polls.push(PHPWASM.awaitConnection(ws));
|
|
8086
8214
|
lookingFor.add('POLLOUT');
|
|
8087
8215
|
}
|
|
8088
|
-
if (
|
|
8216
|
+
if (
|
|
8217
|
+
events & POLLHUP ||
|
|
8218
|
+
events & POLLIN ||
|
|
8219
|
+
events & POLLOUT ||
|
|
8220
|
+
events & POLLERR
|
|
8221
|
+
) {
|
|
8089
8222
|
polls.push(PHPWASM.awaitClose(ws));
|
|
8090
8223
|
lookingFor.add('POLLHUP');
|
|
8091
8224
|
}
|
|
@@ -8094,6 +8227,13 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8094
8227
|
lookingFor.add('POLLERR');
|
|
8095
8228
|
}
|
|
8096
8229
|
}
|
|
8230
|
+
} else if (socketd in PHPWASM.child_proc_by_fd) {
|
|
8231
|
+
const procInfo = PHPWASM.child_proc_by_fd[socketd];
|
|
8232
|
+
if (procInfo.exited) {
|
|
8233
|
+
wakeUp(0);
|
|
8234
|
+
return;
|
|
8235
|
+
}
|
|
8236
|
+
polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data'));
|
|
8097
8237
|
} else {
|
|
8098
8238
|
setTimeout(function () {
|
|
8099
8239
|
wakeUp(1);
|
|
@@ -8380,13 +8520,6 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8380
8520
|
(___wrap_select = Module['___wrap_select'] =
|
|
8381
8521
|
wasmExports['__wrap_select'])(a0, a1, a2, a3, a4));
|
|
8382
8522
|
|
|
8383
|
-
var _wasm_add_cli_arg = (Module['_wasm_add_cli_arg'] = (a0) =>
|
|
8384
|
-
(_wasm_add_cli_arg = Module['_wasm_add_cli_arg'] =
|
|
8385
|
-
wasmExports['wasm_add_cli_arg'])(a0));
|
|
8386
|
-
|
|
8387
|
-
var _run_cli = (Module['_run_cli'] = () =>
|
|
8388
|
-
(_run_cli = Module['_run_cli'] = wasmExports['run_cli'])());
|
|
8389
|
-
|
|
8390
8523
|
var _wasm_set_sapi_name = (Module['_wasm_set_sapi_name'] = (a0) =>
|
|
8391
8524
|
(_wasm_set_sapi_name = Module['_wasm_set_sapi_name'] =
|
|
8392
8525
|
wasmExports['wasm_set_sapi_name'])(a0));
|
|
@@ -8395,6 +8528,13 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8395
8528
|
(_wasm_set_phpini_path = Module['_wasm_set_phpini_path'] =
|
|
8396
8529
|
wasmExports['wasm_set_phpini_path'])(a0));
|
|
8397
8530
|
|
|
8531
|
+
var _wasm_add_cli_arg = (Module['_wasm_add_cli_arg'] = (a0) =>
|
|
8532
|
+
(_wasm_add_cli_arg = Module['_wasm_add_cli_arg'] =
|
|
8533
|
+
wasmExports['wasm_add_cli_arg'])(a0));
|
|
8534
|
+
|
|
8535
|
+
var _run_cli = (Module['_run_cli'] = () =>
|
|
8536
|
+
(_run_cli = Module['_run_cli'] = wasmExports['run_cli'])());
|
|
8537
|
+
|
|
8398
8538
|
var _wasm_add_SERVER_entry = (Module['_wasm_add_SERVER_entry'] = (a0, a1) =>
|
|
8399
8539
|
(_wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] =
|
|
8400
8540
|
wasmExports['wasm_add_SERVER_entry'])(a0, a1));
|
package/jspi/php_8_1.js
CHANGED
|
@@ -3,26 +3,12 @@
|
|
|
3
3
|
// this code in Node.js as an ES module.
|
|
4
4
|
import { createRequire } from 'module';
|
|
5
5
|
const require = createRequire(import.meta.url);
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* __filename and __dirname are not available in ES modules, so we need to
|
|
10
|
-
* polyfill them to ensure the debug command (npx nx debug playground-cli)
|
|
11
|
-
* works.
|
|
12
|
-
*
|
|
13
|
-
* @see https://nodejs.org/api/esm.html#no-__filename-or-__dirname
|
|
14
|
-
*/
|
|
6
|
+
// Note: The path module is currently needed by code injected by the php-wasm Dockerfile.
|
|
15
7
|
import path from 'path';
|
|
16
|
-
if (typeof __filename === 'undefined') {
|
|
17
|
-
var __filename = fileURLToPath(import.meta.url);
|
|
18
|
-
}
|
|
19
|
-
if (typeof __dirname === 'undefined') {
|
|
20
|
-
var __dirname = path.dirname(__filename);
|
|
21
|
-
}
|
|
22
8
|
|
|
23
9
|
const dependencyFilename = path.join(__dirname, '8_1_23', 'php_8_1.wasm');
|
|
24
10
|
export { dependencyFilename };
|
|
25
|
-
export const dependenciesTotalSize =
|
|
11
|
+
export const dependenciesTotalSize = 17183362;
|
|
26
12
|
export function init(RuntimeName, PHPLoader) {
|
|
27
13
|
// The rest of the code comes from the built php.js file and esm-suffix.js
|
|
28
14
|
// include: shell.js
|
|
@@ -7010,6 +6996,44 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7010
6996
|
// The files from the preload directory are preloaded using the
|
|
7011
6997
|
// auto_prepend_file php.ini directive.
|
|
7012
6998
|
FS.mkdir('/internal/shared/preload');
|
|
6999
|
+
// Create stdout and stderr devices. We can't just use Emscripten's
|
|
7000
|
+
// default stdout and stderr devices because they stop processing data
|
|
7001
|
+
// on the first null byte. However, when dealing with binary data,
|
|
7002
|
+
// null bytes are valid and common.
|
|
7003
|
+
FS.registerDevice(FS.makedev(64, 0), {
|
|
7004
|
+
open: () => {},
|
|
7005
|
+
close: () => {},
|
|
7006
|
+
read: () => 0,
|
|
7007
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
7008
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
7009
|
+
PHPWASM.onStdout(chunk);
|
|
7010
|
+
return length;
|
|
7011
|
+
},
|
|
7012
|
+
});
|
|
7013
|
+
FS.mkdev('/internal/stdout', FS.makedev(64, 0));
|
|
7014
|
+
FS.registerDevice(FS.makedev(63, 0), {
|
|
7015
|
+
open: () => {},
|
|
7016
|
+
close: () => {},
|
|
7017
|
+
read: () => 0,
|
|
7018
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
7019
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
7020
|
+
PHPWASM.onStderr(chunk);
|
|
7021
|
+
return length;
|
|
7022
|
+
},
|
|
7023
|
+
});
|
|
7024
|
+
FS.mkdev('/internal/stderr', FS.makedev(63, 0));
|
|
7025
|
+
FS.registerDevice(FS.makedev(62, 0), {
|
|
7026
|
+
open: () => {},
|
|
7027
|
+
close: () => {},
|
|
7028
|
+
read: () => 0,
|
|
7029
|
+
write: (stream, buffer, offset, length, pos) => {
|
|
7030
|
+
const chunk = buffer.subarray(offset, offset + length);
|
|
7031
|
+
PHPWASM.onHeaders(chunk);
|
|
7032
|
+
return length;
|
|
7033
|
+
},
|
|
7034
|
+
});
|
|
7035
|
+
FS.mkdev('/internal/headers', FS.makedev(62, 0));
|
|
7036
|
+
// Handle events.
|
|
7013
7037
|
PHPWASM.EventEmitter = ENVIRONMENT_IS_NODE
|
|
7014
7038
|
? require('events').EventEmitter
|
|
7015
7039
|
: class EventEmitter {
|
|
@@ -7050,9 +7074,71 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7050
7074
|
}
|
|
7051
7075
|
}
|
|
7052
7076
|
};
|
|
7077
|
+
// Clean up the fd -> childProcess mapping when the fd is closed:
|
|
7078
|
+
const originalClose = FS.close;
|
|
7079
|
+
FS.close = function (stream) {
|
|
7080
|
+
originalClose(stream);
|
|
7081
|
+
delete PHPWASM.child_proc_by_fd[stream.fd];
|
|
7082
|
+
};
|
|
7053
7083
|
PHPWASM.child_proc_by_fd = {};
|
|
7054
7084
|
PHPWASM.child_proc_by_pid = {};
|
|
7055
7085
|
PHPWASM.input_devices = {};
|
|
7086
|
+
const originalWrite = TTY.stream_ops.write;
|
|
7087
|
+
TTY.stream_ops.write = function (stream, ...rest) {
|
|
7088
|
+
const retval = originalWrite(stream, ...rest);
|
|
7089
|
+
// Implicit flush since PHP's fflush() doesn't seem to trigger the fsync event
|
|
7090
|
+
// @TODO: Fix this at the wasm level
|
|
7091
|
+
stream.tty.ops.fsync(stream.tty);
|
|
7092
|
+
return retval;
|
|
7093
|
+
};
|
|
7094
|
+
const originalPutChar = TTY.stream_ops.put_char;
|
|
7095
|
+
TTY.stream_ops.put_char = function (tty, val) {
|
|
7096
|
+
/**
|
|
7097
|
+
* Buffer newlines that Emscripten normally ignores.
|
|
7098
|
+
*
|
|
7099
|
+
* Emscripten doesn't do it by default because its default
|
|
7100
|
+
* print function is console.log that implicitly adds a newline. We are overwriting
|
|
7101
|
+
* it with an environment-specific function that outputs exaclty what it was given,
|
|
7102
|
+
* e.g. in Node.js it's process.stdout.write(). Therefore, we need to mak sure
|
|
7103
|
+
* all the newlines make it to the output buffer.
|
|
7104
|
+
*/ if (val === 10) tty.output.push(val);
|
|
7105
|
+
return originalPutChar(tty, val);
|
|
7106
|
+
};
|
|
7107
|
+
},
|
|
7108
|
+
onHeaders: function (chunk) {
|
|
7109
|
+
if (Module['onHeaders']) {
|
|
7110
|
+
Module['onHeaders'](chunk);
|
|
7111
|
+
return;
|
|
7112
|
+
}
|
|
7113
|
+
console.log('headers', {
|
|
7114
|
+
chunk,
|
|
7115
|
+
});
|
|
7116
|
+
},
|
|
7117
|
+
onStdout: function (chunk) {
|
|
7118
|
+
if (Module['onStdout']) {
|
|
7119
|
+
Module['onStdout'](chunk);
|
|
7120
|
+
return;
|
|
7121
|
+
}
|
|
7122
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
7123
|
+
process.stdout.write(chunk);
|
|
7124
|
+
} else {
|
|
7125
|
+
console.log('stdout', {
|
|
7126
|
+
chunk,
|
|
7127
|
+
});
|
|
7128
|
+
}
|
|
7129
|
+
},
|
|
7130
|
+
onStderr: function (chunk) {
|
|
7131
|
+
if (Module['onStderr']) {
|
|
7132
|
+
Module['onStderr'](chunk);
|
|
7133
|
+
return;
|
|
7134
|
+
}
|
|
7135
|
+
if (ENVIRONMENT_IS_NODE) {
|
|
7136
|
+
process.stderr.write(chunk);
|
|
7137
|
+
} else {
|
|
7138
|
+
console.warn('stderr', {
|
|
7139
|
+
chunk,
|
|
7140
|
+
});
|
|
7141
|
+
}
|
|
7056
7142
|
},
|
|
7057
7143
|
getAllWebSockets: function (sock) {
|
|
7058
7144
|
const webSockets = new Set();
|
|
@@ -7234,7 +7320,7 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7234
7320
|
argsArray.push(UTF8ToString(HEAPU32[charPointer >> 2]));
|
|
7235
7321
|
}
|
|
7236
7322
|
}
|
|
7237
|
-
const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) :
|
|
7323
|
+
const cwdstr = cwdPtr ? UTF8ToString(cwdPtr) : FS.cwd();
|
|
7238
7324
|
let envObject = null;
|
|
7239
7325
|
if (envLength) {
|
|
7240
7326
|
envObject = {};
|
|
@@ -7307,6 +7393,15 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7307
7393
|
PHPWASM.child_proc_by_fd[ProcInfo.stderrParentFd] = ProcInfo;
|
|
7308
7394
|
PHPWASM.child_proc_by_pid[ProcInfo.pid] = ProcInfo;
|
|
7309
7395
|
cp.on('exit', function (code) {
|
|
7396
|
+
for (const fd of [
|
|
7397
|
+
// The child process exited. Let's clean up its output streams:
|
|
7398
|
+
ProcInfo.stdoutChildFd,
|
|
7399
|
+
ProcInfo.stderrChildFd,
|
|
7400
|
+
]) {
|
|
7401
|
+
if (FS.streams[fd] && !FS.isClosed(FS.streams[fd])) {
|
|
7402
|
+
FS.close(FS.streams[fd]);
|
|
7403
|
+
}
|
|
7404
|
+
}
|
|
7310
7405
|
ProcInfo.exitCode = code;
|
|
7311
7406
|
ProcInfo.exited = true;
|
|
7312
7407
|
// Emit events for the wasm_poll_socket function.
|
|
@@ -7357,12 +7452,52 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
7357
7452
|
* listen to the 'exit' event.
|
|
7358
7453
|
*/ try {
|
|
7359
7454
|
await new Promise((resolve, reject) => {
|
|
7360
|
-
|
|
7361
|
-
|
|
7455
|
+
/**
|
|
7456
|
+
* There was no `await` between the `spawnProcess` call
|
|
7457
|
+
* and the `await` below so the process haven't had a chance
|
|
7458
|
+
* to run any of the exit-related callbacks yet.
|
|
7459
|
+
*
|
|
7460
|
+
* Good.
|
|
7461
|
+
*
|
|
7462
|
+
* Let's listen to all the lifecycle events and resolve
|
|
7463
|
+
* the promise when the process starts or immediately crashes.
|
|
7464
|
+
*/ let resolved = false;
|
|
7465
|
+
cp.on('spawn', () => {
|
|
7466
|
+
if (resolved) return;
|
|
7467
|
+
resolved = true;
|
|
7468
|
+
resolve();
|
|
7469
|
+
});
|
|
7470
|
+
cp.on('error', (e) => {
|
|
7471
|
+
if (resolved) return;
|
|
7472
|
+
resolved = true;
|
|
7473
|
+
reject(e);
|
|
7474
|
+
});
|
|
7475
|
+
cp.on('exit', function (code) {
|
|
7476
|
+
if (resolved) return;
|
|
7477
|
+
resolved = true;
|
|
7478
|
+
if (code === 0) {
|
|
7479
|
+
resolve();
|
|
7480
|
+
} else {
|
|
7481
|
+
reject(
|
|
7482
|
+
new Error(`Process exited with code ${code}`)
|
|
7483
|
+
);
|
|
7484
|
+
}
|
|
7485
|
+
});
|
|
7486
|
+
/**
|
|
7487
|
+
* If the process haven't even started after 5 seconds, something
|
|
7488
|
+
* is wrong. Perhaps we're missing an event listener, or perhaps
|
|
7489
|
+
* the `spawnProcess` implementation failed to dispatch the relevant
|
|
7490
|
+
* event. Either way, let's crash to avoid blocking the proc_open()
|
|
7491
|
+
* call indefinitely.
|
|
7492
|
+
*/ setTimeout(() => {
|
|
7493
|
+
if (resolved) return;
|
|
7494
|
+
resolved = true;
|
|
7495
|
+
reject(new Error('Process timed out'));
|
|
7496
|
+
}, 5e3);
|
|
7362
7497
|
});
|
|
7363
7498
|
} catch (e) {
|
|
7364
7499
|
console.error(e);
|
|
7365
|
-
wakeUp(
|
|
7500
|
+
wakeUp(ProcInfo.pid);
|
|
7366
7501
|
return;
|
|
7367
7502
|
}
|
|
7368
7503
|
// Now we want to pass data from the STDIN source supplied by PHP
|
|
@@ -8076,14 +8211,7 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8076
8211
|
const POLLNVAL = 32;
|
|
8077
8212
|
return returnCallback((wakeUp) => {
|
|
8078
8213
|
const polls = [];
|
|
8079
|
-
if (socketd
|
|
8080
|
-
const procInfo = PHPWASM.child_proc_by_fd[socketd];
|
|
8081
|
-
if (procInfo.exited) {
|
|
8082
|
-
wakeUp(0);
|
|
8083
|
-
return;
|
|
8084
|
-
}
|
|
8085
|
-
polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data'));
|
|
8086
|
-
} else if (FS.isSocket(FS.getStream(socketd)?.node.mode)) {
|
|
8214
|
+
if (FS.isSocket(FS.getStream(socketd)?.node.mode)) {
|
|
8087
8215
|
const sock = getSocketFromFD(socketd);
|
|
8088
8216
|
if (!sock) {
|
|
8089
8217
|
wakeUp(0);
|
|
@@ -8117,7 +8245,12 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8117
8245
|
polls.push(PHPWASM.awaitConnection(ws));
|
|
8118
8246
|
lookingFor.add('POLLOUT');
|
|
8119
8247
|
}
|
|
8120
|
-
if (
|
|
8248
|
+
if (
|
|
8249
|
+
events & POLLHUP ||
|
|
8250
|
+
events & POLLIN ||
|
|
8251
|
+
events & POLLOUT ||
|
|
8252
|
+
events & POLLERR
|
|
8253
|
+
) {
|
|
8121
8254
|
polls.push(PHPWASM.awaitClose(ws));
|
|
8122
8255
|
lookingFor.add('POLLHUP');
|
|
8123
8256
|
}
|
|
@@ -8126,6 +8259,13 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8126
8259
|
lookingFor.add('POLLERR');
|
|
8127
8260
|
}
|
|
8128
8261
|
}
|
|
8262
|
+
} else if (socketd in PHPWASM.child_proc_by_fd) {
|
|
8263
|
+
const procInfo = PHPWASM.child_proc_by_fd[socketd];
|
|
8264
|
+
if (procInfo.exited) {
|
|
8265
|
+
wakeUp(0);
|
|
8266
|
+
return;
|
|
8267
|
+
}
|
|
8268
|
+
polls.push(PHPWASM.awaitEvent(procInfo.stdout, 'data'));
|
|
8129
8269
|
} else {
|
|
8130
8270
|
setTimeout(function () {
|
|
8131
8271
|
wakeUp(1);
|
|
@@ -8416,13 +8556,6 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8416
8556
|
(___wrap_select = Module['___wrap_select'] =
|
|
8417
8557
|
wasmExports['__wrap_select'])(a0, a1, a2, a3, a4));
|
|
8418
8558
|
|
|
8419
|
-
var _wasm_add_cli_arg = (Module['_wasm_add_cli_arg'] = (a0) =>
|
|
8420
|
-
(_wasm_add_cli_arg = Module['_wasm_add_cli_arg'] =
|
|
8421
|
-
wasmExports['wasm_add_cli_arg'])(a0));
|
|
8422
|
-
|
|
8423
|
-
var _run_cli = (Module['_run_cli'] = () =>
|
|
8424
|
-
(_run_cli = Module['_run_cli'] = wasmExports['run_cli'])());
|
|
8425
|
-
|
|
8426
8559
|
var _wasm_set_sapi_name = (Module['_wasm_set_sapi_name'] = (a0) =>
|
|
8427
8560
|
(_wasm_set_sapi_name = Module['_wasm_set_sapi_name'] =
|
|
8428
8561
|
wasmExports['wasm_set_sapi_name'])(a0));
|
|
@@ -8431,6 +8564,13 @@ export function init(RuntimeName, PHPLoader) {
|
|
|
8431
8564
|
(_wasm_set_phpini_path = Module['_wasm_set_phpini_path'] =
|
|
8432
8565
|
wasmExports['wasm_set_phpini_path'])(a0));
|
|
8433
8566
|
|
|
8567
|
+
var _wasm_add_cli_arg = (Module['_wasm_add_cli_arg'] = (a0) =>
|
|
8568
|
+
(_wasm_add_cli_arg = Module['_wasm_add_cli_arg'] =
|
|
8569
|
+
wasmExports['wasm_add_cli_arg'])(a0));
|
|
8570
|
+
|
|
8571
|
+
var _run_cli = (Module['_run_cli'] = () =>
|
|
8572
|
+
(_run_cli = Module['_run_cli'] = wasmExports['run_cli'])());
|
|
8573
|
+
|
|
8434
8574
|
var _wasm_add_SERVER_entry = (Module['_wasm_add_SERVER_entry'] = (a0, a1) =>
|
|
8435
8575
|
(_wasm_add_SERVER_entry = Module['_wasm_add_SERVER_entry'] =
|
|
8436
8576
|
wasmExports['wasm_add_SERVER_entry'])(a0, a1));
|