From 6cb1849473792bd73dbfb6265d363f149f687572 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 4 Aug 2026 03:03:10 +0900 Subject: fix(plugin): resolve review findings in the plugin activation flow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- crates/shirabe/src/installer.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'crates/shirabe/src/installer.rs') diff --git a/crates/shirabe/src/installer.rs b/crates/shirabe/src/installer.rs index f68ab35f..bda4e2f6 100644 --- a/crates/shirabe/src/installer.rs +++ b/crates/shirabe/src/installer.rs @@ -1257,7 +1257,9 @@ impl Installer { if self.execute_operations { local_repo.set_dev_package_names(self.locker.borrow_mut().get_dev_package_names()?); - self.installation_manager.borrow_mut().execute( + // A shared borrow: plugin registration inside execute re-enters this manager + // handle through the Composer graph. + self.installation_manager.borrow().execute( &crate::repository::InstalledRepositoryInterfaceHandle::from_repository_handle( &local_repo, ), -- cgit v1.3.1