Skip to content

Commit b195d93

Browse files
authored
[PHP web] Export setErrNo() to make less work as pager (#2554)
## Motivation for the change, related issues Some WP-CLI commands fail in Playground web, notably just `wp` that normally prints the help message. This PR addresses those shortcomings. ## Implementation details * Ensure the `setErrNo` function is always exported, otherwise some subprocess handler code paths try to call an undefined function. * Don't call `_free()` that may be unavailable. Call `PHPLoader["free"]` instead. * Wait for the `stdin` data to finish subprocess handler before exiting our mock `less` implementation ## Testing Instructions (or ideally a Blueprint) Confirm the E2E test included with this PR passes in the CI.
1 parent 22773fa commit b195d93

39 files changed

+144
-143
lines changed

packages/php-wasm/compile/php/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2106,10 +2106,10 @@ RUN set -euxo pipefail; \
21062106
source /root/emsdk/emsdk_env.sh; \
21072107
if [ "$WITH_JSPI" = "yes" ]; then \
21082108
# Both imports and exports are required for inter-module communication with wrapped methods, e.g., wasm_recv.
2109-
export ASYNCIFY_FLAGS=" -s ASYNCIFY=2 -sSUPPORT_LONGJMP=wasm -fwasm-exceptions -sJSPI_IMPORTS=js_open_process,js_fd_read,js_waitpid,js_process_status,js_create_input_device,wasm_setsockopt,wasm_shutdown,wasm_close,wasm_recv,__syscall_fcntl64,js_flock,js_release_file_locks,js_waitpid,fd_close -sJSPI_EXPORTS=php_wasm_init,fd_close,wasm_sleep,wasm_read,emscripten_sleep,wasm_sapi_handle_request,wasm_sapi_request_shutdown,wasm_poll_socket,wrap_select,__wrap_select,select,php_pollfd_for,fflush,wasm_popen,wasm_read,wasm_php_exec,run_cli,wasm_recv -s EXTRA_EXPORTED_RUNTIME_METHODS=ccall,PROXYFS,wasmExports,_malloc "; \
2109+
export ASYNCIFY_FLAGS=" -s ASYNCIFY=2 -sSUPPORT_LONGJMP=wasm -fwasm-exceptions -sJSPI_IMPORTS=js_open_process,js_fd_read,js_waitpid,js_process_status,js_create_input_device,wasm_setsockopt,wasm_shutdown,wasm_close,wasm_recv,__syscall_fcntl64,js_flock,js_release_file_locks,js_waitpid,fd_close -sJSPI_EXPORTS=php_wasm_init,fd_close,wasm_sleep,wasm_read,emscripten_sleep,wasm_sapi_handle_request,wasm_sapi_request_shutdown,wasm_poll_socket,wrap_select,__wrap_select,select,php_pollfd_for,fflush,wasm_popen,wasm_read,wasm_php_exec,run_cli,wasm_recv -s EXTRA_EXPORTED_RUNTIME_METHODS=ccall,PROXYFS,wasmExports,_malloc,setErrNo "; \
21102110
echo '#define PLAYGROUND_JSPI 1' > /root/php_wasm_asyncify.h; \
21112111
else \
2112-
export ASYNCIFY_FLAGS=" -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 -s EXPORTED_RUNTIME_METHODS=ccall,PROXYFS,wasmExports $(cat /root/.emcc-php-asyncify-flags) "; \
2112+
export ASYNCIFY_FLAGS=" -s ASYNCIFY=1 -s ASYNCIFY_IGNORE_INDIRECT=1 -s EXPORTED_RUNTIME_METHODS=ccall,PROXYFS,wasmExports,setErrNo $(cat /root/.emcc-php-asyncify-flags) "; \
21132113
echo '' > /root/php_wasm_asyncify.h; \
21142114
fi; \
21152115
export EXPORTED_FUNCTIONS=$'["_exit", \n\

packages/php-wasm/compile/php/phpwasm-emscripten-library.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -711,9 +711,9 @@ const LibraryExample = {
711711
if (!cp.stdin.closed) {
712712
cp.stdin.end();
713713
}
714-
_free(buffer);
715-
_free(iov);
716-
_free(pnum);
714+
PHPLoader["free"](buffer);
715+
PHPLoader["free"](iov);
716+
PHPLoader["free"](pnum);
717717
}
718718

719719
// pump() can never alter the result of this function.

packages/php-wasm/supported-php-versions.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* @property {string} lastRelease
77
*/
88

9-
export const lastRefreshed = '2025-08-04T12:45:56.385Z';
9+
export const lastRefreshed = '2025-08-25T10:10:32.564Z';
1010

1111
/**
1212
* @type {PhpVersion[]}

packages/php-wasm/universal/src/lib/sandboxed-spawn-handler-factory.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,14 @@ export function sandboxedSpawnHandlerFactory(
4747
processApi.on('stdin', (data: Uint8Array) => {
4848
processApi.stdout(data);
4949
});
50+
// Exit after the stdin stream is exhausted.
51+
await new Promise((resolve) => {
52+
processApi.childProcess.stdin.on('finish', () => {
53+
resolve(true);
54+
});
55+
});
5056
processApi.exit(0);
57+
return;
5158
} else if (binaryName === 'php') {
5259
const { php, reap } = await processManager.acquirePHPInstance({
5360
considerPrimary: false,

packages/php-wasm/util/src/lib/create-spawn-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export class ProcessApi extends EventEmitterPolyfill {
9696
* first listener was registered.
9797
*/
9898
private stdinBuffer: Uint8Array[] | null = [];
99-
private childProcess: ChildProcess;
99+
public childProcess: ChildProcess;
100100
constructor(childProcess: ChildProcess) {
101101
super();
102102
this.childProcess = childProcess;
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)