(len: usize)
| 171 | |
| 172 | #[unsafe(no_mangle)] |
| 173 | pub unsafe extern "C" fn run_start(len: usize) -> u32 { |
| 174 | // Discard any previous paused run; a fresh `run_start` is a hard reset of execution state. |
| 175 | with_runtime(|rt| { rt.paused_run = None; }); |
| 176 | |
| 177 | let src = match read_src(len) { |
| 178 | Ok(s) => s, |
| 179 | Err(e) => { |
| 180 | let msg = s!("input rejected: invalid utf-8 at byte ", int e.valid_up_to()); |
| 181 | let n = unsafe { write_out(&msg) }; |
| 182 | return STATUS_ERROR | ((n as u32) & STATUS_PAYLOAD_MASK); |
| 183 | } |
| 184 | }; |
| 185 | |
| 186 | let (tokens, lex_errs) = lex(&src); |
| 187 | let resolver = Box::new(WasmHostResolver { dir: String::new() }); |
| 188 | let mut p = Parser::with_resolver(&src, tokens.into_iter(), resolver); |
| 189 | for e in lex_errs { |
| 190 | p.errors.push(Diagnostic { start: e.start, end: e.end, msg: e.msg.into() }); |
| 191 | } |
| 192 | let (mut chunk, errs) = p.parse(); |
| 193 | |
| 194 | if !errs.is_empty() { |
| 195 | let mut buf = String::new(); |
| 196 | for (i, e) in errs.iter().enumerate() { |
| 197 | if i > 0 { buf.push('\n'); } |
| 198 | buf.push_str(&e.render(&src, None)); |
| 199 | } |
| 200 | let n = unsafe { write_out(&buf) }; |
| 201 | return STATUS_ERROR | ((n as u32) & STATUS_PAYLOAD_MASK); |
| 202 | } |
| 203 | |
| 204 | crate::modules::vm::optimizer::constant_fold(&mut chunk); |
| 205 | |
| 206 | // Leak chunk so its lifetime survives across `run_resume`; reclaimed on page reload. |
| 207 | let chunk_static: &'static SSAChunk = Box::leak(Box::new(chunk)); |
| 208 | let mut vm = VM::with_limits(chunk_static, Limits::sandbox()); |
| 209 | vm.print_hook = Some(stream_print); |
| 210 | vm.set_time_hook(now_ns_host); |
| 211 | vm.strict_input = true; |
| 212 | |
| 213 | let inp_text = with_runtime(|rt| { |
| 214 | if rt.inp_len == 0 { return String::new(); } |
| 215 | let bytes = &rt.inp[..rt.inp_len]; |
| 216 | let inp = core::str::from_utf8(bytes).unwrap_or("").to_string(); |
| 217 | rt.inp_len = 0; |
| 218 | inp |
| 219 | }); |
| 220 | if !inp_text.is_empty() { |
| 221 | vm.input_buffer = inp_text.split('\n').map(alloc::string::String::from).collect(); |
| 222 | } |
| 223 | |
| 224 | step_vm(vm, &src, None) |
| 225 | } |
| 226 | |
| 227 | #[unsafe(no_mangle)] |
| 228 | pub unsafe extern "C" fn run_resume() -> u32 { |
nothing calls this directly
no test coverage detected