[PHP] Batch 3: optional ZIP, curl, and intl extensions#894
Closed
brandonpayton wants to merge 17 commits into
Closed
[PHP] Batch 3: optional ZIP, curl, and intl extensions#894brandonpayton wants to merge 17 commits into
brandonpayton wants to merge 17 commits into
Conversation
PHP's ZIP extension needs a reproducible libzip package, but the original hand-maintained source and configuration lists could drift from the pinned release and retained checkout-local build state. Build pinned libzip 1.11.4 with its upstream CMake graph, explicit wasm32/musl platform facts, and resolver-provided zlib. Publish only the archive, public headers, and relocatable pkg-config file; verify required APIs, link every archive member into a Kandelo executable, audit its actual Wasm imports, and reject producer paths. Validation: two clean builds in distinct directories produced byte-identical declared outputs; each validated 114 archive members and the same 15 allowed Wasm imports. Resolver manifest parsing and host-tool consistency checks also passed. Remaining limits: this package is wasm32-only and enables STORE/DEFLATE without optional crypto, BZIP2, LZMA, or Zstandard backends. It remains unpublished until the aggregate batch lands. Co-authored-by: mho22 <yannick@capsules.codes>
The PHP package did not expose ZipArchive, and its cross-compile link probes could falsely hide newer libzip APIs when unrelated static dependencies failed the whole-program probe. Depend on the resolver-built libzip package, build zip.so as a normal opt-in PHP side module, and preseed only the APIs verified by that exact archive. Keep the required rand, srand, and remove definitions exported from PHP main. Browser coverage serves safe basename-only PHP artifacts and mounts zip.so into the kernel-owned VFS instead of relying on host filesystem access. Validation on the exact ABI 19 serial tree: a clean build produced exactly six declared PHP artifacts with no producer paths; php.wasm and php-fpm.wasm report ABI 19; all 139 zip.so environment imports resolve through PHP or host memory. The focused Vitest suite passed 19/19, real Chromium passed 1/1, and 13 selected upstream ext/zip PHPTs passed on Node with no skips. Remaining limits: zip.so is opt-in and inherits libzip's wasm32 STORE/DEFLATE-only package boundary. A browser-PHPT attempt built its VFS but stopped before PHP because the general demo imports an unrelated full shell catalog and less.wasm was absent; only the dedicated Chromium ZIP result is claimed. The full gate remains the aggregate batch PR's responsibility. Co-authored-by: mho22 <yannick@capsules.codes>
brandonpayton
force-pushed
the
integration/kd-6nz-php-extensions
branch
from
July 12, 2026 08:13
7a76fd9 to
6aee468
Compare
Phase B-1 matrix build status —
|
| Package | Arch | Status | Sha |
|---|---|---|---|
| icu | wasm32 | built | 89ba9e6e |
| libcurl | wasm32 | built | 608a2cd0 |
| libcxx | wasm32 | built | b4e54a56 |
| libcxx | wasm64 | built | 3787dc5e |
| libiconv | wasm32 | built | 99619c53 |
| libpng | wasm32 | built | c11fe7a3 |
| libxml2 | wasm32 | built | d37e55b0 |
| libzip | wasm32 | built | 1548aa2c |
| openssl | wasm32 | built | 3bef3b47 |
| openssl | wasm64 | built | dd55f594 |
| sqlite | wasm32 | built | acaab402 |
| sqlite | wasm64 | built | d8c4bd83 |
| zlib | wasm32 | built | c2644c11 |
| zlib | wasm64 | built | 0a92e1fd |
| bc | wasm32 | built | a59b6b69 |
| bzip2 | wasm32 | built | 949ff502 |
| coreutils | wasm32 | built | 39a3cc51 |
| curl | wasm32 | built | e8f5ddda |
| dash | wasm32 | built | 3d50460e |
| diffutils | wasm32 | built | 85b92dde |
| dinit | wasm32 | built | 221fe8bc |
| fbdoom | wasm32 | built | 47c37ec5 |
| file | wasm32 | built | 15fcd9b9 |
| findutils | wasm32 | built | b9c0c6e3 |
| gawk | wasm32 | built | f6930ef0 |
| git | wasm32 | built | 0012c03b |
| grep | wasm32 | built | 93876756 |
| gzip | wasm32 | built | 6599b79a |
| hello | wasm32 | built | 65f94017 |
| kandelo-sdk | wasm32 | built | eebd138c |
| kernel | wasm32 | built | b697326f |
| less | wasm32 | built | e5fd4d44 |
| lsof | wasm32 | built | c6f6fc76 |
| m4 | wasm32 | built | 93e9875c |
| make | wasm32 | built | 49c532f3 |
| mariadb | wasm32 | built | bd8b7ee5 |
| mariadb | wasm64 | built | 7b3053c7 |
| modeset | wasm32 | built | 80aa3f6a |
| msmtpd | wasm32 | built | 5bca0f0b |
| nano | wasm32 | built | ad03e346 |
| ncurses | wasm32 | built | e67397eb |
| netcat | wasm32 | built | fb699a1f |
| nginx | wasm32 | built | 2c296da1 |
| php | wasm32 | built | 8e2b6815 |
| posix-utils-lite | wasm32 | built | 3830adcc |
| ruby | wasm32 | built | bf41a46b |
| sed | wasm32 | built | 43edede7 |
| spidermonkey | wasm32 | built | 608a829f |
| tar | wasm32 | built | 2d39220c |
| tcl | wasm32 | built | d0336feb |
| unzip | wasm32 | built | 990b360f |
| userspace | wasm32 | built | 1f3f8b39 |
| vim | wasm32 | built | 678b22ef |
| wget | wasm32 | built | f0503b24 |
| xz | wasm32 | built | 7ef7ea7e |
| zip | wasm32 | built | 55ee3121 |
| zstd | wasm32 | built | db024284 |
| bash | wasm32 | built | e5c92cbf |
| mariadb-test | wasm32 | built | cbb09e63 |
| mariadb-vfs | wasm32 | built | bfeb6b22 |
| mariadb-vfs | wasm64 | built | a351a119 |
| nethack | wasm32 | built | 5df5f220 |
| node | wasm32 | built | 6e2568ea |
| spidermonkey-node | wasm32 | built | e9571a92 |
| vim-browser-bundle | wasm32 | built | f74d5f17 |
| nethack-browser-bundle | wasm32 | built | 86775d63 |
| rootfs | wasm32 | built | d7a30a3f |
| shell | wasm32 | built | aa96fffe |
| lamp | wasm32 | built | aadd9846 |
| node-vfs | wasm32 | built | ff759795 |
| wordpress | wasm32 | built | e676ab95 |
Auto-generated; replaced on each push. Raw data in the publish-status workflow artifact.
The original #648 recipe reused a persistent checkout, emitted absolute cache paths in libcurl.pc, and let the curl program declare a libcurl resolver dependency that it did not consume. That made source builds vulnerable to stale state, cache collisions, and non-relocatable metadata. Build curl 8.11.1 from its verified source in a fresh resolver transaction with explicit zlib and OpenSSL inputs, PIC and reproducibility flags, and fatal configure option checking. Upstream curl has no gettext/NLS option, so the recipe documents that fact instead of retaining a no-op flag. Library and program outputs remain separate, and the recipe audits the exact output set, required API symbols, every archive member, linked Wasm imports, and producer-path hygiene. Validation: build-deps host-tool consistency passed; clean libcurl and curl source resolves passed; the 170-member linked smoke and CLI each closed over 15 allowed Wasm imports; the library package contained exactly 14 files; libcurl.a remained SHA-256 12881c39281ce300b819ffc7b3444865ff3cf3fc00bf4e7f975c6f43df9763ae; curl.wasm remained SHA-256 d85d11e77c863fd6990b83e4d3b9d92a59e1608c9232142e0ce885cd490c06f7; and the two packaged curl Vitest cases passed. The standalone curl runtime coverage proves dependency identity and file:// transfer. HTTP and real-browser behavior are exercised through PHP in the following commit; this commit does not claim an external host-bridge networking test. Co-authored-by: Yannick Decat <yannick@capsules.codes>
PHP needs curl without baking it into the base executable or bypassing the package and dlopen contracts. The original #648 artifact targeted an older PHP/ABI graph and did not establish current Node/browser parity, side-module closure, or a source-reproducible libcurl input. Advance the ABI-19 PHP recipe to revision 12, declare the resolver-built libcurl package, configure ext/curl as a shared module, compile its measured object set, and link the PIC libcurl archive into curl.so while resolving libc, zlib, OpenSSL, and PHP symbols against php.wasm. Keep base PHP curl-free. Add static import-closure checks and runtime coverage that mounts and loads the same side module on Node and in a real browser, including dlopen replay across fork and a real HTTP exchange over the kernel-owned loopback network. Validation: the final PHP source resolve produced all seven declared ABI-19 outputs; curl.so was 711962 bytes with SHA-256 26ce8003e614f8960a0df152f4faad8bb399ce4529031b97b3200b315e9a7e77; every PHP output passed the local/cache/temp path-leak scan; five focused Node Vitest cases passed, including the static closure and forked HTTP request; and the real Chromium Playwright test passed all eleven PHP browser scenarios, including curl load/version and the loopback HTTP response. The HTTP evidence uses Kandelo guest loopback because 127.0.0.1 is kernel-owned, not an external host-listener bridge. HTTPS certificate verification and arbitrary remote endpoints were not exercised by these focused tests. Co-authored-by: Yannick Decat <yannick@capsules.codes>
Introduce the initial ICU and PIC libc++ package outputs, C++ weak-self-import coverage, and the PHP intl side-module link path while keeping ICU data outside the base PHP executable. Follow-up commits in this serial reconcile the ABI-19 build, fail-closed linker behavior, reproducibility, runtime closure, fork replay, and host/browser validation. This commit intentionally makes no standalone completion or validation claim. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ICU's native Stage-1 data tools must execute during the cross build. On the Nix Linux runner, link their libstdc++ and libgcc runtimes statically so Stage 2 does not depend on loader paths for host runtime shared libraries; keep the flags Linux-only because the macOS toolchain rejects them. Linux execution evidence remains the responsibility of the later package rebuild/CI validation in this serial. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ICU previously left its common data and pkg-config files outside the declared library output contract, embedded the resolver temporary prefix in libicuuc.a, and relied on undeclared native build tools. The libcxx revision provenance also pointed at a fork commit that did not contain the published PIC recipe. Add a backward-compatible outputs.files contract with parse, cache-key, missing-output, and accepted-output coverage. Declare ICU data/pkg-config outputs and host probes, build from a clean verified source tree, and compile the fallback data path as /usr/lib/php so clean archives are stable. Keep existing package keys unchanged when files is absent, and mark the ICU/libcxx producer revisions as unpublished Automattic work. Validation: the four focused runtime-file xtask tests passed; build-deps check reported 10 consistent tools across four consumers; the six ICU tools matched the dev-shell versions. Two clean ICU rev5 builds produced byte-identical four archives, 197 headers, and icu.dat; resolver validation accepted all declared outputs and rewrote the three .pc prefixes to the canonical cache path. Two clean libcxx rev6 builds in distinct cache locations produced byte-identical four archives and 1,680 headers. Scope limits: the clean producer comparisons were run on macOS/aarch64 in the repository dev shell. The repaired Linux host-tool build is not re-claimed here beyond the original PR CI evidence, and performance was not measured.
The original intl linker change synthesized delayed stubs for every missing env function. That can hide real ABI gaps on unexecuted paths, while name-only self-import detection can also mistake an imported-function re-export for a definition and recurse through its own trampoline. Preserve Batch 2 transactional and fork-replay behavior. Supply a trampoline only when the export section proves the same-name function index is module-defined, keep main-module interposition first, and leave every other unresolved import as an eager instantiation failure. At this point in the serial, provide the wasm-exceptions C++ tag required by the intl side module. Validation: host type generation passed; host/test/dylink.test.ts passed 37/37, including genuine self-definition, missing import, imported-function re-export, C++ tag, rollback, and fork-replay cases. The built ABI-19 intl.so had zero unresolved env/GOT symbols under this rule, and all four real PHP intl Node/kernel cases passed after the stricter index check. Scope limits: this intermediate commit creates the C++ tag at the side-module linker boundary. The later process-state replay commit in this same landing serial deliberately supersedes that ownership model with one process-owned tag and adds cross-side identity coverage. Browser behavior is validated later; performance was not measured.
The original recipe was based on an older PHP tree, linked into the package source directory, and masked make failures with `|| true`. On the reconciled ABI-19 recipe that could publish a partial module: the first strict attempt exposed that only one newline-delimited object had been consumed. Preserve PHP 8.3.15, GNU libiconv, the Batch 2 extensions, forced shared-libc symbols, and fork instrumentation. Add ICU/libcxx as direct resolver dependencies, build every generated shared_objects_intl target without invoking the unsupported libtool link, then link all PIC objects and declared ICU/libcxx archives into OUT_DIR/intl.so. Reserve PHP revision 13 for the serial zip(11), curl(12), intl(13) Batch 3 order. Make the Node data fixture prefer an explicit resolved ICU file and restrict its cache fallback to the current ICU version/revision. Validation: a clean ABI-19 source resolve built 70 intl PIC objects and a 5,860,812-byte side module; php, php-fpm, opcache, phar, and zend_test were byte-identical across two clean temporary builds. The link consumed both libcxx PIC archives, and static inspection found all 3,040 intl imports resolved by PHP, the side module, or linker-owned objects. The focused Node/kernel suite passed 4/4: base PHP excludes intl, explicit loading succeeds, Locale reads icu.dat, and Collator applies locale rules. Scope limits: this evidence is for #839 on the ABI-19 Batch 2 base. The final #647 -> #648 -> #839 serial tree and real browser path are validated separately before recommendation. This adds no kernel/process ABI shape, so no ABI bump or snapshot change is included; performance was not measured.
Instantiation alone did not prove that the host supplied the C++ exception tag with the expected payload signature, and synthetic fork-state tests did not prove that ICU common-data state survives replay of a real PHP side module. Make the WAT fixture throw and catch an i32 payload through env.__cpp_exception. Add a PHP case that loads intl and icu.dat before pcntl_fork, calls an ICU-backed Locale API in the replayed child, calls Locale and Collator again in the parent, and verifies wait/exit status. Validation: with the ABI-19 sysroot present, host/test/dylink.test.ts passed 37/37. packages/registry/php/test/php-intl.test.ts passed 5/5 against the resolver-built PHP/intl/ICU artifacts; the fork-replay case completed in both branches and reaped a zero-status child. Scope limits: this commit records Node/kernel evidence. The equivalent Chromium path is added and run only on the exact landed #647 -> #648 -> #839 serial tree; it is not claimed here.
libc++abi archive members retained the absolute checkout path because both PIC
and non-PIC CMake builds lacked compiler prefix maps. ICU metadata was likewise
rewritten from the resolver temporary prefix to one producer cache path, so
fetched or moved archives still pointed back to the build machine.
Map the entire worktree, including assembled LLVM sources, both build variants,
the smoke source, and sysroots, to /usr/src/kandelo in libcxx compiler paths and
advance it to revision 7. Rewrite ICU pkg-config prefix fields to
${pcfiledir}/../.. and advance it to revision 6, keeping headers and libraries
relative to each extracted package tree.
Validation: two libcxx revision-7 builds from distinct checkout/output roots
produced byte-identical PIC and non-PIC archives, and producer-path scans were
clean. Two ICU revision-6 builds from distinct roots produced byte-identical
declared archives and icu.dat. After moving an ICU prefix, pkg-config resolved
the relocated include/library paths and a consumer compile/link succeeded.
Scope limits: the reproducibility and relocation checks ran on macOS/aarch64 in
the repository dev shell. Linux host-tool execution, the final PHP package,
Node/browser runtime behavior, and aggregate gates are validated by later
commits; performance was not measured.
Problem: program manifests could describe only executable outputs, leaving required data blobs outside cache keys, archives, local mirrors, fetched-artifact validation, and VFS installation metadata. Existing archive collection could also follow external/cyclic symlinks, and unvalidated package/output paths could escape or collide in the mirror. Design: add a program-only runtime_files contract with normalized artifact and absolute guest paths, mode metadata, length-framed cache-key fields, exact nested-artifact lookup, collision checks, and regular-file validation on build/cache/fetch paths. Archive staging dereferences only contained symlinks and rejects escapes, cycles, specials, empty declared trees, and incomplete closures. Local and fetched materialization use one package-scoped mirror layout and a structured repository-build query. Compatibility: manifests with no runtime_files retain their historical cache keys. The previously additive library outputs.files section is versioned and length-framed now, before its first published consumer, while older output sections retain their encoding for cache compatibility. Focused evidence: pkg_manifest tests passed 112/112; archive_stage tests passed 8/8; runtime-filtered tests passed 19/19; delimiter framing, fetched/source mirror parity, incomplete-archive fallback/fetch-only failure, nested paths, collisions, and symlink safety are covered. The full xtask run reached 336 passed and the same 7 pre-existing malformed-Wasm/filename fixture failures observed on the base. Limits: shell helper syntax and host resolver precedence passed, but the full aggregate package build, published-archive round trip, full host/libc gate, and browser gate have not run. The metadata helper is a repository build/materialization API, not a guest or runtime host API.
Problem: replay instantiated a fresh side module without restoring its live TLS-base global, and each module could receive a different C++ exception-tag identity. Pthread workers also have separate instances, tables, and tags, so allowing them to race process dlopen or inherit the process archive could corrupt replay. Design: keep process-owned pointer-width-correct exception/longjmp tags, archive and validate each module's exact positive TLS base, restore only that global over the fork-copied live TLS bytes, and arbitrate process dlopen against pthread fork with a host-private atomic record. Pthread dlopen now fails through dlerror; pthread fork returns ENOTSUP once the process archive is nonempty. Focused evidence: host declaration generation passed; dylink plus binary-resolver Vitest ran 33 tests passed with 16 compiler-dependent skips; the compiled fork/dlopen replay file ran 3/3, including mutated C++ thread_local state plus throw/catch and the real pthread boundary. Limits: the i64 cases exercise 64-bit pointer encoding only, not a memory64 end-to-end runtime. The full host, libc, ABI-classifier, and real browser aggregate gates have not yet run. The archive-size change is intended to remain host-private and transient; the ABI check is still required before landing.
Problem: intl.so needs an ICU data blob at runtime, but the original branch relied on cache scanning and host-only path overrides. That made local, fetched, Node, VFS, and browser executions observe different closures and allowed a present extension to run without its matching data. Design: PHP copies the exact resolver-selected ICU data into its program archive as a declared runtime file at /usr/lib/php/icu.dat. Repository image/test builders query structured package metadata for the guest path and mode, fail when intl exists without its closure, and exercise the same resolver-selected bytes on Node and browser. The PHP build exports __tls_base for fork-safe side-module replay and tracks the loader source as a cache-key input. Focused evidence: runtime metadata resolved to php/icu.dat, /usr/lib/php/icu.dat, mode 0644; the local mirror is byte-identical to both reproducible ICU rev6 outputs; shell syntax, host declarations, and the PHP browser Vite bundle passed. The dev middleware served all 30,782,896 ICU bytes and returned 400 for dot, encoded-dot, and malformed-percent artifact paths. The base-PHP focused case passed against an ABI-19 base-manifest image. Limits: the four intl runtime cases intentionally remain unvalidated on the stale cached intl.so, which the repaired host correctly rejects because it does not export mutable __tls_base. A fresh PHP rebuild, artifact inspection, Node intl/fork tests, real Chromium run, and full aggregate gates are still required. The focused base-manifest rootfs omitted unrelated lazy package entries and is not canonical browser evidence.
Reject unsafe manifest and dependency path components before registry, cache, and archive interpolation, and make package.toml's top-level schema fail closed so a misspelled runtime_files declaration cannot disappear silently. Expose every program output and runtime file in structured runtime metadata. Resolve the complete set from one local, fetched, or installed-package root, allowing whole-tier fallback while refusing mixed partial closures. Route the PHP Node, VFS, and browser consumers through that selected closure. Validation: - pkg_manifest focused suite: 116 passed - runtime metadata focused test: 1 passed - binary resolver/runtime metadata Vitest: 14 passed - live build-deps manifest check: passed - host declaration build: passed - PHP browser Vite production build: passed with ABI-19 kernel/rootfs fixtures - ABI snapshot/version check: passed - full xtask suite: 342 passed; the same 7 pre-existing archive/program fixture failures remain The full host, libc, PHPT, and manual browser suites were not run for this focused repair. Performance was not measured.
Make the shared VFS image writer honor positive partial writes until all bytes are staged, reject zero/negative/invalid progress, and close its descriptor on every exit path. Route the browser-demo wrappers through that shared implementation. Give the Node PHP intl fixture a 256 MiB rebased filesystem before adding the 30.8 MB ICU data file and verify the staged bytes by size and SHA-256. Preserve the browser fixture's proven 256 MiB growable restore and byte-check its injected side-module/runtime fixtures without re-reading the large PHP executable on every invocation. Validation: - focused VFS image-helper tests: 5 passed - exact ABI-19 PHP intl Node suite: 5 passed, including ICU data and fork replay - exact ABI-19 Chromium intl/fork case: 1 passed - host declaration build: passed - PHP browser Vite production build: passed The full browser app typecheck was attempted and remains blocked by pre-existing unrelated type errors. Its production build was attempted and remains blocked by absent coreutils/node/nc binary assets in this isolated worktree. The full host, libc, and manual browser suites were not run. Performance was not measured.
The #839 side-module repair gave each pthread fork exclusive ownership of the process dlopen lock. In the existing two-thread, 16-round concurrent-fork fixture, one thread therefore received ENOTSUP and left its peer blocked at the next barrier. Encode the unchanged host-private slot as an exclusive negative dlopen writer or a positive pthread-fork reader count. Concurrent empty-archive pthread forks can now snapshot in parallel, while dlopen remains excluded until every parent completes unwind, SYS_FORK, and rewind. Keep child reset, archive rejection, error releases, and ownership diagnostics explicit. Validation: the exact pre-#839 base passed the concurrent fixture while the prior aggregate timed out. On this repair, fork-from-thread plus dlopen/fork replay passed 5/5. Full host Vitest reached 1,251 passes, 2 expected failures, and 95 skips; its only two failures are the lazy-rootfs memory64/posix-utils fixtures reproduced on the exact base. Host declarations and the ABI consistency check passed. Browser behavior was not rerun for this host-only arbitration follow-up, and performance was not measured.
13 tasks
brandonpayton
pushed a commit
that referenced
this pull request
Jul 13, 2026
PHP intl needs reproducible ICU and libc++ inputs plus fail-closed C++ side-module linking before the host/guest replay contract can advance safely. Build PIC ICU/libc++ outputs without producer paths, declare non-Wasm runtime files explicitly, complete the initial intl.so link path, reject unresolved C++ imports, and cover exceptions and fork replay. This compatible setup intentionally precedes ABI 36; the next commit owns the incompatible replay-memory and pthread-fork contract, while the following PHP commit owns final ICU runtime-data materialization. Source-era package and focused runtime evidence is retained as review provenance, but the final ABI-38 artifact rebuild and complete Node/browser gate apply at the super-batch tip. Source-PR: #839 Source-PR: #894 Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
brandonpayton
added a commit
that referenced
this pull request
Jul 13, 2026
intl.so needs the exact resolver-selected ICU data blob at runtime. Cache scanning and host-only path overrides made local, fetched, Node, VFS, and browser executions observe different closures and could leave a present extension without matching data. Copy the selected ICU data into the PHP program archive as declared /usr/lib/php/icu.dat state, keep general runtime files in one artifact tier, query structured package metadata from image/test builders, and reject incomplete VFS staging. The PHP consumers now follow the ABI-36 side-module replay contract established by the preceding epoch. Source-era evidence covers reproducible ICU/libc++ outputs, runtime metadata and byte identity, complete PHP artifacts, focused Node/browser intl behavior, and fail-closed stale-artifact handling. Those results are provenance rather than a claim about an ABI-19 artifact; final ABI-38 archives and broad gates remain the super-batch tip's responsibility. Pthread-side dynamic loading remains truthfully unsupported. Source-PR: #839 Source-PR: #894
Member
Author
|
Merged PR #907 supersedes this PHP package wave through the curated commits now on main ( |
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.
Purpose
Stacked Batch 3 integration PR for the PHP extension work. It is based on the
still-open Batch 2 platform/ABI branch, so the extension layer remains
independently reviewable on the exact ABI-19 runtime it was built against.
Constituent PRs were reviewed and repaired individually, then rebase-merged
here in serial PHP-recipe order. Their original GitHub PRs are
MERGED; thisaggregate remains open and must not merge into Batch 2 or
mainwithoutBrandon's explicit approval.
Per-constituent ready-to-merge CI was intentionally skipped under the agreed
batching plan. Focused evidence supports each review decision; the full
ready-to-merge gate runs once on this final aggregate tree.
Constituent review ledger
#647 — reproducible libzip package and PHP ZIP extension — incorporated
zip.soside module, with STORE/DEFLATE behavior through normal Node and browser runtime paths.mho22attribution.zip.soenvironment imports resolved. Focused Vitest passed 19/19; selected Node ZIP PHPTs passed 13/13; dedicated real Chromium passed 1/1 with a DEFLATE close/reopen through the kernel VFS.0aaab1226,6aee4687a. Original PR [PHP] Ship the libzip-backed ZIP extension #647 isMERGED.#648 — reproducible libcurl/curl packages and PHP curl extension — incorporated
curl.so, keeping base PHP curl-free while exercising normal dlopen, fork replay, and kernel networking paths.libcurl.pc, truthful dependencies/host tools, exact outputs, required-symbol checks, all-170-member linking, complete final-import audits, and producer-path rejection. Added package CLI coverage plus Node and browser PHP tests, including a fork-child HTTP request to a guest loopback listener. Rebuilt old merge history as two purpose-led commits with Yannick Decat attribution.curl.sopassed static closure and 5/5 Node tests. Real Chromium passed 1/1 and all eleven asserted PHP scenarios, including forked guest-loopback HTTP.1f369181e,ec8b9e318. Reviewed and landed trees both equal556d557446d5c688c535fbf58f2a474163917665. Original PR [PHP] Ship the libcurl-backed curl extension #648 isMERGED.#839 — reproducible ICU/libc++ packages and optional PHP intl — incorporated
intl.sowith its matchingicu.datruntime closure, while keeping base PHP ICU-free. Shared Node/browser host logic supports fail-closed C++ side-module linking, process-owned exception-tag identity, and TLS-safe fork replay.icu.datthrough the normal package/VFS closure. Host repair proves weak self-imports are module-defined before using a trampoline, fails genuinely missing imports eagerly, owns pointer-width-correct C++ tags per process, restores validated TLS bases across fork replay, and exposes the pthread boundary truthfully. The final VFS repair handles positive partial writes, fails on no progress, provides sufficient Node image capacity, verifies staged bytes, and routes browser-demo writers through the shared implementation. The aggregate host gate then exposed that the initial dlopen lock incorrectly rejected the second concurrent pthread fork; follow-upba4fb0db0preserves dlopen exclusion with an exclusive writer plus counted fork readers.ba4fb0db0, fork/dlopen focus passed 5/5 and full host reached 1,251 passes with 2 expected failures and 95 skips; only the same two fixture failures remain, and both reproduce identically on exact pre-PHP: ship intl as an optional ICU-backed side module #839 baseec8b9e318. The exactba4fb0db0final-head core rerun passed kernel 1,135/1,135, libc 303 with 20 documented XFAIL and one known FLAKE-PASS but no unexpected outcomes, and the ABI consistency check. Real Chromium then ran the two-thread, 16-round concurrent-fork guest at the same head: exit 0, expected PASS output, empty stderr, and no console, page, request, or HTTP errors../run.sh browserverification remain. Reproducibility builds ran on macOS/aarch64; the Linux host-tool path retains package-CI evidence. Pointer-width i64 cases are synthetic rather than a memory64 end-to-end runtime. Pthread-side dynamic loading remains explicitly unsupported. Performance was not measured. A separate TeX Live-only direct VFS writer is outside this PHP landing and is not claimed fixed.3c097d617,6351dca50,54a5e43c1,5ed6e0ee7,a2a439c38,dde62ef75,0c0b8b3a0,42d45e237,41e809ce5,254bbeecf,48bc91ec9, ande6d080f1c; reviewed and landed trees both equal149bb568e0cc6d733fe9e6af17f6fc3db3b86964. Aggregate gate follow-up:ba4fb0db0. Original PR PHP: ship intl as an optional ICU-backed side module #839 isMERGED.Batch 2 browser dependency
Batch 2 advanced from
84f086975to6d93e09d5with two reviewed browserrepairs. The PHP page now imports only the canonical 63-file rootfs closure and
runs all PHPT sections/tests on one worker-owned VFS using the current
initFromImage/spawnFromVfscontract. Typed worker RPCs stage/restoregenerated scripts without returning the live VFS SAB to the main thread.
Focused tests passed 13/13; real Chromium passed
Zend/tests/001.phptand atwo-test FILE-to-CLEAN persistence run. #647 was patch-equivalently rebased
onto that base before #648 and #839 landed.
Verification status
ba4fb0db0: host regression repair, focused PHP Chromium, browser assets, exact-head kernel/libc/ABI evidence are recorded above; canonical/manual browser and the remaining package work remain.Landing mechanics
integration/kd-6nz-php-phpt-platform-fixes(open Batch 2 PR [PHP] Batch 2: PHPT platform and ABI fixes #871), current tip6d93e09d5.integration/kd-6nz-php-extensions, current tipba4fb0db0.mainwithout Brandon's explicit approval.