From 695365a0ad68e4534425c64b7a6a4b6598b68ef7 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Tue, 4 Aug 2026 04:07:41 +0900 Subject: feat(plugin): dispatch plugin event subscribers through the RPC worker Wires the addPlugin subscriber branch end to end: EventSubscriberInterface and Capable become fallible and dyn-compatible (their sole implementor is the PHP plugin proxy, which answers getSubscribedEvents over RPC), listeners register as Callable::PhpMethod and are invoked with a per-call event handle, and the R table now drops entries when a child-side stub destructs. The R table keeps its IndexMap with monotonically increasing handles, so released handles are never reused and no generation counter is needed. Upstream has no subscriber-plugin test, so the path is covered by a Shirabe-owned fixture exercising all three getSubscribedEvents shapes. Co-Authored-By: Claude Fable 5 --- crates/shirabe/src/plugin/plugin_manager.rs | 32 +++++++++++++++-------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'crates/shirabe/src/plugin/plugin_manager.rs') diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs index 65c4b03f..a3810d0c 100644 --- a/crates/shirabe/src/plugin/plugin_manager.rs +++ b/crates/shirabe/src/plugin/plugin_manager.rs @@ -485,9 +485,12 @@ impl PluginManager { .into()); } let handle = self.php_runtime_new_object(&class)?; - let plugin: std::rc::Rc> = std::rc::Rc::new( - std::cell::RefCell::new(PhpPluginProxy::new(handle.phandle, handle.class)), - ); + let plugin: std::rc::Rc> = + std::rc::Rc::new(std::cell::RefCell::new(PhpPluginProxy::new( + handle.phandle, + handle.class, + handle.implements, + ))); self.add_plugin(plugin.clone(), is_global_plugin, Some(package.clone()))?; self.registered_plugins .entry(package.get_name().to_string()) @@ -513,7 +516,7 @@ impl PluginManager { let value = unwrap_php_result(call_function_with_dispatcher( function, args, - Some(&mut PluginRpcDispatcher), + Some(&mut PluginRpcDispatcher::default()), ))?; match value { PluginValue::Bool(value) => Ok(value), @@ -545,7 +548,7 @@ impl PluginManager { unwrap_php_result(call_function_with_dispatcher( "__shirabe_eval", vec![PluginValue::string(code)], - Some(&mut PluginRpcDispatcher), + Some(&mut PluginRpcDispatcher::default()), ))?; Ok(()) } @@ -561,7 +564,7 @@ impl PluginManager { PluginValue::string(file_identifier), PluginValue::string(file), ], - Some(&mut PluginRpcDispatcher), + Some(&mut PluginRpcDispatcher::default()), ))?; Ok(()) } @@ -571,7 +574,7 @@ impl PluginManager { let value = unwrap_php_result(shirabe_php_rpc::new_object( class, vec![], - Some(&mut PluginRpcDispatcher), + Some(&mut PluginRpcDispatcher::default()), ))?; match value { PluginValue::PhpHandle(handle) => Ok(handle), @@ -735,12 +738,12 @@ impl PluginManager { .borrow_mut() .activate(self.composer_full(), self.io.clone())?; - // TODO(plugin): if plugin is EventSubscriberInterface, hook into the event dispatcher - // The PHP code calls $this->composer->getEventDispatcher()->addSubscriber($plugin); - // — add_subscriber here is generic over `S: EventSubscriberInterface` and cannot - // accept a `&dyn EventSubscriberInterface`. Skipped until subscriber dispatch is - // implemented dynamically. - let _ = plugin.borrow().is_event_subscriber_interface(); + let plugin_ref = plugin.borrow(); + if let Some(subscriber) = plugin_ref.as_event_subscriber() { + let event_dispatcher = self.composer_full().borrow().get_event_dispatcher(); + let result = event_dispatcher.borrow_mut().add_subscriber(subscriber); + result?; + } Ok(()) } @@ -949,13 +952,12 @@ impl PluginManager { plugin: &dyn PluginInterface, capability: &str, ) -> anyhow::Result> { - // TODO(plugin): capability lookup let capable = match plugin.as_capable() { Some(c) => c, None => return Ok(None), }; - let capabilities = capable.get_capabilities(); + let capabilities = capable.get_capabilities()?; // PHP: !empty($capabilities[$capability]) && is_string($capabilities[$capability]) && trim($capabilities[$capability]) if let Some(s) = capabilities.get(capability) { -- cgit v1.3.1