API Reference

Rust API

Basic Execution

rust
use tsrun::{Interpreter, StepResult, JsValue};

let mut interp = Interpreter::new();
interp.prepare(r#"
    const greeting = "Hello";
    const target = "World";
    `${greeting}, ${target}!`
"#, None)?;

loop {
    match interp.step()? {
        StepResult::Continue => continue,
        StepResult::Complete(value) => {
            assert_eq!(value.as_str(), Some("Hello, World!"));
            break;
        }
        _ => break,
    }
}

ES Module Loading

The interpreter pauses when imports are needed:

rust
use tsrun::{Interpreter, StepResult, ModulePath};

let mut interp = Interpreter::new();

// Main module with imports
interp.prepare(r#"
    import { add } from "./math.ts";
    export const result = add(2, 3);
"#, Some(ModulePath::new("/main.ts")))?;

loop {
    match interp.step()? {
        StepResult::Continue => continue,
        StepResult::NeedImports(imports) => {
            for import in imports {
                // Load module source from filesystem, network, etc.
                let source = match import.resolved_path.as_str() {
                    "/math.ts" => "export function add(a, b) { return a + b; }",
                    _ => panic!("Unknown module"),
                };
                interp.provide_module(import.resolved_path, source)?;
            }
        }
        StepResult::Complete(value) => {
            println!("Done: {}", value);
            break;
        }
        _ => break,
    }
}

Working with Values

rust
use tsrun::{Interpreter, api, JsValue};
use serde_json::json;

let mut interp = Interpreter::new();
let guard = api::create_guard(&interp);

// Create values from JSON
let user = api::create_from_json(&mut interp, &guard, &json!({
    "name": "Alice",
    "age": 30,
    "tags": ["admin", "developer"]
}))?;

// Read properties
let name = api::get_property(&user, "name")?;
assert_eq!(name.as_str(), Some("Alice"));

// Modify properties
api::set_property(&user, "email", JsValue::from("alice@example.com"))?;

// Call methods
let tags = api::get_property(&user, "tags")?;
let joined = api::call_method(&mut interp, &guard, &tags, "join", &[JsValue::from(", ")])?;
assert_eq!(joined.as_str(), Some("admin, developer"));

Async/Await with Orders

For async operations, the interpreter pauses with pending "orders" that the host fulfills:

rust
use tsrun::{Interpreter, StepResult, OrderResponse, api};

let mut interp = Interpreter::new();

interp.prepare(r#"
    import { order } from "tsrun:host";
    const response = await request({ url: "/api/users" });
    response.data
"#, Some("/main.ts".into()))?;

loop {
    match interp.step()? {
        StepResult::Continue => continue,
        StepResult::Suspended { pending, cancelled } => {
            let mut responses = Vec::new();
            for order in pending {
                // Examine order.payload to determine what to do
                let response = api::create_response_object(&mut interp, &json!({
                    "data": [{"id": 1, "name": "Alice"}]
                }))?;
                responses.push(OrderResponse {
                    id: order.id,
                    result: Ok(response),
                });
            }
            interp.fulfill_orders(responses);
        }
        StepResult::Complete(value) => {
            println!("Result: {}", value);
            break;
        }
        _ => break,
    }
}

Accessing Module Exports

rust
use tsrun::{Interpreter, StepResult, api};

let mut interp = Interpreter::new();
interp.prepare(r#"
    export const VERSION = "1.0.0";
    export const CONFIG = { debug: true };
"#, Some("/config.ts".into()))?;

// Run to completion
loop {
    match interp.step()? {
        StepResult::Continue => continue,
        StepResult::Complete(_) => break,
        _ => break,
    }
}

// Access exports
let version = api::get_export(&interp, "VERSION");
assert_eq!(version.unwrap().as_str(), Some("1.0.0"));

let export_names = api::get_export_names(&interp);
assert!(export_names.contains(&"VERSION".to_string()));
assert!(export_names.contains(&"CONFIG".to_string()));

C API

Build with C API support:

bash
cargo build --release --features c-api

Context Lifecycle

c
#include "tsrun.h"

int main() {
    // Create context
    TsRunContext* ctx = tsrun_new();

    // Prepare and run code
    tsrun_prepare(ctx, "1 + 2 * 3", NULL);
    TsRunStepResult result = tsrun_run(ctx);

    if (result.status == TSRUN_STEP_COMPLETE) {
        printf("Result: %g\n", tsrun_get_number(result.value));
        tsrun_value_free(result.value);
    }

    // Cleanup
    tsrun_step_result_free(&result);
    tsrun_free(ctx);
    return 0;
}

Native Functions

Register C functions callable from JavaScript:

c
static TsRunValue* native_add(TsRunContext* ctx, TsRunValue* this_arg,
                              TsRunValue** args, size_t argc,
                              void* userdata, const char** error_out) {
    double a = tsrun_get_number(args[0]);
    double b = tsrun_get_number(args[1]);
    return tsrun_number(ctx, a + b);
}

int main() {
    TsRunContext* ctx = tsrun_new();

    // Register native function
    TsRunValueResult fn = tsrun_native_function(ctx, "add", native_add, 2, NULL);
    tsrun_set_global(ctx, "add", fn.value);

    // Use from JS
    tsrun_prepare(ctx, "add(10, 20)", NULL);
    TsRunStepResult result = tsrun_run(ctx);
    // result.value is 30.0

    tsrun_step_result_free(&result);
    tsrun_free(ctx);
    return 0;
}

Module Loading

c
TsRunStepResult result = tsrun_run(ctx);

while (result.status == TSRUN_STEP_NEED_IMPORTS) {
    for (size_t i = 0; i < result.import_count; i++) {
        const char* path = result.imports[i].resolved_path;
        const char* source = load_from_filesystem(path);
        tsrun_provide_module(ctx, path, source);
    }
    tsrun_step_result_free(&result);
    result = tsrun_run(ctx);
}

Creating Values

c
// Primitives
TsRunValue* num = tsrun_number(ctx, 42.0);
TsRunValue* str = tsrun_string(ctx, "hello");
TsRunValue* b = tsrun_boolean(ctx, true);
TsRunValue* null = tsrun_null(ctx);
TsRunValue* undef = tsrun_undefined(ctx);

// Objects
TsRunValue* obj = tsrun_object(ctx);
tsrun_set(ctx, obj, "name", tsrun_string(ctx, "Alice"));
tsrun_set(ctx, obj, "age", tsrun_number(ctx, 30));

// Arrays
TsRunValue* arr = tsrun_array(ctx, 3);
tsrun_set_index(ctx, arr, 0, tsrun_number(ctx, 1));
tsrun_set_index(ctx, arr, 1, tsrun_number(ctx, 2));
tsrun_set_index(ctx, arr, 2, tsrun_number(ctx, 3));

Key Functions

Function Description
tsrun_new() Create new interpreter context
tsrun_free(ctx) Free context and all associated memory
tsrun_prepare(ctx, code, path) Prepare code for execution
tsrun_run(ctx) Run until pause or completion
tsrun_provide_module(ctx, path, src) Provide module source
tsrun_native_function(...) Create native function
tsrun_set_global(ctx, name, val) Set global variable
tsrun_get(ctx, obj, key) Get object property
tsrun_set(ctx, obj, key, val) Set object property
tsrun_value_free(val) Free a value