Merge pull request #71 from moe-charm/copilot/fix-70

Fix SocketBox state consistency bug - isServer() method now works correctly after bind()
This commit is contained in:
moe-charm
2025-08-14 17:18:35 +09:00
committed by GitHub
4 changed files with 75 additions and 6 deletions

View File

@ -56,12 +56,18 @@ pub struct SocketBox {
impl Clone for SocketBox { impl Clone for SocketBox {
fn clone(&self) -> Self { fn clone(&self) -> Self {
// Read the current state values atomically
let current_is_server = *self.is_server.lock().unwrap();
let current_is_connected = *self.is_connected.lock().unwrap();
// For listener and stream, we can't clone them, so we'll share them
// but create new Arc instances with the current state
Self { Self {
base: BoxBase::new(), // New unique ID for clone base: BoxBase::new(), // New unique ID for clone
listener: Arc::clone(&self.listener), listener: Arc::clone(&self.listener), // Share the same listener
stream: Arc::clone(&self.stream), stream: Arc::clone(&self.stream), // Share the same stream
is_server: Arc::clone(&self.is_server), is_server: Arc::new(Mutex::new(current_is_server)), // New Arc with current value
is_connected: Arc::clone(&self.is_connected), is_connected: Arc::new(Mutex::new(current_is_connected)), // New Arc with current value
} }
} }
} }
@ -314,7 +320,8 @@ impl SocketBox {
/// サーバーモード確認 /// サーバーモード確認
pub fn is_server(&self) -> Box<dyn NyashBox> { pub fn is_server(&self) -> Box<dyn NyashBox> {
Box::new(BoolBox::new(*self.is_server.lock().unwrap())) let is_server_value = *self.is_server.lock().unwrap();
Box::new(BoolBox::new(is_server_value))
} }
} }

View File

@ -455,7 +455,22 @@ impl NyashInterpreter {
// SocketBox method calls // SocketBox method calls
if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() { if let Some(socket_box) = obj_value.as_any().downcast_ref::<SocketBox>() {
return self.execute_socket_method(socket_box, method, arguments); let result = self.execute_socket_method(socket_box, method, arguments)?;
// 🔧 FIX: Update stored variable for stateful SocketBox methods
// These methods modify the SocketBox internal state, so we need to update
// the stored local variable to ensure subsequent accesses get the updated state
if matches!(method, "bind" | "connect" | "close") {
if let ASTNode::Variable { name, .. } = object {
if let Some(stored_var) = self.local_vars.get_mut(name) {
// Replace the stored instance with the modified one
let updated_instance = socket_box.clone();
*stored_var = Box::new(updated_instance);
}
}
}
return Ok(result);
} }
// HTTPServerBox method calls // HTTPServerBox method calls

24
test_arc_sharing.nyash Normal file
View File

@ -0,0 +1,24 @@
// Test Arc sharing issue
static box Main {
main() {
print("🔬 Testing Arc sharing...")
local socket1
socket1 = new SocketBox()
local socket2
socket2 = socket1 // This should clone
print("Before bind - socket1.isServer(): " + socket1.isServer().toString())
print("Before bind - socket2.isServer(): " + socket2.isServer().toString())
socket1.bind("127.0.0.1", 8080)
print("After bind - socket1.isServer(): " + socket1.isServer().toString())
print("After bind - socket2.isServer(): " + socket2.isServer().toString())
socket1.close()
return true
}
}

23
test_socket_simple.nyash Normal file
View File

@ -0,0 +1,23 @@
// Simple test for SocketBox state sharing
static box Main {
main() {
print("🧪 Testing SocketBox state sharing...")
local socket
socket = new SocketBox()
print("Initial isServer: " + socket.isServer().toString())
local bindOk
bindOk = socket.bind("127.0.0.1", 8080)
print("Bind result: " + bindOk.toString())
print("After bind isServer: " + socket.isServer().toString())
local closeOk
closeOk = socket.close()
print("Close result: " + closeOk.toString())
return true
}
}