Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Run JSPI in Node.js #1873

Closed
adamziel opened this issue Oct 9, 2024 · 9 comments
Closed

Run JSPI in Node.js #1873

adamziel opened this issue Oct 9, 2024 · 9 comments

Comments

@adamziel
Copy link
Collaborator

adamziel commented Oct 9, 2024

JSPI landed in trunk in both @php-wasm/web and @php-wasm/node packages. I couldn't figure out how to enable JSPI support in Node.js, though. It worked back in #1339 with the following CLI flags, but it doesn't work anymore:

$ node --experimental-wasm-stack-switching ./test.js
$ node --experimental-wasm-jspi ./test.js

Could that be related to the new JSPI API in v8? That would be weird, though, because WebAssembly in either case the WebAssembly object doesn't expose any JSPI-related keys – new or old. There's no Suspending, Function, Suspender, and anything else:

> WebAssembly
Object [WebAssembly] {
  compile: [Function: compile],
  validate: [Function: validate],
  instantiate: [Function: instantiate],
  compileStreaming: [Function: compileStreaming],
  instantiateStreaming: [Function: instantiateStreaming]
}

Once we can running the JSPI build in the CLI, we'll be able to check how many new plugins can be installed compared to the Asyncify build:

https://github.com/bgrgicak/playground-tester/

cc @bgrgicak @brandonpayton

@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

The experimental flags work in Node.js. It's just Node won't display WebAssembly.Suspender or WebAssembly.Function when logging the WebAssembly object. It seems like Node.js v22.9.0 still implements the older JSPI specification. I can call these just fine:

new WebAssembly.Suspender();
new WebAssembly.Function();

But the ones from the new JSPI API fail:

new WebAssembly.Suspending();
WebAssembly.promising()

Node.js v22 LTS is stuck with the current v8 release:

As v22 will get stuck with V8 v12.4 as LTS, it will be increasingly difficult to backport patches for them even if the bugs are fixed.

This means we can either wait for Node.js v23 (scheduled for release on Oct 15) and hope it will ship the latest v8 version, or we can build JSPI binaries for Node.js using the older API.

I'd say let's wait for Node.js to catch up. Any code we write to support the older API will take time to write and we'll have to undo it in a few months anyway. Patience is the key.

@adamziel adamziel moved this from Inbox to Blocked in Playground Board Oct 9, 2024
@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

I just confirmed Node.js v23 nightly supports the latest JSPI API!

@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

I just triggered the unit tests using this command and a lot of them passed 🎉

$ ~/Downloads/node-v23.0.0-nightly2024100909d10b50dc-darwin-x64/bin/node --experimental-wasm-jspi --experimental-wasm-stack-switching --expose-gc node_modules/nx/bin/nx run php-wasm-node:test

There were some failures, though. Both ones that we can safely ignore, such as

   ❯ src/test/php-crash.spec.ts > PHP 7.0 – process crash > Does not crash due to an unhandled Asyncify error
     → php.run should have thrown an error

And ones we'll need to look into:

   ❯ src/test/php-request-handler.spec.ts > PHPRequestHandler – Loopback call > Spawn: exec() can spawn another PHP before the previous run() concludes
     → expected 'Starting: <br />\n<b>Warning</b>:  ex…' to deeply equal 'Starting: Ran second.php! Done'
   ❯ src/test/php-request-handler.spec.ts > PHPRequestHandler – Loopback call > Loopback: handler.request() can be called before the previous call concludes
     → expected 'Starting: <br />\n<b>Warning</b>:  ex…' to deeply equal 'Starting: Ran second.php! Done'
stderr | src/test/php-crash.spec.ts > PHP 8.1 – process crash > Does not crash due to an unhandled non promise err

   ❯ src/test/php-networking.spec.ts > PHP 8.3 > should be able to make a request to a server
     → expected '<br />\n<b>Warning</b>:  file_get_con…' to deeply equal 'response from express'
   ❯ src/test/php-networking.spec.ts > PHP 8.3 > cURL > should support single handle requests
     → Test timed out in 1000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".
   ❯ src/test/php-networking.spec.ts > PHP 8.3 > cURL > should support multi handle requests
     → Test timed out in 1000ms.
If this is a long-running test, pass a timeout value as the last argument or configure it globally with "testTimeout".

@brandonpayton
Copy link
Member

Nice work here!

❯ src/test/php-networking.spec.ts > PHP 8.3 > cURL > should support single handle requests
→ Test timed out in 1000ms.

It seems unlikely that this failure is due to a long-running test, but maybe it would be worth increasing the timeout to check.

See:
"JSPI much slower than Asyncify on asynchronous JS to WebAssembly calls"
https://issues.chromium.org/issues/41491351

@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

#1876 should do the trick

@adamziel adamziel moved this from Blocked to In progress in Playground Board Oct 9, 2024
@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

Fixed in #1876. The next released packages will support JSPI.

@adamziel adamziel closed this as completed Oct 9, 2024
@github-project-automation github-project-automation bot moved this from In progress to Done in Playground Board Oct 9, 2024
adamziel added a commit that referenced this issue Oct 9, 2024
 Gets `@php-wasm/node` and all the other CLI packages to load the .wasm
 binaries from the correct path after #1867 introduced JSPI and #1873 made
 it pass all the tests in Node.js

 ## Technical details

In the repo, php.js files are stored in php_wasm/node/jspi or php_wasm/node/asyncify.
 They start with a line like this:

 const dependencyFilename = __dirname + '/8_0_30/php_8_0.wasm';

 After the build, the contents are concatenated into a single file, which
 breaks the dependencyFilename variable. This plugin corrects that by
 replacing __dirname with the correct value such as 'jspi' or 'asyncify'.

 The implementation is naive and assumes the substrings __dirname is only used
 as a variable, are not a part of any other name, and is not seen in any string
 literals.

 ## Test plan

Build the production packages with `nx build php-wasm-node` and run the
PHP CLI package to confirm it doesn't crash. I couldn't get npm link to
work so I created a `dist/packages/php-wasm/node_modules/@php-wasm`
directory and linked all the built packages there with `ln -s`.
adamziel added a commit that referenced this issue Oct 9, 2024
…1877)

Gets `@php-wasm/node` and all the other CLI packages to load the .wasm
binaries from the correct path after #1867 introduced JSPI and #1873
made
 it pass all the tests in Node.js

 ## Technical details

In the repo, php.js files are stored in php_wasm/node/jspi or
php_wasm/node/asyncify.
 They start with a line like this:

 const dependencyFilename = __dirname + '/8_0_30/php_8_0.wasm';

After the build, the contents are concatenated into a single file, which
 breaks the dependencyFilename variable. This plugin corrects that by
replacing __dirname with the correct value such as 'jspi' or 'asyncify'.

The implementation is naive and assumes the substrings __dirname is only
used
as a variable, are not a part of any other name, and is not seen in any
string
 literals.

 ## Test plan

Build the production packages with `nx build php-wasm-node` and run the
PHP CLI package to confirm it doesn't crash. I couldn't get npm link to
work so I created a `dist/packages/php-wasm/node_modules/@php-wasm`
directory and linked all the built packages there with `ln -s`.
@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

The latest @wp-playground/cli release supports JSPI on node.js v23 with the experimental flags. This runs without any issues:

~/Downloads/node-v23.0.0-nightly2024100909d10b50dc-darwin-x64/bin/node --experimental-wasm-jspi --experimental-wasm-stack-switching  ./cli  server

There isn't yet an easy way of checking which build are we running. It would be cool to add a line to phpinfo().

cc @bgrgicak I'm really curious how many more plugins would now insta..

@adamziel
Copy link
Collaborator Author

adamziel commented Oct 9, 2024

@wojtekn this would make Studio much more stable with MySQL - no more WASM crashes

@bgrgicak
Copy link
Collaborator

cc @bgrgicak I'm really curious how many more plugins would now insta..

I need to spend some time making the test runner scalable and adding support for different tests.
Adding JSPI support sounds like a good way to do that. After it's working well we could provide a straightforward way for others to add more tests in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

3 participants