feat: Implement plugin singleton pattern with shutdown support

- Add singleton support for plugin boxes (e.g., CounterBox)
- Implement shutdown_plugins_v2() for controlled plugin lifecycle
- Plugin instances now shared across multiple new() calls
- Shutdown properly releases and allows re-initialization
- All singleton E2E tests passing 

ChatGPT5による高度なプラグインライフサイクル管理実装
- シングルトンパターンでプラグインインスタンス共有
- 明示的なshutdownでリソース解放と再初期化対応
- Nyashの統一ライフサイクルポリシー維持

Note: ast.rs test failures are due to rapid development pace -
tests need updating for new BoxDeclaration fields (private_fields, public_fields)

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Moe Charm
2025-08-21 21:35:17 +09:00
parent 8c6d5b5adc
commit da716addc8
16 changed files with 465 additions and 107 deletions

View File

@ -59,7 +59,13 @@ impl ArrayBox {
let idx = idx_box.value as usize;
let items = self.items.read().unwrap();
match items.get(idx) {
Some(item) => item.clone_box(),
Some(item) => {
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
if item.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
return item.share_box();
}
item.clone_box()
}
None => Box::new(crate::boxes::null_box::NullBox::new()),
}
} else {
@ -228,7 +234,13 @@ impl ArrayBox {
// Create slice
let slice_items: Vec<Box<dyn NyashBox>> = items[start_idx..end_idx]
.iter()
.map(|item| item.clone_box())
.map(|item| {
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
if item.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
return item.share_box();
}
item.clone_box()
})
.collect();
Box::new(ArrayBox::new_with_elements(slice_items))
@ -241,7 +253,13 @@ impl Clone for ArrayBox {
// ディープコピー(独立インスタンス)
let items_guard = self.items.read().unwrap();
let cloned_items: Vec<Box<dyn NyashBox>> = items_guard.iter()
.map(|item| item.clone_box()) // 要素もディープコピー
.map(|item| {
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
if item.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
return item.share_box();
}
item.clone_box()
}) // 要素もディープコピー(ハンドルは共有)
.collect();
ArrayBox {