Skip to content

Migrate to WordPress Playground 3.x packages#2

Open
GabrielGallagher wants to merge 3 commits into
mainfrom
migrate/playground-3x
Open

Migrate to WordPress Playground 3.x packages#2
GabrielGallagher wants to merge 3 commits into
mainfrom
migrate/playground-3x

Conversation

@GabrielGallagher

Copy link
Copy Markdown

Summary

Moves the engine from the playground 1.0.28 stack (vendored package builds + the @expreva/php-wasm-7-4 fork) to upstream 3.1.38. Upstream wp-now is deprecated and unmaintained; the playground 3.x packages are the maintained line.

Builds on #1 (includes its commit). The locateFile Windows workaround from #1 is removed here — 3.x loaders resolve wasm paths correctly; the getPluginFile forward-slash fix is still required and kept.

What changes

Vendored dirs deleted (wp-playground-blueprints, -wordpress, -storage, php-wasm-web-utils, php-wasm-fs-journal): they were stock 1.0.28 builds with rewritten imports, vendored because the 1.x npm packages pulled ~1 GB of transitive wasm (@php-wasm/node + @php-wasm/web). The 3.1.38 releases fixed their dependency graphs, so these are plain npm deps now.

PHP versions honored — removes the options.phpVersion = '7.4' hardcode (the old // TODO: Lazy-load PHP versions):

  • @php-wasm/node-8-2 is the default runtime dependency
  • 7.4 / 8.3 / 8.4 / 8.5 are optional peers, dynamically imported with an actionable error when missing (npm install @php-wasm/node-8-3)
  • One exception to 'no vendoring': the @php-wasm/node loader (68 KB JS) is copied into php-wasm-node/ because the npm package hard-depends on every per-version runtime (~500 MB unpacked). Its dynamic import('@php-wasm/node-X-Y') calls are kept so only declared versions install. The 30 MB icu.dat is omitted → optional intl extension unsupported (documented).

3.x API updates: compileBlueprint is async; Blueprint became a V1/V2 union (typed as BlueprintV1Declaration); PHPRequestHandler.processManagerinstanceManager; bootWordPress(options)bootWordPressAndRequestHandler(options); runtimes now require a processId (allocated in the php-wasm wrapper).

Compatibility

  • startServer / getWpNowConfig / modes / .wp-env.json mappings unchanged.
  • Behavior change: requested PHP versions are real now. Consumers that passed phpVersion: '8.2' were silently getting 7.4; they now get 8.2. Default stays 8.2 (DEFAULT_PHP_VERSION).
  • Consumer installs shrink to one PHP runtime by default.

Verification (Windows 11 / Node 24)

  • Smoke: PHP 8.2 → 8.2.30, PHP 8.4 → 8.4.20, missing 8.3 → install hint.
  • @tangible/template-system against the packed tarball: compile parity 24/24, full suite 121/121 — now on real PHP 8.2 + WordPress 7.0.
  • Typecheck: 76 errors vs 124 on main — all pre-existing, no new errors (verified by diffing normalized tsc output against a main-branch baseline with old deps).

Known limitation (pre-existing): Bun on Windows can't load the fs-ext native module (no prebuilt for bun-win32); use Node there. Documented in the readme.

🤖 Generated with Claude Code

GabrielGallagher and others added 2 commits June 10, 2026 21:28
Two bugs prevented wp-now from starting on Windows:

1. The Emscripten loader in @expreva/php-wasm-* 1.x fails to locate the
   wasm binary on Windows. Under Node, the script directory is derived
   from a file URL pathname such as /C:/path, which Node resolves as
   C:\C:\path. Under Bun (jspi build), the wasm filename arrives at
   locateFile as an already-absolute path and the default implementation
   blindly prepends the script directory. Fixed upstream in php-wasm 3.x,
   but that requires migrating to the playground 3.x stack, so until then
   loadNodeRuntime is wrapped with a Windows-safe locateFile in the
   php-wasm re-export module.

2. getPluginFile built the plugin activation path with path.join, which
   produces backslashes on Windows; WordPress plugin paths always use
   forward slashes, so activate_plugin failed to find the plugin.

Verified on Windows 11 / Node 24 by building the package and running the
@tangible/template-system compile parity suite against it with unpatched
dependencies (server boots, plugin activates, 24 assertions pass);
previously it failed at server startup.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces the playground 1.0.28 stack (vendored package builds plus the
@expreva/php-wasm-7-4 fork) with upstream 3.1.38 packages. Upstream
wp-now is deprecated; the playground 3.x packages are the maintained
line and these official releases no longer pull heavy transitive
dependencies, so the vendored copies of blueprints, wordpress, storage,
and web-utils are deleted in favor of npm dependencies.

PHP versions are now honored instead of being hardcoded to 7.4:
- @php-wasm/node-8-2 ships as the default runtime
- 7.4 / 8.3 / 8.4 / 8.5 are optional peers, imported on demand with an
  actionable error when missing
- The @php-wasm/node loader (68 KB) is vendored in php-wasm-node/
  because the npm package hard-depends on every per-version runtime
  (~500 MB unpacked); see its README. The 30 MB icu.dat is omitted, so
  the optional intl extension is unsupported.

API updates for 3.x: compileBlueprint is async, Blueprint is a V1/V2
union (we use BlueprintV1Declaration), PHPRequestHandler.processManager
is now instanceManager, bootWordPress(options) is now
bootWordPressAndRequestHandler(options), and runtimes require a
processId for file locking (allocated in the php-wasm wrapper).

The Windows locateFile workaround from the previous commit is removed -
3.x loaders resolve wasm paths correctly on Windows.

Typecheck: 76 errors vs 124 on main (pre-existing; no new errors -
verified by diffing normalized tsc output against the main baseline).

Verified on Windows 11 / Node 24:
- Smoke test: PHP 8.2 and 8.4 boot and report correct phpversion();
  missing 8.3 raises the install hint
- @tangible/template-system suites against the packed tarball:
  compile parity 24/24 and full suite 121/121, now on real PHP 8.2
  (previously silently 7.4)

Known limitation: Bun on Windows cannot load the fs-ext native module
(no prebuilt binary); use Node there.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@GabrielGallagher

GabrielGallagher commented Jun 11, 2026

Copy link
Copy Markdown
Author

@nicolas-jaussaud wanted to troubleshoot some L&L issues, but this thing was getting in the way (and was stuck on PHP 7.4 which hasn't been relevant for years). I think this fixes it but can't be sure and didn't test on Linux. LMK if safe to merge. IDK where we use this elsewhere and if there will be an impact.

npm run test:node runs the test suite with Node's native TypeScript
support (--experimental-transform-types), since Bun cannot load the
fs-ext native module on Windows: it is a NAN-based addon and Bun's
V8 ABI compatibility shim crashes loading it (oven-sh/bun#4290).

Node's type stripping requires explicit type-only imports and JSON
import attributes, so type modifiers are added where types were
imported as values (found mechanically with --verbatimModuleSyntax;
zero TS1484 remain) and the test's wp-env JSON imports use
'with { type: json }'. Both syntaxes are also supported by Bun, so
npm run test continues to work unchanged.

Verified on Windows 11 / Node 24: npm run test:node passes 3/3.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@GabrielGallagher

Copy link
Copy Markdown
Author

@titus-toia @nicolas-jaussaud If I merge this, will anything bad happen? I'd love to be able to test things more seamlessly on PHP versions higher than 7.4. Will merging hurt any plugins that depend on it?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants