@fluid-app/widget-runtime 0.1.122 → 0.1.124

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.
@@ -80,14 +80,21 @@ function createRemoteDomReactWorkerRenderer({ connection }) {
80
80
  }
81
81
  function registerRemoteElements() {
82
82
  if (remoteElementsRegistered) return;
83
- remoteElementsRegistered = true;
84
83
  defineRemoteElement(REMOTE_ROOT_TAG_NAME, _remote_dom_core_elements.RemoteRootElement);
85
84
  const fluidTagNames = new Set(require_remote_dom_values.REMOTE_DOM_UI_COMPONENTS.map(({ tagName }) => tagName));
85
+ const nativeConstructors = /* @__PURE__ */ new Map();
86
86
  for (const tagName of require_remote_dom_values.REMOTE_DOM_ALLOWED_TAG_NAMES) {
87
87
  if (fluidTagNames.has(tagName)) continue;
88
- defineRemoteElement(tagName, tagName === "input" ? FluidRemoteInputElement : FluidRemoteElement);
88
+ const alias = `fluid-native-${tagName}`;
89
+ const BaseElement = tagName === "input" ? FluidRemoteInputElement : FluidRemoteElement;
90
+ defineRemoteElement(alias, class extends BaseElement {});
91
+ const constructor = customElements.get(alias);
92
+ if (constructor) nativeConstructors.set(tagName, constructor);
89
93
  }
94
+ const getRegisteredElement = customElements.get.bind(customElements);
95
+ customElements.get = (name) => nativeConstructors.get(name) ?? getRegisteredElement(name);
90
96
  for (const definition of require_remote_dom_values.REMOTE_DOM_UI_COMPONENTS) defineRemoteElement(definition.tagName, createRemoteUiElementConstructor(definition));
97
+ remoteElementsRegistered = true;
91
98
  }
92
99
  function createRemoteUiElementConstructor(definition) {
93
100
  const properties = Object.fromEntries(Object.keys(definition.properties).map((propertyName) => [propertyName, { attribute: false }]));
@@ -160,4 +167,4 @@ function isObjectRecord(value) {
160
167
  //#endregion
161
168
  exports.createRemoteDomReactWorkerRenderer = createRemoteDomReactWorkerRenderer;
162
169
 
163
- //# sourceMappingURL=worker-react-renderer-CR-TvErh.cjs.map
170
+ //# sourceMappingURL=worker-react-renderer-COpONF0h.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-react-renderer-COpONF0h.cjs","names":["SUPPORTED_REMOTE_DOM_EVENTS","BatchingRemoteConnection","RemoteRootElement","REMOTE_DOM_UI_COMPONENTS","REMOTE_DOM_ALLOWED_TAG_NAMES","isRemoteDomSerializableValue"],"sources":["../src/worker-react-renderer.ts"],"sourcesContent":["import {\n BatchingRemoteConnection,\n createRemoteElement,\n RemoteRootElement,\n type RemoteElementEventListenerDefinition,\n type RemoteConnection,\n} from \"@remote-dom/core/elements\";\nimport type { ReactNode } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport {\n isRemoteDomSerializableValue,\n REMOTE_DOM_ALLOWED_TAG_NAMES,\n SUPPORTED_REMOTE_DOM_EVENTS,\n type RemoteDomSerializableValue,\n} from \"./remote-dom-values\";\nimport {\n REMOTE_DOM_UI_COMPONENTS,\n type RemoteDomUiComponentDefinition,\n} from \"./remote-dom-ui-contract\";\n\nexport interface RemoteDomReactWorkerRendererOptions {\n /**\n * The host-backed connection ({@link RemoteConnection}); its `mutate` is the\n * threads-proxied `host.mutate`. The renderer wraps it in a\n * `BatchingRemoteConnection` and flushes explicitly after every commit.\n */\n readonly connection: RemoteConnection;\n}\n\nexport interface RemoteDomReactWorkerRenderer {\n readonly render: (node: ReactNode) => void;\n readonly dispose: () => void;\n}\n\nconst REMOTE_ROOT_TAG_NAME = \"remote-root\";\n\ntype NoRemoteMembers = Record<never, never>;\ntype RemoteEventListeners = Record<string, (payload?: unknown) => unknown>;\n\nconst standardEventDefinitions = createRemoteEventDefinitions(\n SUPPORTED_REMOTE_DOM_EVENTS,\n);\nconst FluidRemoteElement = createRemoteElement<\n NoRemoteMembers,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({ events: standardEventDefinitions });\n\ninterface RemoteInputProperties {\n readonly checked: boolean;\n readonly type: string;\n readonly value: string;\n}\n\nconst RemoteInputElement = createRemoteElement<\n RemoteInputProperties,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({\n events: standardEventDefinitions,\n properties: {\n checked: { attribute: false, default: false },\n type: { attribute: true, default: \"text\" },\n value: { attribute: false, default: \"\" },\n },\n});\n\nclass FluidRemoteInputElement extends RemoteInputElement {\n applyHostState(detail: Readonly<Record<string, unknown>>): void {\n // React wraps public input setters with its value tracker. Update Remote\n // DOM's upstream property cache directly so the following native event is\n // extracted, while still synchronizing the host-controlled value.\n const value = readSerializableString(detail, \"value\");\n if (value !== undefined) this.updateRemoteProperty(\"value\", value);\n\n const checked = detail.checked;\n if (typeof checked === \"boolean\") {\n this.updateRemoteProperty(\"checked\", checked);\n }\n }\n}\n\nlet remoteElementsRegistered = false;\n\nexport function createRemoteDomReactWorkerRenderer({\n connection,\n}: RemoteDomReactWorkerRendererOptions): RemoteDomReactWorkerRenderer {\n registerRemoteElements();\n\n const remoteRoot = document.createElement(\n REMOTE_ROOT_TAG_NAME,\n ) as RemoteRootElement;\n const batchedConnection = new BatchingRemoteConnection(connection);\n remoteRoot.connect(batchedConnection);\n const reactRoot: Root = createRoot(remoteRoot);\n // Remote DOM installs bubbling event proxies from custom-element lifecycle\n // callbacks. Keep the remote tree connected to its synthetic document so\n // those callbacks run for every element React mounts.\n try {\n document.body.append(remoteRoot);\n } catch (error) {\n reactRoot.unmount();\n throw error;\n }\n let disposed = false;\n\n return {\n render(node) {\n flushSync(() => {\n reactRoot.render(node);\n });\n // The host must never observe a capability/event side effect before the\n // DOM it references, so force mutations out immediately after commit.\n batchedConnection.flush();\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n const cleanupErrors: unknown[] = [];\n\n try {\n flushSync(() => {\n reactRoot.unmount();\n });\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n remoteRoot.remove();\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n batchedConnection.flush();\n } catch (error) {\n cleanupErrors.push(error);\n }\n\n if (cleanupErrors.length > 0) {\n throw new AggregateError(\n cleanupErrors,\n \"Remote DOM React session cleanup failed.\",\n );\n }\n },\n };\n}\n\nfunction registerRemoteElements(): void {\n if (remoteElementsRegistered) return;\n defineRemoteElement(REMOTE_ROOT_TAG_NAME, RemoteRootElement);\n const fluidTagNames = new Set<string>(\n REMOTE_DOM_UI_COMPONENTS.map(({ tagName }) => tagName),\n );\n const nativeConstructors = new Map<string, CustomElementConstructor>();\n for (const tagName of REMOTE_DOM_ALLOWED_TAG_NAMES) {\n if (fluidTagNames.has(tagName)) continue;\n const alias = `fluid-native-${tagName}`;\n const BaseElement =\n tagName === \"input\" ? FluidRemoteInputElement : FluidRemoteElement;\n defineRemoteElement(alias, class extends BaseElement {});\n const constructor = customElements.get(alias);\n if (constructor) nativeConstructors.set(tagName, constructor);\n }\n // The worker polyfill looks up constructors before assigning the requested\n // native localName. Register only valid custom names, then supply the native\n // constructor at that lookup seam; host serialization keeps the native tag.\n const getRegisteredElement = customElements.get.bind(customElements);\n customElements.get = (name: string) =>\n nativeConstructors.get(name) ?? getRegisteredElement(name);\n\n for (const definition of REMOTE_DOM_UI_COMPONENTS) {\n defineRemoteElement(\n definition.tagName,\n createRemoteUiElementConstructor(definition),\n );\n }\n remoteElementsRegistered = true;\n}\n\nfunction createRemoteUiElementConstructor(\n definition: RemoteDomUiComponentDefinition,\n): CustomElementConstructor {\n const properties = Object.fromEntries(\n Object.keys(definition.properties).map((propertyName) => [\n propertyName,\n { attribute: false },\n ]),\n );\n const events = createRemoteEventDefinitions(\n definition.events.map(({ eventName }) => eventName),\n );\n return createRemoteElement<\n Record<string, RemoteDomSerializableValue | undefined>,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n >({ events, properties });\n}\n\nfunction defineRemoteElement(\n tagName: string,\n constructor: CustomElementConstructor,\n): void {\n if (customElements.get(tagName)) return;\n customElements.define(tagName, constructor);\n}\n\nfunction createRemoteEventDefinitions(\n eventNames: readonly string[],\n): Readonly<Record<string, RemoteElementEventListenerDefinition>> {\n return Object.fromEntries(\n eventNames.map((eventName) => [\n eventName,\n {\n bubbles: true,\n dispatchEvent(this: Element, payload?: unknown) {\n const detail = readHostEventDetail(payload);\n if (\n this instanceof FluidRemoteInputElement &&\n isObjectRecord(detail)\n ) {\n this.applyHostState(detail);\n }\n return createRemoteDomReactEvent(eventName, detail);\n },\n },\n ]),\n );\n}\n\nfunction readHostEventDetail(\n payload: unknown,\n): RemoteDomSerializableValue | undefined {\n if (isObjectRecord(payload) && isRemoteDomSerializableValue(payload.detail)) {\n return payload.detail;\n }\n return isRemoteDomSerializableValue(payload) ? payload : undefined;\n}\n\nfunction createRemoteDomReactEvent(\n eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n): Event {\n const customDetail = parseCustomEventDetail(eventName, detail);\n const event = new CustomEvent(eventName, {\n bubbles: true,\n cancelable: true,\n detail: customDetail.ok ? customDetail.value : detail,\n });\n if (!isObjectRecord(detail)) return event;\n\n const key = readSerializableString(detail, \"key\");\n if (key !== undefined) setObjectProperty(event, \"key\", key);\n\n const eventType = readSerializableString(detail, \"type\");\n if (eventType !== undefined) setObjectProperty(event, \"inputType\", eventType);\n\n return event;\n}\n\nfunction parseCustomEventDetail(\n _eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n):\n | { readonly ok: true; readonly value: RemoteDomSerializableValue }\n | { readonly ok: false } {\n if (!isObjectRecord(detail)) {\n return { ok: false };\n }\n const detailJson = detail.detailJson;\n if (typeof detailJson !== \"string\") return { ok: false };\n\n try {\n const value: unknown = JSON.parse(detailJson);\n return isRemoteDomSerializableValue(value)\n ? { ok: true, value }\n : { ok: false };\n } catch {\n return { ok: false };\n }\n}\n\nfunction readSerializableString(\n detail: Readonly<Record<string, unknown>>,\n key: string,\n): string | undefined {\n const value = detail[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction setObjectProperty(target: object, key: string, value: unknown): void {\n Object.defineProperty(target, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true,\n });\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}
@@ -79,14 +79,21 @@ function createRemoteDomReactWorkerRenderer({ connection }) {
79
79
  }
80
80
  function registerRemoteElements() {
81
81
  if (remoteElementsRegistered) return;
82
- remoteElementsRegistered = true;
83
82
  defineRemoteElement(REMOTE_ROOT_TAG_NAME, RemoteRootElement);
84
83
  const fluidTagNames = new Set(REMOTE_DOM_UI_COMPONENTS.map(({ tagName }) => tagName));
84
+ const nativeConstructors = /* @__PURE__ */ new Map();
85
85
  for (const tagName of REMOTE_DOM_ALLOWED_TAG_NAMES) {
86
86
  if (fluidTagNames.has(tagName)) continue;
87
- defineRemoteElement(tagName, tagName === "input" ? FluidRemoteInputElement : FluidRemoteElement);
87
+ const alias = `fluid-native-${tagName}`;
88
+ const BaseElement = tagName === "input" ? FluidRemoteInputElement : FluidRemoteElement;
89
+ defineRemoteElement(alias, class extends BaseElement {});
90
+ const constructor = customElements.get(alias);
91
+ if (constructor) nativeConstructors.set(tagName, constructor);
88
92
  }
93
+ const getRegisteredElement = customElements.get.bind(customElements);
94
+ customElements.get = (name) => nativeConstructors.get(name) ?? getRegisteredElement(name);
89
95
  for (const definition of REMOTE_DOM_UI_COMPONENTS) defineRemoteElement(definition.tagName, createRemoteUiElementConstructor(definition));
96
+ remoteElementsRegistered = true;
90
97
  }
91
98
  function createRemoteUiElementConstructor(definition) {
92
99
  const properties = Object.fromEntries(Object.keys(definition.properties).map((propertyName) => [propertyName, { attribute: false }]));
@@ -159,4 +166,4 @@ function isObjectRecord(value) {
159
166
  //#endregion
160
167
  export { createRemoteDomReactWorkerRenderer };
161
168
 
162
- //# sourceMappingURL=worker-react-renderer-BV6ExKCS.mjs.map
169
+ //# sourceMappingURL=worker-react-renderer-ggcPIDLl.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"worker-react-renderer-ggcPIDLl.mjs","names":[],"sources":["../src/worker-react-renderer.ts"],"sourcesContent":["import {\n BatchingRemoteConnection,\n createRemoteElement,\n RemoteRootElement,\n type RemoteElementEventListenerDefinition,\n type RemoteConnection,\n} from \"@remote-dom/core/elements\";\nimport type { ReactNode } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport {\n isRemoteDomSerializableValue,\n REMOTE_DOM_ALLOWED_TAG_NAMES,\n SUPPORTED_REMOTE_DOM_EVENTS,\n type RemoteDomSerializableValue,\n} from \"./remote-dom-values\";\nimport {\n REMOTE_DOM_UI_COMPONENTS,\n type RemoteDomUiComponentDefinition,\n} from \"./remote-dom-ui-contract\";\n\nexport interface RemoteDomReactWorkerRendererOptions {\n /**\n * The host-backed connection ({@link RemoteConnection}); its `mutate` is the\n * threads-proxied `host.mutate`. The renderer wraps it in a\n * `BatchingRemoteConnection` and flushes explicitly after every commit.\n */\n readonly connection: RemoteConnection;\n}\n\nexport interface RemoteDomReactWorkerRenderer {\n readonly render: (node: ReactNode) => void;\n readonly dispose: () => void;\n}\n\nconst REMOTE_ROOT_TAG_NAME = \"remote-root\";\n\ntype NoRemoteMembers = Record<never, never>;\ntype RemoteEventListeners = Record<string, (payload?: unknown) => unknown>;\n\nconst standardEventDefinitions = createRemoteEventDefinitions(\n SUPPORTED_REMOTE_DOM_EVENTS,\n);\nconst FluidRemoteElement = createRemoteElement<\n NoRemoteMembers,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({ events: standardEventDefinitions });\n\ninterface RemoteInputProperties {\n readonly checked: boolean;\n readonly type: string;\n readonly value: string;\n}\n\nconst RemoteInputElement = createRemoteElement<\n RemoteInputProperties,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({\n events: standardEventDefinitions,\n properties: {\n checked: { attribute: false, default: false },\n type: { attribute: true, default: \"text\" },\n value: { attribute: false, default: \"\" },\n },\n});\n\nclass FluidRemoteInputElement extends RemoteInputElement {\n applyHostState(detail: Readonly<Record<string, unknown>>): void {\n // React wraps public input setters with its value tracker. Update Remote\n // DOM's upstream property cache directly so the following native event is\n // extracted, while still synchronizing the host-controlled value.\n const value = readSerializableString(detail, \"value\");\n if (value !== undefined) this.updateRemoteProperty(\"value\", value);\n\n const checked = detail.checked;\n if (typeof checked === \"boolean\") {\n this.updateRemoteProperty(\"checked\", checked);\n }\n }\n}\n\nlet remoteElementsRegistered = false;\n\nexport function createRemoteDomReactWorkerRenderer({\n connection,\n}: RemoteDomReactWorkerRendererOptions): RemoteDomReactWorkerRenderer {\n registerRemoteElements();\n\n const remoteRoot = document.createElement(\n REMOTE_ROOT_TAG_NAME,\n ) as RemoteRootElement;\n const batchedConnection = new BatchingRemoteConnection(connection);\n remoteRoot.connect(batchedConnection);\n const reactRoot: Root = createRoot(remoteRoot);\n // Remote DOM installs bubbling event proxies from custom-element lifecycle\n // callbacks. Keep the remote tree connected to its synthetic document so\n // those callbacks run for every element React mounts.\n try {\n document.body.append(remoteRoot);\n } catch (error) {\n reactRoot.unmount();\n throw error;\n }\n let disposed = false;\n\n return {\n render(node) {\n flushSync(() => {\n reactRoot.render(node);\n });\n // The host must never observe a capability/event side effect before the\n // DOM it references, so force mutations out immediately after commit.\n batchedConnection.flush();\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n const cleanupErrors: unknown[] = [];\n\n try {\n flushSync(() => {\n reactRoot.unmount();\n });\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n remoteRoot.remove();\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n batchedConnection.flush();\n } catch (error) {\n cleanupErrors.push(error);\n }\n\n if (cleanupErrors.length > 0) {\n throw new AggregateError(\n cleanupErrors,\n \"Remote DOM React session cleanup failed.\",\n );\n }\n },\n };\n}\n\nfunction registerRemoteElements(): void {\n if (remoteElementsRegistered) return;\n defineRemoteElement(REMOTE_ROOT_TAG_NAME, RemoteRootElement);\n const fluidTagNames = new Set<string>(\n REMOTE_DOM_UI_COMPONENTS.map(({ tagName }) => tagName),\n );\n const nativeConstructors = new Map<string, CustomElementConstructor>();\n for (const tagName of REMOTE_DOM_ALLOWED_TAG_NAMES) {\n if (fluidTagNames.has(tagName)) continue;\n const alias = `fluid-native-${tagName}`;\n const BaseElement =\n tagName === \"input\" ? FluidRemoteInputElement : FluidRemoteElement;\n defineRemoteElement(alias, class extends BaseElement {});\n const constructor = customElements.get(alias);\n if (constructor) nativeConstructors.set(tagName, constructor);\n }\n // The worker polyfill looks up constructors before assigning the requested\n // native localName. Register only valid custom names, then supply the native\n // constructor at that lookup seam; host serialization keeps the native tag.\n const getRegisteredElement = customElements.get.bind(customElements);\n customElements.get = (name: string) =>\n nativeConstructors.get(name) ?? getRegisteredElement(name);\n\n for (const definition of REMOTE_DOM_UI_COMPONENTS) {\n defineRemoteElement(\n definition.tagName,\n createRemoteUiElementConstructor(definition),\n );\n }\n remoteElementsRegistered = true;\n}\n\nfunction createRemoteUiElementConstructor(\n definition: RemoteDomUiComponentDefinition,\n): CustomElementConstructor {\n const properties = Object.fromEntries(\n Object.keys(definition.properties).map((propertyName) => [\n propertyName,\n { attribute: false },\n ]),\n );\n const events = createRemoteEventDefinitions(\n definition.events.map(({ eventName }) => eventName),\n );\n return createRemoteElement<\n Record<string, RemoteDomSerializableValue | undefined>,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n >({ events, properties });\n}\n\nfunction defineRemoteElement(\n tagName: string,\n constructor: CustomElementConstructor,\n): void {\n if (customElements.get(tagName)) return;\n customElements.define(tagName, constructor);\n}\n\nfunction createRemoteEventDefinitions(\n eventNames: readonly string[],\n): Readonly<Record<string, RemoteElementEventListenerDefinition>> {\n return Object.fromEntries(\n eventNames.map((eventName) => [\n eventName,\n {\n bubbles: true,\n dispatchEvent(this: Element, payload?: unknown) {\n const detail = readHostEventDetail(payload);\n if (\n this instanceof FluidRemoteInputElement &&\n isObjectRecord(detail)\n ) {\n this.applyHostState(detail);\n }\n return createRemoteDomReactEvent(eventName, detail);\n },\n },\n ]),\n );\n}\n\nfunction readHostEventDetail(\n payload: unknown,\n): RemoteDomSerializableValue | undefined {\n if (isObjectRecord(payload) && isRemoteDomSerializableValue(payload.detail)) {\n return payload.detail;\n }\n return isRemoteDomSerializableValue(payload) ? payload : undefined;\n}\n\nfunction createRemoteDomReactEvent(\n eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n): Event {\n const customDetail = parseCustomEventDetail(eventName, detail);\n const event = new CustomEvent(eventName, {\n bubbles: true,\n cancelable: true,\n detail: customDetail.ok ? customDetail.value : detail,\n });\n if (!isObjectRecord(detail)) return event;\n\n const key = readSerializableString(detail, \"key\");\n if (key !== undefined) setObjectProperty(event, \"key\", key);\n\n const eventType = readSerializableString(detail, \"type\");\n if (eventType !== undefined) setObjectProperty(event, \"inputType\", eventType);\n\n return event;\n}\n\nfunction parseCustomEventDetail(\n _eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n):\n | { readonly ok: true; readonly value: RemoteDomSerializableValue }\n | { readonly ok: false } {\n if (!isObjectRecord(detail)) {\n return { ok: false };\n }\n const detailJson = detail.detailJson;\n if (typeof detailJson !== \"string\") return { ok: false };\n\n try {\n const value: unknown = JSON.parse(detailJson);\n return isRemoteDomSerializableValue(value)\n ? { ok: true, value }\n : { ok: false };\n } catch {\n return { ok: false };\n }\n}\n\nfunction readSerializableString(\n detail: Readonly<Record<string, unknown>>,\n key: string,\n): string | undefined {\n const value = detail[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction setObjectProperty(target: object, key: string, value: unknown): void {\n Object.defineProperty(target, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true,\n });\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}
package/dist/worker.cjs CHANGED
@@ -443,7 +443,7 @@ function assertWorkerActive(disposed) {
443
443
  function loadRemoteDomWorkerReactRendererModule() {
444
444
  if (!remoteDomReactWorkerRendererModulePromise) remoteDomReactWorkerRendererModulePromise = (async () => {
445
445
  await Promise.resolve().then(() => require("./worker-react-bootstrap-N8jcWZ3L.cjs"));
446
- return Promise.resolve().then(() => require("./worker-react-renderer-CR-TvErh.cjs"));
446
+ return Promise.resolve().then(() => require("./worker-react-renderer-COpONF0h.cjs"));
447
447
  })().catch((error) => {
448
448
  remoteDomReactWorkerRendererModulePromise = void 0;
449
449
  throw error;
package/dist/worker.mjs CHANGED
@@ -441,7 +441,7 @@ function assertWorkerActive(disposed) {
441
441
  function loadRemoteDomWorkerReactRendererModule() {
442
442
  if (!remoteDomReactWorkerRendererModulePromise) remoteDomReactWorkerRendererModulePromise = (async () => {
443
443
  await import("./worker-react-bootstrap-C7tCMYGA.mjs");
444
- return import("./worker-react-renderer-BV6ExKCS.mjs");
444
+ return import("./worker-react-renderer-ggcPIDLl.mjs");
445
445
  })().catch((error) => {
446
446
  remoteDomReactWorkerRendererModulePromise = void 0;
447
447
  throw error;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluid-app/widget-runtime",
3
- "version": "0.1.122",
3
+ "version": "0.1.124",
4
4
  "description": "Remote DOM host and worker runtime for Fluid widget packages",
5
5
  "files": [
6
6
  "dist"
@@ -32,7 +32,7 @@
32
32
  "dependencies": {
33
33
  "@preact/signals-core": "1.14.3",
34
34
  "@quilted/threads": "^4.1.0",
35
- "@remote-dom/core": "^1.11.1",
35
+ "@remote-dom/core": "^1.12.0",
36
36
  "@remote-dom/react": "^1.2.2",
37
37
  "postcss": "8.5.9",
38
38
  "postcss-value-parser": "4.2.0"
@@ -61,7 +61,7 @@
61
61
  "dev": "tsdown --watch",
62
62
  "lint": "oxlint --deny-warnings",
63
63
  "lint:fix": "oxlint --fix --deny-warnings",
64
- "test": "jest",
64
+ "test": "jest && node scripts/verify-native-worker.mjs",
65
65
  "test:watch": "jest --watch",
66
66
  "typecheck": "tsgo --noEmit"
67
67
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"worker-react-renderer-BV6ExKCS.mjs","names":[],"sources":["../src/worker-react-renderer.ts"],"sourcesContent":["import {\n BatchingRemoteConnection,\n createRemoteElement,\n RemoteRootElement,\n type RemoteElementEventListenerDefinition,\n type RemoteConnection,\n} from \"@remote-dom/core/elements\";\nimport type { ReactNode } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport {\n isRemoteDomSerializableValue,\n REMOTE_DOM_ALLOWED_TAG_NAMES,\n SUPPORTED_REMOTE_DOM_EVENTS,\n type RemoteDomSerializableValue,\n} from \"./remote-dom-values\";\nimport {\n REMOTE_DOM_UI_COMPONENTS,\n type RemoteDomUiComponentDefinition,\n} from \"./remote-dom-ui-contract\";\n\nexport interface RemoteDomReactWorkerRendererOptions {\n /**\n * The host-backed connection ({@link RemoteConnection}); its `mutate` is the\n * threads-proxied `host.mutate`. The renderer wraps it in a\n * `BatchingRemoteConnection` and flushes explicitly after every commit.\n */\n readonly connection: RemoteConnection;\n}\n\nexport interface RemoteDomReactWorkerRenderer {\n readonly render: (node: ReactNode) => void;\n readonly dispose: () => void;\n}\n\nconst REMOTE_ROOT_TAG_NAME = \"remote-root\";\n\ntype NoRemoteMembers = Record<never, never>;\ntype RemoteEventListeners = Record<string, (payload?: unknown) => unknown>;\n\nconst standardEventDefinitions = createRemoteEventDefinitions(\n SUPPORTED_REMOTE_DOM_EVENTS,\n);\nconst FluidRemoteElement = createRemoteElement<\n NoRemoteMembers,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({ events: standardEventDefinitions });\n\ninterface RemoteInputProperties {\n readonly checked: boolean;\n readonly type: string;\n readonly value: string;\n}\n\nconst RemoteInputElement = createRemoteElement<\n RemoteInputProperties,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({\n events: standardEventDefinitions,\n properties: {\n checked: { attribute: false, default: false },\n type: { attribute: true, default: \"text\" },\n value: { attribute: false, default: \"\" },\n },\n});\n\nclass FluidRemoteInputElement extends RemoteInputElement {\n applyHostState(detail: Readonly<Record<string, unknown>>): void {\n // React wraps public input setters with its value tracker. Update Remote\n // DOM's upstream property cache directly so the following native event is\n // extracted, while still synchronizing the host-controlled value.\n const value = readSerializableString(detail, \"value\");\n if (value !== undefined) this.updateRemoteProperty(\"value\", value);\n\n const checked = detail.checked;\n if (typeof checked === \"boolean\") {\n this.updateRemoteProperty(\"checked\", checked);\n }\n }\n}\n\nlet remoteElementsRegistered = false;\n\nexport function createRemoteDomReactWorkerRenderer({\n connection,\n}: RemoteDomReactWorkerRendererOptions): RemoteDomReactWorkerRenderer {\n registerRemoteElements();\n\n const remoteRoot = document.createElement(\n REMOTE_ROOT_TAG_NAME,\n ) as RemoteRootElement;\n const batchedConnection = new BatchingRemoteConnection(connection);\n remoteRoot.connect(batchedConnection);\n const reactRoot: Root = createRoot(remoteRoot);\n // Remote DOM installs bubbling event proxies from custom-element lifecycle\n // callbacks. Keep the remote tree connected to its synthetic document so\n // those callbacks run for every element React mounts.\n try {\n document.body.append(remoteRoot);\n } catch (error) {\n reactRoot.unmount();\n throw error;\n }\n let disposed = false;\n\n return {\n render(node) {\n flushSync(() => {\n reactRoot.render(node);\n });\n // The host must never observe a capability/event side effect before the\n // DOM it references, so force mutations out immediately after commit.\n batchedConnection.flush();\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n const cleanupErrors: unknown[] = [];\n\n try {\n flushSync(() => {\n reactRoot.unmount();\n });\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n remoteRoot.remove();\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n batchedConnection.flush();\n } catch (error) {\n cleanupErrors.push(error);\n }\n\n if (cleanupErrors.length > 0) {\n throw new AggregateError(\n cleanupErrors,\n \"Remote DOM React session cleanup failed.\",\n );\n }\n },\n };\n}\n\nfunction registerRemoteElements(): void {\n if (remoteElementsRegistered) return;\n remoteElementsRegistered = true;\n\n defineRemoteElement(REMOTE_ROOT_TAG_NAME, RemoteRootElement);\n const fluidTagNames = new Set<string>(\n REMOTE_DOM_UI_COMPONENTS.map(({ tagName }) => tagName),\n );\n for (const tagName of REMOTE_DOM_ALLOWED_TAG_NAMES) {\n if (fluidTagNames.has(tagName)) continue;\n defineRemoteElement(\n tagName,\n tagName === \"input\" ? FluidRemoteInputElement : FluidRemoteElement,\n );\n }\n for (const definition of REMOTE_DOM_UI_COMPONENTS) {\n defineRemoteElement(\n definition.tagName,\n createRemoteUiElementConstructor(definition),\n );\n }\n}\n\nfunction createRemoteUiElementConstructor(\n definition: RemoteDomUiComponentDefinition,\n): CustomElementConstructor {\n const properties = Object.fromEntries(\n Object.keys(definition.properties).map((propertyName) => [\n propertyName,\n { attribute: false },\n ]),\n );\n const events = createRemoteEventDefinitions(\n definition.events.map(({ eventName }) => eventName),\n );\n return createRemoteElement<\n Record<string, RemoteDomSerializableValue | undefined>,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n >({ events, properties });\n}\n\nfunction defineRemoteElement(\n tagName: string,\n constructor: CustomElementConstructor,\n): void {\n if (customElements.get(tagName)) return;\n customElements.define(tagName, constructor);\n}\n\nfunction createRemoteEventDefinitions(\n eventNames: readonly string[],\n): Readonly<Record<string, RemoteElementEventListenerDefinition>> {\n return Object.fromEntries(\n eventNames.map((eventName) => [\n eventName,\n {\n bubbles: true,\n dispatchEvent(this: Element, payload?: unknown) {\n const detail = readHostEventDetail(payload);\n if (\n this instanceof FluidRemoteInputElement &&\n isObjectRecord(detail)\n ) {\n this.applyHostState(detail);\n }\n return createRemoteDomReactEvent(eventName, detail);\n },\n },\n ]),\n );\n}\n\nfunction readHostEventDetail(\n payload: unknown,\n): RemoteDomSerializableValue | undefined {\n if (isObjectRecord(payload) && isRemoteDomSerializableValue(payload.detail)) {\n return payload.detail;\n }\n return isRemoteDomSerializableValue(payload) ? payload : undefined;\n}\n\nfunction createRemoteDomReactEvent(\n eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n): Event {\n const customDetail = parseCustomEventDetail(eventName, detail);\n const event = new CustomEvent(eventName, {\n bubbles: true,\n cancelable: true,\n detail: customDetail.ok ? customDetail.value : detail,\n });\n if (!isObjectRecord(detail)) return event;\n\n const key = readSerializableString(detail, \"key\");\n if (key !== undefined) setObjectProperty(event, \"key\", key);\n\n const eventType = readSerializableString(detail, \"type\");\n if (eventType !== undefined) setObjectProperty(event, \"inputType\", eventType);\n\n return event;\n}\n\nfunction parseCustomEventDetail(\n _eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n):\n | { readonly ok: true; readonly value: RemoteDomSerializableValue }\n | { readonly ok: false } {\n if (!isObjectRecord(detail)) {\n return { ok: false };\n }\n const detailJson = detail.detailJson;\n if (typeof detailJson !== \"string\") return { ok: false };\n\n try {\n const value: unknown = JSON.parse(detailJson);\n return isRemoteDomSerializableValue(value)\n ? { ok: true, value }\n : { ok: false };\n } catch {\n return { ok: false };\n }\n}\n\nfunction readSerializableString(\n detail: Readonly<Record<string, unknown>>,\n key: string,\n): string | undefined {\n const value = detail[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction setObjectProperty(target: object, key: string, value: unknown): void {\n Object.defineProperty(target, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true,\n });\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"worker-react-renderer-CR-TvErh.cjs","names":["SUPPORTED_REMOTE_DOM_EVENTS","BatchingRemoteConnection","RemoteRootElement","REMOTE_DOM_UI_COMPONENTS","REMOTE_DOM_ALLOWED_TAG_NAMES","isRemoteDomSerializableValue"],"sources":["../src/worker-react-renderer.ts"],"sourcesContent":["import {\n BatchingRemoteConnection,\n createRemoteElement,\n RemoteRootElement,\n type RemoteElementEventListenerDefinition,\n type RemoteConnection,\n} from \"@remote-dom/core/elements\";\nimport type { ReactNode } from \"react\";\nimport { flushSync } from \"react-dom\";\nimport { createRoot, type Root } from \"react-dom/client\";\n\nimport {\n isRemoteDomSerializableValue,\n REMOTE_DOM_ALLOWED_TAG_NAMES,\n SUPPORTED_REMOTE_DOM_EVENTS,\n type RemoteDomSerializableValue,\n} from \"./remote-dom-values\";\nimport {\n REMOTE_DOM_UI_COMPONENTS,\n type RemoteDomUiComponentDefinition,\n} from \"./remote-dom-ui-contract\";\n\nexport interface RemoteDomReactWorkerRendererOptions {\n /**\n * The host-backed connection ({@link RemoteConnection}); its `mutate` is the\n * threads-proxied `host.mutate`. The renderer wraps it in a\n * `BatchingRemoteConnection` and flushes explicitly after every commit.\n */\n readonly connection: RemoteConnection;\n}\n\nexport interface RemoteDomReactWorkerRenderer {\n readonly render: (node: ReactNode) => void;\n readonly dispose: () => void;\n}\n\nconst REMOTE_ROOT_TAG_NAME = \"remote-root\";\n\ntype NoRemoteMembers = Record<never, never>;\ntype RemoteEventListeners = Record<string, (payload?: unknown) => unknown>;\n\nconst standardEventDefinitions = createRemoteEventDefinitions(\n SUPPORTED_REMOTE_DOM_EVENTS,\n);\nconst FluidRemoteElement = createRemoteElement<\n NoRemoteMembers,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({ events: standardEventDefinitions });\n\ninterface RemoteInputProperties {\n readonly checked: boolean;\n readonly type: string;\n readonly value: string;\n}\n\nconst RemoteInputElement = createRemoteElement<\n RemoteInputProperties,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n>({\n events: standardEventDefinitions,\n properties: {\n checked: { attribute: false, default: false },\n type: { attribute: true, default: \"text\" },\n value: { attribute: false, default: \"\" },\n },\n});\n\nclass FluidRemoteInputElement extends RemoteInputElement {\n applyHostState(detail: Readonly<Record<string, unknown>>): void {\n // React wraps public input setters with its value tracker. Update Remote\n // DOM's upstream property cache directly so the following native event is\n // extracted, while still synchronizing the host-controlled value.\n const value = readSerializableString(detail, \"value\");\n if (value !== undefined) this.updateRemoteProperty(\"value\", value);\n\n const checked = detail.checked;\n if (typeof checked === \"boolean\") {\n this.updateRemoteProperty(\"checked\", checked);\n }\n }\n}\n\nlet remoteElementsRegistered = false;\n\nexport function createRemoteDomReactWorkerRenderer({\n connection,\n}: RemoteDomReactWorkerRendererOptions): RemoteDomReactWorkerRenderer {\n registerRemoteElements();\n\n const remoteRoot = document.createElement(\n REMOTE_ROOT_TAG_NAME,\n ) as RemoteRootElement;\n const batchedConnection = new BatchingRemoteConnection(connection);\n remoteRoot.connect(batchedConnection);\n const reactRoot: Root = createRoot(remoteRoot);\n // Remote DOM installs bubbling event proxies from custom-element lifecycle\n // callbacks. Keep the remote tree connected to its synthetic document so\n // those callbacks run for every element React mounts.\n try {\n document.body.append(remoteRoot);\n } catch (error) {\n reactRoot.unmount();\n throw error;\n }\n let disposed = false;\n\n return {\n render(node) {\n flushSync(() => {\n reactRoot.render(node);\n });\n // The host must never observe a capability/event side effect before the\n // DOM it references, so force mutations out immediately after commit.\n batchedConnection.flush();\n },\n dispose() {\n if (disposed) return;\n disposed = true;\n const cleanupErrors: unknown[] = [];\n\n try {\n flushSync(() => {\n reactRoot.unmount();\n });\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n remoteRoot.remove();\n } catch (error) {\n cleanupErrors.push(error);\n }\n try {\n batchedConnection.flush();\n } catch (error) {\n cleanupErrors.push(error);\n }\n\n if (cleanupErrors.length > 0) {\n throw new AggregateError(\n cleanupErrors,\n \"Remote DOM React session cleanup failed.\",\n );\n }\n },\n };\n}\n\nfunction registerRemoteElements(): void {\n if (remoteElementsRegistered) return;\n remoteElementsRegistered = true;\n\n defineRemoteElement(REMOTE_ROOT_TAG_NAME, RemoteRootElement);\n const fluidTagNames = new Set<string>(\n REMOTE_DOM_UI_COMPONENTS.map(({ tagName }) => tagName),\n );\n for (const tagName of REMOTE_DOM_ALLOWED_TAG_NAMES) {\n if (fluidTagNames.has(tagName)) continue;\n defineRemoteElement(\n tagName,\n tagName === \"input\" ? FluidRemoteInputElement : FluidRemoteElement,\n );\n }\n for (const definition of REMOTE_DOM_UI_COMPONENTS) {\n defineRemoteElement(\n definition.tagName,\n createRemoteUiElementConstructor(definition),\n );\n }\n}\n\nfunction createRemoteUiElementConstructor(\n definition: RemoteDomUiComponentDefinition,\n): CustomElementConstructor {\n const properties = Object.fromEntries(\n Object.keys(definition.properties).map((propertyName) => [\n propertyName,\n { attribute: false },\n ]),\n );\n const events = createRemoteEventDefinitions(\n definition.events.map(({ eventName }) => eventName),\n );\n return createRemoteElement<\n Record<string, RemoteDomSerializableValue | undefined>,\n NoRemoteMembers,\n NoRemoteMembers,\n RemoteEventListeners\n >({ events, properties });\n}\n\nfunction defineRemoteElement(\n tagName: string,\n constructor: CustomElementConstructor,\n): void {\n if (customElements.get(tagName)) return;\n customElements.define(tagName, constructor);\n}\n\nfunction createRemoteEventDefinitions(\n eventNames: readonly string[],\n): Readonly<Record<string, RemoteElementEventListenerDefinition>> {\n return Object.fromEntries(\n eventNames.map((eventName) => [\n eventName,\n {\n bubbles: true,\n dispatchEvent(this: Element, payload?: unknown) {\n const detail = readHostEventDetail(payload);\n if (\n this instanceof FluidRemoteInputElement &&\n isObjectRecord(detail)\n ) {\n this.applyHostState(detail);\n }\n return createRemoteDomReactEvent(eventName, detail);\n },\n },\n ]),\n );\n}\n\nfunction readHostEventDetail(\n payload: unknown,\n): RemoteDomSerializableValue | undefined {\n if (isObjectRecord(payload) && isRemoteDomSerializableValue(payload.detail)) {\n return payload.detail;\n }\n return isRemoteDomSerializableValue(payload) ? payload : undefined;\n}\n\nfunction createRemoteDomReactEvent(\n eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n): Event {\n const customDetail = parseCustomEventDetail(eventName, detail);\n const event = new CustomEvent(eventName, {\n bubbles: true,\n cancelable: true,\n detail: customDetail.ok ? customDetail.value : detail,\n });\n if (!isObjectRecord(detail)) return event;\n\n const key = readSerializableString(detail, \"key\");\n if (key !== undefined) setObjectProperty(event, \"key\", key);\n\n const eventType = readSerializableString(detail, \"type\");\n if (eventType !== undefined) setObjectProperty(event, \"inputType\", eventType);\n\n return event;\n}\n\nfunction parseCustomEventDetail(\n _eventName: string,\n detail: RemoteDomSerializableValue | undefined,\n):\n | { readonly ok: true; readonly value: RemoteDomSerializableValue }\n | { readonly ok: false } {\n if (!isObjectRecord(detail)) {\n return { ok: false };\n }\n const detailJson = detail.detailJson;\n if (typeof detailJson !== \"string\") return { ok: false };\n\n try {\n const value: unknown = JSON.parse(detailJson);\n return isRemoteDomSerializableValue(value)\n ? { ok: true, value }\n : { ok: false };\n } catch {\n return { ok: false };\n }\n}\n\nfunction readSerializableString(\n detail: Readonly<Record<string, unknown>>,\n key: string,\n): string | undefined {\n const value = detail[key];\n return typeof value === \"string\" ? value : undefined;\n}\n\nfunction setObjectProperty(target: object, key: string, value: unknown): void {\n Object.defineProperty(target, key, {\n configurable: true,\n enumerable: true,\n value,\n writable: true,\n });\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n"],"mappings":"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"}