feat(plugin): Fix plugin BoxRef return and Box argument support

- Fixed deadlock in FileBox plugin copyFrom implementation (single lock)
- Added TLV Handle (tag=8) parsing in calls.rs for returned BoxRefs
- Improved plugin loader with config path consistency and detailed logging
- Fixed loader routing for proper Handle type_id/fini_method_id resolution
- Added detailed logging for TLV encoding/decoding in plugin_loader_v2

Test docs/examples/plugin_boxref_return.nyash now works correctly:
- cloneSelf() returns FileBox Handle properly
- copyFrom(Box) accepts plugin Box arguments
- Both FileBox instances close and fini correctly

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-21 00:41:26 +09:00
parent af32896574
commit cc2a820af7
274 changed files with 7244 additions and 4608 deletions

View File

@ -949,6 +949,20 @@ impl NyashInterpreter {
arguments: &[ASTNode],
) -> Result<Box<dyn NyashBox>, RuntimeError> {
eprintln!("🔍 execute_plugin_box_v2_method called: {}.{}", plugin_box.box_type, method);
// Route via loader for proper TLV/Handle handling (early return)
{
let mut arg_values: Vec<Box<dyn NyashBox>> = Vec::new();
for arg in arguments {
arg_values.push(self.execute_expression(arg)?);
}
let loader_guard = crate::runtime::plugin_loader_v2::get_global_loader_v2();
let loader = loader_guard.read().map_err(|_| RuntimeError::RuntimeFailure { message: "Plugin loader lock poisoned".into() })?;
match loader.invoke_instance_method(&plugin_box.box_type, method, plugin_box.instance_id, &arg_values) {
Ok(Some(result_box)) => return Ok(result_box),
Ok(None) => return Ok(Box::new(VoidBox::new())),
Err(e) => return Err(RuntimeError::RuntimeFailure { message: format!("Plugin method {} failed: {:?}", method, e) }),
}
}
// Get global loader to access configuration
let loader = crate::runtime::plugin_loader_v2::get_global_loader_v2();
@ -1085,6 +1099,33 @@ impl NyashInterpreter {
let string = String::from_utf8_lossy(data).to_string();
Ok(Box::new(StringBox::new(string)))
}
8 => {
// Handle type - contains type_id and instance_id
if size == 8 {
let type_id = u32::from_le_bytes([
output_buffer[8], output_buffer[9],
output_buffer[10], output_buffer[11]
]);
let instance_id = u32::from_le_bytes([
output_buffer[12], output_buffer[13],
output_buffer[14], output_buffer[15]
]);
eprintln!("🔍 Received Handle: type_id={}, instance_id={}", type_id, instance_id);
// Create a new PluginBoxV2 instance with the returned handle
let new_plugin_box = PluginBoxV2 {
box_type: plugin_box.box_type.clone(),
type_id: plugin_box.type_id,
invoke_fn: plugin_box.invoke_fn,
instance_id: instance_id,
fini_method_id: plugin_box.fini_method_id,
};
Ok(Box::new(new_plugin_box))
} else {
eprintln!("🔍 Invalid Handle size: {} (expected 8)", size);
Ok(Box::new(VoidBox::new()))
}
}
9 => {
// Void type
Ok(Box::new(StringBox::new("ok")))