aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/plugin/plugin_manager.rs
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-09 19:10:27 +0900
committernsfisis <nsfisis@gmail.com>2026-08-09 19:10:27 +0900
commit78c23c7105914b74ae91c71496265d3b03d7e285 (patch)
tree0f7e4b384bdbc211bb1bba2c274fd416880098d7 /crates/shirabe/src/plugin/plugin_manager.rs
parent6d257691a39fb8c4191f4564ec6406d080dbf6b5 (diff)
downloadphp-shirabe-78c23c7105914b74ae91c71496265d3b03d7e285.tar.gz
php-shirabe-78c23c7105914b74ae91c71496265d3b03d7e285.tar.zst
php-shirabe-78c23c7105914b74ae91c71496265d3b03d7e285.zip
feat(plugin): let a Rust-implemented plugin cross into the worker
PluginManager::getPluginCapability hands the plugin itself to the capability constructor. Only a PHP-implemented plugin had an entity the child could receive, so a Rust-implemented one bailed out; it now crosses as a handle to an R-table entity behind Shirabe\RustPluginStub, or its Capable flavour, since `$plugin instanceof Capable` is what decides whether Composer asks a plugin for capabilities at all. This is what the two capability tests of PluginInstallerTest were waiting on: the mocked Capable plugin is Rust-side, and one of them asserts the identity of the plugin read back out of $capability->args.
Diffstat (limited to 'crates/shirabe/src/plugin/plugin_manager.rs')
-rw-r--r--crates/shirabe/src/plugin/plugin_manager.rs34
1 files changed, 16 insertions, 18 deletions
diff --git a/crates/shirabe/src/plugin/plugin_manager.rs b/crates/shirabe/src/plugin/plugin_manager.rs
index 0746a9b4..0667c6a9 100644
--- a/crates/shirabe/src/plugin/plugin_manager.rs
+++ b/crates/shirabe/src/plugin/plugin_manager.rs
@@ -16,6 +16,7 @@ use crate::plugin::PluginBlockedException;
use crate::plugin::capability::Capability;
use crate::plugin::php_plugin_proxy::{
PhpCapabilityProxy, PhpCommandProviderProxy, PhpPluginProxy, PluginRpcDispatcher, php_is_a,
+ plugin_handle_value,
};
use crate::plugin::plugin_interface::{self, PluginInterface};
use crate::repository::InstalledRepository;
@@ -1031,15 +1032,16 @@ impl PluginManager {
pub fn get_plugin_capability(
&self,
- plugin: &dyn PluginInterface,
+ plugin: &std::rc::Rc<std::cell::RefCell<dyn PluginInterface>>,
capability_class_name: &str,
ctor_args: IndexMap<String, PluginValue>,
) -> anyhow::Result<Option<Box<dyn Capability>>> {
- let capability_class =
- match self.get_capability_implementation_class_name(plugin, capability_class_name)? {
- Some(c) => c,
- None => return Ok(None),
- };
+ let capability_class = match self
+ .get_capability_implementation_class_name(&*plugin.borrow(), capability_class_name)?
+ {
+ Some(c) => c,
+ None => return Ok(None),
+ };
// PHP: if (!class_exists($capabilityClass))
let exists = unwrap_php_result(call_function_with_dispatcher(
@@ -1051,23 +1053,21 @@ impl PluginManager {
return Err(RuntimeException::new(format!(
"Cannot instantiate Capability, as class {} from plugin {} does not exist.",
capability_class,
- plugin.get_class_name()
+ plugin.borrow().get_class_name()
))
.into());
}
// PHP: $ctorArgs['plugin'] = $plugin; the capability constructor receives the plugin
- // instance itself, so a plugin with no PHP-side entity cannot be represented.
- let plugin_value = match plugin.__as_php_plugin_proxy() {
+ // instance itself. A PHP-implemented plugin already has an entity in the child's P
+ // table; a Rust-implemented one crosses as a handle to its R-table entity.
+ let plugin_value = match plugin.borrow().__as_php_plugin_proxy() {
Some(proxy) => PluginValue::PhpHandle(shirabe_php_rpc::PhpObjHandle {
phandle: proxy.phandle,
class: proxy.class.clone(),
implements: proxy.implements.clone(),
}),
- None => anyhow::bail!(
- "cannot instantiate capability {capability_class}: plugin {} has no PHP-side entity to pass as $ctorArgs['plugin']",
- plugin.get_class_name()
- ),
+ None => plugin_handle_value(plugin),
};
let mut ctor_args = ctor_args;
ctor_args.insert("plugin".to_string(), plugin_value);
@@ -1121,11 +1121,9 @@ impl PluginManager {
) -> anyhow::Result<Vec<Box<dyn Capability>>> {
let mut capabilities: Vec<Box<dyn Capability>> = vec![];
for plugin in self.get_plugins() {
- if let Some(capability) = self.get_plugin_capability(
- &*plugin.borrow(),
- capability_class_name,
- ctor_args.clone(),
- )? {
+ if let Some(capability) =
+ self.get_plugin_capability(plugin, capability_class_name, ctor_args.clone())?
+ {
capabilities.push(capability);
}
}