webloom-framework 0.4.0 → 0.4.2
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 +1 -1
- package/dist/advanced.d.ts +20 -8
- package/dist/advanced.js +4 -4
- package/dist/advanced.js.map +1 -1
- package/dist/{chunk-JHJZIO2H.js → chunk-CKML74MG.js} +25 -4
- package/dist/chunk-CKML74MG.js.map +1 -0
- package/dist/{chunk-YOIH6H36.js → chunk-RRNUE457.js} +112 -32
- package/dist/chunk-RRNUE457.js.map +1 -0
- package/dist/{chunk-RAQOFUZY.js → chunk-XVD7ALPV.js} +461 -46
- package/dist/chunk-XVD7ALPV.js.map +1 -0
- package/dist/index.d.ts +5 -5
- package/dist/index.js +4 -4
- package/dist/{messageBus-CtrwkjrO.d.ts → messageBus-BDtkjs6y.d.ts} +1 -1
- package/dist/messagePortServiceTransport-DyNmdgoa.d.ts +150 -0
- package/dist/react.d.ts +1 -1
- package/dist/react.js +1 -1
- package/dist/{runtimeTypes-DquUCHz-.d.ts → runtimeTypes-CleHMFaq.d.ts} +269 -3
- package/dist/{sharedWorkerHost-Cb2a1_KD.d.ts → sharedWorkerHost-BNMUW-8v.d.ts} +37 -2
- package/dist/testing.d.ts +6 -6
- package/dist/testing.js +4 -4
- package/dist/{windowRuntime-B6Ue8jso.d.ts → windowRuntime-BGl_jfbK.d.ts} +2 -2
- package/docs/api.md +1 -1
- package/docs/proposals/webloom-v4/verification.md +100 -54
- package/package.json +5 -3
- package/dist/chunk-JHJZIO2H.js.map +0 -1
- package/dist/chunk-RAQOFUZY.js.map +0 -1
- package/dist/chunk-YOIH6H36.js.map +0 -1
- package/dist/messagePortServiceTransport-B0FyJr43.d.ts +0 -264
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { createMessagePortRuntimeTransport, createCapabilityBridge, createPeerScopeView, createCapabilityPeerView, createMessagePortServiceProvider } from './chunk-
|
|
2
|
-
import { RuntimeInitializationError, normalizeRuntimeLimits, createRuntimeBudget, createRuntimeMessageCodec, capabilityKey, materializePluginDefinitions, createRuntimeUnitImplementationRegistry, createPluginHost, RUNTIME_SNAPSHOT_TYPE, WebLoomError, cloneFrozenAttributes, RUNTIME_PROTOCOL_VERSION, validateDto } from './chunk-
|
|
1
|
+
import { createRuntimeEndpointBinding, createMessagePortRuntimeTransport, createRuntimeEndpointSession, createCapabilityBridge, createPeerScopeView, createCapabilityPeerView, createMessagePortServiceProvider } from './chunk-XVD7ALPV.js';
|
|
2
|
+
import { RuntimeInitializationError, normalizeRuntimeLimits, createRuntimeBudget, createRuntimeMessageCodec, capabilityKey, materializePluginDefinitions, createRuntimeUnitImplementationRegistry, createPluginHost, RUNTIME_SNAPSHOT_TYPE, WebLoomError, cloneFrozenAttributes, RUNTIME_PROTOCOL_VERSION, validateDto } from './chunk-CKML74MG.js';
|
|
3
3
|
|
|
4
4
|
// src/runtime/sharedWorkerHost.ts
|
|
5
5
|
function makeId(prefix) {
|
|
@@ -23,6 +23,7 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
23
23
|
const runtimeCodec = createRuntimeMessageCodec();
|
|
24
24
|
const peerExposureAllowlist = options.peerExposureAllowlist === void 0 ? void 0 : new Set(options.peerExposureAllowlist.map((capability) => capabilityKey(capability)));
|
|
25
25
|
const listeners = /* @__PURE__ */ new Set();
|
|
26
|
+
const peerLifecycleListeners = /* @__PURE__ */ new Set();
|
|
26
27
|
const endpoints = /* @__PURE__ */ new Set();
|
|
27
28
|
let manifests = [];
|
|
28
29
|
let runtimeState = "starting";
|
|
@@ -31,14 +32,26 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
31
32
|
let accepting = true;
|
|
32
33
|
let host;
|
|
33
34
|
let disposePromise;
|
|
35
|
+
const emitPeerLifecycle = (event) => {
|
|
36
|
+
const frozen = Object.freeze({
|
|
37
|
+
...event,
|
|
38
|
+
binding: Object.freeze({ ...event.binding }),
|
|
39
|
+
...event.drain !== void 0 ? { drain: Object.freeze({ ...event.drain }) } : {}
|
|
40
|
+
});
|
|
41
|
+
for (const listener of [...peerLifecycleListeners]) {
|
|
42
|
+
try {
|
|
43
|
+
listener(frozen);
|
|
44
|
+
} catch {
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
34
48
|
const localSnapshot = () => {
|
|
35
49
|
const currentHost = host;
|
|
36
50
|
const units = currentHost ? currentHost.installed().flatMap((pluginId) => currentHost.state(pluginId).units.map((unit) => ({ pluginId: unit.pluginId, unitId: unit.unitId, runtime: unit.runtime, ...unit.instanceId !== void 0 ? { instanceId: unit.instanceId } : {}, state: unit.kind }))) : [];
|
|
37
51
|
const services = runtimeState === "ready" && host ? host.serviceReferences().map((service) => ({ kind: service.kind, capabilityId: service.capabilityId, contractVersion: service.contractVersion, serviceInstanceId: service.serviceInstanceId, attributes: cloneFrozenAttributes(service.attributes), ...service.grantId !== void 0 ? { grantId: service.grantId } : {}, ...service.authorizationRevision !== void 0 ? { authorizationRevision: service.authorizationRevision } : {} })) : [];
|
|
38
52
|
return Object.freeze({ protocolVersion: RUNTIME_PROTOCOL_VERSION, runtimeId: options.id, runtimeKind: "shared-worker", runtimeInstanceId, revision, state: runtimeState, units: Object.freeze(units), services: Object.freeze(services) });
|
|
39
53
|
};
|
|
40
|
-
const emit = () => {
|
|
41
|
-
const snapshot = localSnapshot();
|
|
54
|
+
const emit = (snapshot = localSnapshot()) => {
|
|
42
55
|
for (const listener of [...listeners]) {
|
|
43
56
|
try {
|
|
44
57
|
listener(snapshot);
|
|
@@ -54,10 +67,10 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
54
67
|
if (owners.size === 0) return Object.freeze([]);
|
|
55
68
|
return Object.freeze(host.installed().flatMap((pluginId) => host.state(pluginId).units.filter((unit) => unit.instanceId !== void 0 && owners.has(unit.instanceId)).map((unit) => ({ pluginId: unit.pluginId, unitId: unit.unitId, runtime: unit.runtime, ...unit.instanceId !== void 0 ? { instanceId: unit.instanceId } : {}, state: unit.kind }))));
|
|
56
69
|
};
|
|
57
|
-
const wireSnapshot = (endpoint, nextRevision = endpoint.revision, exposures = endpoint.exposures) => {
|
|
58
|
-
localSnapshot();
|
|
70
|
+
const wireSnapshot = (endpoint, nextRevision = endpoint.revision, exposures = endpoint.exposures, base = localSnapshot()) => {
|
|
59
71
|
const services = [...exposures.values()].map((service) => ({ kind: service.kind, capabilityId: service.capabilityId, contractVersion: service.contractVersion, serviceInstanceId: service.serviceInstanceId, attributes: cloneFrozenAttributes(service.attributes), ...service.grantId !== void 0 ? { grantId: service.grantId } : {}, ...service.authorizationRevision !== void 0 ? { authorizationRevision: service.authorizationRevision } : {} }));
|
|
60
|
-
|
|
72
|
+
const state = base.state === "disconnected" ? "failed" : base.state;
|
|
73
|
+
return { type: RUNTIME_SNAPSHOT_TYPE, protocolVersion: base.protocolVersion, runtimeId: base.runtimeId, runtimeKind: base.runtimeKind, runtimeInstanceId: base.runtimeInstanceId, revision: nextRevision, state, units: projectedUnits(exposures), services: state === "ready" ? services : [], binding: endpoint.binding };
|
|
61
74
|
};
|
|
62
75
|
const validateProjectedSnapshot = (endpoint, exposures) => {
|
|
63
76
|
if (exposures.size > limits.maxSnapshotServices) throw new WebLoomError("resource_limit_exceeded", "Runtime service exposure limit exceeded", "dispatch");
|
|
@@ -65,33 +78,37 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
65
78
|
runtimeCodec.encode(snapshot);
|
|
66
79
|
validateDto(snapshot, { limits: { maxDepth: limits.maxDtoDepth, maxNodes: limits.maxDtoNodes, maxEdges: limits.maxDtoEdges, maxBudgetBytes: limits.maxMessageBudgetBytes }, phase: "dispatch" });
|
|
67
80
|
};
|
|
68
|
-
const publish = (endpoint, exposures = endpoint.exposures) => {
|
|
69
|
-
if (endpoint.closed) return;
|
|
81
|
+
const publish = (endpoint, exposures = endpoint.exposures, base, allowClosed = false) => {
|
|
82
|
+
if (endpoint.closed && !allowClosed) return;
|
|
70
83
|
const nextRevision = endpoint.revision + 1;
|
|
71
|
-
const snapshot = wireSnapshot(endpoint, nextRevision, exposures);
|
|
84
|
+
const snapshot = wireSnapshot(endpoint, nextRevision, exposures, base);
|
|
72
85
|
endpoint.transport.send(snapshot);
|
|
73
86
|
endpoint.revision = nextRevision;
|
|
74
87
|
};
|
|
75
88
|
const publishAll = () => {
|
|
89
|
+
const base = localSnapshot();
|
|
90
|
+
options.snapshotObserver?.(base);
|
|
76
91
|
for (const endpoint of endpoints) {
|
|
77
92
|
try {
|
|
78
|
-
publish(endpoint);
|
|
93
|
+
publish(endpoint, endpoint.exposures, base);
|
|
79
94
|
} catch {
|
|
80
95
|
closeEndpoint(endpoint, "Runtime snapshot publication failed");
|
|
81
96
|
}
|
|
82
97
|
}
|
|
83
|
-
emit();
|
|
98
|
+
emit(base);
|
|
84
99
|
};
|
|
85
100
|
const createEndpoint = (port) => {
|
|
86
101
|
if (!host) throw new Error("SharedWorker Host is unavailable");
|
|
87
102
|
const peerScope = host.rootScope.child("peer", { attributes: { peerId: makeId("peer") } });
|
|
88
103
|
const transport = createMessagePortRuntimeTransport(port, { limits });
|
|
89
|
-
const
|
|
104
|
+
const binding = createRuntimeEndpointBinding(runtimeInstanceId);
|
|
105
|
+
const session = createRuntimeEndpointSession(binding);
|
|
106
|
+
const bridge = createCapabilityBridge({ transport, remoteRuntimeKind: "window-main", limits, budget: outboundBudget, binding, session });
|
|
90
107
|
const exposures = /* @__PURE__ */ new Map();
|
|
91
108
|
const exposurePolicies = /* @__PURE__ */ new Map();
|
|
92
109
|
const peerId = peerScope.identity.attributes.peerId ?? makeId("peer");
|
|
93
110
|
const peerScopeView = createPeerScopeView(peerScope);
|
|
94
|
-
const peerView = createCapabilityPeerView({ peerId, scope: peerScopeView, bridge, capabilityScope: peerScope });
|
|
111
|
+
const peerView = createCapabilityPeerView({ peerId, binding, scope: peerScopeView, bridge, capabilityScope: peerScope });
|
|
95
112
|
let endpointForDisconnect;
|
|
96
113
|
const exposeGroup = (entries, source = "dynamic") => {
|
|
97
114
|
if (peerScope.state !== "active") throw new WebLoomError("service_revoked", "Peer scope is not active", "dispatch", { capabilityId: entries[0]?.capability.id });
|
|
@@ -189,6 +206,10 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
189
206
|
const configuredExposureKeys = /* @__PURE__ */ new Set();
|
|
190
207
|
const peer = {
|
|
191
208
|
peerId,
|
|
209
|
+
binding,
|
|
210
|
+
get endpointState() {
|
|
211
|
+
return session.state;
|
|
212
|
+
},
|
|
192
213
|
get runtimeInstanceId() {
|
|
193
214
|
return bridge.runtimeInstanceId;
|
|
194
215
|
},
|
|
@@ -196,6 +217,12 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
196
217
|
scope: peerScope,
|
|
197
218
|
view: peerView,
|
|
198
219
|
capability: (capability) => bridge.getClient(capability, peerScope),
|
|
220
|
+
beginClose(reason = "Peer endpoint closing") {
|
|
221
|
+
session.beginClose(reason);
|
|
222
|
+
},
|
|
223
|
+
drain(timeoutMs) {
|
|
224
|
+
return bridge.drain(timeoutMs);
|
|
225
|
+
},
|
|
199
226
|
expose(capability, exposureOptions = {}) {
|
|
200
227
|
const result = exposeGroup([{ capability, options: exposureOptions }]);
|
|
201
228
|
configuredExposureKeys.add(capabilityKey(capability));
|
|
@@ -240,12 +267,14 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
240
267
|
transport,
|
|
241
268
|
peerScope,
|
|
242
269
|
peer: peerView,
|
|
270
|
+
binding,
|
|
271
|
+
session,
|
|
243
272
|
budget: inboundBudget,
|
|
244
273
|
limits,
|
|
245
274
|
services: () => [...exposures.values()],
|
|
246
275
|
peerForCall: (_call, reference) => {
|
|
247
276
|
const registration = host?.capabilities.registration({ kind: reference.kind, id: reference.capabilityId, version: reference.contractVersion });
|
|
248
|
-
return createCapabilityPeerView({ peerId, scope: peerScopeView, bridge, allowed: registration?.peerDependencies ?? [], capabilityScope: peerScope });
|
|
277
|
+
return createCapabilityPeerView({ peerId, binding, scope: peerScopeView, bridge, allowed: registration?.peerDependencies ?? [], capabilityScope: peerScope });
|
|
249
278
|
},
|
|
250
279
|
prepareRequest: (call) => {
|
|
251
280
|
if (!host) throw new WebLoomError("service_stale", "SharedWorker Host is unavailable", "dispatch");
|
|
@@ -267,7 +296,7 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
267
296
|
const policy = exposurePolicies.get(key);
|
|
268
297
|
if (!registration || !exposures.has(key)) throw new Error("Runtime service exposure is stale");
|
|
269
298
|
const handlerReference = reference;
|
|
270
|
-
const context = { signal, deadlineAt, ...call.operationId !== void 0 ? { operationId: call.operationId } : {}, reference: handlerReference, origin: "remote", peer: callPeer };
|
|
299
|
+
const context = { signal, deadlineAt, ...call.operationId !== void 0 ? { operationId: call.operationId } : {}, reference: handlerReference, binding: call.binding, origin: "remote", peer: callPeer };
|
|
271
300
|
if (policy?.authorize && !await policy.authorize(context, request)) throw new WebLoomError("permission_denied", "Peer capability authorization denied", "dispatch", { capabilityId: reference.capabilityId, serviceInstanceId: reference.serviceInstanceId });
|
|
272
301
|
if (exposures.get(key)?.serviceInstanceId !== handlerReference.serviceInstanceId) throw new WebLoomError("service_stale", "Runtime service exposure was replaced while authorization was pending", "dispatch", { serviceInstanceId: handlerReference.serviceInstanceId });
|
|
273
302
|
if (peerScope.state !== "active" || signal.aborted) throw new WebLoomError("service_revoked", "Peer scope was revoked", "dispose", { serviceInstanceId: reference.serviceInstanceId });
|
|
@@ -293,9 +322,11 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
293
322
|
return { value: parsed, transfer };
|
|
294
323
|
}
|
|
295
324
|
});
|
|
296
|
-
const endpoint = { port, scope: peerScope, transport, bridge, provider, exposures, installTopLevelExposures, closed: false, revision: 0 };
|
|
325
|
+
const endpoint = { port, scope: peerScope, binding, session, transport, bridge, provider, exposures, installTopLevelExposures, closed: false, revision: 0 };
|
|
297
326
|
endpointForDisconnect = endpoint;
|
|
298
327
|
endpoints.add(endpoint);
|
|
328
|
+
emitPeerLifecycle({ event: "active", peerId, binding, state: "active" });
|
|
329
|
+
session.onClosed(() => closeEndpoint(endpoint, "Runtime endpoint closed"));
|
|
299
330
|
try {
|
|
300
331
|
if (disconnectRequested !== void 0) closeEndpoint(endpoint, disconnectRequested);
|
|
301
332
|
installTopLevelExposures();
|
|
@@ -306,20 +337,44 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
306
337
|
}
|
|
307
338
|
return endpoint;
|
|
308
339
|
};
|
|
309
|
-
const
|
|
340
|
+
const beginCloseEndpoint = (endpoint, reason) => {
|
|
310
341
|
if (endpoint.closed) return;
|
|
311
342
|
endpoint.closed = true;
|
|
312
|
-
endpoint.scope.revoke(reason);
|
|
313
|
-
void endpoint.scope.dispose({ reason });
|
|
314
|
-
endpoint.provider.dispose();
|
|
315
|
-
endpoint.bridge.dispose(reason);
|
|
316
|
-
endpoint.transport.close?.();
|
|
317
343
|
endpoints.delete(endpoint);
|
|
344
|
+
endpoint.scope.revoke(reason);
|
|
345
|
+
endpoint.provider.beginClose(reason);
|
|
346
|
+
endpoint.bridge.beginClose(reason);
|
|
347
|
+
emitPeerLifecycle({ event: "closing", peerId: endpoint.scope.identity.attributes.peerId, binding: endpoint.binding, state: "closing" });
|
|
348
|
+
};
|
|
349
|
+
const closeEndpoint = (endpoint, reason) => {
|
|
350
|
+
if (endpoint.closePromise) return endpoint.closePromise;
|
|
351
|
+
beginCloseEndpoint(endpoint, reason);
|
|
352
|
+
endpoint.closePromise = (async () => {
|
|
353
|
+
let providerDrain;
|
|
354
|
+
let bridgeDrain;
|
|
355
|
+
try {
|
|
356
|
+
[providerDrain, bridgeDrain] = await Promise.all([endpoint.provider.drain(), endpoint.bridge.drain()]);
|
|
357
|
+
} catch {
|
|
358
|
+
providerDrain = { state: endpoint.session.state, drained: false, timedOut: true, pendingExecutions: endpoint.provider.executionCount() };
|
|
359
|
+
bridgeDrain = { state: endpoint.session.state, drained: false, timedOut: true, pendingExecutions: endpoint.bridge.pendingCallCount + endpoint.bridge.activeStreamCount };
|
|
360
|
+
}
|
|
361
|
+
try {
|
|
362
|
+
await endpoint.scope.dispose({ reason });
|
|
363
|
+
} catch {
|
|
364
|
+
}
|
|
365
|
+
endpoint.provider.dispose();
|
|
366
|
+
endpoint.bridge.dispose(reason);
|
|
367
|
+
endpoint.transport.close?.();
|
|
368
|
+
endpoint.session.close();
|
|
369
|
+
emitPeerLifecycle({ event: "closed", peerId: endpoint.scope.identity.attributes.peerId, binding: endpoint.binding, state: "closed", drain: bridgeDrain.drained && providerDrain.drained ? bridgeDrain : { ...bridgeDrain, drained: false, timedOut: bridgeDrain.timedOut || providerDrain.timedOut, pendingExecutions: Math.max(bridgeDrain.pendingExecutions, providerDrain.pendingExecutions) } });
|
|
370
|
+
})();
|
|
371
|
+
return endpoint.closePromise;
|
|
318
372
|
};
|
|
319
373
|
const sendTerminalSnapshot = (port) => {
|
|
320
374
|
try {
|
|
321
375
|
port.start();
|
|
322
|
-
|
|
376
|
+
const binding = createRuntimeEndpointBinding(runtimeInstanceId);
|
|
377
|
+
port.postMessage({ ...localSnapshot(), type: RUNTIME_SNAPSHOT_TYPE, binding });
|
|
323
378
|
setTimeout(() => {
|
|
324
379
|
try {
|
|
325
380
|
port.close();
|
|
@@ -359,8 +414,7 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
359
414
|
if (runtimeState === "ready" && !disposed) {
|
|
360
415
|
revision += 1;
|
|
361
416
|
publishAll();
|
|
362
|
-
}
|
|
363
|
-
emit();
|
|
417
|
+
} else emit();
|
|
364
418
|
});
|
|
365
419
|
} catch (error) {
|
|
366
420
|
runtimeState = "failed";
|
|
@@ -372,7 +426,10 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
372
426
|
listeners.add(listener);
|
|
373
427
|
listener(localSnapshot());
|
|
374
428
|
return () => listeners.delete(listener);
|
|
375
|
-
}, inspect: failedInspection,
|
|
429
|
+
}, inspect: failedInspection, activePeers: () => Object.freeze([]), subscribePeerLifecycle(listener) {
|
|
430
|
+
peerLifecycleListeners.add(listener);
|
|
431
|
+
return () => peerLifecycleListeners.delete(listener);
|
|
432
|
+
}, notifyPeerHandoff: () => false, dispose: async () => ({ scopeId: `runtime:${runtimeInstanceId}`, state: "stopped", attempted: 0, released: 0, pending: [], errors: [], cleanupIncomplete: false }) };
|
|
376
433
|
}
|
|
377
434
|
const ready = host.registerAll(manifests).then(() => {
|
|
378
435
|
for (const endpoint of endpoints) endpoint.installTopLevelExposures();
|
|
@@ -402,17 +459,40 @@ function startSharedWorkerAppInternal(options, injectedScope) {
|
|
|
402
459
|
return () => listeners.delete(listener);
|
|
403
460
|
},
|
|
404
461
|
inspect: () => host ? { ...host.inspect(), peerCount: endpoints.size } : { runtimeId: options.id, runtimeKind: "shared-worker", runtimeInstanceId, version: 0, pluginCount: 0, peerCount: endpoints.size, pendingCallCount: 0, activeStreamCount: 0, plugins: [] },
|
|
462
|
+
activePeers: () => Object.freeze([...endpoints].filter((endpoint) => !endpoint.closed && endpoint.session.state === "active").map((endpoint) => Object.freeze({ event: "active", peerId: endpoint.scope.identity.attributes.peerId, binding: Object.freeze({ ...endpoint.binding }), state: "active" }))),
|
|
463
|
+
subscribePeerLifecycle(listener) {
|
|
464
|
+
peerLifecycleListeners.add(listener);
|
|
465
|
+
for (const endpoint of endpoints) if (!endpoint.closed && endpoint.session.state === "active") listener(Object.freeze({ event: "active", peerId: endpoint.scope.identity.attributes.peerId, binding: Object.freeze({ ...endpoint.binding }), state: "active" }));
|
|
466
|
+
return () => peerLifecycleListeners.delete(listener);
|
|
467
|
+
},
|
|
468
|
+
notifyPeerHandoff(peerId, handoffRevision) {
|
|
469
|
+
const endpoint = [...endpoints].find((candidate) => !candidate.closed && candidate.scope.identity.attributes.peerId === peerId);
|
|
470
|
+
if (!endpoint || endpoint.session.state !== "active") return false;
|
|
471
|
+
emitPeerLifecycle({ event: "handoff", peerId, binding: endpoint.binding, state: "active", ...handoffRevision !== void 0 ? { handoffRevision } : {} });
|
|
472
|
+
return true;
|
|
473
|
+
},
|
|
405
474
|
dispose(reason = "shared worker runtime disposed") {
|
|
406
475
|
if (disposePromise) return disposePromise;
|
|
407
476
|
accepting = false;
|
|
408
477
|
disposed = true;
|
|
409
478
|
runtimeState = "stopping";
|
|
479
|
+
const endpointsToClose = [...endpoints];
|
|
410
480
|
publishAll();
|
|
481
|
+
for (const endpoint of endpointsToClose) beginCloseEndpoint(endpoint, reason);
|
|
411
482
|
disposePromise = (async () => {
|
|
412
|
-
const result = host ?
|
|
483
|
+
const result = await (host ? host.dispose(reason) : Promise.resolve({ scopeId: `runtime:${runtimeInstanceId}`, state: "stopped", attempted: 0, released: 0, pending: [], errors: [], cleanupIncomplete: false }));
|
|
413
484
|
runtimeState = "disposed";
|
|
414
|
-
|
|
415
|
-
|
|
485
|
+
const terminal = localSnapshot();
|
|
486
|
+
options.snapshotObserver?.(terminal);
|
|
487
|
+
for (const endpoint of endpointsToClose) {
|
|
488
|
+
try {
|
|
489
|
+
publish(endpoint, endpoint.exposures, terminal, true);
|
|
490
|
+
} catch {
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
emit(terminal);
|
|
494
|
+
const endpointClosures = endpointsToClose.map((endpoint) => closeEndpoint(endpoint, reason));
|
|
495
|
+
await Promise.all(endpointClosures);
|
|
416
496
|
return result;
|
|
417
497
|
})();
|
|
418
498
|
return disposePromise;
|
|
@@ -429,5 +509,5 @@ function startSharedWorkerAppForTesting(options) {
|
|
|
429
509
|
}
|
|
430
510
|
|
|
431
511
|
export { startSharedWorkerApp, startSharedWorkerAppForTesting };
|
|
432
|
-
//# sourceMappingURL=chunk-
|
|
433
|
-
//# sourceMappingURL=chunk-
|
|
512
|
+
//# sourceMappingURL=chunk-RRNUE457.js.map
|
|
513
|
+
//# sourceMappingURL=chunk-RRNUE457.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/runtime/sharedWorkerHost.ts"],"names":[],"mappings":"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","file":"chunk-RRNUE457.js","sourcesContent":["// SharedWorkerGlobalScope 内的 v4 Runtime。\n\nimport type { CapabilityPeer, RemoteCapability, ServiceReference } from \"../contracts/capability.js\";\nimport { capabilityKey } from \"../contracts/capability.js\";\nimport { WebLoomError, type LifecycleDisposeResult, type LifecycleScope, type RuntimeEndpointBinding, type RuntimeEndpointState, type RuntimeSnapshot } from \"../contracts/lifecycle.js\";\nimport { createRuntimeBudget, normalizeRuntimeLimits, validateDto, type RuntimeBudget, type RuntimeLimitsInput } from \"../transport/dto.js\";\nimport type { PluginManifest } from \"../contracts/plugin.js\";\nimport { createPluginHost, type CreatePluginHostOptions, type HostInspection, type PluginHost } from \"../host/createPluginHost.js\";\nimport { createRuntimeUnitImplementationRegistry } from \"../host/runtimeUnitImplementationRegistry.js\";\nimport { invokeCapabilityHandler } from \"../host/capabilityRegistry.js\";\nimport { materializePluginDefinitions, type RuntimePluginDefinition } from \"./pluginDefinitions.js\";\nimport { createCapabilityBridge } from \"../transport/serviceBridge.js\";\nimport { createMessagePortRuntimeTransport } from \"../transport/messagePortServiceTransport.js\";\nimport { createMessagePortServiceProvider } from \"../transport/messagePortServiceProvider.js\";\nimport { cloneFrozenAttributes } from \"../transport/dto.js\";\nimport { createRuntimeMessageCodec, RUNTIME_PROTOCOL_VERSION, RUNTIME_SNAPSHOT_TYPE } from \"./runtimeProtocol.js\";\nimport { RuntimeInitializationError, type RuntimeStatusListener, type RuntimeStatusSnapshot } from \"./runtimeTypes.js\";\nimport { createCapabilityPeerView, createPeerScopeView } from \"./peerView.js\";\nimport { createRuntimeEndpointBinding, createRuntimeEndpointSession, type RuntimeEndpointSession } from \"./runtimeSession.js\";\n\nexport interface SharedWorkerScopeLike {\n /** SharedWorker 连接事件。 */\n onconnect: ((event: { ports: MessagePort[] }) => void) | null;\n}\n\nexport interface PeerExposureOptions {\n /** 领域授权标识。 */\n readonly grantId?: string;\n /** 授权修订。 */\n readonly authorizationRevision?: number;\n /** 无环公开属性。 */\n readonly attributes?: Readonly<Record<string, unknown>>;\n /** 领域授权检查。 */\n readonly authorize?: (context: import(\"../contracts/capability.js\").HandlerCallContext, request: unknown) => boolean | Promise<boolean>;\n /** 领域 Scope。 */\n readonly scope?: LifecycleScope;\n}\n\nexport interface PeerController {\n /** peer 标识。 */\n readonly peerId: string;\n /** 当前物理 endpoint 的不可复用框架 binding。 */\n readonly binding: RuntimeEndpointBinding;\n /** 当前物理 endpoint 的关闭阶段。 */\n readonly endpointState: RuntimeEndpointState;\n /** 已观察到的页面 Runtime 实例;首个页面快照前为空。 */\n readonly runtimeInstanceId?: string;\n /** 对端 Window Runtime 类型。 */\n readonly runtime: \"window-main\";\n /** peer 子作用域。 */\n readonly scope: LifecycleScope;\n /** 传给普通 handler 的最小 PeerView。 */\n readonly view: CapabilityPeer;\n /** 获取页面暴露的 typed remote capability。 */\n capability<C extends RemoteCapability>(capability: C): import(\"../contracts/capability.js\").CapabilityClient<C>;\n /** 暴露 Worker 已注册的 capability。 */\n expose<C extends RemoteCapability>(capability: C, options?: PeerExposureOptions): { revoke(): void };\n /** 原子暴露一组 capability;任一项非法时不得部分开放。 */\n exposeGroup(entries: readonly { readonly capability: RemoteCapability; readonly options?: PeerExposureOptions }[]): { revoke(): void };\n /** 断开此 peer,不影响其它页面。 */\n disconnect(reason?: string): void;\n /** 同步停止新调用与暴露;后续由 drain/close 完成异步收尾。 */\n beginClose(reason?: string): void;\n /** 等待该 peer endpoint 的 bounded drain。 */\n drain(timeoutMs?: number): Promise<import(\"../contracts/lifecycle.js\").RuntimeDrainResult>;\n /** peer 诊断。 */\n inspect(): Readonly<Record<string, unknown>>;\n}\n\n/** 可信 Host 可观察的 peer 生命周期事件;不包含 owner/lease 等领域字段。 */\nexport interface PeerLifecycleEvent {\n /** active 建立、handoff 通知或关闭阶段。 */\n readonly event: \"active\" | \"handoff\" | \"closing\" | \"closed\";\n /** peer 物理连接的 opaque 标识。 */\n readonly peerId: string;\n /** 当前物理 endpoint 的框架 binding。 */\n readonly binding: RuntimeEndpointBinding;\n /** endpoint 的框架生命周期。 */\n readonly state: RuntimeEndpointState;\n /** closed 事件的真实 bounded drain 结果。 */\n readonly drain?: import(\"../contracts/lifecycle.js\").RuntimeDrainResult;\n /** 可信 Host 提供的 handoff 修订;WebLoom 不解释或选择 owner。 */\n readonly handoffRevision?: number;\n}\n\n/** 可信 Host 查询到的 active peer 只读投影。 */\nexport type ActivePeerSnapshot = Omit<PeerLifecycleEvent, \"event\" | \"drain\" | \"handoffRevision\"> & { readonly event: \"active\" };\n\nexport interface StartSharedWorkerAppOptions extends Omit<CreatePluginHostOptions, \"runtime\" | \"runtimeUnitImplementationRegistry\" | \"runtimeId\" | \"runtimeInstanceId\"> {\n /** Worker Runtime 逻辑标识。 */\n readonly id: string;\n /** Worker realm 的插件定义。 */\n readonly plugins: readonly RuntimePluginDefinition[];\n /** 对每个新 peer 顶层暴露的能力。 */\n readonly expose?: readonly RemoteCapability[];\n /** 同步配置 peer 级策略。 */\n readonly configurePeer?: (peer: PeerController) => void;\n /** configurePeer 可管理的显式 capability allowlist;未设置时不开放动态能力。 */\n readonly peerExposureAllowlist?: readonly RemoteCapability[];\n /** 可信 transport 配额;只能使用默认值或收紧。 */\n readonly limits?: RuntimeLimitsInput;\n}\n\nexport interface StartSharedWorkerAppForTestingOptions extends StartSharedWorkerAppOptions {\n /** testing 入口注入的 SharedWorkerGlobalScope 替身。 */\n readonly globalScope: SharedWorkerScopeLike;\n /** 仅测试用:观察每次向所有 peer 广播前构建的公共快照。 */\n readonly snapshotObserver?: (snapshot: RuntimeStatusSnapshot) => void;\n}\n\nexport interface SharedWorkerApp {\n readonly runtimeKind: \"shared-worker\";\n readonly runtimeId: string;\n readonly runtimeInstanceId: string;\n ready(): Promise<void>;\n reconcile(): Promise<void>;\n state(): RuntimeStatusSnapshot;\n subscribe(listener: RuntimeStatusListener): () => void;\n inspect(): HostInspection;\n /** 只读查询当前仍处于 active 的物理 peer。 */\n activePeers(): readonly ActivePeerSnapshot[];\n /** 订阅 Host 可见的 peer active/closing/closed/handoff 事件。 */\n subscribePeerLifecycle(listener: (event: PeerLifecycleEvent) => void): () => void;\n /** 可信领域在完成自己的 owner/session 交接后报告 handoff;框架不选择 owner。 */\n notifyPeerHandoff(peerId: string, handoffRevision?: number): boolean;\n dispose(reason?: string): Promise<LifecycleDisposeResult>;\n}\n\ninterface Endpoint {\n readonly port: MessagePort;\n readonly scope: LifecycleScope;\n readonly binding: RuntimeEndpointBinding;\n readonly session: RuntimeEndpointSession;\n readonly transport: ReturnType<typeof createMessagePortRuntimeTransport>;\n readonly bridge: ReturnType<typeof createCapabilityBridge>;\n readonly provider: ReturnType<typeof createMessagePortServiceProvider>;\n readonly exposures: Map<string, ServiceReference>;\n readonly installTopLevelExposures: () => void;\n closed: boolean;\n revision: number;\n /** 已启动的 endpoint 收尾 Promise;保证 close 调用幂等且可等待。 */\n closePromise?: Promise<void>;\n}\n\nfunction makeId(prefix: string): string {\n try { if (typeof crypto !== \"undefined\" && typeof crypto.randomUUID === \"function\") return `${prefix}:${crypto.randomUUID()}`; } catch { /* fallback */ }\n return `${prefix}:${Date.now().toString(36)}:${Math.random().toString(36).slice(2)}`;\n}\n\nfunction message(error: unknown): string { return error instanceof Error ? error.message : String(error); }\n\n/** 启动一个真实 SharedWorker Runtime;setup 异步完成前也会发布空 services 快照。 */\nfunction startSharedWorkerAppInternal(options: StartSharedWorkerAppOptions & Pick<StartSharedWorkerAppForTestingOptions, \"snapshotObserver\">, injectedScope?: SharedWorkerScopeLike): SharedWorkerApp {\n if (!options || typeof options.id !== \"string\" || options.id.trim() === \"\") throw new TypeError(\"SharedWorker runtime id must be a non-empty string\");\n const scope = injectedScope ?? ((globalThis as unknown as { onconnect?: unknown }).onconnect !== undefined ? globalThis as unknown as SharedWorkerScopeLike : undefined);\n if (!scope) throw new RuntimeInitializationError({ phase: \"validate\", error: \"startSharedWorkerApp must run in a SharedWorkerGlobalScope\" });\n const runtimeInstanceId = makeId(options.id);\n const limits = normalizeRuntimeLimits(options.limits);\n // One counter per direction is shared by every endpoint in this Runtime;\n // per-peer limits remain enforced inside each bridge/provider.\n const outboundBudget: RuntimeBudget = createRuntimeBudget(limits);\n const inboundBudget: RuntimeBudget = createRuntimeBudget(limits);\n const runtimeCodec = createRuntimeMessageCodec();\n const peerExposureAllowlist = options.peerExposureAllowlist === undefined\n ? undefined\n : new Set(options.peerExposureAllowlist.map((capability) => capabilityKey(capability)));\n const listeners = new Set<RuntimeStatusListener>();\n const peerLifecycleListeners = new Set<(event: PeerLifecycleEvent) => void>();\n const endpoints = new Set<Endpoint>();\n let manifests: readonly PluginManifest[] = [];\n let runtimeState: RuntimeSnapshot[\"state\"] = \"starting\";\n let revision = 0;\n let disposed = false;\n let accepting = true;\n let host: PluginHost | undefined;\n let disposePromise: Promise<LifecycleDisposeResult> | undefined;\n\n const emitPeerLifecycle = (event: PeerLifecycleEvent): void => {\n const frozen = Object.freeze({\n ...event,\n binding: Object.freeze({ ...event.binding }),\n ...(event.drain !== undefined ? { drain: Object.freeze({ ...event.drain }) } : {}),\n });\n for (const listener of [...peerLifecycleListeners]) {\n try { listener(frozen); } catch { /* observer isolation */ }\n }\n };\n\n const localSnapshot = (): RuntimeStatusSnapshot => {\n const currentHost = host;\n const units = currentHost ? currentHost.installed().flatMap((pluginId) => currentHost.state(pluginId).units.map((unit) => ({ pluginId: unit.pluginId, unitId: unit.unitId, runtime: unit.runtime, ...(unit.instanceId !== undefined ? { instanceId: unit.instanceId } : {}), state: unit.kind }))) : [];\n const services = runtimeState === \"ready\" && host ? host.serviceReferences().map((service) => ({ kind: service.kind, capabilityId: service.capabilityId, contractVersion: service.contractVersion, serviceInstanceId: service.serviceInstanceId, attributes: cloneFrozenAttributes(service.attributes), ...(service.grantId !== undefined ? { grantId: service.grantId } : {}), ...(service.authorizationRevision !== undefined ? { authorizationRevision: service.authorizationRevision } : {}) })) : [];\n return Object.freeze({ protocolVersion: RUNTIME_PROTOCOL_VERSION, runtimeId: options.id, runtimeKind: \"shared-worker\", runtimeInstanceId, revision, state: runtimeState, units: Object.freeze(units), services: Object.freeze(services) });\n };\n const emit = (snapshot: RuntimeStatusSnapshot = localSnapshot()): void => { for (const listener of [...listeners]) { try { listener(snapshot); } catch { /* observer isolation */ } } };\n const projectedUnits = (exposures: ReadonlyMap<string, ServiceReference>): readonly RuntimeSnapshot[\"units\"][number][] => {\n if (!host || exposures.size === 0) return Object.freeze([]);\n // A peer may only learn about the provider units behind services explicitly\n // visible in its projection. The local Host snapshot remains complete for\n // trusted inspection; the wire projection must not be a hidden-provider\n // index.\n const owners = new Set(\n host.capabilities.registrations()\n .filter((registration) => exposures.has(capabilityKey(registration.capability)))\n .map((registration) => registration.ownerId),\n );\n if (owners.size === 0) return Object.freeze([]);\n return Object.freeze(host.installed().flatMap((pluginId) => host!.state(pluginId).units\n .filter((unit) => unit.instanceId !== undefined && owners.has(unit.instanceId))\n .map((unit) => ({ pluginId: unit.pluginId, unitId: unit.unitId, runtime: unit.runtime, ...(unit.instanceId !== undefined ? { instanceId: unit.instanceId } : {}), state: unit.kind }))));\n };\n const wireSnapshot = (endpoint: Endpoint, nextRevision = endpoint.revision, exposures: ReadonlyMap<string, ServiceReference> = endpoint.exposures, base = localSnapshot()): RuntimeSnapshot & { readonly type: typeof RUNTIME_SNAPSHOT_TYPE; readonly binding: RuntimeEndpointBinding } => {\n const services = [...exposures.values()].map((service) => ({ kind: service.kind, capabilityId: service.capabilityId, contractVersion: service.contractVersion, serviceInstanceId: service.serviceInstanceId, attributes: cloneFrozenAttributes(service.attributes), ...(service.grantId !== undefined ? { grantId: service.grantId } : {}), ...(service.authorizationRevision !== undefined ? { authorizationRevision: service.authorizationRevision } : {}) }));\n const state: RuntimeSnapshot[\"state\"] = base.state === \"disconnected\" ? \"failed\" : base.state;\n return { type: RUNTIME_SNAPSHOT_TYPE, protocolVersion: base.protocolVersion, runtimeId: base.runtimeId, runtimeKind: base.runtimeKind, runtimeInstanceId: base.runtimeInstanceId, revision: nextRevision, state, units: projectedUnits(exposures), services: state === \"ready\" ? services : [], binding: endpoint.binding };\n };\n const validateProjectedSnapshot = (endpoint: Endpoint, exposures: ReadonlyMap<string, ServiceReference>): void => {\n if (exposures.size > limits.maxSnapshotServices) throw new WebLoomError(\"resource_limit_exceeded\", \"Runtime service exposure limit exceeded\", \"dispatch\");\n const snapshot = wireSnapshot(endpoint, endpoint.revision + 1, exposures);\n runtimeCodec.encode(snapshot);\n validateDto(snapshot, { limits: { maxDepth: limits.maxDtoDepth, maxNodes: limits.maxDtoNodes, maxEdges: limits.maxDtoEdges, maxBudgetBytes: limits.maxMessageBudgetBytes }, phase: \"dispatch\" });\n };\n const publish = (endpoint: Endpoint, exposures = endpoint.exposures, base?: RuntimeStatusSnapshot, allowClosed = false): void => {\n if (endpoint.closed && !allowClosed) return;\n const nextRevision = endpoint.revision + 1;\n const snapshot = wireSnapshot(endpoint, nextRevision, exposures, base);\n endpoint.transport.send(snapshot);\n // postMessage performs structured-clone synchronously. Advance the\n // per-peer revision only after that operation has succeeded.\n endpoint.revision = nextRevision;\n };\n const publishAll = (): void => {\n const base = localSnapshot();\n options.snapshotObserver?.(base);\n for (const endpoint of endpoints) {\n try { publish(endpoint, endpoint.exposures, base); } catch { closeEndpoint(endpoint, \"Runtime snapshot publication failed\"); }\n }\n emit(base);\n };\n\n const createEndpoint = (port: MessagePort): Endpoint => {\n if (!host) throw new Error(\"SharedWorker Host is unavailable\");\n const peerScope = host.rootScope.child(\"peer\", { attributes: { peerId: makeId(\"peer\") } });\n const transport = createMessagePortRuntimeTransport(port, { limits });\n const binding = createRuntimeEndpointBinding(runtimeInstanceId);\n const session = createRuntimeEndpointSession(binding);\n const bridge = createCapabilityBridge({ transport, remoteRuntimeKind: \"window-main\", limits, budget: outboundBudget, binding, session });\n const exposures = new Map<string, ServiceReference>();\n const exposurePolicies = new Map<string, PeerExposureOptions>();\n const peerId = peerScope.identity.attributes.peerId as string | undefined ?? makeId(\"peer\");\n const peerScopeView = createPeerScopeView(peerScope);\n const peerView: CapabilityPeer = createCapabilityPeerView({ peerId, binding, scope: peerScopeView, bridge, capabilityScope: peerScope });\n let endpointForDisconnect: Endpoint | undefined;\n const exposeGroup = (entries: readonly { readonly capability: RemoteCapability; readonly options?: PeerExposureOptions }[], source: \"dynamic\" | \"top-level\" = \"dynamic\"): { revoke(): void } => {\n if (peerScope.state !== \"active\") throw new WebLoomError(\"service_revoked\", \"Peer scope is not active\", \"dispatch\", { capabilityId: entries[0]?.capability.id });\n const prepared: { key: string; reference: ServiceReference; options: PeerExposureOptions }[] = [];\n const keys = new Set<string>();\n for (const entry of entries) {\n const capability = entry.capability;\n const exposureOptions = entry.options ?? {};\n const key = capabilityKey(capability);\n if (source === \"dynamic\" && (!peerExposureAllowlist || !peerExposureAllowlist.has(key))) {\n throw new WebLoomError(\"capability_unavailable\", \"Capability is outside the peer exposure allowlist\", \"dispatch\", { capabilityId: capability.id });\n }\n const registration = host?.capabilities.registration(capability);\n if (!registration || (capability.kind !== \"rpc\" && capability.kind !== \"stream\") || registration.capability.kind !== capability.kind) {\n throw new Error(`Capability \"${capability.id}\" is not a remote capability registered by this Host`);\n }\n if (keys.has(key) || exposures.has(key)) throw new Error(`Capability \"${capability.id}\" is already exposed to this peer`);\n keys.add(key);\n const reference: ServiceReference = Object.freeze({\n ...registration.reference,\n serviceInstanceId: makeId(`exposure:${peerId}:${capability.id}`),\n attributes: cloneFrozenAttributes(exposureOptions.attributes ?? registration.reference.attributes),\n ...(exposureOptions.grantId !== undefined ? { grantId: exposureOptions.grantId } : {}),\n ...(exposureOptions.authorizationRevision !== undefined ? { authorizationRevision: exposureOptions.authorizationRevision } : {}),\n });\n prepared.push({ key, reference, options: exposureOptions });\n }\n const projected = new Map(exposures);\n for (const item of prepared) projected.set(item.key, item.reference);\n if (endpointForDisconnect) validateProjectedSnapshot(endpointForDisconnect, projected);\n else if (projected.size > limits.maxSnapshotServices) throw new WebLoomError(\"resource_limit_exceeded\", \"Runtime service exposure limit exceeded\", \"dispatch\");\n\n let active = true;\n let committed = false;\n const removers: (() => void)[] = [];\n const removeExposure = (key: string): void => {\n if (!active || !committed || !exposures.delete(key)) return;\n exposurePolicies.delete(key);\n // If the peer scope itself is being revoked, the group callback below\n // performs one grouped removal/publication. Avoid exposing an\n // intermediate per-item revision during that synchronous fence.\n if (endpointForDisconnect && peerScope.state === \"active\") {\n try { publish(endpointForDisconnect); } catch { closeEndpoint(endpointForDisconnect, \"Runtime snapshot publication failed\"); }\n }\n };\n const removeGroup = (): void => {\n if (!active) return;\n active = false;\n let changed = false;\n for (const item of prepared) {\n changed = exposures.delete(item.key) || changed;\n exposurePolicies.delete(item.key);\n }\n for (const remove of removers.splice(0)) remove();\n if (changed && endpointForDisconnect) {\n try { publish(endpointForDisconnect); } catch { closeEndpoint(endpointForDisconnect, \"Runtime snapshot publication failed\"); }\n }\n };\n try {\n for (const item of prepared) {\n if (item.options.scope) {\n if (item.options.scope.state !== \"active\") throw new WebLoomError(\"service_revoked\", \"Capability exposure scope is not active\", \"dispatch\", { capabilityId: item.reference.capabilityId });\n removers.push(item.options.scope.onRevoke(() => removeExposure(item.key)));\n }\n }\n removers.push(peerScope.onRevoke(() => removeGroup()));\n } catch (error) {\n for (const remove of removers.splice(0)) remove();\n throw error;\n }\n\n // The projected snapshot is sent before the local maps are changed. A\n // synchronous postMessage failure therefore cannot leave a locally\n // committed service that the peer never observed. Map insertion itself\n // is then a non-throwing commit step and advances exactly one revision\n // for the complete group.\n try {\n if (prepared.length > 0 && endpointForDisconnect) publish(endpointForDisconnect, projected);\n } catch (error) {\n active = false;\n for (const remove of removers.splice(0)) remove();\n throw error;\n }\n if (peerScope.state !== \"active\" || prepared.some((item) => item.options.scope !== undefined && item.options.scope.state !== \"active\")) {\n active = false;\n for (const remove of removers.splice(0)) remove();\n throw new WebLoomError(\"service_revoked\", \"Capability exposure scope was revoked before commit\", \"dispose\", { capabilityId: prepared[0]?.reference.capabilityId });\n }\n for (const item of prepared) {\n exposures.set(item.key, item.reference);\n exposurePolicies.set(item.key, item.options);\n }\n committed = true;\n // Scope callbacks are registered above and only run after this task; the\n // explicit handle remains the first-class idempotent revocation path.\n return { revoke: removeGroup };\n };\n let disconnectRequested: string | undefined;\n const configuredExposureKeys = new Set<string>();\n const peer: PeerController = {\n peerId,\n binding,\n get endpointState() { return session.state; },\n get runtimeInstanceId() { return bridge.runtimeInstanceId; },\n runtime: \"window-main\",\n scope: peerScope,\n view: peerView,\n capability: (capability) => bridge.getClient(capability, peerScope),\n beginClose(reason = \"Peer endpoint closing\") { session.beginClose(reason); },\n drain(timeoutMs) { return bridge.drain(timeoutMs); },\n expose(capability, exposureOptions = {}) {\n const result = exposeGroup([{ capability, options: exposureOptions }]);\n configuredExposureKeys.add(capabilityKey(capability));\n return result;\n },\n exposeGroup(entries) {\n const result = exposeGroup(entries);\n for (const entry of entries) configuredExposureKeys.add(capabilityKey(entry.capability));\n return result;\n },\n disconnect(reason = \"Peer disconnected\") {\n if (endpointForDisconnect) closeEndpoint(endpointForDisconnect, reason);\n else { disconnectRequested = reason; peerScope.revoke(reason); }\n },\n inspect: () => Object.freeze({ peerId, scopeId: peerScope.identity.scopeId, state: peerScope.state, exposedServiceCount: exposures.size, pendingCallCount: bridge.pendingCallCount, activeStreamCount: bridge.activeStreamCount }),\n };\n const installTopLevelExposures = (): void => {\n const entries: { readonly capability: RemoteCapability }[] = [];\n for (const capability of options.expose ?? []) {\n const key = capabilityKey(capability);\n if (exposures.has(key)) {\n if (configuredExposureKeys.has(key)) throw new Error(`Capability \"${capability.id}\" is exposed by configurePeer and top-level expose`);\n continue;\n }\n if (!host?.capabilities.registration(capability)) continue;\n entries.push({ capability });\n }\n // This is an installation path, not a configurePeer-owned exposure. A\n // single projected snapshot keeps the whole top-level set atomic.\n if (entries.length > 0) exposeGroup(entries, \"top-level\");\n };\n try { options.configurePeer?.(peer); } catch (error) {\n peerScope.revoke(\"configurePeer failed\");\n bridge.dispose(\"configurePeer failed\");\n transport.close?.();\n throw error;\n }\n const provider = createMessagePortServiceProvider({\n transport,\n peerScope,\n peer: peerView,\n binding,\n session,\n budget: inboundBudget,\n limits,\n services: () => [...exposures.values()],\n peerForCall: (_call, reference) => {\n const registration = host?.capabilities.registration({ kind: reference.kind, id: reference.capabilityId, version: reference.contractVersion });\n return createCapabilityPeerView({ peerId, binding, scope: peerScopeView, bridge, allowed: registration?.peerDependencies ?? [], capabilityScope: peerScope });\n },\n prepareRequest: (call) => {\n if (!host) throw new WebLoomError(\"service_stale\", \"SharedWorker Host is unavailable\", \"dispatch\");\n const registration = host.capabilities.registration({ kind: call.mode === \"stream\" ? \"stream\" : \"rpc\", id: call.capabilityId, version: call.contractVersion });\n if (!registration || registration.capability.kind !== (call.mode === \"stream\" ? \"stream\" : \"rpc\")) throw new WebLoomError(\"service_stale\", \"Runtime service exposure is stale\", \"dispatch\");\n const parser = registration.capability as typeof registration.capability & { request: { parse(value: unknown): unknown }; transfer?: { request?: (value: unknown) => readonly Transferable[] } };\n let value: unknown;\n try { value = parser.request.parse(call.request); } catch { throw new WebLoomError(\"request_validation_failed\", \"Capability request failed validation\", \"receive\"); }\n return { value, transfer: parser.transfer?.request?.(value) };\n },\n handleCall: async ({ message: call, request, reference, signal, deadlineAt, peer: callPeer }) => {\n if (!host) throw new Error(\"SharedWorker Host is unavailable\");\n const registration = host.capabilities.registration({ kind: reference.kind, id: reference.capabilityId, version: reference.contractVersion });\n const key = capabilityKey({ kind: reference.kind, id: reference.capabilityId, version: reference.contractVersion });\n const policy = exposurePolicies.get(key);\n if (!registration || !exposures.has(key)) throw new Error(\"Runtime service exposure is stale\");\n const handlerReference = reference;\n const context = { signal, deadlineAt, ...(call.operationId !== undefined ? { operationId: call.operationId } : {}), reference: handlerReference, binding: call.binding, origin: \"remote\" as const, peer: callPeer };\n if (policy?.authorize && !(await policy.authorize(context, request))) throw new WebLoomError(\"permission_denied\", \"Peer capability authorization denied\", \"dispatch\", { capabilityId: reference.capabilityId, serviceInstanceId: reference.serviceInstanceId });\n if (exposures.get(key)?.serviceInstanceId !== handlerReference.serviceInstanceId) throw new WebLoomError(\"service_stale\", \"Runtime service exposure was replaced while authorization was pending\", \"dispatch\", { serviceInstanceId: handlerReference.serviceInstanceId });\n if (peerScope.state !== \"active\" || signal.aborted) throw new WebLoomError(\"service_revoked\", \"Peer scope was revoked\", \"dispose\", { serviceInstanceId: reference.serviceInstanceId });\n if (policy?.scope && policy.scope.state !== \"active\") throw new WebLoomError(\"service_revoked\", \"Peer capability authorization scope is revoked\", \"dispose\", { serviceInstanceId: reference.serviceInstanceId });\n const handler = registration.handler as ((value: unknown, context: import(\"../contracts/capability.js\").HandlerCallContext) => unknown | Promise<unknown>) | undefined;\n if (!handler) throw new WebLoomError(\"service_stale\", \"Runtime service handler is unavailable\", \"dispatch\");\n return handler(request, context);\n },\n prepareResult: (value, call) => {\n const registration = host?.capabilities.registration({ kind: \"rpc\", id: call.capabilityId, version: call.contractVersion });\n if (!registration || registration.capability.kind !== \"rpc\") throw new Error(\"RPC capability registration disappeared\");\n const rpc = registration.capability as typeof registration.capability & { response: { parse(value: unknown): unknown }; transfer?: { response?: (value: unknown) => readonly Transferable[] } };\n const parsed = rpc.response.parse(value);\n const transfer = (rpc.transfer?.response?.(parsed) ?? []);\n return { value: parsed, transfer };\n },\n prepareItem: (value, call) => {\n const registration = host?.capabilities.registration({ kind: \"stream\", id: call.capabilityId, version: call.contractVersion });\n if (!registration || registration.capability.kind !== \"stream\") throw new Error(\"stream capability registration disappeared\");\n const stream = registration.capability as typeof registration.capability & { item: { parse(value: unknown): unknown }; transfer?: { item?: (value: unknown) => readonly Transferable[] } };\n const parsed = stream.item.parse(value);\n const transfer = stream.transfer?.item?.(parsed) ?? [];\n return { value: parsed, transfer };\n },\n });\n const endpoint: Endpoint = { port, scope: peerScope, binding, session, transport, bridge, provider, exposures, installTopLevelExposures, closed: false, revision: 0 };\n endpointForDisconnect = endpoint;\n endpoints.add(endpoint);\n emitPeerLifecycle({ event: \"active\", peerId, binding, state: \"active\" });\n // A remote RuntimeHandle may close the physical endpoint directly. The\n // bridge/provider session can acknowledge that close, but the Worker\n // still owns the peer controller and its domain exposure until the\n // endpoint registry is revoked. Route every terminal session transition\n // through the same local endpoint teardown so configurePeer owners\n // observe the physical peer as closed as well.\n session.onClosed(() => closeEndpoint(endpoint, \"Runtime endpoint closed\"));\n try {\n if (disconnectRequested !== undefined) closeEndpoint(endpoint, disconnectRequested);\n installTopLevelExposures();\n // Window and Worker may both publish the first snapshot. Incoming snapshots\n // are consumed only by the bridge; no hello/handshake control message exists.\n publish(endpoint);\n } catch (error) {\n closeEndpoint(endpoint, \"SharedWorker endpoint initialization failed\");\n throw error;\n }\n return endpoint;\n };\n\n const beginCloseEndpoint = (endpoint: Endpoint, reason: string): void => {\n if (endpoint.closed) return;\n // The peer is removed from admission and all exposures are revoked before\n // any asynchronous drain or physical MessagePort close begins.\n endpoint.closed = true;\n endpoints.delete(endpoint);\n endpoint.scope.revoke(reason);\n endpoint.provider.beginClose(reason);\n endpoint.bridge.beginClose(reason);\n emitPeerLifecycle({ event: \"closing\", peerId: endpoint.scope.identity.attributes.peerId as string, binding: endpoint.binding, state: \"closing\" });\n };\n\n const closeEndpoint = (endpoint: Endpoint, reason: string): Promise<void> => {\n if (endpoint.closePromise) return endpoint.closePromise;\n beginCloseEndpoint(endpoint, reason);\n endpoint.closePromise = (async () => {\n let providerDrain;\n let bridgeDrain;\n try {\n // Both drains are started only after the synchronous admission fence\n // above. The public app.dispose() promise includes this handshake.\n [providerDrain, bridgeDrain] = await Promise.all([endpoint.provider.drain(), endpoint.bridge.drain()]);\n } catch {\n providerDrain = { state: endpoint.session.state, drained: false, timedOut: true, pendingExecutions: endpoint.provider.executionCount() };\n bridgeDrain = { state: endpoint.session.state, drained: false, timedOut: true, pendingExecutions: endpoint.bridge.pendingCallCount + endpoint.bridge.activeStreamCount };\n }\n try {\n await endpoint.scope.dispose({ reason });\n } catch {\n // The endpoint's transport must still be closed when a domain cleanup\n // callback fails; the close event reports the bounded drain result.\n }\n endpoint.provider.dispose();\n endpoint.bridge.dispose(reason);\n endpoint.transport.close?.();\n endpoint.session.close();\n emitPeerLifecycle({ event: \"closed\", peerId: endpoint.scope.identity.attributes.peerId as string, binding: endpoint.binding, state: \"closed\", drain: bridgeDrain.drained && providerDrain.drained ? bridgeDrain : { ...bridgeDrain, drained: false, timedOut: bridgeDrain.timedOut || providerDrain.timedOut, pendingExecutions: Math.max(bridgeDrain.pendingExecutions, providerDrain.pendingExecutions) } });\n })();\n return endpoint.closePromise;\n };\n const sendTerminalSnapshot = (port: MessagePort): void => {\n try {\n port.start();\n const binding = createRuntimeEndpointBinding(runtimeInstanceId);\n port.postMessage({ ...localSnapshot(), type: RUNTIME_SNAPSHOT_TYPE, binding });\n // Give the posted terminal snapshot a turn to cross the port before\n // closing a connection made after the Worker Runtime has stopped.\n setTimeout(() => { try { port.close(); } catch { /* noop */ } }, 0);\n } catch { try { port.close(); } catch { /* noop */ } }\n };\n scope.onconnect = (event) => {\n for (const port of event.ports ?? []) {\n if (!accepting || disposed || endpoints.size >= limits.maxPeers) { sendTerminalSnapshot(port); continue; }\n try { createEndpoint(port); } catch { try { port.close(); } catch { /* noop */ } }\n }\n };\n\n try {\n const materialized = materializePluginDefinitions(options.plugins, \"shared-worker\");\n manifests = materialized.map((item) => item.manifest);\n const implementations = createRuntimeUnitImplementationRegistry(materialized.map((item) => ({ pluginId: item.manifest.id, unitId: item.unitId, setup: item.setup, capabilities: item.capabilities })));\n const { id: _id, plugins: _plugins, expose: _expose, configurePeer: _configurePeer, ...hostOptions } = options;\n host = createPluginHost({ ...hostOptions, runtime: \"shared-worker\", runtimeId: options.id, runtimeInstanceId, runtimeUnitImplementationRegistry: implementations });\n host.subscribe(() => { if (runtimeState === \"ready\" && !disposed) { revision += 1; publishAll(); } else emit(); });\n } catch (error) {\n runtimeState = \"failed\";\n const failure = new RuntimeInitializationError({ phase: \"validate\", error: message(error) });\n const failedReady = Promise.reject(failure);\n void failedReady.catch(() => undefined);\n const failedInspection = (): HostInspection => ({ runtimeId: options.id, runtimeKind: \"shared-worker\", runtimeInstanceId, version: 0, pluginCount: 0, peerCount: endpoints.size, pendingCallCount: 0, activeStreamCount: 0, plugins: [] });\n return { runtimeKind: \"shared-worker\", runtimeId: options.id, runtimeInstanceId, ready: () => failedReady, reconcile: async () => failedReady, state: localSnapshot, subscribe(listener) { listeners.add(listener); listener(localSnapshot()); return () => listeners.delete(listener); }, inspect: failedInspection, activePeers: () => Object.freeze([]), subscribePeerLifecycle(listener) { peerLifecycleListeners.add(listener); return () => peerLifecycleListeners.delete(listener); }, notifyPeerHandoff: () => false, dispose: async () => ({ scopeId: `runtime:${runtimeInstanceId}`, state: \"stopped\", attempted: 0, released: 0, pending: [], errors: [], cleanupIncomplete: false }) };\n }\n\n const ready = host.registerAll(manifests).then(() => {\n // A peer may have been connected before Host startup finished. Installing\n // the same top-level projection again is idempotent, while a configurePeer\n // collision remains an explicit error.\n for (const endpoint of endpoints) endpoint.installTopLevelExposures();\n if (!disposed) { runtimeState = \"ready\"; revision += 1; publishAll(); }\n }, (error) => { if (!disposed) { runtimeState = \"failed\"; publishAll(); } throw new RuntimeInitializationError({ phase: \"startup\", error: message(error) }); });\n void ready.catch(() => undefined);\n const app: SharedWorkerApp = {\n runtimeKind: \"shared-worker\", runtimeId: options.id, runtimeInstanceId,\n ready: () => ready,\n reconcile: () => host?.reconcile() ?? Promise.resolve(),\n state: localSnapshot,\n subscribe(listener) { listeners.add(listener); listener(localSnapshot()); return () => listeners.delete(listener); },\n inspect: () => host ? { ...host.inspect(), peerCount: endpoints.size } : { runtimeId: options.id, runtimeKind: \"shared-worker\", runtimeInstanceId, version: 0, pluginCount: 0, peerCount: endpoints.size, pendingCallCount: 0, activeStreamCount: 0, plugins: [] },\n activePeers: () => Object.freeze([...endpoints].filter((endpoint) => !endpoint.closed && endpoint.session.state === \"active\").map((endpoint) => Object.freeze({ event: \"active\" as const, peerId: endpoint.scope.identity.attributes.peerId as string, binding: Object.freeze({ ...endpoint.binding }), state: \"active\" as const }))),\n subscribePeerLifecycle(listener) { peerLifecycleListeners.add(listener); for (const endpoint of endpoints) if (!endpoint.closed && endpoint.session.state === \"active\") listener(Object.freeze({ event: \"active\" as const, peerId: endpoint.scope.identity.attributes.peerId as string, binding: Object.freeze({ ...endpoint.binding }), state: \"active\" as const })); return () => peerLifecycleListeners.delete(listener); },\n notifyPeerHandoff(peerId, handoffRevision) {\n const endpoint = [...endpoints].find((candidate) => !candidate.closed && candidate.scope.identity.attributes.peerId === peerId);\n if (!endpoint || endpoint.session.state !== \"active\") return false;\n emitPeerLifecycle({ event: \"handoff\", peerId, binding: endpoint.binding, state: \"active\", ...(handoffRevision !== undefined ? { handoffRevision } : {}) });\n return true;\n },\n dispose(reason = \"shared worker runtime disposed\") {\n if (disposePromise) return disposePromise;\n accepting = false;\n disposed = true;\n runtimeState = \"stopping\";\n // Capture before publishing the terminal snapshot: a synchronous\n // postMessage failure during publishAll may itself close an endpoint.\n const endpointsToClose = [...endpoints];\n publishAll();\n // Fence every currently connected endpoint synchronously before the\n // first await. This closes admission and revokes peer capabilities while\n // the Host is still alive, then waits for each bounded close handshake.\n for (const endpoint of endpointsToClose) beginCloseEndpoint(endpoint, reason);\n disposePromise = (async () => {\n const result = await (host ? host.dispose(reason) : Promise.resolve({ scopeId: `runtime:${runtimeInstanceId}`, state: \"stopped\" as const, attempted: 0, released: 0, pending: [], errors: [], cleanupIncomplete: false }));\n runtimeState = \"disposed\";\n const terminal = localSnapshot();\n options.snapshotObserver?.(terminal);\n // Endpoint admission is already fenced, but its transport stays alive\n // long enough for every Window to observe the terminal disposed\n // snapshot before the bounded close handshake tears it down.\n for (const endpoint of endpointsToClose) {\n try { publish(endpoint, endpoint.exposures, terminal, true); } catch { /* close path still proceeds */ }\n }\n emit(terminal);\n const endpointClosures = endpointsToClose.map((endpoint) => closeEndpoint(endpoint, reason));\n await Promise.all(endpointClosures);\n return result;\n })();\n return disposePromise;\n },\n };\n return app;\n}\n\n/** 生产入口:只从真实 SharedWorkerGlobalScope 获取连接事件。 */\nexport function startSharedWorkerApp(options: StartSharedWorkerAppOptions): SharedWorkerApp {\n return startSharedWorkerAppInternal(options);\n}\n\n/** testing/advanced harness 入口;生产包的 startSharedWorkerApp 不接受 scope 注入。 */\nexport function startSharedWorkerAppForTesting(options: StartSharedWorkerAppForTestingOptions): SharedWorkerApp {\n const { globalScope, ...runtimeOptions } = options;\n return startSharedWorkerAppInternal(runtimeOptions, globalScope);\n}\n"]}
|