test: Verify plugin system with feature flags
- Successfully built CounterBox and FileBox plugins in release mode - All plugin E2E tests passing with --features plugins flag - CounterBox: 2/2 tests ✅ (basic inc/get, assignment sharing) - FileBox: 4/4 tests ✅ (close void, delegation, VM, Handle TLV) プラグインシステムの完全動作確認 - プラグインのリリースビルド成功 - plugins featureフラグでのE2Eテスト全て成功 - 統一レジストリシステムが正常動作 🤖 Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -547,12 +547,29 @@ impl NyashInterpreter {
|
||||
|
||||
/// local変数を宣言(関数内でのみ有効)
|
||||
pub(super) fn declare_local_variable(&mut self, name: &str, value: Box<dyn NyashBox>) {
|
||||
self.local_vars.insert(name.to_string(), Arc::from(value));
|
||||
// Pass-by-share for plugin handle types; by-value (clone) semantics can be applied at call sites
|
||||
#[allow(unused_mut)]
|
||||
let mut store_value = value;
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
{
|
||||
if store_value.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
|
||||
store_value = store_value.share_box();
|
||||
}
|
||||
}
|
||||
self.local_vars.insert(name.to_string(), Arc::from(store_value));
|
||||
}
|
||||
|
||||
/// outbox変数を宣言(static関数内で所有権移転)
|
||||
pub(super) fn declare_outbox_variable(&mut self, name: &str, value: Box<dyn NyashBox>) {
|
||||
self.outbox_vars.insert(name.to_string(), Arc::from(value));
|
||||
#[allow(unused_mut)]
|
||||
let mut store_value = value;
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
{
|
||||
if store_value.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
|
||||
store_value = store_value.share_box();
|
||||
}
|
||||
}
|
||||
self.outbox_vars.insert(name.to_string(), Arc::from(store_value));
|
||||
}
|
||||
|
||||
/// local変数スタックを保存・復元(関数呼び出し時)
|
||||
|
||||
@ -282,7 +282,22 @@ impl NyashInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
self.set_variable(name, val.clone_box())?;
|
||||
// Assign-by-share for plugin handle types; clone for others
|
||||
let assigned = {
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
{
|
||||
if val.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
|
||||
val.share_box()
|
||||
} else {
|
||||
val.clone_box()
|
||||
}
|
||||
}
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
{
|
||||
val.clone_box()
|
||||
}
|
||||
};
|
||||
self.set_variable(name, assigned)?;
|
||||
Ok(val)
|
||||
}
|
||||
|
||||
@ -330,7 +345,18 @@ impl NyashInterpreter {
|
||||
// 🚨 フィールド差し替え時の自動finiは削除(Nyashの明示的哲学)
|
||||
// プログラマーが必要なら明示的にfini()を呼ぶべき
|
||||
|
||||
instance.set_field(field, Arc::from(val.clone_box()))
|
||||
// Store-by-share for plugin handle types; clone for others
|
||||
let stored = {
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
{
|
||||
if val.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
|
||||
val.share_box()
|
||||
} else { val.clone_box() }
|
||||
}
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
{ val.clone_box() }
|
||||
};
|
||||
instance.set_field(field, Arc::from(stored))
|
||||
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
|
||||
Ok(val)
|
||||
} else {
|
||||
@ -354,7 +380,17 @@ impl NyashInterpreter {
|
||||
// 🚨 フィールド差し替え時の自動finiは削除(Nyashの明示的哲学)
|
||||
// プログラマーが必要なら明示的にfini()を呼ぶべき
|
||||
|
||||
instance.set_field(field, Arc::from(val.clone_box()))
|
||||
let stored = {
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
{
|
||||
if val.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
|
||||
val.share_box()
|
||||
} else { val.clone_box() }
|
||||
}
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
{ val.clone_box() }
|
||||
};
|
||||
instance.set_field(field, Arc::from(stored))
|
||||
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
|
||||
Ok(val)
|
||||
} else {
|
||||
@ -378,7 +414,17 @@ impl NyashInterpreter {
|
||||
// 🚨 フィールド差し替え時の自動finiは削除(Nyashの明示的哲学)
|
||||
// プログラマーが必要なら明示的にfini()を呼ぶべき
|
||||
|
||||
instance.set_field(field, Arc::from(val.clone_box()))
|
||||
let stored = {
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
{
|
||||
if val.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>().is_some() {
|
||||
val.share_box()
|
||||
} else { val.clone_box() }
|
||||
}
|
||||
#[cfg(any(not(feature = "plugins"), target_arch = "wasm32"))]
|
||||
{ val.clone_box() }
|
||||
};
|
||||
instance.set_field(field, Arc::from(stored))
|
||||
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
|
||||
Ok(val)
|
||||
} else {
|
||||
|
||||
@ -50,7 +50,7 @@ v2
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn e2e_counter_assignment_clones_not_shares() {
|
||||
fn e2e_counter_assignment_shares_handle() {
|
||||
if !try_init_plugins() { return; }
|
||||
|
||||
let code = r#"
|
||||
@ -66,10 +66,9 @@ v
|
||||
|
||||
match interpreter.execute(ast) {
|
||||
Ok(result) => {
|
||||
// Current semantics: assignment clones (not shares), so c remains 0
|
||||
assert_eq!(result.to_string_box().value, "0");
|
||||
// New semantics: plugin handle assign shares, so c reflects x.inc()
|
||||
assert_eq!(result.to_string_box().value, "1");
|
||||
}
|
||||
Err(e) => panic!("Counter assignment test failed: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user