feat: WASMビルド完全対応+finiシステム修正 🎉
## WASMビルド対応 - TimerBox、AudioBox等の問題のあるBoxをWASM環境では条件付きコンパイルで除外 - WebBox (WebDisplayBox, WebConsoleBox, WebCanvasBox) にas_anyメソッド追加 - プラグイン関連コードに#[cfg]ガードを追加 - web-sysフィーチャーを追加(Performance、MouseEvent等) - projects/nyash-wasmのビルドが完全に通るように! ## finiシステム修正 - フィールド差し替え時の自動fini削除(Nyashの明示的哲学に従う) - スコープ離脱時のみfini実行(meは除外) - ドキュメント更新で正しいfiniルールを明記 ## その他 - CLAUDE.mdにWASMビルド方法を追記(wasm-pack build --target web) - 開発サーバー起動方法を記載(python3 -m http.server 8010) - cargo testで全テスト成功を確認 これでNyashがブラウザで動作可能に!🐱✨ 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -503,6 +503,30 @@ impl NyashInterpreter {
|
||||
}
|
||||
|
||||
pub(super) fn restore_local_vars(&mut self, saved: HashMap<String, Box<dyn NyashBox>>) {
|
||||
// 🎯 スコープ離脱時:現在のローカル変数に対してfiniを呼ぶ
|
||||
// ただし「me」は特別扱い(インスタンス自身なのでfiniしない)
|
||||
for (name, value) in &self.local_vars {
|
||||
// 「me」はインスタンス自身なのでスコープ離脱時にfiniしない
|
||||
if name == "me" {
|
||||
continue;
|
||||
}
|
||||
|
||||
// ユーザー定義Box(InstanceBox)の場合
|
||||
if let Some(instance) = (**value).as_any().downcast_ref::<InstanceBox>() {
|
||||
let _ = instance.fini();
|
||||
eprintln!("🔄 Scope exit: Called fini() on local variable '{}' (InstanceBox)", name);
|
||||
}
|
||||
// プラグインBoxの場合
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
if let Some(plugin) = (**value).as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
plugin.call_fini();
|
||||
eprintln!("🔄 Scope exit: Called fini() on local variable '{}' (PluginBox)", name);
|
||||
}
|
||||
// ビルトインBoxは元々finiメソッドを持たないので呼ばない
|
||||
// (StringBox、IntegerBox等はリソース管理不要)
|
||||
}
|
||||
|
||||
// その後、保存されていた変数で復元
|
||||
self.local_vars = saved.into_iter()
|
||||
.map(|(k, v)| (k, Arc::from(v))) // Convert Box to Arc
|
||||
.collect();
|
||||
@ -516,6 +540,23 @@ impl NyashInterpreter {
|
||||
}
|
||||
|
||||
pub(super) fn restore_outbox_vars(&mut self, saved: HashMap<String, Box<dyn NyashBox>>) {
|
||||
// 🎯 スコープ離脱時:現在のoutbox変数に対してもfiniを呼ぶ
|
||||
for (name, value) in &self.outbox_vars {
|
||||
// ユーザー定義Box(InstanceBox)の場合
|
||||
if let Some(instance) = (**value).as_any().downcast_ref::<InstanceBox>() {
|
||||
let _ = instance.fini();
|
||||
eprintln!("🔄 Scope exit: Called fini() on outbox variable '{}' (InstanceBox)", name);
|
||||
}
|
||||
// プラグインBoxの場合
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
if let Some(plugin) = (**value).as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
plugin.call_fini();
|
||||
eprintln!("🔄 Scope exit: Called fini() on outbox variable '{}' (PluginBox)", name);
|
||||
}
|
||||
// ビルトインBoxは元々finiメソッドを持たないので呼ばない(要修正)
|
||||
}
|
||||
|
||||
// その後、保存されていた変数で復元
|
||||
self.outbox_vars = saved.into_iter()
|
||||
.map(|(k, v)| (k, Arc::from(v))) // Convert Box to Arc
|
||||
.collect();
|
||||
|
||||
@ -13,6 +13,7 @@ use crate::instance_v2::InstanceBox;
|
||||
use crate::channel_box::ChannelBox;
|
||||
use crate::interpreter::core::{NyashInterpreter, RuntimeError};
|
||||
use crate::interpreter::finalization;
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
use crate::runtime::plugin_loader_v2::PluginBoxV2;
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -489,6 +490,7 @@ impl NyashInterpreter {
|
||||
// RangeBox method calls (将来的に追加予定)
|
||||
|
||||
// PluginBoxV2 method calls
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
if let Some(plugin_box) = obj_value.as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
return self.execute_plugin_box_v2_method(plugin_box, method, arguments);
|
||||
}
|
||||
@ -902,6 +904,7 @@ impl NyashInterpreter {
|
||||
}
|
||||
|
||||
/// Execute method call on PluginBoxV2
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
fn execute_plugin_box_v2_method(
|
||||
&mut self,
|
||||
plugin_box: &PluginBoxV2,
|
||||
|
||||
@ -305,17 +305,8 @@ impl NyashInterpreter {
|
||||
}
|
||||
}
|
||||
|
||||
// 既存のフィールド値があれば fini() を呼ぶ
|
||||
if let Some(old_field_value) = instance.get_field(field) {
|
||||
if let Some(old_instance) = (*old_field_value).as_any().downcast_ref::<InstanceBox>() {
|
||||
let _ = old_instance.fini();
|
||||
finalization::mark_as_finalized(old_instance.box_id());
|
||||
}
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
if let Some(old_plugin) = (*old_field_value).as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
old_plugin.call_fini();
|
||||
}
|
||||
}
|
||||
// 🚨 フィールド差し替え時の自動finiは削除(Nyashの明示的哲学)
|
||||
// プログラマーが必要なら明示的にfini()を呼ぶべき
|
||||
|
||||
instance.set_field(field, Arc::from(val.clone_box()))
|
||||
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
|
||||
@ -342,17 +333,8 @@ impl NyashInterpreter {
|
||||
});
|
||||
}
|
||||
|
||||
// 既存のthis.field値があれば fini() を呼ぶ
|
||||
if let Some(old_field_value) = instance.get_field(field) {
|
||||
if let Some(old_instance) = (*old_field_value).as_any().downcast_ref::<InstanceBox>() {
|
||||
let _ = old_instance.fini();
|
||||
finalization::mark_as_finalized(old_instance.box_id());
|
||||
}
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
if let Some(old_plugin) = (*old_field_value).as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
old_plugin.call_fini();
|
||||
}
|
||||
}
|
||||
// 🚨 フィールド差し替え時の自動finiは削除(Nyashの明示的哲学)
|
||||
// プログラマーが必要なら明示的にfini()を呼ぶべき
|
||||
|
||||
instance.set_field(field, Arc::from(val.clone_box()))
|
||||
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
|
||||
@ -379,17 +361,8 @@ impl NyashInterpreter {
|
||||
});
|
||||
}
|
||||
|
||||
// 既存のme.field値があれば fini() を呼ぶ
|
||||
if let Some(old_field_value) = instance.get_field(field) {
|
||||
if let Some(old_instance) = (*old_field_value).as_any().downcast_ref::<InstanceBox>() {
|
||||
let _ = old_instance.fini();
|
||||
finalization::mark_as_finalized(old_instance.box_id());
|
||||
}
|
||||
#[cfg(all(feature = "plugins", not(target_arch = "wasm32")))]
|
||||
if let Some(old_plugin) = (*old_field_value).as_any().downcast_ref::<crate::runtime::plugin_loader_v2::PluginBoxV2>() {
|
||||
old_plugin.call_fini();
|
||||
}
|
||||
}
|
||||
// 🚨 フィールド差し替え時の自動finiは削除(Nyashの明示的哲学)
|
||||
// プログラマーが必要なら明示的にfini()を呼ぶべき
|
||||
|
||||
instance.set_field(field, Arc::from(val.clone_box()))
|
||||
.map_err(|e| RuntimeError::InvalidOperation { message: e })?;
|
||||
|
||||
@ -15,6 +15,8 @@
|
||||
use super::*;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use crate::boxes::web::{WebDisplayBox, WebConsoleBox, WebCanvasBox};
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use crate::boxes::FloatBox;
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
impl NyashInterpreter {
|
||||
|
||||
Reference in New Issue
Block a user