Skip to content

桥接机制 (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_bytes16 KiB最大请求消息大小
max_response_bytes16 KiB最大响应消息大小
max_result_bytes12 KiB处理函数返回结果的最大大小
max_id_bytes64请求 ID 最大字节数
max_command_bytes128命令名称最大字节数

错误代码

当桥接调用失败时,JS 的 Promise 会被拒绝,并返回一个包含 code 字段的错误:

错误码原因
invalid_requestJSON 格式错误
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.* 的内置命令。