aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe-php-rpc/php/stubs
AgeCommit message (Collapse)Author
2026-08-04feat(plugin): generate the worker proxy stubs from the Composer sourcesnsfisis
Replace the hand-written proxy stubs under crates/shirabe-php-rpc/php/stubs with output of scripts/plugin-stub-generator, a deterministic emitter that derives every stub from the Composer checkout and the classifier report. Anything it cannot faithfully proxy (by-ref/variadic parameters, magic methods, public properties, diverging omitted overrides, stale stub files, a STUB_FILES entry missing in lib.rs) fails generation instead of degrading silently, so future Composer releases surface new members as explicit errors rather than silent gaps. Regenerating the stubs also normalizes the hand-written inconsistencies (uniform guarded constructors, import-based type spellings) and fixes real gaps the review of the generated diff uncovered: the BaseIO authentication methods now carry the real class's untyped signatures, and the previously missing ConsoleIO::sanitize is materialized together with its private static helper. A cargo test runs generate-stubs --check to keep the committed stubs, the generator and the embedded list from drifting apart. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04fix(plugin): resolve review findings in the plugin activation flownsfisis
InstallationManager::execute now takes &self (the mock recorder moved into a RefCell) and its callers hold only shared borrows: plugin registration inside a batch re-enters the same manager handle through Composer::getInstallationManager()->getInstallPath(), which panicked on the RefCell re-borrow under the &mut shape — the same re-entrancy the repository side already fixed, unreachable from the ported tests because they call PluginInstaller::install directly like PHPUnit does. The worker-side InstalledVersions mirror now matches the full tail of FilesystemRepository::write: unconditional reload plus the reflection-based selfDir/installedIsLocalDir restore. The previous class_exists(false) guard rested on a lazy-load assumption that does not hold in the worker (its real ClassLoader only knows the Composer checkout's vendor dir, so a later lazy load would read the checkout's installed.php, not the project's); the mirror is now skipped only when the class is not autoloadable at all, i.e. no plugin runtime and hence no observer code. Boot-time seeding stays TODO(plugin). Also from the review: registered_plugins entries are removed only after the deactivate/uninstall loop (PHP unsets last, and a throw must leave the entry observable); extra.class keeps associative-array values and fails loudly on non-strings instead of silently dropping them; the two discarded write() results now propagate (they carry the reload-push failure); register_package's allow-plugins skip message is DEBUG like the addPlugin side; the loader-eviction divergence of REGISTERED_LOADERS and the lossy UTF-8 spots carry searchable markers; the test-only proxy downcast follows the __ naming rule; the R-table dispatch clones the entity out instead of holding the table borrow across the handler; the IO/PartialComposer stubs turn a plugin-side `new NullIO()` into an explicit error instead of an ArgumentCountError; and the empty() emulation covers float 0.0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-04feat(plugin): activate plugins through the PHP RPC workernsfisis
Implement the remainder of PluginManager::registerPackage: the plugin autoload map is built by the ported createLoader/parseAutoloads and served to the worker over the existing reverse-RPC autoloader, files entries go through a composerRequire-equivalent glue call, and already-defined classes take the upstream _composer_tmp rename/eval path. Instantiation uses the new NewObject/CallPhpMethod lanes backed by a P table in the worker; PhpPluginProxy adapts the resulting handle to PluginInterface, with $composer/$io exposed to plugin callbacks via an R table (unsupported methods stay explicit errors). Hand-written proxy stubs cover Composer, PartialComposer and the IO hierarchy, and the stub autoloader is re-prepended after loading the Composer PHP runtime so its vendor autoloader cannot shadow proxied FQCNs. FilesystemRepository::write now mirrors InstalledVersions::reload into a running worker (class_exists-guarded, so an unloaded class keeps its upstream lazy-load behavior), removing the previously undefined observation window. The installer pipeline passes the installed repository as a shared handle instead of a long-lived `&mut dyn`: plugin registration runs inside InstallationManager::execute and re-enters the same local repository through the RepositoryManager, which would panic on the RefCell re-borrow under the old shape. PluginInterface lifecycle methods now take an owned ComposerHandle (plugins retain $composer past the call) and return anyhow::Result (PHP plugin code may throw); the plugin list uses shared ownership so the identity comparison of removePlugin survives the dual storage in registeredPlugins, matching PHP reference semantics. Ports the activate/upgrade/uninstall tests of PluginInstallerTest, serialized across the shared worker process whose persistent class table is exactly what exercises the rename path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-03feat(php-rpc): rework the RPC channel into the tagged plugin protocolnsfisis
Replace the name\0arg framing with the plugin wire protocol: tagged frames with corr_id multiplexing, a MAX_FRAME_LEN bound, a thread-ID based reentrant SessionLock, and the PluginValue codec (encoder plus the first recursive decoder, iterative with a 512-level depth cap). Float formatting is ported from php-src into shirabe-php-src so the encoder is byte-compatible with serialize() under serialize_precision=-1, which the spawned worker now pins. The worker gains a standing dispatch loop, CallRustMethod reentrancy, hand-written Event proxy stubs, and explicit-error answers for everything not implemented yet. The public query API (get_php_version and friends) is unchanged and now rides the new protocol; the codec is verified against real PHP by roundtrip oracle tests covering floats, non-UTF-8 bytes and deep nesting. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>