Skip to main content

PiJsRuntime

Struct PiJsRuntime 

Source
pub struct PiJsRuntime<C: SchedulerClock = WallClock> { /* private fields */ }
Expand description

Integrated PiJS runtime combining QuickJS, scheduler, and Promise bridge.

This is the main entry point for running JavaScript extensions with proper async hostcall support. It provides:

  • Promise-based pi.* methods that enqueue hostcall requests
  • Deterministic event loop scheduling
  • Automatic microtask draining after macrotasks
  • Hostcall completion → Promise resolution/rejection

§Example

// Create runtime
let runtime = PiJsRuntime::new().await?;

// Evaluate extension code
runtime.eval("
    pi.tool('read', { path: 'foo.txt' }).then(result => {
        console.log('Got:', result);
    });
").await?;

// Process hostcall requests
while let Some(request) = runtime.drain_hostcall_requests().pop_front() {
    // Execute the hostcall
    let result = execute_tool(&request.kind, &request.payload).await;
    // Deliver completion back to JS
    runtime.complete_hostcall(&request.call_id, result)?;
}

// Tick the event loop to deliver completions
let stats = runtime.tick().await?;

Implementations§

Source§

impl PiJsRuntime<WallClock>

Source

pub async fn new() -> Result<Self>

Create a new PiJS runtime with the default wall clock.

Source§

impl<C: SchedulerClock + 'static> PiJsRuntime<C>

Source

pub async fn with_clock(clock: C) -> Result<Self>

Create a new PiJS runtime with a custom clock.

Source

pub async fn with_clock_and_config( clock: C, config: PiJsRuntimeConfig, ) -> Result<Self>

Create a new PiJS runtime with a custom clock and runtime config.

Source

pub async fn with_clock_and_config_with_policy( clock: C, config: PiJsRuntimeConfig, policy: Option<ExtensionPolicy>, ) -> Result<Self>

Create a new PiJS runtime with a custom clock, runtime config, and optional policy.

Source

pub async fn reset_for_warm_reload(&self) -> Result<PiJsWarmResetReport>

Source

pub async fn eval(&self, source: &str) -> Result<()>

Evaluate JavaScript source code.

Source

pub async fn call_global_void(&self, name: &str) -> Result<()>

Invoke a zero-argument global JS function and drain immediate microtasks.

This is useful for hot loops that need to trigger pre-installed JS helpers without paying per-call parser/compile overhead from eval().

Source

pub const fn repair_mode(&self) -> RepairMode

The configured repair mode for this runtime.

Source

pub const fn auto_repair_enabled(&self) -> bool

Whether the auto-repair pipeline should apply repairs.

Source

pub fn record_repair(&self, event: ExtensionRepairEvent)

Record an auto-repair event. The event is appended to the internal log and emitted as a structured tracing span so external log sinks can capture it.

Source

pub fn drain_repair_events(&self) -> Vec<ExtensionRepairEvent>

Drain all accumulated repair events, leaving the internal buffer empty. Useful for conformance reports that need to distinguish clean passes from repaired passes.

Source

pub fn repair_count(&self) -> u64

Number of repair events recorded since the runtime was created.

Source

pub fn reset_transient_state(&self)

Reset transient module state for warm isolate reuse.

Clears extension roots, dynamic virtual modules, named export tracking, repair events, and cache counters while preserving the compiled sources cache (both in-memory and disk). This lets the runtime be reloaded with a fresh set of extensions without paying the SWC transpilation cost again.

Source

pub async fn eval_file(&self, path: &Path) -> Result<()>

Evaluate a JavaScript file.

Source

pub async fn read_global_json(&self, name: &str) -> Result<Value>

Read a global variable from the JS context and convert it to JSON.

This is primarily intended for integration tests and diagnostics; it intentionally does not expose raw rquickjs types as part of the public API.

Source

pub fn drain_hostcall_requests(&self) -> VecDeque<HostcallRequest>

Drain pending hostcall requests from the queue.

Returns the requests that need to be processed by the host. After processing, call complete_hostcall() for each.

Source

pub async fn drain_microtasks(&self) -> Result<usize>

Drain pending QuickJS jobs (Promise microtasks) until fixpoint.

Source

pub fn next_timer_deadline_ms(&self) -> Option<u64>

Return the next timer deadline (runtime clock), if any.

Source

pub fn pending_hostcall_count(&self) -> usize

Peek at pending hostcall requests without draining.

Source

pub fn hostcall_queue_telemetry(&self) -> HostcallQueueTelemetry

Snapshot queue depth/backpressure counters for diagnostics.

Source

pub fn hostcall_queue_wait_ms(&self, call_id: &str) -> Option<u64>

Queue wait (enqueue -> dispatch start) in milliseconds for a pending hostcall.

Source

pub fn is_hostcall_pending(&self, call_id: &str) -> bool

Check whether a given hostcall is still pending.

This is useful for streaming hostcalls that need to stop polling/reading once the JS side has timed out or otherwise completed the call.

Source

pub async fn get_registered_tools(&self) -> Result<Vec<ExtensionToolDef>>

Get all tools registered by loaded JS extensions.

Source

pub async fn get_global_json(&self, name: &str) -> Result<Value>

Read a global value by name and convert it to JSON.

This is intentionally a narrow helper that avoids exposing raw rquickjs types in the public API (useful for integration tests and debugging).

Source

pub fn complete_hostcall( &self, call_id: impl Into<String>, outcome: HostcallOutcome, )

Enqueue a hostcall completion to be delivered on next tick.

Source

pub fn complete_hostcalls_batch<I>(&self, completions: I)
where I: IntoIterator<Item = (String, HostcallOutcome)>,

Enqueue multiple hostcall completions in one scheduler borrow.

Source

pub fn enqueue_event(&self, event_id: impl Into<String>, payload: Value)

Enqueue an inbound event to be delivered on next tick.

Source

pub fn set_timeout(&self, delay_ms: u64) -> u64

Set a timer to fire after the given delay.

Returns the timer ID for cancellation.

Source

pub fn clear_timeout(&self, timer_id: u64) -> bool

Cancel a timer by ID.

Source

pub fn now_ms(&self) -> u64

Get the current time from the clock.

Source

pub fn has_pending(&self) -> bool

Check if there are pending tasks (macrotasks or timers).

Source

pub async fn tick(&self) -> Result<PiJsTickStats>

Execute one tick of the event loop.

This will:

  1. Move due timers to the macrotask queue
  2. Execute one macrotask (if any)
  3. Drain all pending QuickJS jobs (microtasks)

Returns statistics about what was executed.

Source

pub fn add_allowed_read_root(&self, root: PathBuf)

Install the pi.* bridge with Promise-returning hostcall methods.

The bridge uses a two-layer design:

  1. Rust native functions (__pi_*_native) that return call_id strings
  2. JS wrappers (pi.*) that create Promises and register them

This avoids lifetime issues with returning Promises from Rust closures. Register an additional filesystem root that readFileSync is allowed to access. Called before loading each extension so it can read its own bundled assets (HTML templates, markdown docs, etc.).

Source

pub fn add_extension_root(&self, root: PathBuf)

Register an extension root directory so the resolver can detect monorepo escape patterns (Pattern 3). Also registers the root for readFileSync access.

Source

pub fn add_extension_root_with_id( &self, root: PathBuf, extension_id: Option<&str>, )

Register an extension root with optional extension ID metadata.

Pattern 4 (missing npm dependency proxy stubs) uses this metadata to apply stricter policy for official/first-party extensions and to allow same-scope package imports (@scope/*) when scope can be discovered.

Trait Implementations§

Auto Trait Implementations§

§

impl<C> Freeze for PiJsRuntime<C>

§

impl<C = WallClock> !RefUnwindSafe for PiJsRuntime<C>

§

impl<C = WallClock> !Send for PiJsRuntime<C>

§

impl<C = WallClock> !Sync for PiJsRuntime<C>

§

impl<C> Unpin for PiJsRuntime<C>

§

impl<C> UnsafeUnpin for PiJsRuntime<C>

§

impl<C = WallClock> !UnwindSafe for PiJsRuntime<C>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

Source§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

Source§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

Source§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, _span: NoopSpan) -> Self

Instruments this future with a span (no-op when disabled).
Source§

fn in_current_span(self) -> Self

Instruments this future with the current span (no-op when disabled).
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ParallelSend for T

Source§

impl<T> Send for T
where T: ?Sized,

Source§

impl<T> Sync for T
where T: ?Sized,