v0.7: event-listener system (addEventListener/step/breakpoint/signal/exit)
- Native step/cont moved to __step_native/__cont_native; public step()/cont()
defined in prelude.js wrap them and dispatch JS listeners on each stop.
- addEventListener/removeEventListener/clearListeners/listeners() registry on
globalThis, persistent for the daemon lifetime (independent of ctx.reset()).
- Event object carries {state, prev, stop_reason} plus breakpoint_id/signal/
exit_code as appropriate. Implements the SPEC 'Event Listeners' + 'Core Loop'.
- No-listener fast path keeps existing scripts zero-cost.
- examples/smarm_ctx_switch.js: worked session inspecting smarm's naked-asm
context switch; README updated (status table, listener API, deferred list).
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
//!
|
||||
//! Native globals installed here:
|
||||
//! spawn(path, ...args) -> { pid, status }
|
||||
//! step(n=1) / cont() -> stop-reason string
|
||||
//! __step_native(n=1) / __cont_native() -> stop-reason string
|
||||
//! (public step()/cont() are defined in prelude.js and fire listeners)
|
||||
//! print(...args), ctx (persistent object)
|
||||
//! state.pc, state.sp -> BigInt (live ptrace)
|
||||
//! state.registers -> object of BigInts
|
||||
@@ -181,7 +182,12 @@ fn install_globals<'js>(
|
||||
globals.set("spawn", f)?;
|
||||
}
|
||||
|
||||
// ---------- step(n=1) ----------
|
||||
// ---------- __step_native(n=1) ----------
|
||||
// Raw single-stepper. Steps up to n instructions, stopping early if the
|
||||
// target dies. Returns the last stop-reason string. The public `step(n)`
|
||||
// is defined in prelude.js: it loops one instruction at a time so it can
|
||||
// fire 'step'/'breakpoint' listeners after each stop. We keep the native
|
||||
// n-loop too, for the fast path when no listeners are registered.
|
||||
{
|
||||
let target = target.clone();
|
||||
let f = Function::new(c.clone(), move |c: Ctx<'js>, n: rquickjs::function::Opt<i64>| -> rquickjs::Result<String> {
|
||||
@@ -204,10 +210,13 @@ fn install_globals<'js>(
|
||||
}
|
||||
Ok(last.map(|r| r.tag()).unwrap_or_else(|| "step".into()))
|
||||
})?;
|
||||
globals.set("step", f)?;
|
||||
globals.set("__step_native", f)?;
|
||||
}
|
||||
|
||||
// ---------- continue() / cont() ----------
|
||||
// ---------- __cont_native() ----------
|
||||
// Raw continue. Resumes until the next stop (breakpoint, signal, exit).
|
||||
// The public `cont()` in prelude.js wraps this to fire listeners on the
|
||||
// resulting stop.
|
||||
{
|
||||
let target = target.clone();
|
||||
let f = Function::new(c.clone(), move |c: Ctx<'js>| -> rquickjs::Result<String> {
|
||||
@@ -219,8 +228,8 @@ fn install_globals<'js>(
|
||||
}
|
||||
})?;
|
||||
// NOTE: `continue` is a reserved keyword in JS — `continue()` as an
|
||||
// expression is a syntax error. We expose only `cont()` for v0.1.
|
||||
globals.set("cont", f)?;
|
||||
// expression is a syntax error. We expose only `cont()`.
|
||||
globals.set("__cont_native", f)?;
|
||||
}
|
||||
|
||||
// ---------- state ----------
|
||||
|
||||
Reference in New Issue
Block a user