Skip to content

[PHP][Node] Export more side-module symbols to support the SQLite WASM extension (#3605) - #3605

Merged
adamziel merged 3 commits into
trunkfrom
codex/export-native-parser-side-module-symbols
May 7, 2026
Merged

[PHP][Node] Export more side-module symbols to support the SQLite WASM extension (#3605)#3605
adamziel merged 3 commits into
trunkfrom
codex/export-native-parser-side-module-symbols

Conversation

@adamziel

@adamziel adamziel commented May 6, 2026

Copy link
Copy Markdown
Collaborator

What it does

Allows JSPI PHP runtimes to load the SQLite Integration Rust wp_mysql_parser side module by exporting the native symbols it imports from PHP.wasm.

Rationale

The parser side module currently fails under the published PHP 8.3 runtime because the dynamic linker cannot resolve several libc/pthread and Zend symbols. MAIN_MODULE=2 only exports symbols explicitly requested during the PHP build, so the functions must be both referenced from zend-side-module-exports.c and passed to the linker as --export entries.

Implementation

Adds the missing libc/pthread exports and PHP 8+ Zend exports to the JSPI side-module export list.

Also updates packages/php-wasm/.dockerignore so PHP rebuilds can copy existing extension side modules into the Docker build context. The link step scans those .so files to preserve symbols imported by bundled extensions, but the previous ignore rules filtered out node-builds/web-builds entirely in sparse checkouts.

Testing instructions

Validated locally with a rebuilt Node JSPI PHP 8.3 runtime:

PATH="/tmp/playground-podman-bin:$PATH" npm run recompile:php:node:jspi:8.3

Then compared the rebuilt runtime exports against the SQLite parser side module:

runtime exports: 582
side env imports: 84
missing exact-or-underscore env imports: 0

Replaced Reprint's local @php-wasm/node-8-3/jspi test runtime with the rebuilt artifact and verified the native extension path:

PLAYGROUND_PHP_VERSION=8.3 \
WP_MYSQL_PARSER_EXTENSION_MANIFEST=https://wordpress.github.io/sqlite-database-integration/wp_mysql_parser-wasm-extension/latest/manifest.json \
npx --yes node@24 --experimental-wasm-jspi tests/e2e/ci/php-wasm-runner.mjs tests/e2e/ci/verify-wp-mysql-parser.php /home/claude/reprint lexer

PLAYGROUND_PHP_VERSION=8.3 \
WP_MYSQL_PARSER_EXTENSION_MANIFEST=https://wordpress.github.io/sqlite-database-integration/wp_mysql_parser-wasm-extension/latest/manifest.json \
npx --yes node@24 --experimental-wasm-jspi tests/e2e/ci/php-wasm-runner.mjs tests/e2e/ci/verify-wp-mysql-parser.php /home/claude/reprint parser

Both passed. Parser mode verified WP_MySQL_Native_Parser_Node and the WP_PDO_MySQL_On_SQLite::create_parser() native-backed AST path.

Focused Reprint benchmark with 1,000 posts / 2,500 postmeta rows also passed after forcing the benchmark wrapper to use Node 24 for JSPI:

playground-sqlite-db-pull  | 3.99 s | wp_mysql_parser=enabled, native_lexer=verified, native_parser=selected
playground-sqlite-db-apply | 6.12 s | wp_mysql_parser=enabled, native_parser=verified, sqlite_driver_parser=verified

Local notes: this machine had no Docker daemon, so the PHP rebuild used a rootless Podman wrapper. I had to reset stale Reprint e2e fixture state and install the exporter plugin Composer dependencies before the benchmark source site would provision cleanly.

@adamziel

adamziel commented May 7, 2026

Copy link
Copy Markdown
Collaborator Author

Local validation after adding zend_std_get_properties:

  • Built all supported JSPI PHP runtimes locally with the PR branch:
    • PHP 8.5.6, 8.4.21, 8.3.31, 8.2.31, 8.1.34, 8.0.30, 7.4.33
  • Checked the published SQLite Integration wp_mysql_parser JSPI side modules against the rebuilt PHP wasm exports:
    • PHP 8.0 through 8.5 all resolved with zero missing env imports
  • Copied the rebuilt JSPI packages into Reprint's local tests/e2e/node_modules/@php-wasm/node-* packages and ran the actual parser verification script in both parser and lexer modes for PHP 8.0 through 8.5.
    • Each version reported wp_mysql_parser: enabled
    • Each version verified the native lexer and WP_MySQL_Native_Token_Stream
    • Each version verified the native parser delegate, WP_MySQL_Native_Parser_Node AST, and SQLite driver's parser integration
  • PHP 7.4 was build-validated only. The SQLite Integration manifest currently lists JSPI parser artifacts for PHP 8.0-8.5, but not PHP 7.4.

One non-runtime note: PHP 8.5 prints a deprecation warning from Reprint's verification helper for ReflectionProperty::setAccessible(). The verification still passes; this is not a missing export/runtime failure.

@adamziel

adamziel commented May 7, 2026

Copy link
Copy Markdown
Collaborator Author

Pushed the generated node JSPI PHP runtime binaries as well:

  • Rebuilt and committed PHP 7.4 JSPI runtime output.
  • Added the verified PHP 8.0-8.5 JSPI runtime outputs used for the Reprint parser/lexer checks.
  • Updated supported-php-versions.mjs for the exact rebuilt patch releases:
    • 8.5.6, 8.4.21, 8.3.31, 8.2.31, 8.1.34, 8.0.30, 7.4.33
  • The 8.2-8.5 wasm directories moved to the new exact patch-version directories that the regenerated loaders reference.

Validation after restoring the binaries into the repo:

  • wp_mysql_parser JSPI side-module imports resolve with zero missing imports against PHP 8.0-8.5 rebuilt runtimes.
  • PHP 7.4 rebuilt runtime exposes representative PR-added side-module symbols including zend_get_executed_scope, zval_ptr_dtor, pthread_cond_signal, writev, zend_compile_string, and zend_ce_exception.
@adamziel
adamziel marked this pull request as ready for review May 7, 2026 21:20
@adamziel
adamziel requested review from a team, Copilot and zaerl May 7, 2026 21:20
@adamziel adamziel changed the title Export SQLite parser side-module symbols May 7, 2026
@adamziel
adamziel merged commit f319ada into trunk May 7, 2026
54 of 55 checks passed
@adamziel adamziel changed the title [PHP] Export more side-module symbols to support the SQLite WASM extension May 7, 2026
@adamziel
adamziel deleted the codex/export-native-parser-side-module-symbols branch May 7, 2026 21:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Exports additional libc/pthread and Zend symbols from the PHP.wasm main module so the SQLite Integration Rust side module (wp_mysql_parser) can dynamically link under JSPI PHP 8.3+.

Changes:

  • Added missing libc/pthread + PHP 8+ Zend symbol exports to the side-module export list (both the reference TU and linker export list).
  • Updated .dockerignore to include only extension side modules in the Docker build context so the link step can preserve their imports.
  • Bumped supported PHP patch release metadata and refresh timestamp.

Reviewed changes

Copilot reviewed 4 out of 18 changed files in this pull request and generated 2 comments.

File Description
packages/php-wasm/supported-php-versions.mjs Updates patch versions and refresh timestamp for supported PHP builds.
packages/php-wasm/compile/php/zend-side-module-exports.c References additional libc/pthread/Zend symbols to force them into the main module exports.
packages/php-wasm/compile/php/Dockerfile Adds the same symbols to the --export list used by the linker via .WASM_ABI_EXPORTS.
packages/php-wasm/.dockerignore Re-includes only extension side-module assets from node-builds/ and web-builds/ in Docker build context.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

*/

export const lastRefreshed = '2026-04-24T16:57:46.127Z';
export const lastRefreshed = '2026-05-07T07:40:54.656Z';
Comment on lines 2246 to +2277
echo 'destroy_op_array'; \
echo '_efree'; \
echo '_zend_bailout'; \
echo 'getentropy'; \
echo 'posix_memalign'; \
echo 'pthread_cond_signal'; \
echo 'pthread_cond_wait'; \
echo 'pthread_condattr_destroy'; \
echo 'pthread_condattr_init'; \
echo 'pthread_condattr_setclock'; \
echo 'pthread_mutex_trylock'; \
echo 'pthread_mutexattr_destroy'; \
echo 'pthread_mutexattr_init'; \
echo 'pthread_mutexattr_settype'; \
echo 'sched_yield'; \
echo 'writev'; \
if [ "$PHP_VERSION_MAJOR" -ge 8 ]; then \
echo 'zend_array_count'; \
echo 'zend_declare_property'; \
echo 'zend_do_implement_interface'; \
echo 'zend_hash_get_current_key_zval_ex'; \
echo 'zend_is_callable'; \
echo 'zend_is_iterable'; \
echo 'zend_lookup_class_ex'; \
echo 'zend_objects_new'; \
echo 'zend_register_internal_interface'; \
echo 'zend_std_get_properties'; \
echo 'zend_std_has_property'; \
echo 'zend_std_read_property'; \
echo 'zend_std_write_property'; \
echo 'zend_throw_exception_object'; \
fi; \
@adamziel adamziel changed the title [PHP] Export more side-module symbols to support the SQLite WASM extension (#3605) May 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment