Skip to main content

shape_vm/executor/vm_impl/
output.rs

1use super::super::*;
2
3impl VirtualMachine {
4    /// Enable output capture for testing
5    /// When enabled, print output goes to an internal buffer instead of stdout
6    pub fn enable_output_capture(&mut self) {
7        self.output_buffer = Some(Vec::new());
8    }
9
10    /// Get captured output (returns empty vec if capture not enabled)
11    pub fn get_captured_output(&self) -> Vec<String> {
12        self.output_buffer.clone().unwrap_or_default()
13    }
14
15    /// Clear captured output
16    pub fn clear_captured_output(&mut self) {
17        if let Some(ref mut buf) = self.output_buffer {
18            buf.clear();
19        }
20    }
21
22    /// Write to output (either buffer or stdout)
23    pub(crate) fn write_output(&mut self, text: &str) {
24        if let Some(ref mut buf) = self.output_buffer {
25            buf.push(text.to_string());
26        } else {
27            println!("{}", text);
28        }
29    }
30
31    /// Set a module_binding variable by name using ValueWord directly.
32    pub(crate) fn set_module_binding_by_name_nb(&mut self, name: &str, value: ValueWord) {
33        if let Some(idx) = self
34            .program
35            .module_binding_names
36            .iter()
37            .position(|n| n == name)
38        {
39            if idx < self.module_bindings.len() {
40                // BARRIER: heap write site — overwrites module binding by name
41                self.module_bindings[idx] = value;
42            } else {
43                self.module_bindings.resize_with(idx + 1, ValueWord::none);
44                // BARRIER: heap write site — overwrites module binding by name (after resize)
45                self.module_bindings[idx] = value;
46            }
47        }
48    }
49
50    /// Get the line number of the last error (for LSP integration)
51    pub fn last_error_line(&self) -> Option<u32> {
52        self.last_error_line
53    }
54
55    /// Get the file path of the last error (for LSP integration)
56    pub fn last_error_file(&self) -> Option<&str> {
57        self.last_error_file.as_deref()
58    }
59
60    /// Capture an uncaught exception payload for host-side rendering.
61    pub(crate) fn set_last_uncaught_exception(&mut self, value: ValueWord) {
62        self.last_uncaught_exception = Some(value);
63    }
64
65    /// Clear any previously captured uncaught exception payload.
66    pub(crate) fn clear_last_uncaught_exception(&mut self) {
67        self.last_uncaught_exception = None;
68    }
69
70    /// Take the last uncaught exception payload if present.
71    pub fn take_last_uncaught_exception(&mut self) -> Option<ValueWord> {
72        self.last_uncaught_exception.take()
73    }
74}