Runtime and bundle

Runtime and bundle

Both are auto-imported under their prefix.

bundle

Compile-time project metadata, filled in from the manifest during a build.

Value Meaning
bundle::name the display name
bundle::identifier the reverse-DNS bundle id
bundle::version the project version
bundle::app_id the platform app id, when linked
bundle::host <slug>.serve.pekoui.com, empty until deployed
bundle::framework native, static, server, or cli
bundle::scheme the custom URL scheme, when declared
bundle::window "WIDTHxHEIGHT", when both are set
bundle::debug true for a debug build

Every one is a plain value with a declared default, so a build outside a project leaves them empty rather than failing. Code that reads them should handle the empty case:

let window: string = bundle::window
if window.contains("x") {
    // parse it
}

runtime

The boundary with the garbage collector. Most application code needs one function from it.

[public] fn create_managed(raw: cstr) => string

create_managed copies raw C bytes into a fresh managed string, which is what you want when a C function hands back a char*:

[public] fn get(name: string) => string {
    return runtime::create_managed(c_env::peko_env(name.to_raw()))
}

Its counterpart managed_string(buffer) wraps a buffer that is already managed, taking ownership rather than copying. Using the wrong one either leaks or produces a use-after-move.

The module also exposes allocate<T>(count) for managed buffers, the scalar conversion helpers, and the collector lifecycle calls (init, shutdown, attach_thread, detach_thread). The lifecycle calls are made by the generated program entry; application code should not call them.

The GC ABI is declared in one header and nowhere else. Redeclaring it produces duplicate symbols and undefined behavior. The low-level guide covers this.