Week in review: 1 June 2026
A recap of what shipped during the week of 1 June. Five items this week: a second framework roadmap (CodeIgniter 4 alongside Laravel), four new runtime modules (password, hash, sessions, MySQL), continued progress on the embedded -S server and ini parameter handling, a full audit of how each PHP type is represented in JS, and the removal of Rector as a pre-processing step thanks to two new transpiler features.
CodeIgniter 4 joins the roadmap
The roadmap page now carries a framework selector at the top. Switching between Laravel and CodeIgniter 4 swaps the phase plan and the per-package status. The CI4 roadmap was computed from composer show on the framework and grouped into the same five-phase shape: foundations, pure utilities, dev utilities, the PHPUnit and sebastian/* testing stack, and the framework itself plus its static-analysis tooling. The two roadmaps reuse status for shared packages (PSRs, deep-copy, sebastian/exporter, phpunit/phpunit), so progress on Laravel automatically reflects on CI4 where the packages overlap.
The motivation and a longer write-up of the CI4 work itself (including the opensourcepos POC that boots and logs in) is in the CI4 roadmap post.
Password, hash, sessions, MySQL
Four runtime areas landed to support CI4 (and incidentally cover a chunk of what Laravel needs in its later phases). password_hash and password_verify produce hashes in the same format PHP does, including the algorithm marker and cost prefix, so round-trips between PHP-side data and the converted runtime are bit-for-bit compatible. The hash module covers hash, hash_hmac, hash_equals, hash_init, and the common algorithm names CI4 uses for session signing and CSRF tokens.
The sessions module exposes the $_SESSION superglobal, the session_* entry points, and a handler interface that framework-side session backends (file, database, redis, memcached) plug into without further runtime work. The MySQL client implements the mysqli and PDO surfaces CI4 reaches for: prepared statements, parameter binding, transactions, the row-fetching shapes the query builder expects. The common path is in; some of the exotic charset and timezone handling still needs exercising.
Embedded server and ini tuning
The embedded -S server SAPI that landed in the previous sprint kept making steady progress this week. Most of the work was finishing the configuration surface: which ini directives the server honours at start-up, which are tunable per-request, and how the server merges command-line overrides with the directives declared in the pext.ini equivalent the bootstrap reads. The behaviour now mirrors PHP's -S mode closely enough that the documented PHP flags work the same way in Pext, with the same precedence between command-line, ini file, and environment.
Full type-coverage audit
Every primitive and structural type PHP exposes (int, float, string, bool, null, array, object, resource, callable) was audited for how it is represented in the converted runtime, where it differs from a naive JS mapping, and what the cost of the difference is. The notable finds: resource still has a few rough edges where the runtime returns a thin wrapper that some PHP code path treats as something more substantial; float matches IEEE 754 doubles directly, which is correct but means a small handful of PHP-specific edge cases (the precision setting on string conversion, comparisons against integer extremes) needed dedicated handling; and the array story is the same it has always been, the dual ordered-map-and-list semantics, well-trodden by now.
The audit became a living document the runtime tests now reference. Adding a new built-in that returns a resource or that compares floats now has a paragraph to look up before the test gets written.
Dropping the Rector pre-processing step
The conversion pipeline used to run rector over the input PHP first, mostly to normalise a couple of forms the transpiler did not yet handle. That pre-processing step is gone this week, because the transpiler now handles both of the things rector was rewriting.
The first was case-insensitive identifier resolution. PHP function names, class names, and namespace segments are case-insensitive at the language level: strlen(), STRLEN(), and StrLen() all resolve to the same function. The transpiler now does the same normalisation at conversion time, with the same rules PHP applies (functions and classes are case-insensitive; constants and variables are not), and emits canonical references so the generated JS is identifier-stable. No more rector rewriting STRLEN to strlen before the transpiler sees it.
The second was named arguments. PHP 8.0 added the foo(arg: 1, other: 2) form, which binds arguments by name rather than position. JavaScript has no equivalent at the call site, so this had been handled by rector rewriting named calls into positional calls before conversion. The transpiler now emits a small runtime resolver instead: for any call site that uses named arguments, the conversion looks the target up in a reflection-derived metadata table, computes the positional order at call time, and dispatches to the target with the resolved arguments. The metadata table is built once at module load. Variadic targets and constructors with named arguments work the same way.
Removing the pre-processing step shortens the build, drops one external tool from the dependency surface, and makes the converted output traceable line-for-line back to the original PHP file. The transpiler is now the only thing between input and output.