wp-now: Update Playground and PHP WASM dependencies
What?
This pull request is a continuation of #345 to update Playground dependencies from 0.6.16 to 0.9.39 and adapt existing code to work with breaking changes.
Resolves #319.
Why?
To keep up with upstream changes and benefit from new features and bug fixes.
How?
Update to new interface for PHP runtime instances, requests, and file system mount.
Based on similar logic in @wp-playground/wordpress (bootWordpress) and cli.
- Use
PHPclass from@php-wasm/universalinstead ofNodePHPfrom@php-wasm/node, which no longer exists.- WordPress/wordpress-playground#1457
- Use
PHPRequestHandlerinstead ofphp.request() - Use
createNodeFsMountHandlerto mount the file system with Node-specific adaptor forphp.mount() - Remove logic that handled PHP instances manually
Further changes were necessary to pass all existing tests.
- Update
executeWpClibased on fork ofwp-nowin Automattic/studio- Use TLS certificates
- Workaround for stdin/out/err
- Not implemented yet: SQLite command
- Update
@php-wasm/compileto add any missing C functions to the list inASYNCIFY_IMPORTSin the Dockerfile here.- Documentation about WASM errors related to Asyncify: https://wordpress.github.io/wordpress-playground/developers/architecture/wasm-asyncify/#asyncify-crashes
Testing Instructions
npx nx test wp-now
Currently there are 3 failing tests, as seen in the CI logs.
They're about running PHP as CLI, and about WP-CLI.
❯ src/tests/wp-now.spec.ts (46 tests | 3 failed | 1 skipped) 70720ms
❯ src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file
→ expected '' to match /8\.0/i
❯ src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file and change php version
→ expected '' to match /7\.4/i
❯ src/tests/wp-now.spec.ts > wp-cli command > wp-cli displays the version
→ Program terminated with exit(1)
There are also WASM errors associated with the PHP CLI tests, both:
RuntimeError: null function or function signature mismatch
That could be related to a similar error described in:
- WordPress/wordpress-playground#1716
I'll copy the WASM error stack traces below for reference. They're slightly different, so might have different causes.
stderr | src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file
RuntimeError: null function or function signature mismatch
at php_auto_globals_create_get (wasm://wasm/php.wasm-0380e0be:1:6470748)
at php_hash_environment (wasm://wasm/php.wasm-0380e0be:1:6417625)
at dynCall_i (wasm://wasm/php.wasm-0380e0be:1:7251146)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29057:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_i (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29675:14)
at php_request_startup (wasm://wasm/php.wasm-0380e0be:1:2685484)
at dynCall_i (wasm://wasm/php.wasm-0380e0be:1:7251146)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29057:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_i (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29675:14)
at do_cli (wasm://wasm/php.wasm-0380e0be:1:7284591)
at dynCall_iii (wasm://wasm/php.wasm-0380e0be:1:7250788)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29057:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_iii (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29598:14) {
cause: Error:
at Object.Asyncify.handleSleep (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29857:45)
at _wasm_poll_socket (file://~/playground-tools/node_modules/@php-wasm/node/index.js:28922:21)
at php_pollfd_for (wasm://wasm/php.wasm-0380e0be:1:633716)
at php_network_connect_socket (wasm://wasm/php.wasm-0380e0be:1:3934833)
at php_tcp_sockop_set_option (wasm://wasm/php.wasm-0380e0be:1:6332023)
at php_openssl_sockop_set_option (wasm://wasm/php.wasm-0380e0be:1:6373167)
at _php_stream_set_option (wasm://wasm/php.wasm-0380e0be:1:252064)
at dynCall_iiiii (wasm://wasm/php.wasm-0380e0be:1:7250364)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29057:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_iiiii (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29609:14)
at _php_stream_xport_create (wasm://wasm/php.wasm-0380e0be:1:1105389)
at zif_stream_socket_client (wasm://wasm/php.wasm-0380e0be:1:5252366)
at ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER (wasm://wasm/php.wasm-0380e0be:1:7683052)
at execute_ex (wasm://wasm/php.wasm-0380e0be:1:7135045)
at zend_execute (wasm://wasm/php.wasm-0380e0be:1:2359117)
}
stderr | src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file and change php version
RuntimeError: null function or function signature mismatch
at php_auto_globals_create_get (wasm://wasm/php.wasm-039ec376:1:6739627)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8576690)
at php_hash_environment (wasm://wasm/php.wasm-039ec376:1:6669088)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8452698)
at dynCall_i (wasm://wasm/php.wasm-039ec376:1:7679921)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:36486:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_i (file://~/playground-tools/node_modules/@php-wasm/node/index.js:37035:14)
at php_request_startup (wasm://wasm/php.wasm-039ec376:1:2843395)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8448590)
at dynCall_i (wasm://wasm/php.wasm-039ec376:1:7679921)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:36486:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_i (file://~/playground-tools/node_modules/@php-wasm/node/index.js:37035:14)
at do_cli (wasm://wasm/php.wasm-039ec376:1:7715417)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8448901) {
cause: Error:
at Object.Asyncify.handleSleep (file://~/playground-tools/node_modules/@php-wasm/node/index.js:37272:45)
at _wasm_poll_socket (file://~/playground-tools/node_modules/@php-wasm/node/index.js:36351:21)
at php_pollfd_for (wasm://wasm/php.wasm-039ec376:1:622857)
at php_network_connect_socket (wasm://wasm/php.wasm-039ec376:1:4156375)
at php_tcp_sockop_set_option (wasm://wasm/php.wasm-039ec376:1:6572034)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8570026)
at php_openssl_sockop_set_option (wasm://wasm/php.wasm-039ec376:1:6613667)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8538339)
at _php_stream_set_option (wasm://wasm/php.wasm-039ec376:1:264442)
at _php_stream_xport_create (wasm://wasm/php.wasm-039ec376:1:1195532)
at zif_stream_socket_client (wasm://wasm/php.wasm-039ec376:1:5474793)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8561025)
at ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER (wasm://wasm/php.wasm-039ec376:1:8131754)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8581554)
at execute_ex (wasm://wasm/php.wasm-039ec376:1:7554683)
at null.<anonymous> (wasm://wasm/php.wasm-039ec376:1:8591528)
}
I checked the called php_ functions to ensure they're listed in the ASYNCIFY_IMPORTS in the Dockerfile for compiling PHP to WASM. They all seem to be there, but I might have missed something.
- https://github.com/WordPress/wordpress-playground/blob/2975b41ced95054ab3332cad41f27af557309b08/packages/php-wasm/compile/php/Dockerfile#L439
I saw that a similar update of Playground and PHP-WASM dependencies happened in:
- https://github.com/Automattic/studio/pull/491
The project includes a vendored and patched wp-now. Looks like they had to implement a tricky workaround to make WP-CLI work, but I'm hoping that won't be necessary to copy over; otherwise that would probably be better as a separate PR for the Playground repo, as a prerequisite for this one.
One difference I noticed is setting up TLS root certificates.
- https://github.com/Automattic/studio/pull/491/files#diff-952f2fb6ea000e9e9dcd9d21f7740b883493d4235bf24b5086745a18b6e14b36
I'll try that and some other relevant changes, and see if it helps with passing the remaining tests.
@sejas poke for the reviews! :-)
As for the unreachable errors, it might require a PR similar to https://github.com/WordPress/wordpress-playground/pull/1716 that adds all the C functions from the stack trace to the Dockerfile. See https://wordpress.github.io/wordpress-playground/developers/architecture/wasm-asyncify/#asyncify-crashes
OK, down to 2 failing tests, both about PHP CLI and WASM errors.
it might require a PR that..adds all the C functions from the stack trace to the Dockerfile.
I need help with solving the WASM part - as far as I can see, all the C functions are already listed in ASYNCIFY_IMPORTS in the Dockerfile of @php-wasm/compile here. I'll go through them again to make sure I didn't miss anything.
For the WP-CLI test that was failing before, I ported the changes in executeWpCli from the fork of wp-now in Automattic/studio:
- https://github.com/Automattic/studio/blob/trunk/vendor/wp-now/src/execute-wp-cli.ts
It includes a somewhat gnarly workaround to make WP-CLI work. Some of this might be suitable to move upstream as shared logic in @wp-playground/wordpress or cli.
One part I had to comment out, about SQLite command. Maybe this could be left for another PR to more fully develop the WP-CLI integration, which is (I think) not yet part of the public interface of wp-now.
Here are the functions listed in the WASM error stacks (below). I combined and sorted them alphabetically, then checked each against the Dockerfile in @php-wasm/compile/php.
- [x] _php_stream_set_option
- [x] _php_stream_xport_create
- [ ] _wasm_poll_socket
- [x] dynCall_iiiii
- [x] execute_ex
- [x] php_network_connect_socket
- [x] php_openssl_sockop_set_option
- [x] php_pollfd_for
- [x] php_tcp_sockop_set_option
- [x] zend_execute
- [x] zif_stream_socket_client
The missing one is _wasm_poll_socket. Looks like it may belong with the other _wasm_* functions in the Dockerfile as part of EXPORTED_FUNCTIONS instead of ASYNCIFY_IMPORT.
I can create a PR for this - but it might be better to try locally first, and see if it actually solves the issue. I guess in my local playground repo I'll recompile PHP-WASM with the change, then link the NPM package(s) to playground-tools and see if the tests pass.
There's an ongoing PR that updates the same Dockerfile, adds a number of C functions to the Asyncify list, and recompiles all versions of PHP WASM.
- WordPress/wordpress-playground#1716
This could be the quickest solution to ask if they can add _wasm_poll_socket to EXPORTED_FUNCTIONS as part of their work.
...
cause: Error:
at Object.Asyncify.handleSleep (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29857:45)
at _wasm_poll_socket (file://~/playground-tools/node_modules/@php-wasm/node/index.js:28922:21)
at php_pollfd_for (wasm://wasm/php.wasm-0381a85e:1:634630)
at php_network_connect_socket (wasm://wasm/php.wasm-0381a85e:1:3939767)
at php_tcp_sockop_set_option (wasm://wasm/php.wasm-0381a85e:1:6339293)
at php_openssl_sockop_set_option (wasm://wasm/php.wasm-0381a85e:1:6381905)
at _php_stream_set_option (wasm://wasm/php.wasm-0381a85e:1:252625)
at dynCall_iiiii (wasm://wasm/php.wasm-0381a85e:1:7262168)
at ret.<computed> (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29057:22)
at t.wasmExports.<computed> (file://~/playground-tools/node_modules/@php-wasm/universal/index.js:522:18)
at invoke_iiiii (file://~/playground-tools/node_modules/@php-wasm/node/index.js:29609:14)
at _php_stream_xport_create (wasm://wasm/php.wasm-0381a85e:1:1106649)
at zif_stream_socket_client (wasm://wasm/php.wasm-0381a85e:1:5257722)
at ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER (wasm://wasm/php.wasm-0381a85e:1:7695829)
at execute_ex (wasm://wasm/php.wasm-0381a85e:1:7146849)
at zend_execute (wasm://wasm/php.wasm-0381a85e:1:2361792)
...
cause: Error:
at Object.Asyncify.handleSleep (file://~/playground-tools/node_modules/@php-wasm/node/index.js:37272:45)
at _wasm_poll_socket (file://~/playground-tools/node_modules/@php-wasm/node/index.js:36351:21)
at php_pollfd_for (wasm://wasm/php.wasm-039fea6e:1:623826)
at php_network_connect_socket (wasm://wasm/php.wasm-039fea6e:1:4162312)
at php_tcp_sockop_set_option (wasm://wasm/php.wasm-039fea6e:1:6583506)
at null.<anonymous> (wasm://wasm/php.wasm-039fea6e:1:8588223)
at php_openssl_sockop_set_option (wasm://wasm/php.wasm-039fea6e:1:6626546)
at null.<anonymous> (wasm://wasm/php.wasm-039fea6e:1:8556536)
at _php_stream_set_option (wasm://wasm/php.wasm-039fea6e:1:265054)
at _php_stream_xport_create (wasm://wasm/php.wasm-039fea6e:1:1196959)
at zif_stream_socket_client (wasm://wasm/php.wasm-039fea6e:1:5481212)
at null.<anonymous> (wasm://wasm/php.wasm-039fea6e:1:8579222)
at ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER (wasm://wasm/php.wasm-039fea6e:1:8148852)
at null.<anonymous> (wasm://wasm/php.wasm-039fea6e:1:8600108)
at execute_ex (wasm://wasm/php.wasm-039fea6e:1:7570728)
at null.<anonymous> (wasm://wasm/php.wasm-039fea6e:1:8610440)
Next steps to complete this PR:
- [x] In my local
playgroundrepo, add_wasm_poll_socketto the Dockerfile as part of EXPORTED_FUNCTIONS. Recompile PHP-WASM with the change. This takes a while.npm run recompile:php:node- Building all packages with
npm run buildfails:
✅ Solved by removing the cache folder:NX Error: write EPIPE [NX Daemon Server] - Server stopped because: "Stopping the daemon the set of ignored files changed (native)"rm -rf node_modules/.cache npm run build - The task
php-wasm-node:build:package-jsonfails for several PHP versions.
✅ Solved by compiling each version:✘ [ERROR] Could not resolve "../../public/php_8_3.js" packages/php-wasm/node/src/lib/get-php-loader-module.ts:10:23: 10 │ return await import(`../../public/php_8_3.js`); ╵ ~~~~~~~~~~~~~~~~~~~~~~~~~for f in 7.0 7.1 7.2 7.3 7.4 8.0 8.1 8.2 8.3; do npm run recompile:php:node:$f done
- Building all packages with
- [x] ~Link~ Copy built NPM package(s) to
playground-tools/node_modules.npm linkdoesn't work, it links to uncompiled source.- Manually creating symlinks to
@php-wasmpackages doesn't work. Modules importing each other lead to symlinks (created by npm or nx) withinplayground/node_moduleswith uncompiled source. - ✅ Just copy built packages from
dist.cd playground-tools/node_modules/@php-wasm for f in *; do if [ -d "$f" ]; then echo "$f" rsync -r --delete ../../../playground/dist/packages/php-wasm/"$f"/ "$f" fi done
- [ ] ❌ Confirm WASM errors are resolved and all tests pass.
npx nx test wp-now - [ ] Create PR for the change in
playgroundrepo. - [ ] When that's merged (and maybe also wordpress-playground#1716), update PHP-WASM dependencies in this PR.
Even after adding _wasm_poll_socket to PHP-WASM, the same two tests are failing with the same WASM errors. ..Oh, I see there are several functions I missed in the error stack trace (from above cause: Error).
- [x] do_cli
- [x] dynCall_i
- [x] invoke_i
- [ ] php_auto_globals_create_get
- [ ] php_hash_environment
- [ ] php_request_startup
I added these to ASYNCIFY_ONLY and recompiled PHP-WASM, but still getting the same WASM errors. I cleared Docker cache with docker builder prune and recompiled again, same result. I noticed playground#1716 was merged, but I'm getting the same result after pull and another recompile.
By the way, I'm finding it helpful to use Bun to run functions during development, without having to build the project or run the test suite every time.
In a parent directory, a quick script to try things:
import path from 'node:path'
import getWpNowConfig, { WPNowMode } from './playground-tools/packages/wp-now/src/config'
import { executePHP } from './playground-tools/packages/wp-now/src/execute-php'
import { executeWPCli } from './playground-tools/packages/wp-now/src/execute-wp-cli'
const options = await getWpNowConfig({
path: path.join(import.meta.dir, 'test'),
port: 3000,
reset: true,
})
console.log(
await executeWPCli(['cli', 'version'])
)
await executePHP(['php', '--version'], options)
await executePHP(['php', `--help`], options)
await executePHP(['php', `-r`, `echo 'hi';`], {
...options,
mode: WPNowMode.INDEX,
})
await executePHP(
['php', `-r`, `echo json_encode( scandir('${options.documentRoot}') );`],
options,
)
This last CLI command throws a different error than in the tests. Maybe the stack trace contains a hint about how to solve it.
WASM ERROR
call_indirect to a null table entry (evaluating 'original(...args)')
29056 | for (let [x, original] of Object.entries(exports)) {
29057 | if (typeof original == "function") {
29058 | ret[x] = (...args) => {
29059 | Asyncify.exportCallStack.push(x);
29060 | try {
29061 | return original(...args);
^
RuntimeError: call_indirect to a null table entry (evaluating 'original(...args)')
at php.wasm.wasm-function[php_auto_globals_create_get]
at php.wasm.wasm-function[php_hash_environment]
at php.wasm.wasm-function[dynCall_i]
at ~/playground-tools/node_modules/@php-wasm/node/index.js:29061:22
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:556:18
at invoke_i (~/playground-tools/node_modules/@php-wasm/node/index.js:29679:14)
at php.wasm.wasm-function[php_request_startup]
at php.wasm.wasm-function[dynCall_i]
at ~/playground-tools/node_modules/@php-wasm/node/index.js:29061:22
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:556:18
at invoke_i (~/playground-tools/node_modules/@php-wasm/node/index.js:29679:14)
at php.wasm.wasm-function[do_cli]
at php.wasm.wasm-function[dynCall_iii]
at ~/playground-tools/node_modules/@php-wasm/node/index.js:29061:22
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:556:18
at invoke_iii (~/playground-tools/node_modules/@php-wasm/node/index.js:29602:14)
at php.wasm.wasm-function[run_cli]
at ~/playground-tools/node_modules/@php-wasm/node/index.js:29061:22
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:556:18
at ccall (~/playground-tools/node_modules/@php-wasm/node/index.js:29256:15)
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:1229:47
at cli (~/playground-tools/node_modules/@php-wasm/universal/index.js:1220:13)
at ~/playground-tools/packages/wp-now/src/execute-php.ts:40:13
29856 | PHPLoader.debug = "debug" in PHPLoader ? PHPLoader.debug : true;
29857 | if (PHPLoader.debug && typeof Asyncify !== "undefined") {
29858 | const originalHandleSleep = Asyncify.handleSleep;
29859 | Asyncify.handleSleep = function(startAsync) {
29860 | if (!ABORT) {
29861 | Module["lastAsyncifyStackSource"] = new Error();
^
error: Error
at ~/playground-tools/node_modules/@php-wasm/node/index.js:29861:45
at php.wasm.wasm-function[php_pollfd_for] (native:1:1)
at php.wasm.wasm-function[php_network_connect_socket] (native:1:1)
at php.wasm.wasm-function[php_tcp_sockop_set_option] (native:1:1)
at php.wasm.wasm-function[php_openssl_sockop_set_option] (native:1:1)
at php.wasm.wasm-function[_php_stream_set_option] (native:1:1)
at php.wasm.wasm-function[dynCall_iiiii] (native:1:1)
at 13211 (native:1:1)
at ~/playground-tools/node_modules/@php-wasm/node/index.js:33821:11
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:19:6
at invoke_iiiii (~/playground-tools/node_modules/@php-wasm/node/index.js:34416:13)
at php.wasm.wasm-function[_php_stream_xport_create] (native:1:1)
at php.wasm.wasm-function[zif_stream_socket_client] (native:1:1)
at php.wasm.wasm-function[ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER] (native:1:1)
at php.wasm.wasm-function[execute_ex] (native:1:1)
at php.wasm.wasm-function[zend_execute] (native:1:1)
at php.wasm.wasm-function[zend_execute_scripts] (native:1:1)
at php.wasm.wasm-function[dynCall_iiiii] (native:1:1)
at 13211 (native:1:1)
at ~/playground-tools/node_modules/@php-wasm/node/index.js:33821:11
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:19:6
at invoke_iiiii (~/playground-tools/node_modules/@php-wasm/node/index.js:34416:13)
at php.wasm.wasm-function[php_execute_script] (native:1:1)
at php.wasm.wasm-function[dynCall_ii] (native:1:1)
at 13214 (native:1:1)
at ~/playground-tools/node_modules/@php-wasm/node/index.js:33821:11
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:19:6
at invoke_ii (~/playground-tools/node_modules/@php-wasm/node/index.js:34428:13)
at php.wasm.wasm-function[wasm_sapi_handle_request] (native:1:1)
at 9847 (native:1:1)
at ~/playground-tools/node_modules/@php-wasm/node/index.js:33821:11
at ~/playground-tools/node_modules/@php-wasm/universal/index.js:19:6
Here's the complete list of wasm-functions from above, checked against the Dockerfile for PHP-WASM.
- [x] _php_stream_set_option
- [x] _php_stream_xport_create
- [ ] _wasm_poll_socket
- [x] do_cli
- [x] dynCall_i
- [x] dynCall_ii
- [x] dynCall_iii
- [x] dynCall_iiiii
- [x] execute_ex
- [x] invoke_i
- [x] invoke_iii
- [x] invoke_iiiii
- [ ] php_auto_globals_create_get
- [ ] php_hash_environment
- [ ] php_request_startup
- [x] php_execute_script
- [x] php_network_connect_socket
- [x] php_openssl_sockop_set_option
- [x] php_pollfd_for
- [x] php_tcp_sockop_set_option
- [x] run_cli
- [x] wasm_sapi_handle_request
- [x] ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER
- [x] zend_execute
- [x] zend_execute_scripts
- [x] zif_stream_socket_client
In my fork of playground, I added:
_wasm_poll_sockettoEXPORTED_FUNCTIONS- missing
php_*functions toASYNCIFY_ONLY(notASYNCIFY_IMPORTSwhich is a much shorter list)
For some reason that doesn't solve it.
All tests pass when PHP CLI is run in "index" mode.
Other modes (playground, plugin, theme, wordpress) fail with WASM error. That makes me think, maybe the issue is not with missing functions but in the way the PHP instance is set up before calling the CLI.
OK, I applied the suggested changes. Thank you for the review. I ported some useful changes from the Studio fork of wp-now, including support for rewrite rules and file not found action; and improvements to php.ini setup and rotate runtime instances with shared init steps.
Getting closer.. All tests passing, except:
I couldn't reproduce the WASM errors you mentioned.
I temporarily "solved" it by forcing PHP CLI to run in index mode. But any other mode throws.
I'll remove that patch so the CI shows the errors again. I'm not sure how to solve this one, as far as I could tell, adding functions to PHP-WASM and recompiling didn't eliminate the error.
Thanks for the quick updates! 🙏 I'll check the errors to find a solution. I'll keep you updated.
Poke @sejas :)
I updated Playground dependencies to the newest version 1.0.2.
The WASM error stack trace looks the same as before. I'll try again to solve it, apparently it happens with any wp-now mode other than index.
stderr | src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file
RuntimeError: null function or function signature mismatch
at php_auto_globals_create_get (wasm://wasm/php.wasm-0372e072:1:6312604)
...
stderr | src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file and change php version
RuntimeError: null function or function signature mismatch
at php_auto_globals_create_get (wasm://wasm/php.wasm-0390d672:1:6582750)
...
Strangely, the CI step typecheck is failing for an unrelated file.
On my local machine it's passing.
@eliot-akira , thanks for upgrading to 1.0.2.
I tested it in my laptop. I'm getting the same errors you mentioned, and one more error about compressing (Test starting different modes > startServer > startServer compresses the html file). I need to debug it a bit more.
Currently these are the errors I get when running the wp-now tests npx nx test wp-now:
Full error trace
❯ npx nx test wp-now
nx run wp-now:test
RUN v0.31.1 /Users/macbookpro/Documents/projects-m3.nosync/playground-tools/packages/wp-now
✓ src/wp-playground-wordpress/tests/is-valid-wordpress-version.test.ts (1 test) 6ms
✓ src/tests/add-trailing-slash.spec.ts (3 tests) 4ms
✓ src/wp-playground-wordpress/tests/get-plugin-file.spec.ts (3 tests) 3ms
✓ src/tests/github-codespaces.spec.ts (2 tests) 3ms
✓ src/tests/execute-php.spec.ts (4 tests) 441ms
stdout | unknown test
Downloading wordpress...
Downloading sqlite...
stdout | unknown test
sqlite downloaded.
sqlite: 1.056s
stdout | unknown test
wordpress downloaded.
wordpress: 5.044s
stderr | src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file
RuntimeError: null function or function signature mismatch
at php_auto_globals_create_get (wasm://wasm/php.wasm-0372e072:1:6312604)
at php_hash_environment (wasm://wasm/php.wasm-0372e072:1:6259481)
at dynCall_i (wasm://wasm/php.wasm-0372e072:1:7084092)
at ret. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:92342:22)
at t.wasmExports. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/universal/index.js:556:18)
at invoke_i (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:92961:14)
at php_request_startup (wasm://wasm/php.wasm-0372e072:1:2610200)
at dynCall_i (wasm://wasm/php.wasm-0372e072:1:7084092)
at ret. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:92342:22)
at t.wasmExports. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/universal/index.js:556:18)
at invoke_i (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:92961:14)
at do_cli (wasm://wasm/php.wasm-0372e072:1:7116695)
at dynCall_iii (wasm://wasm/php.wasm-0372e072:1:7083734)
at ret. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:92342:22)
at t.wasmExports. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/universal/index.js:556:18)
at invoke_iii (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:92884:14)
stderr | src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file and change php version
RuntimeError: null function or function signature mismatch
at php_auto_globals_create_get (wasm://wasm/php.wasm-0390d672:1:6582750)
at null. (wasm://wasm/php.wasm-0390d672:1:8400512)
at php_hash_environment (wasm://wasm/php.wasm-0390d672:1:6512206)
at null. (wasm://wasm/php.wasm-0390d672:1:8277676)
at dynCall_i (wasm://wasm/php.wasm-0390d672:1:7514405)
at ret. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:99769:22)
at t.wasmExports. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/universal/index.js:556:18)
at invoke_i (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:100319:14)
at php_request_startup (wasm://wasm/php.wasm-0390d672:1:2766633)
at null. (wasm://wasm/php.wasm-0390d672:1:8273290)
at dynCall_i (wasm://wasm/php.wasm-0390d672:1:7514405)
at ret. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:99769:22)
at t.wasmExports. (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/universal/index.js:556:18)
at invoke_i (file:///Users/macbookpro/Documents/projects-m3.nosync/playground-tools/node_modules/@php-wasm/node/index.js:100319:14)
at do_cli (wasm://wasm/php.wasm-0390d672:1:7549060)
at null. (wasm://wasm/php.wasm-0390d672:1:8273601)
❯ src/tests/wp-now.spec.ts (46 tests | 3 failed | 1 skipped) 80778ms
❯ src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file
→ expected '' to match /8.0/i
❯ src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file and change php version
→ expected '' to match /7.4/i
❯ src/tests/wp-now.spec.ts > Test starting different modes > startServer > startServer compresses the html file
→ expected null to be 'gzip' // Object.is equality
⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯
FAIL src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file
AssertionError: expected '' to match /8.0/i
❯ src/tests/wp-now.spec.ts:664:19
662| process.argv = ['node', 'wp-now', 'php', filePath];
663| await runCli();
664| expect(output).toMatch(/8.0/i);
| ^
665| expect(processExitMock).toHaveBeenCalledWith(0);
666| });
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/3]⎯
FAIL src/tests/wp-now.spec.ts > Test starting different modes > validate php comand arguments passed through yargs > php should execute a file and change php version
AssertionError: expected '' to match /7.4/i
❯ src/tests/wp-now.spec.ts:679:19
677| ];
678| await runCli();
679| expect(output).toMatch(/7.4/i);
| ^
680| expect(processExitMock).toHaveBeenCalledWith(0);
681| });
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/3]⎯
FAIL src/tests/wp-now.spec.ts > Test starting different modes > startServer > startServer compresses the html file
AssertionError: expected null to be 'gzip' // Object.is equality
❯ src/tests/wp-now.spec.ts:718:48
716| ])('startServer compresses the %s file', async (_, file) => {
717| const req = await fetch(${options.absoluteUrl}${file});
718| expect(req.headers.get('content-encoding')).toBe('gzip');
| ^
719| });
720|
- Expected - 0
- Received + 1
- 'gzip'
- null
⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/3]⎯
Test Files 1 failed | 5 passed (6)
Tests 3 failed | 55 passed | 1 skipped (59)
Start at 17:04:02
Duration 81.61s (transform 152ms, setup 0ms, collect 1.01s, tests 81.23s, environment 1.68s, prepare 263ms)
——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
NX Ran target test for project wp-now (1m)
✖ 1/1 failed
✔ 0/1 succeeded [0 read from cache]
What is weird is that in CI it seems to (fail)(https://github.com/WordPress/playground-tools/actions/runs/11314731564/job/31465056405?pr=350) onwordpress-playground-block:typecheck. And in my laptop the typcheck passes correctly.
> nx run wordpress-playground-block:typecheck
Error: packages/wordpress-playground-block/src/components/playground-preview/download-zipped-package.ts(9,2): error TS7006: Parameter 'codeEditorMode' implicitly has an 'any' type.
Warning: run-commands command "tsc -p packages/wordpress-playground-block/tsconfig.lib.json --noEmit" exited with non-zero status code
While in my local machine, those typecheck pass:
I've updated executePHP to work only on index mode. I think it's a good solution because users will probably use wp-now php on sites that already exist. Ideally in the future we could remove the modes and just setup the WordPress folders the first time the users starts a site. (https://github.com/WordPress/playground-tools/pull/350/commits/2dbb1a52589a383d8f51a158f803384e8b3fabe7)
I also fixed the tests that were checking if express was compressing files before sending them in the request. (https://github.com/WordPress/playground-tools/pull/350/commits/a73938c241c3b85cfc4693d38a1e8d74d9faf7cc)
Let's see if the nx run wordpress-playground-block:typecheck pass this time 🤞
It seems the CI rebases from trunk, that's why we didn't get the error in our local machines. I fixed the typecheck here https://github.com/WordPress/playground-tools/pull/350/commits/123551999a96aeb6b9abf688314b4ce6a937e394
Whew, that was a tough one. :smile: Thank you for seeing it through!
Thank YOU @eliot-akira for working hard on it 🙏 .
I couldn't publish the release yet, I got some errors in the build process. I created a PR https://github.com/WordPress/playground-tools/pull/359 but I think I also caught a bug in wordpress-playground repo.