运行时生命周期
每个 qzjs 程序都遵循相同的生命周期:创建 → 使用 → 销毁。
创建运行时
c
qz_config_t config = {
.initial_script = "postMessage('ready');", // 在创建时于 qzjs 线程上求值
.message_cb = on_message, // 出站消息
.debug = 0, // 启用调试输出(0 或 1)
};
qz_t *rt = qz_create(&config);
if (!rt) {
// 创建失败 — initial_script 抛出异常,或线程/循环初始化失败
}qz_create 执行以下操作:
- 启动 qzjs 的内部线程并初始化嵌入式 libuv 循环
- 创建 JSRuntime 和初始上下文
- 注册构建时扩展集(
QZ_EXTENSIONS表 — 内置扩展如 compress/crypto/textcodec/wamr,当其QZ_WITH_*选项开启时生效, 以及通过QZ_EXTRA_SOURCES添加的任何用户扩展) - 将 WinterTC 兼容的运行时注入到初始上下文中
- 在内部线程上求值
initial_script— 抛出异常会使qz_create返回NULL
qz_create 会阻塞,直到内部线程就绪且 initial_script 已求值。运行时拥有其全部资源。
销毁运行时
c
qz_destroy(rt); // 优雅关闭,仅宿主线程,NULL 安全qz_destroy 会:
- 请求内部线程退出并 join 它
- 销毁所有上下文(调用扩展的
destroy钩子) - 释放 JSRuntime 和嵌入式 libuv 循环
- 释放运行时
qz_destroy(NULL) 是安全的(无操作)。
线程安全
- 所有 JS 在 qzjs 的内部线程上运行 — 宿主线程从不调用 JS
qz_post_message是线程安全的 — 可从任何线程调用;JSON 会被拷贝message_cb在 qzjs 线程上触发 — 你的回调必须线程安全qz_destroy仅限宿主线程 — 从调用qz_create的线程调用
内存模型
- 所有每运行时状态存储在
qz_t上 — 零可变文件作用域状态 - 类 ID 是运行时作用域的(在一个
qz_t内的各上下文之间共享) - 通过
qz_get_rt_from_ctx(ctx)(内部 API)从JSContext*恢复qz_t*