UNPKG

65.8 kBJavaScriptView Raw
1/* Partytown 0.2.1 - MIT builder.io */
2(self => {
3 const WinIdKey = Symbol();
4 const InstanceIdKey = Symbol();
5 const NodeNameKey = Symbol();
6 const NamespaceKey = Symbol();
7 const ApplyPathKey = Symbol();
8 const InstanceStateKey = Symbol();
9 const HookContinue = Symbol();
10 const HookPrevent = Symbol();
11 const webWorkerInstances = new Map;
12 const webWorkerRefsByRefId = {};
13 const webWorkerRefIdsByRef = new WeakMap;
14 const nodeConstructors = {};
15 const envGlobalConstructors = new Map;
16 const webWorkerCtx = {};
17 const environments = {};
18 const cachedDimensions = new Map;
19 const cachedStructure = new Map;
20 const commaSplit = str => str.split(",");
21 const getterDimensionPropNames = commaSplit("clientWidth,clientHeight,clientTop,clientLeft,innerWidth,innerHeight,offsetWidth,offsetHeight,offsetTop,offsetLeft,outerWidth,outerHeight,pageXOffset,pageYOffset,scrollWidth,scrollHeight,scrollTop,scrollLeft");
22 const nodeStructurePropNames = commaSplit("childNodes,firstChild,isConnected,lastChild,nextSibling,parentElement,parentNode,previousSibling");
23 const elementStructurePropNames = commaSplit("childElementCount,children,firstElementChild,lastElementChild,nextElementSibling,previousElementSibling");
24 const structureChangingMethodNames = commaSplit("insertBefore,remove,removeChild,replaceChild");
25 const dimensionChangingSetterNames = commaSplit("className,width,height,hidden,innerHTML,innerText,textContent");
26 const dimensionChangingMethodNames = commaSplit("setAttribute,setProperty");
27 const elementGetterDimensionMethodNames = commaSplit("getClientRects,getBoundingClientRect");
28 const windowGetterDimensionMethodNames = [ "getComputedStyle" ];
29 const eventTargetMethods = commaSplit("addEventListener,dispatchEvent,removeEventListener");
30 const noop = () => true;
31 const len = obj => obj.length;
32 const getConstructorName = obj => {
33 try {
34 return obj.constructor.name;
35 } catch (e) {}
36 return "";
37 };
38 const EMPTY_ARRAY = [];
39 const randomId = () => Math.round(999999999 * Math.random() + 4);
40 const defineProperty = (obj, memberName, descriptor) => Object.defineProperty(obj, memberName, {
41 ...descriptor,
42 configurable: true
43 });
44 const defineConstructorName = (Cstr, value) => defineProperty(Cstr, "name", {
45 value: value
46 });
47 const definePrototypeProperty = (Cstr, memberName, descriptor) => defineProperty(Cstr.prototype, memberName, descriptor);
48 const definePrototypePropertyDescriptor = (Cstr, propertyDescriptorMap) => Object.defineProperties(Cstr.prototype, propertyDescriptorMap);
49 const definePrototypeValue = (Cstr, memberName, value) => definePrototypeProperty(Cstr, memberName, {
50 value: value,
51 writable: true
52 });
53 const hasInstanceStateValue = (instance, stateKey) => stateKey in instance[InstanceStateKey];
54 const getInstanceStateValue = (instance, stateKey) => instance[InstanceStateKey][stateKey];
55 const setInstanceStateValue = (instance, stateKey, stateValue) => instance[InstanceStateKey][stateKey] = stateValue;
56 const setWorkerRef = (ref, refId) => {
57 refId = webWorkerRefIdsByRef.get(ref);
58 if (!refId) {
59 webWorkerRefIdsByRef.set(ref, refId = randomId());
60 webWorkerRefsByRefId[refId] = ref;
61 }
62 return refId;
63 };
64 const logWorker = (msg, winId = -1) => {
65 try {
66 const config = webWorkerCtx.$config$;
67 if (config.logStackTraces) {
68 const frames = (new Error).stack.split("\n");
69 const i = frames.findIndex((f => f.includes("logWorker")));
70 msg += "\n" + frames.slice(i + 1).join("\n");
71 }
72 let prefix;
73 let color;
74 if (winId > -1) {
75 prefix = `Worker (${normalizedWinId(winId)}) 🎉`;
76 color = winColor(winId);
77 } else {
78 prefix = self.name;
79 color = "#9844bf";
80 }
81 if (webWorkerCtx.lastLog !== msg) {
82 webWorkerCtx.lastLog = msg;
83 console.debug.apply(console, [ `%c${prefix}`, `background: ${color}; color: white; padding: 2px 3px; border-radius: 2px; font-size: 0.8em;`, msg ]);
84 }
85 } catch (e) {}
86 };
87 const winIds = [];
88 const normalizedWinId = winId => {
89 winIds.includes(winId) || winIds.push(winId);
90 return winIds.indexOf(winId) + 1;
91 };
92 const winColor = winId => {
93 const colors = [ "#00309e", "#ea3655", "#eea727" ];
94 const index = normalizedWinId(winId) - 1;
95 return colors[index] || colors[colors.length - 1];
96 };
97 const getTargetProp = (target, applyPath) => {
98 let n = "";
99 if (target) {
100 const instanceId = target[InstanceIdKey];
101 const cstrName = getConstructorName(target);
102 if (0 === instanceId) {
103 n = "";
104 } else if (1 === instanceId) {
105 n = "document.";
106 } else if (2 === instanceId) {
107 n = "document.documentElement.";
108 } else if (3 === instanceId) {
109 n = "document.head.";
110 } else if (4 === instanceId) {
111 n = "document.body.";
112 } else if (target[NodeNameKey]) {
113 let nodeName = target[NodeNameKey];
114 n = "#text" === nodeName ? "textNode." : "#comment" === nodeName ? "commentNode." : "#document" === nodeName ? "document." : "html" === nodeName ? "doctype." : nodeName.toLowerCase() + ".";
115 } else {
116 n = 2 === target.nodeType ? "attributes." : "CanvasRenderingContext2D" === cstrName ? "context2D." : "CanvasRenderingContextWebGL" === cstrName ? "contextWebGL." : "CSSStyleDeclaration" === cstrName ? "value." : "MutationObserver" === cstrName ? "mutationObserver." : "NamedNodeMap" === cstrName ? "namedNodeMap." : "ResizeObserver" === cstrName ? "resizeObserver." : cstrName.substring(0, 1).toLowerCase() + cstrName.substring(1) + ".";
117 }
118 target[ApplyPathKey] && target[ApplyPathKey].length && (n += [ ...target[ApplyPathKey] ].join(".") + ".");
119 }
120 if (applyPath.length > 1) {
121 const first = applyPath.slice(0, applyPath.length - 1);
122 const last = applyPath[applyPath.length - 1];
123 if (!isNaN(last)) {
124 return n + `${first.join(".")}[${last}]`;
125 }
126 }
127 return n + applyPath.join(".");
128 };
129 const getLogValue = (applyPath, v) => {
130 const type = typeof v;
131 if (void 0 === v) {
132 return "undefined";
133 }
134 if ("boolean" === type || "number" === type || null == v) {
135 return JSON.stringify(v);
136 }
137 if ("string" === type) {
138 return applyPath.includes("cookie") ? JSON.stringify(v.substr(0, 10) + "...") : JSON.stringify(v.length > 50 ? v.substr(0, 40) + "..." : v);
139 }
140 if (Array.isArray(v)) {
141 return `[${v.map(getLogValue).join(", ")}]`;
142 }
143 if ("object" === type) {
144 const instanceId = v[InstanceIdKey];
145 if ("number" == typeof instanceId) {
146 if (4 === instanceId) {
147 return "<body>";
148 }
149 if (1 === instanceId) {
150 return "#document";
151 }
152 if (2 === instanceId) {
153 return "<html>";
154 }
155 if (3 === instanceId) {
156 return "<head>";
157 }
158 if (0 === instanceId) {
159 return "window";
160 }
161 if (v[NodeNameKey]) {
162 if (1 === v.nodeType) {
163 return `<${v[NodeNameKey].toLowerCase()}>`;
164 }
165 if (10 === v.nodeType) {
166 return `<!DOCTYPE ${v[NodeNameKey]}>`;
167 }
168 if (v.nodeType <= 11) {
169 return v[NodeNameKey];
170 }
171 }
172 return "¯\\_(ツ)_/¯ instance obj";
173 }
174 return v[Symbol.iterator] ? `[${Array.from(v).map((i => getLogValue(applyPath, i))).join(", ")}]` : "value" in v ? "string" == typeof v.value ? `"${v.value}"` : objToString(v.value) : objToString(v);
175 }
176 return (v => "object" == typeof v && v && v.then)(v) ? "Promise" : "function" === type ? `ƒ() ${v.name || ""}`.trim() : `¯\\_(ツ)_/¯ ${String(v)}`.trim();
177 };
178 const objToString = obj => {
179 const s = [];
180 for (let key in obj) {
181 const value = obj[key];
182 const type = typeof value;
183 "string" === type ? s.push(`${key}: "${value}"`) : "function" === type ? s.push(`${key}: Æ’`) : Array.isArray(type) ? s.push(`${key}: [..]`) : "object" === type && value ? s.push(`${key}: {..}`) : s.push(`${key}: ${String(value)}`);
184 }
185 let str = s.join(", ");
186 str.length > 200 && (str = str.substring(0, 200) + "..");
187 return `{ ${str} }`;
188 };
189 const logDimensionCacheClearMethod = (target, methodName) => {
190 (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logCalls) && logWorker(`Dimension cache cleared from method call ${methodName}()`, target[WinIdKey]);
191 };
192 const taskQueue = [];
193 let asyncMsgTimer = 0;
194 const queue = (instance, $applyPath$, callType, $assignInstanceId$, $groupedGetters$, buffer, task) => {
195 task = {
196 $winId$: instance[WinIdKey],
197 $instanceId$: instance[InstanceIdKey],
198 $applyPath$: [ ...instance[ApplyPathKey], ...$applyPath$ ],
199 $assignInstanceId$: $assignInstanceId$,
200 $groupedGetters$: $groupedGetters$
201 };
202 task.$debug$ = ((target, applyPath, callType) => {
203 let m = getTargetProp(target, applyPath);
204 1 === callType ? m += " (blocking)" : 2 === callType ? m += " (non-blocking)" : 3 === callType && (m += " (non-blocking, no-side-effect)");
205 return m.trim();
206 })(instance, $applyPath$, callType);
207 if (3 === callType) {
208 webWorkerCtx.$postMessage$([ 10, {
209 $msgId$: randomId(),
210 $tasks$: [ task ]
211 } ], buffer ? [ buffer instanceof ArrayBuffer ? buffer : buffer.buffer ] : void 0);
212 } else {
213 taskQueue.push(task);
214 buffer && console.error("buffer must be sent NonBlockingNoSideEffect");
215 if (1 === callType) {
216 return sendToMain(true);
217 }
218 asyncMsgTimer = setTimeout(sendToMain, 20);
219 }
220 };
221 const sendToMain = isBlocking => {
222 clearTimeout(asyncMsgTimer);
223 if (len(taskQueue)) {
224 webWorkerCtx.$config$.logMainAccess && logWorker(`Main access, tasks sent: ${taskQueue.length}`);
225 const endTask = taskQueue[len(taskQueue) - 1];
226 const accessReq = {
227 $msgId$: randomId(),
228 $tasks$: taskQueue.slice()
229 };
230 taskQueue.length = 0;
231 if (isBlocking) {
232 const accessRsp = ((webWorkerCtx, accessReq) => {
233 const xhr = new XMLHttpRequest;
234 xhr.open("POST", webWorkerCtx.$libPath$ + "proxytown", false);
235 xhr.send(JSON.stringify(accessReq));
236 return JSON.parse(xhr.responseText);
237 })(webWorkerCtx, accessReq);
238 const isPromise = accessRsp.$isPromise$;
239 const rtnValue = deserializeFromMain(endTask.$winId$, endTask.$instanceId$, endTask.$applyPath$, accessRsp.$rtnValue$);
240 if (accessRsp.$error$) {
241 if (isPromise) {
242 return Promise.reject(accessRsp.$error$);
243 }
244 throw new Error(accessRsp.$error$);
245 }
246 return isPromise ? Promise.resolve(rtnValue) : rtnValue;
247 }
248 webWorkerCtx.$postMessage$([ 10, accessReq ]);
249 }
250 };
251 const getter = (instance, applyPath, groupedGetters, rtnValue) => {
252 if (webWorkerCtx.$config$.get) {
253 rtnValue = webWorkerCtx.$config$.get(createHookOptions(instance, applyPath));
254 if (rtnValue !== HookContinue) {
255 return rtnValue;
256 }
257 }
258 rtnValue = queue(instance, applyPath, 1, void 0, groupedGetters);
259 ((target, applyPath, rtnValue, restrictedToWorker = false, groupedGetters = false) => {
260 if (webWorkerCtx.$config$.logGetters) {
261 try {
262 const msg = `Get ${getTargetProp(target, applyPath)}, returned: ${getLogValue(applyPath, rtnValue)}${restrictedToWorker ? " (restricted to worker)" : ""}${groupedGetters ? " (grouped getter)" : ""}`;
263 msg.includes("Symbol(") || logWorker(msg, target[WinIdKey]);
264 } catch (e) {}
265 }
266 })(instance, applyPath, rtnValue, false, !!groupedGetters);
267 return rtnValue;
268 };
269 const setter = (instance, applyPath, value, hookSetterValue) => {
270 if (webWorkerCtx.$config$.set) {
271 hookSetterValue = webWorkerCtx.$config$.set({
272 value: value,
273 prevent: HookPrevent,
274 ...createHookOptions(instance, applyPath)
275 });
276 if (hookSetterValue === HookPrevent) {
277 return;
278 }
279 hookSetterValue !== HookContinue && (value = hookSetterValue);
280 }
281 if (dimensionChangingSetterNames.some((s => applyPath.includes(s)))) {
282 cachedDimensions.clear();
283 ((target, propName) => {
284 (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logSetters) && logWorker(`Dimension cache cleared from setter "${propName}"`, target[WinIdKey]);
285 })(instance, applyPath[applyPath.length - 1]);
286 }
287 applyPath = [ ...applyPath, serializeInstanceForMain(instance, value), 0 ];
288 ((target, applyPath, value, restrictedToWorker = false) => {
289 if (webWorkerCtx.$config$.logSetters) {
290 try {
291 applyPath = applyPath.slice(0, applyPath.length - 2);
292 logWorker(`Set ${getTargetProp(target, applyPath)}, value: ${getLogValue(applyPath, value)}${restrictedToWorker ? " (restricted to worker)" : ""}`, target[WinIdKey]);
293 } catch (e) {}
294 }
295 })(instance, applyPath, value);
296 queue(instance, applyPath, 2);
297 };
298 const callMethod = (instance, applyPath, args, callType, assignInstanceId, buffer, rtnValue, methodName) => {
299 if (webWorkerCtx.$config$.apply) {
300 rtnValue = webWorkerCtx.$config$.apply({
301 args: args,
302 ...createHookOptions(instance, applyPath)
303 });
304 if (rtnValue !== HookContinue) {
305 return rtnValue;
306 }
307 }
308 methodName = applyPath[len(applyPath) - 1];
309 applyPath = [ ...applyPath, serializeInstanceForMain(instance, args) ];
310 callType = callType || 1;
311 if ("setAttribute" === methodName && hasInstanceStateValue(instance, args[0])) {
312 setInstanceStateValue(instance, args[0], args[1]);
313 } else if (structureChangingMethodNames.includes(methodName)) {
314 cachedDimensions.clear();
315 cachedStructure.clear();
316 ((target, methodName) => {
317 (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logCalls) && logWorker(`Dimension and DOM structure cache cleared from method call ${methodName}()`, target[WinIdKey]);
318 })(instance, methodName);
319 } else if (dimensionChangingMethodNames.includes(methodName)) {
320 callType = 2;
321 cachedDimensions.clear();
322 logDimensionCacheClearMethod(instance, methodName);
323 }
324 rtnValue = queue(instance, applyPath, callType, assignInstanceId, void 0, buffer);
325 ((target, applyPath, args, rtnValue) => {
326 if (webWorkerCtx.$config$.logCalls) {
327 try {
328 applyPath = applyPath.slice(0, applyPath.length - 1);
329 logWorker(`Call ${getTargetProp(target, applyPath)}(${args.map((v => getLogValue(applyPath, v))).join(", ")}), returned: ${getLogValue(applyPath, rtnValue)}`, target[WinIdKey]);
330 } catch (e) {}
331 }
332 })(instance, applyPath, args, rtnValue);
333 return rtnValue;
334 };
335 const constructGlobal = (instance, cstrName, args) => {
336 ((target, cstrName, args) => {
337 if (webWorkerCtx.$config$.logCalls) {
338 try {
339 logWorker(`Construct new ${cstrName}(${args.map((v => getLogValue([], v))).join(", ")})`, target[WinIdKey]);
340 } catch (e) {}
341 }
342 })(instance, cstrName, args);
343 queue(instance, [ 1, cstrName, serializeInstanceForMain(instance, args) ], 1);
344 };
345 const createHookOptions = (instance, applyPath) => ({
346 name: applyPath.join("."),
347 continue: HookContinue,
348 nodeName: instance[NodeNameKey],
349 constructor: getConstructorName(instance)
350 });
351 const addStorageApi = (win, storageName, items) => {
352 let getIndexByKey = key => items.findIndex((i => i[STORAGE_KEY] === key));
353 let index;
354 let item;
355 let storage = {
356 getItem(key) {
357 index = getIndexByKey(key);
358 return index > -1 ? items[index][STORAGE_VALUE] : null;
359 },
360 setItem(key, value) {
361 index = getIndexByKey(key);
362 index > -1 ? items[index][STORAGE_VALUE] = value : items.push([ key, value ]);
363 callMethod(win, [ storageName, "setItem" ], [ key, value ], 2);
364 },
365 removeItem(key) {
366 index = getIndexByKey(key);
367 index > -1 && items.splice(index, 1);
368 callMethod(win, [ storageName, "removeItem" ], [ key ], 2);
369 },
370 key(index) {
371 item = items[index];
372 return item ? item[STORAGE_KEY] : null;
373 },
374 clear() {
375 items.length = 0;
376 callMethod(win, [ storageName, "clear" ], EMPTY_ARRAY, 2);
377 },
378 get length() {
379 return items.length;
380 }
381 };
382 win[storageName] = storage;
383 };
384 const STORAGE_KEY = 0;
385 const STORAGE_VALUE = 1;
386 class WorkerProxy {
387 constructor(winId, instanceId, applyPath, nodeName, namespace) {
388 this[WinIdKey] = winId;
389 this[InstanceIdKey] = instanceId;
390 this[ApplyPathKey] = applyPath || [];
391 this[NodeNameKey] = nodeName;
392 this[InstanceStateKey] = {};
393 namespace && (this[NamespaceKey] = namespace);
394 }
395 }
396 class WorkerEventTargetProxy extends WorkerProxy {}
397 eventTargetMethods.map((methodName => WorkerEventTargetProxy.prototype[methodName] = function(...args) {
398 return callMethod(this, [ methodName ], args, 2);
399 }));
400 class WorkerTrapProxy extends WorkerProxy {
401 constructor(winId, instanceId, applyPath, nodeName) {
402 super(winId, instanceId, applyPath, nodeName);
403 return new Proxy(this, {
404 get: (instance, propName) => getter(instance, [ propName ]),
405 set(instance, propName, propValue) {
406 setter(instance, [ propName ], propValue);
407 return true;
408 }
409 });
410 }
411 }
412 const lazyLoadMedia = () => {
413 if (!self.ptm) {
414 self.ptm = [ getter, setter, callMethod, constructGlobal, definePrototypePropertyDescriptor, randomId, WorkerProxy, WorkerEventTargetProxy, WinIdKey, InstanceIdKey, ApplyPathKey ];
415 webWorkerCtx.$importScripts$(webWorkerCtx.$libPath$ + "partytown-media.js");
416 }
417 return self.ptm;
418 };
419 const htmlMedia = commaSplit("AUDIO,CANVAS,VIDEO");
420 const windowMediaConstructors = commaSplit("Audio,MediaSource");
421 const getOrCreateNodeInstance = (winId, instanceId, nodeName, namespace, instance) => {
422 instance = webWorkerInstances.get(instanceId);
423 if (!instance) {
424 instance = createNodeInstance(winId, instanceId, nodeName, namespace);
425 webWorkerInstances.set(instanceId, instance);
426 }
427 return instance;
428 };
429 const createNodeInstance = (winId, instanceId, nodeName, namespace) => {
430 htmlMedia.includes(nodeName) && lazyLoadMedia();
431 const NodeCstr = nodeConstructors[nodeName] ? nodeConstructors[nodeName] : nodeName.includes("-") ? nodeConstructors.UNKNOWN : self.HTMLElement;
432 return new NodeCstr(winId, instanceId, [], nodeName, namespace);
433 };
434 const runScriptContent = (env, instanceId, scriptContent, winId, errorMsg) => {
435 try {
436 webWorkerCtx.$config$.logScriptExecution && logWorker(`Execute script (${instanceId}): ${scriptContent.substr(0, 100).split("\n").map((l => l.trim())).join(" ").trim().substr(0, 60)}...`, winId);
437 env.$currentScriptId$ = instanceId;
438 run(env, scriptContent);
439 } catch (contentError) {
440 console.error(scriptContent, contentError);
441 errorMsg = String(contentError.stack || contentError);
442 }
443 env.$currentScriptId$ = -1;
444 return errorMsg;
445 };
446 const run = (env, scriptContent, scriptUrl) => new Function(`with(this){${scriptContent.replace(/\bthis\b/g, "thi$(this)").replace(/\/\/# so/g, "//Xso")};function thi$(t){return t===this?window:t}}` + (scriptUrl ? "\n//# sourceURL=" + scriptUrl : "")).call(env.$window$);
447 const runStateLoadHandlers = (instance, type, handlers) => {
448 handlers = getInstanceStateValue(instance, type);
449 handlers && setTimeout((() => handlers.map((cb => cb({
450 type: type
451 })))));
452 };
453 const resolveToUrl = (env, url, noUserHook, baseLocation) => {
454 baseLocation = env.$location$;
455 while (!baseLocation.host) {
456 env = environments[env.$parentWinId$];
457 baseLocation = env.$location$;
458 if (env.$winId$ === env.$parentWinId$) {
459 break;
460 }
461 }
462 const resolvedUrl = new URL(url || "", baseLocation);
463 if (!noUserHook && webWorkerCtx.$config$.resolveUrl) {
464 const configResolvedUrl = webWorkerCtx.$config$.resolveUrl(resolvedUrl, baseLocation);
465 if (configResolvedUrl) {
466 return configResolvedUrl;
467 }
468 }
469 return resolvedUrl;
470 };
471 const resolveUrl = (env, url, noUserHook) => resolveToUrl(env, url, noUserHook) + "";
472 const getUrl = elm => resolveToUrl(getEnv(elm), getInstanceStateValue(elm, 4));
473 const getPartytownScript = () => `<script src=${JSON.stringify(webWorkerCtx.$libPath$ + "partytown.js")} async><\/script>`;
474 const createImageConstructor = env => class HTMLImageElement {
475 constructor() {
476 this.s = "";
477 this.l = [];
478 this.e = [];
479 }
480 get src() {
481 return this.s;
482 }
483 set src(src) {
484 webWorkerCtx.$config$.logImageRequests && logWorker(`Image() request: ${resolveUrl(env, src)}`, env.$winId$);
485 fetch(resolveUrl(env, src, true), {
486 mode: "no-cors",
487 keepalive: true
488 }).then((rsp => {
489 rsp.ok || 0 === rsp.status ? this.l.map((cb => cb({
490 type: "load"
491 }))) : this.e.map((cb => cb({
492 type: "error"
493 })));
494 }), (() => this.e.forEach((cb => cb({
495 type: "error"
496 })))));
497 }
498 addEventListener(eventName, cb) {
499 "load" === eventName && this.l.push(cb);
500 "error" === eventName && this.e.push(cb);
501 }
502 get onload() {
503 return this.l[0];
504 }
505 set onload(cb) {
506 this.l = [ cb ];
507 }
508 get onerror() {
509 return this.e[0];
510 }
511 set onerror(cb) {
512 this.e = [ cb ];
513 }
514 };
515 class Location extends URL {
516 assign() {
517 logWorker("location.assign(), noop");
518 }
519 reload() {
520 logWorker("location.reload(), noop");
521 }
522 replace() {
523 logWorker("location.replace(), noop");
524 }
525 }
526 class Window extends WorkerProxy {
527 constructor($winId$, $parentWinId$, url) {
528 super($winId$, 0);
529 let _this = this;
530 let globalName;
531 let value;
532 let win;
533 for (globalName in self) {
534 if (!(globalName in _this) && "onmessage" !== globalName) {
535 value = self[globalName];
536 if (null != value) {
537 const isFunction = "function" == typeof value && !value.toString().startsWith("class");
538 _this[globalName] = isFunction ? value.bind(self) : value;
539 }
540 }
541 }
542 Object.getOwnPropertyNames(self).map((globalName => {
543 globalName in _this || (_this[globalName] = self[globalName]);
544 }));
545 envGlobalConstructors.forEach(((GlobalCstr, cstrName) => {
546 _this[cstrName] = defineConstructorName(class {
547 constructor(...args) {
548 const instance = new GlobalCstr($winId$, randomId());
549 constructGlobal(instance, cstrName, args);
550 return instance;
551 }
552 }, cstrName);
553 }));
554 windowMediaConstructors.map((cstrName => defineProperty(_this, cstrName, {
555 get() {
556 delete _this[cstrName];
557 const initMediaConstructors = lazyLoadMedia();
558 const initMediaConstructor = initMediaConstructors[cstrName];
559 return _this[cstrName] = initMediaConstructor(getEnv(_this), _this, cstrName);
560 }
561 })));
562 "trustedTypes" in self && (_this.trustedTypes = self.trustedTypes);
563 win = new Proxy(_this, {
564 has: () => true
565 });
566 environments[$winId$] = {
567 $winId$: $winId$,
568 $parentWinId$: $parentWinId$,
569 $window$: win,
570 $document$: createNodeInstance($winId$, 1, "#document"),
571 $documentElement$: createNodeInstance($winId$, 2, "HTML"),
572 $head$: createNodeInstance($winId$, 3, "HEAD"),
573 $body$: createNodeInstance($winId$, 4, "BODY"),
574 $location$: new Location(url)
575 };
576 _this.requestAnimationFrame = cb => setTimeout((() => cb(performance.now())), 9);
577 _this.cancelAnimationFrame = id => clearTimeout(id);
578 _this.requestIdleCallback = (cb, start) => {
579 start = Date.now();
580 return setTimeout((() => cb({
581 didTimeout: false,
582 timeRemaining: () => Math.max(0, 50 - (Date.now() - start))
583 })), 1);
584 };
585 _this.cancelIdleCallback = id => clearTimeout(id);
586 addStorageApi(_this, "localStorage", webWorkerCtx.$localStorage$);
587 addStorageApi(_this, "sessionStorage", webWorkerCtx.$sessionStorage$);
588 _this.Worker = void 0;
589 return win;
590 }
591 get body() {
592 return getEnv(this).$body$;
593 }
594 get document() {
595 return getEnv(this).$document$;
596 }
597 get documentElement() {
598 return getEnv(this).$documentElement$;
599 }
600 fetch(input, init) {
601 input = "string" == typeof input || input instanceof URL ? String(input) : input.url;
602 return fetch(resolveUrl(getEnv(this), input), init);
603 }
604 get frameElement() {
605 const env = getEnv(this);
606 const parentWinId = env.$parentWinId$;
607 const winId = env.$winId$;
608 return winId === parentWinId ? null : getOrCreateNodeInstance(parentWinId, winId, "IFRAME");
609 }
610 get globalThis() {
611 return this;
612 }
613 get head() {
614 return getEnv(this).$head$;
615 }
616 get location() {
617 return getEnv(this).$location$;
618 }
619 set location(loc) {
620 getEnv(this).$location$.href = loc + "";
621 }
622 get Image() {
623 return createImageConstructor(getEnv(this));
624 }
625 get name() {
626 return name + `${normalizedWinId(this[WinIdKey])} (${this[WinIdKey]})`;
627 }
628 get navigator() {
629 return (env => {
630 const navigator = self.navigator;
631 navigator.sendBeacon = (url, body) => {
632 if (webWorkerCtx.$config$.logSendBeaconRequests) {
633 try {
634 logWorker(`sendBeacon: ${resolveUrl(env, url, true)}${body ? ", data: " + JSON.stringify(body) : ""}`);
635 } catch (e) {
636 console.error(e);
637 }
638 }
639 try {
640 fetch(resolveUrl(env, url, true), {
641 method: "POST",
642 body: body,
643 mode: "no-cors",
644 keepalive: true
645 });
646 return true;
647 } catch (e) {
648 console.error(e);
649 return false;
650 }
651 };
652 return navigator;
653 })(getEnv(this));
654 }
655 get origin() {
656 return getEnv(this).$location$.origin;
657 }
658 get parent() {
659 return environments[getEnv(this).$parentWinId$].$window$;
660 }
661 get self() {
662 return this;
663 }
664 get top() {
665 for (let envWinId in environments) {
666 if (environments[envWinId].$winId$ === environments[envWinId].$parentWinId$) {
667 return environments[envWinId].$window$;
668 }
669 }
670 }
671 get window() {
672 return this;
673 }
674 }
675 const createEnvironment = ({$winId$: $winId$, $parentWinId$: $parentWinId$, $url$: $url$}) => {
676 if (environments[$winId$]) {
677 environments[$winId$].$location$.href = $url$;
678 } else {
679 new Window($winId$, $parentWinId$, $url$);
680 {
681 const winType = $winId$ === $parentWinId$ ? "top" : "iframe";
682 logWorker(`Created ${winType} window ${normalizedWinId($winId$)} environment (${$winId$})`, $winId$);
683 }
684 }
685 webWorkerCtx.$postMessage$([ 6, $winId$ ]);
686 return environments[$winId$];
687 };
688 const getEnv = instance => environments[instance[WinIdKey]];
689 const HTMLSrcElementDescriptorMap = {
690 addEventListener: {
691 value(...args) {
692 const eventName = args[0];
693 const callbacks = getInstanceStateValue(this, eventName) || [];
694 callbacks.push(args[1]);
695 setInstanceStateValue(this, eventName, callbacks);
696 }
697 },
698 async: {
699 get: noop,
700 set: noop
701 },
702 defer: {
703 get: noop,
704 set: noop
705 },
706 onload: {
707 get() {
708 let callbacks = getInstanceStateValue(this, "load");
709 return callbacks && callbacks[0] || null;
710 },
711 set(cb) {
712 setInstanceStateValue(this, "load", cb ? [ cb ] : null);
713 }
714 },
715 onerror: {
716 get() {
717 let callbacks = getInstanceStateValue(this, "error");
718 return callbacks && callbacks[0] || null;
719 },
720 set(cb) {
721 setInstanceStateValue(this, "error", cb ? [ cb ] : null);
722 }
723 }
724 };
725 const innerHTMLDescriptor = {
726 get() {
727 return getInstanceStateValue(this, 3) || "";
728 },
729 set(scriptContent) {
730 setInstanceStateValue(this, 3, scriptContent);
731 }
732 };
733 const HTMLScriptDescriptorMap = {
734 innerHTML: innerHTMLDescriptor,
735 innerText: innerHTMLDescriptor,
736 src: {
737 get() {
738 return getInstanceStateValue(this, 4) || "";
739 },
740 set(url) {
741 const env = getEnv(this);
742 const orgUrl = resolveUrl(env, url, true);
743 url = resolveUrl(env, url);
744 setInstanceStateValue(this, 4, url);
745 setter(this, [ "src" ], url);
746 orgUrl !== url && setter(this, [ "dataset", "ptsrc" ], orgUrl);
747 }
748 },
749 getAttribute: {
750 value(attrName) {
751 return "src" === attrName ? this.src : callMethod(this, [ "getAttribute" ], [ attrName ]);
752 }
753 },
754 setAttribute: {
755 value(attrName, attrValue) {
756 scriptAttrPropNames.includes(attrName) ? this[attrName] = attrValue : callMethod(this, [ "setAttribute" ], [ attrName, attrValue ]);
757 }
758 },
759 textContent: innerHTMLDescriptor,
760 type: {
761 get() {
762 return getter(this, [ "type" ]);
763 },
764 set(type) {
765 if (!isScriptJsType(type)) {
766 setInstanceStateValue(this, 5, type);
767 setter(this, [ "type" ], type);
768 }
769 }
770 },
771 ...HTMLSrcElementDescriptorMap
772 };
773 const isScriptJsType = scriptType => !scriptType || "text/javascript" === scriptType;
774 const scriptAttrPropNames = commaSplit("src,type");
775 class Node extends WorkerProxy {
776 appendChild(node) {
777 return this.insertBefore(node, null);
778 }
779 get href() {}
780 set href(_) {}
781 insertBefore(newNode, referenceNode) {
782 const winId = newNode[WinIdKey] = this[WinIdKey];
783 const instanceId = newNode[InstanceIdKey];
784 const nodeName = newNode[NodeNameKey];
785 const isScript = "SCRIPT" === nodeName;
786 const isIFrame = "IFRAME" === nodeName;
787 if (isScript) {
788 const scriptContent = getInstanceStateValue(newNode, 3);
789 const scriptType = getInstanceStateValue(newNode, 5);
790 if (scriptContent) {
791 if (isScriptJsType(scriptType)) {
792 const errorMsg = runScriptContent(getEnv(newNode), instanceId, scriptContent, winId, "");
793 const datasetType = errorMsg ? "pterror" : "ptid";
794 const datasetValue = errorMsg || instanceId;
795 setter(newNode, [ "type" ], "text/partytown-x");
796 setter(newNode, [ "dataset", datasetType ], datasetValue);
797 }
798 setter(newNode, [ "innerHTML" ], scriptContent);
799 }
800 }
801 callMethod(this, [ "insertBefore" ], [ newNode, referenceNode ]);
802 isIFrame && ((winId, iframe) => {
803 let i = 0;
804 let type;
805 let handlers;
806 setter(iframe, [ "dataset", "ptwindow" ], winId);
807 const callback = () => {
808 if (environments[winId] && environments[winId].$isInitialized$) {
809 type = getInstanceStateValue(iframe, 1) ? "error" : "load";
810 handlers = getInstanceStateValue(iframe, type);
811 handlers && handlers.map((handler => handler({
812 type: type
813 })));
814 } else if (i++ > 2e3) {
815 handlers = getInstanceStateValue(iframe, "error");
816 handlers && handlers.map((handler => handler({
817 type: "error"
818 })));
819 } else {
820 setTimeout(callback, 9);
821 }
822 };
823 callback();
824 })(instanceId, newNode);
825 if (isScript) {
826 sendToMain(true);
827 webWorkerCtx.$postMessage$([ 6, winId ]);
828 }
829 return newNode;
830 }
831 get nodeName() {
832 return this[NodeNameKey];
833 }
834 get nodeType() {
835 return 3;
836 }
837 get ownerDocument() {
838 return getEnv(this).$document$;
839 }
840 }
841 class Attr {
842 constructor(serializedAttr) {
843 this.name = serializedAttr[0];
844 this.value = serializedAttr[1];
845 }
846 get nodeName() {
847 return this.name;
848 }
849 get nodeType() {
850 return 2;
851 }
852 }
853 class CSSStyleDeclaration extends WorkerProxy {
854 constructor(winId, instanceId, applyPath, styles) {
855 super(winId, instanceId, applyPath);
856 Object.assign(this, styles);
857 return new Proxy(this, {
858 get: (target, propName) => target[propName],
859 set(target, propName, propValue) {
860 setter(target, [ propName ], propValue);
861 ((target, propName) => {
862 (webWorkerCtx.$config$.logGetters || webWorkerCtx.$config$.logSetters) && logWorker(`Dimension cache cleared from style.${propName} setter`, target[WinIdKey]);
863 })(target, propName);
864 cachedDimensions.clear();
865 return true;
866 }
867 });
868 }
869 getPropertyValue(propName) {
870 return this[propName];
871 }
872 setProperty(propName, propValue) {
873 this[propName] = propValue;
874 }
875 }
876 class NodeList {
877 constructor(nodes) {
878 (this._ = nodes).map(((node, index) => this[index] = node));
879 }
880 entries() {
881 return this._.entries();
882 }
883 forEach(cb, thisArg) {
884 this._.map(cb, thisArg);
885 }
886 item(index) {
887 return this[index];
888 }
889 keys() {
890 return this._.keys();
891 }
892 get length() {
893 return len(this._);
894 }
895 values() {
896 return this._.values();
897 }
898 [Symbol.iterator]() {
899 return this._[Symbol.iterator]();
900 }
901 }
902 const serializeForMain = ($winId$, $instanceId$, value, added, type) => void 0 !== value && (type = typeof value) ? "string" === type || "boolean" === type || "number" === type || null == value ? [ 0, value ] : "function" === type ? [ 4, {
903 $winId$: $winId$,
904 $instanceId$: $instanceId$,
905 $refId$: setWorkerRef(value)
906 } ] : (added = added || new Set) && Array.isArray(value) ? added.has(value) ? [ 1, [] ] : added.add(value) && [ 1, value.map((v => serializeForMain($winId$, $instanceId$, v, added))) ] : "object" === type ? "number" == typeof value[InstanceIdKey] ? [ 3, {
907 $winId$: value[WinIdKey],
908 $instanceId$: value[InstanceIdKey]
909 } ] : value instanceof Event ? [ 5, serializeObjectForMain($winId$, $instanceId$, value, false, added) ] : supportsTrustedHTML && value instanceof TrustedHTML ? [ 0, value.toString() ] : value instanceof ArrayBuffer ? [ 8, value ] : ArrayBuffer.isView(value) ? [ 9, value.buffer, getConstructorName(value) ] : [ 2, serializeObjectForMain($winId$, $instanceId$, value, true, added) ] : void 0 : value;
910 const supportsTrustedHTML = "undefined" != typeof TrustedHTML;
911 const serializeObjectForMain = (winId, instanceId, obj, includeFunctions, added, serializedObj, propName, propValue) => {
912 serializedObj = {};
913 if (!added.has(obj)) {
914 added.add(obj);
915 for (propName in obj) {
916 propValue = obj[propName];
917 (includeFunctions || "function" != typeof propValue) && (serializedObj[propName] = serializeForMain(winId, instanceId, propValue, added));
918 }
919 }
920 return serializedObj;
921 };
922 const serializeInstanceForMain = (instance, value) => instance ? serializeForMain(instance[WinIdKey], instance[InstanceIdKey], value) : [ 0, value ];
923 const deserializeFromMain = (winId, instanceId, applyPath, serializedValueTransfer, serializedType, serializedValue, obj, key) => {
924 if (serializedValueTransfer) {
925 serializedType = serializedValueTransfer[0];
926 serializedValue = serializedValueTransfer[1];
927 if (0 === serializedType || 11 === serializedType || 12 === serializedType) {
928 return serializedValue;
929 }
930 if (4 === serializedType) {
931 return deserializeRefFromMain(applyPath, serializedValue);
932 }
933 if (6 === serializedType) {
934 return noop;
935 }
936 if (3 === serializedType) {
937 return getOrCreateSerializedInstance(serializedValue);
938 }
939 if (7 === serializedType) {
940 return new NodeList(serializedValue.map(getOrCreateSerializedInstance));
941 }
942 if (10 === serializedType) {
943 return new Attr(serializedValue);
944 }
945 if (1 === serializedType) {
946 return serializedValue.map((v => deserializeFromMain(winId, instanceId, applyPath, v)));
947 }
948 obj = {};
949 for (key in serializedValue) {
950 obj[key] = deserializeFromMain(winId, instanceId, [ ...applyPath, key ], serializedValue[key]);
951 }
952 if (13 === serializedType) {
953 return new CSSStyleDeclaration(winId, instanceId, applyPath, obj);
954 }
955 if (5 === serializedType) {
956 return (eventProps => new Proxy(new Event(eventProps.type, eventProps), {
957 get: (target, propName) => propName in eventProps ? eventProps[propName] : target[String(propName)]
958 }))(obj);
959 }
960 if (2 === serializedType) {
961 return obj;
962 }
963 }
964 };
965 const getOrCreateSerializedInstance = ({$winId$: $winId$, $instanceId$: $instanceId$, $nodeName$: $nodeName$}) => getPlatformInstance($winId$, $instanceId$) || getOrCreateNodeInstance($winId$, $instanceId$, $nodeName$);
966 const getPlatformInstance = (winId, instanceId) => {
967 const env = environments[winId];
968 return 0 === instanceId ? env.$window$ : 1 === instanceId ? env.$document$ : 2 === instanceId ? env.$documentElement$ : 3 === instanceId ? env.$head$ : 4 === instanceId ? env.$body$ : void 0;
969 };
970 const deserializeRefFromMain = (applyPath, {$winId$: $winId$, $instanceId$: $instanceId$, $nodeName$: $nodeName$, $refId$: $refId$}) => {
971 webWorkerRefsByRefId[$refId$] || webWorkerRefIdsByRef.set(webWorkerRefsByRefId[$refId$] = function(...args) {
972 const instance = getOrCreateNodeInstance($winId$, $instanceId$, $nodeName$);
973 return callMethod(instance, applyPath, args);
974 }, $refId$);
975 return webWorkerRefsByRefId[$refId$];
976 };
977 const HTMLStyleDescriptorMap = {
978 sheet: {
979 get() {
980 return new CSSStyleSheet(this);
981 }
982 }
983 };
984 class CSSStyleSheet {
985 constructor(ownerNode) {
986 this.ownerNode = ownerNode;
987 }
988 get cssRules() {
989 const ownerNode = this.ownerNode;
990 return new Proxy({}, {
991 get(target, propKey) {
992 const propName = String(propKey);
993 return "item" === propName ? index => getCssRule(ownerNode, index) : "length" === propName ? getCssRules(ownerNode).length : isNaN(propName) ? target[propKey] : getCssRule(ownerNode, propName);
994 }
995 });
996 }
997 insertRule(ruleText, index) {
998 const cssRules = getCssRules(this.ownerNode);
999 index = void 0 === index ? 0 : index;
1000 if (index >= 0 && index <= cssRules.length) {
1001 callMethod(this.ownerNode, [ "sheet", "insertRule" ], [ ruleText, index ]);
1002 cssRules.splice(index, 0, 0);
1003 }
1004 logDimensionCacheClearMethod(this.ownerNode, "insertRule");
1005 cachedDimensions.clear();
1006 return index;
1007 }
1008 deleteRule(index) {
1009 callMethod(this.ownerNode, [ "sheet", "deleteRule" ], [ index ]);
1010 getCssRules(this.ownerNode).splice(index, 1);
1011 logDimensionCacheClearMethod(this.ownerNode, "deleteRule");
1012 cachedDimensions.clear();
1013 }
1014 }
1015 const getCssRules = (ownerNode, cssRules) => {
1016 cssRules = getInstanceStateValue(ownerNode, 2);
1017 if (!cssRules) {
1018 cssRules = getter(ownerNode, [ "sheet", "cssRules" ]);
1019 setInstanceStateValue(ownerNode, 2, cssRules);
1020 }
1021 return cssRules;
1022 };
1023 const getCssRule = (ownerNode, index, cssRules) => {
1024 cssRules = getCssRules(ownerNode);
1025 0 === cssRules[index] && (cssRules[index] = getter(ownerNode, [ "sheet", "cssRules", parseInt(index, 10) ]));
1026 return cssRules[index];
1027 };
1028 const DocumentDescriptorMap = {
1029 body: {
1030 get() {
1031 return getEnv(this).$body$;
1032 }
1033 },
1034 createElement: {
1035 value(tagName) {
1036 tagName = tagName.toUpperCase();
1037 const winId = this[WinIdKey];
1038 const instanceId = randomId();
1039 const elm = getOrCreateNodeInstance(winId, instanceId, tagName);
1040 callMethod(this, [ "createElement" ], [ tagName ], 2, instanceId);
1041 if ("IFRAME" === tagName) {
1042 const env = createEnvironment({
1043 $winId$: instanceId,
1044 $parentWinId$: winId,
1045 $url$: "about:blank"
1046 });
1047 env.$window$.fetch = fetch;
1048 setter(elm, [ "srcdoc" ], getPartytownScript());
1049 } else if ("SCRIPT" === tagName) {
1050 const scriptType = getInstanceStateValue(elm, 5);
1051 isScriptJsType(scriptType) && setter(elm, [ "type" ], "text/partytown");
1052 }
1053 return elm;
1054 }
1055 },
1056 createElementNS: {
1057 value(namespace, tagName) {
1058 tagName = tagName.toLowerCase();
1059 const winId = this[WinIdKey];
1060 const instanceId = randomId();
1061 const nsElm = getOrCreateNodeInstance(winId, instanceId, tagName, namespace);
1062 callMethod(this, [ "createElementNS" ], [ namespace, tagName ], 2, instanceId);
1063 return nsElm;
1064 }
1065 },
1066 createTextNode: {
1067 value(text) {
1068 const winId = this[WinIdKey];
1069 const instanceId = randomId();
1070 const textNode = getOrCreateNodeInstance(winId, instanceId, "#text");
1071 callMethod(this, [ "createTextNode" ], [ text ], 2, instanceId);
1072 return textNode;
1073 }
1074 },
1075 createEvent: {
1076 value: type => new Event(type)
1077 },
1078 currentScript: {
1079 get() {
1080 const winId = this[WinIdKey];
1081 const currentScriptId = getEnv(this).$currentScriptId$;
1082 return currentScriptId > 0 ? getOrCreateNodeInstance(winId, currentScriptId, "SCRIPT") : null;
1083 }
1084 },
1085 defaultView: {
1086 get() {
1087 return (instance => getEnv(instance).$window$)(this);
1088 }
1089 },
1090 documentElement: {
1091 get() {
1092 return getEnv(this).$documentElement$;
1093 }
1094 },
1095 getElementsByTagName: {
1096 value(tagName) {
1097 tagName = tagName.toUpperCase();
1098 return "BODY" === tagName ? [ getEnv(this).$body$ ] : "HEAD" === tagName ? [ getEnv(this).$head$ ] : callMethod(this, [ "getElementsByTagName" ], [ tagName ]);
1099 }
1100 },
1101 head: {
1102 get() {
1103 return getEnv(this).$head$;
1104 }
1105 },
1106 implementation: {
1107 value: {
1108 hasFeature: noop
1109 }
1110 },
1111 location: {
1112 get() {
1113 return getEnv(this).$location$;
1114 },
1115 set(url) {
1116 getEnv(this).$location$.href = url + "";
1117 }
1118 },
1119 nodeType: {
1120 value: 9
1121 },
1122 parentNode: {
1123 value: null
1124 },
1125 parentElement: {
1126 value: null
1127 },
1128 readyState: {
1129 value: "complete"
1130 }
1131 };
1132 const DocumentElementChildDescriptorMap = {
1133 parentElement: {
1134 get() {
1135 return this.parentNode;
1136 }
1137 },
1138 parentNode: {
1139 get() {
1140 return getEnv(this).$documentElement$;
1141 }
1142 }
1143 };
1144 const DocumentElementDescriptorMap = {
1145 parentElement: {
1146 value: null
1147 },
1148 parentNode: {
1149 get() {
1150 return getEnv(this).$document$;
1151 }
1152 }
1153 };
1154 const ElementDescriptorMap = {
1155 localName: {
1156 get() {
1157 return this[NodeNameKey].toLowerCase();
1158 }
1159 },
1160 namespaceURI: {
1161 get() {
1162 return this[NamespaceKey] || "http://www.w3.org/1999/xhtml";
1163 }
1164 },
1165 nodeType: {
1166 value: 1
1167 },
1168 tagName: {
1169 get() {
1170 return this[NodeNameKey];
1171 }
1172 }
1173 };
1174 const HTMLAnchorDescriptorMap = {
1175 hash: {
1176 get() {
1177 return getUrl(this).hash;
1178 }
1179 },
1180 host: {
1181 get() {
1182 return getUrl(this).host;
1183 }
1184 },
1185 hostname: {
1186 get() {
1187 return getUrl(this).hostname;
1188 }
1189 },
1190 href: {
1191 get() {
1192 return getUrl(this).href;
1193 },
1194 set(href) {
1195 href += "";
1196 setInstanceStateValue(this, 4, href);
1197 setter(this, [ "href" ], href);
1198 }
1199 },
1200 origin: {
1201 get() {
1202 return getUrl(this).origin;
1203 }
1204 },
1205 pathname: {
1206 get() {
1207 return getUrl(this).pathname;
1208 }
1209 },
1210 port: {
1211 get() {
1212 return getUrl(this).port;
1213 }
1214 },
1215 protocol: {
1216 get() {
1217 return getUrl(this).protocol;
1218 }
1219 },
1220 search: {
1221 get() {
1222 return getUrl(this).search;
1223 }
1224 }
1225 };
1226 const HTMLIFrameDescriptorMap = {
1227 contentDocument: {
1228 get() {
1229 return this.contentWindow.document;
1230 }
1231 },
1232 contentWindow: {
1233 get() {
1234 const iframeContentWinId = this[InstanceIdKey];
1235 const env = environments[iframeContentWinId];
1236 return env.$window$;
1237 }
1238 },
1239 src: {
1240 get() {
1241 return getInstanceStateValue(this, 4) || "";
1242 },
1243 set(url) {
1244 let xhr = new XMLHttpRequest;
1245 let xhrStatus;
1246 url = resolveUrl(getEnv(this), url);
1247 setInstanceStateValue(this, 1, void 0);
1248 setInstanceStateValue(this, 4, url);
1249 xhr.open("GET", url, false);
1250 xhr.send();
1251 xhrStatus = xhr.status;
1252 xhrStatus > 199 && xhrStatus < 300 ? setter(this, [ "srcdoc" ], ((url, html) => `<base href="${url}">` + html.replace(/<script>/g, '<script type="text/partytown">').replace(/<script /g, '<script type="text/partytown" ').replace(/text\/javascript/g, "text/partytown") + getPartytownScript())(url, xhr.responseText)) : setInstanceStateValue(this, 1, xhrStatus);
1253 }
1254 },
1255 ...HTMLSrcElementDescriptorMap
1256 };
1257 const defineWorkerInterface = ([cstrName, superCstrName, members, interfaceType, nodeName]) => {
1258 const SuperCstr = TrapConstructors[cstrName] ? WorkerTrapProxy : "EventTarget" === superCstrName ? WorkerEventTargetProxy : "Object" === superCstrName ? WorkerProxy : self[superCstrName];
1259 const Cstr = self[cstrName] = defineConstructorName(self[cstrName] || class extends SuperCstr {}, cstrName);
1260 12 === interfaceType && envGlobalConstructors.set(cstrName, Cstr);
1261 nodeName && (nodeConstructors[nodeName] = Cstr);
1262 members.map((([memberName, memberType, staticValue]) => {
1263 memberName in Cstr.prototype || memberName in SuperCstr.prototype || ("string" == typeof memberType ? definePrototypeProperty(Cstr, memberName, {
1264 get() {
1265 if (!hasInstanceStateValue(this, memberName)) {
1266 const winId = this[WinIdKey];
1267 const instanceId = this[InstanceIdKey];
1268 const applyPath = [ ...this[ApplyPathKey], memberName ];
1269 const nodeName = this[NodeNameKey];
1270 const PropCstr = self[memberType];
1271 setInstanceStateValue(this, memberName, new PropCstr(winId, instanceId, applyPath, nodeName));
1272 }
1273 return getInstanceStateValue(this, memberName);
1274 },
1275 set(value) {
1276 setInstanceStateValue(this, memberName, value);
1277 }
1278 }) : 5 === memberType ? definePrototypeValue(Cstr, memberName, (function(...args) {
1279 return callMethod(this, [ memberName ], args);
1280 })) : memberType > 0 && (void 0 !== staticValue ? definePrototypeValue(Cstr, memberName, staticValue) : definePrototypeProperty(Cstr, memberName, {
1281 get() {
1282 return getter(this, [ memberName ]);
1283 },
1284 set(value) {
1285 return setter(this, [ memberName ], value);
1286 }
1287 })));
1288 }));
1289 };
1290 const TrapConstructors = {
1291 CSSStyleDeclaration: 1,
1292 DOMStringMap: 1,
1293 NamedNodeMap: 1
1294 };
1295 const definePrototypeNodeType = (Cstr, nodeType) => definePrototypeValue(Cstr, "nodeType", nodeType);
1296 const cachedTreeProps = (Cstr, treeProps) => treeProps.map((propName => definePrototypeProperty(Cstr, propName, {
1297 get() {
1298 let cacheKey = getInstanceCacheKey(this, propName);
1299 let result = cachedStructure.get(cacheKey);
1300 if (!result) {
1301 result = getter(this, [ propName ]);
1302 cachedStructure.set(cacheKey, result);
1303 }
1304 return result;
1305 }
1306 })));
1307 const getInstanceCacheKey = (instance, memberName, args) => [ instance[WinIdKey], instance[InstanceIdKey], memberName, ...(args || EMPTY_ARRAY).map((arg => String(arg && arg[WinIdKey] ? arg[InstanceIdKey] : arg))) ].join(".");
1308 const cachedProps = (Cstr, propNames) => commaSplit(propNames).map((propName => definePrototypeProperty(Cstr, propName, {
1309 get() {
1310 hasInstanceStateValue(this, propName) || setInstanceStateValue(this, propName, getter(this, [ propName ]));
1311 return getInstanceStateValue(this, propName);
1312 },
1313 set(val) {
1314 getInstanceStateValue(this, propName) !== val && setter(this, [ propName ], val);
1315 setInstanceStateValue(this, propName, val);
1316 }
1317 })));
1318 const constantProps = (Cstr, props) => Object.keys(props).map((propName => definePrototypeValue(Cstr, propName, props[propName])));
1319 const cachedDimensionProps = Cstr => getterDimensionPropNames.map((propName => definePrototypeProperty(Cstr, propName, {
1320 get() {
1321 const dimension = cachedDimensions.get(getInstanceCacheKey(this, propName));
1322 if ("number" == typeof dimension) {
1323 return dimension;
1324 }
1325 const groupedDimensions = getter(this, [ propName ], getterDimensionPropNames);
1326 if (groupedDimensions && "object" == typeof groupedDimensions) {
1327 Object.entries(groupedDimensions).map((([dimensionPropName, value]) => cachedDimensions.set(getInstanceCacheKey(this, dimensionPropName), value)));
1328 return groupedDimensions[propName];
1329 }
1330 return groupedDimensions;
1331 }
1332 })));
1333 const cachedDimensionMethods = (Cstr, dimensionMethodNames) => dimensionMethodNames.map((methodName => {
1334 Cstr.prototype[methodName] = function(...args) {
1335 let cacheKey = getInstanceCacheKey(this, methodName, args);
1336 let dimensions = cachedDimensions.get(cacheKey);
1337 if (!dimensions) {
1338 dimensions = callMethod(this, [ methodName ], args);
1339 cachedDimensions.set(cacheKey, dimensions);
1340 }
1341 return dimensions;
1342 };
1343 }));
1344 class Performance extends WorkerProxy {
1345 now() {
1346 return performance.now();
1347 }
1348 }
1349 const initWebWorker = initWebWorkerData => {
1350 const config = webWorkerCtx.$config$ = JSON.parse(initWebWorkerData.$config$);
1351 [ "resolveUrl", "get", "set", "apply" ].map((configName => {
1352 config[configName] && (config[configName] = new Function("return " + config[configName])());
1353 }));
1354 webWorkerCtx.$importScripts$ = importScripts.bind(self);
1355 webWorkerCtx.$libPath$ = initWebWorkerData.$libPath$;
1356 webWorkerCtx.$localStorage$ = initWebWorkerData.$localStorage$;
1357 webWorkerCtx.$sessionStorage$ = initWebWorkerData.$sessionStorage$;
1358 webWorkerCtx.$postMessage$ = postMessage.bind(self);
1359 webWorkerCtx.$sharedDataBuffer$ = initWebWorkerData.$sharedDataBuffer$;
1360 self.postMessage = self.importScripts = void 0;
1361 self.Node = Node;
1362 self.Window = Window;
1363 self.CSSStyleSheet = CSSStyleSheet;
1364 self.Performance = Performance;
1365 initWebWorkerData.$interfaces$.map(defineWorkerInterface);
1366 (() => {
1367 const Document = self.Document;
1368 const DocumentFragment = self.DocumentFragment;
1369 const Element = self.Element;
1370 commaSplit("atob,btoa,crypto,indexedDB,setTimeout,setInterval,clearTimeout,clearInterval").map((memberName => delete Window.prototype[memberName]));
1371 definePrototypePropertyDescriptor(Element, ElementDescriptorMap);
1372 definePrototypePropertyDescriptor(Document, DocumentDescriptorMap);
1373 definePrototypePropertyDescriptor(self.HTMLAnchorElement, HTMLAnchorDescriptorMap);
1374 definePrototypePropertyDescriptor(self.HTMLIFrameElement, HTMLIFrameDescriptorMap);
1375 definePrototypePropertyDescriptor(self.HTMLScriptElement, HTMLScriptDescriptorMap);
1376 definePrototypePropertyDescriptor(self.HTMLStyleElement, HTMLStyleDescriptorMap);
1377 definePrototypePropertyDescriptor(self.HTMLHeadElement, DocumentElementChildDescriptorMap);
1378 definePrototypePropertyDescriptor(self.HTMLBodyElement, DocumentElementChildDescriptorMap);
1379 definePrototypePropertyDescriptor(self.HTMLHtmlElement, DocumentElementDescriptorMap);
1380 constantProps(CSSStyleSheet, {
1381 type: "text/css"
1382 });
1383 definePrototypeNodeType(self.Comment, 8);
1384 definePrototypeNodeType(self.DocumentType, 10);
1385 definePrototypeNodeType(DocumentFragment, 11);
1386 cachedTreeProps(Node, nodeStructurePropNames);
1387 cachedTreeProps(Element, elementStructurePropNames);
1388 cachedTreeProps(DocumentFragment, elementStructurePropNames);
1389 cachedDimensionProps(Element);
1390 cachedDimensionMethods(Element, elementGetterDimensionMethodNames);
1391 cachedDimensionProps(Window);
1392 cachedDimensionMethods(Window, windowGetterDimensionMethodNames);
1393 cachedProps(Window, "devicePixelRatio");
1394 cachedProps(Document, "compatMode,referrer");
1395 cachedProps(Element, "id");
1396 })();
1397 webWorkerCtx.$isInitialized$ = 1;
1398 logWorker("Initialized web worker");
1399 };
1400 const queuedEvents = [];
1401 const receiveMessageFromSandboxToWorker = ev => {
1402 const msg = ev.data;
1403 const msgType = msg[0];
1404 if (webWorkerCtx.$isInitialized$) {
1405 if (6 === msgType) {
1406 (async initScript => {
1407 let winId = initScript.$winId$;
1408 let instanceId = initScript.$instanceId$;
1409 let instance = getOrCreateNodeInstance(winId, instanceId, "SCRIPT");
1410 let scriptContent = initScript.$content$;
1411 let scriptSrc = initScript.$url$;
1412 let scriptOrgSrc = initScript.$orgUrl$;
1413 let errorMsg = "";
1414 let env = environments[winId];
1415 let rsp;
1416 if (scriptSrc) {
1417 try {
1418 scriptSrc = resolveToUrl(env, scriptSrc) + "";
1419 setInstanceStateValue(instance, 4, scriptSrc);
1420 webWorkerCtx.$config$.logScriptExecution && logWorker(`Execute script (${instanceId}) src: ${scriptOrgSrc}`, winId);
1421 rsp = await self.fetch(scriptSrc);
1422 if (rsp.ok) {
1423 scriptContent = await rsp.text();
1424 env.$currentScriptId$ = instanceId;
1425 run(env, scriptContent, scriptOrgSrc || scriptSrc);
1426 runStateLoadHandlers(instance, "load");
1427 } else {
1428 errorMsg = rsp.statusText;
1429 runStateLoadHandlers(instance, "error");
1430 }
1431 } catch (urlError) {
1432 console.error(urlError);
1433 errorMsg = String(urlError.stack || urlError);
1434 runStateLoadHandlers(instance, "error");
1435 }
1436 } else {
1437 scriptContent && (errorMsg = runScriptContent(env, instanceId, scriptContent, winId, errorMsg));
1438 }
1439 env.$currentScriptId$ = -1;
1440 webWorkerCtx.$postMessage$([ 5, winId, instanceId, errorMsg ]);
1441 })(msg[1]);
1442 } else if (7 === msgType) {
1443 (({$instanceId$: $instanceId$, $refId$: $refId$, $thisArg$: $thisArg$, $args$: $args$}) => {
1444 if (webWorkerRefsByRefId[$refId$]) {
1445 try {
1446 const thisArg = deserializeFromMain(null, $instanceId$, [], $thisArg$);
1447 const args = deserializeFromMain(null, $instanceId$, [], $args$);
1448 webWorkerRefsByRefId[$refId$].apply(thisArg, args);
1449 } catch (e) {
1450 console.error(e);
1451 }
1452 }
1453 })(msg[1]);
1454 } else if (8 === msgType) {
1455 (({$winId$: $winId$, $forward$: $forward$, $args$: $args$}) => {
1456 try {
1457 let target = environments[$winId$].$window$;
1458 let i = 0;
1459 let l = len($forward$);
1460 for (;i < l; i++) {
1461 i + 1 < l ? target = target[$forward$[i]] : target[$forward$[i]].apply(target, deserializeFromMain(null, 0, [], $args$));
1462 }
1463 } catch (e) {
1464 console.error(e);
1465 }
1466 })(msg[1]);
1467 } else if (3 === msgType) {
1468 createEnvironment(msg[1]);
1469 } else if (4 === msgType) {
1470 environments[msg[1]].$isInitialized$ = 1;
1471 {
1472 const winId = msg[1];
1473 const env = environments[winId];
1474 const winType = env.$winId$ === env.$parentWinId$ ? "top" : "iframe";
1475 logWorker(`Initialized ${winType} window ${normalizedWinId(winId)} environment (${winId}) 🎉`, winId);
1476 }
1477 } else {
1478 11 === msgType && (environments[msg[1]].$location$.href = msg[2]);
1479 }
1480 } else if (1 === msgType) {
1481 initWebWorker(msg[1]);
1482 webWorkerCtx.$postMessage$([ 2 ]);
1483 queuedEvents.length && logWorker(`Queued ready messages: ${queuedEvents.length}`);
1484 queuedEvents.slice().forEach(receiveMessageFromSandboxToWorker);
1485 queuedEvents.length = 0;
1486 } else {
1487 queuedEvents.push(ev);
1488 }
1489 };
1490 self.onmessage = receiveMessageFromSandboxToWorker;
1491 postMessage([ 0 ]);
1492})(self);