CLI: Auto-enable JSPI flags on Node.js 23+#3407
Closed
obenland wants to merge 2 commits intoWordPress:trunkfrom
Closed
CLI: Auto-enable JSPI flags on Node.js 23+#3407obenland wants to merge 2 commits intoWordPress:trunkfrom
obenland wants to merge 2 commits intoWordPress:trunkfrom
Conversation
When running on Node.js 23+, the CLI now automatically re-executes itself with --experimental-wasm-jspi and --experimental-wasm-stack-switching flags if they are not already present. Without JSPI, the CLI falls back to the Asyncify WASM build which crashes with "RuntimeError: unreachable" when PHP code triggers proc_open() — for example when running `wp plugin check` via WP-CLI, which internally invokes PHPCS. JSPI handles these async WASM operations correctly. On Node.js < 23, the behavior is unchanged (Asyncify remains the only option). Ref: WordPress#1872
Contributor
There was a problem hiding this comment.
Pull request overview
Automatically enables Node.js 23+ experimental JSPI/stack-switching flags by re-executing the CLI when the flags are missing, preventing Asyncify-related crashes for PHP proc_open() chains.
Changes:
- Added a startup check for Node.js major version >= 23 and presence of JSPI flags.
- Re-executes the current CLI command with missing JSPI flags using
execFileSyncand inherits stdio.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Use `error: unknown` with proper narrowing instead of `error: any` - Handle signal-terminated children by re-raising the signal - Add explicit `process.exit(0)` after successful re-exec
5 tasks
Collaborator
Collaborator
|
@obenland that other PR is now merge and will get released no later than Monday when the automated job runs. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
I tried to see if the plugin-check plugin could be run against new plugin directory submissions from CLI via Playground, but the wp-cli blueprint step crashes on Asyncify builds because PHPCS uses
proc_open()internally.Summary
When running on Node.js 23+, the CLI now automatically re-executes itself with
--experimental-wasm-jspiand--experimental-wasm-stack-switchingflags if they are not already present.Without JSPI, the CLI falls back to the Asyncify WASM build which crashes with
RuntimeError: unreachablewhen PHP code triggersproc_open()— for example when runningwp plugin checkvia thewp-cliblueprint step, which internally invokes PHPCS. JSPI handles these async WASM operations correctly.On Node.js < 23, the behavior is unchanged (Asyncify remains the only option).
How it works
The entry point (
cli.ts) checks:process.execArgv?If flags are missing, it re-executes the same command with the flags added to exec args using
execFileSyncwithstdio: 'inherit', then exits with the child's exit code (or re-raises the signal if the child was terminated by one).How I discovered this
While exploring using Playground CLI to run WordPress Plugin Check (PCP) before plugin submission, the
wp-cliblueprint step consistently crashed:Running the same command with
node --experimental-wasm-jspi --experimental-wasm-stack-switching cli.js ...worked perfectly — all 22 plugin_repo checks ran includingplugin_review_phpcs(which usesproc_openinternally for PHPCS).The root cause:
npx @wp-playground/clispawns Node without JSPI flags, sowasm-feature-detectfalls back to Asyncify, and Asyncify cannot handle theproc_opencall chain.Test plan
npx @wp-playground/cli@latest run-blueprint --blueprint=<blueprint-with-wp-cli-step>should use JSPI (check forjspi/php_*.jsin stack traces, notasyncify/php_*.js)wp plugin checkviawp-cliblueprint step should complete without crashing--port,--mount, or other flagsRef: #1872