webloom-framework 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -43
- package/dist/advanced.d.ts +168 -0
- package/dist/advanced.js +441 -0
- package/dist/advanced.js.map +1 -0
- package/dist/chunk-4DSINPZD.js +158 -0
- package/dist/chunk-4DSINPZD.js.map +1 -0
- package/dist/chunk-JHJZIO2H.js +4018 -0
- package/dist/chunk-JHJZIO2H.js.map +1 -0
- package/dist/chunk-RAQOFUZY.js +1737 -0
- package/dist/chunk-RAQOFUZY.js.map +1 -0
- package/dist/chunk-YOIH6H36.js +433 -0
- package/dist/chunk-YOIH6H36.js.map +1 -0
- package/dist/index.d.ts +38 -443
- package/dist/index.js +38 -1967
- package/dist/index.js.map +1 -1
- package/dist/messageBus-CtrwkjrO.d.ts +5 -0
- package/dist/messagePortServiceTransport-B0FyJr43.d.ts +264 -0
- package/dist/react.d.ts +41 -28
- package/dist/react.js +79 -88
- package/dist/react.js.map +1 -1
- package/dist/runtimeTypes-DquUCHz-.d.ts +1640 -0
- package/dist/sharedWorkerHost-Cb2a1_KD.d.ts +190 -0
- package/dist/testing.d.ts +18 -17
- package/dist/testing.js +23 -15
- package/dist/testing.js.map +1 -1
- package/dist/windowRuntime-B6Ue8jso.d.ts +23 -0
- package/docs/api.md +149 -111
- package/docs/migration-baseline.md +2 -2
- package/docs/proposals/browser-runtime-v1/implementation-plan.md +7 -1
- package/docs/proposals/browser-runtime-v1/requirements.md +6 -1
- package/docs/proposals/browser-runtime-v1/verification.md +20 -13
- package/docs/proposals/shared-worker-call-first/SWCF-009-typed-transfer-follow-up.md +34 -0
- package/docs/proposals/shared-worker-call-first/implementation-plan.md +567 -0
- package/docs/proposals/webloom-v4/implementation-plan.md +443 -0
- package/docs/proposals/webloom-v4/requirements.md +555 -0
- package/docs/proposals/webloom-v4/verification.md +84 -0
- package/package.json +9 -2
- package/dist/chunk-URY3E6UH.js +0 -3802
- package/dist/chunk-URY3E6UH.js.map +0 -1
- package/dist/createPluginHost-ChJNBTsX.d.ts +0 -1339
- package/dist/resourceRegistry-MNM1c7od.d.ts +0 -157
package/docs/api.md
CHANGED
|
@@ -1,27 +1,31 @@
|
|
|
1
|
-
# WebLoom API 说明
|
|
1
|
+
# WebLoom v4 API 说明
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
WebLoom 0.4.0 只支持两个真实 JavaScript realm:`window-main` 和
|
|
4
|
+
`shared-worker`。`runtime` 是受限的 `RuntimeKind`,不是可自由填写的环境标签;不支持
|
|
5
|
+
的 Runtime 在装配边界 fail closed。
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
`
|
|
7
|
-
|
|
8
|
-
其它服务端 PluginHost。
|
|
7
|
+
一次 Runtime 启动生成不可复用的 `runtimeInstanceId`。每个插件运行单元启动生成不可
|
|
8
|
+
复用的 `instanceId`。同一个 SharedWorker 接收多个 Window 连接时,Worker 单元仍只有
|
|
9
|
+
一个实例;每条物理端口拥有独立的 peer、调用、订阅和 exposure。
|
|
9
10
|
|
|
10
|
-
|
|
11
|
-
会生成不可复用的 `unitInstanceId`(在 Host 的兼容状态接口中表现为
|
|
12
|
-
`instanceId`)。同一 SharedWorker 接收多个 Window 连接时,Worker 单元仍只有
|
|
13
|
-
一个实例;每条端口连接拥有独立的 `connectionId`、请求和取消空间。
|
|
11
|
+
## capability 与普通插件
|
|
14
12
|
|
|
15
|
-
|
|
13
|
+
Capability 对象是契约、类型和运行时校验的唯一入口。跨 realm 只发送不含函数的
|
|
14
|
+
`{ kind, id, version }` descriptor;parser、transfer extractor 和 handler 留在各自
|
|
15
|
+
realm。
|
|
16
16
|
|
|
17
17
|
```ts
|
|
18
|
-
import { createWindowApp, definePlugin } from "webloom-framework";
|
|
18
|
+
import { createWindowApp, defineCapability, definePlugin } from "webloom-framework";
|
|
19
|
+
|
|
20
|
+
const Hello = defineCapability<{ value: string }>({
|
|
21
|
+
kind: "local", id: "hello.service", version: "1",
|
|
22
|
+
});
|
|
19
23
|
|
|
20
24
|
const hello = definePlugin({
|
|
21
25
|
id: "hello",
|
|
22
|
-
provides: [
|
|
26
|
+
provides: [Hello] as const,
|
|
23
27
|
setup(ctx) {
|
|
24
|
-
ctx.provide(
|
|
28
|
+
ctx.provide(Hello, { value: "world" });
|
|
25
29
|
ctx.onDispose(() => {
|
|
26
30
|
// 释放本插件登记的资源。
|
|
27
31
|
});
|
|
@@ -29,143 +33,177 @@ const hello = definePlugin({
|
|
|
29
33
|
});
|
|
30
34
|
|
|
31
35
|
const app = await createWindowApp({ plugins: [hello] });
|
|
32
|
-
const service = app.capability
|
|
36
|
+
const service = app.capability(Hello);
|
|
33
37
|
```
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
静态 descriptor 可用于验证和快照,不携带函数。`createWindowApp()` 自动固定
|
|
37
|
-
`window-main`、生成实例身份、创建内部 Implementation Registry、批量注册并
|
|
38
|
-
等待初始启动;使用者不需要手工 `register()`。
|
|
39
|
+
local capability 不能跨 Runtime;RPC/stream capability 必须提供生产 `ValueParser`:
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
41
|
+
```ts
|
|
42
|
+
const ReadProfile = defineCapability({
|
|
43
|
+
kind: "rpc",
|
|
44
|
+
id: "profile.read",
|
|
45
|
+
version: "1",
|
|
46
|
+
request: profileRequestParser,
|
|
47
|
+
response: profileResponseParser,
|
|
48
|
+
});
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
const Changes = defineCapability({
|
|
51
|
+
kind: "stream",
|
|
52
|
+
id: "profile.changes",
|
|
53
|
+
version: "1",
|
|
54
|
+
request: profileWatchParser,
|
|
55
|
+
item: profileChangeParser,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const profile = definePlugin({
|
|
59
|
+
id: "profile",
|
|
60
|
+
provides: [ReadProfile, Changes] as const,
|
|
61
|
+
setup(ctx) {
|
|
62
|
+
ctx.handle(ReadProfile, (request, call) => loadProfile(request.userId, call.signal));
|
|
63
|
+
ctx.handle(Changes, (request, call) => observeProfiles(request, call.signal));
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`ctx.provide(C, value)` 只注册声明的 local;`ctx.handle(C, handler)` 只注册声明的
|
|
69
|
+
RPC/stream。`ctx.capability(C)` 和 `ctx.optionalCapability(C)` 的参数、返回值由 C
|
|
70
|
+
推导,调用者不再手写请求/结果泛型,也不能临时传入 transfer 数组。
|
|
71
|
+
|
|
72
|
+
## SharedWorker 与双向 peer
|
|
45
73
|
|
|
46
74
|
Worker 入口:
|
|
47
75
|
|
|
48
76
|
```ts
|
|
49
77
|
import { definePlugin, startSharedWorkerApp } from "webloom-framework";
|
|
78
|
+
import { Health } from "./contracts";
|
|
50
79
|
|
|
51
|
-
const
|
|
52
|
-
id: "
|
|
53
|
-
provides: [
|
|
80
|
+
const coordinator = definePlugin({
|
|
81
|
+
id: "coordinator",
|
|
82
|
+
provides: [Health] as const,
|
|
54
83
|
setup(ctx) {
|
|
55
|
-
ctx.
|
|
56
|
-
handle(request: { key: string }) {
|
|
57
|
-
return { key: request.key };
|
|
58
|
-
},
|
|
59
|
-
});
|
|
84
|
+
ctx.handle(Health, (request) => ({ type: request.type, instanceId: ctx.instanceId }));
|
|
60
85
|
},
|
|
61
86
|
});
|
|
62
87
|
|
|
63
|
-
startSharedWorkerApp({ id: "coordinator", plugins: [
|
|
88
|
+
startSharedWorkerApp({ id: "coordinator", plugins: [coordinator], expose: [Health] });
|
|
64
89
|
```
|
|
65
90
|
|
|
66
|
-
Window
|
|
91
|
+
Window 侧把 Bundler 生成的 JavaScript Worker URL 传给连接器:
|
|
67
92
|
|
|
68
93
|
```ts
|
|
69
|
-
|
|
70
|
-
import coordinatorWorkerUrl from "./coordinator.worker.ts?sharedworker&url";
|
|
94
|
+
import workerUrl from "./coordinator.worker.ts?sharedworker&url";
|
|
71
95
|
import { connectSharedWorker } from "webloom-framework";
|
|
96
|
+
import { Health } from "./contracts";
|
|
72
97
|
|
|
73
|
-
const runtime =
|
|
98
|
+
const runtime = connectSharedWorker({ id: "coordinator", url: workerUrl });
|
|
99
|
+
const result = await runtime.capability(Health).call({ type: "health" });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
`connectSharedWorker()` 同步返回 `RuntimeHandle`。远程 capability 的 proxy 构造不等待
|
|
103
|
+
Worker;第一次 call/subscribe 在一个有限 deadline 内等待精确的 Runtime、contract 和
|
|
104
|
+
service exposure。断线、协议不兼容、超时和撤销都返回结构化错误;框架不自动重连或重放。
|
|
105
|
+
|
|
106
|
+
页面反向能力必须先存在于 WindowApp:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const page = await createWindowApp({ plugins: [pageIoPlugin] });
|
|
110
|
+
const runtime = connectSharedWorker({
|
|
74
111
|
id: "coordinator",
|
|
75
|
-
url:
|
|
112
|
+
url: workerUrl,
|
|
113
|
+
client: { app: page, expose: [LocalStorageIo] },
|
|
76
114
|
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Worker 的 handler 通过 `call.peer.capability(LocalStorageIo)` 得到当前端口对应页面的
|
|
118
|
+
typed client。`PeerController` 只在可信 `configurePeer` 回调中出现,不暴露原始 port、Worker 或发送函数;`peer.expose(C, options)`
|
|
119
|
+
只允许暴露本 Host 已注册的 RPC/stream,并在 provider scope、peer scope 和领域 scope
|
|
120
|
+
任一撤销时同步移除。授权更新必须 revoke 旧 exposure 后新建,旧 proxy 永不换绑。
|
|
121
|
+
|
|
122
|
+
如果页面需要在已有 Host 上分阶段增加远程依赖,从 `/advanced` 使用:
|
|
77
123
|
|
|
78
|
-
|
|
79
|
-
|
|
124
|
+
```ts
|
|
125
|
+
import { attachRemote, registerPlugins } from "webloom-framework/advanced";
|
|
126
|
+
|
|
127
|
+
const detach = await attachRemote(page, runtime);
|
|
128
|
+
await registerPlugins(page, [remoteConsumerPlugin]);
|
|
129
|
+
// 结束页面生命周期时:detach(); await page.dispose();
|
|
80
130
|
```
|
|
81
131
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Worker 重启或 Provider 实例变化都会同步撤销旧代理。重连只建立新连接和新代理,
|
|
85
|
-
不会重放可能产生外部副作用的调用,也不会静默替换旧代理的绑定。
|
|
132
|
+
普通 `createWindowApp()` 不接受 Host 或测试 scope 注入,也不会根据 Worker manifest 创建
|
|
133
|
+
第二套 Window 单元。
|
|
86
134
|
|
|
87
|
-
|
|
88
|
-
`?sharedworker&url` 或等价的独立 Rollup entry;不要把
|
|
89
|
-
`new URL("./coordinator.worker.ts", import.meta.url)` 作为普通参数传入框架,
|
|
90
|
-
因为框架内部的 `new SharedWorker()` 不会让 Vite 重新发现调用方源码入口。
|
|
135
|
+
## wire、快照与错误
|
|
91
136
|
|
|
92
|
-
`
|
|
137
|
+
唯一 Runtime wire 是 `webloom.runtime.v1`,消息为 snapshot、runtime-error、call、result、
|
|
138
|
+
error、cancel、next、credit。快照只有 ready 状态发布当前可调用 services;每条 peer 有
|
|
139
|
+
独立严格递增 revision。旧协议被明确拒绝,不尝试降级解析。
|
|
93
140
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
| `subscribe()` | 观察 Runtime/Unit/服务快照 |
|
|
103
|
-
| `dispose()` | 同步撤销本句柄,异步关闭连接资源 |
|
|
141
|
+
框架错误通过 `WebLoomError` 暴露,至少覆盖 `protocol_mismatch`、`invalid_snapshot`、
|
|
142
|
+
`capability_unavailable`、`contract_mismatch`、`request_validation_failed`、
|
|
143
|
+
`response_validation_failed`、`request_clone_failed`、`response_clone_failed`、
|
|
144
|
+
`transfer_invalid`、`handler_failed`、`call_timeout`、`request_cancelled`、
|
|
145
|
+
`service_revoked`、`service_stale`、`transport_unavailable`、
|
|
146
|
+
`runtime_initialization_failed` 和 `stream_overflow`。错误只带脱敏 message/details,
|
|
147
|
+
不回显 request、密钥、口令、凭据或授权 headers;发送请求后的超时不推断远端副作用一定
|
|
148
|
+
未发生。
|
|
104
149
|
|
|
105
|
-
|
|
150
|
+
## transfer 与 stream
|
|
106
151
|
|
|
107
|
-
|
|
108
|
-
|
|
152
|
+
RPC 契约可声明 `transfer.request(value)`、`transfer.response(value)`,stream 契约可声明
|
|
153
|
+
`transfer.item(value)`。顺序固定为 parser → extractor/去重/可达性校验 → `postMessage`;
|
|
154
|
+
接收端再次 parser。多个 TypedArray 视图共享同一个 backing buffer 时,转移其中一个会
|
|
155
|
+
转移整个 buffer 的所有权。发送后取消不恢复所有权,也不会自动重传;迟到结果不交付给
|
|
156
|
+
旧 proxy。
|
|
157
|
+
|
|
158
|
+
Stream handler 返回 `AsyncIterable`,订阅返回 `ready`、`closed` 和幂等 `cancel()`:
|
|
109
159
|
|
|
110
160
|
```ts
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
contractVersion: "coordinator.service.v1",
|
|
118
|
-
sourceRuntime: "shared-worker",
|
|
119
|
-
}],
|
|
120
|
-
async setup(ctx) {
|
|
121
|
-
const coordinator = ctx.serviceBridge?.requireProxy({
|
|
122
|
-
capabilityId: "coordinator.service",
|
|
123
|
-
contractVersion: "coordinator.service.v1",
|
|
124
|
-
runtime: "shared-worker",
|
|
125
|
-
}, ctx.scope);
|
|
126
|
-
ctx.provide("window.coordinator", await coordinator.call({ type: "health" }));
|
|
127
|
-
},
|
|
128
|
-
})],
|
|
129
|
-
});
|
|
161
|
+
const sub = runtime.capability(Changes).subscribe(
|
|
162
|
+
{ userId: "123" },
|
|
163
|
+
{ onNext: renderChange, timeoutMs: 5_000 },
|
|
164
|
+
);
|
|
165
|
+
await sub.ready;
|
|
166
|
+
await sub.closed;
|
|
130
167
|
```
|
|
131
168
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
169
|
+
默认 credit 为 16,窗口范围为 1–256;没有 credit 时 producer 不拉取 iterator,item
|
|
170
|
+
交付完成后才补回 credit。sequence 从 1 连续递增;错序、重复、非法 credit、消费者
|
|
171
|
+
回调失败和撤销都会终止当前订阅,不影响其它 peer。长流没有自动心跳或持久重放保证。
|
|
135
172
|
|
|
136
|
-
##
|
|
173
|
+
## Scope、诊断与 React
|
|
137
174
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
ownership 和 cleanup callbacks;这个 Scope 不再从用户声明的生命周期分类推导。
|
|
175
|
+
`scope.listen()`、`scope.interval()`、`scope.subscribe()` 都返回幂等 release,并在同步
|
|
176
|
+
revoke 时解除资源;它们复用同一个 Scope resource ledger。异步创建使用 `scope.acquire()`,
|
|
177
|
+
晚到资源仍会在 Scope 已撤销后尽力释放。
|
|
142
178
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
`LifecycleDisposeResult` 暴露。
|
|
179
|
+
App/Handle 提供不可变 `state()`、`inspect()`、`subscribe()`。inspect 只报告 Runtime、
|
|
180
|
+
插件/单元、scope、peer 和 framework-owned pending/stream 计数;`explain()` 返回稳定的
|
|
181
|
+
缺 provider、契约不匹配、依赖阻塞、scope 撤销和初始化失败原因,不包含业务载荷。
|
|
147
182
|
|
|
148
|
-
|
|
149
|
-
fence)不属于 WebLoom Runtime 生命周期。应用自己的 Coordinator/服务控制器
|
|
150
|
-
负责推进领域状态,再通过新的服务快照让旧代理失效。
|
|
183
|
+
React 在 `/react`:
|
|
151
184
|
|
|
152
|
-
|
|
185
|
+
```tsx
|
|
186
|
+
import { WebLoomProvider, useCapability, usePluginState } from "webloom-framework/react";
|
|
187
|
+
|
|
188
|
+
function Panel() {
|
|
189
|
+
const health = useCapability(Health);
|
|
190
|
+
const plugin = usePluginState("coordinator");
|
|
191
|
+
return <output>{plugin?.lifecycleState ?? health ? "ready" : "waiting"}</output>;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
<WebLoomProvider app={runtime}><Panel /></WebLoomProvider>;
|
|
195
|
+
```
|
|
153
196
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
`defineRuntimeUnitProvidedContracts()` 生成默认 v1 版本;框架不会根据 capability
|
|
157
|
-
名称猜测远端服务。`providedContracts`、Provider 实例身份、Runtime 启动身份和
|
|
158
|
-
快照 revision 都参与代理绑定。
|
|
197
|
+
Provider 保存稳定 App 引用,hooks 使用外部 store 一致性机制;capability、plugin 和
|
|
198
|
+
selector 按相关状态订阅,不把每次全局版本变化广播给所有消费者。
|
|
159
199
|
|
|
160
|
-
##
|
|
200
|
+
## 入口边界
|
|
161
201
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
202
|
+
- 主入口:capability、插件、三个 Runtime 构造函数、App/Handle、契约/错误/Scope;不加载 React 或底层 transport。
|
|
203
|
+
- `/advanced`:Host/graph/registry、peer exposure、strict v4 bridge/provider 和分阶段装配。
|
|
204
|
+
- `/react`:WebLoomProvider、typed capability/plugin/resource hooks。
|
|
205
|
+
- `/testing`:生产 parser 驱动的 fake transport、可控 Worker/Scope harness。
|
|
166
206
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
仓库提供 `scripts/browser-runtime-fixture/` 与 `pnpm run test:browser`;缺少
|
|
171
|
-
Playwright/Chromium 时脚本明确报告 unsupported,不回退为 Node 或同页面模拟。
|
|
207
|
+
真实浏览器验收必须使用 Bundler 产出的 SharedWorker chunk 和 Chromium;Node
|
|
208
|
+
MessageChannel 单测只证明 transport simulation,不替代 Window/SharedWorker realm、多个
|
|
209
|
+
页面、transfer ownership 或 Worker 退出验收。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
| WebLoom 起始提交 | `f1c801655c3132c57b66045ff6d5e642fba4a8ea` |
|
|
9
9
|
| Node | `v22.13.1` |
|
|
10
10
|
| pnpm | `11.5.1` |
|
|
11
|
-
| 下一发布包版本 | `0.
|
|
11
|
+
| 下一发布包版本 | `0.3.0` |
|
|
12
12
|
| npm 包名 | `webloom-framework` |
|
|
13
13
|
| 发布来源提交 | `a5ace48` |
|
|
14
14
|
| 已发布基线标签 | `v0.1.0` |
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
## 当前工作区发布状态
|
|
22
22
|
|
|
23
|
-
当前工作区正在准备 `webloom-framework@0.
|
|
23
|
+
当前工作区正在准备 `webloom-framework@0.3.0`,但该版本尚未发布到 npm;下游在发布
|
|
24
24
|
责任人完成正式发布前继续使用本地工作区依赖。`v0.1.0` / npm `0.1.0` 是已发布基线,
|
|
25
25
|
不是本轮未发布代码的验收替代品。
|
|
26
26
|
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
# WebLoom 浏览器双运行时施工单
|
|
2
2
|
|
|
3
|
+
> SharedWorker 的 `hello`、RemoteService `handshake`、`baseline/resync`、握手超时和
|
|
4
|
+
> 自动重连要求,已被[SharedWorker call-first 消融施工单](../shared-worker-call-first/implementation-plan.md)
|
|
5
|
+
> 覆盖。其余 Runtime、PluginHost、生命周期和安全边界继续有效。
|
|
6
|
+
|
|
3
7
|
## 1. 施工目标
|
|
4
8
|
|
|
5
9
|
把 WebLoom 从字符串运行标签和手工初始化装配,升级为真实的 `window-main + shared-worker` 浏览器双运行时;删除无执行语义的 `lifetime` 与插件分类 `kind`;用高层 API 封装 SharedWorker、MessagePort 和远程 capability。
|
|
6
10
|
|
|
7
|
-
需求基线见[浏览器双运行时迭代需求](./requirements.md)
|
|
11
|
+
需求基线见[浏览器双运行时迭代需求](./requirements.md)。本施工单保留基础双运行时的
|
|
12
|
+
历史实施顺序;SharedWorker 连接相关条款已由上方 call-first 施工单取代,不再作为
|
|
13
|
+
当前 hello/handshake/baseline/reconnect 行为的真值。
|
|
8
14
|
|
|
9
15
|
## 2. 施工边界
|
|
10
16
|
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
# WebLoom 浏览器双运行时迭代需求
|
|
2
2
|
|
|
3
|
+
> SharedWorker 连接协议现已采用 call-first 方向。本文涉及 `hello`、握手、baseline、
|
|
4
|
+
> resync、`ready()` 和自动重连的条款,由
|
|
5
|
+
> [SharedWorker call-first 消融施工单](../shared-worker-call-first/implementation-plan.md)
|
|
6
|
+
> 覆盖;其他产品目标和安全要求不变。
|
|
7
|
+
|
|
3
8
|
## 1. 文档信息
|
|
4
9
|
|
|
5
10
|
- 项目:WebLoom
|
|
6
11
|
- 迭代:浏览器双运行时 v1
|
|
7
|
-
-
|
|
12
|
+
- 状态:基础 Runtime 已实施;SharedWorker 连接部分由 call-first 施工单收口
|
|
8
13
|
- 文档性质:破坏性简化迭代;不代表当前代码已经具备本文能力
|
|
9
14
|
- 关联施工单:[浏览器双运行时施工单](./implementation-plan.md)
|
|
10
15
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 浏览器双运行时验证记录
|
|
2
2
|
|
|
3
3
|
更新时间:2026-09-09
|
|
4
4
|
|
|
5
5
|
## 当前已通过
|
|
6
6
|
|
|
7
|
-
- WebLoom TypeScript typecheck:通过。
|
|
8
|
-
- Vitest:
|
|
7
|
+
- WebLoom 0.3.0 TypeScript typecheck:通过。
|
|
8
|
+
- Vitest:16 个测试文件、107 个测试通过;SharedWorker 的 Node 部分明确使用
|
|
9
9
|
`MessageChannel` transport simulation。
|
|
10
10
|
- `pnpm lint:boundaries`:通过。
|
|
11
11
|
- `pnpm build`:通过。
|
|
@@ -14,19 +14,22 @@
|
|
|
14
14
|
- `git diff --check`:通过。
|
|
15
15
|
|
|
16
16
|
本轮还覆盖了 Window Host 的 `remoteRuntime` 投影、跨 Runtime 精确契约依赖、
|
|
17
|
-
断线后 blocked/
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
断线后 blocked/reconcile、required 元数据防降级、显式 `unitId` 投影、
|
|
18
|
+
惰性 call deadline、SharedWorker 错误连接收敛、stopping/disposed 后拒绝新连接,
|
|
19
|
+
以及 dispose 后旧代理永久失效。
|
|
20
20
|
|
|
21
21
|
## 真实浏览器证据
|
|
22
22
|
|
|
23
23
|
仓库新增 `scripts/browser-runtime-fixture/` 和 `pnpm run test:browser`。fixture
|
|
24
24
|
先由 Vite 生产构建,再从临时 dist preview 启动真实 HTML Window、module
|
|
25
25
|
SharedWorker 和两个页面,断言 Window/Worker realm marker、Worker setup 只执行
|
|
26
|
-
一次、共享 Worker
|
|
27
|
-
|
|
26
|
+
一次、共享 Worker/runtime/service 实例身份;同时覆盖显式 dispose 后重建新句柄和新
|
|
27
|
+
代理、旧代理失效、协议版本不兼容和构建后 Worker URL。
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
当前执行结果:通过;最终 fixture 连续 10/10 次通过。terminal 场景先等待触发页和观察页
|
|
30
|
+
都报告 connected、ready、subscription installed,再触发 shutdown;两端均收到
|
|
31
|
+
`ready → stopping → disposed`。另有末态后连接页面收到 `starting → disposed`,不补发
|
|
32
|
+
历史 `stopping`。仓库声明 Playwright 1.63.0,已安装 Chromium;runner 会在
|
|
30
33
|
每次验收前执行 `playwright install chromium`,缺少浏览器时仍 fail closed 为
|
|
31
34
|
`unsupported`/退出码 2,不回退为 Node 或同页面 MessageChannel。
|
|
32
35
|
|
|
@@ -43,7 +46,11 @@ SharedWorker 和两个页面,断言 Window/Worker realm marker、Worker setup
|
|
|
43
46
|
client 通过 `connectSharedWorker()` 复用同一物理端口,保留原有 Coordinator RPC、
|
|
44
47
|
私钥隔离、session epoch、owner fence、final-I/O lease 和 localStorage bridge。
|
|
45
48
|
Keymaster typecheck、production build 以及 215-file Vitest batch 已通过。
|
|
46
|
-
- `webloom-framework@0.
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
- `webloom-framework@0.3.0` 仍是待发布工作区版本;npm registry 当前没有该版本,
|
|
50
|
+
下游使用本地 tarball 完成消费者验证,release-boundary 已切换为精确 `0.3.0`。
|
|
51
|
+
Keymaster 的 release-boundary 现在还会动态查询 registry 的精确版本、tarball
|
|
52
|
+
integrity,并与 frozen lockfile 比对;当前门禁因 registry 404 失败。因此“npm
|
|
53
|
+
0.3.0 发布后重新安装并验收”尚未完成。Keymaster 另有
|
|
54
|
+
`pnpm verify:webloom-registry`,会在全新临时目录生成 lockfile、执行 registry-only
|
|
55
|
+
`npm ci` 并导入三个公共入口;当前同样因 404 fail closed。没有在本轮伪造 registry
|
|
56
|
+
版本或自动发布。
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# SWCF-009 typed capability/transfer 后续施工单
|
|
2
|
+
|
|
3
|
+
## 状态与版本边界
|
|
4
|
+
|
|
5
|
+
本施工单从 `webloom-framework@0.3.0` 的 call-first 迁移中正式拆出,目标后续
|
|
6
|
+
版本(暂定 `0.4.0`)。因此 0.3.0 保留 `connectSharedWorker()` 的
|
|
7
|
+
`onConnection` 和 `startSharedWorkerApp()` 的 `onPortConnect` 作为 Keymaster
|
|
8
|
+
迁移接缝,但不得把这两个接缝描述成最终公共架构。
|
|
9
|
+
|
|
10
|
+
0.3.0 的已完成范围是 Runtime v2、惰性 ServiceBridge、call/result/error/cancel
|
|
11
|
+
传输、完整快照、Provider/revocation fence、Demo 和 Keymaster 的 v2 service wire。
|
|
12
|
+
0.3.0 不宣称 SWCF-009 或 npm registry 发布完成。
|
|
13
|
+
|
|
14
|
+
## 后续不变量
|
|
15
|
+
|
|
16
|
+
- capability method 必须声明 request transferables 和 result transferables;未声明的
|
|
17
|
+
capability 只能走 structured clone。
|
|
18
|
+
- transfer list 由 capability 适配器产生,调用方不得取得裸 Runtime `MessagePort`,也
|
|
19
|
+
不得用 `any` 或全局消息监听绕过 capability 边界。
|
|
20
|
+
- request/result 的 transferable 所有权、取消、deadline、dispose、Worker 重启和
|
|
21
|
+
late-result fence 都必须有类型级和真实浏览器测试。
|
|
22
|
+
- Keymaster Coordinator 的主请求、事件和 Local `localStorage` page bridge 必须迁入
|
|
23
|
+
typed API;owner/session/grant/handover/final-I/O fence 与 `UpgradeGate.handshake`
|
|
24
|
+
必须保持原顺序和语义。
|
|
25
|
+
|
|
26
|
+
## 收口门禁
|
|
27
|
+
|
|
28
|
+
1. 先实现并导出 typed request/result transfer descriptor 和测试入口。
|
|
29
|
+
2. 迁移 Keymaster Coordinator 的所有主 RPC、事件及 transferable 操作;保留领域
|
|
30
|
+
`connectionId` 仅在其自身协议中使用。
|
|
31
|
+
3. 通过真实浏览器双 Tab、断线/重启、lock/unlock、A → B → A、Local bridge、迟到
|
|
32
|
+
result 和安全 fence 回归。
|
|
33
|
+
4. 从生产入口删除 `onConnection`、`onPortConnect`;把 worker factory 保持在 testing
|
|
34
|
+
入口,并重新执行三仓 typecheck、build、pack/registry consumer 和发布验收。
|