@fluid-app/widget-runtime 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +77 -0
  2. package/dist/Thread-0eUyc0Hw.cjs +591 -0
  3. package/dist/Thread-0eUyc0Hw.cjs.map +1 -0
  4. package/dist/Thread-BiW7rXts.mjs +574 -0
  5. package/dist/Thread-BiW7rXts.mjs.map +1 -0
  6. package/dist/index.cjs +6 -0
  7. package/dist/index.d.cts +3 -0
  8. package/dist/index.d.mts +3 -0
  9. package/dist/index.mjs +3 -0
  10. package/dist/remote-dom-renderer-BU-73KvK.d.mts +90 -0
  11. package/dist/remote-dom-renderer-BU-73KvK.d.mts.map +1 -0
  12. package/dist/remote-dom-renderer-DSHFetvm.d.cts +90 -0
  13. package/dist/remote-dom-renderer-DSHFetvm.d.cts.map +1 -0
  14. package/dist/remote-dom-renderer-DUQf80Nu.cjs +2116 -0
  15. package/dist/remote-dom-renderer-DUQf80Nu.cjs.map +1 -0
  16. package/dist/remote-dom-renderer-DcwcNPsu.mjs +2081 -0
  17. package/dist/remote-dom-renderer-DcwcNPsu.mjs.map +1 -0
  18. package/dist/remote-dom-values-BSAxrOE7.mjs +238 -0
  19. package/dist/remote-dom-values-BSAxrOE7.mjs.map +1 -0
  20. package/dist/remote-dom-values-D4AgBNWr.d.cts +32 -0
  21. package/dist/remote-dom-values-D4AgBNWr.d.cts.map +1 -0
  22. package/dist/remote-dom-values-DbgIedSg.cjs +297 -0
  23. package/dist/remote-dom-values-DbgIedSg.cjs.map +1 -0
  24. package/dist/remote-dom-values-EwoLXnSn.d.mts +32 -0
  25. package/dist/remote-dom-values-EwoLXnSn.d.mts.map +1 -0
  26. package/dist/remote-dom.cjs +6 -0
  27. package/dist/remote-dom.d.cts +3 -0
  28. package/dist/remote-dom.d.mts +3 -0
  29. package/dist/remote-dom.mjs +3 -0
  30. package/dist/worker-react-bootstrap-C7tCMYGA.mjs +13 -0
  31. package/dist/worker-react-bootstrap-C7tCMYGA.mjs.map +1 -0
  32. package/dist/worker-react-bootstrap-N8jcWZ3L.cjs +13 -0
  33. package/dist/worker-react-bootstrap-N8jcWZ3L.cjs.map +1 -0
  34. package/dist/worker-react-renderer-BKzig_Vy.mjs +185 -0
  35. package/dist/worker-react-renderer-BKzig_Vy.mjs.map +1 -0
  36. package/dist/worker-react-renderer-BSFxMMf7.cjs +186 -0
  37. package/dist/worker-react-renderer-BSFxMMf7.cjs.map +1 -0
  38. package/dist/worker.cjs +325 -0
  39. package/dist/worker.cjs.map +1 -0
  40. package/dist/worker.d.cts +46 -0
  41. package/dist/worker.d.cts.map +1 -0
  42. package/dist/worker.d.mts +46 -0
  43. package/dist/worker.d.mts.map +1 -0
  44. package/dist/worker.mjs +319 -0
  45. package/dist/worker.mjs.map +1 -0
  46. package/package.json +68 -0
@@ -0,0 +1,2116 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __copyProps = (to, from, except, desc) => {
9
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
10
+ key = keys[i];
11
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
12
+ get: ((k) => from[k]).bind(null, key),
13
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
14
+ });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
19
+ value: mod,
20
+ enumerable: true
21
+ }) : target, mod));
22
+ //#endregion
23
+ const require_Thread = require("./Thread-0eUyc0Hw.cjs");
24
+ const require_remote_dom_values = require("./remote-dom-values-DbgIedSg.cjs");
25
+ let _remote_dom_core = require("@remote-dom/core");
26
+ let _remote_dom_core_elements = require("@remote-dom/core/elements");
27
+ let _remote_dom_core_receivers = require("@remote-dom/core/receivers");
28
+ let postcss_lib_parse = require("postcss/lib/parse");
29
+ postcss_lib_parse = __toESM(postcss_lib_parse);
30
+ let postcss_value_parser = require("postcss-value-parser");
31
+ postcss_value_parser = __toESM(postcss_value_parser);
32
+ //#region src/remote-dom-sanitizer.ts
33
+ const REMOTE_DOM_DENIED_TAG_NAMES = new Set([
34
+ "applet",
35
+ "base",
36
+ "body",
37
+ "embed",
38
+ "frame",
39
+ "frameset",
40
+ "head",
41
+ "html",
42
+ "iframe",
43
+ "link",
44
+ "meta",
45
+ "noscript",
46
+ "object",
47
+ "portal",
48
+ "script",
49
+ "slot",
50
+ "style",
51
+ "template",
52
+ "title"
53
+ ]);
54
+ const REMOTE_DOM_ALLOWED_TAG_NAME_SET = new Set(require_remote_dom_values.REMOTE_DOM_ALLOWED_TAG_NAMES);
55
+ const GLOBAL_ALLOWED_ATTRIBUTES = new Set([
56
+ "aria-activedescendant",
57
+ "aria-atomic",
58
+ "aria-autocomplete",
59
+ "aria-braillelabel",
60
+ "aria-brailleroledescription",
61
+ "aria-busy",
62
+ "aria-checked",
63
+ "aria-colcount",
64
+ "aria-colindex",
65
+ "aria-colindextext",
66
+ "aria-colspan",
67
+ "aria-controls",
68
+ "aria-current",
69
+ "aria-describedby",
70
+ "aria-description",
71
+ "aria-details",
72
+ "aria-disabled",
73
+ "aria-errormessage",
74
+ "aria-expanded",
75
+ "aria-haspopup",
76
+ "aria-hidden",
77
+ "aria-invalid",
78
+ "aria-keyshortcuts",
79
+ "aria-label",
80
+ "aria-labelledby",
81
+ "aria-level",
82
+ "aria-live",
83
+ "aria-modal",
84
+ "aria-multiline",
85
+ "aria-multiselectable",
86
+ "aria-orientation",
87
+ "aria-owns",
88
+ "aria-placeholder",
89
+ "aria-posinset",
90
+ "aria-pressed",
91
+ "aria-readonly",
92
+ "aria-required",
93
+ "aria-roledescription",
94
+ "aria-rowcount",
95
+ "aria-rowindex",
96
+ "aria-rowindextext",
97
+ "aria-rowspan",
98
+ "aria-selected",
99
+ "aria-setsize",
100
+ "aria-sort",
101
+ "aria-valuemax",
102
+ "aria-valuemin",
103
+ "aria-valuenow",
104
+ "aria-valuetext",
105
+ "class",
106
+ "dir",
107
+ "hidden",
108
+ "id",
109
+ "inert",
110
+ "lang",
111
+ "role",
112
+ "tabindex",
113
+ "title",
114
+ "translate"
115
+ ]);
116
+ const TAG_ALLOWED_ATTRIBUTES = {
117
+ a: new Set([
118
+ "download",
119
+ "href",
120
+ "hreflang",
121
+ "rel",
122
+ "target",
123
+ "type"
124
+ ]),
125
+ audio: new Set([
126
+ "autoplay",
127
+ "controls",
128
+ "loop",
129
+ "muted",
130
+ "preload",
131
+ "src"
132
+ ]),
133
+ blockquote: new Set(["cite"]),
134
+ button: new Set([
135
+ "disabled",
136
+ "name",
137
+ "type",
138
+ "value"
139
+ ]),
140
+ col: new Set(["span"]),
141
+ colgroup: new Set(["span"]),
142
+ data: new Set(["value"]),
143
+ del: new Set(["cite", "datetime"]),
144
+ details: new Set(["open"]),
145
+ dialog: new Set(["open"]),
146
+ form: new Set(["autocomplete", "name"]),
147
+ img: new Set([
148
+ "alt",
149
+ "decoding",
150
+ "height",
151
+ "loading",
152
+ "src",
153
+ "width"
154
+ ]),
155
+ input: new Set([
156
+ "accept",
157
+ "autocomplete",
158
+ "checked",
159
+ "disabled",
160
+ "max",
161
+ "maxlength",
162
+ "min",
163
+ "minlength",
164
+ "name",
165
+ "pattern",
166
+ "placeholder",
167
+ "readonly",
168
+ "required",
169
+ "step",
170
+ "type",
171
+ "value"
172
+ ]),
173
+ ins: new Set(["cite", "datetime"]),
174
+ label: new Set(["for"]),
175
+ meter: new Set([
176
+ "high",
177
+ "low",
178
+ "max",
179
+ "min",
180
+ "optimum",
181
+ "value"
182
+ ]),
183
+ optgroup: new Set(["disabled", "label"]),
184
+ option: new Set([
185
+ "disabled",
186
+ "label",
187
+ "selected",
188
+ "value"
189
+ ]),
190
+ output: new Set(["for", "name"]),
191
+ progress: new Set(["max", "value"]),
192
+ q: new Set(["cite"]),
193
+ select: new Set([
194
+ "autocomplete",
195
+ "disabled",
196
+ "multiple",
197
+ "name",
198
+ "required",
199
+ "size"
200
+ ]),
201
+ source: new Set([
202
+ "height",
203
+ "media",
204
+ "sizes",
205
+ "src",
206
+ "type",
207
+ "width"
208
+ ]),
209
+ td: new Set([
210
+ "colspan",
211
+ "headers",
212
+ "rowspan"
213
+ ]),
214
+ textarea: new Set([
215
+ "autocomplete",
216
+ "cols",
217
+ "disabled",
218
+ "maxlength",
219
+ "minlength",
220
+ "name",
221
+ "placeholder",
222
+ "readonly",
223
+ "required",
224
+ "rows",
225
+ "value",
226
+ "wrap"
227
+ ]),
228
+ th: new Set([
229
+ "abbr",
230
+ "colspan",
231
+ "headers",
232
+ "rowspan",
233
+ "scope"
234
+ ]),
235
+ time: new Set(["datetime"]),
236
+ track: new Set([
237
+ "default",
238
+ "kind",
239
+ "label",
240
+ "src",
241
+ "srclang"
242
+ ]),
243
+ video: new Set([
244
+ "autoplay",
245
+ "controls",
246
+ "height",
247
+ "loop",
248
+ "muted",
249
+ "playsinline",
250
+ "poster",
251
+ "preload",
252
+ "src",
253
+ "width"
254
+ ])
255
+ };
256
+ const BOOLEAN_ATTRIBUTES = new Set([
257
+ "autoplay",
258
+ "checked",
259
+ "controls",
260
+ "default",
261
+ "disabled",
262
+ "hidden",
263
+ "inert",
264
+ "loop",
265
+ "multiple",
266
+ "muted",
267
+ "open",
268
+ "playsinline",
269
+ "readonly",
270
+ "required",
271
+ "selected"
272
+ ]);
273
+ const SAFE_INPUT_TYPES = new Set([
274
+ "button",
275
+ "checkbox",
276
+ "color",
277
+ "date",
278
+ "datetime-local",
279
+ "email",
280
+ "file",
281
+ "hidden",
282
+ "month",
283
+ "number",
284
+ "password",
285
+ "radio",
286
+ "range",
287
+ "reset",
288
+ "search",
289
+ "submit",
290
+ "tel",
291
+ "text",
292
+ "time",
293
+ "url",
294
+ "week"
295
+ ]);
296
+ const SAFE_BUTTON_TYPES = new Set([
297
+ "button",
298
+ "reset",
299
+ "submit"
300
+ ]);
301
+ const SAFE_LOADING_VALUES = new Set(["eager", "lazy"]);
302
+ const SAFE_DECODING_VALUES = new Set([
303
+ "async",
304
+ "auto",
305
+ "sync"
306
+ ]);
307
+ const SAFE_PRELOAD_VALUES = new Set([
308
+ "auto",
309
+ "metadata",
310
+ "none"
311
+ ]);
312
+ const SAFE_TRACK_KIND_VALUES = new Set([
313
+ "captions",
314
+ "chapters",
315
+ "descriptions",
316
+ "metadata",
317
+ "subtitles"
318
+ ]);
319
+ const URL_VALUED_ATTRIBUTES = new Set([
320
+ "cite",
321
+ "href",
322
+ "poster",
323
+ "src"
324
+ ]);
325
+ const MEDIA_SOURCE_TAGS = new Set([
326
+ "audio",
327
+ "img",
328
+ "source",
329
+ "track",
330
+ "video"
331
+ ]);
332
+ const SUPPORTED_REMOTE_DOM_EVENT_SET = new Set(require_remote_dom_values.SUPPORTED_REMOTE_DOM_EVENTS);
333
+ const REMOTE_DOM_SEARCH_SORT_EVENT_SET = new Set(require_remote_dom_values.REMOTE_DOM_SEARCH_SORT_EVENTS);
334
+ function sanitizeRemoteDomTagName(tagName) {
335
+ if (typeof tagName !== "string") return void 0;
336
+ const normalizedTagName = tagName.trim().toLowerCase();
337
+ if (normalizedTagName.length === 0 || REMOTE_DOM_DENIED_TAG_NAMES.has(normalizedTagName) || !REMOTE_DOM_ALLOWED_TAG_NAME_SET.has(normalizedTagName)) return;
338
+ return normalizedTagName;
339
+ }
340
+ function sanitizeRemoteDomAttributes(tagName, attributes, options = {}) {
341
+ if (!isObjectRecord$1(attributes)) return [];
342
+ const sanitizedAttributes = [];
343
+ for (const [rawName, rawValue] of Object.entries(attributes)) {
344
+ const attribute = sanitizeRemoteDomAttribute(tagName, rawName, rawValue, options);
345
+ if (attribute) sanitizedAttributes.push(attribute);
346
+ }
347
+ return sanitizedAttributes;
348
+ }
349
+ function sanitizeRemoteDomProperty(tagName, rawName, rawValue) {
350
+ if (typeof rawName !== "string") return void 0;
351
+ const normalizedTagName = tagName.trim().toLowerCase();
352
+ const name = rawName.trim().toLowerCase();
353
+ if (!require_remote_dom_values.isSafeRemoteDomPropertyKey(name)) return;
354
+ if (normalizedTagName === "input") {
355
+ if (name === "checked" && typeof rawValue === "boolean") return {
356
+ name,
357
+ value: rawValue
358
+ };
359
+ if (name === "value" && typeof rawValue === "string") return {
360
+ name,
361
+ value: rawValue
362
+ };
363
+ }
364
+ if (normalizedTagName === "fluid-ui-search-sort") {
365
+ if (name === "searchvalue" && typeof rawValue === "string") return {
366
+ name: "searchValue",
367
+ value: rawValue
368
+ };
369
+ if (name === "placeholder") return typeof rawValue === "string" || rawValue === void 0 ? {
370
+ name: "placeholder",
371
+ value: rawValue
372
+ } : void 0;
373
+ if (name === "sortoptions") {
374
+ const value = sanitizeSearchSortOptions(rawValue);
375
+ return value === void 0 && rawValue !== void 0 ? void 0 : {
376
+ name: "sortOptions",
377
+ value
378
+ };
379
+ }
380
+ if (name === "sortvalue") return typeof rawValue === "string" || rawValue === void 0 ? {
381
+ name: "sortValue",
382
+ value: rawValue
383
+ } : void 0;
384
+ }
385
+ if (normalizedTagName === "fluid-spacer-widget") {
386
+ if (name === "customheight") return typeof rawValue === "string" || rawValue === void 0 ? {
387
+ name: "customHeight",
388
+ value: rawValue
389
+ } : void 0;
390
+ if (name === "previewmode" && typeof rawValue === "boolean") return {
391
+ name: "previewMode",
392
+ value: rawValue
393
+ };
394
+ }
395
+ }
396
+ function isRemoteDomPropertyName(tagName, rawName) {
397
+ const normalizedTagName = tagName.trim().toLowerCase();
398
+ const name = rawName.trim().toLowerCase();
399
+ if (normalizedTagName === "input") return name === "checked" || name === "value";
400
+ if (normalizedTagName === "fluid-ui-search-sort") return name === "searchvalue" || name === "placeholder" || name === "sortoptions" || name === "sortvalue";
401
+ if (normalizedTagName === "fluid-spacer-widget") return name === "customheight" || name === "previewmode";
402
+ return false;
403
+ }
404
+ function sanitizeRemoteDomAttribute(tagName, rawName, rawValue, options = {}) {
405
+ if (typeof rawName !== "string") return void 0;
406
+ const normalizedTagName = tagName.trim().toLowerCase();
407
+ const name = rawName.trim().toLowerCase();
408
+ if (!require_remote_dom_values.isSafeRemoteDomPropertyKey(name)) return void 0;
409
+ if (!isAllowedAttributeName(normalizedTagName, name)) return void 0;
410
+ if (name === "type" && normalizedTagName === "input") {
411
+ const value = stringifyAttributeValue(rawValue).toLowerCase();
412
+ return SAFE_INPUT_TYPES.has(value) ? {
413
+ name,
414
+ value
415
+ } : void 0;
416
+ }
417
+ if (name === "type" && normalizedTagName === "button") {
418
+ const value = stringifyAttributeValue(rawValue).toLowerCase();
419
+ return SAFE_BUTTON_TYPES.has(value) ? {
420
+ name,
421
+ value
422
+ } : void 0;
423
+ }
424
+ if (URL_VALUED_ATTRIBUTES.has(name)) {
425
+ const value = sanitizeUrlValuedAttribute(normalizedTagName, name, rawValue, options.urlOriginPolicy);
426
+ return value ? {
427
+ name,
428
+ value
429
+ } : void 0;
430
+ }
431
+ if (name === "target") {
432
+ const value = stringifyAttributeValue(rawValue);
433
+ return value === "_blank" || value === "_self" ? {
434
+ name,
435
+ value
436
+ } : void 0;
437
+ }
438
+ if (name === "rel") {
439
+ const value = sanitizeTokenList(rawValue);
440
+ return value.length > 0 ? {
441
+ name,
442
+ value
443
+ } : void 0;
444
+ }
445
+ if (name === "loading") return sanitizeEnumAttribute(name, rawValue, SAFE_LOADING_VALUES);
446
+ if (name === "decoding") return sanitizeEnumAttribute(name, rawValue, SAFE_DECODING_VALUES);
447
+ if (name === "preload") return sanitizeEnumAttribute(name, rawValue, SAFE_PRELOAD_VALUES);
448
+ if (name === "kind" && normalizedTagName === "track") return sanitizeEnumAttribute(name, rawValue, SAFE_TRACK_KIND_VALUES);
449
+ if (BOOLEAN_ATTRIBUTES.has(name)) return rawValue === true || rawValue === "" || rawValue === name ? {
450
+ name,
451
+ value: ""
452
+ } : void 0;
453
+ const value = stringifyAttributeValue(rawValue);
454
+ if (value.length === 0 && rawValue !== "") return void 0;
455
+ const sanitizedValue = sanitizeCssComponentValueUrlReferences(value, options.urlOriginPolicy);
456
+ if (sanitizedValue === void 0) return;
457
+ return {
458
+ name,
459
+ value: sanitizedValue
460
+ };
461
+ }
462
+ function sanitizeRemoteDomUrl(value, options) {
463
+ if (typeof value !== "string") return void 0;
464
+ const trimmedValue = value.trim();
465
+ if (trimmedValue.length === 0 || trimmedValue !== value || hasControlCharacter(trimmedValue) || trimmedValue.includes("\\") || trimmedValue.startsWith("//")) return;
466
+ if (trimmedValue.startsWith("#")) return options.allowHashOnly === true ? trimmedValue : void 0;
467
+ if (isRelativeUrl(trimmedValue)) {
468
+ if (!options.allowRelative) return void 0;
469
+ const parsedRelativeUrl = resolveRemoteDomRelativeUrl(trimmedValue, options.originPolicy, options.relativeUrlBase ?? "artifact");
470
+ if (!parsedRelativeUrl) return void 0;
471
+ return isAllowedHttpOrigin(parsedRelativeUrl.origin, options.originPolicy, options.allowedHttpOriginGroups ?? []) ? parsedRelativeUrl.href : void 0;
472
+ }
473
+ let parsedUrl;
474
+ try {
475
+ parsedUrl = new URL(trimmedValue);
476
+ } catch {
477
+ return;
478
+ }
479
+ if (parsedUrl.protocol === "http:" || parsedUrl.protocol === "https:") return isAllowedHttpOrigin(parsedUrl.origin, options.originPolicy, options.allowedHttpOriginGroups ?? []) ? trimmedValue : void 0;
480
+ if (options.allowMailTo && parsedUrl.protocol === "mailto:") return trimmedValue;
481
+ if (options.allowTel && parsedUrl.protocol === "tel:") return trimmedValue;
482
+ }
483
+ function sanitizeRemoteDomCssUrlReferences(value, options = {}) {
484
+ if (typeof value !== "string") return void 0;
485
+ return sanitizeCssTextUrlReferences(value, options.urlOriginPolicy);
486
+ }
487
+ function isSupportedRemoteDomEventName(eventName, tagName) {
488
+ if (SUPPORTED_REMOTE_DOM_EVENT_SET.has(eventName)) return true;
489
+ return tagName?.trim().toLowerCase() === "fluid-ui-search-sort" && REMOTE_DOM_SEARCH_SORT_EVENT_SET.has(eventName);
490
+ }
491
+ function serializeRemoteDomEvent(event, targetId, currentTargetId, currentTargetTagName) {
492
+ if (!isSupportedRemoteDomEventName(event.type, currentTargetTagName)) return;
493
+ const inputState = readInputState(event.target);
494
+ return {
495
+ type: event.type,
496
+ targetId,
497
+ currentTargetId,
498
+ bubbles: event.bubbles,
499
+ cancelable: event.cancelable,
500
+ defaultPrevented: event.defaultPrevented,
501
+ ...inputState,
502
+ ...readKeyboardState(event),
503
+ ...readPointerState(event),
504
+ ...readMouseState(event),
505
+ ...readCustomEventDetail(event)
506
+ };
507
+ }
508
+ function sanitizeSearchSortOptions(value) {
509
+ if (!Array.isArray(value)) return void 0;
510
+ const options = [];
511
+ for (const option of value) {
512
+ if (!isObjectRecord$1(option) || typeof option.label !== "string" || typeof option.value !== "string") return;
513
+ options.push({
514
+ label: option.label,
515
+ value: option.value
516
+ });
517
+ }
518
+ return options;
519
+ }
520
+ function readCustomEventDetail(event) {
521
+ if (!(event instanceof CustomEvent) || !REMOTE_DOM_SEARCH_SORT_EVENT_SET.has(event.type)) return {};
522
+ if (!require_remote_dom_values.isRemoteDomSerializableValue(event.detail)) return {};
523
+ try {
524
+ const detailJson = JSON.stringify(event.detail);
525
+ return typeof detailJson === "string" ? { detailJson } : {};
526
+ } catch {
527
+ return {};
528
+ }
529
+ }
530
+ function sanitizeUrlValuedAttribute(tagName, name, value, originPolicy) {
531
+ if (name === "href") return sanitizeRemoteDomUrl(value, {
532
+ allowHashOnly: true,
533
+ allowMailTo: true,
534
+ allowRelative: true,
535
+ allowTel: true,
536
+ allowedHttpOriginGroups: [
537
+ "artifact",
538
+ "media",
539
+ "navigation"
540
+ ],
541
+ originPolicy,
542
+ relativeUrlBase: "navigation"
543
+ });
544
+ if (name === "src" && MEDIA_SOURCE_TAGS.has(tagName)) return sanitizeRemoteDomUrl(value, {
545
+ allowHashOnly: false,
546
+ allowMailTo: false,
547
+ allowRelative: true,
548
+ allowTel: false,
549
+ allowedHttpOriginGroups: ["artifact", "media"],
550
+ originPolicy,
551
+ relativeUrlBase: "artifact"
552
+ });
553
+ if (name === "poster" && tagName === "video") return sanitizeRemoteDomUrl(value, {
554
+ allowHashOnly: false,
555
+ allowMailTo: false,
556
+ allowRelative: true,
557
+ allowTel: false,
558
+ allowedHttpOriginGroups: ["artifact", "media"],
559
+ originPolicy,
560
+ relativeUrlBase: "artifact"
561
+ });
562
+ return sanitizeRemoteDomUrl(value, {
563
+ allowHashOnly: false,
564
+ allowMailTo: false,
565
+ allowRelative: true,
566
+ allowTel: false,
567
+ allowedHttpOriginGroups: ["artifact", "media"],
568
+ originPolicy,
569
+ relativeUrlBase: "artifact"
570
+ });
571
+ }
572
+ function sanitizeEnumAttribute(name, rawValue, safeValues) {
573
+ const value = stringifyAttributeValue(rawValue).toLowerCase();
574
+ return safeValues.has(value) ? {
575
+ name,
576
+ value
577
+ } : void 0;
578
+ }
579
+ function hasControlCharacter(value) {
580
+ for (let index = 0; index < value.length; index += 1) {
581
+ const codePoint = value.charCodeAt(index);
582
+ if (codePoint < 32 || codePoint >= 127 && codePoint <= 159) return true;
583
+ }
584
+ return false;
585
+ }
586
+ function isAllowedAttributeName(tagName, name) {
587
+ if (name.length === 0 || name.startsWith("on") || name === "style" || name === "srcdoc" || name.includes(":") || !/^[a-z][a-z0-9_.-]*$/u.test(name)) return false;
588
+ if (name.startsWith("data-")) return true;
589
+ if (GLOBAL_ALLOWED_ATTRIBUTES.has(name)) return true;
590
+ return TAG_ALLOWED_ATTRIBUTES[tagName]?.has(name) === true;
591
+ }
592
+ function stringifyAttributeValue(value) {
593
+ if (typeof value === "string") return value;
594
+ if (typeof value === "number" || typeof value === "boolean") return String(value);
595
+ return "";
596
+ }
597
+ function sanitizeTokenList(value) {
598
+ return stringifyAttributeValue(value).split(/\s+/u).filter((token) => /^[a-z0-9_-]+$/iu.test(token)).join(" ");
599
+ }
600
+ function escapeCssString(value) {
601
+ return value.replace(/\\/gu, "\\\\").replace(/"/gu, "\\\"");
602
+ }
603
+ const CSS_URL_FUNCTION_NAME = "url";
604
+ const CSS_IMPORT_RULE_NAME = "import";
605
+ const CSS_REJECTED_URL_FUNCTION_NAMES = new Set(["image-set", "-webkit-image-set"]);
606
+ function sanitizeCssTextUrlReferences(cssText, originPolicy) {
607
+ let stylesheet;
608
+ try {
609
+ stylesheet = (0, postcss_lib_parse.default)(cssText);
610
+ } catch {
611
+ return;
612
+ }
613
+ let valid = true;
614
+ stylesheet.walkAtRules((atRule) => {
615
+ if (!valid) return;
616
+ const decodedName = decodeCssEscapes(atRule.name)?.toLowerCase();
617
+ if (!decodedName) {
618
+ valid = false;
619
+ return;
620
+ }
621
+ const sanitizedParams = decodedName === CSS_IMPORT_RULE_NAME ? sanitizeCssImportParameters(atRule.params, originPolicy) : sanitizeCssComponentValueUrlReferences(atRule.params, originPolicy);
622
+ if (sanitizedParams === void 0) {
623
+ valid = false;
624
+ return;
625
+ }
626
+ if (decodedName === CSS_IMPORT_RULE_NAME) atRule.name = decodedName;
627
+ atRule.params = sanitizedParams;
628
+ });
629
+ stylesheet.walkDecls((declaration) => {
630
+ if (!valid) return;
631
+ const sanitizedValue = sanitizeCssComponentValueUrlReferences(declaration.value, originPolicy);
632
+ if (sanitizedValue === void 0) {
633
+ valid = false;
634
+ return;
635
+ }
636
+ declaration.value = sanitizedValue;
637
+ });
638
+ return valid ? stylesheet.toString() : void 0;
639
+ }
640
+ function sanitizeCssImportParameters(params, originPolicy) {
641
+ const parsed = (0, postcss_value_parser.default)(params);
642
+ const firstToken = parsed.nodes.find((node) => node.type !== "space" && node.type !== "comment");
643
+ if (!firstToken) return void 0;
644
+ if (firstToken.type === "string") {
645
+ const decodedUrl = decodeCssEscapes(firstToken.value);
646
+ const sanitizedUrl = decodedUrl === void 0 ? void 0 : sanitizeCssUrlToken(decodedUrl, originPolicy);
647
+ if (!sanitizedUrl) return void 0;
648
+ firstToken.quote = "\"";
649
+ firstToken.value = escapeCssString(sanitizedUrl);
650
+ } else if (firstToken.type !== "function" || decodeCssEscapes(firstToken.value)?.toLowerCase() !== CSS_URL_FUNCTION_NAME) return;
651
+ return sanitizeParsedCssValue(parsed.nodes, originPolicy) ? postcss_value_parser.default.stringify(parsed.nodes) : void 0;
652
+ }
653
+ function sanitizeCssComponentValueUrlReferences(cssValue, originPolicy) {
654
+ const parsed = (0, postcss_value_parser.default)(cssValue);
655
+ return sanitizeParsedCssValue(parsed.nodes, originPolicy) ? postcss_value_parser.default.stringify(parsed.nodes) : void 0;
656
+ }
657
+ function sanitizeParsedCssValue(nodes, originPolicy) {
658
+ for (const node of nodes) {
659
+ if ("unclosed" in node && node.unclosed === true) return false;
660
+ if (node.type !== "function") continue;
661
+ const decodedFunctionName = decodeCssEscapes(node.value);
662
+ if (decodedFunctionName === void 0) return false;
663
+ const functionName = decodedFunctionName.toLowerCase();
664
+ if (CSS_REJECTED_URL_FUNCTION_NAMES.has(functionName)) return false;
665
+ if (functionName === CSS_URL_FUNCTION_NAME) {
666
+ if (!sanitizeCssUrlFunctionNode(node, originPolicy)) return false;
667
+ continue;
668
+ }
669
+ if (!sanitizeParsedCssValue(node.nodes, originPolicy)) return false;
670
+ }
671
+ return true;
672
+ }
673
+ function sanitizeCssUrlFunctionNode(node, originPolicy) {
674
+ const tokens = node.nodes.filter((child) => child.type !== "space" && child.type !== "comment");
675
+ if (tokens.length !== 1) return false;
676
+ const token = tokens[0];
677
+ if (!token || token.type !== "word" && token.type !== "string") return false;
678
+ if ("unclosed" in token && token.unclosed === true) return false;
679
+ const decodedUrl = decodeCssEscapes(token.value);
680
+ const sanitizedUrl = decodedUrl === void 0 ? void 0 : sanitizeCssUrlToken(decodedUrl, originPolicy);
681
+ if (!sanitizedUrl) return false;
682
+ node.value = CSS_URL_FUNCTION_NAME;
683
+ node.before = "";
684
+ node.after = "";
685
+ node.nodes = [{
686
+ type: "string",
687
+ quote: "\"",
688
+ value: escapeCssString(sanitizedUrl),
689
+ sourceIndex: token.sourceIndex,
690
+ sourceEndIndex: token.sourceEndIndex
691
+ }];
692
+ return true;
693
+ }
694
+ /** Decodes CSS escapes after the maintained parser has identified a token. */
695
+ function decodeCssEscapes(value) {
696
+ let decoded = "";
697
+ for (let index = 0; index < value.length; index += 1) {
698
+ const codeUnit = value[index];
699
+ if (codeUnit !== "\\") {
700
+ decoded += codeUnit;
701
+ continue;
702
+ }
703
+ index += 1;
704
+ const escaped = value[index];
705
+ if (escaped === void 0 || escaped === "\n" || escaped === "\r" || escaped === "\f") return;
706
+ if (!/^[0-9a-f]$/iu.test(escaped)) {
707
+ decoded += escaped;
708
+ continue;
709
+ }
710
+ const hexStart = index;
711
+ while (index + 1 < value.length && index + 1 - hexStart < 6 && /^[0-9a-f]$/iu.test(value[index + 1] ?? "")) index += 1;
712
+ const codePoint = Number.parseInt(value.slice(hexStart, index + 1), 16);
713
+ decoded += codePoint === 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343 ? "�" : String.fromCodePoint(codePoint);
714
+ if (/^[ \n\r\t\f]$/u.test(value[index + 1] ?? "")) index += 1;
715
+ }
716
+ return decoded;
717
+ }
718
+ function sanitizeCssUrlToken(rawUrl, originPolicy) {
719
+ return sanitizeRemoteDomUrl(rawUrl.trim().replace(/^(["'])(.*)\1$/u, "$2"), {
720
+ allowHashOnly: false,
721
+ allowMailTo: false,
722
+ allowRelative: true,
723
+ allowTel: false,
724
+ allowedHttpOriginGroups: ["artifact", "media"],
725
+ originPolicy,
726
+ relativeUrlBase: "artifact"
727
+ });
728
+ }
729
+ function resolveRemoteDomRelativeUrl(value, originPolicy, base) {
730
+ const baseUrl = base === "navigation" ? originPolicy?.navigationOrigin : originPolicy?.artifactBaseUrl;
731
+ if (!baseUrl) return void 0;
732
+ try {
733
+ const resolvedUrl = new URL(value, baseUrl);
734
+ return resolvedUrl.protocol === "http:" || resolvedUrl.protocol === "https:" ? resolvedUrl : void 0;
735
+ } catch {
736
+ return;
737
+ }
738
+ }
739
+ function isAllowedHttpOrigin(origin, originPolicy, allowedGroups) {
740
+ if (allowedGroups.length === 0 || !originPolicy) return false;
741
+ for (const group of allowedGroups) {
742
+ if (group === "artifact" && originPolicy.artifactOrigins.includes(origin)) return true;
743
+ if (group === "media" && originPolicy.mediaOrigins.includes(origin)) return true;
744
+ if (group === "navigation" && originPolicy.navigationOrigin === origin) return true;
745
+ }
746
+ return false;
747
+ }
748
+ function isRelativeUrl(value) {
749
+ return !/^[a-z][a-z0-9+.-]*:/iu.test(value);
750
+ }
751
+ function readInputState(target) {
752
+ if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement || target instanceof HTMLSelectElement) {
753
+ const inputState = { value: target.value };
754
+ if (target instanceof HTMLInputElement) inputState.checked = target.checked;
755
+ return inputState;
756
+ }
757
+ return {};
758
+ }
759
+ function readKeyboardState(event) {
760
+ if (!(event instanceof KeyboardEvent)) return {};
761
+ return {
762
+ altKey: event.altKey,
763
+ code: event.code,
764
+ ctrlKey: event.ctrlKey,
765
+ key: event.key,
766
+ metaKey: event.metaKey,
767
+ shiftKey: event.shiftKey
768
+ };
769
+ }
770
+ function readMouseState(event) {
771
+ if (!(event instanceof MouseEvent)) return {};
772
+ return {
773
+ altKey: event.altKey,
774
+ button: event.button,
775
+ buttons: event.buttons,
776
+ clientX: event.clientX,
777
+ clientY: event.clientY,
778
+ ctrlKey: event.ctrlKey,
779
+ metaKey: event.metaKey,
780
+ shiftKey: event.shiftKey
781
+ };
782
+ }
783
+ function readPointerState(event) {
784
+ if (!isObjectRecord$1(event) || typeof PointerEvent === "undefined") return {};
785
+ if (!(event instanceof PointerEvent)) return {};
786
+ return {
787
+ isPrimary: event.isPrimary,
788
+ pointerId: event.pointerId,
789
+ pointerType: event.pointerType
790
+ };
791
+ }
792
+ function isObjectRecord$1(value) {
793
+ return typeof value === "object" && value !== null;
794
+ }
795
+ //#endregion
796
+ //#region src/remote-dom-sanitizing-connection.ts
797
+ var RemoteDomConnectionCallDeniedError = class extends Error {
798
+ constructor(method) {
799
+ super(`Remote DOM element method "${method}" was blocked; host method calls are denied.`);
800
+ this.name = "RemoteDomConnectionCallDeniedError";
801
+ }
802
+ };
803
+ function createSanitizingRemoteConnection(options) {
804
+ const state = { nodes: new Map([[_remote_dom_core.ROOT_ID, {
805
+ kind: "element",
806
+ localName: "",
807
+ childIds: []
808
+ }]]) };
809
+ function reset() {
810
+ state.nodes.clear();
811
+ state.nodes.set(_remote_dom_core.ROOT_ID, {
812
+ kind: "element",
813
+ localName: "",
814
+ childIds: []
815
+ });
816
+ }
817
+ function mutate(records) {
818
+ if (records.length > options.maxMutationBatchSize) {
819
+ options.onInvalidRecord?.("Remote DOM mutation batch exceeded maxMutationBatchSize");
820
+ return;
821
+ }
822
+ const normalizedRecords = [];
823
+ const pendingEventListenerUpdates = [];
824
+ const workingState = cloneSanitizingState(state);
825
+ for (const rawRecord of records) {
826
+ const record = parseRemoteMutationRecord(rawRecord);
827
+ if (!record) {
828
+ options.onInvalidRecord?.("Remote DOM worker sent an invalid upstream mutation record");
829
+ return;
830
+ }
831
+ const normalized = normalizeMutationRecordForHost(options, workingState, record, pendingEventListenerUpdates);
832
+ if (!normalized.ok) {
833
+ if (normalized.message === NODE_LIMIT_MESSAGE) options.onNodeLimitExceeded?.();
834
+ else options.onInvalidRecord?.(normalized.message);
835
+ return;
836
+ }
837
+ if (normalized.record) normalizedRecords.push(normalized.record);
838
+ }
839
+ try {
840
+ if (normalizedRecords.length > 0) options.connection.mutate(normalizedRecords);
841
+ } catch (error) {
842
+ options.onMutateError?.(error);
843
+ return;
844
+ }
845
+ commitSanitizingState(state, workingState);
846
+ for (const update of pendingEventListenerUpdates) options.onEventListenerUpdate?.(update.targetId, update.eventName, update.listener);
847
+ }
848
+ return {
849
+ mutate,
850
+ call(_id, method) {
851
+ throw new RemoteDomConnectionCallDeniedError(method);
852
+ },
853
+ reset
854
+ };
855
+ }
856
+ function cloneSanitizingState(state) {
857
+ const nodes = /* @__PURE__ */ new Map();
858
+ for (const [id, node] of state.nodes) nodes.set(id, node.kind === "element" ? {
859
+ ...node,
860
+ childIds: [...node.childIds]
861
+ } : { kind: "text" });
862
+ return { nodes };
863
+ }
864
+ function commitSanitizingState(state, workingState) {
865
+ state.nodes.clear();
866
+ for (const [id, node] of workingState.nodes) state.nodes.set(id, node);
867
+ }
868
+ const NODE_LIMIT_MESSAGE = "Remote DOM mutation exceeded node limit.";
869
+ function normalizeMutationRecordForHost(options, state, mutation, pendingEventListenerUpdates) {
870
+ switch (mutation[0]) {
871
+ case _remote_dom_core.MUTATION_TYPE_INSERT_CHILD: {
872
+ const [, parentId, child, index] = mutation;
873
+ const parent = state.nodes.get(parentId);
874
+ if (!parent || parent.kind !== "element") return {
875
+ ok: false,
876
+ message: `Remote DOM mutation referenced missing insertChild parent node "${parentId}".`
877
+ };
878
+ if (!Number.isInteger(index) || index < 0 || index > parent.childIds.length) return {
879
+ ok: false,
880
+ message: "Remote DOM insertChild index was invalid."
881
+ };
882
+ const normalized = normalizeRemoteNodeForHost(options, state, child, new Set(state.nodes.keys()), pendingEventListenerUpdates);
883
+ if (!normalized.ok) return normalized;
884
+ if (Math.max(0, state.nodes.size - 1) + normalized.nodeCount > options.maxDomNodeCount) return {
885
+ ok: false,
886
+ message: NODE_LIMIT_MESSAGE
887
+ };
888
+ registerSimulatedRemoteNode(state, normalized.node);
889
+ parent.childIds.splice(index, 0, normalized.node.id);
890
+ return {
891
+ ok: true,
892
+ record: [
893
+ _remote_dom_core.MUTATION_TYPE_INSERT_CHILD,
894
+ parentId,
895
+ normalized.node,
896
+ index
897
+ ]
898
+ };
899
+ }
900
+ case _remote_dom_core.MUTATION_TYPE_REMOVE_CHILD: {
901
+ const [, parentId, index] = mutation;
902
+ const parent = state.nodes.get(parentId);
903
+ if (!parent || parent.kind !== "element") return {
904
+ ok: false,
905
+ message: `Remote DOM mutation referenced missing removeChild parent node "${parentId}".`
906
+ };
907
+ if (!Number.isInteger(index) || index < 0 || index >= parent.childIds.length) return {
908
+ ok: false,
909
+ message: "Remote DOM removeChild index was invalid."
910
+ };
911
+ const [removedId] = parent.childIds.splice(index, 1);
912
+ if (!removedId) return {
913
+ ok: false,
914
+ message: "Remote DOM removeChild index was invalid."
915
+ };
916
+ removeSimulatedRemoteNode(state, removedId);
917
+ return {
918
+ ok: true,
919
+ record: mutation
920
+ };
921
+ }
922
+ case _remote_dom_core.MUTATION_TYPE_UPDATE_TEXT: {
923
+ const [, id] = mutation;
924
+ const target = state.nodes.get(id);
925
+ if (!target || target.kind !== "text") return {
926
+ ok: false,
927
+ message: `Remote DOM mutation referenced missing updateText target node "${id}".`
928
+ };
929
+ return {
930
+ ok: true,
931
+ record: mutation
932
+ };
933
+ }
934
+ case _remote_dom_core.MUTATION_TYPE_UPDATE_PROPERTY: return normalizeUpdatePropertyRecordForHost(options, state, mutation, pendingEventListenerUpdates);
935
+ }
936
+ }
937
+ function normalizeUpdatePropertyRecordForHost(options, state, mutation, pendingEventListenerUpdates) {
938
+ const [, id, property, value, updateType] = mutation;
939
+ if (!require_remote_dom_values.isSafeRemoteDomPropertyKey(property)) return {
940
+ ok: false,
941
+ message: `Remote DOM mutation used an unsafe property key "${property}".`
942
+ };
943
+ const node = state.nodes.get(id);
944
+ if (!node || node.kind !== "element") return {
945
+ ok: false,
946
+ message: `Remote DOM mutation referenced missing updateProperty target node "${id}".`
947
+ };
948
+ if (updateType === _remote_dom_core.UPDATE_PROPERTY_TYPE_EVENT_LISTENER) {
949
+ if (!isSupportedRemoteDomEventName(property, node.localName)) return { ok: true };
950
+ const listener = typeof value === "function" ? value : null;
951
+ pendingEventListenerUpdates.push({
952
+ targetId: id,
953
+ eventName: property,
954
+ listener
955
+ });
956
+ return { ok: true };
957
+ }
958
+ if (value !== void 0 && !require_remote_dom_values.isRemoteDomSerializableValue(value)) return {
959
+ ok: false,
960
+ message: `Remote DOM mutation property "${property}" was not serializable.`
961
+ };
962
+ if (updateType === _remote_dom_core.UPDATE_PROPERTY_TYPE_PROPERTY) {
963
+ const sanitizedProperty = sanitizeRemoteDomProperty(node.localName, property, value);
964
+ if (sanitizedProperty) return {
965
+ ok: true,
966
+ record: [
967
+ _remote_dom_core.MUTATION_TYPE_UPDATE_PROPERTY,
968
+ id,
969
+ sanitizedProperty.name,
970
+ sanitizedProperty.value,
971
+ _remote_dom_core.UPDATE_PROPERTY_TYPE_PROPERTY
972
+ ]
973
+ };
974
+ if (isRemoteDomPropertyName(node.localName, property)) return {
975
+ ok: false,
976
+ message: `Remote DOM property "${property}" had an invalid value for "${node.localName}".`
977
+ };
978
+ }
979
+ const [attribute] = sanitizeRemoteDomAttributes(node.localName, { [property]: value }, { urlOriginPolicy: options.urlOriginPolicy });
980
+ if (attribute) return {
981
+ ok: true,
982
+ record: [
983
+ _remote_dom_core.MUTATION_TYPE_UPDATE_PROPERTY,
984
+ id,
985
+ attribute.name,
986
+ attribute.value,
987
+ _remote_dom_core.UPDATE_PROPERTY_TYPE_ATTRIBUTE
988
+ ]
989
+ };
990
+ const normalizedAttributeName = property.trim().toLowerCase();
991
+ if (!/^[a-z][a-z0-9_.-]*$/u.test(normalizedAttributeName)) return {
992
+ ok: false,
993
+ message: `Remote DOM mutation used an invalid attribute removal name "${property}".`
994
+ };
995
+ return {
996
+ ok: true,
997
+ record: [
998
+ _remote_dom_core.MUTATION_TYPE_UPDATE_PROPERTY,
999
+ id,
1000
+ normalizedAttributeName,
1001
+ void 0,
1002
+ _remote_dom_core.UPDATE_PROPERTY_TYPE_ATTRIBUTE
1003
+ ]
1004
+ };
1005
+ }
1006
+ function normalizeRemoteNodeForHost(options, state, value, seen, pendingEventListenerUpdates) {
1007
+ if (!isObjectRecord(value)) return {
1008
+ ok: false,
1009
+ message: "Remote DOM render payload was not a node."
1010
+ };
1011
+ if (value.type === _remote_dom_core.NODE_TYPE_TEXT && typeof value.id === "string" && typeof value.data === "string") {
1012
+ const idValidation = validateRemoteNodeId(value.id, seen);
1013
+ if (!idValidation.ok) return idValidation;
1014
+ return {
1015
+ ok: true,
1016
+ node: {
1017
+ id: value.id,
1018
+ type: _remote_dom_core.NODE_TYPE_TEXT,
1019
+ data: value.data
1020
+ },
1021
+ nodeCount: 1
1022
+ };
1023
+ }
1024
+ if (value.type !== _remote_dom_core.NODE_TYPE_ELEMENT || typeof value.id !== "string" || typeof value.element !== "string") return {
1025
+ ok: false,
1026
+ message: "Remote DOM render payload was not a valid node."
1027
+ };
1028
+ const idValidation = validateRemoteNodeId(value.id, seen);
1029
+ if (!idValidation.ok) return idValidation;
1030
+ const properties = readRemoteNodeProperties(value);
1031
+ if (!properties) return {
1032
+ ok: false,
1033
+ message: `Remote DOM element "${value.id}" contained non-serializable properties.`
1034
+ };
1035
+ const tagName = sanitizeRemoteDomTagName(value.element);
1036
+ if (!tagName) return {
1037
+ ok: false,
1038
+ message: `Remote DOM element "${value.id}" used an unsupported tag name.`
1039
+ };
1040
+ queueRemoteNodeEventListeners(value.id, tagName, value.eventListeners, pendingEventListenerUpdates);
1041
+ if (!Array.isArray(value.children)) return {
1042
+ ok: false,
1043
+ message: `Remote DOM element "${value.id}" did not contain a valid children array.`
1044
+ };
1045
+ const children = [];
1046
+ let nodeCount = 1;
1047
+ for (const child of value.children) {
1048
+ const normalized = normalizeRemoteNodeForHost(options, state, child, seen, pendingEventListenerUpdates);
1049
+ if (!normalized.ok) return normalized;
1050
+ children.push(normalized.node);
1051
+ nodeCount += normalized.nodeCount;
1052
+ }
1053
+ const remoteProperties = {};
1054
+ let attributeProperties = properties;
1055
+ if (isObjectRecord(value.properties)) {
1056
+ const mutableAttributeProperties = { ...properties };
1057
+ attributeProperties = mutableAttributeProperties;
1058
+ for (const [rawName, rawValue] of Object.entries(value.properties)) {
1059
+ const property = sanitizeRemoteDomProperty(tagName, rawName, rawValue);
1060
+ if (property) {
1061
+ remoteProperties[property.name] = property.value;
1062
+ delete mutableAttributeProperties[rawName];
1063
+ continue;
1064
+ }
1065
+ if (isRemoteDomPropertyName(tagName, rawName)) return {
1066
+ ok: false,
1067
+ message: `Remote DOM property "${rawName}" had an invalid value for "${tagName}".`
1068
+ };
1069
+ }
1070
+ }
1071
+ const attributes = sanitizeRemoteDomAttributes(tagName, attributeProperties, { urlOriginPolicy: options.urlOriginPolicy });
1072
+ const remoteAttributes = {};
1073
+ for (const attribute of attributes) remoteAttributes[attribute.name] = attribute.value;
1074
+ if (tagName === "button" && remoteAttributes.type === void 0) remoteAttributes.type = "button";
1075
+ return {
1076
+ ok: true,
1077
+ node: {
1078
+ id: value.id,
1079
+ type: _remote_dom_core.NODE_TYPE_ELEMENT,
1080
+ element: tagName,
1081
+ attributes: remoteAttributes,
1082
+ properties: remoteProperties,
1083
+ children
1084
+ },
1085
+ nodeCount
1086
+ };
1087
+ }
1088
+ function queueRemoteNodeEventListeners(id, tagName, eventListeners, pendingEventListenerUpdates) {
1089
+ if (!isObjectRecord(eventListeners)) return;
1090
+ for (const [eventName, listener] of Object.entries(eventListeners)) {
1091
+ if (!require_remote_dom_values.isSafeRemoteDomPropertyKey(eventName) || !isSupportedRemoteDomEventName(eventName, tagName)) continue;
1092
+ pendingEventListenerUpdates.push({
1093
+ targetId: id,
1094
+ eventName,
1095
+ listener: typeof listener === "function" ? listener : null
1096
+ });
1097
+ }
1098
+ }
1099
+ function validateRemoteNodeId(id, seen) {
1100
+ if (id === _remote_dom_core.ROOT_ID) return {
1101
+ ok: false,
1102
+ message: `Remote DOM node id "${id}" is reserved`
1103
+ };
1104
+ if (seen.has(id)) return {
1105
+ ok: false,
1106
+ message: `Remote DOM render payload contained duplicate node id "${id}"`
1107
+ };
1108
+ seen.add(id);
1109
+ return { ok: true };
1110
+ }
1111
+ function readRemoteNodeProperties(value) {
1112
+ const properties = {};
1113
+ for (const source of [value.attributes, value.properties]) {
1114
+ if (source === void 0) continue;
1115
+ if (!isObjectRecord(source)) return void 0;
1116
+ for (const [key, item] of Object.entries(source)) {
1117
+ if (!require_remote_dom_values.isSafeRemoteDomPropertyKey(key)) return void 0;
1118
+ if (item !== void 0 && !require_remote_dom_values.isRemoteDomSerializableValue(item)) return;
1119
+ properties[key] = item;
1120
+ }
1121
+ }
1122
+ return properties;
1123
+ }
1124
+ function registerSimulatedRemoteNode(state, node) {
1125
+ if (node.type === _remote_dom_core.NODE_TYPE_TEXT) {
1126
+ state.nodes.set(node.id, { kind: "text" });
1127
+ return;
1128
+ }
1129
+ if (node.type !== _remote_dom_core.NODE_TYPE_ELEMENT) return;
1130
+ state.nodes.set(node.id, {
1131
+ kind: "element",
1132
+ localName: node.element,
1133
+ childIds: node.children.map((child) => child.id)
1134
+ });
1135
+ for (const child of node.children) registerSimulatedRemoteNode(state, child);
1136
+ }
1137
+ function removeSimulatedRemoteNode(state, id) {
1138
+ const node = state.nodes.get(id);
1139
+ if (!node) return;
1140
+ state.nodes.delete(id);
1141
+ if (node.kind === "element") for (const childId of node.childIds) removeSimulatedRemoteNode(state, childId);
1142
+ }
1143
+ function parseRemoteMutationRecord(value) {
1144
+ if (!Array.isArray(value)) return void 0;
1145
+ switch (value[0]) {
1146
+ case _remote_dom_core.MUTATION_TYPE_INSERT_CHILD: return value.length === 4 && typeof value[1] === "string" && isObjectRecord(value[2]) && typeof value[3] === "number" ? value : void 0;
1147
+ case _remote_dom_core.MUTATION_TYPE_REMOVE_CHILD: return value.length === 3 && typeof value[1] === "string" && typeof value[2] === "number" ? value : void 0;
1148
+ case _remote_dom_core.MUTATION_TYPE_UPDATE_TEXT: return value.length === 3 && typeof value[1] === "string" && typeof value[2] === "string" ? value : void 0;
1149
+ case _remote_dom_core.MUTATION_TYPE_UPDATE_PROPERTY: return (value.length === 4 || value.length === 5) && typeof value[1] === "string" && typeof value[2] === "string" ? value : void 0;
1150
+ default: return;
1151
+ }
1152
+ }
1153
+ function isObjectRecord(value) {
1154
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1155
+ }
1156
+ //#endregion
1157
+ //#region src/remote-dom-styles.ts
1158
+ const remoteDomCssArtifactCache = /* @__PURE__ */ new Map();
1159
+ const DEFAULT_THEME_DATA_ATTRIBUTES = [
1160
+ "data-theme",
1161
+ "data-mode",
1162
+ "data-color-mode",
1163
+ "data-fluid-theme",
1164
+ "data-fluid-color-scheme"
1165
+ ];
1166
+ const REMOTE_DOM_WIDGET_STYLE_ATTRIBUTE = "data-fluid-widget-style";
1167
+ function attachRemoteDomStyles({ artifact, root, cssText, widgetCssText, cssUrls, fluidComponentCssText, fluidComponentCssUrls, themeBridgeCssText, urlOriginPolicy, useConstructableStylesheets = true, fetchCss, onFailure, themeBridge }) {
1168
+ const styleElements = [];
1169
+ const adoptedSheets = /* @__PURE__ */ new Set();
1170
+ const acquiredArtifacts = [];
1171
+ let disposed = false;
1172
+ let failureReported = false;
1173
+ const resolvedUrlOriginPolicy = urlOriginPolicy ?? require_remote_dom_values.createRemoteDomUrlOriginPolicy({ artifactUrls: collectArtifactUrls$1(artifact) });
1174
+ const { sources, failedSourceCount: rejectedSourceCount } = createStyleSources({
1175
+ artifact,
1176
+ cssText,
1177
+ widgetCssText,
1178
+ cssUrls,
1179
+ fluidComponentCssText,
1180
+ fluidComponentCssUrls,
1181
+ themeBridgeCssText,
1182
+ urlOriginPolicy: resolvedUrlOriginPolicy
1183
+ });
1184
+ const declaredSourceCount = sources.length + rejectedSourceCount;
1185
+ const bridge = themeBridge === false ? void 0 : createRemoteDomThemeBridge({
1186
+ root,
1187
+ ...themeBridge
1188
+ });
1189
+ const reportFailures = (failedSourceCount) => {
1190
+ if (disposed || failureReported || failedSourceCount === 0) return;
1191
+ failureReported = true;
1192
+ try {
1193
+ onFailure?.(failedSourceCount);
1194
+ } catch {}
1195
+ };
1196
+ return {
1197
+ ready: Promise.resolve().then(async () => {
1198
+ const sourceResults = await Promise.all(sources.map(async (source) => {
1199
+ if (disposed) return void 0;
1200
+ if (source.kind === "text") return source;
1201
+ let artifact;
1202
+ try {
1203
+ artifact = acquireCssArtifact(source, root, fetchCss);
1204
+ acquiredArtifacts.push(artifact);
1205
+ const sanitizedCssText = sanitizeRemoteDomCssUrlReferences(await artifact.entry.promise, { urlOriginPolicy: resolvedUrlOriginPolicy });
1206
+ if (!sanitizedCssText) {
1207
+ releaseCssArtifact(artifact);
1208
+ if (artifact.entry.refCount === 0) remoteDomCssArtifactCache.delete(artifact.entry.key);
1209
+ return null;
1210
+ }
1211
+ if (disposed) {
1212
+ releaseCssArtifact(artifact);
1213
+ return;
1214
+ }
1215
+ return {
1216
+ kind: "text",
1217
+ label: source.label,
1218
+ cssText: sanitizedCssText,
1219
+ artifact: artifact.entry
1220
+ };
1221
+ } catch {
1222
+ if (artifact) {
1223
+ releaseCssArtifact(artifact);
1224
+ if (artifact.entry.refCount === 0) remoteDomCssArtifactCache.delete(artifact.entry.key);
1225
+ }
1226
+ return null;
1227
+ }
1228
+ }));
1229
+ if (disposed) return;
1230
+ const resolvedSources = [];
1231
+ let resolutionFailureCount = 0;
1232
+ for (const source of sourceResults) if (source === null) resolutionFailureCount += 1;
1233
+ else if (source !== void 0) resolvedSources.push(source);
1234
+ const installationFailureCount = installResolvedStyleSources({
1235
+ root,
1236
+ sources: resolvedSources,
1237
+ styleElements,
1238
+ adoptedSheets,
1239
+ useConstructableStylesheets
1240
+ });
1241
+ reportFailures(rejectedSourceCount + resolutionFailureCount + installationFailureCount);
1242
+ }).catch(() => {
1243
+ reportFailures(declaredSourceCount);
1244
+ }),
1245
+ dispose: () => {
1246
+ if (disposed) return;
1247
+ disposed = true;
1248
+ const cleanupErrors = [];
1249
+ runStyleCleanupStep(cleanupErrors, () => bridge?.dispose());
1250
+ runStyleCleanupStep(cleanupErrors, () => removeAdoptedSheets(root, adoptedSheets));
1251
+ for (const styleElement of styleElements) runStyleCleanupStep(cleanupErrors, () => styleElement.remove());
1252
+ for (const artifact of acquiredArtifacts) runStyleCleanupStep(cleanupErrors, () => releaseCssArtifact(artifact));
1253
+ throwStyleCleanupErrors(cleanupErrors, "Remote DOM style disposal encountered cleanup failures");
1254
+ }
1255
+ };
1256
+ }
1257
+ function createRemoteDomThemeBridge(options) {
1258
+ const sourceElement = options.sourceElement ?? options.root.ownerDocument.documentElement;
1259
+ const host = options.root.host;
1260
+ const managedVariables = /* @__PURE__ */ new Set();
1261
+ const managedAttributes = /* @__PURE__ */ new Set();
1262
+ const managedClasses = /* @__PURE__ */ new Set();
1263
+ const originalVariables = host instanceof HTMLElement ? snapshotCssVariables(host) : /* @__PURE__ */ new Map();
1264
+ const originalAttributes = host instanceof HTMLElement ? snapshotDataAttributes(host) : /* @__PURE__ */ new Map();
1265
+ const originalClasses = host instanceof HTMLElement ? new Set(host.classList) : /* @__PURE__ */ new Set();
1266
+ let disposed = false;
1267
+ let observer;
1268
+ const restore = () => {
1269
+ if (!(host instanceof HTMLElement)) return;
1270
+ restoreThemeBridgeState({
1271
+ host,
1272
+ managedVariables,
1273
+ managedAttributes,
1274
+ managedClasses,
1275
+ originalVariables,
1276
+ originalAttributes,
1277
+ originalClasses
1278
+ });
1279
+ };
1280
+ const update = () => {
1281
+ if (disposed || !(host instanceof HTMLElement)) return;
1282
+ try {
1283
+ mirrorCssVariables({
1284
+ host,
1285
+ sourceElement,
1286
+ variableNames: options.cssVariableNames,
1287
+ managedVariables,
1288
+ originalVariables
1289
+ });
1290
+ mirrorDataAttributes({
1291
+ host,
1292
+ sourceElement,
1293
+ dataAttributes: options.dataAttributes,
1294
+ copyAllDataAttributes: options.copyAllDataAttributes ?? true,
1295
+ managedAttributes,
1296
+ originalAttributes
1297
+ });
1298
+ mirrorClasses({
1299
+ host,
1300
+ sourceElement,
1301
+ classNames: options.classNames ?? "all",
1302
+ managedClasses,
1303
+ originalClasses
1304
+ });
1305
+ } catch (error) {
1306
+ throw rollbackThemeBridge(error);
1307
+ }
1308
+ };
1309
+ const rollbackThemeBridge = (error) => {
1310
+ disposed = true;
1311
+ const cleanupErrors = [];
1312
+ runStyleCleanupStep(cleanupErrors, () => observer?.disconnect());
1313
+ runStyleCleanupStep(cleanupErrors, restore);
1314
+ return cleanupErrors.length === 0 ? error : new AggregateError([error, ...cleanupErrors], "Remote DOM theme update failed and rollback encountered cleanup failures");
1315
+ };
1316
+ try {
1317
+ update();
1318
+ if (options.observe !== false && typeof MutationObserver !== "undefined") {
1319
+ observer = new MutationObserver(() => update());
1320
+ observer.observe(options.observeTarget ?? sourceElement, {
1321
+ attributes: true,
1322
+ childList: options.observeTarget ? true : false,
1323
+ subtree: options.observeTarget ? true : false
1324
+ });
1325
+ }
1326
+ } catch (error) {
1327
+ if (disposed) throw error;
1328
+ throw rollbackThemeBridge(error);
1329
+ }
1330
+ return {
1331
+ update,
1332
+ dispose: () => {
1333
+ if (disposed) return;
1334
+ disposed = true;
1335
+ const cleanupErrors = [];
1336
+ runStyleCleanupStep(cleanupErrors, () => observer?.disconnect());
1337
+ runStyleCleanupStep(cleanupErrors, restore);
1338
+ throwStyleCleanupErrors(cleanupErrors, "Remote DOM theme bridge disposal encountered cleanup failures");
1339
+ }
1340
+ };
1341
+ }
1342
+ function collectArtifactUrls$1(artifact) {
1343
+ return [
1344
+ artifact.workerEntryUrl,
1345
+ ...artifact.cssUrls,
1346
+ ...artifact.assetUrls
1347
+ ];
1348
+ }
1349
+ function createStyleSources({ artifact, cssText, widgetCssText, cssUrls, fluidComponentCssText, fluidComponentCssUrls, themeBridgeCssText, urlOriginPolicy }) {
1350
+ const sources = [];
1351
+ const defaultVersion = `${artifact.packageId}@${artifact.version}`;
1352
+ let failedSourceCount = 0;
1353
+ failedSourceCount += addTextSource(sources, "fluid-components", fluidComponentCssText, urlOriginPolicy);
1354
+ failedSourceCount += addUrlSources(sources, "fluid-components", fluidComponentCssUrls ?? [], defaultVersion, urlOriginPolicy);
1355
+ failedSourceCount += addTextSource(sources, "theme-bridge", themeBridgeCssText, urlOriginPolicy);
1356
+ failedSourceCount += addTextSource(sources, "widget", widgetCssText ?? cssText, urlOriginPolicy);
1357
+ failedSourceCount += addUrlSources(sources, "widget", cssUrls ?? artifact.cssUrls, defaultVersion, urlOriginPolicy);
1358
+ return {
1359
+ sources,
1360
+ failedSourceCount
1361
+ };
1362
+ }
1363
+ function addTextSource(sources, label, cssText, urlOriginPolicy) {
1364
+ if (!cssText || cssText.length === 0) return 0;
1365
+ try {
1366
+ const sanitizedCssText = sanitizeRemoteDomCssUrlReferences(cssText, { urlOriginPolicy });
1367
+ if (!sanitizedCssText) return 1;
1368
+ sources.push({
1369
+ kind: "text",
1370
+ label,
1371
+ cssText: sanitizedCssText
1372
+ });
1373
+ return 0;
1374
+ } catch {
1375
+ return 1;
1376
+ }
1377
+ }
1378
+ function addUrlSources(sources, label, cssUrls, defaultVersion, urlOriginPolicy) {
1379
+ let failedSourceCount = 0;
1380
+ for (const cssUrl of cssUrls) try {
1381
+ const sanitizedUrl = sanitizeRemoteDomUrl(typeof cssUrl === "string" ? cssUrl : cssUrl.url, {
1382
+ allowHashOnly: false,
1383
+ allowMailTo: false,
1384
+ allowRelative: false,
1385
+ allowTel: false,
1386
+ allowedHttpOriginGroups: ["artifact"],
1387
+ originPolicy: urlOriginPolicy
1388
+ });
1389
+ if (!sanitizedUrl) {
1390
+ failedSourceCount += 1;
1391
+ continue;
1392
+ }
1393
+ sources.push({
1394
+ kind: "url",
1395
+ label,
1396
+ url: sanitizedUrl,
1397
+ version: typeof cssUrl === "string" ? defaultVersion : cssUrl.version ?? defaultVersion
1398
+ });
1399
+ } catch {
1400
+ failedSourceCount += 1;
1401
+ }
1402
+ return failedSourceCount;
1403
+ }
1404
+ function acquireCssArtifact(source, root, fetchCss) {
1405
+ const key = createCssArtifactCacheKey(source.url, source.version);
1406
+ const existingEntry = remoteDomCssArtifactCache.get(key);
1407
+ if (existingEntry) {
1408
+ existingEntry.refCount += 1;
1409
+ return {
1410
+ entry: existingEntry,
1411
+ released: false
1412
+ };
1413
+ }
1414
+ const entry = {
1415
+ key,
1416
+ url: source.url,
1417
+ version: source.version,
1418
+ promise: resolveFetchCss(root, fetchCss)(source.url),
1419
+ sheet: void 0,
1420
+ refCount: 1
1421
+ };
1422
+ remoteDomCssArtifactCache.set(key, entry);
1423
+ return {
1424
+ entry,
1425
+ released: false
1426
+ };
1427
+ }
1428
+ function releaseCssArtifact(artifact) {
1429
+ if (artifact.released) return;
1430
+ artifact.released = true;
1431
+ artifact.entry.refCount = Math.max(0, artifact.entry.refCount - 1);
1432
+ }
1433
+ function runStyleCleanupStep(errors, cleanup) {
1434
+ try {
1435
+ cleanup();
1436
+ } catch (error) {
1437
+ errors.push(error);
1438
+ }
1439
+ }
1440
+ function throwStyleCleanupErrors(errors, message) {
1441
+ if (errors.length > 0) throw new AggregateError(errors, message);
1442
+ }
1443
+ function installResolvedStyleSources({ root, sources, styleElements, adoptedSheets, useConstructableStylesheets }) {
1444
+ const canAdoptStylesheets = useConstructableStylesheets && readAdoptedStyleSheets(root) !== void 0;
1445
+ let failedSourceCount = 0;
1446
+ let adoptedSourceCount = 0;
1447
+ for (const source of sources) {
1448
+ let sheet;
1449
+ if (canAdoptStylesheets) try {
1450
+ sheet = getOrCreateConstructableStyleSheet(source.cssText, source.artifact);
1451
+ } catch {
1452
+ sheet = void 0;
1453
+ }
1454
+ if (sheet) {
1455
+ adoptedSheets.add(sheet);
1456
+ adoptedSourceCount += 1;
1457
+ continue;
1458
+ }
1459
+ let styleElement;
1460
+ try {
1461
+ styleElement = root.ownerDocument.createElement("style");
1462
+ styleElement.setAttribute(REMOTE_DOM_WIDGET_STYLE_ATTRIBUTE, source.label);
1463
+ styleElement.textContent = source.cssText;
1464
+ root.append(styleElement);
1465
+ styleElements.push(styleElement);
1466
+ } catch {
1467
+ styleElement?.remove();
1468
+ failedSourceCount += 1;
1469
+ }
1470
+ }
1471
+ if (adoptedSheets.size > 0) try {
1472
+ appendAdoptedSheets(root, Array.from(adoptedSheets));
1473
+ } catch {
1474
+ let removalFailed = false;
1475
+ try {
1476
+ removeAdoptedSheets(root, adoptedSheets);
1477
+ } catch {
1478
+ removalFailed = true;
1479
+ }
1480
+ if (!removalFailed) adoptedSheets.clear();
1481
+ failedSourceCount += adoptedSourceCount;
1482
+ }
1483
+ return failedSourceCount;
1484
+ }
1485
+ function getOrCreateConstructableStyleSheet(cssText, cachedArtifact) {
1486
+ if (cachedArtifact?.sheet) return cachedArtifact.sheet;
1487
+ const sheet = createConstructableStyleSheet(cssText);
1488
+ if (cachedArtifact) cachedArtifact.sheet = sheet;
1489
+ return sheet;
1490
+ }
1491
+ function createConstructableStyleSheet(cssText) {
1492
+ if (typeof CSSStyleSheet === "undefined") return void 0;
1493
+ const sheet = new CSSStyleSheet();
1494
+ if (typeof sheet.replaceSync !== "function") return void 0;
1495
+ try {
1496
+ sheet.replaceSync(cssText);
1497
+ return sheet;
1498
+ } catch {
1499
+ return;
1500
+ }
1501
+ }
1502
+ function appendAdoptedSheets(root, sheets) {
1503
+ const previousAdoptedStyleSheets = readAdoptedStyleSheets(root);
1504
+ if (!previousAdoptedStyleSheets) return;
1505
+ root.adoptedStyleSheets = [...previousAdoptedStyleSheets, ...sheets];
1506
+ }
1507
+ function removeAdoptedSheets(root, adoptedSheets) {
1508
+ if (adoptedSheets.size === 0) return;
1509
+ const currentAdoptedStyleSheets = readAdoptedStyleSheets(root);
1510
+ if (!currentAdoptedStyleSheets) return;
1511
+ root.adoptedStyleSheets = currentAdoptedStyleSheets.filter((sheet) => !adoptedSheets.has(sheet));
1512
+ }
1513
+ function readAdoptedStyleSheets(root) {
1514
+ if (!("adoptedStyleSheets" in root)) return void 0;
1515
+ return [...root.adoptedStyleSheets];
1516
+ }
1517
+ function resolveFetchCss(root, fetchCss) {
1518
+ if (fetchCss) return fetchCss;
1519
+ const windowFetch = root.ownerDocument.defaultView?.fetch;
1520
+ if (typeof windowFetch === "function") return async (url) => {
1521
+ const response = await windowFetch(url);
1522
+ if (!response.ok) throw new Error(`Failed to fetch Remote DOM CSS: ${url}`);
1523
+ return response.text();
1524
+ };
1525
+ return async () => "";
1526
+ }
1527
+ function createCssArtifactCacheKey(url, version) {
1528
+ return `${version}:${url}`;
1529
+ }
1530
+ function snapshotCssVariables(host) {
1531
+ const declaredVariableNames = /* @__PURE__ */ new Set();
1532
+ collectCssVariableNamesFromDeclaration(declaredVariableNames, host.style);
1533
+ const snapshots = /* @__PURE__ */ new Map();
1534
+ for (const variableName of declaredVariableNames) snapshots.set(variableName, {
1535
+ value: host.style.getPropertyValue(variableName),
1536
+ priority: host.style.getPropertyPriority(variableName)
1537
+ });
1538
+ return snapshots;
1539
+ }
1540
+ function snapshotDataAttributes(host) {
1541
+ const snapshots = /* @__PURE__ */ new Map();
1542
+ for (const attributeName of host.getAttributeNames()) {
1543
+ if (!attributeName.startsWith("data-")) continue;
1544
+ const value = host.getAttribute(attributeName);
1545
+ if (value !== null) snapshots.set(attributeName, value);
1546
+ }
1547
+ return snapshots;
1548
+ }
1549
+ function restoreThemeBridgeState({ host, managedVariables, managedAttributes, managedClasses, originalVariables, originalAttributes, originalClasses }) {
1550
+ const restorationErrors = [];
1551
+ for (const variableName of Array.from(managedVariables)) runStyleCleanupStep(restorationErrors, () => {
1552
+ restoreCssVariable(host, variableName, originalVariables);
1553
+ managedVariables.delete(variableName);
1554
+ });
1555
+ for (const attributeName of Array.from(managedAttributes)) runStyleCleanupStep(restorationErrors, () => {
1556
+ const originalValue = originalAttributes.get(attributeName);
1557
+ if (originalValue === void 0) host.removeAttribute(attributeName);
1558
+ else host.setAttribute(attributeName, originalValue);
1559
+ managedAttributes.delete(attributeName);
1560
+ });
1561
+ for (const className of Array.from(managedClasses)) runStyleCleanupStep(restorationErrors, () => {
1562
+ host.classList.toggle(className, originalClasses.has(className));
1563
+ managedClasses.delete(className);
1564
+ });
1565
+ throwStyleCleanupErrors(restorationErrors, "Remote DOM theme restoration encountered cleanup failures");
1566
+ }
1567
+ function restoreCssVariable(host, variableName, originalVariables) {
1568
+ const original = originalVariables.get(variableName);
1569
+ if (original) host.style.setProperty(variableName, original.value, original.priority);
1570
+ else host.style.removeProperty(variableName);
1571
+ }
1572
+ function mirrorCssVariables({ host, sourceElement, variableNames, managedVariables, originalVariables }) {
1573
+ const computedStyle = sourceElement.ownerDocument.defaultView?.getComputedStyle(sourceElement);
1574
+ const nextVariables = new Set((variableNames ?? collectCssVariableNames(sourceElement, computedStyle)).filter((variableName) => variableName.startsWith("--")));
1575
+ for (const variableName of managedVariables) if (!nextVariables.has(variableName)) {
1576
+ restoreCssVariable(host, variableName, originalVariables);
1577
+ managedVariables.delete(variableName);
1578
+ }
1579
+ for (const variableName of nextVariables) {
1580
+ const value = computedStyle?.getPropertyValue(variableName) ?? "";
1581
+ if (value.length > 0) {
1582
+ managedVariables.add(variableName);
1583
+ host.style.setProperty(variableName, value.trim());
1584
+ } else {
1585
+ restoreCssVariable(host, variableName, originalVariables);
1586
+ managedVariables.delete(variableName);
1587
+ }
1588
+ }
1589
+ }
1590
+ function collectCssVariableNames(sourceElement, computedStyle) {
1591
+ const variableNames = /* @__PURE__ */ new Set();
1592
+ collectCssVariableNamesFromDeclaration(variableNames, computedStyle);
1593
+ if (sourceElement instanceof HTMLElement || sourceElement instanceof SVGElement) collectCssVariableNamesFromDeclaration(variableNames, sourceElement.style);
1594
+ return Array.from(variableNames);
1595
+ }
1596
+ function collectCssVariableNamesFromDeclaration(variableNames, declaration) {
1597
+ if (!declaration) return;
1598
+ for (let index = 0; index < declaration.length; index += 1) {
1599
+ const propertyName = declaration.item(index);
1600
+ if (propertyName.startsWith("--")) variableNames.add(propertyName);
1601
+ }
1602
+ }
1603
+ function mirrorDataAttributes({ host, sourceElement, dataAttributes, copyAllDataAttributes, managedAttributes, originalAttributes }) {
1604
+ const nextAttributes = /* @__PURE__ */ new Map();
1605
+ const attributeNames = (dataAttributes ?? (copyAllDataAttributes ? sourceElement.getAttributeNames() : DEFAULT_THEME_DATA_ATTRIBUTES)).filter((attributeName) => attributeName.startsWith("data-"));
1606
+ for (const attributeName of attributeNames) {
1607
+ const value = sourceElement.getAttribute(attributeName);
1608
+ if (value !== null) nextAttributes.set(attributeName, value);
1609
+ }
1610
+ for (const attributeName of managedAttributes) if (!nextAttributes.has(attributeName)) {
1611
+ const originalValue = originalAttributes.get(attributeName);
1612
+ if (originalValue === void 0) host.removeAttribute(attributeName);
1613
+ else host.setAttribute(attributeName, originalValue);
1614
+ managedAttributes.delete(attributeName);
1615
+ }
1616
+ for (const [attributeName, value] of nextAttributes) {
1617
+ managedAttributes.add(attributeName);
1618
+ host.setAttribute(attributeName, value);
1619
+ }
1620
+ }
1621
+ function mirrorClasses({ host, sourceElement, classNames, managedClasses, originalClasses }) {
1622
+ const sourceClasses = new Set(sourceElement.classList);
1623
+ const nextClasses = classNames === "all" ? sourceClasses : new Set(classNames.filter((className) => sourceClasses.has(className)));
1624
+ for (const className of managedClasses) if (!nextClasses.has(className)) {
1625
+ host.classList.toggle(className, originalClasses.has(className));
1626
+ managedClasses.delete(className);
1627
+ }
1628
+ for (const className of nextClasses) {
1629
+ managedClasses.add(className);
1630
+ host.classList.add(className);
1631
+ }
1632
+ }
1633
+ //#endregion
1634
+ //#region src/remote-dom-renderer.ts
1635
+ const DEFAULT_MAX_MUTATION_BATCH_SIZE = 100;
1636
+ const DEFAULT_MAX_DOM_NODE_COUNT = 1e3;
1637
+ function mountRemoteDomWidget(options) {
1638
+ const initialProps = options.props ?? null;
1639
+ assertSerializable(initialProps, "Initial widget props");
1640
+ const shadowRoot = createShadowRoot(options.host);
1641
+ const navigationOrigin = normalizeNavigationOrigin(options.hostOrigin);
1642
+ const urlOriginPolicy = require_remote_dom_values.createRemoteDomUrlOriginPolicy({
1643
+ artifactUrls: collectArtifactUrls(options.artifact),
1644
+ ...options.mediaOrigins === void 0 ? {} : { mediaOrigins: options.mediaOrigins },
1645
+ ...navigationOrigin === void 0 ? {} : { navigationOrigin }
1646
+ });
1647
+ const styles = attachRemoteDomStyles({
1648
+ artifact: options.artifact,
1649
+ root: shadowRoot,
1650
+ urlOriginPolicy,
1651
+ onFailure: (count) => {
1652
+ reportError(options, `${count} Remote DOM widget styles failed to load`);
1653
+ },
1654
+ ...options.cssText === void 0 ? {} : { cssText: options.cssText },
1655
+ ...options.widgetCssText === void 0 ? {} : { widgetCssText: options.widgetCssText },
1656
+ ...options.cssUrls === void 0 ? {} : { cssUrls: options.cssUrls },
1657
+ ...options.fluidComponentCssText === void 0 ? {} : { fluidComponentCssText: options.fluidComponentCssText },
1658
+ ...options.fluidComponentCssUrls === void 0 ? {} : { fluidComponentCssUrls: options.fluidComponentCssUrls },
1659
+ ...options.themeBridgeCssText === void 0 ? {} : { themeBridgeCssText: options.themeBridgeCssText },
1660
+ ...options.themeBridge === void 0 ? {} : { themeBridge: options.themeBridge },
1661
+ ...options.fetchCss === void 0 ? {} : { fetchCss: options.fetchCss },
1662
+ ...options.useConstructableStylesheets === void 0 ? {} : { useConstructableStylesheets: options.useConstructableStylesheets }
1663
+ });
1664
+ let worker;
1665
+ try {
1666
+ worker = (options.workerFactory ?? createDefaultWorker)(options.artifact.workerEntryUrl, { type: "module" });
1667
+ } catch (error) {
1668
+ reportCleanupErrors(options, "Remote DOM widget setup cleanup failed", collectCleanupErrors([() => styles.dispose(), () => clearRenderedRemoteDomNodes(shadowRoot)]));
1669
+ throw error;
1670
+ }
1671
+ let thread;
1672
+ try {
1673
+ thread = new require_Thread.Thread(createWorkerMessageTarget(worker));
1674
+ } catch (error) {
1675
+ reportCleanupErrors(options, "Remote DOM widget setup cleanup failed", collectCleanupErrors([
1676
+ () => styles.dispose(),
1677
+ () => worker.terminate(),
1678
+ () => clearRenderedRemoteDomNodes(shadowRoot)
1679
+ ]));
1680
+ throw error;
1681
+ }
1682
+ let state;
1683
+ const pendingListenerUpdates = /* @__PURE__ */ new Map();
1684
+ const connection = createSanitizingRemoteConnection({
1685
+ connection: new _remote_dom_core_receivers.DOMRemoteReceiver({
1686
+ root: shadowRoot,
1687
+ call: () => {
1688
+ throw new RemoteDomConnectionCallDeniedError("remote element method");
1689
+ }
1690
+ }).connection,
1691
+ urlOriginPolicy,
1692
+ maxMutationBatchSize: options.maxMutationBatchSize ?? DEFAULT_MAX_MUTATION_BATCH_SIZE,
1693
+ maxDomNodeCount: options.maxDomNodeCount ?? DEFAULT_MAX_DOM_NODE_COUNT,
1694
+ onEventListenerUpdate: (targetId, eventName, listener) => {
1695
+ pendingListenerUpdates.set(subscriptionKey(targetId, eventName), {
1696
+ targetId,
1697
+ eventName,
1698
+ listener
1699
+ });
1700
+ },
1701
+ onNodeLimitExceeded: () => {
1702
+ reportError(options, "Remote DOM widget exceeded its DOM node limit");
1703
+ },
1704
+ onInvalidRecord: (message) => reportError(options, message),
1705
+ onMutateError: (error) => reportError(options, "Remote DOM mutation could not be applied", error)
1706
+ });
1707
+ const submitListener = createSubmitPreventionListener();
1708
+ const navigationListener = (event) => {
1709
+ handleNavigationIntent(state, event);
1710
+ };
1711
+ state = {
1712
+ options,
1713
+ shadowRoot,
1714
+ worker,
1715
+ thread,
1716
+ styles,
1717
+ urlOriginPolicy,
1718
+ navigationOrigin,
1719
+ nodesById: new Map([[_remote_dom_core.ROOT_ID, shadowRoot]]),
1720
+ subscriptions: /* @__PURE__ */ new Map(),
1721
+ pendingListenerUpdates,
1722
+ submitListener,
1723
+ navigationListener,
1724
+ disposed: false,
1725
+ cleanupStarted: false
1726
+ };
1727
+ shadowRoot.addEventListener("submit", submitListener, { capture: true });
1728
+ shadowRoot.addEventListener("click", navigationListener, { capture: true });
1729
+ worker.onerror = (event) => {
1730
+ if (state.disposed) return;
1731
+ reportError(options, event.message || "Remote DOM widget worker failed", event.error);
1732
+ disposeAfterFailure(state, false);
1733
+ };
1734
+ const ready = Promise.all([styles.ready, thread.imports.mount({
1735
+ widgetType: options.artifact.widgetType,
1736
+ props: initialProps
1737
+ }, {
1738
+ mutate(records) {
1739
+ if (state.disposed) return;
1740
+ connection.mutate(records);
1741
+ rebuildNodeIndex(state);
1742
+ flushPendingListenerUpdates(state);
1743
+ },
1744
+ callCapability(capability, method, payload) {
1745
+ return callCapability(state, capability, method, payload);
1746
+ },
1747
+ reportError(error) {
1748
+ reportError(options, error.message);
1749
+ }
1750
+ })]).then(() => void 0);
1751
+ ready.catch((error) => {
1752
+ if (state.disposed) return;
1753
+ reportError(options, "Remote DOM widget failed to mount", error);
1754
+ disposeAfterFailure(state);
1755
+ });
1756
+ return {
1757
+ shadowRoot,
1758
+ styles,
1759
+ ready,
1760
+ updateProps(props) {
1761
+ if (state.disposed) return;
1762
+ assertSerializable(props, "Widget props");
1763
+ state.thread.imports.updateProps(props).catch((error) => {
1764
+ if (!state.disposed) reportError(options, "Remote DOM widget props update failed", error);
1765
+ });
1766
+ },
1767
+ dispose() {
1768
+ disposeMount(state);
1769
+ }
1770
+ };
1771
+ }
1772
+ function callCapability(state, capability, method, payload) {
1773
+ if (state.disposed) return Promise.reject(/* @__PURE__ */ new Error("Remote DOM widget has been disposed"));
1774
+ if (!state.options.artifact.capabilities.some((declaration) => declaration.name === capability)) return Promise.reject(/* @__PURE__ */ new Error(`Remote DOM capability "${capability}" was not declared`));
1775
+ if (payload !== void 0 && !require_remote_dom_values.isRemoteDomSerializableValue(payload)) return Promise.reject(/* @__PURE__ */ new Error("Remote DOM capability payload was not serializable"));
1776
+ if (capability === "fullscreen" && state.options.onFullscreen) return Promise.resolve().then(() => state.options.onFullscreen?.({
1777
+ method,
1778
+ ...payload === void 0 ? {} : { payload },
1779
+ host: state.options.host,
1780
+ shadowRoot: state.shadowRoot
1781
+ })).then((result) => {
1782
+ if (result === void 0) throw new Error("Remote DOM fullscreen handler returned no result");
1783
+ return assertSerializableCapabilityResult(result);
1784
+ });
1785
+ if (!state.options.callCapability) return Promise.reject(/* @__PURE__ */ new Error(`No host handler is configured for capability "${capability}"`));
1786
+ return Promise.resolve().then(() => state.options.callCapability?.(capability, method, payload)).then((result) => {
1787
+ if (result === void 0) throw new Error(`Capability handler for "${capability}" returned no result`);
1788
+ return assertSerializableCapabilityResult(result);
1789
+ });
1790
+ }
1791
+ function assertSerializableCapabilityResult(result) {
1792
+ if (!require_remote_dom_values.isRemoteDomSerializableValue(result)) throw new Error("Remote DOM capability result was not serializable");
1793
+ return result;
1794
+ }
1795
+ function rebuildNodeIndex(state) {
1796
+ state.nodesById.clear();
1797
+ state.nodesById.set(_remote_dom_core.ROOT_ID, state.shadowRoot);
1798
+ const visit = (node) => {
1799
+ state.nodesById.set((0, _remote_dom_core_elements.remoteId)(node), node);
1800
+ for (const child of node.childNodes) visit(child);
1801
+ };
1802
+ for (const child of state.shadowRoot.childNodes) if (!isWidgetStyleNode(child)) visit(child);
1803
+ for (const subscription of Array.from(state.subscriptions.values())) if (!state.nodesById.has(subscription.targetId)) unsubscribe(state, subscription.targetId, subscription.eventName);
1804
+ }
1805
+ function flushPendingListenerUpdates(state) {
1806
+ for (const update of state.pendingListenerUpdates.values()) if (update.listener === null) unsubscribe(state, update.targetId, update.eventName);
1807
+ else subscribe(state, update.targetId, update.eventName, update.listener);
1808
+ state.pendingListenerUpdates.clear();
1809
+ }
1810
+ function subscribe(state, targetId, eventName, proxy) {
1811
+ const target = state.nodesById.get(targetId);
1812
+ const tagName = target instanceof Element ? target.localName : void 0;
1813
+ if (!target || !isSupportedRemoteDomEventName(eventName, tagName)) return;
1814
+ unsubscribe(state, targetId, eventName);
1815
+ const capture = targetId === _remote_dom_core.ROOT_ID;
1816
+ const listener = (event) => {
1817
+ if (!capture && hasCloserEventSubscription(state, event, target, eventName)) return;
1818
+ if (eventName === "submit" && event.cancelable) event.preventDefault();
1819
+ const actualTargetId = resolveEventTargetId(state, event);
1820
+ if (!actualTargetId) return;
1821
+ const eventPayload = serializeRemoteDomEvent(event, actualTargetId, targetId, tagName);
1822
+ if (!eventPayload) return;
1823
+ try {
1824
+ const result = proxy({
1825
+ targetId: actualTargetId,
1826
+ detail: toSerializableEventPayload(eventPayload)
1827
+ });
1828
+ if (isPromiseLike(result)) result.catch((error) => {
1829
+ reportEventDeliveryFailure(state, error);
1830
+ });
1831
+ } catch (error) {
1832
+ reportEventDeliveryFailure(state, error);
1833
+ }
1834
+ };
1835
+ target.addEventListener(eventName, listener, { capture });
1836
+ require_Thread.retain(proxy);
1837
+ state.subscriptions.set(subscriptionKey(targetId, eventName), {
1838
+ targetId,
1839
+ eventName,
1840
+ target,
1841
+ listener,
1842
+ capture,
1843
+ proxy
1844
+ });
1845
+ }
1846
+ function hasCloserEventSubscription(state, event, subscriptionTarget, eventName) {
1847
+ for (const pathTarget of event.composedPath()) {
1848
+ if (pathTarget === subscriptionTarget) return false;
1849
+ if (!(pathTarget instanceof Node)) continue;
1850
+ const pathTargetId = (0, _remote_dom_core_elements.remoteId)(pathTarget);
1851
+ if (state.nodesById.get(pathTargetId) === pathTarget && state.subscriptions.has(subscriptionKey(pathTargetId, eventName))) return true;
1852
+ }
1853
+ return false;
1854
+ }
1855
+ function unsubscribe(state, targetId, eventName) {
1856
+ const key = subscriptionKey(targetId, eventName);
1857
+ const subscription = state.subscriptions.get(key);
1858
+ if (!subscription) return;
1859
+ subscription.target.removeEventListener(eventName, subscription.listener, { capture: subscription.capture });
1860
+ require_Thread.release(subscription.proxy);
1861
+ state.subscriptions.delete(key);
1862
+ }
1863
+ function resolveEventTargetId(state, event) {
1864
+ for (const target of event.composedPath()) {
1865
+ if (target === state.shadowRoot) return _remote_dom_core.ROOT_ID;
1866
+ if (!(target instanceof Node)) continue;
1867
+ const id = (0, _remote_dom_core_elements.remoteId)(target);
1868
+ if (state.nodesById.get(id) === target) return id;
1869
+ }
1870
+ }
1871
+ function handleNavigationIntent(state, event) {
1872
+ if (!(event instanceof MouseEvent)) return;
1873
+ const anchor = (event.target instanceof Element ? event.target : event.target instanceof Text ? event.target.parentElement : null)?.closest("a[href]");
1874
+ if (!(anchor instanceof HTMLAnchorElement)) return;
1875
+ if (!state.shadowRoot.contains(anchor)) return;
1876
+ if (event.cancelable) event.preventDefault();
1877
+ const href = sanitizeRemoteDomUrl(anchor.getAttribute("href"), {
1878
+ allowHashOnly: true,
1879
+ allowMailTo: false,
1880
+ allowRelative: true,
1881
+ allowTel: false,
1882
+ allowedHttpOriginGroups: ["navigation"],
1883
+ originPolicy: state.urlOriginPolicy,
1884
+ relativeUrlBase: "navigation"
1885
+ });
1886
+ const url = href ? resolveInternalNavigationUrl(href, state.navigationOrigin) : void 0;
1887
+ if (!href || !url || !state.options.onNavigate) {
1888
+ reportError(state.options, "Remote DOM navigation was blocked because no allowed internal route handler was available");
1889
+ return;
1890
+ }
1891
+ const targetId = findNodeId(state, anchor);
1892
+ Promise.resolve(state.options.onNavigate({
1893
+ href,
1894
+ url,
1895
+ source: "anchor",
1896
+ ...targetId === void 0 ? {} : { targetId },
1897
+ altKey: event.altKey,
1898
+ button: event.button,
1899
+ ctrlKey: event.ctrlKey,
1900
+ metaKey: event.metaKey,
1901
+ shiftKey: event.shiftKey
1902
+ })).catch((error) => {
1903
+ if (!state.disposed) reportError(state.options, "Remote DOM navigation handler failed", error);
1904
+ });
1905
+ }
1906
+ function disposeMount(state, notifyWorker = true) {
1907
+ if (state.cleanupStarted) return;
1908
+ state.cleanupStarted = true;
1909
+ state.disposed = true;
1910
+ const cleanupSteps = [
1911
+ () => {
1912
+ state.worker.onerror = null;
1913
+ },
1914
+ () => {
1915
+ state.shadowRoot.removeEventListener("submit", state.submitListener, { capture: true });
1916
+ },
1917
+ () => {
1918
+ state.shadowRoot.removeEventListener("click", state.navigationListener, { capture: true });
1919
+ }
1920
+ ];
1921
+ for (const subscription of Array.from(state.subscriptions.values())) cleanupSteps.push(() => {
1922
+ unsubscribe(state, subscription.targetId, subscription.eventName);
1923
+ });
1924
+ cleanupSteps.push(() => state.pendingListenerUpdates.clear(), () => state.styles.dispose(), () => clearRenderedRemoteDomNodes(state.shadowRoot), () => state.nodesById.clear());
1925
+ const cleanupErrors = collectCleanupErrors(cleanupSteps);
1926
+ if (notifyWorker) Promise.resolve(state.thread.imports.dispose()).catch(() => void 0);
1927
+ queueMicrotask(() => {
1928
+ reportCleanupErrors(state.options, "Remote DOM widget asynchronous cleanup failed", collectCleanupErrors([() => state.thread.close(), () => state.worker.terminate()]));
1929
+ });
1930
+ if (cleanupErrors.length > 0) throw new AggregateError(cleanupErrors, "Remote DOM widget cleanup failed");
1931
+ }
1932
+ function disposeAfterFailure(state, notifyWorker = true) {
1933
+ try {
1934
+ disposeMount(state, notifyWorker);
1935
+ } catch (cleanupError) {
1936
+ reportError(state.options, "Remote DOM widget cleanup failed after an earlier error", cleanupError);
1937
+ }
1938
+ }
1939
+ function reportEventDeliveryFailure(state, error) {
1940
+ if (state.disposed) return;
1941
+ reportError(state.options, "Remote DOM event delivery failed", error);
1942
+ }
1943
+ function createShadowRoot(host) {
1944
+ if (host.shadowRoot) {
1945
+ host.shadowRoot.replaceChildren();
1946
+ return host.shadowRoot;
1947
+ }
1948
+ return host.attachShadow({ mode: "open" });
1949
+ }
1950
+ function createSubmitPreventionListener() {
1951
+ return (event) => {
1952
+ if (event.cancelable) event.preventDefault();
1953
+ };
1954
+ }
1955
+ function collectArtifactUrls(artifact) {
1956
+ return [
1957
+ artifact.workerEntryUrl,
1958
+ ...artifact.cssUrls,
1959
+ ...artifact.assetUrls
1960
+ ];
1961
+ }
1962
+ function normalizeNavigationOrigin(value) {
1963
+ if (!value) return void 0;
1964
+ try {
1965
+ const url = new URL(value);
1966
+ return url.protocol === "http:" || url.protocol === "https:" ? url.origin : void 0;
1967
+ } catch {
1968
+ return;
1969
+ }
1970
+ }
1971
+ function resolveInternalNavigationUrl(href, navigationOrigin) {
1972
+ if (href.startsWith("#")) return href;
1973
+ if (href.startsWith("//") || /^https?:(?!\/\/)/iu.test(href)) return;
1974
+ try {
1975
+ const url = new URL(href, navigationOrigin ?? "https://fluid.local");
1976
+ if (url.protocol !== "http:" && url.protocol !== "https:") return;
1977
+ if (/^[a-z][a-z\d+.-]*:/iu.test(href) && (!navigationOrigin || url.origin !== navigationOrigin)) return;
1978
+ return `${url.pathname}${url.search}${url.hash}`;
1979
+ } catch {
1980
+ return;
1981
+ }
1982
+ }
1983
+ function findNodeId(state, node) {
1984
+ for (const [id, candidate] of state.nodesById) if (candidate === node) return id;
1985
+ }
1986
+ function isWidgetStyleNode(node) {
1987
+ return node instanceof HTMLStyleElement && node.hasAttribute("data-fluid-widget-style");
1988
+ }
1989
+ function clearRenderedRemoteDomNodes(shadowRoot) {
1990
+ for (const child of Array.from(shadowRoot.childNodes)) if (!isWidgetStyleNode(child)) child.remove();
1991
+ }
1992
+ function toSerializableEventPayload(payload) {
1993
+ const result = {
1994
+ bubbles: payload.bubbles,
1995
+ cancelable: payload.cancelable,
1996
+ currentTargetId: payload.currentTargetId,
1997
+ defaultPrevented: payload.defaultPrevented,
1998
+ targetId: payload.targetId,
1999
+ type: payload.type
2000
+ };
2001
+ for (const key of [
2002
+ "altKey",
2003
+ "button",
2004
+ "buttons",
2005
+ "checked",
2006
+ "clientX",
2007
+ "clientY",
2008
+ "code",
2009
+ "ctrlKey",
2010
+ "detailJson",
2011
+ "isPrimary",
2012
+ "key",
2013
+ "metaKey",
2014
+ "pointerId",
2015
+ "pointerType",
2016
+ "shiftKey",
2017
+ "value"
2018
+ ]) {
2019
+ const value = payload[key];
2020
+ if (value !== void 0) result[key] = value;
2021
+ }
2022
+ return result;
2023
+ }
2024
+ function assertSerializable(value, description) {
2025
+ if (!require_remote_dom_values.isRemoteDomSerializableValue(value)) throw new TypeError(`${description} must be serializable`);
2026
+ }
2027
+ function createWorkerMessageTarget(worker) {
2028
+ return {
2029
+ send(message, transferables) {
2030
+ worker.postMessage(message, transferables ?? []);
2031
+ },
2032
+ listen(listener, { signal }) {
2033
+ const onMessage = (event) => {
2034
+ listener(event.data);
2035
+ };
2036
+ if (worker.addEventListener) worker.addEventListener("message", onMessage, { signal });
2037
+ else {
2038
+ worker.onmessage = onMessage;
2039
+ signal?.addEventListener("abort", () => {
2040
+ worker.onmessage = null;
2041
+ }, { once: true });
2042
+ }
2043
+ }
2044
+ };
2045
+ }
2046
+ function createDefaultWorker(workerEntryUrl, options) {
2047
+ if (typeof Worker === "undefined") throw new Error("Remote DOM Worker is not available in this environment");
2048
+ if (!shouldWrapWorkerEntryUrl(workerEntryUrl)) return new Worker(workerEntryUrl, options);
2049
+ return createBlobWrappedWorker(workerEntryUrl, options);
2050
+ }
2051
+ function shouldWrapWorkerEntryUrl(workerEntryUrl) {
2052
+ if (typeof location === "undefined" || typeof Blob === "undefined" || typeof URL.createObjectURL !== "function") return false;
2053
+ try {
2054
+ return new URL(workerEntryUrl, location.href).origin !== location.origin;
2055
+ } catch {
2056
+ return false;
2057
+ }
2058
+ }
2059
+ function createBlobWrappedWorker(workerEntryUrl, options) {
2060
+ const blobUrl = URL.createObjectURL(new Blob([`import ${JSON.stringify(workerEntryUrl)};\n`], { type: "application/javascript" }));
2061
+ let worker;
2062
+ try {
2063
+ worker = new Worker(blobUrl, options);
2064
+ } catch (error) {
2065
+ URL.revokeObjectURL(blobUrl);
2066
+ throw error;
2067
+ }
2068
+ const terminate = worker.terminate.bind(worker);
2069
+ worker.terminate = () => {
2070
+ try {
2071
+ terminate();
2072
+ } finally {
2073
+ URL.revokeObjectURL(blobUrl);
2074
+ }
2075
+ };
2076
+ return worker;
2077
+ }
2078
+ function reportError(options, message, cause) {
2079
+ try {
2080
+ options.onError?.(new Error(message, cause === void 0 ? {} : { cause }));
2081
+ } catch {}
2082
+ }
2083
+ function collectCleanupErrors(cleanupSteps) {
2084
+ const errors = [];
2085
+ for (const cleanup of cleanupSteps) try {
2086
+ cleanup();
2087
+ } catch (error) {
2088
+ errors.push(error);
2089
+ }
2090
+ return errors;
2091
+ }
2092
+ function reportCleanupErrors(options, message, errors) {
2093
+ if (errors.length === 0) return;
2094
+ reportError(options, message, errors.length === 1 ? errors[0] : new AggregateError(errors, "Multiple cleanup operations failed"));
2095
+ }
2096
+ function subscriptionKey(targetId, eventName) {
2097
+ return `${targetId}:${eventName}`;
2098
+ }
2099
+ function isPromiseLike(value) {
2100
+ return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
2101
+ }
2102
+ //#endregion
2103
+ Object.defineProperty(exports, "__toESM", {
2104
+ enumerable: true,
2105
+ get: function() {
2106
+ return __toESM;
2107
+ }
2108
+ });
2109
+ Object.defineProperty(exports, "mountRemoteDomWidget", {
2110
+ enumerable: true,
2111
+ get: function() {
2112
+ return mountRemoteDomWidget;
2113
+ }
2114
+ });
2115
+
2116
+ //# sourceMappingURL=remote-dom-renderer-DUQf80Nu.cjs.map