@fluid-app/widget-runtime 0.1.4 → 0.1.6
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 +36 -0
- package/dist/index.cjs +3 -2
- package/dist/index.d.cts +3 -2
- package/dist/index.d.mts +3 -2
- package/dist/index.mjs +3 -3
- package/dist/{remote-dom-renderer-CKvnUH8G.d.mts → remote-dom-renderer-BGIZ0FRi.d.mts} +35 -1
- package/dist/remote-dom-renderer-BGIZ0FRi.d.mts.map +1 -0
- package/dist/{remote-dom-renderer-f7OWlvvv.cjs → remote-dom-renderer-BlZKfMAA.cjs} +340 -172
- package/dist/remote-dom-renderer-BlZKfMAA.cjs.map +1 -0
- package/dist/{remote-dom-renderer-CeYSItkU.d.cts → remote-dom-renderer-BoB9jd3B.d.cts} +35 -1
- package/dist/remote-dom-renderer-BoB9jd3B.d.cts.map +1 -0
- package/dist/{remote-dom-renderer-CpdKWANy.mjs → remote-dom-renderer-Dn3pfVsl.mjs} +340 -172
- package/dist/remote-dom-renderer-Dn3pfVsl.mjs.map +1 -0
- package/dist/remote-dom-ui-contract-B140dMly.d.mts +632 -0
- package/dist/remote-dom-ui-contract-B140dMly.d.mts.map +1 -0
- package/dist/remote-dom-ui-contract-BLOyWbT2.d.cts +632 -0
- package/dist/remote-dom-ui-contract-BLOyWbT2.d.cts.map +1 -0
- package/dist/remote-dom-values-B5UZPDRy.cjs +849 -0
- package/dist/remote-dom-values-B5UZPDRy.cjs.map +1 -0
- package/dist/remote-dom-values-D4AgBNWr.d.cts.map +1 -1
- package/dist/remote-dom-values-EwoLXnSn.d.mts.map +1 -1
- package/dist/remote-dom-values-wEbrw5iW.mjs +790 -0
- package/dist/remote-dom-values-wEbrw5iW.mjs.map +1 -0
- package/dist/remote-dom.cjs +2 -2
- package/dist/remote-dom.d.cts +1 -1
- package/dist/remote-dom.d.mts +1 -1
- package/dist/remote-dom.mjs +2 -2
- package/dist/{worker-react-renderer-BKzig_Vy.mjs → worker-react-renderer-BV6ExKCS.mjs} +17 -40
- package/dist/worker-react-renderer-BV6ExKCS.mjs.map +1 -0
- package/dist/{worker-react-renderer-BvHZ2o0B.cjs → worker-react-renderer-CR-TvErh.cjs} +18 -41
- package/dist/worker-react-renderer-CR-TvErh.cjs.map +1 -0
- package/dist/worker.cjs +18 -3
- package/dist/worker.cjs.map +1 -1
- package/dist/worker.d.cts +17 -2
- package/dist/worker.d.cts.map +1 -1
- package/dist/worker.d.mts +17 -1
- package/dist/worker.d.mts.map +1 -1
- package/dist/worker.mjs +17 -3
- package/dist/worker.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/remote-dom-renderer-CKvnUH8G.d.mts.map +0 -1
- package/dist/remote-dom-renderer-CeYSItkU.d.cts.map +0 -1
- package/dist/remote-dom-renderer-CpdKWANy.mjs.map +0 -1
- package/dist/remote-dom-renderer-f7OWlvvv.cjs.map +0 -1
- package/dist/remote-dom-values-BSAxrOE7.mjs +0 -238
- package/dist/remote-dom-values-BSAxrOE7.mjs.map +0 -1
- package/dist/remote-dom-values-DbgIedSg.cjs +0 -297
- package/dist/remote-dom-values-DbgIedSg.cjs.map +0 -1
- package/dist/worker-react-renderer-BKzig_Vy.mjs.map +0 -1
- package/dist/worker-react-renderer-BvHZ2o0B.cjs.map +0 -1
package/dist/worker.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.cjs","names":["isRemoteDomSerializableValue","isRemoteDomSerializableValue","Thread"],"sources":["../src/worker-lockdown.ts","../src/worker-capability-function.ts","../src/worker-network-access.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 \"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","type NativeFetch = typeof fetch;\n\nexport interface RemoteDomWorkerNetworkAccessSession {\n readonly granted: boolean;\n readonly hostOrigin?: string | undefined;\n}\n\ninterface NetworkAccessGuard {\n setSession(session: RemoteDomWorkerNetworkAccessSession): void;\n clearSession(): void;\n}\n\nconst guards = new WeakMap<object, NetworkAccessGuard>();\n\n/** Registered symbol so every module instance of this file sees the same\n * brand — a module-local `Symbol()` would duplicate exactly like the\n * WeakMap above and detect nothing. The brand carries no capability:\n * forging or stripping it never opens a network grant (every branch\n * still fails closed); it only keeps the duplicate-instance vs\n * native-pre-seal diagnosis trustworthy. */\nconst GUARDED_FETCH_BRAND = Symbol.for(\"fluid.remote-dom.guarded-fetch\");\n\nexport class RemoteDomDuplicateNetworkGuardError extends Error {\n constructor() {\n super(\n \"Remote DOM worker network guard is already installed by another \" +\n \"module instance of @fluid-app/widget-runtime. The dev server \" +\n \"served the worker SDK subgraph under two module URLs; previews \" +\n \"must resolve it to a single module instance.\",\n );\n this.name = \"RemoteDomDuplicateNetworkGuardError\";\n }\n}\n\nexport function prepareRemoteDomWorkerNetworkAccess(\n globals: object = globalThis,\n): void {\n if (guards.has(globals)) return;\n\n const existingFetch = Reflect.get(globals, \"fetch\") as unknown;\n if (\n typeof existingFetch === \"function\" &&\n Reflect.get(existingFetch, GUARDED_FETCH_BRAND) === true\n ) {\n throw new RemoteDomDuplicateNetworkGuardError();\n }\n\n const nativeFetch = readNativeFetch(globals);\n const NativeUrl = readNativeUrl(globals);\n const baseUrl = readBaseUrl(globals);\n let session: RemoteDomWorkerNetworkAccessSession = { granted: false };\n const guardedFetch: NativeFetch = (input, init) => {\n if (!session.granted) {\n return Promise.reject(\n new Error(\"Remote DOM worker network access is not granted.\"),\n );\n }\n\n const target = getFetchTarget(input, NativeUrl, baseUrl);\n if (!target) {\n return Promise.reject(\n new Error(\"Remote DOM worker cannot validate the fetch target.\"),\n );\n }\n if (isBlockedTarget(target, session.hostOrigin, NativeUrl)) {\n return Promise.reject(\n new Error(`Remote DOM worker cannot fetch ${target.origin}.`),\n );\n }\n return nativeFetch.call(globals, input, init);\n };\n\n // The sealed `fetch` property on globals does not freeze the guarded\n // function object itself, so the brand needs its own immutable\n // descriptor — a plain assignment could be deleted or forged by\n // same-realm widget code.\n Object.defineProperty(guardedFetch, GUARDED_FETCH_BRAND, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n Object.defineProperty(globals, \"fetch\", {\n configurable: false,\n enumerable: false,\n value: guardedFetch,\n writable: false,\n });\n guards.set(globals, {\n setSession(nextSession) {\n session = nextSession;\n },\n clearSession() {\n session = { granted: false };\n },\n });\n}\n\nexport function bindRemoteDomWorkerNetworkAccessSession(\n session: RemoteDomWorkerNetworkAccessSession,\n globals: object = globalThis,\n): () => void {\n prepareRemoteDomWorkerNetworkAccess(globals);\n const guard = guards.get(globals);\n if (!guard) {\n throw new Error(\"Remote DOM worker network guard failed to initialize.\");\n }\n guard.setSession(session);\n return () => guard.clearSession();\n}\n\nfunction readNativeFetch(globals: object): NativeFetch {\n const candidate = Reflect.get(globals, \"fetch\") as unknown;\n if (typeof candidate !== \"function\") {\n return () =>\n Promise.reject(\n new Error(\"Remote DOM worker native fetch is unavailable.\"),\n );\n }\n return candidate as NativeFetch;\n}\n\nfunction readNativeUrl(globals: object): typeof URL {\n const candidate = Reflect.get(globals, \"URL\") as unknown;\n return typeof candidate === \"function\" ? (candidate as typeof URL) : URL;\n}\n\nfunction readBaseUrl(globals: object): string | undefined {\n const location = Reflect.get(globals, \"location\") as\n | { href?: unknown }\n | undefined;\n return typeof location?.href === \"string\" ? location.href : undefined;\n}\n\nfunction getFetchTarget(\n input: RequestInfo | URL,\n NativeUrl: typeof URL,\n baseUrl: string | undefined,\n): URL | undefined {\n let value: string;\n if (typeof input === \"string\") value = input;\n else if (input instanceof NativeUrl) value = input.href;\n else if (typeof input.url === \"string\") value = input.url;\n else return undefined;\n\n try {\n return new NativeUrl(value, baseUrl);\n } catch {\n return undefined;\n }\n}\n\nfunction isBlockedTarget(\n target: URL,\n hostOrigin: string | undefined,\n NativeUrl: typeof URL,\n): boolean {\n if (target.protocol !== \"http:\" && target.protocol !== \"https:\") return false;\n\n if (hostOrigin) {\n try {\n const host = new NativeUrl(hostOrigin);\n if (\n target.protocol === host.protocol &&\n normalizeHostname(target.hostname) ===\n normalizeHostname(host.hostname) &&\n target.port === host.port\n ) {\n return true;\n }\n } catch {\n return true;\n }\n }\n\n const hostname = normalizeHostname(target.hostname);\n if (\n hostname === \"fluid.app\" ||\n hostname.endsWith(\".fluid.app\") ||\n hostname === \"localhost\" ||\n hostname.endsWith(\".localhost\")\n ) {\n return true;\n }\n return isPrivateIpv4(hostname) || isPrivateIpv6(hostname);\n}\n\nfunction normalizeHostname(hostname: string): string {\n return hostname\n .toLowerCase()\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\");\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\");\n if (parts.length !== 4) return false;\n const octets = parts.map(Number);\n if (\n octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)\n ) {\n return false;\n }\n const first = octets[0];\n const second = octets[1];\n if (first === undefined || second === undefined) return false;\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168)\n );\n}\n\nfunction isPrivateIpv6(hostname: string): boolean {\n if (!hostname.includes(\":\")) return false;\n const normalized = hostname.toLowerCase();\n if (normalized === \"::\" || normalized === \"::1\") return true;\n const firstGroup = normalized.split(\":\")[0] ?? \"\";\n const firstValue = Number.parseInt(firstGroup || \"0\", 16);\n if ((firstValue & 0xfe00) === 0xfc00 || (firstValue & 0xffc0) === 0xfe80) {\n return true;\n }\n const mappedIpv4 = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/.exec(normalized)?.[1];\n if (mappedIpv4) return isPrivateIpv4(mappedIpv4);\n\n const mappedHex = /^::ffff:([\\da-f]{1,4}):([\\da-f]{1,4})$/.exec(normalized);\n if (!mappedHex) return false;\n const high = Number.parseInt(mappedHex[1] ?? \"\", 16);\n const low = Number.parseInt(mappedHex[2] ?? \"\", 16);\n return isPrivateIpv4(`${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`);\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\";\nimport {\n bindRemoteDomWorkerNetworkAccessSession,\n prepareRemoteDomWorkerNetworkAccess,\n} from \"./worker-network-access\";\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 readonly networkAccessGranted?: boolean | undefined;\n readonly hostOrigin?: string | undefined;\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\nexport function prepareRemoteDomWidgetWorker(): void {\n prepareRemoteDomWorkerNetworkAccess();\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 const lockdownGlobals = testEnvironment?.lockdownGlobals ?? globalThis;\n const networkGuardEnabled = testEnvironment?.disableLockdown !== true;\n\n if (networkGuardEnabled) {\n try {\n prepareRemoteDomWorkerNetworkAccess(lockdownGlobals);\n } catch (error) {\n failClosedWorkerOnNetworkGuardError(workerSelf, error);\n }\n }\n\n if (testEnvironment?.disableLockdown !== true) {\n const lockdownResult = lockdownRemoteDomWorkerGlobals({\n globals: 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 let clearNetworkAccessSession: (() => void) | undefined;\n /** One stable context value per MOUNT, not per render.\n *\n * `host` is fixed for the whole mount, so this closure is\n * semantically constant — but building it inline in render() gave it\n * a fresh identity every time. useRemoteDomCapability memoizes on\n * `[callCapability, name]`, so every render handed consumers a brand\n * new capability object and re-fired any effect keyed on it. Paired\n * with the portal calling updateProps on every parent re-render\n * (build-widget-registry serializes props into a fresh object each\n * time), that turned into one host RPC per re-render even when no\n * value changed. */\n let capabilityValue: CallCapability | 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 currentWidget = widget;\n const node = createElement(currentWidget, toComponentProps(props));\n renderer.render(\n createElement(\n RemoteDomCapabilityContext.Provider,\n { value: capabilityValue },\n node,\n ),\n );\n };\n\n const disposeMount = (): void => {\n if (\n !mounted &&\n !renderer &&\n !host &&\n !clearCapabilitySession &&\n !clearNetworkAccessSession\n )\n return;\n\n const mountedRenderer = renderer;\n const retainedHost = host;\n const clearMountedCapabilitySession = clearCapabilitySession;\n const clearMountedNetworkAccessSession = clearNetworkAccessSession;\n renderer = undefined;\n host = undefined;\n props = undefined;\n widget = undefined;\n clearCapabilitySession = undefined;\n clearNetworkAccessSession = undefined;\n // Released with the mount it belongs to, so a remount cannot hand\n // the next widget a closure over the previous host.\n capabilityValue = undefined;\n mounted = false;\n\n const errors: unknown[] = [];\n try {\n clearMountedCapabilitySession?.();\n } catch (error) {\n errors.push(error);\n }\n try {\n clearMountedNetworkAccessSession?.();\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 // Built once here, not per render — see capabilityValue above.\n capabilityValue = (capability, method, payload) =>\n nextHost.callCapability(capability, method, payload);\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 if (networkGuardEnabled) {\n clearNetworkAccessSession = bindRemoteDomWorkerNetworkAccessSession(\n {\n granted: init.networkAccessGranted === true,\n hostOrigin: init.hostOrigin,\n },\n lockdownGlobals,\n );\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 // The mount sets `mounted` before awaiting the renderer module, so\n // there is a real window where the widget is mounting but has no\n // renderer yet. Storing the props is the whole job in that window:\n // the in-flight mount ends in its own render() call and picks them\n // up, so the newer props win either way.\n //\n // Rendering here instead would throw \"has not been mounted\",\n // report a fatal error to the host, and reject — for a widget that\n // goes on to paint correctly. The portal calls updateProps from an\n // effect keyed on a freshly-serialized props object every parent\n // render (build-widget-registry.ts), and wires onError straight\n // into setError, so that lands as a permanent \"Unable to render\"\n // alert over a working widget.\n if (!renderer) return;\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 shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker lockdown failed for globals: ${result.failedGlobals.join(\", \")}.`,\n );\n}\n\nfunction failClosedWorkerOnNetworkGuardError(\n workerSelf: RemoteDomWorkerGlobalScopeLike,\n error: unknown,\n): never {\n shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker network guard install failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n}\n\nfunction shutdownWorkerScope(workerSelf: RemoteDomWorkerGlobalScopeLike): void {\n try {\n workerSelf.onmessage = null;\n } catch {\n // The fail-closed error still prevents the worker runtime from starting.\n }\n workerSelf.close?.();\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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"}
|
|
1
|
+
{"version":3,"file":"worker.cjs","names":["isRemoteDomSerializableValue","isRemoteDomSerializableValue","Thread"],"sources":["../src/worker-lockdown.ts","../src/worker-capability-function.ts","../src/worker-network-access.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 \"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","type NativeFetch = typeof fetch;\n\nexport interface RemoteDomWorkerNetworkAccessSession {\n readonly granted: boolean;\n readonly hostOrigin?: string | undefined;\n}\n\ninterface NetworkAccessGuard {\n setSession(session: RemoteDomWorkerNetworkAccessSession): void;\n clearSession(): void;\n}\n\nconst guards = new WeakMap<object, NetworkAccessGuard>();\n\n/** Registered symbol so every module instance of this file sees the same\n * brand — a module-local `Symbol()` would duplicate exactly like the\n * WeakMap above and detect nothing. The brand carries no capability:\n * forging or stripping it never opens a network grant (every branch\n * still fails closed); it only keeps the duplicate-instance vs\n * native-pre-seal diagnosis trustworthy. */\nconst GUARDED_FETCH_BRAND = Symbol.for(\"fluid.remote-dom.guarded-fetch\");\n\nexport class RemoteDomDuplicateNetworkGuardError extends Error {\n constructor() {\n super(\n \"Remote DOM worker network guard is already installed by another \" +\n \"module instance of @fluid-app/widget-runtime. The dev server \" +\n \"served the worker SDK subgraph under two module URLs; previews \" +\n \"must resolve it to a single module instance.\",\n );\n this.name = \"RemoteDomDuplicateNetworkGuardError\";\n }\n}\n\nexport function prepareRemoteDomWorkerNetworkAccess(\n globals: object = globalThis,\n): void {\n if (guards.has(globals)) return;\n\n const existingFetch = Reflect.get(globals, \"fetch\") as unknown;\n if (\n typeof existingFetch === \"function\" &&\n Reflect.get(existingFetch, GUARDED_FETCH_BRAND) === true\n ) {\n throw new RemoteDomDuplicateNetworkGuardError();\n }\n\n const nativeFetch = readNativeFetch(globals);\n const NativeUrl = readNativeUrl(globals);\n const baseUrl = readBaseUrl(globals);\n let session: RemoteDomWorkerNetworkAccessSession = { granted: false };\n const guardedFetch: NativeFetch = (input, init) => {\n if (!session.granted) {\n return Promise.reject(\n new Error(\"Remote DOM worker network access is not granted.\"),\n );\n }\n\n const target = getFetchTarget(input, NativeUrl, baseUrl);\n if (!target) {\n return Promise.reject(\n new Error(\"Remote DOM worker cannot validate the fetch target.\"),\n );\n }\n if (isBlockedTarget(target, session.hostOrigin, NativeUrl)) {\n return Promise.reject(\n new Error(`Remote DOM worker cannot fetch ${target.origin}.`),\n );\n }\n return nativeFetch.call(globals, input, init);\n };\n\n // The sealed `fetch` property on globals does not freeze the guarded\n // function object itself, so the brand needs its own immutable\n // descriptor — a plain assignment could be deleted or forged by\n // same-realm widget code.\n Object.defineProperty(guardedFetch, GUARDED_FETCH_BRAND, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n Object.defineProperty(globals, \"fetch\", {\n configurable: false,\n enumerable: false,\n value: guardedFetch,\n writable: false,\n });\n guards.set(globals, {\n setSession(nextSession) {\n session = nextSession;\n },\n clearSession() {\n session = { granted: false };\n },\n });\n}\n\nexport function bindRemoteDomWorkerNetworkAccessSession(\n session: RemoteDomWorkerNetworkAccessSession,\n globals: object = globalThis,\n): () => void {\n prepareRemoteDomWorkerNetworkAccess(globals);\n const guard = guards.get(globals);\n if (!guard) {\n throw new Error(\"Remote DOM worker network guard failed to initialize.\");\n }\n guard.setSession(session);\n return () => guard.clearSession();\n}\n\nfunction readNativeFetch(globals: object): NativeFetch {\n const candidate = Reflect.get(globals, \"fetch\") as unknown;\n if (typeof candidate !== \"function\") {\n return () =>\n Promise.reject(\n new Error(\"Remote DOM worker native fetch is unavailable.\"),\n );\n }\n return candidate as NativeFetch;\n}\n\nfunction readNativeUrl(globals: object): typeof URL {\n const candidate = Reflect.get(globals, \"URL\") as unknown;\n return typeof candidate === \"function\" ? (candidate as typeof URL) : URL;\n}\n\nfunction readBaseUrl(globals: object): string | undefined {\n const location = Reflect.get(globals, \"location\") as\n | { href?: unknown }\n | undefined;\n return typeof location?.href === \"string\" ? location.href : undefined;\n}\n\nfunction getFetchTarget(\n input: RequestInfo | URL,\n NativeUrl: typeof URL,\n baseUrl: string | undefined,\n): URL | undefined {\n let value: string;\n if (typeof input === \"string\") value = input;\n else if (input instanceof NativeUrl) value = input.href;\n else if (typeof input.url === \"string\") value = input.url;\n else return undefined;\n\n try {\n return new NativeUrl(value, baseUrl);\n } catch {\n return undefined;\n }\n}\n\nfunction isBlockedTarget(\n target: URL,\n hostOrigin: string | undefined,\n NativeUrl: typeof URL,\n): boolean {\n if (target.protocol !== \"http:\" && target.protocol !== \"https:\") return false;\n\n if (hostOrigin) {\n try {\n const host = new NativeUrl(hostOrigin);\n if (\n target.protocol === host.protocol &&\n normalizeHostname(target.hostname) ===\n normalizeHostname(host.hostname) &&\n target.port === host.port\n ) {\n return true;\n }\n } catch {\n return true;\n }\n }\n\n const hostname = normalizeHostname(target.hostname);\n if (\n hostname === \"fluid.app\" ||\n hostname.endsWith(\".fluid.app\") ||\n hostname === \"localhost\" ||\n hostname.endsWith(\".localhost\")\n ) {\n return true;\n }\n return isPrivateIpv4(hostname) || isPrivateIpv6(hostname);\n}\n\nfunction normalizeHostname(hostname: string): string {\n return hostname\n .toLowerCase()\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\");\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\");\n if (parts.length !== 4) return false;\n const octets = parts.map(Number);\n if (\n octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)\n ) {\n return false;\n }\n const first = octets[0];\n const second = octets[1];\n if (first === undefined || second === undefined) return false;\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168)\n );\n}\n\nfunction isPrivateIpv6(hostname: string): boolean {\n if (!hostname.includes(\":\")) return false;\n const normalized = hostname.toLowerCase();\n if (normalized === \"::\" || normalized === \"::1\") return true;\n const firstGroup = normalized.split(\":\")[0] ?? \"\";\n const firstValue = Number.parseInt(firstGroup || \"0\", 16);\n if ((firstValue & 0xfe00) === 0xfc00 || (firstValue & 0xffc0) === 0xfe80) {\n return true;\n }\n const mappedIpv4 = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/.exec(normalized)?.[1];\n if (mappedIpv4) return isPrivateIpv4(mappedIpv4);\n\n const mappedHex = /^::ffff:([\\da-f]{1,4}):([\\da-f]{1,4})$/.exec(normalized);\n if (!mappedHex) return false;\n const high = Number.parseInt(mappedHex[1] ?? \"\", 16);\n const low = Number.parseInt(mappedHex[2] ?? \"\", 16);\n return isPrivateIpv4(`${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`);\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 { REMOTE_DOM_UI_CONTRACT_VERSION } from \"./remote-dom-ui-contract\";\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\";\nimport {\n bindRemoteDomWorkerNetworkAccessSession,\n prepareRemoteDomWorkerNetworkAccess,\n} from \"./worker-network-access\";\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 readonly supportedUiContractVersions?: readonly string[] | undefined;\n readonly networkAccessGranted?: boolean | undefined;\n readonly hostOrigin?: string | undefined;\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 /** Widget components keyed by the descriptor's exact widget type. */\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 /** Stops the worker thread and releases its active Remote DOM mount. */\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\n/**\n * Starts a worker that serves the supplied Remote DOM widget components.\n *\n * The selected host must support the worker's Fluid UI contract before the\n * component mounts. Portal SDK hosts configure this support automatically.\n */\nexport function startRemoteDomWidgetWorker(\n options: RemoteDomWidgetWorkerOptions,\n): RemoteDomWidgetWorkerController {\n return startRemoteDomWidgetWorkerInternal(options);\n}\n\n/**\n * Preserves the worker's native fetch implementation before Remote DOM\n * polyfills install browser-like globals.\n *\n * Call this before loading the React worker bootstrap. Widget packages created\n * by the Fluid tooling already call it in the generated worker entry.\n */\nexport function prepareRemoteDomWidgetWorker(): void {\n prepareRemoteDomWorkerNetworkAccess();\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 const lockdownGlobals = testEnvironment?.lockdownGlobals ?? globalThis;\n const networkGuardEnabled = testEnvironment?.disableLockdown !== true;\n\n if (networkGuardEnabled) {\n try {\n prepareRemoteDomWorkerNetworkAccess(lockdownGlobals);\n } catch (error) {\n failClosedWorkerOnNetworkGuardError(workerSelf, error);\n }\n }\n\n if (testEnvironment?.disableLockdown !== true) {\n const lockdownResult = lockdownRemoteDomWorkerGlobals({\n globals: 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 let clearNetworkAccessSession: (() => void) | undefined;\n /** One stable context value per MOUNT, not per render.\n *\n * `host` is fixed for the whole mount, so this closure is\n * semantically constant — but building it inline in render() gave it\n * a fresh identity every time. useRemoteDomCapability memoizes on\n * `[callCapability, name]`, so every render handed consumers a brand\n * new capability object and re-fired any effect keyed on it. Paired\n * with the portal calling updateProps on every parent re-render\n * (build-widget-registry serializes props into a fresh object each\n * time), that turned into one host RPC per re-render even when no\n * value changed. */\n let capabilityValue: CallCapability | 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 currentWidget = widget;\n const node = createElement(currentWidget, toComponentProps(props));\n renderer.render(\n createElement(\n RemoteDomCapabilityContext.Provider,\n { value: capabilityValue },\n node,\n ),\n );\n };\n\n const disposeMount = (): void => {\n if (\n !mounted &&\n !renderer &&\n !host &&\n !clearCapabilitySession &&\n !clearNetworkAccessSession\n )\n return;\n\n const mountedRenderer = renderer;\n const retainedHost = host;\n const clearMountedCapabilitySession = clearCapabilitySession;\n const clearMountedNetworkAccessSession = clearNetworkAccessSession;\n renderer = undefined;\n host = undefined;\n props = undefined;\n widget = undefined;\n clearCapabilitySession = undefined;\n clearNetworkAccessSession = undefined;\n // Released with the mount it belongs to, so a remount cannot hand\n // the next widget a closure over the previous host.\n capabilityValue = undefined;\n mounted = false;\n\n const errors: unknown[] = [];\n try {\n clearMountedCapabilitySession?.();\n } catch (error) {\n errors.push(error);\n }\n try {\n clearMountedNetworkAccessSession?.();\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 if (\n !init.supportedUiContractVersions?.includes(\n REMOTE_DOM_UI_CONTRACT_VERSION,\n )\n ) {\n throw new Error(\n `Remote DOM widget requires Fluid UI contract ${REMOTE_DOM_UI_CONTRACT_VERSION}, which this host does not support.`,\n );\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 // Built once here, not per render — see capabilityValue above.\n capabilityValue = (capability, method, payload) =>\n nextHost.callCapability(capability, method, payload);\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 if (networkGuardEnabled) {\n clearNetworkAccessSession = bindRemoteDomWorkerNetworkAccessSession(\n {\n granted: init.networkAccessGranted === true,\n hostOrigin: init.hostOrigin,\n },\n lockdownGlobals,\n );\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 // The mount sets `mounted` before awaiting the renderer module, so\n // there is a real window where the widget is mounting but has no\n // renderer yet. Storing the props is the whole job in that window:\n // the in-flight mount ends in its own render() call and picks them\n // up, so the newer props win either way.\n //\n // Rendering here instead would throw \"has not been mounted\",\n // report a fatal error to the host, and reject — for a widget that\n // goes on to paint correctly. The portal calls updateProps from an\n // effect keyed on a freshly-serialized props object every parent\n // render (build-widget-registry.ts), and wires onError straight\n // into setError, so that lands as a permanent \"Unable to render\"\n // alert over a working widget.\n if (!renderer) return;\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 shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker lockdown failed for globals: ${result.failedGlobals.join(\", \")}.`,\n );\n}\n\nfunction failClosedWorkerOnNetworkGuardError(\n workerSelf: RemoteDomWorkerGlobalScopeLike,\n error: unknown,\n): never {\n shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker network guard install failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n}\n\nfunction shutdownWorkerScope(workerSelf: RemoteDomWorkerGlobalScopeLike): void {\n try {\n workerSelf.onmessage = null;\n } catch {\n // The fail-closed error still prevents the worker runtime from starting.\n }\n workerSelf.close?.();\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/dist/worker.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as RemoteDomSerializableValue } from "./remote-dom-values-D4AgBNWr.cjs";
|
|
2
|
+
import { i as RemoteDomUiValueCodec, n as RemoteDomUiComponentName, r as RemoteDomUiComponentProps, t as REMOTE_DOM_UI_COMPONENTS } from "./remote-dom-ui-contract-BLOyWbT2.cjs";
|
|
2
3
|
import { ComponentType } from "react";
|
|
3
|
-
|
|
4
4
|
//#region src/worker-capability-function.d.ts
|
|
5
5
|
interface RemoteDomCapabilityDeclaration {
|
|
6
6
|
readonly name: string;
|
|
@@ -31,17 +31,32 @@ interface RemoteDomWidgetWorkerDefinition {
|
|
|
31
31
|
}
|
|
32
32
|
type RemoteDomWidgetWorkerEntry = RemoteDomWidgetComponent | RemoteDomWidgetWorkerDefinition;
|
|
33
33
|
interface RemoteDomWidgetWorkerOptions {
|
|
34
|
+
/** Widget components keyed by the descriptor's exact widget type. */
|
|
34
35
|
readonly widgets: Readonly<Record<string, RemoteDomWidgetWorkerEntry>>;
|
|
35
36
|
}
|
|
36
37
|
interface RemoteDomWidgetWorkerController {
|
|
38
|
+
/** Stops the worker thread and releases its active Remote DOM mount. */
|
|
37
39
|
dispose(): void;
|
|
38
40
|
}
|
|
39
41
|
interface RemoteDomCapability {
|
|
40
42
|
call(method: string, payload?: RemoteDomSerializableValue): Promise<RemoteDomSerializableValue>;
|
|
41
43
|
}
|
|
42
44
|
declare function useRemoteDomCapability(name: string): RemoteDomCapability;
|
|
45
|
+
/**
|
|
46
|
+
* Starts a worker that serves the supplied Remote DOM widget components.
|
|
47
|
+
*
|
|
48
|
+
* The selected host must support the worker's Fluid UI contract before the
|
|
49
|
+
* component mounts. Portal SDK hosts configure this support automatically.
|
|
50
|
+
*/
|
|
43
51
|
declare function startRemoteDomWidgetWorker(options: RemoteDomWidgetWorkerOptions): RemoteDomWidgetWorkerController;
|
|
52
|
+
/**
|
|
53
|
+
* Preserves the worker's native fetch implementation before Remote DOM
|
|
54
|
+
* polyfills install browser-like globals.
|
|
55
|
+
*
|
|
56
|
+
* Call this before loading the React worker bootstrap. Widget packages created
|
|
57
|
+
* by the Fluid tooling already call it in the generated worker entry.
|
|
58
|
+
*/
|
|
44
59
|
declare function prepareRemoteDomWidgetWorker(): void;
|
|
45
60
|
//#endregion
|
|
46
|
-
export { type RemoteDomCapability, type RemoteDomCapabilityDeclaration, type RemoteDomCapabilityFunction, RemoteDomCapabilityFunctionError, type RemoteDomCapabilityFunctionErrorCode, type RemoteDomCapabilityFunctionMetadata, type RemoteDomSerializableValue, type RemoteDomWidgetWorkerController, type RemoteDomWidgetWorkerDefinition, type RemoteDomWidgetWorkerEntry, type RemoteDomWidgetWorkerOptions, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, prepareRemoteDomWidgetWorker, startRemoteDomWidgetWorker, useRemoteDomCapability };
|
|
61
|
+
export { REMOTE_DOM_UI_COMPONENTS, type RemoteDomCapability, type RemoteDomCapabilityDeclaration, type RemoteDomCapabilityFunction, RemoteDomCapabilityFunctionError, type RemoteDomCapabilityFunctionErrorCode, type RemoteDomCapabilityFunctionMetadata, type RemoteDomSerializableValue, type RemoteDomUiComponentName, type RemoteDomUiComponentProps, type RemoteDomUiValueCodec, type RemoteDomWidgetWorkerController, type RemoteDomWidgetWorkerDefinition, type RemoteDomWidgetWorkerEntry, type RemoteDomWidgetWorkerOptions, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, prepareRemoteDomWidgetWorker, startRemoteDomWidgetWorker, useRemoteDomCapability };
|
|
47
62
|
//# sourceMappingURL=worker.d.cts.map
|
package/dist/worker.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.cts","names":[],"sources":["../src/worker-capability-function.ts","../src/worker-runtime.ts"],"mappings":";;;;UAGiB,8BAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGM,mCAAA;EAAA,SACN,UAAA;EAAA,SACA,OAAA;EAAA,SACA,MAAA;AAAA;AAAA,KAGC,oCAAA;AAAA,cAMC,gCAAA,SAAyC,KAAA;EAAA,SAClC,IAAA;EAAA,SACT,IAAA,EAAM,oCAAA;cAEH,IAAA,EAAM,oCAAA,EAAsC,OAAA;AAAA;AAAA,KAM9C,2BAAA,gBACK,0BAAA,gBACD,0BAAA,mBACX,KAAA,yBACK,OAAA,CAAQ,MAAA,KACb,KAAA,EAAO,KAAA,KAAU,OAAA,CAAQ,MAAA;AAAA,iBAkBd,iCAAA,gBACC,0BAAA,gBACD,0BAAA,eAAA,CAEd,QAAA,EAAU,mCAAA,GACT,2BAAA,CAA4B,MAAA,EAAQ,KAAA;AAAA,iBAoEvB,sCAAA,CACd,KAAA,YACC,mCAAA;;;
|
|
1
|
+
{"version":3,"file":"worker.d.cts","names":[],"sources":["../src/worker-capability-function.ts","../src/worker-runtime.ts"],"mappings":";;;;UAGiB,8BAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGM,mCAAA;EAAA,SACN,UAAA;EAAA,SACA,OAAA;EAAA,SACA,MAAA;AAAA;AAAA,KAGC,oCAAA;AAAA,cAMC,gCAAA,SAAyC,KAAA;EAAA,SAClC,IAAA;EAAA,SACT,IAAA,EAAM,oCAAA;cAEH,IAAA,EAAM,oCAAA,EAAsC,OAAA;AAAA;AAAA,KAM9C,2BAAA,gBACK,0BAAA,gBACD,0BAAA,mBACX,KAAA,yBACK,OAAA,CAAQ,MAAA,KACb,KAAA,EAAO,KAAA,KAAU,OAAA,CAAQ,MAAA;AAAA,iBAkBd,iCAAA,gBACC,0BAAA,gBACD,0BAAA,eAAA,CAEd,QAAA,EAAU,mCAAA,GACT,2BAAA,CAA4B,MAAA,EAAQ,KAAA;AAAA,iBAoEvB,sCAAA,CACd,KAAA,YACC,mCAAA;;;KC5DE,wBAAA,GAA2B,aAAA,CAC9B,QAAA,CAAS,MAAA;AAAA,UAGM,+BAAA;EAAA,SACN,SAAA,EAAW,wBAAA;EAAA,SACX,YAAA,WAAuB,8BAAA;EDpDvB;EAAA,SCsDA,SAAA,YAAqB,mCAAA;AAAA;AAAA,KAGpB,0BAAA,GACR,wBAAA,GACA,+BAAA;AAAA,UAEa,4BAAA;ED3DyC;EAAA,SC6D/C,OAAA,EAAS,QAAA,CAAS,MAAA,SAAe,0BAAA;AAAA;AAAA,UAS3B,+BAAA;ED5DC;EC8DhB,OAAA;AAAA;AAAA,UAGe,mBAAA;EACf,IAAA,CACE,MAAA,UACA,OAAA,GAAU,0BAAA,GACT,OAAA,CAAQ,0BAAA;AAAA;AAAA,iBAaG,sBAAA,CAAuB,IAAA,WAAe,mBAAA;;;;;;;iBAqCtC,0BAAA,CACd,OAAA,EAAS,4BAAA,GACR,+BAAA;;;;;;;ADtGH;iBCiHgB,4BAAA,CAAA"}
|
package/dist/worker.d.mts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { n as RemoteDomSerializableValue } from "./remote-dom-values-EwoLXnSn.mjs";
|
|
2
|
+
import { i as RemoteDomUiValueCodec, n as RemoteDomUiComponentName, r as RemoteDomUiComponentProps, t as REMOTE_DOM_UI_COMPONENTS } from "./remote-dom-ui-contract-B140dMly.mjs";
|
|
2
3
|
import { ComponentType } from "react";
|
|
3
4
|
|
|
4
5
|
//#region src/worker-capability-function.d.ts
|
|
@@ -31,17 +32,32 @@ interface RemoteDomWidgetWorkerDefinition {
|
|
|
31
32
|
}
|
|
32
33
|
type RemoteDomWidgetWorkerEntry = RemoteDomWidgetComponent | RemoteDomWidgetWorkerDefinition;
|
|
33
34
|
interface RemoteDomWidgetWorkerOptions {
|
|
35
|
+
/** Widget components keyed by the descriptor's exact widget type. */
|
|
34
36
|
readonly widgets: Readonly<Record<string, RemoteDomWidgetWorkerEntry>>;
|
|
35
37
|
}
|
|
36
38
|
interface RemoteDomWidgetWorkerController {
|
|
39
|
+
/** Stops the worker thread and releases its active Remote DOM mount. */
|
|
37
40
|
dispose(): void;
|
|
38
41
|
}
|
|
39
42
|
interface RemoteDomCapability {
|
|
40
43
|
call(method: string, payload?: RemoteDomSerializableValue): Promise<RemoteDomSerializableValue>;
|
|
41
44
|
}
|
|
42
45
|
declare function useRemoteDomCapability(name: string): RemoteDomCapability;
|
|
46
|
+
/**
|
|
47
|
+
* Starts a worker that serves the supplied Remote DOM widget components.
|
|
48
|
+
*
|
|
49
|
+
* The selected host must support the worker's Fluid UI contract before the
|
|
50
|
+
* component mounts. Portal SDK hosts configure this support automatically.
|
|
51
|
+
*/
|
|
43
52
|
declare function startRemoteDomWidgetWorker(options: RemoteDomWidgetWorkerOptions): RemoteDomWidgetWorkerController;
|
|
53
|
+
/**
|
|
54
|
+
* Preserves the worker's native fetch implementation before Remote DOM
|
|
55
|
+
* polyfills install browser-like globals.
|
|
56
|
+
*
|
|
57
|
+
* Call this before loading the React worker bootstrap. Widget packages created
|
|
58
|
+
* by the Fluid tooling already call it in the generated worker entry.
|
|
59
|
+
*/
|
|
44
60
|
declare function prepareRemoteDomWidgetWorker(): void;
|
|
45
61
|
//#endregion
|
|
46
|
-
export { type RemoteDomCapability, type RemoteDomCapabilityDeclaration, type RemoteDomCapabilityFunction, RemoteDomCapabilityFunctionError, type RemoteDomCapabilityFunctionErrorCode, type RemoteDomCapabilityFunctionMetadata, type RemoteDomSerializableValue, type RemoteDomWidgetWorkerController, type RemoteDomWidgetWorkerDefinition, type RemoteDomWidgetWorkerEntry, type RemoteDomWidgetWorkerOptions, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, prepareRemoteDomWidgetWorker, startRemoteDomWidgetWorker, useRemoteDomCapability };
|
|
62
|
+
export { REMOTE_DOM_UI_COMPONENTS, type RemoteDomCapability, type RemoteDomCapabilityDeclaration, type RemoteDomCapabilityFunction, RemoteDomCapabilityFunctionError, type RemoteDomCapabilityFunctionErrorCode, type RemoteDomCapabilityFunctionMetadata, type RemoteDomSerializableValue, type RemoteDomUiComponentName, type RemoteDomUiComponentProps, type RemoteDomUiValueCodec, type RemoteDomWidgetWorkerController, type RemoteDomWidgetWorkerDefinition, type RemoteDomWidgetWorkerEntry, type RemoteDomWidgetWorkerOptions, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, prepareRemoteDomWidgetWorker, startRemoteDomWidgetWorker, useRemoteDomCapability };
|
|
47
63
|
//# sourceMappingURL=worker.d.mts.map
|
package/dist/worker.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.d.mts","names":[],"sources":["../src/worker-capability-function.ts","../src/worker-runtime.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"worker.d.mts","names":[],"sources":["../src/worker-capability-function.ts","../src/worker-runtime.ts"],"mappings":";;;;;UAGiB,8BAAA;EAAA,SACN,IAAA;EAAA,SACA,OAAA;AAAA;AAAA,UAGM,mCAAA;EAAA,SACN,UAAA;EAAA,SACA,OAAA;EAAA,SACA,MAAA;AAAA;AAAA,KAGC,oCAAA;AAAA,cAMC,gCAAA,SAAyC,KAAA;EAAA,SAClC,IAAA;EAAA,SACT,IAAA,EAAM,oCAAA;cAEH,IAAA,EAAM,oCAAA,EAAsC,OAAA;AAAA;AAAA,KAM9C,2BAAA,gBACK,0BAAA,gBACD,0BAAA,mBACX,KAAA,yBACK,OAAA,CAAQ,MAAA,KACb,KAAA,EAAO,KAAA,KAAU,OAAA,CAAQ,MAAA;AAAA,iBAkBd,iCAAA,gBACC,0BAAA,gBACD,0BAAA,eAAA,CAEd,QAAA,EAAU,mCAAA,GACT,2BAAA,CAA4B,MAAA,EAAQ,KAAA;AAAA,iBAoEvB,sCAAA,CACd,KAAA,YACC,mCAAA;;;KC5DE,wBAAA,GAA2B,aAAA,CAC9B,QAAA,CAAS,MAAA;AAAA,UAGM,+BAAA;EAAA,SACN,SAAA,EAAW,wBAAA;EAAA,SACX,YAAA,WAAuB,8BAAA;EDpDvB;EAAA,SCsDA,SAAA,YAAqB,mCAAA;AAAA;AAAA,KAGpB,0BAAA,GACR,wBAAA,GACA,+BAAA;AAAA,UAEa,4BAAA;ED3DyC;EAAA,SC6D/C,OAAA,EAAS,QAAA,CAAS,MAAA,SAAe,0BAAA;AAAA;AAAA,UAS3B,+BAAA;ED5DC;EC8DhB,OAAA;AAAA;AAAA,UAGe,mBAAA;EACf,IAAA,CACE,MAAA,UACA,OAAA,GAAU,0BAAA,GACT,OAAA,CAAQ,0BAAA;AAAA;AAAA,iBAaG,sBAAA,CAAuB,IAAA,WAAe,mBAAA;;;;;;;iBAqCtC,0BAAA,CACd,OAAA,EAAS,4BAAA,GACR,+BAAA;;;;;;;ADtGH;iBCiHgB,4BAAA,CAAA"}
|
package/dist/worker.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { n as release, r as retain, t as Thread } from "./Thread-BiW7rXts.mjs";
|
|
2
|
-
import {
|
|
2
|
+
import { a as isRemoteDomSerializableValue, l as REMOTE_DOM_UI_COMPONENTS } from "./remote-dom-values-wEbrw5iW.mjs";
|
|
3
3
|
import { createContext, createElement, useContext, useMemo } from "react";
|
|
4
4
|
//#region src/worker-lockdown.ts
|
|
5
5
|
const DISALLOWED_GLOBAL_NAMES = [
|
|
@@ -244,9 +244,22 @@ function useRemoteDomCapability(name) {
|
|
|
244
244
|
return callCapability(name, method, payload);
|
|
245
245
|
} }), [callCapability, name]);
|
|
246
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Starts a worker that serves the supplied Remote DOM widget components.
|
|
249
|
+
*
|
|
250
|
+
* The selected host must support the worker's Fluid UI contract before the
|
|
251
|
+
* component mounts. Portal SDK hosts configure this support automatically.
|
|
252
|
+
*/
|
|
247
253
|
function startRemoteDomWidgetWorker(options) {
|
|
248
254
|
return startRemoteDomWidgetWorkerInternal(options);
|
|
249
255
|
}
|
|
256
|
+
/**
|
|
257
|
+
* Preserves the worker's native fetch implementation before Remote DOM
|
|
258
|
+
* polyfills install browser-like globals.
|
|
259
|
+
*
|
|
260
|
+
* Call this before loading the React worker bootstrap. Widget packages created
|
|
261
|
+
* by the Fluid tooling already call it in the generated worker entry.
|
|
262
|
+
*/
|
|
250
263
|
function prepareRemoteDomWidgetWorker() {
|
|
251
264
|
prepareRemoteDomWorkerNetworkAccess();
|
|
252
265
|
}
|
|
@@ -332,6 +345,7 @@ function startRemoteDomWidgetWorkerInternal(options, testEnvironment) {
|
|
|
332
345
|
if (mounted || renderer || host) throw new Error("Remote DOM widget worker is already mounted.");
|
|
333
346
|
if (init.widgetType.length === 0) throw new Error("Remote DOM widget type cannot be empty.");
|
|
334
347
|
if (!isRemoteDomSerializableValue(init.props)) throw new Error("Remote DOM widget props must be serializable.");
|
|
348
|
+
if (!init.supportedUiContractVersions?.includes("2")) throw new Error(`Remote DOM widget requires Fluid UI contract 2, which this host does not support.`);
|
|
335
349
|
const selectedEntry = options.widgets[init.widgetType];
|
|
336
350
|
if (!selectedEntry) throw new Error(`Remote DOM worker does not contain widget type ${init.widgetType}.`);
|
|
337
351
|
const selectedWidget = normalizeWidgetEntry(selectedEntry);
|
|
@@ -427,7 +441,7 @@ function assertWorkerActive(disposed) {
|
|
|
427
441
|
function loadRemoteDomWorkerReactRendererModule() {
|
|
428
442
|
if (!remoteDomReactWorkerRendererModulePromise) remoteDomReactWorkerRendererModulePromise = (async () => {
|
|
429
443
|
await import("./worker-react-bootstrap-C7tCMYGA.mjs");
|
|
430
|
-
return import("./worker-react-renderer-
|
|
444
|
+
return import("./worker-react-renderer-BV6ExKCS.mjs");
|
|
431
445
|
})().catch((error) => {
|
|
432
446
|
remoteDomReactWorkerRendererModulePromise = void 0;
|
|
433
447
|
throw error;
|
|
@@ -480,6 +494,6 @@ function isObjectRecord(value) {
|
|
|
480
494
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
481
495
|
}
|
|
482
496
|
//#endregion
|
|
483
|
-
export { RemoteDomCapabilityFunctionError, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, prepareRemoteDomWidgetWorker, startRemoteDomWidgetWorker, useRemoteDomCapability };
|
|
497
|
+
export { REMOTE_DOM_UI_COMPONENTS, RemoteDomCapabilityFunctionError, defineRemoteDomCapabilityFunction, getRemoteDomCapabilityFunctionMetadata, prepareRemoteDomWidgetWorker, startRemoteDomWidgetWorker, useRemoteDomCapability };
|
|
484
498
|
|
|
485
499
|
//# sourceMappingURL=worker.mjs.map
|
package/dist/worker.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"worker.mjs","names":[],"sources":["../src/worker-lockdown.ts","../src/worker-capability-function.ts","../src/worker-network-access.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 \"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","type NativeFetch = typeof fetch;\n\nexport interface RemoteDomWorkerNetworkAccessSession {\n readonly granted: boolean;\n readonly hostOrigin?: string | undefined;\n}\n\ninterface NetworkAccessGuard {\n setSession(session: RemoteDomWorkerNetworkAccessSession): void;\n clearSession(): void;\n}\n\nconst guards = new WeakMap<object, NetworkAccessGuard>();\n\n/** Registered symbol so every module instance of this file sees the same\n * brand — a module-local `Symbol()` would duplicate exactly like the\n * WeakMap above and detect nothing. The brand carries no capability:\n * forging or stripping it never opens a network grant (every branch\n * still fails closed); it only keeps the duplicate-instance vs\n * native-pre-seal diagnosis trustworthy. */\nconst GUARDED_FETCH_BRAND = Symbol.for(\"fluid.remote-dom.guarded-fetch\");\n\nexport class RemoteDomDuplicateNetworkGuardError extends Error {\n constructor() {\n super(\n \"Remote DOM worker network guard is already installed by another \" +\n \"module instance of @fluid-app/widget-runtime. The dev server \" +\n \"served the worker SDK subgraph under two module URLs; previews \" +\n \"must resolve it to a single module instance.\",\n );\n this.name = \"RemoteDomDuplicateNetworkGuardError\";\n }\n}\n\nexport function prepareRemoteDomWorkerNetworkAccess(\n globals: object = globalThis,\n): void {\n if (guards.has(globals)) return;\n\n const existingFetch = Reflect.get(globals, \"fetch\") as unknown;\n if (\n typeof existingFetch === \"function\" &&\n Reflect.get(existingFetch, GUARDED_FETCH_BRAND) === true\n ) {\n throw new RemoteDomDuplicateNetworkGuardError();\n }\n\n const nativeFetch = readNativeFetch(globals);\n const NativeUrl = readNativeUrl(globals);\n const baseUrl = readBaseUrl(globals);\n let session: RemoteDomWorkerNetworkAccessSession = { granted: false };\n const guardedFetch: NativeFetch = (input, init) => {\n if (!session.granted) {\n return Promise.reject(\n new Error(\"Remote DOM worker network access is not granted.\"),\n );\n }\n\n const target = getFetchTarget(input, NativeUrl, baseUrl);\n if (!target) {\n return Promise.reject(\n new Error(\"Remote DOM worker cannot validate the fetch target.\"),\n );\n }\n if (isBlockedTarget(target, session.hostOrigin, NativeUrl)) {\n return Promise.reject(\n new Error(`Remote DOM worker cannot fetch ${target.origin}.`),\n );\n }\n return nativeFetch.call(globals, input, init);\n };\n\n // The sealed `fetch` property on globals does not freeze the guarded\n // function object itself, so the brand needs its own immutable\n // descriptor — a plain assignment could be deleted or forged by\n // same-realm widget code.\n Object.defineProperty(guardedFetch, GUARDED_FETCH_BRAND, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n Object.defineProperty(globals, \"fetch\", {\n configurable: false,\n enumerable: false,\n value: guardedFetch,\n writable: false,\n });\n guards.set(globals, {\n setSession(nextSession) {\n session = nextSession;\n },\n clearSession() {\n session = { granted: false };\n },\n });\n}\n\nexport function bindRemoteDomWorkerNetworkAccessSession(\n session: RemoteDomWorkerNetworkAccessSession,\n globals: object = globalThis,\n): () => void {\n prepareRemoteDomWorkerNetworkAccess(globals);\n const guard = guards.get(globals);\n if (!guard) {\n throw new Error(\"Remote DOM worker network guard failed to initialize.\");\n }\n guard.setSession(session);\n return () => guard.clearSession();\n}\n\nfunction readNativeFetch(globals: object): NativeFetch {\n const candidate = Reflect.get(globals, \"fetch\") as unknown;\n if (typeof candidate !== \"function\") {\n return () =>\n Promise.reject(\n new Error(\"Remote DOM worker native fetch is unavailable.\"),\n );\n }\n return candidate as NativeFetch;\n}\n\nfunction readNativeUrl(globals: object): typeof URL {\n const candidate = Reflect.get(globals, \"URL\") as unknown;\n return typeof candidate === \"function\" ? (candidate as typeof URL) : URL;\n}\n\nfunction readBaseUrl(globals: object): string | undefined {\n const location = Reflect.get(globals, \"location\") as\n | { href?: unknown }\n | undefined;\n return typeof location?.href === \"string\" ? location.href : undefined;\n}\n\nfunction getFetchTarget(\n input: RequestInfo | URL,\n NativeUrl: typeof URL,\n baseUrl: string | undefined,\n): URL | undefined {\n let value: string;\n if (typeof input === \"string\") value = input;\n else if (input instanceof NativeUrl) value = input.href;\n else if (typeof input.url === \"string\") value = input.url;\n else return undefined;\n\n try {\n return new NativeUrl(value, baseUrl);\n } catch {\n return undefined;\n }\n}\n\nfunction isBlockedTarget(\n target: URL,\n hostOrigin: string | undefined,\n NativeUrl: typeof URL,\n): boolean {\n if (target.protocol !== \"http:\" && target.protocol !== \"https:\") return false;\n\n if (hostOrigin) {\n try {\n const host = new NativeUrl(hostOrigin);\n if (\n target.protocol === host.protocol &&\n normalizeHostname(target.hostname) ===\n normalizeHostname(host.hostname) &&\n target.port === host.port\n ) {\n return true;\n }\n } catch {\n return true;\n }\n }\n\n const hostname = normalizeHostname(target.hostname);\n if (\n hostname === \"fluid.app\" ||\n hostname.endsWith(\".fluid.app\") ||\n hostname === \"localhost\" ||\n hostname.endsWith(\".localhost\")\n ) {\n return true;\n }\n return isPrivateIpv4(hostname) || isPrivateIpv6(hostname);\n}\n\nfunction normalizeHostname(hostname: string): string {\n return hostname\n .toLowerCase()\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\");\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\");\n if (parts.length !== 4) return false;\n const octets = parts.map(Number);\n if (\n octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)\n ) {\n return false;\n }\n const first = octets[0];\n const second = octets[1];\n if (first === undefined || second === undefined) return false;\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168)\n );\n}\n\nfunction isPrivateIpv6(hostname: string): boolean {\n if (!hostname.includes(\":\")) return false;\n const normalized = hostname.toLowerCase();\n if (normalized === \"::\" || normalized === \"::1\") return true;\n const firstGroup = normalized.split(\":\")[0] ?? \"\";\n const firstValue = Number.parseInt(firstGroup || \"0\", 16);\n if ((firstValue & 0xfe00) === 0xfc00 || (firstValue & 0xffc0) === 0xfe80) {\n return true;\n }\n const mappedIpv4 = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/.exec(normalized)?.[1];\n if (mappedIpv4) return isPrivateIpv4(mappedIpv4);\n\n const mappedHex = /^::ffff:([\\da-f]{1,4}):([\\da-f]{1,4})$/.exec(normalized);\n if (!mappedHex) return false;\n const high = Number.parseInt(mappedHex[1] ?? \"\", 16);\n const low = Number.parseInt(mappedHex[2] ?? \"\", 16);\n return isPrivateIpv4(`${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`);\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\";\nimport {\n bindRemoteDomWorkerNetworkAccessSession,\n prepareRemoteDomWorkerNetworkAccess,\n} from \"./worker-network-access\";\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 readonly networkAccessGranted?: boolean | undefined;\n readonly hostOrigin?: string | undefined;\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\nexport function prepareRemoteDomWidgetWorker(): void {\n prepareRemoteDomWorkerNetworkAccess();\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 const lockdownGlobals = testEnvironment?.lockdownGlobals ?? globalThis;\n const networkGuardEnabled = testEnvironment?.disableLockdown !== true;\n\n if (networkGuardEnabled) {\n try {\n prepareRemoteDomWorkerNetworkAccess(lockdownGlobals);\n } catch (error) {\n failClosedWorkerOnNetworkGuardError(workerSelf, error);\n }\n }\n\n if (testEnvironment?.disableLockdown !== true) {\n const lockdownResult = lockdownRemoteDomWorkerGlobals({\n globals: 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 let clearNetworkAccessSession: (() => void) | undefined;\n /** One stable context value per MOUNT, not per render.\n *\n * `host` is fixed for the whole mount, so this closure is\n * semantically constant — but building it inline in render() gave it\n * a fresh identity every time. useRemoteDomCapability memoizes on\n * `[callCapability, name]`, so every render handed consumers a brand\n * new capability object and re-fired any effect keyed on it. Paired\n * with the portal calling updateProps on every parent re-render\n * (build-widget-registry serializes props into a fresh object each\n * time), that turned into one host RPC per re-render even when no\n * value changed. */\n let capabilityValue: CallCapability | 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 currentWidget = widget;\n const node = createElement(currentWidget, toComponentProps(props));\n renderer.render(\n createElement(\n RemoteDomCapabilityContext.Provider,\n { value: capabilityValue },\n node,\n ),\n );\n };\n\n const disposeMount = (): void => {\n if (\n !mounted &&\n !renderer &&\n !host &&\n !clearCapabilitySession &&\n !clearNetworkAccessSession\n )\n return;\n\n const mountedRenderer = renderer;\n const retainedHost = host;\n const clearMountedCapabilitySession = clearCapabilitySession;\n const clearMountedNetworkAccessSession = clearNetworkAccessSession;\n renderer = undefined;\n host = undefined;\n props = undefined;\n widget = undefined;\n clearCapabilitySession = undefined;\n clearNetworkAccessSession = undefined;\n // Released with the mount it belongs to, so a remount cannot hand\n // the next widget a closure over the previous host.\n capabilityValue = undefined;\n mounted = false;\n\n const errors: unknown[] = [];\n try {\n clearMountedCapabilitySession?.();\n } catch (error) {\n errors.push(error);\n }\n try {\n clearMountedNetworkAccessSession?.();\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 // Built once here, not per render — see capabilityValue above.\n capabilityValue = (capability, method, payload) =>\n nextHost.callCapability(capability, method, payload);\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 if (networkGuardEnabled) {\n clearNetworkAccessSession = bindRemoteDomWorkerNetworkAccessSession(\n {\n granted: init.networkAccessGranted === true,\n hostOrigin: init.hostOrigin,\n },\n lockdownGlobals,\n );\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 // The mount sets `mounted` before awaiting the renderer module, so\n // there is a real window where the widget is mounting but has no\n // renderer yet. Storing the props is the whole job in that window:\n // the in-flight mount ends in its own render() call and picks them\n // up, so the newer props win either way.\n //\n // Rendering here instead would throw \"has not been mounted\",\n // report a fatal error to the host, and reject — for a widget that\n // goes on to paint correctly. The portal calls updateProps from an\n // effect keyed on a freshly-serialized props object every parent\n // render (build-widget-registry.ts), and wires onError straight\n // into setError, so that lands as a permanent \"Unable to render\"\n // alert over a working widget.\n if (!renderer) return;\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 shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker lockdown failed for globals: ${result.failedGlobals.join(\", \")}.`,\n );\n}\n\nfunction failClosedWorkerOnNetworkGuardError(\n workerSelf: RemoteDomWorkerGlobalScopeLike,\n error: unknown,\n): never {\n shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker network guard install failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n}\n\nfunction shutdownWorkerScope(workerSelf: RemoteDomWorkerGlobalScopeLike): void {\n try {\n workerSelf.onmessage = null;\n } catch {\n // The fail-closed error still prevents the worker runtime from starting.\n }\n workerSelf.close?.();\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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"}
|
|
1
|
+
{"version":3,"file":"worker.mjs","names":[],"sources":["../src/worker-lockdown.ts","../src/worker-capability-function.ts","../src/worker-network-access.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 \"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","type NativeFetch = typeof fetch;\n\nexport interface RemoteDomWorkerNetworkAccessSession {\n readonly granted: boolean;\n readonly hostOrigin?: string | undefined;\n}\n\ninterface NetworkAccessGuard {\n setSession(session: RemoteDomWorkerNetworkAccessSession): void;\n clearSession(): void;\n}\n\nconst guards = new WeakMap<object, NetworkAccessGuard>();\n\n/** Registered symbol so every module instance of this file sees the same\n * brand — a module-local `Symbol()` would duplicate exactly like the\n * WeakMap above and detect nothing. The brand carries no capability:\n * forging or stripping it never opens a network grant (every branch\n * still fails closed); it only keeps the duplicate-instance vs\n * native-pre-seal diagnosis trustworthy. */\nconst GUARDED_FETCH_BRAND = Symbol.for(\"fluid.remote-dom.guarded-fetch\");\n\nexport class RemoteDomDuplicateNetworkGuardError extends Error {\n constructor() {\n super(\n \"Remote DOM worker network guard is already installed by another \" +\n \"module instance of @fluid-app/widget-runtime. The dev server \" +\n \"served the worker SDK subgraph under two module URLs; previews \" +\n \"must resolve it to a single module instance.\",\n );\n this.name = \"RemoteDomDuplicateNetworkGuardError\";\n }\n}\n\nexport function prepareRemoteDomWorkerNetworkAccess(\n globals: object = globalThis,\n): void {\n if (guards.has(globals)) return;\n\n const existingFetch = Reflect.get(globals, \"fetch\") as unknown;\n if (\n typeof existingFetch === \"function\" &&\n Reflect.get(existingFetch, GUARDED_FETCH_BRAND) === true\n ) {\n throw new RemoteDomDuplicateNetworkGuardError();\n }\n\n const nativeFetch = readNativeFetch(globals);\n const NativeUrl = readNativeUrl(globals);\n const baseUrl = readBaseUrl(globals);\n let session: RemoteDomWorkerNetworkAccessSession = { granted: false };\n const guardedFetch: NativeFetch = (input, init) => {\n if (!session.granted) {\n return Promise.reject(\n new Error(\"Remote DOM worker network access is not granted.\"),\n );\n }\n\n const target = getFetchTarget(input, NativeUrl, baseUrl);\n if (!target) {\n return Promise.reject(\n new Error(\"Remote DOM worker cannot validate the fetch target.\"),\n );\n }\n if (isBlockedTarget(target, session.hostOrigin, NativeUrl)) {\n return Promise.reject(\n new Error(`Remote DOM worker cannot fetch ${target.origin}.`),\n );\n }\n return nativeFetch.call(globals, input, init);\n };\n\n // The sealed `fetch` property on globals does not freeze the guarded\n // function object itself, so the brand needs its own immutable\n // descriptor — a plain assignment could be deleted or forged by\n // same-realm widget code.\n Object.defineProperty(guardedFetch, GUARDED_FETCH_BRAND, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n Object.defineProperty(globals, \"fetch\", {\n configurable: false,\n enumerable: false,\n value: guardedFetch,\n writable: false,\n });\n guards.set(globals, {\n setSession(nextSession) {\n session = nextSession;\n },\n clearSession() {\n session = { granted: false };\n },\n });\n}\n\nexport function bindRemoteDomWorkerNetworkAccessSession(\n session: RemoteDomWorkerNetworkAccessSession,\n globals: object = globalThis,\n): () => void {\n prepareRemoteDomWorkerNetworkAccess(globals);\n const guard = guards.get(globals);\n if (!guard) {\n throw new Error(\"Remote DOM worker network guard failed to initialize.\");\n }\n guard.setSession(session);\n return () => guard.clearSession();\n}\n\nfunction readNativeFetch(globals: object): NativeFetch {\n const candidate = Reflect.get(globals, \"fetch\") as unknown;\n if (typeof candidate !== \"function\") {\n return () =>\n Promise.reject(\n new Error(\"Remote DOM worker native fetch is unavailable.\"),\n );\n }\n return candidate as NativeFetch;\n}\n\nfunction readNativeUrl(globals: object): typeof URL {\n const candidate = Reflect.get(globals, \"URL\") as unknown;\n return typeof candidate === \"function\" ? (candidate as typeof URL) : URL;\n}\n\nfunction readBaseUrl(globals: object): string | undefined {\n const location = Reflect.get(globals, \"location\") as\n | { href?: unknown }\n | undefined;\n return typeof location?.href === \"string\" ? location.href : undefined;\n}\n\nfunction getFetchTarget(\n input: RequestInfo | URL,\n NativeUrl: typeof URL,\n baseUrl: string | undefined,\n): URL | undefined {\n let value: string;\n if (typeof input === \"string\") value = input;\n else if (input instanceof NativeUrl) value = input.href;\n else if (typeof input.url === \"string\") value = input.url;\n else return undefined;\n\n try {\n return new NativeUrl(value, baseUrl);\n } catch {\n return undefined;\n }\n}\n\nfunction isBlockedTarget(\n target: URL,\n hostOrigin: string | undefined,\n NativeUrl: typeof URL,\n): boolean {\n if (target.protocol !== \"http:\" && target.protocol !== \"https:\") return false;\n\n if (hostOrigin) {\n try {\n const host = new NativeUrl(hostOrigin);\n if (\n target.protocol === host.protocol &&\n normalizeHostname(target.hostname) ===\n normalizeHostname(host.hostname) &&\n target.port === host.port\n ) {\n return true;\n }\n } catch {\n return true;\n }\n }\n\n const hostname = normalizeHostname(target.hostname);\n if (\n hostname === \"fluid.app\" ||\n hostname.endsWith(\".fluid.app\") ||\n hostname === \"localhost\" ||\n hostname.endsWith(\".localhost\")\n ) {\n return true;\n }\n return isPrivateIpv4(hostname) || isPrivateIpv6(hostname);\n}\n\nfunction normalizeHostname(hostname: string): string {\n return hostname\n .toLowerCase()\n .replace(/^\\[|\\]$/g, \"\")\n .replace(/\\.$/, \"\");\n}\n\nfunction isPrivateIpv4(hostname: string): boolean {\n const parts = hostname.split(\".\");\n if (parts.length !== 4) return false;\n const octets = parts.map(Number);\n if (\n octets.some((part) => !Number.isInteger(part) || part < 0 || part > 255)\n ) {\n return false;\n }\n const first = octets[0];\n const second = octets[1];\n if (first === undefined || second === undefined) return false;\n return (\n first === 0 ||\n first === 10 ||\n first === 127 ||\n (first === 169 && second === 254) ||\n (first === 172 && second >= 16 && second <= 31) ||\n (first === 192 && second === 168)\n );\n}\n\nfunction isPrivateIpv6(hostname: string): boolean {\n if (!hostname.includes(\":\")) return false;\n const normalized = hostname.toLowerCase();\n if (normalized === \"::\" || normalized === \"::1\") return true;\n const firstGroup = normalized.split(\":\")[0] ?? \"\";\n const firstValue = Number.parseInt(firstGroup || \"0\", 16);\n if ((firstValue & 0xfe00) === 0xfc00 || (firstValue & 0xffc0) === 0xfe80) {\n return true;\n }\n const mappedIpv4 = /^::ffff:(\\d+\\.\\d+\\.\\d+\\.\\d+)$/.exec(normalized)?.[1];\n if (mappedIpv4) return isPrivateIpv4(mappedIpv4);\n\n const mappedHex = /^::ffff:([\\da-f]{1,4}):([\\da-f]{1,4})$/.exec(normalized);\n if (!mappedHex) return false;\n const high = Number.parseInt(mappedHex[1] ?? \"\", 16);\n const low = Number.parseInt(mappedHex[2] ?? \"\", 16);\n return isPrivateIpv4(`${high >> 8}.${high & 0xff}.${low >> 8}.${low & 0xff}`);\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 { REMOTE_DOM_UI_CONTRACT_VERSION } from \"./remote-dom-ui-contract\";\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\";\nimport {\n bindRemoteDomWorkerNetworkAccessSession,\n prepareRemoteDomWorkerNetworkAccess,\n} from \"./worker-network-access\";\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 readonly supportedUiContractVersions?: readonly string[] | undefined;\n readonly networkAccessGranted?: boolean | undefined;\n readonly hostOrigin?: string | undefined;\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 /** Widget components keyed by the descriptor's exact widget type. */\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 /** Stops the worker thread and releases its active Remote DOM mount. */\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\n/**\n * Starts a worker that serves the supplied Remote DOM widget components.\n *\n * The selected host must support the worker's Fluid UI contract before the\n * component mounts. Portal SDK hosts configure this support automatically.\n */\nexport function startRemoteDomWidgetWorker(\n options: RemoteDomWidgetWorkerOptions,\n): RemoteDomWidgetWorkerController {\n return startRemoteDomWidgetWorkerInternal(options);\n}\n\n/**\n * Preserves the worker's native fetch implementation before Remote DOM\n * polyfills install browser-like globals.\n *\n * Call this before loading the React worker bootstrap. Widget packages created\n * by the Fluid tooling already call it in the generated worker entry.\n */\nexport function prepareRemoteDomWidgetWorker(): void {\n prepareRemoteDomWorkerNetworkAccess();\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 const lockdownGlobals = testEnvironment?.lockdownGlobals ?? globalThis;\n const networkGuardEnabled = testEnvironment?.disableLockdown !== true;\n\n if (networkGuardEnabled) {\n try {\n prepareRemoteDomWorkerNetworkAccess(lockdownGlobals);\n } catch (error) {\n failClosedWorkerOnNetworkGuardError(workerSelf, error);\n }\n }\n\n if (testEnvironment?.disableLockdown !== true) {\n const lockdownResult = lockdownRemoteDomWorkerGlobals({\n globals: 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 let clearNetworkAccessSession: (() => void) | undefined;\n /** One stable context value per MOUNT, not per render.\n *\n * `host` is fixed for the whole mount, so this closure is\n * semantically constant — but building it inline in render() gave it\n * a fresh identity every time. useRemoteDomCapability memoizes on\n * `[callCapability, name]`, so every render handed consumers a brand\n * new capability object and re-fired any effect keyed on it. Paired\n * with the portal calling updateProps on every parent re-render\n * (build-widget-registry serializes props into a fresh object each\n * time), that turned into one host RPC per re-render even when no\n * value changed. */\n let capabilityValue: CallCapability | 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 currentWidget = widget;\n const node = createElement(currentWidget, toComponentProps(props));\n renderer.render(\n createElement(\n RemoteDomCapabilityContext.Provider,\n { value: capabilityValue },\n node,\n ),\n );\n };\n\n const disposeMount = (): void => {\n if (\n !mounted &&\n !renderer &&\n !host &&\n !clearCapabilitySession &&\n !clearNetworkAccessSession\n )\n return;\n\n const mountedRenderer = renderer;\n const retainedHost = host;\n const clearMountedCapabilitySession = clearCapabilitySession;\n const clearMountedNetworkAccessSession = clearNetworkAccessSession;\n renderer = undefined;\n host = undefined;\n props = undefined;\n widget = undefined;\n clearCapabilitySession = undefined;\n clearNetworkAccessSession = undefined;\n // Released with the mount it belongs to, so a remount cannot hand\n // the next widget a closure over the previous host.\n capabilityValue = undefined;\n mounted = false;\n\n const errors: unknown[] = [];\n try {\n clearMountedCapabilitySession?.();\n } catch (error) {\n errors.push(error);\n }\n try {\n clearMountedNetworkAccessSession?.();\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 if (\n !init.supportedUiContractVersions?.includes(\n REMOTE_DOM_UI_CONTRACT_VERSION,\n )\n ) {\n throw new Error(\n `Remote DOM widget requires Fluid UI contract ${REMOTE_DOM_UI_CONTRACT_VERSION}, which this host does not support.`,\n );\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 // Built once here, not per render — see capabilityValue above.\n capabilityValue = (capability, method, payload) =>\n nextHost.callCapability(capability, method, payload);\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 if (networkGuardEnabled) {\n clearNetworkAccessSession = bindRemoteDomWorkerNetworkAccessSession(\n {\n granted: init.networkAccessGranted === true,\n hostOrigin: init.hostOrigin,\n },\n lockdownGlobals,\n );\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 // The mount sets `mounted` before awaiting the renderer module, so\n // there is a real window where the widget is mounting but has no\n // renderer yet. Storing the props is the whole job in that window:\n // the in-flight mount ends in its own render() call and picks them\n // up, so the newer props win either way.\n //\n // Rendering here instead would throw \"has not been mounted\",\n // report a fatal error to the host, and reject — for a widget that\n // goes on to paint correctly. The portal calls updateProps from an\n // effect keyed on a freshly-serialized props object every parent\n // render (build-widget-registry.ts), and wires onError straight\n // into setError, so that lands as a permanent \"Unable to render\"\n // alert over a working widget.\n if (!renderer) return;\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 shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker lockdown failed for globals: ${result.failedGlobals.join(\", \")}.`,\n );\n}\n\nfunction failClosedWorkerOnNetworkGuardError(\n workerSelf: RemoteDomWorkerGlobalScopeLike,\n error: unknown,\n): never {\n shutdownWorkerScope(workerSelf);\n throw new Error(\n `Remote DOM worker network guard install failed: ${\n error instanceof Error ? error.message : String(error)\n }`,\n { cause: error },\n );\n}\n\nfunction shutdownWorkerScope(workerSelf: RemoteDomWorkerGlobalScopeLike): void {\n try {\n workerSelf.onmessage = null;\n } catch {\n // The fail-closed error still prevents the worker runtime from starting.\n }\n workerSelf.close?.();\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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"}
|