桥接机制 (Bridge)
桥接机制通过 JSON 消息将 WebView 中的 JavaScript 与原生的 Zig 处理函数(Handlers)连接起来。
架构设计 (Architecture)
WebView JS Zig Runtime
────────── ───────────
window.zero.invoke(cmd, payload)
│ │
├──── JSON message ───────────►│
│ 大小检查 (最大 16 KiB)
│ 策略检查 (源与权限)
│ 处理函数查找并执行
│◄─── JSON 响应 ───────────────┤定义处理函数 (Defining a Handler)
zig
fn ping(context: *anyopaque, invocation: zero_native.bridge.Invocation, output: []u8) anyerror![]const u8 {
_ = invocation;
const self: *App = @ptrCast(@alignCast(context));
self.ping_count += 1;
return std.fmt.bufPrint(output, "{{\"message\":\"pong\",\"count\":{d}}}", .{self.ping_count});
}处理函数会将 JSON 结果写入提供的输出缓冲区(最大 12 KiB)并返回其切片。返回的结果必须是有效的 JSON 值;如果返回无效的原始文本,将会以 handler_failed 错误被拒绝。在返回用户提供的数据作为字符串时,请使用桥接辅助函数以对引号和控制字符进行转义:
zig
return zero_native.bridge.writeJsonStringValue(output, user_supplied_name);接入分发器 (Wiring the Dispatcher)
zig
fn bridge(self: *App) zero_native.BridgeDispatcher {
self.handlers = .{.{ .name = "native.ping", .context = self, .invoke_fn = ping }};
return .{
.policy = .{ .enabled = true, .commands = &policies },
.registry = .{ .handlers = &self.handlers },
};
}在 JavaScript 中调用
javascript
const result = await window.zero.invoke("native.ping", { source: "webview" });
console.log(result); // { message: "pong from Zig", count: 1 }调用对象 (Invocation)
当处理函数被调用时,它会收到一个包含以下信息的 Invocation 对象:
request.id— 调用方提供的请求 ID(最大 64 字节)request.command— 命令名称(最大 128 字节,不能包含/或空格)request.payload— JSON 载荷字符串source.origin— 发起请求页面的源(例如zero://app)source.window_id— 发送该请求的窗口 ID
大小限制
| 常量 | 值 | 描述 |
|---|---|---|
max_message_bytes | 16 KiB | 最大请求消息大小 |
max_response_bytes | 16 KiB | 最大响应消息大小 |
max_result_bytes | 12 KiB | 处理函数返回结果的最大大小 |
max_id_bytes | 64 | 请求 ID 最大字节数 |
max_command_bytes | 128 | 命令名称最大字节数 |
错误代码
当桥接调用失败时,JS 的 Promise 会被拒绝,并返回一个包含 code 字段的错误:
| 错误码 | 原因 |
|---|---|
invalid_request | JSON 格式错误 |
unknown_command | 未注册该命令的处理函数 |
permission_denied | 源(Origin)或权限校验失败 |
handler_failed | 处理函数内部返回了错误 |
payload_too_large | 消息大小超过 16 KiB |
internal_error | 未预期的运行时错误 |
javascript
try {
const result = await window.zero.invoke("native.ping", {});
} catch (error) {
console.error(error.code, error.message);
}桥接类型
| 类型 | 描述 |
|---|---|
BridgeDispatcher | 融合了策略(Policy)与注册表(Registry) |
BridgePolicy | 是否启用桥接以及允许调用哪些指令的策略 |
BridgeCommandPolicy | 单条指令级的策略:名称、所需权限、允许的源(Origins) |
BridgeRegistry | 将指令名称映射到对应的处理函数 |
BridgeHandler | 包含名称、上下文指针以及函数入口 invoke_fn |
另请参见:适用于 zero-native.window.*、zero-native.webview.* 以及 zero-native.dialog.* 的内置命令。