aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/plugin/plugin_manager.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-04 04:31:51 +0900
committernsfisis <nsfisis@gmail.com>2026-08-04 05:43:26 +0900
commit3f3ad76eafcc5513000ac7526c74c2009bb390d8 (patch)
treee601fd78b4bed6add607305098bdf6257eeba7d8 /crates/shirabe/src/plugin/plugin_manager.rs
parent695365a0ad68e4534425c64b7a6a4b6598b68ef7 (diff)
downloadphp-shirabe-3f3ad76eafcc5513000ac7526c74c2009bb390d8.tar.gz
php-shirabe-3f3ad76eafcc5513000ac7526c74c2009bb390d8.tar.zst
php-shirabe-3f3ad76eafcc5513000ac7526c74c2009bb390d8.zip
feat(plugin): remove subscribed listeners when a plugin is removed
Wire removePlugin to EventDispatcher::removeListener now that subscriber listeners carry the plugin's P-table handle: PHP's $candidate[0] === $listener identity check maps to phandle equality on Callable::PhpMethod. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/plugin/plugin_manager.rs')
-rw-r--r--crates/shirabe/src/plugin/plugin_manager.rs16
1 files changed, 13 insertions, 3 deletions
diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs
index a3810d0c..aaee7d5a 100644
--- a/crates/shirabe/src/plugin/plugin_manager.rs
+++ b/crates/shirabe/src/plugin/plugin_manager.rs
@@ -772,9 +772,19 @@ impl PluginManager {
.borrow_mut()
.deactivate(self.composer_full(), self.io.clone())?;
- // TODO(plugin): remove_listener accepts any callable/object in PHP; here we have
- // a plugin instance and need to translate to a Callable, which is not portable
- // without runtime reflection.
+ // PHP passes the plugin object itself; its cross-RPC identity (the P-table handle) is
+ // carried by the subscriber accessor, and `addSubscriber` is the only source of
+ // listeners capturing a plugin object today.
+ // TODO(plugin): a plugin registering `[$this, 'method']` listeners directly through an
+ // EventDispatcher proxy would have no removal path here; no such RPC surface exists yet.
+ let subscriber_handle = removed
+ .borrow()
+ .as_event_subscriber()
+ .map(|s| s.subscriber_handle());
+ if let Some(handle) = subscriber_handle {
+ let event_dispatcher = self.composer_full().borrow().get_event_dispatcher();
+ event_dispatcher.borrow_mut().remove_listener(&handle);
+ }
Ok(())
}