@fluid-app/widget-runtime 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +15 -1
  2. package/dist/index.cjs +1 -1
  3. package/dist/index.d.cts +1 -1
  4. package/dist/index.d.mts +1 -1
  5. package/dist/index.mjs +1 -1
  6. package/dist/{remote-dom-renderer-BU-73KvK.d.mts → remote-dom-renderer-CKvnUH8G.d.mts} +4 -1
  7. package/dist/remote-dom-renderer-CKvnUH8G.d.mts.map +1 -0
  8. package/dist/{remote-dom-renderer-DSHFetvm.d.cts → remote-dom-renderer-CeYSItkU.d.cts} +4 -1
  9. package/dist/remote-dom-renderer-CeYSItkU.d.cts.map +1 -0
  10. package/dist/{remote-dom-renderer-DcwcNPsu.mjs → remote-dom-renderer-CpdKWANy.mjs} +129 -20
  11. package/dist/remote-dom-renderer-CpdKWANy.mjs.map +1 -0
  12. package/dist/{remote-dom-renderer-DUQf80Nu.cjs → remote-dom-renderer-f7OWlvvv.cjs} +129 -20
  13. package/dist/remote-dom-renderer-f7OWlvvv.cjs.map +1 -0
  14. package/dist/remote-dom.cjs +1 -1
  15. package/dist/remote-dom.d.cts +1 -1
  16. package/dist/remote-dom.d.mts +1 -1
  17. package/dist/remote-dom.mjs +1 -1
  18. package/dist/{worker-react-renderer-BSFxMMf7.cjs → worker-react-renderer-BvHZ2o0B.cjs} +2 -2
  19. package/dist/{worker-react-renderer-BSFxMMf7.cjs.map → worker-react-renderer-BvHZ2o0B.cjs.map} +1 -1
  20. package/dist/worker.cjs +149 -7
  21. package/dist/worker.cjs.map +1 -1
  22. package/dist/worker.d.cts +2 -1
  23. package/dist/worker.d.cts.map +1 -1
  24. package/dist/worker.d.mts +2 -1
  25. package/dist/worker.d.mts.map +1 -1
  26. package/dist/worker.mjs +147 -6
  27. package/dist/worker.mjs.map +1 -1
  28. package/package.json +1 -1
  29. package/dist/remote-dom-renderer-BU-73KvK.d.mts.map +0 -1
  30. package/dist/remote-dom-renderer-DSHFetvm.d.cts.map +0 -1
  31. package/dist/remote-dom-renderer-DUQf80Nu.cjs.map +0 -1
  32. package/dist/remote-dom-renderer-DcwcNPsu.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"remote-dom-renderer-CpdKWANy.mjs","names":["isObjectRecord","REMOTE_DOM_ROOT_ID","collectArtifactUrls","REMOTE_DOM_ROOT_ID"],"sources":["../src/remote-dom-sanitizer.ts","../src/remote-dom-sanitizing-connection.ts","../src/remote-dom-styles.ts","../src/remote-dom-renderer.ts"],"sourcesContent":["import postcssParse from \"postcss/lib/parse\";\nimport valueParser from \"postcss-value-parser\";\n\nimport {\n FLUID_SEARCH_SORT_TAG_NAME,\n FLUID_SPACER_WIDGET_TAG_NAME,\n isRemoteDomSerializableValue,\n isSafeRemoteDomPropertyKey,\n REMOTE_DOM_ALLOWED_TAG_NAMES,\n REMOTE_DOM_SEARCH_SORT_EVENTS,\n SUPPORTED_REMOTE_DOM_EVENTS,\n} from \"./remote-dom-values\";\nimport type {\n RemoteDomSerializableValue,\n RemoteDomUrlOriginPolicy,\n} from \"./remote-dom-values\";\n\nconst REMOTE_DOM_DENIED_TAG_NAMES = new Set([\n \"applet\",\n \"base\",\n \"body\",\n \"embed\",\n \"frame\",\n \"frameset\",\n \"head\",\n \"html\",\n \"iframe\",\n \"link\",\n \"meta\",\n \"noscript\",\n \"object\",\n \"portal\",\n \"script\",\n \"slot\",\n \"style\",\n \"template\",\n \"title\",\n]);\n\nconst REMOTE_DOM_ALLOWED_TAG_NAME_SET = new Set<string>(\n REMOTE_DOM_ALLOWED_TAG_NAMES,\n);\n\nconst GLOBAL_ALLOWED_ATTRIBUTES = new Set([\n \"aria-activedescendant\",\n \"aria-atomic\",\n \"aria-autocomplete\",\n \"aria-braillelabel\",\n \"aria-brailleroledescription\",\n \"aria-busy\",\n \"aria-checked\",\n \"aria-colcount\",\n \"aria-colindex\",\n \"aria-colindextext\",\n \"aria-colspan\",\n \"aria-controls\",\n \"aria-current\",\n \"aria-describedby\",\n \"aria-description\",\n \"aria-details\",\n \"aria-disabled\",\n \"aria-errormessage\",\n \"aria-expanded\",\n \"aria-haspopup\",\n \"aria-hidden\",\n \"aria-invalid\",\n \"aria-keyshortcuts\",\n \"aria-label\",\n \"aria-labelledby\",\n \"aria-level\",\n \"aria-live\",\n \"aria-modal\",\n \"aria-multiline\",\n \"aria-multiselectable\",\n \"aria-orientation\",\n \"aria-owns\",\n \"aria-placeholder\",\n \"aria-posinset\",\n \"aria-pressed\",\n \"aria-readonly\",\n \"aria-required\",\n \"aria-roledescription\",\n \"aria-rowcount\",\n \"aria-rowindex\",\n \"aria-rowindextext\",\n \"aria-rowspan\",\n \"aria-selected\",\n \"aria-setsize\",\n \"aria-sort\",\n \"aria-valuemax\",\n \"aria-valuemin\",\n \"aria-valuenow\",\n \"aria-valuetext\",\n \"class\",\n \"dir\",\n \"hidden\",\n \"id\",\n \"inert\",\n \"lang\",\n \"role\",\n \"tabindex\",\n \"title\",\n \"translate\",\n]);\n\nconst TAG_ALLOWED_ATTRIBUTES: Readonly<Record<string, ReadonlySet<string>>> = {\n a: new Set([\"download\", \"href\", \"hreflang\", \"rel\", \"target\", \"type\"]),\n audio: new Set([\"autoplay\", \"controls\", \"loop\", \"muted\", \"preload\", \"src\"]),\n blockquote: new Set([\"cite\"]),\n button: new Set([\"disabled\", \"name\", \"type\", \"value\"]),\n col: new Set([\"span\"]),\n colgroup: new Set([\"span\"]),\n data: new Set([\"value\"]),\n del: new Set([\"cite\", \"datetime\"]),\n details: new Set([\"open\"]),\n dialog: new Set([\"open\"]),\n form: new Set([\"autocomplete\", \"name\"]),\n img: new Set([\"alt\", \"decoding\", \"height\", \"loading\", \"src\", \"width\"]),\n input: new Set([\n \"accept\",\n \"autocomplete\",\n \"checked\",\n \"disabled\",\n \"max\",\n \"maxlength\",\n \"min\",\n \"minlength\",\n \"name\",\n \"pattern\",\n \"placeholder\",\n \"readonly\",\n \"required\",\n \"step\",\n \"type\",\n \"value\",\n ]),\n ins: new Set([\"cite\", \"datetime\"]),\n label: new Set([\"for\"]),\n meter: new Set([\"high\", \"low\", \"max\", \"min\", \"optimum\", \"value\"]),\n optgroup: new Set([\"disabled\", \"label\"]),\n option: new Set([\"disabled\", \"label\", \"selected\", \"value\"]),\n output: new Set([\"for\", \"name\"]),\n progress: new Set([\"max\", \"value\"]),\n q: new Set([\"cite\"]),\n select: new Set([\n \"autocomplete\",\n \"disabled\",\n \"multiple\",\n \"name\",\n \"required\",\n \"size\",\n ]),\n source: new Set([\"height\", \"media\", \"sizes\", \"src\", \"type\", \"width\"]),\n td: new Set([\"colspan\", \"headers\", \"rowspan\"]),\n textarea: new Set([\n \"autocomplete\",\n \"cols\",\n \"disabled\",\n \"maxlength\",\n \"minlength\",\n \"name\",\n \"placeholder\",\n \"readonly\",\n \"required\",\n \"rows\",\n \"value\",\n \"wrap\",\n ]),\n th: new Set([\"abbr\", \"colspan\", \"headers\", \"rowspan\", \"scope\"]),\n time: new Set([\"datetime\"]),\n track: new Set([\"default\", \"kind\", \"label\", \"src\", \"srclang\"]),\n video: new Set([\n \"autoplay\",\n \"controls\",\n \"height\",\n \"loop\",\n \"muted\",\n \"playsinline\",\n \"poster\",\n \"preload\",\n \"src\",\n \"width\",\n ]),\n};\n\nconst BOOLEAN_ATTRIBUTES = new Set([\n \"autoplay\",\n \"checked\",\n \"controls\",\n \"default\",\n \"disabled\",\n \"hidden\",\n \"inert\",\n \"loop\",\n \"multiple\",\n \"muted\",\n \"open\",\n \"playsinline\",\n \"readonly\",\n \"required\",\n \"selected\",\n]);\n\nconst SAFE_INPUT_TYPES = new Set([\n \"button\",\n \"checkbox\",\n \"color\",\n \"date\",\n \"datetime-local\",\n \"email\",\n \"file\",\n \"hidden\",\n \"month\",\n \"number\",\n \"password\",\n \"radio\",\n \"range\",\n \"reset\",\n \"search\",\n \"submit\",\n \"tel\",\n \"text\",\n \"time\",\n \"url\",\n \"week\",\n]);\n\nconst SAFE_BUTTON_TYPES = new Set([\"button\", \"reset\", \"submit\"]);\nconst SAFE_LOADING_VALUES = new Set([\"eager\", \"lazy\"]);\nconst SAFE_DECODING_VALUES = new Set([\"async\", \"auto\", \"sync\"]);\nconst SAFE_PRELOAD_VALUES = new Set([\"auto\", \"metadata\", \"none\"]);\nconst SAFE_TRACK_KIND_VALUES = new Set([\n \"captions\",\n \"chapters\",\n \"descriptions\",\n \"metadata\",\n \"subtitles\",\n]);\nconst URL_VALUED_ATTRIBUTES = new Set([\"cite\", \"href\", \"poster\", \"src\"]);\nconst MEDIA_SOURCE_TAGS = new Set([\"audio\", \"img\", \"source\", \"track\", \"video\"]);\nconst SUPPORTED_REMOTE_DOM_EVENT_SET = new Set<string>(\n SUPPORTED_REMOTE_DOM_EVENTS,\n);\nconst REMOTE_DOM_SEARCH_SORT_EVENT_SET = new Set<string>(\n REMOTE_DOM_SEARCH_SORT_EVENTS,\n);\n\nexport interface RemoteDomSanitizedAttribute {\n readonly name: string;\n readonly value: string;\n}\n\nexport type RemoteDomSanitizedProperty =\n | { readonly name: \"checked\"; readonly value: boolean }\n | { readonly name: \"value\"; readonly value: string }\n | { readonly name: \"searchValue\"; readonly value: string }\n | { readonly name: \"placeholder\"; readonly value: string | undefined }\n | {\n readonly name: \"sortOptions\";\n readonly value:\n | readonly Readonly<{ label: string; value: string }>[]\n | undefined;\n }\n | { readonly name: \"sortValue\"; readonly value: string | undefined }\n | { readonly name: \"customHeight\"; readonly value: string | undefined }\n | { readonly name: \"previewMode\"; readonly value: boolean };\n\nexport interface RemoteDomSanitizerOptions {\n readonly allowedAnchorUrls?: ReadonlySet<string> | undefined;\n readonly urlOriginPolicy?: RemoteDomUrlOriginPolicy | undefined;\n}\n\ntype RemoteDomAllowedHttpOriginGroup = \"artifact\" | \"media\" | \"navigation\";\n\nexport function sanitizeRemoteDomTagName(tagName: unknown): string | undefined {\n if (typeof tagName !== \"string\") return undefined;\n\n const normalizedTagName = tagName.trim().toLowerCase();\n if (\n normalizedTagName.length === 0 ||\n REMOTE_DOM_DENIED_TAG_NAMES.has(normalizedTagName) ||\n !REMOTE_DOM_ALLOWED_TAG_NAME_SET.has(normalizedTagName)\n ) {\n return undefined;\n }\n\n return normalizedTagName;\n}\n\nexport function sanitizeRemoteDomAttributes(\n tagName: string,\n attributes: unknown,\n options: RemoteDomSanitizerOptions = {},\n): RemoteDomSanitizedAttribute[] {\n if (!isObjectRecord(attributes)) return [];\n\n const sanitizedAttributes: RemoteDomSanitizedAttribute[] = [];\n for (const [rawName, rawValue] of Object.entries(attributes)) {\n const attribute = sanitizeRemoteDomAttribute(\n tagName,\n rawName,\n rawValue,\n options,\n );\n if (attribute) {\n sanitizedAttributes.push(attribute);\n }\n }\n\n return sanitizedAttributes;\n}\n\nexport function sanitizeRemoteDomProperty(\n tagName: string,\n rawName: unknown,\n rawValue: unknown,\n): RemoteDomSanitizedProperty | undefined {\n if (typeof rawName !== \"string\") return undefined;\n\n const normalizedTagName = tagName.trim().toLowerCase();\n const name = rawName.trim().toLowerCase();\n if (!isSafeRemoteDomPropertyKey(name)) {\n return undefined;\n }\n\n if (normalizedTagName === \"input\") {\n if (name === \"checked\" && typeof rawValue === \"boolean\") {\n return { name, value: rawValue };\n }\n\n if (name === \"value\" && typeof rawValue === \"string\") {\n return { name, value: rawValue };\n }\n }\n\n if (normalizedTagName === FLUID_SEARCH_SORT_TAG_NAME) {\n if (name === \"searchvalue\" && typeof rawValue === \"string\") {\n return { name: \"searchValue\", value: rawValue };\n }\n if (name === \"placeholder\") {\n return typeof rawValue === \"string\" || rawValue === undefined\n ? { name: \"placeholder\", value: rawValue }\n : undefined;\n }\n if (name === \"sortoptions\") {\n const value = sanitizeSearchSortOptions(rawValue);\n return value === undefined && rawValue !== undefined\n ? undefined\n : { name: \"sortOptions\", value };\n }\n if (name === \"sortvalue\") {\n return typeof rawValue === \"string\" || rawValue === undefined\n ? { name: \"sortValue\", value: rawValue }\n : undefined;\n }\n }\n\n if (normalizedTagName === FLUID_SPACER_WIDGET_TAG_NAME) {\n if (name === \"customheight\") {\n return typeof rawValue === \"string\" || rawValue === undefined\n ? { name: \"customHeight\", value: rawValue }\n : undefined;\n }\n if (name === \"previewmode\" && typeof rawValue === \"boolean\") {\n return { name: \"previewMode\", value: rawValue };\n }\n }\n\n return undefined;\n}\n\nexport function isRemoteDomPropertyName(\n tagName: string,\n rawName: string,\n): boolean {\n const normalizedTagName = tagName.trim().toLowerCase();\n const name = rawName.trim().toLowerCase();\n if (normalizedTagName === \"input\") {\n return name === \"checked\" || name === \"value\";\n }\n if (normalizedTagName === FLUID_SEARCH_SORT_TAG_NAME) {\n return (\n name === \"searchvalue\" ||\n name === \"placeholder\" ||\n name === \"sortoptions\" ||\n name === \"sortvalue\"\n );\n }\n if (normalizedTagName === FLUID_SPACER_WIDGET_TAG_NAME) {\n return name === \"customheight\" || name === \"previewmode\";\n }\n return false;\n}\n\nexport function sanitizeRemoteDomAttribute(\n tagName: string,\n rawName: unknown,\n rawValue: unknown,\n options: RemoteDomSanitizerOptions = {},\n): RemoteDomSanitizedAttribute | undefined {\n if (typeof rawName !== \"string\") return undefined;\n\n const normalizedTagName = tagName.trim().toLowerCase();\n const name = rawName.trim().toLowerCase();\n if (!isSafeRemoteDomPropertyKey(name)) return undefined;\n if (!isAllowedAttributeName(normalizedTagName, name)) return undefined;\n\n if (name === \"type\" && normalizedTagName === \"input\") {\n const value = stringifyAttributeValue(rawValue).toLowerCase();\n return SAFE_INPUT_TYPES.has(value) ? { name, value } : undefined;\n }\n\n if (name === \"type\" && normalizedTagName === \"button\") {\n const value = stringifyAttributeValue(rawValue).toLowerCase();\n return SAFE_BUTTON_TYPES.has(value) ? { name, value } : undefined;\n }\n\n if (URL_VALUED_ATTRIBUTES.has(name)) {\n const value = sanitizeUrlValuedAttribute(\n normalizedTagName,\n name,\n rawValue,\n options.allowedAnchorUrls,\n options.urlOriginPolicy,\n );\n return value ? { name, value } : undefined;\n }\n\n if (name === \"target\") {\n const value = stringifyAttributeValue(rawValue);\n return value === \"_blank\" || value === \"_self\"\n ? { name, value }\n : undefined;\n }\n\n if (name === \"rel\") {\n const value = sanitizeTokenList(rawValue);\n return value.length > 0 ? { name, value } : undefined;\n }\n\n if (name === \"loading\") {\n return sanitizeEnumAttribute(name, rawValue, SAFE_LOADING_VALUES);\n }\n\n if (name === \"decoding\") {\n return sanitizeEnumAttribute(name, rawValue, SAFE_DECODING_VALUES);\n }\n\n if (name === \"preload\") {\n return sanitizeEnumAttribute(name, rawValue, SAFE_PRELOAD_VALUES);\n }\n\n if (name === \"kind\" && normalizedTagName === \"track\") {\n return sanitizeEnumAttribute(name, rawValue, SAFE_TRACK_KIND_VALUES);\n }\n\n if (BOOLEAN_ATTRIBUTES.has(name)) {\n return rawValue === true || rawValue === \"\" || rawValue === name\n ? { name, value: \"\" }\n : undefined;\n }\n\n const value = stringifyAttributeValue(rawValue);\n if (value.length === 0 && rawValue !== \"\") return undefined;\n const sanitizedValue = sanitizeCssComponentValueUrlReferences(\n value,\n options.urlOriginPolicy,\n );\n if (sanitizedValue === undefined) {\n return undefined;\n }\n\n return { name, value: sanitizedValue };\n}\n\nexport function sanitizeRemoteDomUrl(\n value: unknown,\n options: Readonly<{\n allowHashOnly?: boolean | undefined;\n allowMailTo: boolean;\n allowRelative?: boolean | undefined;\n allowTel: boolean;\n allowedHttpOriginGroups?:\n | readonly RemoteDomAllowedHttpOriginGroup[]\n | undefined;\n allowedHttpUrls?: ReadonlySet<string> | undefined;\n originPolicy?: RemoteDomUrlOriginPolicy | undefined;\n relativeUrlBase?: \"artifact\" | \"navigation\" | undefined;\n }>,\n): string | undefined {\n if (typeof value !== \"string\") return undefined;\n\n const trimmedValue = value.trim();\n if (\n trimmedValue.length === 0 ||\n trimmedValue !== value ||\n hasControlCharacter(trimmedValue) ||\n trimmedValue.includes(\"\\\\\") ||\n trimmedValue.startsWith(\"//\")\n ) {\n return undefined;\n }\n\n if (trimmedValue.startsWith(\"#\")) {\n return options.allowHashOnly === true ? trimmedValue : undefined;\n }\n\n if (isRelativeUrl(trimmedValue)) {\n if (!options.allowRelative) return undefined;\n\n const parsedRelativeUrl = resolveRemoteDomRelativeUrl(\n trimmedValue,\n options.originPolicy,\n options.relativeUrlBase ?? \"artifact\",\n );\n if (!parsedRelativeUrl) return undefined;\n\n return isAllowedHttpOrigin(\n parsedRelativeUrl.origin,\n options.originPolicy,\n options.allowedHttpOriginGroups ?? [],\n )\n ? parsedRelativeUrl.href\n : undefined;\n }\n\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(trimmedValue);\n } catch {\n return undefined;\n }\n\n if (parsedUrl.protocol === \"http:\" || parsedUrl.protocol === \"https:\") {\n if (options.allowedHttpUrls?.has(parsedUrl.href)) {\n return parsedUrl.href;\n }\n return isAllowedHttpOrigin(\n parsedUrl.origin,\n options.originPolicy,\n options.allowedHttpOriginGroups ?? [],\n )\n ? trimmedValue\n : undefined;\n }\n\n if (options.allowMailTo && parsedUrl.protocol === \"mailto:\") {\n return trimmedValue;\n }\n\n if (options.allowTel && parsedUrl.protocol === \"tel:\") {\n return trimmedValue;\n }\n\n return undefined;\n}\n\nexport function sanitizeRemoteDomCssUrlReferences(\n value: unknown,\n options: RemoteDomSanitizerOptions = {},\n): string | undefined {\n if (typeof value !== \"string\") return undefined;\n\n return sanitizeCssTextUrlReferences(value, options.urlOriginPolicy);\n}\n\nexport function isSupportedRemoteDomEventName(\n eventName: string,\n tagName?: string,\n): boolean {\n if (SUPPORTED_REMOTE_DOM_EVENT_SET.has(eventName)) return true;\n return (\n tagName?.trim().toLowerCase() === FLUID_SEARCH_SORT_TAG_NAME &&\n REMOTE_DOM_SEARCH_SORT_EVENT_SET.has(eventName)\n );\n}\n\nexport interface RemoteDomSerializedEventPayload {\n readonly type: string;\n readonly targetId: string;\n readonly currentTargetId: string;\n readonly bubbles: boolean;\n readonly cancelable: boolean;\n readonly defaultPrevented: boolean;\n readonly value?: string;\n readonly checked?: boolean;\n readonly key?: string;\n readonly code?: string;\n readonly altKey?: boolean;\n readonly ctrlKey?: boolean;\n readonly metaKey?: boolean;\n readonly shiftKey?: boolean;\n readonly button?: number;\n readonly buttons?: number;\n readonly clientX?: number;\n readonly clientY?: number;\n readonly pointerId?: number;\n readonly pointerType?: string;\n readonly isPrimary?: boolean;\n readonly detailJson?: string;\n}\n\nexport function serializeRemoteDomEvent(\n event: Event,\n targetId: string,\n currentTargetId: string,\n currentTargetTagName?: string,\n): RemoteDomSerializedEventPayload | undefined {\n if (!isSupportedRemoteDomEventName(event.type, currentTargetTagName)) {\n return undefined;\n }\n\n const inputState = readInputState(event.target);\n const payload: RemoteDomSerializedEventPayload = {\n type: event.type,\n targetId,\n currentTargetId,\n bubbles: event.bubbles,\n cancelable: event.cancelable,\n defaultPrevented: event.defaultPrevented,\n ...inputState,\n ...readKeyboardState(event),\n ...readPointerState(event),\n ...readMouseState(event),\n ...readCustomEventDetail(event),\n };\n\n return payload;\n}\n\nfunction sanitizeSearchSortOptions(\n value: unknown,\n): readonly Readonly<{ label: string; value: string }>[] | undefined {\n if (!Array.isArray(value)) return undefined;\n const options: Array<Readonly<{ label: string; value: string }>> = [];\n for (const option of value) {\n if (\n !isObjectRecord(option) ||\n typeof option.label !== \"string\" ||\n typeof option.value !== \"string\"\n ) {\n return undefined;\n }\n options.push({ label: option.label, value: option.value });\n }\n return options;\n}\n\nfunction readCustomEventDetail(\n event: Event,\n): Pick<RemoteDomSerializedEventPayload, \"detailJson\"> {\n if (\n !(event instanceof CustomEvent) ||\n !REMOTE_DOM_SEARCH_SORT_EVENT_SET.has(event.type)\n ) {\n return {};\n }\n if (!isRemoteDomSerializableValue(event.detail)) return {};\n\n try {\n const detailJson = JSON.stringify(event.detail);\n return typeof detailJson === \"string\" ? { detailJson } : {};\n } catch {\n return {};\n }\n}\n\nfunction sanitizeUrlValuedAttribute(\n tagName: string,\n name: string,\n value: unknown,\n allowedAnchorUrls: ReadonlySet<string> | undefined,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): string | undefined {\n if (name === \"href\" && tagName === \"a\") {\n return sanitizeRemoteDomUrl(value, {\n allowHashOnly: true,\n allowMailTo: false,\n allowRelative: true,\n allowTel: false,\n allowedHttpOriginGroups: [\"navigation\"],\n ...(allowedAnchorUrls ? { allowedHttpUrls: allowedAnchorUrls } : {}),\n originPolicy,\n relativeUrlBase: \"navigation\",\n });\n }\n\n if (name === \"src\" && MEDIA_SOURCE_TAGS.has(tagName)) {\n return sanitizeRemoteDomUrl(value, {\n allowHashOnly: false,\n allowMailTo: false,\n allowRelative: true,\n allowTel: false,\n allowedHttpOriginGroups: [\"artifact\", \"media\"],\n originPolicy,\n relativeUrlBase: \"artifact\",\n });\n }\n\n if (name === \"poster\" && tagName === \"video\") {\n return sanitizeRemoteDomUrl(value, {\n allowHashOnly: false,\n allowMailTo: false,\n allowRelative: true,\n allowTel: false,\n allowedHttpOriginGroups: [\"artifact\", \"media\"],\n originPolicy,\n relativeUrlBase: \"artifact\",\n });\n }\n\n return sanitizeRemoteDomUrl(value, {\n allowHashOnly: false,\n allowMailTo: false,\n allowRelative: true,\n allowTel: false,\n allowedHttpOriginGroups: [\"artifact\", \"media\"],\n originPolicy,\n relativeUrlBase: \"artifact\",\n });\n}\n\nfunction sanitizeEnumAttribute(\n name: string,\n rawValue: unknown,\n safeValues: ReadonlySet<string>,\n): RemoteDomSanitizedAttribute | undefined {\n const value = stringifyAttributeValue(rawValue).toLowerCase();\n return safeValues.has(value) ? { name, value } : undefined;\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index += 1) {\n const codePoint = value.charCodeAt(index);\n if (codePoint < 32 || (codePoint >= 127 && codePoint <= 159)) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction isAllowedAttributeName(tagName: string, name: string): boolean {\n if (\n name.length === 0 ||\n name.startsWith(\"on\") ||\n name === \"style\" ||\n name === \"srcdoc\" ||\n name.includes(\":\") ||\n !/^[a-z][a-z0-9_.-]*$/u.test(name)\n ) {\n return false;\n }\n\n if (name.startsWith(\"data-\")) return true;\n if (GLOBAL_ALLOWED_ATTRIBUTES.has(name)) return true;\n\n return TAG_ALLOWED_ATTRIBUTES[tagName]?.has(name) === true;\n}\n\nfunction stringifyAttributeValue(value: unknown): string {\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\")\n return String(value);\n return \"\";\n}\n\nfunction sanitizeTokenList(value: unknown): string {\n return stringifyAttributeValue(value)\n .split(/\\s+/u)\n .filter((token) => /^[a-z0-9_-]+$/iu.test(token))\n .join(\" \");\n}\n\nfunction escapeCssString(value: string): string {\n return value.replace(/\\\\/gu, \"\\\\\\\\\").replace(/\"/gu, '\\\\\"');\n}\n\nconst CSS_URL_FUNCTION_NAME = \"url\";\nconst CSS_IMPORT_RULE_NAME = \"import\";\nconst CSS_REJECTED_URL_FUNCTION_NAMES = new Set([\n \"image-set\",\n \"-webkit-image-set\",\n]);\ntype CssValueNode = ReturnType<typeof valueParser>[\"nodes\"][number];\ntype CssFunctionNode = Extract<CssValueNode, { type: \"function\" }>;\n\nfunction sanitizeCssTextUrlReferences(\n cssText: string,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): string | undefined {\n let stylesheet: ReturnType<typeof postcssParse>;\n try {\n stylesheet = postcssParse(cssText);\n } catch {\n return undefined;\n }\n\n let valid = true;\n stylesheet.walkAtRules((atRule) => {\n if (!valid) return;\n\n const decodedName = decodeCssEscapes(atRule.name)?.toLowerCase();\n if (!decodedName) {\n valid = false;\n return;\n }\n\n const sanitizedParams =\n decodedName === CSS_IMPORT_RULE_NAME\n ? sanitizeCssImportParameters(atRule.params, originPolicy)\n : sanitizeCssComponentValueUrlReferences(atRule.params, originPolicy);\n if (sanitizedParams === undefined) {\n valid = false;\n return;\n }\n\n if (decodedName === CSS_IMPORT_RULE_NAME) atRule.name = decodedName;\n atRule.params = sanitizedParams;\n });\n\n stylesheet.walkDecls((declaration) => {\n if (!valid) return;\n const sanitizedValue = sanitizeCssComponentValueUrlReferences(\n declaration.value,\n originPolicy,\n );\n if (sanitizedValue === undefined) {\n valid = false;\n return;\n }\n declaration.value = sanitizedValue;\n });\n\n return valid ? stylesheet.toString() : undefined;\n}\n\nfunction sanitizeCssImportParameters(\n params: string,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): string | undefined {\n const parsed = valueParser(params);\n const firstToken = parsed.nodes.find(\n (node) => node.type !== \"space\" && node.type !== \"comment\",\n );\n if (!firstToken) return undefined;\n\n if (firstToken.type === \"string\") {\n const decodedUrl = decodeCssEscapes(firstToken.value);\n const sanitizedUrl =\n decodedUrl === undefined\n ? undefined\n : sanitizeCssUrlToken(decodedUrl, originPolicy);\n if (!sanitizedUrl) return undefined;\n firstToken.quote = '\"';\n firstToken.value = escapeCssString(sanitizedUrl);\n } else if (\n firstToken.type !== \"function\" ||\n decodeCssEscapes(firstToken.value)?.toLowerCase() !== CSS_URL_FUNCTION_NAME\n ) {\n return undefined;\n }\n\n return sanitizeParsedCssValue(parsed.nodes, originPolicy)\n ? valueParser.stringify(parsed.nodes)\n : undefined;\n}\n\nfunction sanitizeCssComponentValueUrlReferences(\n cssValue: string,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): string | undefined {\n const parsed = valueParser(cssValue);\n return sanitizeParsedCssValue(parsed.nodes, originPolicy)\n ? valueParser.stringify(parsed.nodes)\n : undefined;\n}\n\n/** True when a word token ends in a hex escape that CSS would terminate\n * with the following whitespace.\n *\n * CSS Syntax §4.3.7: a hex escape consumes one trailing whitespace\n * character, so `\\75 rl(…)` is a SINGLE function token named `url`.\n * postcss-value-parser instead splits on that whitespace and hands us\n * [word \"\\75\", space, function \"rl\"] — a function whose name decodes\n * to `rl`, which is in neither the url nor the rejected-function set,\n * so the value sails past the origin policy and Chromium then fetches\n * the attacker's URL. Same for `u\\72 l(`, `ur\\6c (`, `\\69 mage-set(`\n * and `image-se\\74 (`, and for tab/newline/form-feed as the\n * terminator.\n *\n * We cannot re-join the tokens without reimplementing the tokenizer,\n * so we fail closed on the shape instead. Escapes inside strings are\n * unaffected — those are `string` nodes, so `content: \"\\201C \"` and\n * friends still round-trip. */\nfunction hasWhitespaceTerminatedEscape(node: CssValueNode): boolean {\n return node.type === \"word\" && /\\\\[0-9a-fA-F]{1,6}$/.test(node.value);\n}\n\n/** True when `nodes[index]` is the first half of a function name that\n * CSS will re-join across the whitespace the escape consumes.\n *\n * Narrower than \"any word ending in an escape\", deliberately. Only a\n * FUNCTION can fetch anything, so the shape that matters is\n * word-escape → single whitespace → function: `\\75 rl(…)` re-joins to\n * `url(…)`. Re-joining a word onto another WORD just yields an\n * identifier, which is inert — and rejecting those took ordinary\n * declarations like `color: \\72 ed` down with them. Since one rejected\n * declaration invalidates the entire source, that discarded whole\n * stylesheets over a value that could never fetch.\n *\n * The whitespace run must be exactly ONE CSS whitespace: §4.3.7 has\n * the escape consume one, so `\\75 rl(` (two spaces) leaves a real\n * separator behind and is two tokens, not a disguised function.\n *\n * Counted after normalizing newlines, not in raw code units. CSS\n * preprocessing (§3.3) folds CRLF and a lone CR into a single LF\n * BEFORE tokenizing, so `\\75\\r\\nrl(` is one whitespace to the browser\n * and resolves to `url(...)`. Measuring the raw string made that two\n * characters, which skipped the rejection entirely and handed the\n * attacker back the bypass. */\nfunction startsDisguisedFunction(\n nodes: CssValueNode[],\n index: number,\n): boolean {\n // Walks the whole CHAIN, not just one pair. Each escape consumes the\n // single whitespace after it, so a name can be spread over any number\n // of word-space tokens before the function: `\\75 \\72 l(` is `u`+`r`+\n // `l` = `url(`, and `\\69 mage-se\\74 (` is `i`+`image-set`. Checking\n // only word-space-function caught the two-token spelling and let\n // every longer one through.\n let name = \"\";\n let i = index;\n for (;;) {\n const word = nodes[i];\n if (!word || !hasWhitespaceTerminatedEscape(word)) return false;\n const separator = nodes[i + 1];\n if (separator?.type !== \"space\") return false;\n // CSS preprocessing (§3.3) folds CRLF and a lone CR into one LF\n // BEFORE tokenizing, so those are a single terminator; two real\n // spaces are not, and leave a genuine separator behind.\n const normalized = separator.value.replace(/\\r\\n?|\\f/g, \"\\n\");\n if (normalized.length !== 1) return false;\n const decodedWord = decodeCssEscapes(word.value);\n if (decodedWord === undefined) return true; // unreadable — fail closed\n name += decodedWord;\n\n const next = nodes[i + 2];\n if (next?.type === \"function\") {\n // Both halves decoded: an escape can hide in the suffix too, and\n // the raw value built `ur\\6c`, which matches neither name.\n const decodedSuffix = decodeCssEscapes(next.value);\n if (decodedSuffix === undefined) return true; // fail closed\n const reconstructed = `${name}${decodedSuffix}`.toLowerCase();\n return (\n reconstructed === CSS_URL_FUNCTION_NAME ||\n CSS_REJECTED_URL_FUNCTION_NAMES.has(reconstructed)\n );\n }\n // Another escaped word continues the name; anything else ends it as\n // an ordinary identifier — `color: \\72 ed` is just `red`.\n if (next?.type !== \"word\") return false;\n i += 2;\n }\n}\n\nfunction sanitizeParsedCssValue(\n nodes: CssValueNode[],\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): boolean {\n for (const [index, node] of nodes.entries()) {\n if (\"unclosed\" in node && node.unclosed === true) return false;\n // Checked before the `function` filter below: the token that\n // carries the escape is a `word`, and it is the token after the\n // whitespace that becomes the disguised function.\n if (startsDisguisedFunction(nodes, index)) return false;\n if (node.type !== \"function\") continue;\n\n const decodedFunctionName = decodeCssEscapes(node.value);\n if (decodedFunctionName === undefined) return false;\n const functionName = decodedFunctionName.toLowerCase();\n if (CSS_REJECTED_URL_FUNCTION_NAMES.has(functionName)) return false;\n\n if (functionName === CSS_URL_FUNCTION_NAME) {\n if (!sanitizeCssUrlFunctionNode(node, originPolicy)) return false;\n continue;\n }\n\n if (!sanitizeParsedCssValue(node.nodes, originPolicy)) return false;\n }\n\n return true;\n}\n\nfunction sanitizeCssUrlFunctionNode(\n node: CssFunctionNode,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): boolean {\n const tokens = node.nodes.filter(\n (child) => child.type !== \"space\" && child.type !== \"comment\",\n );\n if (tokens.length !== 1) return false;\n\n const token = tokens[0];\n if (!token || (token.type !== \"word\" && token.type !== \"string\"))\n return false;\n if (\"unclosed\" in token && token.unclosed === true) return false;\n\n const decodedUrl = decodeCssEscapes(token.value);\n const sanitizedUrl =\n decodedUrl === undefined\n ? undefined\n : sanitizeCssUrlToken(decodedUrl, originPolicy);\n if (!sanitizedUrl) return false;\n\n node.value = CSS_URL_FUNCTION_NAME;\n node.before = \"\";\n node.after = \"\";\n node.nodes = [\n {\n type: \"string\",\n quote: '\"',\n value: escapeCssString(sanitizedUrl),\n sourceIndex: token.sourceIndex,\n sourceEndIndex: token.sourceEndIndex,\n },\n ];\n return true;\n}\n\n/** Decodes CSS escapes after the maintained parser has identified a token. */\nfunction decodeCssEscapes(value: string): string | undefined {\n let decoded = \"\";\n\n for (let index = 0; index < value.length; index += 1) {\n const codeUnit = value[index];\n if (codeUnit !== \"\\\\\") {\n decoded += codeUnit;\n continue;\n }\n\n index += 1;\n const escaped = value[index];\n if (\n escaped === undefined ||\n escaped === \"\\n\" ||\n escaped === \"\\r\" ||\n escaped === \"\\f\"\n ) {\n return undefined;\n }\n\n if (!/^[0-9a-f]$/iu.test(escaped)) {\n decoded += escaped;\n continue;\n }\n\n const hexStart = index;\n while (\n index + 1 < value.length &&\n index + 1 - hexStart < 6 &&\n /^[0-9a-f]$/iu.test(value[index + 1] ?? \"\")\n ) {\n index += 1;\n }\n\n const codePoint = Number.parseInt(value.slice(hexStart, index + 1), 16);\n decoded +=\n codePoint === 0 ||\n codePoint > 0x10ffff ||\n (codePoint >= 0xd800 && codePoint <= 0xdfff)\n ? \"\\uFFFD\"\n : String.fromCodePoint(codePoint);\n\n if (/^[ \\n\\r\\t\\f]$/u.test(value[index + 1] ?? \"\")) index += 1;\n }\n\n return decoded;\n}\n\nfunction sanitizeCssUrlToken(\n rawUrl: string,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n): string | undefined {\n const unquotedUrl = rawUrl.trim().replace(/^([\"'])(.*)\\1$/u, \"$2\");\n return sanitizeRemoteDomUrl(unquotedUrl, {\n allowHashOnly: false,\n allowMailTo: false,\n allowRelative: true,\n allowTel: false,\n allowedHttpOriginGroups: [\"artifact\", \"media\"],\n originPolicy,\n relativeUrlBase: \"artifact\",\n });\n}\n\nfunction resolveRemoteDomRelativeUrl(\n value: string,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n base: \"artifact\" | \"navigation\",\n): URL | undefined {\n const baseUrl =\n base === \"navigation\"\n ? originPolicy?.navigationOrigin\n : originPolicy?.artifactBaseUrl;\n if (!baseUrl) return undefined;\n\n try {\n const resolvedUrl = new URL(value, baseUrl);\n return resolvedUrl.protocol === \"http:\" || resolvedUrl.protocol === \"https:\"\n ? resolvedUrl\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nfunction isAllowedHttpOrigin(\n origin: string,\n originPolicy: RemoteDomUrlOriginPolicy | undefined,\n allowedGroups: readonly RemoteDomAllowedHttpOriginGroup[],\n): boolean {\n if (allowedGroups.length === 0 || !originPolicy) return false;\n\n for (const group of allowedGroups) {\n if (group === \"artifact\" && originPolicy.artifactOrigins.includes(origin)) {\n return true;\n }\n if (group === \"media\" && originPolicy.mediaOrigins.includes(origin)) {\n return true;\n }\n if (group === \"navigation\" && originPolicy.navigationOrigin === origin) {\n return true;\n }\n }\n\n return false;\n}\n\nfunction isRelativeUrl(value: string): boolean {\n return !/^[a-z][a-z0-9+.-]*:/iu.test(value);\n}\n\nfunction readInputState(\n target: EventTarget | null,\n): Pick<RemoteDomSerializedEventPayload, \"checked\" | \"value\"> {\n if (\n target instanceof HTMLInputElement ||\n target instanceof HTMLTextAreaElement ||\n target instanceof HTMLSelectElement\n ) {\n const inputState: { value?: string; checked?: boolean } = {\n value: target.value,\n };\n if (target instanceof HTMLInputElement) {\n inputState.checked = target.checked;\n }\n return inputState;\n }\n\n return {};\n}\n\nfunction readKeyboardState(\n event: Event,\n): Pick<\n RemoteDomSerializedEventPayload,\n \"altKey\" | \"code\" | \"ctrlKey\" | \"key\" | \"metaKey\" | \"shiftKey\"\n> {\n if (!(event instanceof KeyboardEvent)) return {};\n\n return {\n altKey: event.altKey,\n code: event.code,\n ctrlKey: event.ctrlKey,\n key: event.key,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n };\n}\n\nfunction readMouseState(\n event: Event,\n): Pick<\n RemoteDomSerializedEventPayload,\n | \"altKey\"\n | \"button\"\n | \"buttons\"\n | \"clientX\"\n | \"clientY\"\n | \"ctrlKey\"\n | \"metaKey\"\n | \"shiftKey\"\n> {\n if (!(event instanceof MouseEvent)) return {};\n\n return {\n altKey: event.altKey,\n button: event.button,\n buttons: event.buttons,\n clientX: event.clientX,\n clientY: event.clientY,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n };\n}\n\nfunction readPointerState(\n event: Event,\n): Pick<\n RemoteDomSerializedEventPayload,\n \"isPrimary\" | \"pointerId\" | \"pointerType\"\n> {\n if (!isObjectRecord(event) || typeof PointerEvent === \"undefined\") return {};\n if (!(event instanceof PointerEvent)) return {};\n\n return {\n isPrimary: event.isPrimary,\n pointerId: event.pointerId,\n pointerType: event.pointerType,\n };\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null;\n}\n\nexport type RemoteDomSanitizableAttributes = Readonly<\n Record<string, RemoteDomSerializableValue | undefined>\n>;\n","import {\n MUTATION_TYPE_INSERT_CHILD,\n MUTATION_TYPE_REMOVE_CHILD,\n MUTATION_TYPE_UPDATE_PROPERTY,\n MUTATION_TYPE_UPDATE_TEXT,\n NODE_TYPE_ELEMENT,\n NODE_TYPE_TEXT,\n ROOT_ID as REMOTE_DOM_ROOT_ID,\n UPDATE_PROPERTY_TYPE_ATTRIBUTE,\n UPDATE_PROPERTY_TYPE_EVENT_LISTENER,\n UPDATE_PROPERTY_TYPE_PROPERTY,\n type RemoteConnection,\n type RemoteMutationRecord,\n type RemoteMutationRecordUpdateProperty,\n type RemoteNodeSerialization,\n} from \"@remote-dom/core\";\nimport {\n isRemoteDomPropertyName,\n isSupportedRemoteDomEventName,\n sanitizeRemoteDomAttributes,\n sanitizeRemoteDomProperty,\n sanitizeRemoteDomTagName,\n} from \"./remote-dom-sanitizer\";\nimport {\n isRemoteDomSerializableValue,\n isSafeRemoteDomPropertyKey,\n type RemoteDomNodeProperties,\n type RemoteDomUrlOriginPolicy,\n} from \"./remote-dom-values\";\n\n/**\n * A worker event-listener proxied across the thread boundary. The host invokes\n * it with a sanitized event payload and is responsible for `release()`-ing it.\n */\nexport type RemoteDomEventListenerProxy = (\n ...args: readonly unknown[]\n) => unknown;\n\nexport interface SanitizingRemoteConnectionOptions {\n /** The receiver's connection; sanitized records are forwarded here. */\n readonly connection: RemoteConnection;\n readonly allowedAnchorUrls?: ReadonlySet<string> | undefined;\n readonly urlOriginPolicy: RemoteDomUrlOriginPolicy;\n readonly maxMutationBatchSize: number;\n readonly maxDomNodeCount: number;\n /**\n * Invoked for every stripped event-listener record. `listener` is the proxied\n * worker function, or `null` when the listener is being removed.\n */\n readonly onEventListenerUpdate?:\n | ((\n targetId: string,\n eventName: string,\n listener: RemoteDomEventListenerProxy | null,\n ) => void)\n | undefined;\n /** Invoked when a mutation would push the node count over the limit. */\n readonly onNodeLimitExceeded?: (() => void) | undefined;\n /**\n * Invoked with a diagnostic message when a record is structurally invalid,\n * references a missing target, or otherwise fails validation. The batch is\n * dropped rather than forwarded.\n */\n readonly onInvalidRecord?: ((message: string) => void) | undefined;\n /** Invoked when the wrapped `connection.mutate` throws. */\n readonly onMutateError?: ((error: unknown) => void) | undefined;\n}\n\n/**\n * The sanitizing connection. `mutate` runs the full host-side sanitization\n * pipeline before forwarding to the wrapped receiver connection; `call` is\n * denied to close the arbitrary element-method surface the receiver exposes.\n */\nexport interface SanitizingRemoteConnection {\n mutate(records: readonly RemoteMutationRecord[]): void;\n call(id: string, method: string, ...args: readonly unknown[]): never;\n reset(): void;\n}\n\nexport class RemoteDomConnectionCallDeniedError extends Error {\n constructor(method: string) {\n super(\n `Remote DOM element method \"${method}\" was blocked; host method calls are denied.`,\n );\n this.name = \"RemoteDomConnectionCallDeniedError\";\n }\n}\n\ninterface SimulatedElement {\n readonly kind: \"element\";\n readonly localName: string;\n readonly childIds: string[];\n}\n\ninterface SimulatedText {\n readonly kind: \"text\";\n}\n\ntype SimulatedNode = SimulatedElement | SimulatedText;\n\ninterface SanitizingState {\n readonly nodes: Map<string, SimulatedNode>;\n}\n\ninterface PendingEventListenerUpdate {\n readonly targetId: string;\n readonly eventName: string;\n readonly listener: RemoteDomEventListenerProxy | null;\n}\n\ntype NormalizeRemoteNodeResult =\n | {\n readonly ok: true;\n readonly node: RemoteNodeSerialization;\n readonly nodeCount: number;\n }\n | { readonly ok: false; readonly message: string };\n\ntype NormalizeMutationResult =\n | { readonly ok: true; readonly record?: RemoteMutationRecord }\n | { readonly ok: false; readonly message: string };\n\nexport function createSanitizingRemoteConnection(\n options: SanitizingRemoteConnectionOptions,\n): SanitizingRemoteConnection {\n const state: SanitizingState = {\n nodes: new Map<string, SimulatedNode>([\n [REMOTE_DOM_ROOT_ID, { kind: \"element\", localName: \"\", childIds: [] }],\n ]),\n };\n\n function reset(): void {\n state.nodes.clear();\n state.nodes.set(REMOTE_DOM_ROOT_ID, {\n kind: \"element\",\n localName: \"\",\n childIds: [],\n });\n }\n\n function mutate(records: readonly RemoteMutationRecord[]): void {\n if (records.length > options.maxMutationBatchSize) {\n options.onInvalidRecord?.(\n \"Remote DOM mutation batch exceeded maxMutationBatchSize\",\n );\n return;\n }\n\n const normalizedRecords: RemoteMutationRecord[] = [];\n const pendingEventListenerUpdates: PendingEventListenerUpdate[] = [];\n const workingState = cloneSanitizingState(state);\n\n for (const rawRecord of records) {\n const record = parseRemoteMutationRecord(rawRecord);\n if (!record) {\n options.onInvalidRecord?.(\n \"Remote DOM worker sent an invalid upstream mutation record\",\n );\n return;\n }\n\n const normalized = normalizeMutationRecordForHost(\n options,\n workingState,\n record,\n pendingEventListenerUpdates,\n );\n if (!normalized.ok) {\n if (normalized.message === NODE_LIMIT_MESSAGE) {\n options.onNodeLimitExceeded?.();\n } else {\n options.onInvalidRecord?.(normalized.message);\n }\n return;\n }\n if (normalized.record) normalizedRecords.push(normalized.record);\n }\n\n try {\n if (normalizedRecords.length > 0) {\n options.connection.mutate(normalizedRecords);\n }\n } catch (error) {\n options.onMutateError?.(error);\n return;\n }\n\n commitSanitizingState(state, workingState);\n for (const update of pendingEventListenerUpdates) {\n options.onEventListenerUpdate?.(\n update.targetId,\n update.eventName,\n update.listener,\n );\n }\n }\n\n return {\n mutate,\n call(_id: string, method: string): never {\n throw new RemoteDomConnectionCallDeniedError(method);\n },\n reset,\n };\n}\n\nfunction cloneSanitizingState(state: SanitizingState): SanitizingState {\n const nodes = new Map<string, SimulatedNode>();\n for (const [id, node] of state.nodes) {\n nodes.set(\n id,\n node.kind === \"element\"\n ? { ...node, childIds: [...node.childIds] }\n : { kind: \"text\" },\n );\n }\n return {\n nodes,\n };\n}\n\nfunction commitSanitizingState(\n state: SanitizingState,\n workingState: SanitizingState,\n): void {\n state.nodes.clear();\n for (const [id, node] of workingState.nodes) {\n state.nodes.set(id, node);\n }\n}\n\nconst NODE_LIMIT_MESSAGE = \"Remote DOM mutation exceeded node limit.\";\n\nfunction normalizeMutationRecordForHost(\n options: SanitizingRemoteConnectionOptions,\n state: SanitizingState,\n mutation: RemoteMutationRecord,\n pendingEventListenerUpdates: PendingEventListenerUpdate[],\n): NormalizeMutationResult {\n switch (mutation[0]) {\n case MUTATION_TYPE_INSERT_CHILD: {\n const [, parentId, child, index] = mutation;\n const parent = state.nodes.get(parentId);\n if (!parent || parent.kind !== \"element\") {\n return {\n ok: false,\n message: `Remote DOM mutation referenced missing insertChild parent node \"${parentId}\".`,\n };\n }\n if (\n !Number.isInteger(index) ||\n index < 0 ||\n index > parent.childIds.length\n ) {\n return {\n ok: false,\n message: \"Remote DOM insertChild index was invalid.\",\n };\n }\n\n const normalized = normalizeRemoteNodeForHost(\n options,\n state,\n child,\n new Set(state.nodes.keys()),\n pendingEventListenerUpdates,\n );\n if (!normalized.ok) return normalized;\n\n const nextNodeCount =\n Math.max(0, state.nodes.size - 1) + normalized.nodeCount;\n if (nextNodeCount > options.maxDomNodeCount) {\n return { ok: false, message: NODE_LIMIT_MESSAGE };\n }\n\n registerSimulatedRemoteNode(state, normalized.node);\n parent.childIds.splice(index, 0, normalized.node.id);\n return {\n ok: true,\n record: [MUTATION_TYPE_INSERT_CHILD, parentId, normalized.node, index],\n };\n }\n case MUTATION_TYPE_REMOVE_CHILD: {\n const [, parentId, index] = mutation;\n const parent = state.nodes.get(parentId);\n if (!parent || parent.kind !== \"element\") {\n return {\n ok: false,\n message: `Remote DOM mutation referenced missing removeChild parent node \"${parentId}\".`,\n };\n }\n if (\n !Number.isInteger(index) ||\n index < 0 ||\n index >= parent.childIds.length\n ) {\n return {\n ok: false,\n message: \"Remote DOM removeChild index was invalid.\",\n };\n }\n const [removedId] = parent.childIds.splice(index, 1);\n if (!removedId) {\n return {\n ok: false,\n message: \"Remote DOM removeChild index was invalid.\",\n };\n }\n removeSimulatedRemoteNode(state, removedId);\n return { ok: true, record: mutation };\n }\n case MUTATION_TYPE_UPDATE_TEXT: {\n const [, id] = mutation;\n const target = state.nodes.get(id);\n if (!target || target.kind !== \"text\") {\n return {\n ok: false,\n message: `Remote DOM mutation referenced missing updateText target node \"${id}\".`,\n };\n }\n return { ok: true, record: mutation };\n }\n case MUTATION_TYPE_UPDATE_PROPERTY:\n return normalizeUpdatePropertyRecordForHost(\n options,\n state,\n mutation,\n pendingEventListenerUpdates,\n );\n }\n}\n\nfunction normalizeUpdatePropertyRecordForHost(\n options: SanitizingRemoteConnectionOptions,\n state: SanitizingState,\n mutation: RemoteMutationRecordUpdateProperty,\n pendingEventListenerUpdates: PendingEventListenerUpdate[],\n): NormalizeMutationResult {\n const [, id, property, value, updateType] = mutation;\n if (!isSafeRemoteDomPropertyKey(property)) {\n return {\n ok: false,\n message: `Remote DOM mutation used an unsafe property key \"${property}\".`,\n };\n }\n\n const node = state.nodes.get(id);\n if (!node || node.kind !== \"element\") {\n return {\n ok: false,\n message: `Remote DOM mutation referenced missing updateProperty target node \"${id}\".`,\n };\n }\n\n if (updateType === UPDATE_PROPERTY_TYPE_EVENT_LISTENER) {\n if (!isSupportedRemoteDomEventName(property, node.localName)) {\n return { ok: true };\n }\n const listener =\n typeof value === \"function\"\n ? (value as RemoteDomEventListenerProxy)\n : null;\n pendingEventListenerUpdates.push({\n targetId: id,\n eventName: property,\n listener,\n });\n return { ok: true };\n }\n\n if (value !== undefined && !isRemoteDomSerializableValue(value)) {\n return {\n ok: false,\n message: `Remote DOM mutation property \"${property}\" was not serializable.`,\n };\n }\n\n if (updateType === UPDATE_PROPERTY_TYPE_PROPERTY) {\n const sanitizedProperty = sanitizeRemoteDomProperty(\n node.localName,\n property,\n value,\n );\n if (sanitizedProperty) {\n return {\n ok: true,\n record: [\n MUTATION_TYPE_UPDATE_PROPERTY,\n id,\n sanitizedProperty.name,\n sanitizedProperty.value,\n UPDATE_PROPERTY_TYPE_PROPERTY,\n ],\n };\n }\n\n if (isRemoteDomPropertyName(node.localName, property)) {\n return {\n ok: false,\n message: `Remote DOM property \"${property}\" had an invalid value for \"${node.localName}\".`,\n };\n }\n }\n\n const [attribute] = sanitizeRemoteDomAttributes(\n node.localName,\n { [property]: value },\n {\n ...(options.allowedAnchorUrls\n ? { allowedAnchorUrls: options.allowedAnchorUrls }\n : {}),\n urlOriginPolicy: options.urlOriginPolicy,\n },\n );\n if (attribute) {\n return {\n ok: true,\n record: [\n MUTATION_TYPE_UPDATE_PROPERTY,\n id,\n attribute.name,\n attribute.value,\n UPDATE_PROPERTY_TYPE_ATTRIBUTE,\n ],\n };\n }\n\n const normalizedAttributeName = property.trim().toLowerCase();\n if (!/^[a-z][a-z0-9_.-]*$/u.test(normalizedAttributeName)) {\n return {\n ok: false,\n message: `Remote DOM mutation used an invalid attribute removal name \"${property}\".`,\n };\n }\n\n return {\n ok: true,\n record: [\n MUTATION_TYPE_UPDATE_PROPERTY,\n id,\n normalizedAttributeName,\n undefined,\n UPDATE_PROPERTY_TYPE_ATTRIBUTE,\n ],\n };\n}\n\ntype RemoteDomSerializableValueMaybe =\n RemoteDomNodeProperties[keyof RemoteDomNodeProperties];\n\nfunction normalizeRemoteNodeForHost(\n options: SanitizingRemoteConnectionOptions,\n state: SanitizingState,\n value: unknown,\n seen: Set<string>,\n pendingEventListenerUpdates: PendingEventListenerUpdate[],\n): NormalizeRemoteNodeResult {\n if (!isObjectRecord(value)) {\n return { ok: false, message: \"Remote DOM render payload was not a node.\" };\n }\n\n if (\n value.type === NODE_TYPE_TEXT &&\n typeof value.id === \"string\" &&\n typeof value.data === \"string\"\n ) {\n const idValidation = validateRemoteNodeId(value.id, seen);\n if (!idValidation.ok) return idValidation;\n return {\n ok: true,\n node: { id: value.id, type: NODE_TYPE_TEXT, data: value.data },\n nodeCount: 1,\n };\n }\n\n if (\n value.type !== NODE_TYPE_ELEMENT ||\n typeof value.id !== \"string\" ||\n typeof value.element !== \"string\"\n ) {\n return {\n ok: false,\n message: \"Remote DOM render payload was not a valid node.\",\n };\n }\n\n const idValidation = validateRemoteNodeId(value.id, seen);\n if (!idValidation.ok) return idValidation;\n\n const properties = readRemoteNodeProperties(value);\n if (!properties) {\n return {\n ok: false,\n message: `Remote DOM element \"${value.id}\" contained non-serializable properties.`,\n };\n }\n\n const tagName = sanitizeRemoteDomTagName(value.element);\n if (!tagName) {\n return {\n ok: false,\n message: `Remote DOM element \"${value.id}\" used an unsupported tag name.`,\n };\n }\n\n queueRemoteNodeEventListeners(\n value.id,\n tagName,\n value.eventListeners,\n pendingEventListenerUpdates,\n );\n\n if (!Array.isArray(value.children)) {\n return {\n ok: false,\n message: `Remote DOM element \"${value.id}\" did not contain a valid children array.`,\n };\n }\n\n const children: RemoteNodeSerialization[] = [];\n let nodeCount = 1;\n for (const child of value.children) {\n const normalized = normalizeRemoteNodeForHost(\n options,\n state,\n child,\n seen,\n pendingEventListenerUpdates,\n );\n if (!normalized.ok) return normalized;\n children.push(normalized.node);\n nodeCount += normalized.nodeCount;\n }\n\n const remoteProperties: Record<string, RemoteDomSerializableValueMaybe> = {};\n let attributeProperties = properties;\n if (isObjectRecord(value.properties)) {\n const mutableAttributeProperties: Record<\n string,\n RemoteDomSerializableValueMaybe\n > = { ...properties };\n attributeProperties = mutableAttributeProperties;\n for (const [rawName, rawValue] of Object.entries(value.properties)) {\n const property = sanitizeRemoteDomProperty(tagName, rawName, rawValue);\n if (property) {\n remoteProperties[property.name] = property.value;\n delete mutableAttributeProperties[rawName];\n continue;\n }\n\n if (isRemoteDomPropertyName(tagName, rawName)) {\n return {\n ok: false,\n message: `Remote DOM property \"${rawName}\" had an invalid value for \"${tagName}\".`,\n };\n }\n }\n }\n\n const attributes = sanitizeRemoteDomAttributes(tagName, attributeProperties, {\n ...(options.allowedAnchorUrls\n ? { allowedAnchorUrls: options.allowedAnchorUrls }\n : {}),\n urlOriginPolicy: options.urlOriginPolicy,\n });\n const remoteAttributes: Record<string, string> = {};\n for (const attribute of attributes) {\n remoteAttributes[attribute.name] = attribute.value;\n }\n if (tagName === \"button\" && remoteAttributes.type === undefined) {\n remoteAttributes.type = \"button\";\n }\n\n return {\n ok: true,\n node: {\n id: value.id,\n type: NODE_TYPE_ELEMENT,\n element: tagName,\n attributes: remoteAttributes,\n properties: remoteProperties,\n children,\n },\n nodeCount,\n };\n}\n\nfunction queueRemoteNodeEventListeners(\n id: string,\n tagName: string,\n eventListeners: unknown,\n pendingEventListenerUpdates: PendingEventListenerUpdate[],\n): void {\n if (!isObjectRecord(eventListeners)) return;\n for (const [eventName, listener] of Object.entries(eventListeners)) {\n if (\n !isSafeRemoteDomPropertyKey(eventName) ||\n !isSupportedRemoteDomEventName(eventName, tagName)\n ) {\n continue;\n }\n pendingEventListenerUpdates.push({\n targetId: id,\n eventName,\n listener:\n typeof listener === \"function\"\n ? (listener as RemoteDomEventListenerProxy)\n : null,\n });\n }\n}\n\nfunction validateRemoteNodeId(\n id: string,\n seen: Set<string>,\n): { readonly ok: true } | { readonly ok: false; readonly message: string } {\n if (id === REMOTE_DOM_ROOT_ID) {\n return { ok: false, message: `Remote DOM node id \"${id}\" is reserved` };\n }\n\n if (seen.has(id)) {\n return {\n ok: false,\n message: `Remote DOM render payload contained duplicate node id \"${id}\"`,\n };\n }\n\n seen.add(id);\n return { ok: true };\n}\n\nfunction readRemoteNodeProperties(\n value: Readonly<Record<string, unknown>>,\n): RemoteDomNodeProperties | undefined {\n const properties: Record<string, RemoteDomSerializableValueMaybe> = {};\n for (const source of [value.attributes, value.properties]) {\n if (source === undefined) continue;\n if (!isObjectRecord(source)) return undefined;\n\n for (const [key, item] of Object.entries(source)) {\n if (!isSafeRemoteDomPropertyKey(key)) return undefined;\n if (item !== undefined && !isRemoteDomSerializableValue(item)) {\n return undefined;\n }\n properties[key] = item as RemoteDomSerializableValueMaybe;\n }\n }\n\n return properties;\n}\n\nfunction registerSimulatedRemoteNode(\n state: SanitizingState,\n node: RemoteNodeSerialization,\n): void {\n if (node.type === NODE_TYPE_TEXT) {\n state.nodes.set(node.id, { kind: \"text\" });\n return;\n }\n if (node.type !== NODE_TYPE_ELEMENT) return;\n state.nodes.set(node.id, {\n kind: \"element\",\n localName: node.element,\n childIds: node.children.map((child) => child.id),\n });\n for (const child of node.children) {\n registerSimulatedRemoteNode(state, child);\n }\n}\n\nfunction removeSimulatedRemoteNode(state: SanitizingState, id: string): void {\n const node = state.nodes.get(id);\n if (!node) return;\n state.nodes.delete(id);\n if (node.kind === \"element\") {\n for (const childId of node.childIds) {\n removeSimulatedRemoteNode(state, childId);\n }\n }\n}\n\nfunction parseRemoteMutationRecord(\n value: unknown,\n): RemoteMutationRecord | undefined {\n if (!Array.isArray(value)) return undefined;\n switch (value[0]) {\n case MUTATION_TYPE_INSERT_CHILD:\n return value.length === 4 &&\n typeof value[1] === \"string\" &&\n isObjectRecord(value[2]) &&\n typeof value[3] === \"number\"\n ? (value as RemoteMutationRecord)\n : undefined;\n case MUTATION_TYPE_REMOVE_CHILD:\n return value.length === 3 &&\n typeof value[1] === \"string\" &&\n typeof value[2] === \"number\"\n ? (value as RemoteMutationRecord)\n : undefined;\n case MUTATION_TYPE_UPDATE_TEXT:\n return value.length === 3 &&\n typeof value[1] === \"string\" &&\n typeof value[2] === \"string\"\n ? (value as RemoteMutationRecord)\n : undefined;\n case MUTATION_TYPE_UPDATE_PROPERTY:\n return (value.length === 4 || value.length === 5) &&\n typeof value[1] === \"string\" &&\n typeof value[2] === \"string\"\n ? (value as RemoteMutationRecord)\n : undefined;\n default:\n return undefined;\n }\n}\n\nfunction isObjectRecord(\n value: unknown,\n): value is Readonly<Record<string, unknown>> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n","import {\n sanitizeRemoteDomCssUrlReferences,\n sanitizeRemoteDomUrl,\n} from \"./remote-dom-sanitizer\";\nimport {\n createRemoteDomUrlOriginPolicy,\n type RemoteDomUrlOriginPolicy,\n} from \"./remote-dom-values\";\n\nexport interface RemoteDomStyleAttachment {\n readonly ready: Promise<void>;\n readonly dispose: () => void;\n}\n\nexport interface RemoteDomStyleArtifact {\n readonly packageId: string;\n readonly version: string;\n readonly workerEntryUrl: string;\n readonly cssUrls: readonly string[];\n readonly assetUrls: readonly string[];\n}\n\nexport interface RemoteDomCssUrlSource {\n readonly url: string;\n readonly version?: string;\n}\n\nexport type RemoteDomCssUrlInput = string | RemoteDomCssUrlSource;\n\nexport type RemoteDomCssFetcher = (url: string) => Promise<string>;\n\nexport interface RemoteDomThemeBridge {\n readonly update: () => void;\n readonly dispose: () => void;\n}\n\nexport interface RemoteDomThemeBridgeOptions {\n readonly root: ShadowRoot;\n readonly sourceElement?: Element | undefined;\n readonly observeTarget?: Node | undefined;\n readonly observe?: boolean | undefined;\n readonly cssVariableNames?: readonly string[] | undefined;\n readonly dataAttributes?: readonly string[] | undefined;\n readonly classNames?: readonly string[] | \"all\" | undefined;\n readonly copyAllDataAttributes?: boolean | undefined;\n}\n\nexport interface AttachRemoteDomStylesOptions {\n readonly artifact: RemoteDomStyleArtifact;\n readonly root: ShadowRoot;\n readonly cssText?: string | undefined;\n readonly widgetCssText?: string | undefined;\n readonly cssUrls?: readonly RemoteDomCssUrlInput[] | undefined;\n readonly fluidComponentCssText?: string | undefined;\n readonly fluidComponentCssUrls?: readonly RemoteDomCssUrlInput[] | undefined;\n readonly themeBridgeCssText?: string | undefined;\n readonly urlOriginPolicy?: RemoteDomUrlOriginPolicy | undefined;\n readonly useConstructableStylesheets?: boolean | undefined;\n readonly fetchCss?: RemoteDomCssFetcher | undefined;\n /**\n * Notification-only diagnostic hook. Exceptions thrown by the callback are\n * contained and never make `RemoteDomStyleAttachment.ready` reject.\n */\n readonly onFailure?: ((failedSourceCount: number) => void) | undefined;\n readonly themeBridge?:\n | Omit<RemoteDomThemeBridgeOptions, \"root\">\n | false\n | undefined;\n}\n\ninterface StyleSourceBase {\n readonly label: string;\n}\n\ninterface TextStyleSource extends StyleSourceBase {\n readonly kind: \"text\";\n readonly cssText: string;\n}\n\ninterface UrlStyleSource extends StyleSourceBase {\n readonly kind: \"url\";\n readonly url: string;\n readonly version: string;\n}\n\ninterface ResolvedStyleSource extends TextStyleSource {\n readonly artifact?: CachedCssArtifact;\n}\n\ntype StyleSource = TextStyleSource | UrlStyleSource;\ninterface CreatedStyleSources {\n readonly sources: readonly StyleSource[];\n readonly failedSourceCount: number;\n}\n\ninterface CssVariableSnapshot {\n readonly value: string;\n readonly priority: string;\n}\n\ninterface CachedCssArtifact {\n readonly key: string;\n readonly url: string;\n readonly version: string;\n readonly promise: Promise<string>;\n sheet: CSSStyleSheet | undefined;\n refCount: number;\n}\n\ninterface AcquiredCssArtifact {\n readonly entry: CachedCssArtifact;\n released: boolean;\n}\n\nconst remoteDomCssArtifactCache = new Map<string, CachedCssArtifact>();\n\nconst DEFAULT_THEME_DATA_ATTRIBUTES = [\n \"data-theme\",\n \"data-mode\",\n \"data-color-mode\",\n \"data-fluid-theme\",\n \"data-fluid-color-scheme\",\n] as const;\n\nexport const REMOTE_DOM_WIDGET_STYLE_ATTRIBUTE = \"data-fluid-widget-style\";\n\nexport function attachRemoteDomStyles({\n artifact,\n root,\n cssText,\n widgetCssText,\n cssUrls,\n fluidComponentCssText,\n fluidComponentCssUrls,\n themeBridgeCssText,\n urlOriginPolicy,\n useConstructableStylesheets = true,\n fetchCss,\n onFailure,\n themeBridge,\n}: AttachRemoteDomStylesOptions): RemoteDomStyleAttachment {\n const styleElements: HTMLStyleElement[] = [];\n const adoptedSheets = new Set<CSSStyleSheet>();\n const acquiredArtifacts: AcquiredCssArtifact[] = [];\n let disposed = false;\n let failureReported = false;\n\n const resolvedUrlOriginPolicy =\n urlOriginPolicy ??\n createRemoteDomUrlOriginPolicy({\n artifactUrls: collectArtifactUrls(artifact),\n });\n\n const { sources, failedSourceCount: rejectedSourceCount } =\n createStyleSources({\n artifact,\n cssText,\n widgetCssText,\n cssUrls,\n fluidComponentCssText,\n fluidComponentCssUrls,\n themeBridgeCssText,\n urlOriginPolicy: resolvedUrlOriginPolicy,\n });\n const declaredSourceCount = sources.length + rejectedSourceCount;\n const bridge =\n themeBridge === false\n ? undefined\n : createRemoteDomThemeBridge({ root, ...themeBridge });\n\n const reportFailures = (failedSourceCount: number): void => {\n if (disposed || failureReported || failedSourceCount === 0) return;\n failureReported = true;\n try {\n onFailure?.(failedSourceCount);\n } catch {\n // A failing onFailure callback must not make style readiness reject.\n }\n };\n\n const ready = Promise.resolve()\n .then(async () => {\n const sourceResults = await Promise.all(\n sources.map(\n async (source): Promise<ResolvedStyleSource | null | undefined> => {\n if (disposed) return undefined;\n if (source.kind === \"text\") return source;\n\n let artifact: AcquiredCssArtifact | undefined;\n try {\n artifact = acquireCssArtifact(source, root, fetchCss);\n acquiredArtifacts.push(artifact);\n const resolvedCssText = await artifact.entry.promise;\n const sanitizedCssText = sanitizeRemoteDomCssUrlReferences(\n resolvedCssText,\n {\n urlOriginPolicy: resolvedUrlOriginPolicy,\n },\n );\n if (!sanitizedCssText) {\n releaseCssArtifact(artifact);\n if (artifact.entry.refCount === 0) {\n remoteDomCssArtifactCache.delete(artifact.entry.key);\n }\n return null;\n }\n\n if (disposed) {\n releaseCssArtifact(artifact);\n return undefined;\n }\n\n return {\n kind: \"text\" as const,\n label: source.label,\n cssText: sanitizedCssText,\n artifact: artifact.entry,\n } satisfies ResolvedStyleSource;\n } catch {\n if (artifact) {\n releaseCssArtifact(artifact);\n if (artifact.entry.refCount === 0) {\n remoteDomCssArtifactCache.delete(artifact.entry.key);\n }\n }\n return null;\n }\n },\n ),\n );\n\n if (disposed) return;\n\n const resolvedSources: ResolvedStyleSource[] = [];\n let resolutionFailureCount = 0;\n for (const source of sourceResults) {\n if (source === null) {\n resolutionFailureCount += 1;\n } else if (source !== undefined) {\n resolvedSources.push(source);\n }\n }\n const installationFailureCount = installResolvedStyleSources({\n root,\n sources: resolvedSources,\n styleElements,\n adoptedSheets,\n useConstructableStylesheets,\n });\n reportFailures(\n rejectedSourceCount + resolutionFailureCount + installationFailureCount,\n );\n })\n .catch(() => {\n // Style readiness is intentionally non-rejecting. Forward the aggregate through\n // onFailure when supplied; the renderer wires it to its safe error path.\n reportFailures(declaredSourceCount);\n });\n\n return {\n ready,\n dispose: () => {\n if (disposed) return;\n disposed = true;\n\n const cleanupErrors: unknown[] = [];\n runStyleCleanupStep(cleanupErrors, () => bridge?.dispose());\n runStyleCleanupStep(cleanupErrors, () =>\n removeAdoptedSheets(root, adoptedSheets),\n );\n\n for (const styleElement of styleElements) {\n runStyleCleanupStep(cleanupErrors, () => styleElement.remove());\n }\n\n for (const artifact of acquiredArtifacts) {\n runStyleCleanupStep(cleanupErrors, () => releaseCssArtifact(artifact));\n }\n\n throwStyleCleanupErrors(\n cleanupErrors,\n \"Remote DOM style disposal encountered cleanup failures\",\n );\n },\n };\n}\n\nexport function createRemoteDomThemeBridge(\n options: RemoteDomThemeBridgeOptions,\n): RemoteDomThemeBridge {\n const sourceElement =\n options.sourceElement ?? options.root.ownerDocument.documentElement;\n const host = options.root.host;\n const managedVariables = new Set<string>();\n const managedAttributes = new Set<string>();\n const managedClasses = new Set<string>();\n // These snapshots document host ownership for every managed key. Updates may\n // temporarily overwrite those keys, but removal and disposal restore the\n // host's exact pre-bridge values (including CSS declaration priority).\n const originalVariables =\n host instanceof HTMLElement\n ? snapshotCssVariables(host)\n : new Map<string, CssVariableSnapshot>();\n const originalAttributes =\n host instanceof HTMLElement\n ? snapshotDataAttributes(host)\n : new Map<string, string>();\n const originalClasses =\n host instanceof HTMLElement ? new Set(host.classList) : new Set<string>();\n let disposed = false;\n let observer: MutationObserver | undefined;\n\n const restore = (): void => {\n if (!(host instanceof HTMLElement)) return;\n restoreThemeBridgeState({\n host,\n managedVariables,\n managedAttributes,\n managedClasses,\n originalVariables,\n originalAttributes,\n originalClasses,\n });\n };\n\n const update = (): void => {\n if (disposed || !(host instanceof HTMLElement)) return;\n\n try {\n mirrorCssVariables({\n host,\n sourceElement,\n variableNames: options.cssVariableNames,\n managedVariables,\n originalVariables,\n });\n mirrorDataAttributes({\n host,\n sourceElement,\n dataAttributes: options.dataAttributes,\n copyAllDataAttributes: options.copyAllDataAttributes ?? true,\n managedAttributes,\n originalAttributes,\n });\n mirrorClasses({\n host,\n sourceElement,\n classNames: options.classNames ?? \"all\",\n managedClasses,\n originalClasses,\n });\n } catch (error) {\n throw rollbackThemeBridge(error);\n }\n };\n\n const rollbackThemeBridge = (error: unknown): unknown => {\n disposed = true;\n const cleanupErrors: unknown[] = [];\n runStyleCleanupStep(cleanupErrors, () => observer?.disconnect());\n runStyleCleanupStep(cleanupErrors, restore);\n return cleanupErrors.length === 0\n ? error\n : new AggregateError(\n [error, ...cleanupErrors],\n \"Remote DOM theme update failed and rollback encountered cleanup failures\",\n );\n };\n\n try {\n update();\n if (options.observe !== false && typeof MutationObserver !== \"undefined\") {\n observer = new MutationObserver(() => update());\n observer.observe(options.observeTarget ?? sourceElement, {\n attributes: true,\n childList: options.observeTarget ? true : false,\n subtree: options.observeTarget ? true : false,\n });\n }\n } catch (error) {\n if (disposed) throw error;\n throw rollbackThemeBridge(error);\n }\n\n return {\n update,\n dispose: () => {\n if (disposed) return;\n disposed = true;\n\n const cleanupErrors: unknown[] = [];\n runStyleCleanupStep(cleanupErrors, () => observer?.disconnect());\n runStyleCleanupStep(cleanupErrors, restore);\n throwStyleCleanupErrors(\n cleanupErrors,\n \"Remote DOM theme bridge disposal encountered cleanup failures\",\n );\n },\n };\n}\n\nexport function updateRemoteDomTheme(bridge: RemoteDomThemeBridge): void {\n bridge.update();\n}\n\nexport function clearRemoteDomStyleCache(): void {\n remoteDomCssArtifactCache.clear();\n}\n\nexport function getRemoteDomStyleCacheSnapshot(): readonly Readonly<{\n key: string;\n refCount: number;\n url: string;\n version: string;\n}>[] {\n return Array.from(remoteDomCssArtifactCache.values(), (entry) => ({\n key: entry.key,\n refCount: entry.refCount,\n url: entry.url,\n version: entry.version,\n }));\n}\n\nfunction collectArtifactUrls(\n artifact: RemoteDomStyleArtifact,\n): readonly string[] {\n return [artifact.workerEntryUrl, ...artifact.cssUrls, ...artifact.assetUrls];\n}\n\nfunction createStyleSources({\n artifact,\n cssText,\n widgetCssText,\n cssUrls,\n fluidComponentCssText,\n fluidComponentCssUrls,\n themeBridgeCssText,\n urlOriginPolicy,\n}: Pick<\n AttachRemoteDomStylesOptions,\n | \"cssText\"\n | \"cssUrls\"\n | \"artifact\"\n | \"fluidComponentCssText\"\n | \"fluidComponentCssUrls\"\n | \"themeBridgeCssText\"\n | \"urlOriginPolicy\"\n | \"widgetCssText\"\n>): CreatedStyleSources {\n const sources: StyleSource[] = [];\n const defaultVersion = `${artifact.packageId}@${artifact.version}`;\n let failedSourceCount = 0;\n\n failedSourceCount += addTextSource(\n sources,\n \"fluid-components\",\n fluidComponentCssText,\n urlOriginPolicy,\n );\n failedSourceCount += addUrlSources(\n sources,\n \"fluid-components\",\n fluidComponentCssUrls ?? [],\n defaultVersion,\n urlOriginPolicy,\n );\n failedSourceCount += addTextSource(\n sources,\n \"theme-bridge\",\n themeBridgeCssText,\n urlOriginPolicy,\n );\n failedSourceCount += addTextSource(\n sources,\n \"widget\",\n widgetCssText ?? cssText,\n urlOriginPolicy,\n );\n failedSourceCount += addUrlSources(\n sources,\n \"widget\",\n cssUrls ?? artifact.cssUrls,\n defaultVersion,\n urlOriginPolicy,\n );\n\n return { sources, failedSourceCount };\n}\n\nfunction addTextSource(\n sources: StyleSource[],\n label: string,\n cssText: string | undefined,\n urlOriginPolicy: RemoteDomUrlOriginPolicy | undefined,\n): number {\n if (!cssText || cssText.length === 0) return 0;\n\n try {\n const sanitizedCssText = sanitizeRemoteDomCssUrlReferences(cssText, {\n urlOriginPolicy,\n });\n if (!sanitizedCssText) return 1;\n\n sources.push({ kind: \"text\", label, cssText: sanitizedCssText });\n return 0;\n } catch {\n return 1;\n }\n}\n\nfunction addUrlSources(\n sources: StyleSource[],\n label: string,\n cssUrls: readonly RemoteDomCssUrlInput[],\n defaultVersion: string,\n urlOriginPolicy: RemoteDomUrlOriginPolicy | undefined,\n): number {\n let failedSourceCount = 0;\n for (const cssUrl of cssUrls) {\n try {\n const url = typeof cssUrl === \"string\" ? cssUrl : cssUrl.url;\n const sanitizedUrl = sanitizeRemoteDomUrl(url, {\n allowHashOnly: false,\n allowMailTo: false,\n allowRelative: false,\n allowTel: false,\n allowedHttpOriginGroups: [\"artifact\"],\n originPolicy: urlOriginPolicy,\n });\n if (!sanitizedUrl) {\n failedSourceCount += 1;\n continue;\n }\n\n sources.push({\n kind: \"url\",\n label,\n url: sanitizedUrl,\n version:\n typeof cssUrl === \"string\"\n ? defaultVersion\n : (cssUrl.version ?? defaultVersion),\n });\n } catch {\n failedSourceCount += 1;\n }\n }\n return failedSourceCount;\n}\n\nfunction acquireCssArtifact(\n source: UrlStyleSource,\n root: ShadowRoot,\n fetchCss: RemoteDomCssFetcher | undefined,\n): AcquiredCssArtifact {\n const key = createCssArtifactCacheKey(source.url, source.version);\n const existingEntry = remoteDomCssArtifactCache.get(key);\n if (existingEntry) {\n existingEntry.refCount += 1;\n return { entry: existingEntry, released: false };\n }\n\n const entry: CachedCssArtifact = {\n key,\n url: source.url,\n version: source.version,\n promise: resolveFetchCss(root, fetchCss)(source.url),\n sheet: undefined,\n refCount: 1,\n };\n remoteDomCssArtifactCache.set(key, entry);\n return { entry, released: false };\n}\n\nfunction releaseCssArtifact(artifact: AcquiredCssArtifact): void {\n if (artifact.released) return;\n artifact.released = true;\n artifact.entry.refCount = Math.max(0, artifact.entry.refCount - 1);\n}\n\nfunction runStyleCleanupStep(errors: unknown[], cleanup: () => void): void {\n try {\n cleanup();\n } catch (error) {\n errors.push(error);\n }\n}\n\nfunction throwStyleCleanupErrors(\n errors: readonly unknown[],\n message: string,\n): void {\n if (errors.length > 0) throw new AggregateError(errors, message);\n}\n\nfunction installResolvedStyleSources({\n root,\n sources,\n styleElements,\n adoptedSheets,\n useConstructableStylesheets,\n}: {\n readonly root: ShadowRoot;\n readonly sources: readonly ResolvedStyleSource[];\n readonly styleElements: HTMLStyleElement[];\n readonly adoptedSheets: Set<CSSStyleSheet>;\n readonly useConstructableStylesheets: boolean;\n}): number {\n const canAdoptStylesheets =\n useConstructableStylesheets && readAdoptedStyleSheets(root) !== undefined;\n let failedSourceCount = 0;\n let adoptedSourceCount = 0;\n\n for (const source of sources) {\n let sheet: CSSStyleSheet | undefined;\n if (canAdoptStylesheets) {\n try {\n sheet = getOrCreateConstructableStyleSheet(\n source.cssText,\n source.artifact,\n );\n } catch {\n sheet = undefined;\n }\n }\n\n if (sheet) {\n adoptedSheets.add(sheet);\n adoptedSourceCount += 1;\n continue;\n }\n\n let styleElement: HTMLStyleElement | undefined;\n try {\n styleElement = root.ownerDocument.createElement(\"style\");\n styleElement.setAttribute(\n REMOTE_DOM_WIDGET_STYLE_ATTRIBUTE,\n source.label,\n );\n styleElement.textContent = source.cssText;\n root.append(styleElement);\n styleElements.push(styleElement);\n } catch {\n styleElement?.remove();\n failedSourceCount += 1;\n }\n }\n\n if (adoptedSheets.size > 0) {\n try {\n appendAdoptedSheets(root, Array.from(adoptedSheets));\n } catch {\n let removalFailed = false;\n try {\n removeAdoptedSheets(root, adoptedSheets);\n } catch {\n removalFailed = true;\n }\n if (!removalFailed) adoptedSheets.clear();\n failedSourceCount += adoptedSourceCount;\n }\n }\n\n return failedSourceCount;\n}\n\nfunction getOrCreateConstructableStyleSheet(\n cssText: string,\n cachedArtifact: CachedCssArtifact | undefined,\n): CSSStyleSheet | undefined {\n if (cachedArtifact?.sheet) return cachedArtifact.sheet;\n\n const sheet = createConstructableStyleSheet(cssText);\n if (cachedArtifact) cachedArtifact.sheet = sheet;\n return sheet;\n}\n\nfunction createConstructableStyleSheet(\n cssText: string,\n): CSSStyleSheet | undefined {\n if (typeof CSSStyleSheet === \"undefined\") return undefined;\n\n const sheet = new CSSStyleSheet();\n if (typeof sheet.replaceSync !== \"function\") return undefined;\n\n try {\n sheet.replaceSync(cssText);\n return sheet;\n } catch {\n return undefined;\n }\n}\n\nfunction appendAdoptedSheets(\n root: ShadowRoot,\n sheets: readonly CSSStyleSheet[],\n): void {\n const previousAdoptedStyleSheets = readAdoptedStyleSheets(root);\n if (!previousAdoptedStyleSheets) return;\n\n root.adoptedStyleSheets = [...previousAdoptedStyleSheets, ...sheets];\n}\n\nfunction removeAdoptedSheets(\n root: ShadowRoot,\n adoptedSheets: ReadonlySet<CSSStyleSheet>,\n): void {\n if (adoptedSheets.size === 0) return;\n\n const currentAdoptedStyleSheets = readAdoptedStyleSheets(root);\n if (!currentAdoptedStyleSheets) return;\n\n root.adoptedStyleSheets = currentAdoptedStyleSheets.filter(\n (sheet) => !adoptedSheets.has(sheet),\n );\n}\n\nfunction readAdoptedStyleSheets(root: ShadowRoot): CSSStyleSheet[] | undefined {\n if (!(\"adoptedStyleSheets\" in root)) return undefined;\n\n return [...root.adoptedStyleSheets];\n}\n\nfunction resolveFetchCss(\n root: ShadowRoot,\n fetchCss: RemoteDomCssFetcher | undefined,\n): RemoteDomCssFetcher {\n if (fetchCss) return fetchCss;\n\n const windowFetch = root.ownerDocument.defaultView?.fetch;\n if (typeof windowFetch === \"function\") {\n return async (url) => {\n const response = await windowFetch(url);\n if (!response.ok) {\n throw new Error(`Failed to fetch Remote DOM CSS: ${url}`);\n }\n return response.text();\n };\n }\n\n return async () => \"\";\n}\n\nfunction createCssArtifactCacheKey(url: string, version: string): string {\n return `${version}:${url}`;\n}\n\nfunction snapshotCssVariables(\n host: HTMLElement,\n): ReadonlyMap<string, CssVariableSnapshot> {\n const declaredVariableNames = new Set<string>();\n collectCssVariableNamesFromDeclaration(declaredVariableNames, host.style);\n\n const snapshots = new Map<string, CssVariableSnapshot>();\n for (const variableName of declaredVariableNames) {\n snapshots.set(variableName, {\n value: host.style.getPropertyValue(variableName),\n priority: host.style.getPropertyPriority(variableName),\n });\n }\n return snapshots;\n}\n\nfunction snapshotDataAttributes(\n host: HTMLElement,\n): ReadonlyMap<string, string> {\n const snapshots = new Map<string, string>();\n for (const attributeName of host.getAttributeNames()) {\n if (!attributeName.startsWith(\"data-\")) continue;\n const value = host.getAttribute(attributeName);\n if (value !== null) snapshots.set(attributeName, value);\n }\n return snapshots;\n}\n\nfunction restoreThemeBridgeState({\n host,\n managedVariables,\n managedAttributes,\n managedClasses,\n originalVariables,\n originalAttributes,\n originalClasses,\n}: {\n readonly host: HTMLElement;\n readonly managedVariables: Set<string>;\n readonly managedAttributes: Set<string>;\n readonly managedClasses: Set<string>;\n readonly originalVariables: ReadonlyMap<string, CssVariableSnapshot>;\n readonly originalAttributes: ReadonlyMap<string, string>;\n readonly originalClasses: ReadonlySet<string>;\n}): void {\n const restorationErrors: unknown[] = [];\n\n for (const variableName of Array.from(managedVariables)) {\n runStyleCleanupStep(restorationErrors, () => {\n restoreCssVariable(host, variableName, originalVariables);\n managedVariables.delete(variableName);\n });\n }\n\n for (const attributeName of Array.from(managedAttributes)) {\n runStyleCleanupStep(restorationErrors, () => {\n const originalValue = originalAttributes.get(attributeName);\n if (originalValue === undefined) {\n host.removeAttribute(attributeName);\n } else {\n host.setAttribute(attributeName, originalValue);\n }\n managedAttributes.delete(attributeName);\n });\n }\n\n for (const className of Array.from(managedClasses)) {\n runStyleCleanupStep(restorationErrors, () => {\n host.classList.toggle(className, originalClasses.has(className));\n managedClasses.delete(className);\n });\n }\n\n throwStyleCleanupErrors(\n restorationErrors,\n \"Remote DOM theme restoration encountered cleanup failures\",\n );\n}\n\nfunction restoreCssVariable(\n host: HTMLElement,\n variableName: string,\n originalVariables: ReadonlyMap<string, CssVariableSnapshot>,\n): void {\n const original = originalVariables.get(variableName);\n if (original) {\n host.style.setProperty(variableName, original.value, original.priority);\n } else {\n host.style.removeProperty(variableName);\n }\n}\n\nfunction mirrorCssVariables({\n host,\n sourceElement,\n variableNames,\n managedVariables,\n originalVariables,\n}: {\n readonly host: HTMLElement;\n readonly sourceElement: Element;\n readonly variableNames: readonly string[] | undefined;\n readonly managedVariables: Set<string>;\n readonly originalVariables: ReadonlyMap<string, CssVariableSnapshot>;\n}): void {\n const computedStyle =\n sourceElement.ownerDocument.defaultView?.getComputedStyle(sourceElement);\n const nextVariables = new Set(\n (\n variableNames ?? collectCssVariableNames(sourceElement, computedStyle)\n ).filter((variableName) => variableName.startsWith(\"--\")),\n );\n\n for (const variableName of managedVariables) {\n if (!nextVariables.has(variableName)) {\n restoreCssVariable(host, variableName, originalVariables);\n managedVariables.delete(variableName);\n }\n }\n\n for (const variableName of nextVariables) {\n const value = computedStyle?.getPropertyValue(variableName) ?? \"\";\n if (value.length > 0) {\n managedVariables.add(variableName);\n host.style.setProperty(variableName, value.trim());\n } else {\n restoreCssVariable(host, variableName, originalVariables);\n managedVariables.delete(variableName);\n }\n }\n}\n\nfunction collectCssVariableNames(\n sourceElement: Element,\n computedStyle: CSSStyleDeclaration | undefined,\n): readonly string[] {\n const variableNames = new Set<string>();\n collectCssVariableNamesFromDeclaration(variableNames, computedStyle);\n\n if (\n sourceElement instanceof HTMLElement ||\n sourceElement instanceof SVGElement\n ) {\n collectCssVariableNamesFromDeclaration(variableNames, sourceElement.style);\n }\n\n return Array.from(variableNames);\n}\n\nfunction collectCssVariableNamesFromDeclaration(\n variableNames: Set<string>,\n declaration: CSSStyleDeclaration | undefined,\n): void {\n if (!declaration) return;\n\n for (let index = 0; index < declaration.length; index += 1) {\n const propertyName = declaration.item(index);\n if (propertyName.startsWith(\"--\")) {\n variableNames.add(propertyName);\n }\n }\n}\n\nfunction mirrorDataAttributes({\n host,\n sourceElement,\n dataAttributes,\n copyAllDataAttributes,\n managedAttributes,\n originalAttributes,\n}: {\n readonly host: HTMLElement;\n readonly sourceElement: Element;\n readonly dataAttributes: readonly string[] | undefined;\n readonly copyAllDataAttributes: boolean;\n readonly managedAttributes: Set<string>;\n readonly originalAttributes: ReadonlyMap<string, string>;\n}): void {\n const nextAttributes = new Map<string, string>();\n const attributeNames = (\n dataAttributes ??\n (copyAllDataAttributes\n ? sourceElement.getAttributeNames()\n : DEFAULT_THEME_DATA_ATTRIBUTES)\n ).filter((attributeName) => attributeName.startsWith(\"data-\"));\n\n for (const attributeName of attributeNames) {\n const value = sourceElement.getAttribute(attributeName);\n if (value !== null) nextAttributes.set(attributeName, value);\n }\n\n for (const attributeName of managedAttributes) {\n if (!nextAttributes.has(attributeName)) {\n const originalValue = originalAttributes.get(attributeName);\n if (originalValue === undefined) {\n host.removeAttribute(attributeName);\n } else {\n host.setAttribute(attributeName, originalValue);\n }\n managedAttributes.delete(attributeName);\n }\n }\n\n for (const [attributeName, value] of nextAttributes) {\n managedAttributes.add(attributeName);\n host.setAttribute(attributeName, value);\n }\n}\n\nfunction mirrorClasses({\n host,\n sourceElement,\n classNames,\n managedClasses,\n originalClasses,\n}: {\n readonly host: HTMLElement;\n readonly sourceElement: Element;\n readonly classNames: readonly string[] | \"all\";\n readonly managedClasses: Set<string>;\n readonly originalClasses: ReadonlySet<string>;\n}): void {\n const sourceClasses = new Set(sourceElement.classList);\n const nextClasses =\n classNames === \"all\"\n ? sourceClasses\n : new Set(classNames.filter((className) => sourceClasses.has(className)));\n\n for (const className of managedClasses) {\n if (!nextClasses.has(className)) {\n host.classList.toggle(className, originalClasses.has(className));\n managedClasses.delete(className);\n }\n }\n\n for (const className of nextClasses) {\n managedClasses.add(className);\n host.classList.add(className);\n }\n}\n","import {\n release,\n retain,\n Thread,\n type ThreadMessageTarget,\n} from \"@quilted/threads\";\nimport { ROOT_ID as REMOTE_DOM_ROOT_ID } from \"@remote-dom/core\";\nimport { remoteId } from \"@remote-dom/core/elements\";\nimport { DOMRemoteReceiver } from \"@remote-dom/core/receivers\";\nimport {\n createSanitizingRemoteConnection,\n RemoteDomConnectionCallDeniedError,\n type RemoteDomEventListenerProxy,\n} from \"./remote-dom-sanitizing-connection\";\nimport {\n isSupportedRemoteDomEventName,\n sanitizeRemoteDomUrl,\n serializeRemoteDomEvent,\n} from \"./remote-dom-sanitizer\";\nimport {\n attachRemoteDomStyles,\n REMOTE_DOM_WIDGET_STYLE_ATTRIBUTE,\n type RemoteDomCssFetcher,\n type RemoteDomCssUrlInput,\n type RemoteDomStyleAttachment,\n type RemoteDomStyleArtifact,\n type RemoteDomThemeBridgeOptions,\n} from \"./remote-dom-styles\";\nimport {\n createRemoteDomUrlOriginPolicy,\n isRemoteDomSerializableValue,\n REMOTE_DOM_FULLSCREEN_CAPABILITY,\n type RemoteDomNavigationIntent,\n type RemoteDomSerializableValue,\n type RemoteDomUrlOriginPolicy,\n} from \"./remote-dom-values\";\nimport type {\n RemoteDomWidgetWorkerApi,\n RemoteDomWidgetWorkerHostApi,\n} from \"./worker-runtime\";\n\nexport type { RemoteDomNavigationIntent };\n\nexport interface RemoteDomCapabilityDeclaration {\n readonly name: string;\n readonly version: string;\n}\n\nexport interface RemoteDomWidgetArtifact extends RemoteDomStyleArtifact {\n readonly widgetType: string;\n readonly capabilities: readonly RemoteDomCapabilityDeclaration[];\n readonly networkAccessGranted?: boolean | undefined;\n}\n\nexport interface RemoteDomFullscreenRequest {\n readonly method: string;\n readonly payload?: RemoteDomSerializableValue | undefined;\n readonly host: HTMLElement;\n readonly shadowRoot: ShadowRoot;\n}\n\nexport interface MountRemoteDomWidgetOptions {\n readonly host: HTMLElement;\n readonly artifact: RemoteDomWidgetArtifact;\n readonly props?: RemoteDomSerializableValue | undefined;\n readonly callCapability?:\n | ((\n capability: string,\n method: string,\n payload?: RemoteDomSerializableValue,\n ) => RemoteDomSerializableValue | Promise<RemoteDomSerializableValue>)\n | undefined;\n readonly onNavigate?:\n | ((intent: RemoteDomNavigationIntent) => void | Promise<void>)\n | undefined;\n readonly onFullscreen?:\n | ((\n request: RemoteDomFullscreenRequest,\n ) => RemoteDomSerializableValue | Promise<RemoteDomSerializableValue>)\n | undefined;\n readonly onError?: ((error: Error) => void) | undefined;\n readonly workerFactory?: RemoteDomWorkerFactory | undefined;\n readonly hostOrigin?: string | undefined;\n readonly mediaOrigins?: readonly string[] | undefined;\n /** Canonical absolute HTTP(S) URLs registered for native new-tab anchors. */\n readonly allowedAnchorUrls?: ReadonlySet<string> | undefined;\n readonly maxMutationBatchSize?: number | undefined;\n readonly maxDomNodeCount?: number | undefined;\n readonly cssText?: string | undefined;\n readonly widgetCssText?: string | undefined;\n readonly cssUrls?: readonly RemoteDomCssUrlInput[] | undefined;\n readonly fluidComponentCssText?: string | undefined;\n readonly fluidComponentCssUrls?: readonly RemoteDomCssUrlInput[] | undefined;\n readonly themeBridgeCssText?: string | undefined;\n readonly themeBridge?:\n | Omit<RemoteDomThemeBridgeOptions, \"root\">\n | false\n | undefined;\n readonly fetchCss?: RemoteDomCssFetcher | undefined;\n readonly useConstructableStylesheets?: boolean | undefined;\n}\n\nexport interface RemoteDomWidgetHandle {\n readonly shadowRoot: ShadowRoot;\n readonly styles: RemoteDomStyleAttachment;\n readonly ready: Promise<void>;\n updateProps(props: RemoteDomSerializableValue): void;\n dispose(): void;\n}\n\nexport interface RemoteDomWorkerLike {\n onmessage: ((event: MessageEvent<unknown>) => void) | null;\n onerror: ((event: ErrorEvent) => void) | null;\n postMessage(message: unknown, transfer?: Transferable[]): void;\n terminate(): void;\n addEventListener?: (\n type: \"message\",\n listener: (event: MessageEvent<unknown>) => void,\n options?: { signal?: AbortSignal },\n ) => void;\n}\n\nexport type RemoteDomWorkerFactory = (\n workerEntryUrl: string,\n options: WorkerOptions,\n) => RemoteDomWorkerLike;\n\ninterface RemoteDomEventSubscription {\n readonly targetId: string;\n readonly eventName: string;\n readonly target: EventTarget;\n readonly listener: EventListener;\n readonly capture: boolean;\n readonly proxy: RemoteDomEventListenerProxy;\n}\n\ninterface PendingEventListenerUpdate {\n readonly targetId: string;\n readonly eventName: string;\n readonly listener: RemoteDomEventListenerProxy | null;\n}\n\ninterface MountState {\n readonly options: MountRemoteDomWidgetOptions;\n readonly shadowRoot: ShadowRoot;\n readonly worker: RemoteDomWorkerLike;\n readonly thread: Thread<RemoteDomWidgetWorkerApi>;\n readonly styles: RemoteDomStyleAttachment;\n readonly urlOriginPolicy: RemoteDomUrlOriginPolicy;\n readonly navigationOrigin: string | undefined;\n readonly nodesById: Map<string, Node>;\n readonly subscriptions: Map<string, RemoteDomEventSubscription>;\n readonly pendingListenerUpdates: Map<string, PendingEventListenerUpdate>;\n readonly submitListener: EventListener;\n readonly navigationListener: EventListener;\n disposed: boolean;\n cleanupStarted: boolean;\n}\n\nconst DEFAULT_MAX_MUTATION_BATCH_SIZE = 100;\nconst DEFAULT_MAX_DOM_NODE_COUNT = 1_000;\n\nexport function mountRemoteDomWidget(\n options: MountRemoteDomWidgetOptions,\n): RemoteDomWidgetHandle {\n const initialProps = options.props ?? null;\n assertSerializable(initialProps, \"Initial widget props\");\n\n const shadowRoot = createShadowRoot(options.host);\n const navigationOrigin = normalizeNavigationOrigin(options.hostOrigin);\n const urlOriginPolicy = createRemoteDomUrlOriginPolicy({\n artifactUrls: collectArtifactUrls(options.artifact),\n ...(options.mediaOrigins === undefined\n ? {}\n : { mediaOrigins: options.mediaOrigins }),\n ...(navigationOrigin === undefined ? {} : { navigationOrigin }),\n });\n const styles = attachRemoteDomStyles({\n artifact: options.artifact,\n root: shadowRoot,\n urlOriginPolicy,\n onFailure: (count) => {\n reportError(options, `${count} Remote DOM widget styles failed to load`);\n },\n ...(options.cssText === undefined ? {} : { cssText: options.cssText }),\n ...(options.widgetCssText === undefined\n ? {}\n : { widgetCssText: options.widgetCssText }),\n ...(options.cssUrls === undefined ? {} : { cssUrls: options.cssUrls }),\n ...(options.fluidComponentCssText === undefined\n ? {}\n : { fluidComponentCssText: options.fluidComponentCssText }),\n ...(options.fluidComponentCssUrls === undefined\n ? {}\n : { fluidComponentCssUrls: options.fluidComponentCssUrls }),\n ...(options.themeBridgeCssText === undefined\n ? {}\n : { themeBridgeCssText: options.themeBridgeCssText }),\n ...(options.themeBridge === undefined\n ? {}\n : { themeBridge: options.themeBridge }),\n ...(options.fetchCss === undefined ? {} : { fetchCss: options.fetchCss }),\n ...(options.useConstructableStylesheets === undefined\n ? {}\n : { useConstructableStylesheets: options.useConstructableStylesheets }),\n });\n\n let worker: RemoteDomWorkerLike;\n try {\n worker = (options.workerFactory ?? createDefaultWorker)(\n options.artifact.workerEntryUrl,\n { type: \"module\" },\n );\n } catch (error) {\n reportCleanupErrors(\n options,\n \"Remote DOM widget setup cleanup failed\",\n collectCleanupErrors([\n () => styles.dispose(),\n () => clearRenderedRemoteDomNodes(shadowRoot),\n ]),\n );\n throw error;\n }\n\n let thread: Thread<RemoteDomWidgetWorkerApi>;\n try {\n thread = new Thread<RemoteDomWidgetWorkerApi>(\n createWorkerMessageTarget(worker),\n );\n } catch (error) {\n reportCleanupErrors(\n options,\n \"Remote DOM widget setup cleanup failed\",\n collectCleanupErrors([\n () => styles.dispose(),\n () => worker.terminate(),\n () => clearRenderedRemoteDomNodes(shadowRoot),\n ]),\n );\n throw error;\n }\n\n let state: MountState;\n const pendingListenerUpdates = new Map<string, PendingEventListenerUpdate>();\n const receiver = new DOMRemoteReceiver({\n root: shadowRoot as unknown as Element,\n call: () => {\n throw new RemoteDomConnectionCallDeniedError(\"remote element method\");\n },\n });\n const connection = createSanitizingRemoteConnection({\n connection: receiver.connection,\n ...(options.allowedAnchorUrls\n ? { allowedAnchorUrls: options.allowedAnchorUrls }\n : {}),\n urlOriginPolicy,\n maxMutationBatchSize:\n options.maxMutationBatchSize ?? DEFAULT_MAX_MUTATION_BATCH_SIZE,\n maxDomNodeCount: options.maxDomNodeCount ?? DEFAULT_MAX_DOM_NODE_COUNT,\n onEventListenerUpdate: (targetId, eventName, listener) => {\n pendingListenerUpdates.set(subscriptionKey(targetId, eventName), {\n targetId,\n eventName,\n listener,\n });\n },\n onNodeLimitExceeded: () => {\n reportError(options, \"Remote DOM widget exceeded its DOM node limit\");\n },\n onInvalidRecord: (message) => reportError(options, message),\n onMutateError: (error) =>\n reportError(options, \"Remote DOM mutation could not be applied\", error),\n });\n\n const submitListener = createSubmitPreventionListener();\n const navigationListener: EventListener = (event) => {\n handleNavigationIntent(state, event);\n };\n state = {\n options,\n shadowRoot,\n worker,\n thread,\n styles,\n urlOriginPolicy,\n navigationOrigin,\n nodesById: new Map([[REMOTE_DOM_ROOT_ID, shadowRoot]]),\n subscriptions: new Map(),\n pendingListenerUpdates,\n submitListener,\n navigationListener,\n disposed: false,\n cleanupStarted: false,\n };\n\n shadowRoot.addEventListener(\"submit\", submitListener, { capture: true });\n shadowRoot.addEventListener(\"click\", navigationListener, { capture: true });\n worker.onerror = (event) => {\n // Cancel the event FIRST, and regardless of `disposed`. An uncaught\n // throw inside a worker is re-reported on the *host* document unless\n // this event is canceled, so without preventDefault every widget\n // crash lands in the host page's `window.onerror` — which in Mist\n // Desktop is Sentry's global handler. A widget failure the runtime\n // already handles (onError → inline \"couldn't render this widget\")\n // was being filed a second time as an unhandled production error\n // against the host app. Sandboxed widget faults must not escape into\n // host telemetry.\n event.preventDefault?.();\n if (state.disposed) return;\n reportError(\n options,\n event.message || \"Remote DOM widget worker failed\",\n event.error,\n );\n disposeAfterFailure(state, false);\n };\n\n const hostApi: RemoteDomWidgetWorkerHostApi = {\n mutate(records) {\n if (state.disposed) return;\n connection.mutate(records);\n rebuildNodeIndex(state);\n enforceAllowedAnchorSafety(state);\n flushPendingListenerUpdates(state);\n },\n callCapability(capability, method, payload) {\n return callCapability(state, capability, method, payload);\n },\n reportError(error) {\n reportError(options, error.message);\n },\n };\n\n const ready = Promise.all([\n styles.ready,\n thread.imports.mount(\n {\n widgetType: options.artifact.widgetType,\n props: initialProps,\n ...(options.artifact.networkAccessGranted === true\n ? {\n networkAccessGranted: true,\n hostOrigin: options.hostOrigin,\n }\n : {}),\n },\n hostApi,\n ),\n ]).then(() => undefined);\n void ready.catch((error: unknown) => {\n if (state.disposed) return;\n reportError(options, \"Remote DOM widget failed to mount\", error);\n disposeAfterFailure(state);\n });\n\n return {\n shadowRoot,\n styles,\n ready,\n updateProps(props) {\n if (state.disposed) return;\n assertSerializable(props, \"Widget props\");\n void state.thread.imports.updateProps(props).catch((error: unknown) => {\n if (!state.disposed) {\n reportError(options, \"Remote DOM widget props update failed\", error);\n }\n });\n },\n dispose() {\n disposeMount(state);\n },\n };\n}\n\nfunction callCapability(\n state: MountState,\n capability: string,\n method: string,\n payload: RemoteDomSerializableValue | undefined,\n): Promise<RemoteDomSerializableValue> {\n if (state.disposed) {\n return Promise.reject(new Error(\"Remote DOM widget has been disposed\"));\n }\n if (\n !state.options.artifact.capabilities.some(\n (declaration) => declaration.name === capability,\n )\n ) {\n return Promise.reject(\n new Error(`Remote DOM capability \"${capability}\" was not declared`),\n );\n }\n if (payload !== undefined && !isRemoteDomSerializableValue(payload)) {\n return Promise.reject(\n new Error(\"Remote DOM capability payload was not serializable\"),\n );\n }\n\n if (\n capability === REMOTE_DOM_FULLSCREEN_CAPABILITY &&\n state.options.onFullscreen\n ) {\n return Promise.resolve()\n .then(() =>\n state.options.onFullscreen?.({\n method,\n ...(payload === undefined ? {} : { payload }),\n host: state.options.host,\n shadowRoot: state.shadowRoot,\n }),\n )\n .then((result) => {\n if (result === undefined) {\n throw new Error(\"Remote DOM fullscreen handler returned no result\");\n }\n return assertSerializableCapabilityResult(result);\n });\n }\n if (!state.options.callCapability) {\n return Promise.reject(\n new Error(`No host handler is configured for capability \"${capability}\"`),\n );\n }\n\n return Promise.resolve()\n .then(() => state.options.callCapability?.(capability, method, payload))\n .then((result) => {\n if (result === undefined) {\n throw new Error(\n `Capability handler for \"${capability}\" returned no result`,\n );\n }\n return assertSerializableCapabilityResult(result);\n });\n}\n\nfunction assertSerializableCapabilityResult(\n result: RemoteDomSerializableValue,\n): RemoteDomSerializableValue {\n if (!isRemoteDomSerializableValue(result)) {\n throw new Error(\"Remote DOM capability result was not serializable\");\n }\n return result;\n}\n\nfunction rebuildNodeIndex(state: MountState): void {\n state.nodesById.clear();\n state.nodesById.set(REMOTE_DOM_ROOT_ID, state.shadowRoot);\n\n const visit = (node: Node): void => {\n state.nodesById.set(remoteId(node), node);\n for (const child of node.childNodes) visit(child);\n };\n for (const child of state.shadowRoot.childNodes) {\n if (!isWidgetStyleNode(child)) visit(child);\n }\n\n for (const subscription of Array.from(state.subscriptions.values())) {\n if (!state.nodesById.has(subscription.targetId)) {\n unsubscribe(state, subscription.targetId, subscription.eventName);\n }\n }\n}\n\nfunction flushPendingListenerUpdates(state: MountState): void {\n for (const update of state.pendingListenerUpdates.values()) {\n if (update.listener === null) {\n unsubscribe(state, update.targetId, update.eventName);\n } else {\n subscribe(state, update.targetId, update.eventName, update.listener);\n }\n }\n state.pendingListenerUpdates.clear();\n}\n\nfunction subscribe(\n state: MountState,\n targetId: string,\n eventName: string,\n proxy: RemoteDomEventListenerProxy,\n): void {\n const target = state.nodesById.get(targetId);\n const tagName = target instanceof Element ? target.localName : undefined;\n if (!target || !isSupportedRemoteDomEventName(eventName, tagName)) return;\n\n unsubscribe(state, targetId, eventName);\n const capture = targetId === REMOTE_DOM_ROOT_ID;\n const listener: EventListener = (event) => {\n if (\n !capture &&\n hasCloserEventSubscription(state, event, target, eventName)\n ) {\n return;\n }\n if (eventName === \"submit\" && event.cancelable) event.preventDefault();\n\n const actualTargetId = resolveEventTargetId(state, event);\n if (!actualTargetId) return;\n const eventPayload = serializeRemoteDomEvent(\n event,\n actualTargetId,\n targetId,\n tagName,\n );\n if (!eventPayload) return;\n\n try {\n const result = proxy({\n targetId: actualTargetId,\n detail: toSerializableEventPayload(eventPayload),\n });\n if (isPromiseLike(result)) {\n void result.catch((error: unknown) => {\n reportEventDeliveryFailure(state, error);\n });\n }\n } catch (error) {\n reportEventDeliveryFailure(state, error);\n }\n };\n\n target.addEventListener(eventName, listener, { capture });\n retain(proxy);\n state.subscriptions.set(subscriptionKey(targetId, eventName), {\n targetId,\n eventName,\n target,\n listener,\n capture,\n proxy,\n });\n}\n\nfunction hasCloserEventSubscription(\n state: MountState,\n event: Event,\n subscriptionTarget: EventTarget,\n eventName: string,\n): boolean {\n for (const pathTarget of event.composedPath()) {\n if (pathTarget === subscriptionTarget) return false;\n if (!(pathTarget instanceof Node)) continue;\n const pathTargetId = remoteId(pathTarget);\n if (\n state.nodesById.get(pathTargetId) === pathTarget &&\n state.subscriptions.has(subscriptionKey(pathTargetId, eventName))\n ) {\n return true;\n }\n }\n return false;\n}\n\nfunction unsubscribe(\n state: MountState,\n targetId: string,\n eventName: string,\n): void {\n const key = subscriptionKey(targetId, eventName);\n const subscription = state.subscriptions.get(key);\n if (!subscription) return;\n subscription.target.removeEventListener(eventName, subscription.listener, {\n capture: subscription.capture,\n });\n release(subscription.proxy);\n state.subscriptions.delete(key);\n}\n\nfunction resolveEventTargetId(\n state: MountState,\n event: Event,\n): string | undefined {\n for (const target of event.composedPath()) {\n if (target === state.shadowRoot) return REMOTE_DOM_ROOT_ID;\n if (!(target instanceof Node)) continue;\n const id = remoteId(target);\n if (state.nodesById.get(id) === target) return id;\n }\n return undefined;\n}\n\nfunction handleNavigationIntent(state: MountState, event: Event): void {\n if (!(event instanceof MouseEvent)) return;\n const element =\n event.target instanceof Element\n ? event.target\n : event.target instanceof Text\n ? event.target.parentElement\n : null;\n const anchor = element?.closest(\"a[href]\");\n if (!(anchor instanceof HTMLAnchorElement)) return;\n if (!state.shadowRoot.contains(anchor)) return;\n\n const allowedAnchorUrl = resolveAllowedAnchorUrl(\n anchor.getAttribute(\"href\"),\n state.options.allowedAnchorUrls,\n );\n if (allowedAnchorUrl) {\n enforceAllowedAnchorSafetyAttributes(anchor);\n return;\n }\n\n if (event.cancelable) event.preventDefault();\n\n const href = sanitizeRemoteDomUrl(anchor.getAttribute(\"href\"), {\n allowHashOnly: true,\n allowMailTo: false,\n allowRelative: true,\n allowTel: false,\n allowedHttpOriginGroups: [\"navigation\"],\n originPolicy: state.urlOriginPolicy,\n relativeUrlBase: \"navigation\",\n });\n\n const url = href\n ? resolveInternalNavigationUrl(href, state.navigationOrigin)\n : undefined;\n if (!href || !url || !state.options.onNavigate) {\n reportError(\n state.options,\n \"Remote DOM navigation was blocked because no allowed internal route handler was available\",\n );\n return;\n }\n\n const targetId = findNodeId(state, anchor);\n void Promise.resolve(\n state.options.onNavigate({\n href,\n url,\n source: \"anchor\",\n ...(targetId === undefined ? {} : { targetId }),\n altKey: event.altKey,\n button: event.button,\n ctrlKey: event.ctrlKey,\n metaKey: event.metaKey,\n shiftKey: event.shiftKey,\n }),\n ).catch((error: unknown) => {\n if (!state.disposed) {\n reportError(state.options, \"Remote DOM navigation handler failed\", error);\n }\n });\n}\n\nfunction disposeMount(state: MountState, notifyWorker = true): void {\n if (state.cleanupStarted) return;\n state.cleanupStarted = true;\n state.disposed = true;\n const cleanupSteps: Array<() => void> = [\n () => {\n state.worker.onerror = null;\n },\n () => {\n state.shadowRoot.removeEventListener(\"submit\", state.submitListener, {\n capture: true,\n });\n },\n () => {\n state.shadowRoot.removeEventListener(\"click\", state.navigationListener, {\n capture: true,\n });\n },\n ];\n for (const subscription of Array.from(state.subscriptions.values())) {\n cleanupSteps.push(() => {\n unsubscribe(state, subscription.targetId, subscription.eventName);\n });\n }\n cleanupSteps.push(\n () => state.pendingListenerUpdates.clear(),\n () => state.styles.dispose(),\n () => clearRenderedRemoteDomNodes(state.shadowRoot),\n () => state.nodesById.clear(),\n );\n\n const cleanupErrors = collectCleanupErrors(cleanupSteps);\n\n if (notifyWorker) {\n void Promise.resolve(state.thread.imports.dispose()).catch(() => undefined);\n }\n queueMicrotask(() => {\n reportCleanupErrors(\n state.options,\n \"Remote DOM widget asynchronous cleanup failed\",\n collectCleanupErrors([\n () => state.thread.close(),\n () => state.worker.terminate(),\n ]),\n );\n });\n\n if (cleanupErrors.length > 0) {\n throw new AggregateError(cleanupErrors, \"Remote DOM widget cleanup failed\");\n }\n}\n\nfunction disposeAfterFailure(state: MountState, notifyWorker = true): void {\n try {\n disposeMount(state, notifyWorker);\n } catch (cleanupError) {\n reportError(\n state.options,\n \"Remote DOM widget cleanup failed after an earlier error\",\n cleanupError,\n );\n }\n}\n\nfunction reportEventDeliveryFailure(state: MountState, error: unknown): void {\n // Thread proxies can reject after teardown releases them. Those failures are\n // expected disposal races; failures while mounted are genuine diagnostics.\n if (state.disposed) return;\n reportError(state.options, \"Remote DOM event delivery failed\", error);\n}\n\nfunction createShadowRoot(host: HTMLElement): ShadowRoot {\n if (host.shadowRoot) {\n host.shadowRoot.replaceChildren();\n return host.shadowRoot;\n }\n return host.attachShadow({ mode: \"open\" });\n}\n\nfunction createSubmitPreventionListener(): EventListener {\n return (event) => {\n if (event.cancelable) event.preventDefault();\n };\n}\n\nfunction collectArtifactUrls(\n artifact: RemoteDomWidgetArtifact,\n): readonly string[] {\n return [artifact.workerEntryUrl, ...artifact.cssUrls, ...artifact.assetUrls];\n}\n\nfunction normalizeNavigationOrigin(\n value: string | undefined,\n): string | undefined {\n if (!value) return undefined;\n try {\n const url = new URL(value);\n return url.protocol === \"http:\" || url.protocol === \"https:\"\n ? url.origin\n : undefined;\n } catch {\n return undefined;\n }\n}\n\nexport function resolveAllowedAnchorUrl(\n href: string | null,\n allowedAnchorUrls: ReadonlySet<string> | undefined,\n): string | undefined {\n if (!href || !allowedAnchorUrls) return undefined;\n\n let parsed: URL;\n try {\n parsed = new URL(href);\n } catch {\n return undefined;\n }\n if (parsed.protocol !== \"http:\" && parsed.protocol !== \"https:\") {\n return undefined;\n }\n return allowedAnchorUrls.has(parsed.href) ? parsed.href : undefined;\n}\n\nfunction enforceAllowedAnchorSafety(state: MountState): void {\n for (const anchor of state.shadowRoot.querySelectorAll<HTMLAnchorElement>(\n \"a[href]\",\n )) {\n if (\n !resolveAllowedAnchorUrl(\n anchor.getAttribute(\"href\"),\n state.options.allowedAnchorUrls,\n )\n ) {\n continue;\n }\n\n enforceAllowedAnchorSafetyAttributes(anchor);\n }\n}\n\nfunction enforceAllowedAnchorSafetyAttributes(anchor: HTMLAnchorElement): void {\n anchor.target = \"_blank\";\n const relTokens = new Set(anchor.rel.split(/\\s+/u).filter(Boolean));\n relTokens.add(\"noopener\");\n relTokens.add(\"noreferrer\");\n anchor.rel = Array.from(relTokens).join(\" \");\n anchor.removeAttribute(\"download\");\n}\n\nfunction resolveInternalNavigationUrl(\n href: string,\n navigationOrigin: string | undefined,\n): string | undefined {\n if (href.startsWith(\"#\")) return href;\n if (href.startsWith(\"//\") || /^https?:(?!\\/\\/)/iu.test(href)) {\n return undefined;\n }\n try {\n const url = new URL(href, navigationOrigin ?? \"https://fluid.local\");\n if (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n return undefined;\n }\n if (\n /^[a-z][a-z\\d+.-]*:/iu.test(href) &&\n (!navigationOrigin || url.origin !== navigationOrigin)\n ) {\n return undefined;\n }\n return `${url.pathname}${url.search}${url.hash}`;\n } catch {\n return undefined;\n }\n}\n\nfunction findNodeId(state: MountState, node: Node): string | undefined {\n for (const [id, candidate] of state.nodesById) {\n if (candidate === node) return id;\n }\n return undefined;\n}\n\nfunction isWidgetStyleNode(node: Node): boolean {\n return (\n node instanceof HTMLStyleElement &&\n node.hasAttribute(REMOTE_DOM_WIDGET_STYLE_ATTRIBUTE)\n );\n}\n\nfunction clearRenderedRemoteDomNodes(shadowRoot: ShadowRoot): void {\n for (const child of Array.from(shadowRoot.childNodes)) {\n if (!isWidgetStyleNode(child)) child.remove();\n }\n}\n\nfunction toSerializableEventPayload(\n payload: NonNullable<ReturnType<typeof serializeRemoteDomEvent>>,\n): RemoteDomSerializableValue {\n const result: Record<string, RemoteDomSerializableValue> = {\n bubbles: payload.bubbles,\n cancelable: payload.cancelable,\n currentTargetId: payload.currentTargetId,\n defaultPrevented: payload.defaultPrevented,\n targetId: payload.targetId,\n type: payload.type,\n };\n for (const key of [\n \"altKey\",\n \"button\",\n \"buttons\",\n \"checked\",\n \"clientX\",\n \"clientY\",\n \"code\",\n \"ctrlKey\",\n \"detailJson\",\n \"isPrimary\",\n \"key\",\n \"metaKey\",\n \"pointerId\",\n \"pointerType\",\n \"shiftKey\",\n \"value\",\n ] as const) {\n const value = payload[key];\n if (value !== undefined) result[key] = value;\n }\n return result;\n}\n\nfunction assertSerializable(\n value: unknown,\n description: string,\n): asserts value is RemoteDomSerializableValue {\n if (!isRemoteDomSerializableValue(value)) {\n throw new TypeError(`${description} must be serializable`);\n }\n}\n\nfunction createWorkerMessageTarget(\n worker: RemoteDomWorkerLike,\n): ThreadMessageTarget {\n return {\n send(message, transferables) {\n worker.postMessage(message, transferables ?? []);\n },\n listen(listener, { signal }) {\n const onMessage = (event: MessageEvent<unknown>): void => {\n listener(event.data);\n };\n if (worker.addEventListener) {\n worker.addEventListener(\"message\", onMessage, { signal });\n } else {\n worker.onmessage = onMessage;\n signal?.addEventListener(\n \"abort\",\n () => {\n worker.onmessage = null;\n },\n { once: true },\n );\n }\n },\n };\n}\n\nexport function createDefaultWorker(\n workerEntryUrl: string,\n options: WorkerOptions,\n): RemoteDomWorkerLike {\n if (typeof Worker === \"undefined\") {\n throw new Error(\"Remote DOM Worker is not available in this environment\");\n }\n if (!shouldWrapWorkerEntryUrl(workerEntryUrl)) {\n return new Worker(workerEntryUrl, options);\n }\n return createBlobWrappedWorker(workerEntryUrl, options);\n}\n\nfunction shouldWrapWorkerEntryUrl(workerEntryUrl: string): boolean {\n if (\n typeof location === \"undefined\" ||\n typeof Blob === \"undefined\" ||\n typeof URL.createObjectURL !== \"function\"\n ) {\n return false;\n }\n try {\n return new URL(workerEntryUrl, location.href).origin !== location.origin;\n } catch {\n return false;\n }\n}\n\nfunction createBlobWrappedWorker(\n workerEntryUrl: string,\n options: WorkerOptions,\n): RemoteDomWorkerLike {\n const blobUrl = URL.createObjectURL(\n new Blob([`import ${JSON.stringify(workerEntryUrl)};\\n`], {\n type: \"application/javascript\",\n }),\n );\n let worker: Worker;\n try {\n worker = new Worker(blobUrl, options);\n } catch (error) {\n URL.revokeObjectURL(blobUrl);\n throw error;\n }\n const terminate = worker.terminate.bind(worker);\n worker.terminate = (): void => {\n try {\n terminate();\n } finally {\n URL.revokeObjectURL(blobUrl);\n }\n };\n return worker;\n}\n\nfunction reportError(\n options: MountRemoteDomWidgetOptions,\n message: string,\n cause?: unknown,\n): void {\n try {\n options.onError?.(new Error(message, cause === undefined ? {} : { cause }));\n } catch {\n // A host error callback must not destabilize the widget lifecycle.\n }\n}\n\nfunction collectCleanupErrors(\n cleanupSteps: readonly (() => void)[],\n): unknown[] {\n const errors: unknown[] = [];\n for (const cleanup of cleanupSteps) {\n try {\n cleanup();\n } catch (error) {\n errors.push(error);\n }\n }\n return errors;\n}\n\nfunction reportCleanupErrors(\n options: MountRemoteDomWidgetOptions,\n message: string,\n errors: readonly unknown[],\n): void {\n if (errors.length === 0) return;\n reportError(\n options,\n message,\n errors.length === 1\n ? errors[0]\n : new AggregateError(errors, \"Multiple cleanup operations failed\"),\n );\n}\n\nfunction subscriptionKey(targetId: string, eventName: string): string {\n return `${targetId}:${eventName}`;\n}\n\nfunction isPromiseLike(value: unknown): value is Promise<unknown> {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"then\" in value &&\n typeof value.then === \"function\"\n );\n}\n"],"mappings":"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"}
@@ -422,7 +422,7 @@ function sanitizeRemoteDomAttribute(tagName, rawName, rawValue, options = {}) {
422
422
  } : void 0;
423
423
  }
424
424
  if (URL_VALUED_ATTRIBUTES.has(name)) {
425
- const value = sanitizeUrlValuedAttribute(normalizedTagName, name, rawValue, options.urlOriginPolicy);
425
+ const value = sanitizeUrlValuedAttribute(normalizedTagName, name, rawValue, options.allowedAnchorUrls, options.urlOriginPolicy);
426
426
  return value ? {
427
427
  name,
428
428
  value
@@ -476,7 +476,10 @@ function sanitizeRemoteDomUrl(value, options) {
476
476
  } catch {
477
477
  return;
478
478
  }
479
- if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") return isAllowedHttpOrigin(parsedUrl.origin, options.originPolicy, options.allowedHttpOriginGroups ?? []) ? trimmedValue : void 0;
479
+ if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") {
480
+ if (options.allowedHttpUrls?.has(parsedUrl.href)) return parsedUrl.href;
481
+ return isAllowedHttpOrigin(parsedUrl.origin, options.originPolicy, options.allowedHttpOriginGroups ?? []) ? trimmedValue : void 0;
482
+ }
480
483
  if (options.allowMailTo && parsedUrl.protocol === "mailto:") return trimmedValue;
481
484
  if (options.allowTel && parsedUrl.protocol === "tel:") return trimmedValue;
482
485
  }
@@ -527,17 +530,14 @@ function readCustomEventDetail(event) {
527
530
  return {};
528
531
  }
529
532
  }
530
- function sanitizeUrlValuedAttribute(tagName, name, value, originPolicy) {
531
- if (name === "href") return sanitizeRemoteDomUrl(value, {
533
+ function sanitizeUrlValuedAttribute(tagName, name, value, allowedAnchorUrls, originPolicy) {
534
+ if (name === "href" && tagName === "a") return sanitizeRemoteDomUrl(value, {
532
535
  allowHashOnly: true,
533
- allowMailTo: true,
536
+ allowMailTo: false,
534
537
  allowRelative: true,
535
- allowTel: true,
536
- allowedHttpOriginGroups: [
537
- "artifact",
538
- "media",
539
- "navigation"
540
- ],
538
+ allowTel: false,
539
+ allowedHttpOriginGroups: ["navigation"],
540
+ ...allowedAnchorUrls ? { allowedHttpUrls: allowedAnchorUrls } : {},
541
541
  originPolicy,
542
542
  relativeUrlBase: "navigation"
543
543
  });
@@ -654,9 +654,75 @@ function sanitizeCssComponentValueUrlReferences(cssValue, originPolicy) {
654
654
  const parsed = (0, postcss_value_parser.default)(cssValue);
655
655
  return sanitizeParsedCssValue(parsed.nodes, originPolicy) ? postcss_value_parser.default.stringify(parsed.nodes) : void 0;
656
656
  }
657
+ /** True when a word token ends in a hex escape that CSS would terminate
658
+ * with the following whitespace.
659
+ *
660
+ * CSS Syntax §4.3.7: a hex escape consumes one trailing whitespace
661
+ * character, so `\75 rl(…)` is a SINGLE function token named `url`.
662
+ * postcss-value-parser instead splits on that whitespace and hands us
663
+ * [word "\75", space, function "rl"] — a function whose name decodes
664
+ * to `rl`, which is in neither the url nor the rejected-function set,
665
+ * so the value sails past the origin policy and Chromium then fetches
666
+ * the attacker's URL. Same for `u\72 l(`, `ur\6c (`, `\69 mage-set(`
667
+ * and `image-se\74 (`, and for tab/newline/form-feed as the
668
+ * terminator.
669
+ *
670
+ * We cannot re-join the tokens without reimplementing the tokenizer,
671
+ * so we fail closed on the shape instead. Escapes inside strings are
672
+ * unaffected — those are `string` nodes, so `content: "\201C "` and
673
+ * friends still round-trip. */
674
+ function hasWhitespaceTerminatedEscape(node) {
675
+ return node.type === "word" && /\\[0-9a-fA-F]{1,6}$/.test(node.value);
676
+ }
677
+ /** True when `nodes[index]` is the first half of a function name that
678
+ * CSS will re-join across the whitespace the escape consumes.
679
+ *
680
+ * Narrower than "any word ending in an escape", deliberately. Only a
681
+ * FUNCTION can fetch anything, so the shape that matters is
682
+ * word-escape → single whitespace → function: `\75 rl(…)` re-joins to
683
+ * `url(…)`. Re-joining a word onto another WORD just yields an
684
+ * identifier, which is inert — and rejecting those took ordinary
685
+ * declarations like `color: \72 ed` down with them. Since one rejected
686
+ * declaration invalidates the entire source, that discarded whole
687
+ * stylesheets over a value that could never fetch.
688
+ *
689
+ * The whitespace run must be exactly ONE CSS whitespace: §4.3.7 has
690
+ * the escape consume one, so `\75 rl(` (two spaces) leaves a real
691
+ * separator behind and is two tokens, not a disguised function.
692
+ *
693
+ * Counted after normalizing newlines, not in raw code units. CSS
694
+ * preprocessing (§3.3) folds CRLF and a lone CR into a single LF
695
+ * BEFORE tokenizing, so `\75\r\nrl(` is one whitespace to the browser
696
+ * and resolves to `url(...)`. Measuring the raw string made that two
697
+ * characters, which skipped the rejection entirely and handed the
698
+ * attacker back the bypass. */
699
+ function startsDisguisedFunction(nodes, index) {
700
+ let name = "";
701
+ let i = index;
702
+ for (;;) {
703
+ const word = nodes[i];
704
+ if (!word || !hasWhitespaceTerminatedEscape(word)) return false;
705
+ const separator = nodes[i + 1];
706
+ if (separator?.type !== "space") return false;
707
+ if (separator.value.replace(/\r\n?|\f/g, "\n").length !== 1) return false;
708
+ const decodedWord = decodeCssEscapes(word.value);
709
+ if (decodedWord === void 0) return true;
710
+ name += decodedWord;
711
+ const next = nodes[i + 2];
712
+ if (next?.type === "function") {
713
+ const decodedSuffix = decodeCssEscapes(next.value);
714
+ if (decodedSuffix === void 0) return true;
715
+ const reconstructed = `${name}${decodedSuffix}`.toLowerCase();
716
+ return reconstructed === CSS_URL_FUNCTION_NAME || CSS_REJECTED_URL_FUNCTION_NAMES.has(reconstructed);
717
+ }
718
+ if (next?.type !== "word") return false;
719
+ i += 2;
720
+ }
721
+ }
657
722
  function sanitizeParsedCssValue(nodes, originPolicy) {
658
- for (const node of nodes) {
723
+ for (const [index, node] of nodes.entries()) {
659
724
  if ("unclosed" in node && node.unclosed === true) return false;
725
+ if (startsDisguisedFunction(nodes, index)) return false;
660
726
  if (node.type !== "function") continue;
661
727
  const decodedFunctionName = decodeCssEscapes(node.value);
662
728
  if (decodedFunctionName === void 0) return false;
@@ -976,7 +1042,10 @@ function normalizeUpdatePropertyRecordForHost(options, state, mutation, pendingE
976
1042
  message: `Remote DOM property "${property}" had an invalid value for "${node.localName}".`
977
1043
  };
978
1044
  }
979
- const [attribute] = sanitizeRemoteDomAttributes(node.localName, { [property]: value }, { urlOriginPolicy: options.urlOriginPolicy });
1045
+ const [attribute] = sanitizeRemoteDomAttributes(node.localName, { [property]: value }, {
1046
+ ...options.allowedAnchorUrls ? { allowedAnchorUrls: options.allowedAnchorUrls } : {},
1047
+ urlOriginPolicy: options.urlOriginPolicy
1048
+ });
980
1049
  if (attribute) return {
981
1050
  ok: true,
982
1051
  record: [
@@ -1068,7 +1137,10 @@ function normalizeRemoteNodeForHost(options, state, value, seen, pendingEventLis
1068
1137
  };
1069
1138
  }
1070
1139
  }
1071
- const attributes = sanitizeRemoteDomAttributes(tagName, attributeProperties, { urlOriginPolicy: options.urlOriginPolicy });
1140
+ const attributes = sanitizeRemoteDomAttributes(tagName, attributeProperties, {
1141
+ ...options.allowedAnchorUrls ? { allowedAnchorUrls: options.allowedAnchorUrls } : {},
1142
+ urlOriginPolicy: options.urlOriginPolicy
1143
+ });
1072
1144
  const remoteAttributes = {};
1073
1145
  for (const attribute of attributes) remoteAttributes[attribute.name] = attribute.value;
1074
1146
  if (tagName === "button" && remoteAttributes.type === void 0) remoteAttributes.type = "button";
@@ -1688,6 +1760,7 @@ function mountRemoteDomWidget(options) {
1688
1760
  throw new RemoteDomConnectionCallDeniedError("remote element method");
1689
1761
  }
1690
1762
  }).connection,
1763
+ ...options.allowedAnchorUrls ? { allowedAnchorUrls: options.allowedAnchorUrls } : {},
1691
1764
  urlOriginPolicy,
1692
1765
  maxMutationBatchSize: options.maxMutationBatchSize ?? DEFAULT_MAX_MUTATION_BATCH_SIZE,
1693
1766
  maxDomNodeCount: options.maxDomNodeCount ?? DEFAULT_MAX_DOM_NODE_COUNT,
@@ -1727,18 +1800,17 @@ function mountRemoteDomWidget(options) {
1727
1800
  shadowRoot.addEventListener("submit", submitListener, { capture: true });
1728
1801
  shadowRoot.addEventListener("click", navigationListener, { capture: true });
1729
1802
  worker.onerror = (event) => {
1803
+ event.preventDefault?.();
1730
1804
  if (state.disposed) return;
1731
1805
  reportError(options, event.message || "Remote DOM widget worker failed", event.error);
1732
1806
  disposeAfterFailure(state, false);
1733
1807
  };
1734
- const ready = Promise.all([styles.ready, thread.imports.mount({
1735
- widgetType: options.artifact.widgetType,
1736
- props: initialProps
1737
- }, {
1808
+ const hostApi = {
1738
1809
  mutate(records) {
1739
1810
  if (state.disposed) return;
1740
1811
  connection.mutate(records);
1741
1812
  rebuildNodeIndex(state);
1813
+ enforceAllowedAnchorSafety(state);
1742
1814
  flushPendingListenerUpdates(state);
1743
1815
  },
1744
1816
  callCapability(capability, method, payload) {
@@ -1747,7 +1819,15 @@ function mountRemoteDomWidget(options) {
1747
1819
  reportError(error) {
1748
1820
  reportError(options, error.message);
1749
1821
  }
1750
- })]).then(() => void 0);
1822
+ };
1823
+ const ready = Promise.all([styles.ready, thread.imports.mount({
1824
+ widgetType: options.artifact.widgetType,
1825
+ props: initialProps,
1826
+ ...options.artifact.networkAccessGranted === true ? {
1827
+ networkAccessGranted: true,
1828
+ hostOrigin: options.hostOrigin
1829
+ } : {}
1830
+ }, hostApi)]).then(() => void 0);
1751
1831
  ready.catch((error) => {
1752
1832
  if (state.disposed) return;
1753
1833
  reportError(options, "Remote DOM widget failed to mount", error);
@@ -1873,6 +1953,10 @@ function handleNavigationIntent(state, event) {
1873
1953
  const anchor = (event.target instanceof Element ? event.target : event.target instanceof Text ? event.target.parentElement : null)?.closest("a[href]");
1874
1954
  if (!(anchor instanceof HTMLAnchorElement)) return;
1875
1955
  if (!state.shadowRoot.contains(anchor)) return;
1956
+ if (resolveAllowedAnchorUrl(anchor.getAttribute("href"), state.options.allowedAnchorUrls)) {
1957
+ enforceAllowedAnchorSafetyAttributes(anchor);
1958
+ return;
1959
+ }
1876
1960
  if (event.cancelable) event.preventDefault();
1877
1961
  const href = sanitizeRemoteDomUrl(anchor.getAttribute("href"), {
1878
1962
  allowHashOnly: true,
@@ -1968,6 +2052,31 @@ function normalizeNavigationOrigin(value) {
1968
2052
  return;
1969
2053
  }
1970
2054
  }
2055
+ function resolveAllowedAnchorUrl(href, allowedAnchorUrls) {
2056
+ if (!href || !allowedAnchorUrls) return void 0;
2057
+ let parsed;
2058
+ try {
2059
+ parsed = new URL(href);
2060
+ } catch {
2061
+ return;
2062
+ }
2063
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return;
2064
+ return allowedAnchorUrls.has(parsed.href) ? parsed.href : void 0;
2065
+ }
2066
+ function enforceAllowedAnchorSafety(state) {
2067
+ for (const anchor of state.shadowRoot.querySelectorAll("a[href]")) {
2068
+ if (!resolveAllowedAnchorUrl(anchor.getAttribute("href"), state.options.allowedAnchorUrls)) continue;
2069
+ enforceAllowedAnchorSafetyAttributes(anchor);
2070
+ }
2071
+ }
2072
+ function enforceAllowedAnchorSafetyAttributes(anchor) {
2073
+ anchor.target = "_blank";
2074
+ const relTokens = new Set(anchor.rel.split(/\s+/u).filter(Boolean));
2075
+ relTokens.add("noopener");
2076
+ relTokens.add("noreferrer");
2077
+ anchor.rel = Array.from(relTokens).join(" ");
2078
+ anchor.removeAttribute("download");
2079
+ }
1971
2080
  function resolveInternalNavigationUrl(href, navigationOrigin) {
1972
2081
  if (href.startsWith("#")) return href;
1973
2082
  if (href.startsWith("//") || /^https?:(?!\/\/)/iu.test(href)) return;
@@ -2113,4 +2222,4 @@ Object.defineProperty(exports, "mountRemoteDomWidget", {
2113
2222
  }
2114
2223
  });
2115
2224
 
2116
- //# sourceMappingURL=remote-dom-renderer-DUQf80Nu.cjs.map
2225
+ //# sourceMappingURL=remote-dom-renderer-f7OWlvvv.cjs.map