@fluid-app/widget-runtime 0.1.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.
Files changed (46) hide show
  1. package/README.md +77 -0
  2. package/dist/Thread-0eUyc0Hw.cjs +591 -0
  3. package/dist/Thread-0eUyc0Hw.cjs.map +1 -0
  4. package/dist/Thread-BiW7rXts.mjs +574 -0
  5. package/dist/Thread-BiW7rXts.mjs.map +1 -0
  6. package/dist/index.cjs +6 -0
  7. package/dist/index.d.cts +3 -0
  8. package/dist/index.d.mts +3 -0
  9. package/dist/index.mjs +3 -0
  10. package/dist/remote-dom-renderer-BU-73KvK.d.mts +90 -0
  11. package/dist/remote-dom-renderer-BU-73KvK.d.mts.map +1 -0
  12. package/dist/remote-dom-renderer-DSHFetvm.d.cts +90 -0
  13. package/dist/remote-dom-renderer-DSHFetvm.d.cts.map +1 -0
  14. package/dist/remote-dom-renderer-DUQf80Nu.cjs +2116 -0
  15. package/dist/remote-dom-renderer-DUQf80Nu.cjs.map +1 -0
  16. package/dist/remote-dom-renderer-DcwcNPsu.mjs +2081 -0
  17. package/dist/remote-dom-renderer-DcwcNPsu.mjs.map +1 -0
  18. package/dist/remote-dom-values-BSAxrOE7.mjs +238 -0
  19. package/dist/remote-dom-values-BSAxrOE7.mjs.map +1 -0
  20. package/dist/remote-dom-values-D4AgBNWr.d.cts +32 -0
  21. package/dist/remote-dom-values-D4AgBNWr.d.cts.map +1 -0
  22. package/dist/remote-dom-values-DbgIedSg.cjs +297 -0
  23. package/dist/remote-dom-values-DbgIedSg.cjs.map +1 -0
  24. package/dist/remote-dom-values-EwoLXnSn.d.mts +32 -0
  25. package/dist/remote-dom-values-EwoLXnSn.d.mts.map +1 -0
  26. package/dist/remote-dom.cjs +6 -0
  27. package/dist/remote-dom.d.cts +3 -0
  28. package/dist/remote-dom.d.mts +3 -0
  29. package/dist/remote-dom.mjs +3 -0
  30. package/dist/worker-react-bootstrap-C7tCMYGA.mjs +13 -0
  31. package/dist/worker-react-bootstrap-C7tCMYGA.mjs.map +1 -0
  32. package/dist/worker-react-bootstrap-N8jcWZ3L.cjs +13 -0
  33. package/dist/worker-react-bootstrap-N8jcWZ3L.cjs.map +1 -0
  34. package/dist/worker-react-renderer-BKzig_Vy.mjs +185 -0
  35. package/dist/worker-react-renderer-BKzig_Vy.mjs.map +1 -0
  36. package/dist/worker-react-renderer-BSFxMMf7.cjs +186 -0
  37. package/dist/worker-react-renderer-BSFxMMf7.cjs.map +1 -0
  38. package/dist/worker.cjs +325 -0
  39. package/dist/worker.cjs.map +1 -0
  40. package/dist/worker.d.cts +46 -0
  41. package/dist/worker.d.cts.map +1 -0
  42. package/dist/worker.d.mts +46 -0
  43. package/dist/worker.d.mts.map +1 -0
  44. package/dist/worker.mjs +319 -0
  45. package/dist/worker.mjs.map +1 -0
  46. package/package.json +68 -0
@@ -0,0 +1,319 @@
1
+ import { n as release, r as retain, t as Thread } from "./Thread-BiW7rXts.mjs";
2
+ import { c as isRemoteDomSerializableValue } from "./remote-dom-values-BSAxrOE7.mjs";
3
+ import { createContext, createElement, useContext, useMemo } from "react";
4
+ //#region src/worker-lockdown.ts
5
+ const DISALLOWED_GLOBAL_NAMES = [
6
+ "fetch",
7
+ "XMLHttpRequest",
8
+ "WebSocket",
9
+ "EventSource",
10
+ "WebSocketStream",
11
+ "WebTransport",
12
+ "RTCPeerConnection",
13
+ "importScripts",
14
+ "localStorage",
15
+ "sessionStorage",
16
+ "indexedDB",
17
+ "caches",
18
+ "BroadcastChannel",
19
+ "Worker",
20
+ "SharedWorker",
21
+ "ShadowRealm"
22
+ ];
23
+ function lockdownRemoteDomWorkerGlobals(options = {}) {
24
+ const globals = options.globals ?? globalThis;
25
+ const mode = options.mode ?? "throw";
26
+ const lockedGlobals = [];
27
+ const failedGlobals = [];
28
+ for (const name of DISALLOWED_GLOBAL_NAMES) if (lockdownGlobal(globals, name, mode)) lockedGlobals.push(name);
29
+ else failedGlobals.push(name);
30
+ return {
31
+ lockedGlobals,
32
+ failedGlobals
33
+ };
34
+ }
35
+ function lockdownGlobal(globals, name, mode) {
36
+ const replacement = mode === "throw" ? createFailClosedGlobal(name) : void 0;
37
+ try {
38
+ Object.defineProperty(globals, name, {
39
+ configurable: false,
40
+ enumerable: false,
41
+ value: replacement,
42
+ writable: false
43
+ });
44
+ return true;
45
+ } catch {
46
+ try {
47
+ delete globals[name];
48
+ return !(name in globals);
49
+ } catch {
50
+ return false;
51
+ }
52
+ }
53
+ }
54
+ function createFailClosedGlobal(name) {
55
+ return function failClosedGlobal() {
56
+ throw new Error(`Remote DOM worker global ${name} is unavailable.`);
57
+ };
58
+ }
59
+ //#endregion
60
+ //#region src/worker-capability-function.ts
61
+ var RemoteDomCapabilityFunctionError = class extends Error {
62
+ name = "RemoteDomCapabilityFunctionError";
63
+ code;
64
+ constructor(code, message) {
65
+ super(message);
66
+ this.code = code;
67
+ }
68
+ };
69
+ const REMOTE_DOM_CAPABILITY_FUNCTION_METADATA = Symbol("fluid.remote-dom-capability-function-metadata");
70
+ let activeCapabilitySession;
71
+ function defineRemoteDomCapabilityFunction(metadata) {
72
+ assertMetadataPart(metadata.capability, "capability");
73
+ assertMetadataPart(metadata.version, "version");
74
+ assertMetadataPart(metadata.method, "method");
75
+ const stableMetadata = { ...metadata };
76
+ const capabilityFunction = async (...args) => {
77
+ const [input] = args;
78
+ const session = activeCapabilitySession;
79
+ if (!session) throw new RemoteDomCapabilityFunctionError("NOT_MOUNTED", `Capability function "${stableMetadata.capability}.${stableMetadata.method}" can only be called while a Remote DOM widget is mounted.`);
80
+ if (!session.declarations.some(({ capability, version, method }) => capability === stableMetadata.capability && method === stableMetadata.method && version === stableMetadata.version)) throw new RemoteDomCapabilityFunctionError("NOT_DECLARED", `Capability "${stableMetadata.capability}" version "${stableMetadata.version}" is not declared for widget "${session.widgetType}". Add this function to defineWidget({ uses: [...] }).`);
81
+ if (args.length > 1 || args.length === 1 && (input === void 0 || !isRemoteDomSerializableValue(input))) throw new RemoteDomCapabilityFunctionError("INVALID_ARGUMENT", `Capability function "${stableMetadata.capability}.${stableMetadata.method}" received an argument that is not JSON-serializable.`);
82
+ const response = await session.callCapability(stableMetadata.capability, stableMetadata.method, input);
83
+ if (!isRemoteDomSerializableValue(response)) throw new RemoteDomCapabilityFunctionError("INVALID_RESPONSE", `Capability function "${stableMetadata.capability}.${stableMetadata.method}" received a host response that is not JSON-serializable.`);
84
+ return response;
85
+ };
86
+ Object.defineProperty(capabilityFunction, REMOTE_DOM_CAPABILITY_FUNCTION_METADATA, { value: stableMetadata });
87
+ return capabilityFunction;
88
+ }
89
+ function getRemoteDomCapabilityFunctionMetadata(value) {
90
+ if (typeof value !== "function") return void 0;
91
+ const metadata = Object.getOwnPropertyDescriptor(value, REMOTE_DOM_CAPABILITY_FUNCTION_METADATA)?.value;
92
+ if (!isRemoteDomCapabilityFunctionMetadata(metadata)) return void 0;
93
+ return { ...metadata };
94
+ }
95
+ /** @internal Used by the worker lifecycle to scope direct capability calls. */
96
+ function bindRemoteDomCapabilitySession(session) {
97
+ if (activeCapabilitySession) throw new Error("A Remote DOM capability session is already active.");
98
+ activeCapabilitySession = session;
99
+ return () => {
100
+ if (activeCapabilitySession === session) activeCapabilitySession = void 0;
101
+ };
102
+ }
103
+ function isRemoteDomCapabilityFunctionMetadata(value) {
104
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return false;
105
+ return "capability" in value && typeof value.capability === "string" && value.capability.length > 0 && "version" in value && typeof value.version === "string" && value.version.length > 0 && "method" in value && typeof value.method === "string" && value.method.length > 0;
106
+ }
107
+ function assertMetadataPart(value, part) {
108
+ if (value.length === 0) throw new Error(`Remote DOM capability function ${part} cannot be empty.`);
109
+ }
110
+ //#endregion
111
+ //#region src/worker-runtime.ts
112
+ const RemoteDomCapabilityContext = createContext(void 0);
113
+ let remoteDomReactWorkerRendererModulePromise;
114
+ function useRemoteDomCapability(name) {
115
+ const callCapability = useContext(RemoteDomCapabilityContext);
116
+ if (!callCapability) throw new Error("useRemoteDomCapability must be used inside a Remote DOM widget.");
117
+ if (name.length === 0) throw new Error("Remote DOM capability names cannot be empty.");
118
+ return useMemo(() => ({ call(method, payload) {
119
+ if (method.length === 0) return Promise.reject(/* @__PURE__ */ new Error("Remote DOM capability method names cannot be empty."));
120
+ if (payload !== void 0 && !isRemoteDomSerializableValue(payload)) return Promise.reject(/* @__PURE__ */ new Error("Remote DOM capability payload must be serializable."));
121
+ return callCapability(name, method, payload);
122
+ } }), [callCapability, name]);
123
+ }
124
+ function startRemoteDomWidgetWorker(options) {
125
+ return startRemoteDomWidgetWorkerInternal(options);
126
+ }
127
+ function startRemoteDomWidgetWorkerInternal(options, testEnvironment) {
128
+ const workerSelf = testEnvironment?.self ?? readGlobalWorkerSelf();
129
+ if (testEnvironment?.disableLockdown !== true) {
130
+ const lockdownResult = lockdownRemoteDomWorkerGlobals({ globals: testEnvironment?.lockdownGlobals });
131
+ if (lockdownResult.failedGlobals.length > 0) failClosedWorker(workerSelf, lockdownResult);
132
+ }
133
+ let disposed = false;
134
+ let mounted = false;
135
+ let renderer;
136
+ let host;
137
+ let props;
138
+ let widget;
139
+ let clearCapabilitySession;
140
+ const render = () => {
141
+ assertWorkerActive(disposed);
142
+ if (!mounted || !renderer || !host || !widget || props === void 0) throw new Error("Remote DOM widget worker has not been mounted.");
143
+ const currentHost = host;
144
+ const node = createElement(widget, toComponentProps(props));
145
+ renderer.render(createElement(RemoteDomCapabilityContext.Provider, { value: (capability, method, payload) => currentHost.callCapability(capability, method, payload) }, node));
146
+ };
147
+ const disposeMount = () => {
148
+ if (!mounted && !renderer && !host && !clearCapabilitySession) return;
149
+ const mountedRenderer = renderer;
150
+ const retainedHost = host;
151
+ const clearMountedCapabilitySession = clearCapabilitySession;
152
+ renderer = void 0;
153
+ host = void 0;
154
+ props = void 0;
155
+ widget = void 0;
156
+ clearCapabilitySession = void 0;
157
+ mounted = false;
158
+ const errors = [];
159
+ try {
160
+ clearMountedCapabilitySession?.();
161
+ } catch (error) {
162
+ errors.push(error);
163
+ }
164
+ try {
165
+ mountedRenderer?.dispose();
166
+ } catch (error) {
167
+ errors.push(error);
168
+ }
169
+ if (retainedHost) try {
170
+ release(retainedHost);
171
+ } catch (error) {
172
+ errors.push(error);
173
+ }
174
+ if (errors.length > 0) throw new AggregateError(errors, "Remote DOM widget worker cleanup failed.");
175
+ };
176
+ const thread = new Thread(toThreadMessageTarget(workerSelf), { exports: {
177
+ async mount(init, nextHost) {
178
+ assertWorkerActive(disposed);
179
+ if (mounted || renderer || host) throw new Error("Remote DOM widget worker is already mounted.");
180
+ if (init.widgetType.length === 0) throw new Error("Remote DOM widget type cannot be empty.");
181
+ if (!isRemoteDomSerializableValue(init.props)) throw new Error("Remote DOM widget props must be serializable.");
182
+ const selectedEntry = options.widgets[init.widgetType];
183
+ if (!selectedEntry) throw new Error(`Remote DOM worker does not contain widget type ${init.widgetType}.`);
184
+ const selectedWidget = normalizeWidgetEntry(selectedEntry);
185
+ try {
186
+ retain(nextHost);
187
+ host = nextHost;
188
+ props = init.props;
189
+ widget = selectedWidget.component;
190
+ clearCapabilitySession = bindRemoteDomCapabilitySession({
191
+ widgetType: init.widgetType,
192
+ declarations: selectedWidget.functions ?? [],
193
+ callCapability: (capability, method, payload) => nextHost.callCapability(capability, method, payload)
194
+ });
195
+ mounted = true;
196
+ const rendererModule = await loadRemoteDomWorkerReactRendererModule();
197
+ assertWorkerActive(disposed);
198
+ renderer = rendererModule.createRemoteDomReactWorkerRenderer({ connection: {
199
+ mutate(records) {
200
+ Promise.resolve(nextHost.mutate(records)).catch(() => void 0);
201
+ },
202
+ call() {
203
+ throw new Error("Remote DOM worker widgets cannot invoke host element methods.");
204
+ }
205
+ } });
206
+ render();
207
+ } catch (error) {
208
+ reportWorkerError(nextHost, error, "Remote DOM widget mount failed.");
209
+ try {
210
+ disposeMount();
211
+ } catch (cleanupError) {
212
+ reportWorkerError(nextHost, cleanupError, "Remote DOM widget cleanup failed.");
213
+ }
214
+ throw error;
215
+ }
216
+ },
217
+ async updateProps(nextProps) {
218
+ assertWorkerActive(disposed);
219
+ if (!mounted) throw new Error("Remote DOM widget worker has not been mounted.");
220
+ if (!isRemoteDomSerializableValue(nextProps)) throw new Error("Remote DOM widget props must be serializable.");
221
+ props = nextProps;
222
+ try {
223
+ render();
224
+ } catch (error) {
225
+ if (host) reportWorkerError(host, error, "Remote DOM widget render failed.");
226
+ throw error;
227
+ }
228
+ },
229
+ async dispose() {
230
+ disposeMount();
231
+ }
232
+ } });
233
+ return { dispose() {
234
+ if (disposed) return;
235
+ disposed = true;
236
+ const errors = [];
237
+ try {
238
+ disposeMount();
239
+ } catch (error) {
240
+ errors.push(error);
241
+ }
242
+ try {
243
+ thread.close();
244
+ } catch (error) {
245
+ errors.push(error);
246
+ }
247
+ try {
248
+ workerSelf.onmessage = null;
249
+ } catch (error) {
250
+ errors.push(error);
251
+ }
252
+ if (errors.length > 0) throw new AggregateError(errors, "Remote DOM widget worker shutdown failed.");
253
+ } };
254
+ }
255
+ function normalizeWidgetEntry(entry) {
256
+ if (typeof entry === "function") return {
257
+ component: entry,
258
+ capabilities: []
259
+ };
260
+ return entry;
261
+ }
262
+ function toComponentProps(props) {
263
+ return isObjectRecord(props) ? props : { value: props };
264
+ }
265
+ function assertWorkerActive(disposed) {
266
+ if (disposed) throw new Error("Remote DOM widget worker has been disposed.");
267
+ }
268
+ function loadRemoteDomWorkerReactRendererModule() {
269
+ if (!remoteDomReactWorkerRendererModulePromise) remoteDomReactWorkerRendererModulePromise = (async () => {
270
+ await import("./worker-react-bootstrap-C7tCMYGA.mjs");
271
+ return import("./worker-react-renderer-BKzig_Vy.mjs");
272
+ })().catch((error) => {
273
+ remoteDomReactWorkerRendererModulePromise = void 0;
274
+ throw error;
275
+ });
276
+ return remoteDomReactWorkerRendererModulePromise;
277
+ }
278
+ function reportWorkerError(host, error, fallbackMessage) {
279
+ try {
280
+ host.reportError({ message: error instanceof Error ? error.message : fallbackMessage });
281
+ } catch {}
282
+ }
283
+ function failClosedWorker(workerSelf, result) {
284
+ try {
285
+ workerSelf.onmessage = null;
286
+ } catch {}
287
+ workerSelf.close?.();
288
+ throw new Error(`Remote DOM worker lockdown failed for globals: ${result.failedGlobals.join(", ")}.`);
289
+ }
290
+ function readGlobalWorkerSelf() {
291
+ const candidate = globalThis;
292
+ if (typeof candidate.postMessage !== "function") throw new Error("Remote DOM widget runtime requires a Worker global scope.");
293
+ if (candidate.onmessage === void 0) candidate.onmessage = null;
294
+ return candidate;
295
+ }
296
+ function toThreadMessageTarget(scope) {
297
+ return {
298
+ send(message, transferables) {
299
+ scope.postMessage(message, transferables ?? []);
300
+ },
301
+ listen(listener, { signal }) {
302
+ if (scope.addEventListener) {
303
+ scope.addEventListener("message", (event) => listener(event.data), { signal });
304
+ return;
305
+ }
306
+ scope.onmessage = (event) => listener(event.data);
307
+ signal?.addEventListener("abort", () => {
308
+ scope.onmessage = null;
309
+ }, { once: true });
310
+ }
311
+ };
312
+ }
313
+ function isObjectRecord(value) {
314
+ return typeof value === "object" && value !== null && !Array.isArray(value);
315
+ }
316
+ //#endregion
317
+ export { RemoteDomCapabilityFunctionError, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, startRemoteDomWidgetWorker, useRemoteDomCapability };
318
+
319
+ //# sourceMappingURL=worker.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker.mjs","names":[],"sources":["../src/worker-lockdown.ts","../src/worker-capability-function.ts","../src/worker-runtime.ts"],"sourcesContent":["export interface RemoteDomWorkerLockdownOptions {\n readonly globals?: object | undefined;\n readonly mode?: \"throw\" | \"undefined\" | undefined;\n}\n\nexport interface RemoteDomWorkerLockdownResult {\n readonly lockedGlobals: readonly string[];\n readonly failedGlobals: readonly string[];\n}\n\nconst DISALLOWED_GLOBAL_NAMES = [\n \"fetch\",\n \"XMLHttpRequest\",\n \"WebSocket\",\n \"EventSource\",\n \"WebSocketStream\",\n \"WebTransport\",\n \"RTCPeerConnection\",\n \"importScripts\",\n \"localStorage\",\n \"sessionStorage\",\n \"indexedDB\",\n \"caches\",\n \"BroadcastChannel\",\n \"Worker\",\n \"SharedWorker\",\n \"ShadowRealm\",\n] as const;\n\nexport function lockdownRemoteDomWorkerGlobals(\n options: RemoteDomWorkerLockdownOptions = {},\n): RemoteDomWorkerLockdownResult {\n const globals = options.globals ?? globalThis;\n const mode = options.mode ?? \"throw\";\n const lockedGlobals: string[] = [];\n const failedGlobals: string[] = [];\n\n for (const name of DISALLOWED_GLOBAL_NAMES) {\n if (lockdownGlobal(globals, name, mode)) {\n lockedGlobals.push(name);\n } else {\n failedGlobals.push(name);\n }\n }\n\n return { lockedGlobals, failedGlobals };\n}\n\nfunction lockdownGlobal(\n globals: object,\n name: string,\n mode: \"throw\" | \"undefined\",\n): boolean {\n const replacement =\n mode === \"throw\" ? createFailClosedGlobal(name) : undefined;\n\n try {\n Object.defineProperty(globals, name, {\n configurable: false,\n enumerable: false,\n value: replacement,\n writable: false,\n });\n return true;\n } catch {\n try {\n delete (globals as Record<string, unknown>)[name];\n return !(name in globals);\n } catch {\n return false;\n }\n }\n}\n\nfunction createFailClosedGlobal(name: string): () => never {\n return function failClosedGlobal(): never {\n throw new Error(`Remote DOM worker global ${name} is unavailable.`);\n };\n}\n","import { isRemoteDomSerializableValue } from \"./remote-dom-values\";\nimport type { RemoteDomSerializableValue } from \"./remote-dom-values\";\n\nexport interface RemoteDomCapabilityDeclaration {\n readonly name: string;\n readonly version: string;\n}\n\nexport interface RemoteDomCapabilityFunctionMetadata {\n readonly capability: string;\n readonly version: string;\n readonly method: string;\n}\n\nexport type RemoteDomCapabilityFunctionErrorCode =\n | \"NOT_MOUNTED\"\n | \"NOT_DECLARED\"\n | \"INVALID_ARGUMENT\"\n | \"INVALID_RESPONSE\";\n\nexport class RemoteDomCapabilityFunctionError extends Error {\n override readonly name = \"RemoteDomCapabilityFunctionError\";\n readonly code: RemoteDomCapabilityFunctionErrorCode;\n\n constructor(code: RemoteDomCapabilityFunctionErrorCode, message: string) {\n super(message);\n this.code = code;\n }\n}\n\nexport type RemoteDomCapabilityFunction<\n Output extends RemoteDomSerializableValue,\n Input extends RemoteDomSerializableValue | void = void,\n> = [Input] extends [void]\n ? () => Promise<Output>\n : (input: Input) => Promise<Output>;\n\ninterface RemoteDomCapabilitySession {\n readonly widgetType: string;\n readonly declarations: readonly RemoteDomCapabilityFunctionMetadata[];\n readonly callCapability: (\n capability: string,\n method: string,\n payload?: RemoteDomSerializableValue,\n ) => Promise<RemoteDomSerializableValue>;\n}\n\nconst REMOTE_DOM_CAPABILITY_FUNCTION_METADATA = Symbol(\n \"fluid.remote-dom-capability-function-metadata\",\n);\n\nlet activeCapabilitySession: RemoteDomCapabilitySession | undefined;\n\nexport function defineRemoteDomCapabilityFunction<\n Output extends RemoteDomSerializableValue,\n Input extends RemoteDomSerializableValue | void = void,\n>(\n metadata: RemoteDomCapabilityFunctionMetadata,\n): RemoteDomCapabilityFunction<Output, Input> {\n assertMetadataPart(metadata.capability, \"capability\");\n assertMetadataPart(metadata.version, \"version\");\n assertMetadataPart(metadata.method, \"method\");\n\n const stableMetadata = { ...metadata };\n const capabilityFunction = async (\n ...args: readonly (RemoteDomSerializableValue | undefined)[]\n ): Promise<Output> => {\n const [input] = args;\n const session = activeCapabilitySession;\n if (!session) {\n throw new RemoteDomCapabilityFunctionError(\n \"NOT_MOUNTED\",\n `Capability function \"${stableMetadata.capability}.${stableMetadata.method}\" can only be called while a Remote DOM widget is mounted.`,\n );\n }\n\n const isDeclared = session.declarations.some(\n ({ capability, version, method }) =>\n capability === stableMetadata.capability &&\n method === stableMetadata.method &&\n version === stableMetadata.version,\n );\n if (!isDeclared) {\n throw new RemoteDomCapabilityFunctionError(\n \"NOT_DECLARED\",\n `Capability \"${stableMetadata.capability}\" version \"${stableMetadata.version}\" is not declared for widget \"${session.widgetType}\". Add this function to defineWidget({ uses: [...] }).`,\n );\n }\n\n if (\n args.length > 1 ||\n (args.length === 1 &&\n (input === undefined || !isRemoteDomSerializableValue(input)))\n ) {\n throw new RemoteDomCapabilityFunctionError(\n \"INVALID_ARGUMENT\",\n `Capability function \"${stableMetadata.capability}.${stableMetadata.method}\" received an argument that is not JSON-serializable.`,\n );\n }\n\n const response = await session.callCapability(\n stableMetadata.capability,\n stableMetadata.method,\n input,\n );\n if (!isRemoteDomSerializableValue(response)) {\n throw new RemoteDomCapabilityFunctionError(\n \"INVALID_RESPONSE\",\n `Capability function \"${stableMetadata.capability}.${stableMetadata.method}\" received a host response that is not JSON-serializable.`,\n );\n }\n\n return response as Output;\n };\n\n Object.defineProperty(\n capabilityFunction,\n REMOTE_DOM_CAPABILITY_FUNCTION_METADATA,\n {\n value: stableMetadata,\n },\n );\n\n return capabilityFunction as RemoteDomCapabilityFunction<Output, Input>;\n}\n\nexport function getRemoteDomCapabilityFunctionMetadata(\n value: unknown,\n): RemoteDomCapabilityFunctionMetadata | undefined {\n if (typeof value !== \"function\") return undefined;\n\n const descriptor = Object.getOwnPropertyDescriptor(\n value,\n REMOTE_DOM_CAPABILITY_FUNCTION_METADATA,\n );\n const metadata = descriptor?.value;\n if (!isRemoteDomCapabilityFunctionMetadata(metadata)) return undefined;\n\n return { ...metadata };\n}\n\n/** @internal Used by the worker lifecycle to scope direct capability calls. */\nexport function bindRemoteDomCapabilitySession(\n session: RemoteDomCapabilitySession,\n): () => void {\n if (activeCapabilitySession) {\n throw new Error(\"A Remote DOM capability session is already active.\");\n }\n\n activeCapabilitySession = session;\n return () => {\n if (activeCapabilitySession === session) {\n activeCapabilitySession = undefined;\n }\n };\n}\n\nfunction isRemoteDomCapabilityFunctionMetadata(\n value: unknown,\n): value is RemoteDomCapabilityFunctionMetadata {\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n return false;\n }\n\n return (\n \"capability\" in value &&\n typeof value.capability === \"string\" &&\n value.capability.length > 0 &&\n \"version\" in value &&\n typeof value.version === \"string\" &&\n value.version.length > 0 &&\n \"method\" in value &&\n typeof value.method === \"string\" &&\n value.method.length > 0\n );\n}\n\nfunction assertMetadataPart(value: string, part: string): void {\n if (value.length === 0) {\n throw new Error(`Remote DOM capability function ${part} cannot be empty.`);\n }\n}\n","import { release, retain, Thread } from \"@quilted/threads\";\nimport type { ThreadMessageTarget } from \"@quilted/threads\";\nimport type { RemoteMutationRecord } from \"@remote-dom/core\";\nimport type { RemoteConnection } from \"@remote-dom/core/elements\";\nimport {\n createContext,\n createElement,\n useContext,\n useMemo,\n type ComponentType,\n} from \"react\";\n\nimport { isRemoteDomSerializableValue } from \"./remote-dom-values\";\nimport type { RemoteDomSerializableValue } from \"./remote-dom-values\";\nimport { lockdownRemoteDomWorkerGlobals } from \"./worker-lockdown\";\nimport type { RemoteDomWorkerLockdownResult } from \"./worker-lockdown\";\nimport { bindRemoteDomCapabilitySession } from \"./worker-capability-function\";\nimport type {\n RemoteDomCapabilityDeclaration,\n RemoteDomCapabilityFunctionMetadata,\n} from \"./worker-capability-function\";\n\ntype RemoteDomReactWorkerRendererModule =\n typeof import(\"./worker-react-renderer\");\n\nexport interface RemoteDomWorkerGlobalScopeLike {\n onmessage: ((event: MessageEvent<unknown>) => void) | null;\n postMessage(message: unknown, transfer?: Transferable[]): void;\n addEventListener?: (\n type: \"message\",\n listener: (event: MessageEvent<unknown>) => void,\n options?: { signal?: AbortSignal },\n ) => void;\n close?: () => void;\n}\n\nexport interface RemoteDomWidgetWorkerHostApi {\n mutate(records: readonly RemoteMutationRecord[]): void;\n callCapability(\n capability: string,\n method: string,\n payload?: RemoteDomSerializableValue,\n ): Promise<RemoteDomSerializableValue>;\n reportError(error: { readonly message: string }): void;\n}\n\nexport interface RemoteDomWidgetWorkerMountOptions {\n readonly widgetType: string;\n readonly props: RemoteDomSerializableValue;\n}\n\nexport interface RemoteDomWidgetWorkerApi {\n mount(\n options: RemoteDomWidgetWorkerMountOptions,\n host: RemoteDomWidgetWorkerHostApi,\n ): Promise<void>;\n updateProps(props: RemoteDomSerializableValue): Promise<void>;\n dispose(): Promise<void>;\n}\n\ntype RemoteDomWidgetComponent = ComponentType<\n Readonly<Record<string, unknown>>\n>;\n\nexport interface RemoteDomWidgetWorkerDefinition {\n readonly component: RemoteDomWidgetComponent;\n readonly capabilities: readonly RemoteDomCapabilityDeclaration[];\n /** @internal Exact functions authorized for direct worker calls. */\n readonly functions?: readonly RemoteDomCapabilityFunctionMetadata[];\n}\n\nexport type RemoteDomWidgetWorkerEntry =\n | RemoteDomWidgetComponent\n | RemoteDomWidgetWorkerDefinition;\n\nexport interface RemoteDomWidgetWorkerOptions {\n readonly widgets: Readonly<Record<string, RemoteDomWidgetWorkerEntry>>;\n}\n\ninterface RemoteDomWidgetWorkerTestEnvironment {\n readonly self: RemoteDomWorkerGlobalScopeLike;\n readonly disableLockdown?: boolean;\n readonly lockdownGlobals?: object;\n}\n\nexport interface RemoteDomWidgetWorkerController {\n dispose(): void;\n}\n\nexport interface RemoteDomCapability {\n call(\n method: string,\n payload?: RemoteDomSerializableValue,\n ): Promise<RemoteDomSerializableValue>;\n}\n\ntype CallCapability = RemoteDomWidgetWorkerHostApi[\"callCapability\"];\n\nconst RemoteDomCapabilityContext = createContext<CallCapability | undefined>(\n undefined,\n);\n\nlet remoteDomReactWorkerRendererModulePromise:\n | Promise<RemoteDomReactWorkerRendererModule>\n | undefined;\n\nexport function useRemoteDomCapability(name: string): RemoteDomCapability {\n const callCapability = useContext(RemoteDomCapabilityContext);\n if (!callCapability) {\n throw new Error(\n \"useRemoteDomCapability must be used inside a Remote DOM widget.\",\n );\n }\n if (name.length === 0) {\n throw new Error(\"Remote DOM capability names cannot be empty.\");\n }\n\n return useMemo(\n () => ({\n call(method: string, payload?: RemoteDomSerializableValue) {\n if (method.length === 0) {\n return Promise.reject(\n new Error(\"Remote DOM capability method names cannot be empty.\"),\n );\n }\n if (payload !== undefined && !isRemoteDomSerializableValue(payload)) {\n return Promise.reject(\n new Error(\"Remote DOM capability payload must be serializable.\"),\n );\n }\n return callCapability(name, method, payload);\n },\n }),\n [callCapability, name],\n );\n}\n\nexport function startRemoteDomWidgetWorker(\n options: RemoteDomWidgetWorkerOptions,\n): RemoteDomWidgetWorkerController {\n return startRemoteDomWidgetWorkerInternal(options);\n}\n\n/** @internal Test-only injection; not exported from the package worker entry. */\nexport function startRemoteDomWidgetWorkerForTest(\n options: RemoteDomWidgetWorkerOptions,\n environment: RemoteDomWidgetWorkerTestEnvironment,\n): RemoteDomWidgetWorkerController {\n return startRemoteDomWidgetWorkerInternal(options, environment);\n}\n\nfunction startRemoteDomWidgetWorkerInternal(\n options: RemoteDomWidgetWorkerOptions,\n testEnvironment?: RemoteDomWidgetWorkerTestEnvironment,\n): RemoteDomWidgetWorkerController {\n const workerSelf = testEnvironment?.self ?? readGlobalWorkerSelf();\n\n if (testEnvironment?.disableLockdown !== true) {\n const lockdownResult = lockdownRemoteDomWorkerGlobals({\n globals: testEnvironment?.lockdownGlobals,\n });\n if (lockdownResult.failedGlobals.length > 0) {\n failClosedWorker(workerSelf, lockdownResult);\n }\n }\n\n let disposed = false;\n let mounted = false;\n let renderer:\n | ReturnType<\n RemoteDomReactWorkerRendererModule[\"createRemoteDomReactWorkerRenderer\"]\n >\n | undefined;\n let host: RemoteDomWidgetWorkerHostApi | undefined;\n let props: RemoteDomSerializableValue | undefined;\n let widget: RemoteDomWidgetComponent | undefined;\n let clearCapabilitySession: (() => void) | undefined;\n\n const render = (): void => {\n assertWorkerActive(disposed);\n if (!mounted || !renderer || !host || !widget || props === undefined) {\n throw new Error(\"Remote DOM widget worker has not been mounted.\");\n }\n\n const currentHost = host;\n const currentWidget = widget;\n const node = createElement(currentWidget, toComponentProps(props));\n renderer.render(\n createElement(\n RemoteDomCapabilityContext.Provider,\n {\n value: (capability, method, payload) =>\n currentHost.callCapability(capability, method, payload),\n },\n node,\n ),\n );\n };\n\n const disposeMount = (): void => {\n if (!mounted && !renderer && !host && !clearCapabilitySession) return;\n\n const mountedRenderer = renderer;\n const retainedHost = host;\n const clearMountedCapabilitySession = clearCapabilitySession;\n renderer = undefined;\n host = undefined;\n props = undefined;\n widget = undefined;\n clearCapabilitySession = undefined;\n mounted = false;\n\n const errors: unknown[] = [];\n try {\n clearMountedCapabilitySession?.();\n } catch (error) {\n errors.push(error);\n }\n try {\n mountedRenderer?.dispose();\n } catch (error) {\n errors.push(error);\n }\n if (retainedHost) {\n try {\n release(retainedHost);\n } catch (error) {\n errors.push(error);\n }\n }\n if (errors.length > 0) {\n throw new AggregateError(\n errors,\n \"Remote DOM widget worker cleanup failed.\",\n );\n }\n };\n\n const workerApi: RemoteDomWidgetWorkerApi = {\n async mount(init, nextHost) {\n assertWorkerActive(disposed);\n if (mounted || renderer || host) {\n throw new Error(\"Remote DOM widget worker is already mounted.\");\n }\n if (init.widgetType.length === 0) {\n throw new Error(\"Remote DOM widget type cannot be empty.\");\n }\n if (!isRemoteDomSerializableValue(init.props)) {\n throw new Error(\"Remote DOM widget props must be serializable.\");\n }\n\n const selectedEntry = options.widgets[init.widgetType];\n if (!selectedEntry) {\n throw new Error(\n `Remote DOM worker does not contain widget type ${init.widgetType}.`,\n );\n }\n const selectedWidget = normalizeWidgetEntry(selectedEntry);\n\n try {\n retain(nextHost);\n host = nextHost;\n props = init.props;\n widget = selectedWidget.component;\n clearCapabilitySession = bindRemoteDomCapabilitySession({\n widgetType: init.widgetType,\n declarations: selectedWidget.functions ?? [],\n callCapability: (capability, method, payload) =>\n nextHost.callCapability(capability, method, payload),\n });\n mounted = true;\n\n const rendererModule = await loadRemoteDomWorkerReactRendererModule();\n assertWorkerActive(disposed);\n const connection: RemoteConnection = {\n mutate(records) {\n void Promise.resolve(nextHost.mutate(records)).catch(\n () => undefined,\n );\n },\n call() {\n throw new Error(\n \"Remote DOM worker widgets cannot invoke host element methods.\",\n );\n },\n };\n renderer = rendererModule.createRemoteDomReactWorkerRenderer({\n connection,\n });\n render();\n } catch (error) {\n reportWorkerError(nextHost, error, \"Remote DOM widget mount failed.\");\n try {\n disposeMount();\n } catch (cleanupError) {\n reportWorkerError(\n nextHost,\n cleanupError,\n \"Remote DOM widget cleanup failed.\",\n );\n }\n throw error;\n }\n },\n async updateProps(nextProps) {\n assertWorkerActive(disposed);\n if (!mounted) {\n throw new Error(\"Remote DOM widget worker has not been mounted.\");\n }\n if (!isRemoteDomSerializableValue(nextProps)) {\n throw new Error(\"Remote DOM widget props must be serializable.\");\n }\n\n props = nextProps;\n try {\n render();\n } catch (error) {\n if (host) {\n reportWorkerError(host, error, \"Remote DOM widget render failed.\");\n }\n throw error;\n }\n },\n async dispose() {\n disposeMount();\n },\n };\n\n const thread = new Thread<Record<string, never>, RemoteDomWidgetWorkerApi>(\n toThreadMessageTarget(workerSelf),\n { exports: workerApi },\n );\n\n return {\n dispose() {\n if (disposed) return;\n disposed = true;\n const errors: unknown[] = [];\n try {\n disposeMount();\n } catch (error) {\n errors.push(error);\n }\n try {\n thread.close();\n } catch (error) {\n errors.push(error);\n }\n try {\n workerSelf.onmessage = null;\n } catch (error) {\n errors.push(error);\n }\n if (errors.length > 0) {\n throw new AggregateError(\n errors,\n \"Remote DOM widget worker shutdown failed.\",\n );\n }\n },\n };\n}\n\nfunction normalizeWidgetEntry(\n entry: RemoteDomWidgetWorkerEntry,\n): RemoteDomWidgetWorkerDefinition {\n if (typeof entry === \"function\") {\n return { component: entry, capabilities: [] };\n }\n\n return entry;\n}\n\nfunction toComponentProps(\n props: RemoteDomSerializableValue,\n): Readonly<Record<string, unknown>> {\n return isObjectRecord(props) ? props : { value: props };\n}\n\nfunction assertWorkerActive(disposed: boolean): void {\n if (disposed) {\n throw new Error(\"Remote DOM widget worker has been disposed.\");\n }\n}\n\nfunction loadRemoteDomWorkerReactRendererModule(): Promise<RemoteDomReactWorkerRendererModule> {\n if (!remoteDomReactWorkerRendererModulePromise) {\n remoteDomReactWorkerRendererModulePromise = (async () => {\n await import(\"./worker-react-bootstrap\");\n return import(\"./worker-react-renderer\");\n })().catch((error: unknown) => {\n remoteDomReactWorkerRendererModulePromise = undefined;\n throw error;\n });\n }\n return remoteDomReactWorkerRendererModulePromise;\n}\n\nfunction reportWorkerError(\n host: RemoteDomWidgetWorkerHostApi,\n error: unknown,\n fallbackMessage: string,\n): void {\n try {\n host.reportError({\n message: error instanceof Error ? error.message : fallbackMessage,\n });\n } catch {\n // The host proxy may already be closed during teardown.\n }\n}\n\nfunction failClosedWorker(\n workerSelf: RemoteDomWorkerGlobalScopeLike,\n result: RemoteDomWorkerLockdownResult,\n): never {\n try {\n workerSelf.onmessage = null;\n } catch {\n // The error below still prevents the worker runtime from starting.\n }\n workerSelf.close?.();\n throw new Error(\n `Remote DOM worker lockdown failed for globals: ${result.failedGlobals.join(\", \")}.`,\n );\n}\n\nfunction readGlobalWorkerSelf(): RemoteDomWorkerGlobalScopeLike {\n const candidate = globalThis as Partial<RemoteDomWorkerGlobalScopeLike>;\n if (typeof candidate.postMessage !== \"function\") {\n throw new Error(\n \"Remote DOM widget runtime requires a Worker global scope.\",\n );\n }\n if (candidate.onmessage === undefined) {\n candidate.onmessage = null;\n }\n return candidate as RemoteDomWorkerGlobalScopeLike;\n}\n\nfunction toThreadMessageTarget(\n scope: RemoteDomWorkerGlobalScopeLike,\n): ThreadMessageTarget {\n return {\n send(message, transferables) {\n scope.postMessage(message, transferables ?? []);\n },\n listen(listener, { signal }) {\n if (scope.addEventListener) {\n scope.addEventListener(\"message\", (event) => listener(event.data), {\n signal,\n });\n return;\n }\n\n scope.onmessage = (event) => listener(event.data);\n signal?.addEventListener(\n \"abort\",\n () => {\n scope.onmessage = null;\n },\n { once: true },\n );\n },\n };\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, RemoteDomSerializableValue>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,68 @@
1
+ {
2
+ "name": "@fluid-app/widget-runtime",
3
+ "version": "0.1.0",
4
+ "description": "Remote DOM host and worker runtime for Fluid widget packages",
5
+ "files": [
6
+ "dist"
7
+ ],
8
+ "type": "module",
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.mjs",
11
+ "types": "./dist/index.d.mts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.mts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ },
18
+ "./remote-dom": {
19
+ "types": "./dist/remote-dom.d.mts",
20
+ "import": "./dist/remote-dom.mjs",
21
+ "require": "./dist/remote-dom.cjs"
22
+ },
23
+ "./worker": {
24
+ "types": "./dist/worker.d.mts",
25
+ "import": "./dist/worker.mjs",
26
+ "require": "./dist/worker.cjs"
27
+ }
28
+ },
29
+ "publishConfig": {
30
+ "access": "public"
31
+ },
32
+ "dependencies": {
33
+ "@preact/signals-core": "1.14.3",
34
+ "@quilted/threads": "^4.1.0",
35
+ "@remote-dom/core": "^1.11.1",
36
+ "@remote-dom/react": "^1.2.2",
37
+ "postcss": "8.5.9",
38
+ "postcss-value-parser": "4.2.0"
39
+ },
40
+ "devDependencies": {
41
+ "@swc/core": "^1.15.18",
42
+ "@swc/jest": "^0.2.39",
43
+ "@types/jest": "^29.5.14",
44
+ "@types/node": "24.10.12",
45
+ "@types/react": "^19.2.13",
46
+ "@types/react-dom": "^19.2.3",
47
+ "jest": "^29.7.0",
48
+ "jest-environment-jsdom": "^29.7.0",
49
+ "react": "^19.2.4",
50
+ "react-dom": "^19.2.4",
51
+ "tsdown": "^0.21.0",
52
+ "typescript": "^5",
53
+ "@fluid-app/typescript-config": "0.0.0"
54
+ },
55
+ "peerDependencies": {
56
+ "react": ">=18.0.0",
57
+ "react-dom": ">=18.0.0"
58
+ },
59
+ "scripts": {
60
+ "build": "tsdown",
61
+ "dev": "tsdown --watch",
62
+ "lint": "oxlint --deny-warnings",
63
+ "lint:fix": "oxlint --fix --deny-warnings",
64
+ "test": "jest",
65
+ "test:watch": "jest --watch",
66
+ "typecheck": "tsgo --noEmit"
67
+ }
68
+ }