@lunardinos/browser 0.2.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.
- package/README.md +51 -0
- package/dist/recorder-core.js +4892 -0
- package/dist/src/persistence.d.ts +16 -0
- package/dist/src/persistence.d.ts.map +1 -0
- package/dist/src/persistence.js +62 -0
- package/dist/src/recorder-core.d.ts +72 -0
- package/dist/src/recorder-core.d.ts.map +1 -0
- package/dist/src/recorder-core.js +470 -0
- package/package.json +24 -0
|
@@ -0,0 +1,4892 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __returnValue = (v) => v;
|
|
3
|
+
function __exportSetter(name, newValue) {
|
|
4
|
+
this[name] = __returnValue.bind(null, newValue);
|
|
5
|
+
}
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, {
|
|
9
|
+
get: all[name],
|
|
10
|
+
enumerable: true,
|
|
11
|
+
configurable: true,
|
|
12
|
+
set: __exportSetter.bind(all, name)
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
16
|
+
|
|
17
|
+
// ../rrweb-types/src/index.ts
|
|
18
|
+
var MouseInteractions;
|
|
19
|
+
var init_src = __esm(() => {
|
|
20
|
+
((MouseInteractions2) => {
|
|
21
|
+
MouseInteractions2[MouseInteractions2["MouseUp"] = 0] = "MouseUp";
|
|
22
|
+
MouseInteractions2[MouseInteractions2["MouseDown"] = 1] = "MouseDown";
|
|
23
|
+
MouseInteractions2[MouseInteractions2["Click"] = 2] = "Click";
|
|
24
|
+
MouseInteractions2[MouseInteractions2["ContextMenu"] = 3] = "ContextMenu";
|
|
25
|
+
MouseInteractions2[MouseInteractions2["DblClick"] = 4] = "DblClick";
|
|
26
|
+
MouseInteractions2[MouseInteractions2["Focus"] = 5] = "Focus";
|
|
27
|
+
MouseInteractions2[MouseInteractions2["Blur"] = 6] = "Blur";
|
|
28
|
+
MouseInteractions2[MouseInteractions2["TouchStart"] = 7] = "TouchStart";
|
|
29
|
+
MouseInteractions2[MouseInteractions2["TouchMove_Departed"] = 8] = "TouchMove_Departed";
|
|
30
|
+
MouseInteractions2[MouseInteractions2["TouchEnd"] = 9] = "TouchEnd";
|
|
31
|
+
MouseInteractions2[MouseInteractions2["TouchCancel"] = 10] = "TouchCancel";
|
|
32
|
+
})(MouseInteractions ||= {});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
// ../rrweb-record/src/dom.ts
|
|
36
|
+
function getUntaintedPrototype(key) {
|
|
37
|
+
if (untaintedBasePrototype[key])
|
|
38
|
+
return untaintedBasePrototype[key];
|
|
39
|
+
const defaultObj = globalThis[key];
|
|
40
|
+
const defaultPrototype = defaultObj.prototype;
|
|
41
|
+
const accessorNames = key in testableAccessors ? testableAccessors[key] : undefined;
|
|
42
|
+
const isUntaintedAccessors = Boolean(accessorNames?.every((accessor) => Boolean(Object.getOwnPropertyDescriptor(defaultPrototype, accessor)?.get?.toString().includes("[native code]"))));
|
|
43
|
+
const methodNames = key in testableMethods ? testableMethods[key] : undefined;
|
|
44
|
+
const isUntaintedMethods = Boolean(methodNames?.every((method) => typeof defaultPrototype[method] === "function" && defaultPrototype[method]?.toString().includes("[native code]")));
|
|
45
|
+
if (isUntaintedAccessors && isUntaintedMethods && !isAngularZonePresent()) {
|
|
46
|
+
untaintedBasePrototype[key] = defaultObj.prototype;
|
|
47
|
+
return defaultObj.prototype;
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const iframeEl = document.createElement("iframe");
|
|
51
|
+
document.body.appendChild(iframeEl);
|
|
52
|
+
const win = iframeEl.contentWindow;
|
|
53
|
+
if (!win)
|
|
54
|
+
return defaultObj.prototype;
|
|
55
|
+
const untaintedObject = win[key].prototype;
|
|
56
|
+
document.body.removeChild(iframeEl);
|
|
57
|
+
if (!untaintedObject)
|
|
58
|
+
return defaultPrototype;
|
|
59
|
+
return untaintedBasePrototype[key] = untaintedObject;
|
|
60
|
+
} catch {
|
|
61
|
+
return defaultPrototype;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
function getUntaintedAccessor(key, instance, accessor) {
|
|
65
|
+
const cacheKey = `${key}.${String(accessor)}`;
|
|
66
|
+
if (untaintedAccessorCache[cacheKey])
|
|
67
|
+
return untaintedAccessorCache[cacheKey].call(instance);
|
|
68
|
+
const untaintedPrototype = getUntaintedPrototype(key);
|
|
69
|
+
const untaintedAccessor = Object.getOwnPropertyDescriptor(untaintedPrototype, accessor)?.get;
|
|
70
|
+
if (!untaintedAccessor)
|
|
71
|
+
return instance[accessor];
|
|
72
|
+
untaintedAccessorCache[cacheKey] = untaintedAccessor;
|
|
73
|
+
return untaintedAccessor.call(instance);
|
|
74
|
+
}
|
|
75
|
+
function getUntaintedMethod(key, instance, method) {
|
|
76
|
+
const cacheKey = `${key}.${String(method)}`;
|
|
77
|
+
if (untaintedMethodCache[cacheKey])
|
|
78
|
+
return untaintedMethodCache[cacheKey].bind(instance);
|
|
79
|
+
const untaintedPrototype = getUntaintedPrototype(key);
|
|
80
|
+
const untaintedMethod = untaintedPrototype[method];
|
|
81
|
+
if (typeof untaintedMethod !== "function")
|
|
82
|
+
return instance[method];
|
|
83
|
+
untaintedMethodCache[cacheKey] = untaintedMethod;
|
|
84
|
+
return untaintedMethod.bind(instance);
|
|
85
|
+
}
|
|
86
|
+
function childNodes(n) {
|
|
87
|
+
return getUntaintedAccessor("Node", n, "childNodes");
|
|
88
|
+
}
|
|
89
|
+
function parentNode(n) {
|
|
90
|
+
return getUntaintedAccessor("Node", n, "parentNode");
|
|
91
|
+
}
|
|
92
|
+
function parentElement(n) {
|
|
93
|
+
return getUntaintedAccessor("Node", n, "parentElement");
|
|
94
|
+
}
|
|
95
|
+
function textContent(n) {
|
|
96
|
+
return getUntaintedAccessor("Node", n, "textContent");
|
|
97
|
+
}
|
|
98
|
+
function contains(n, other) {
|
|
99
|
+
return getUntaintedMethod("Node", n, "contains")(other);
|
|
100
|
+
}
|
|
101
|
+
function getRootNode(n) {
|
|
102
|
+
return getUntaintedMethod("Node", n, "getRootNode")();
|
|
103
|
+
}
|
|
104
|
+
function host(n) {
|
|
105
|
+
if (!n || !("host" in n))
|
|
106
|
+
return null;
|
|
107
|
+
return getUntaintedAccessor("ShadowRoot", n, "host");
|
|
108
|
+
}
|
|
109
|
+
function styleSheets(n) {
|
|
110
|
+
return n.styleSheets;
|
|
111
|
+
}
|
|
112
|
+
function shadowRoot(n) {
|
|
113
|
+
if (!n || !("shadowRoot" in n))
|
|
114
|
+
return null;
|
|
115
|
+
return getUntaintedAccessor("Element", n, "shadowRoot");
|
|
116
|
+
}
|
|
117
|
+
function querySelector(n, selectors) {
|
|
118
|
+
return getUntaintedAccessor("Element", n, "querySelector")(selectors);
|
|
119
|
+
}
|
|
120
|
+
function querySelectorAll(n, selectors) {
|
|
121
|
+
return getUntaintedAccessor("Element", n, "querySelectorAll")(selectors);
|
|
122
|
+
}
|
|
123
|
+
function mutationObserverCtor() {
|
|
124
|
+
return getUntaintedPrototype("MutationObserver").constructor;
|
|
125
|
+
}
|
|
126
|
+
var testableAccessors, testableMethods, untaintedBasePrototype, isAngularZonePresent = () => {
|
|
127
|
+
return !!globalThis.Zone;
|
|
128
|
+
}, untaintedAccessorCache, untaintedMethodCache, dom_default;
|
|
129
|
+
var init_dom = __esm(() => {
|
|
130
|
+
testableAccessors = {
|
|
131
|
+
Node: ["childNodes", "parentNode", "parentElement", "textContent"],
|
|
132
|
+
ShadowRoot: ["host", "styleSheets"],
|
|
133
|
+
Element: ["shadowRoot", "querySelector", "querySelectorAll"],
|
|
134
|
+
MutationObserver: []
|
|
135
|
+
};
|
|
136
|
+
testableMethods = {
|
|
137
|
+
Node: ["contains", "getRootNode"],
|
|
138
|
+
ShadowRoot: ["getSelection"],
|
|
139
|
+
Element: [],
|
|
140
|
+
MutationObserver: ["constructor"]
|
|
141
|
+
};
|
|
142
|
+
untaintedBasePrototype = {};
|
|
143
|
+
untaintedAccessorCache = {};
|
|
144
|
+
untaintedMethodCache = {};
|
|
145
|
+
dom_default = {
|
|
146
|
+
childNodes,
|
|
147
|
+
parentNode,
|
|
148
|
+
parentElement,
|
|
149
|
+
textContent,
|
|
150
|
+
contains,
|
|
151
|
+
getRootNode,
|
|
152
|
+
host,
|
|
153
|
+
styleSheets,
|
|
154
|
+
shadowRoot,
|
|
155
|
+
querySelector,
|
|
156
|
+
querySelectorAll,
|
|
157
|
+
mutationObserver: mutationObserverCtor
|
|
158
|
+
};
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// ../rrweb-record/src/redact-pii.ts
|
|
162
|
+
function redactPII(text) {
|
|
163
|
+
let result = text;
|
|
164
|
+
for (const { re, tag } of PII_PATTERNS) {
|
|
165
|
+
re.lastIndex = 0;
|
|
166
|
+
result = result.replace(re, tag);
|
|
167
|
+
}
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
var EMAIL_RE, PHONE_RE, CC_RE, SSN_RE, IP_RE, PII_PATTERNS;
|
|
171
|
+
var init_redact_pii = __esm(() => {
|
|
172
|
+
EMAIL_RE = /\b[\w.+-]+@[\w.-]+\.\w{2,}\b/g;
|
|
173
|
+
PHONE_RE = /(?:\+|(?<=\s|^))\(?\d{1,4}\)?[\s-]\(?\d{1,5}\)?[\s-]?\d{2,}(?:[\s-]\d+)*/g;
|
|
174
|
+
CC_RE = /\b\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}\b/g;
|
|
175
|
+
SSN_RE = /\b\d{3}-\d{2}-\d{4}\b/g;
|
|
176
|
+
IP_RE = /\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b/g;
|
|
177
|
+
PII_PATTERNS = [
|
|
178
|
+
{ re: CC_RE, tag: "[redacted cc]" },
|
|
179
|
+
{ re: SSN_RE, tag: "[redacted ssn]" },
|
|
180
|
+
{ re: EMAIL_RE, tag: "[redacted email]" },
|
|
181
|
+
{ re: IP_RE, tag: "[redacted ip]" },
|
|
182
|
+
{ re: PHONE_RE, tag: "[redacted phone]" }
|
|
183
|
+
];
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
// ../rrweb-record/src/snapshot-utils.ts
|
|
187
|
+
function isElement(n) {
|
|
188
|
+
return n.nodeType === n.ELEMENT_NODE;
|
|
189
|
+
}
|
|
190
|
+
function isShadowRoot(n) {
|
|
191
|
+
const hostEl = n && "host" in n && "mode" in n && dom_default.host(n) || null;
|
|
192
|
+
return Boolean(hostEl && "shadowRoot" in hostEl && dom_default.shadowRoot(hostEl) === n);
|
|
193
|
+
}
|
|
194
|
+
function isNativeShadowDom(shadowRoot2) {
|
|
195
|
+
return Object.prototype.toString.call(shadowRoot2) === "[object ShadowRoot]";
|
|
196
|
+
}
|
|
197
|
+
function fixBrowserCompatibilityIssuesInCSS(cssText) {
|
|
198
|
+
if (cssText.includes(" background-clip: text;") && !cssText.includes(" -webkit-background-clip: text;")) {
|
|
199
|
+
cssText = cssText.replace(/\sbackground-clip:\s*text;/g, " -webkit-background-clip: text; background-clip: text;");
|
|
200
|
+
}
|
|
201
|
+
return cssText;
|
|
202
|
+
}
|
|
203
|
+
function escapeImportStatement(rule) {
|
|
204
|
+
const { cssText } = rule;
|
|
205
|
+
if (cssText.split('"').length < 3)
|
|
206
|
+
return cssText;
|
|
207
|
+
const statement = ["@import", `url(${JSON.stringify(rule.href)})`];
|
|
208
|
+
if (rule.layerName === "") {
|
|
209
|
+
statement.push("layer");
|
|
210
|
+
} else if (rule.layerName) {
|
|
211
|
+
statement.push(`layer(${rule.layerName})`);
|
|
212
|
+
}
|
|
213
|
+
if (rule.supportsText) {
|
|
214
|
+
statement.push(`supports(${rule.supportsText})`);
|
|
215
|
+
}
|
|
216
|
+
if (rule.media.length) {
|
|
217
|
+
statement.push(rule.media.mediaText);
|
|
218
|
+
}
|
|
219
|
+
return `${statement.join(" ")};`;
|
|
220
|
+
}
|
|
221
|
+
function stringifyStylesheet(s) {
|
|
222
|
+
try {
|
|
223
|
+
const rules = s.rules || s.cssRules;
|
|
224
|
+
if (!rules) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
let sheetHref = s.href;
|
|
228
|
+
if (!sheetHref && s.ownerNode && s.ownerNode.ownerDocument) {
|
|
229
|
+
sheetHref = s.ownerNode.ownerDocument.location.href;
|
|
230
|
+
}
|
|
231
|
+
const stringifiedRules = Array.from(rules, (rule) => stringifyRule(rule, sheetHref)).join("");
|
|
232
|
+
return fixBrowserCompatibilityIssuesInCSS(stringifiedRules);
|
|
233
|
+
} catch (_error) {
|
|
234
|
+
return null;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
function stringifyRule(rule, sheetHref) {
|
|
238
|
+
if (isCSSImportRule(rule)) {
|
|
239
|
+
let importStringified;
|
|
240
|
+
try {
|
|
241
|
+
importStringified = stringifyStylesheet(rule.styleSheet) || escapeImportStatement(rule);
|
|
242
|
+
} catch (_error) {
|
|
243
|
+
importStringified = rule.cssText;
|
|
244
|
+
}
|
|
245
|
+
if (rule.styleSheet.href) {
|
|
246
|
+
return absolutifyURLs(importStringified, rule.styleSheet.href);
|
|
247
|
+
}
|
|
248
|
+
return importStringified;
|
|
249
|
+
}
|
|
250
|
+
let ruleStringified = rule.cssText;
|
|
251
|
+
if (isCSSStyleRule(rule) && rule.selectorText.includes(":")) {
|
|
252
|
+
ruleStringified = fixSafariColons(ruleStringified);
|
|
253
|
+
}
|
|
254
|
+
if (sheetHref) {
|
|
255
|
+
return absolutifyURLs(ruleStringified, sheetHref);
|
|
256
|
+
}
|
|
257
|
+
return ruleStringified;
|
|
258
|
+
}
|
|
259
|
+
function fixSafariColons(cssStringified) {
|
|
260
|
+
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
261
|
+
return cssStringified.replace(regex, "$1\\$2");
|
|
262
|
+
}
|
|
263
|
+
function isCSSImportRule(rule) {
|
|
264
|
+
return "styleSheet" in rule;
|
|
265
|
+
}
|
|
266
|
+
function isCSSStyleRule(rule) {
|
|
267
|
+
return "selectorText" in rule;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
class PathMirror {
|
|
271
|
+
nodePathMap = new WeakMap;
|
|
272
|
+
pathNodeMap = new Map;
|
|
273
|
+
nodeMetaMap = new WeakMap;
|
|
274
|
+
computePath(n) {
|
|
275
|
+
const parts = [];
|
|
276
|
+
let current = n;
|
|
277
|
+
let parent = dom_default.parentNode(current);
|
|
278
|
+
while (parent) {
|
|
279
|
+
const children = dom_default.childNodes(parent);
|
|
280
|
+
const idx = Array.prototype.indexOf.call(children, current);
|
|
281
|
+
if (idx === -1)
|
|
282
|
+
break;
|
|
283
|
+
parts.unshift(idx);
|
|
284
|
+
current = parent;
|
|
285
|
+
parent = dom_default.parentNode(current);
|
|
286
|
+
}
|
|
287
|
+
return parts.join(".");
|
|
288
|
+
}
|
|
289
|
+
getPath(n) {
|
|
290
|
+
if (!n)
|
|
291
|
+
return "";
|
|
292
|
+
const cached = this.nodePathMap.get(n);
|
|
293
|
+
if (cached !== undefined)
|
|
294
|
+
return cached;
|
|
295
|
+
return this.computePath(n);
|
|
296
|
+
}
|
|
297
|
+
getNode(path) {
|
|
298
|
+
return this.pathNodeMap.get(path) || null;
|
|
299
|
+
}
|
|
300
|
+
getPaths() {
|
|
301
|
+
return Array.from(this.pathNodeMap.keys());
|
|
302
|
+
}
|
|
303
|
+
has(path) {
|
|
304
|
+
return this.pathNodeMap.has(path);
|
|
305
|
+
}
|
|
306
|
+
add(n, meta) {
|
|
307
|
+
const path = meta.path;
|
|
308
|
+
if (path !== undefined) {
|
|
309
|
+
this.nodePathMap.set(n, path);
|
|
310
|
+
this.pathNodeMap.set(path, n);
|
|
311
|
+
}
|
|
312
|
+
this.nodeMetaMap.set(n, meta);
|
|
313
|
+
}
|
|
314
|
+
replace(path, n) {
|
|
315
|
+
const oldNode = this.pathNodeMap.get(path);
|
|
316
|
+
if (oldNode) {
|
|
317
|
+
const meta = this.nodeMetaMap.get(oldNode);
|
|
318
|
+
if (meta)
|
|
319
|
+
this.nodeMetaMap.set(n, meta);
|
|
320
|
+
}
|
|
321
|
+
this.pathNodeMap.set(path, n);
|
|
322
|
+
this.nodePathMap.set(n, path);
|
|
323
|
+
}
|
|
324
|
+
setPath(n, path) {
|
|
325
|
+
this.nodePathMap.set(n, path);
|
|
326
|
+
this.pathNodeMap.set(path, n);
|
|
327
|
+
}
|
|
328
|
+
setMeta(n, meta) {
|
|
329
|
+
this.nodeMetaMap.set(n, meta);
|
|
330
|
+
}
|
|
331
|
+
getMeta(n) {
|
|
332
|
+
return this.nodeMetaMap.get(n) || null;
|
|
333
|
+
}
|
|
334
|
+
hasNode(node) {
|
|
335
|
+
return this.nodePathMap.has(node);
|
|
336
|
+
}
|
|
337
|
+
isIgnored(n) {
|
|
338
|
+
return this.nodePathMap.get(n) === IGNORED_PATH;
|
|
339
|
+
}
|
|
340
|
+
isSerialized(n) {
|
|
341
|
+
const path = this.nodePathMap.get(n);
|
|
342
|
+
return path !== undefined && path !== IGNORED_PATH;
|
|
343
|
+
}
|
|
344
|
+
removeNodeFromMap(n) {
|
|
345
|
+
const path = this.nodePathMap.get(n);
|
|
346
|
+
if (path !== undefined) {
|
|
347
|
+
this.pathNodeMap.delete(path);
|
|
348
|
+
}
|
|
349
|
+
this.nodePathMap.delete(n);
|
|
350
|
+
if (n.childNodes) {
|
|
351
|
+
n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
reset() {
|
|
355
|
+
this.nodePathMap = new WeakMap;
|
|
356
|
+
this.pathNodeMap = new Map;
|
|
357
|
+
this.nodeMetaMap = new WeakMap;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
function createMirror() {
|
|
361
|
+
return new PathMirror;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
class Mirror {
|
|
365
|
+
pathNodeMap = new Map;
|
|
366
|
+
nodeMetaMap = new WeakMap;
|
|
367
|
+
nodePathMap = new WeakMap;
|
|
368
|
+
getPath(n) {
|
|
369
|
+
if (!n)
|
|
370
|
+
return "";
|
|
371
|
+
return this.nodePathMap.get(n) ?? "";
|
|
372
|
+
}
|
|
373
|
+
getNode(path) {
|
|
374
|
+
return this.pathNodeMap.get(path) || null;
|
|
375
|
+
}
|
|
376
|
+
getPaths() {
|
|
377
|
+
return Array.from(this.pathNodeMap.keys());
|
|
378
|
+
}
|
|
379
|
+
getMeta(n) {
|
|
380
|
+
return this.nodeMetaMap.get(n) || null;
|
|
381
|
+
}
|
|
382
|
+
has(path) {
|
|
383
|
+
return this.pathNodeMap.has(path);
|
|
384
|
+
}
|
|
385
|
+
hasNode(node) {
|
|
386
|
+
return this.nodeMetaMap.has(node);
|
|
387
|
+
}
|
|
388
|
+
add(n, meta) {
|
|
389
|
+
const path = meta.path;
|
|
390
|
+
if (path !== undefined) {
|
|
391
|
+
this.pathNodeMap.set(path, n);
|
|
392
|
+
this.nodePathMap.set(n, path);
|
|
393
|
+
}
|
|
394
|
+
this.nodeMetaMap.set(n, meta);
|
|
395
|
+
}
|
|
396
|
+
replace(path, n) {
|
|
397
|
+
const oldNode = this.pathNodeMap.get(path);
|
|
398
|
+
if (oldNode) {
|
|
399
|
+
const meta = this.nodeMetaMap.get(oldNode);
|
|
400
|
+
if (meta)
|
|
401
|
+
this.nodeMetaMap.set(n, meta);
|
|
402
|
+
}
|
|
403
|
+
this.pathNodeMap.set(path, n);
|
|
404
|
+
this.nodePathMap.set(n, path);
|
|
405
|
+
}
|
|
406
|
+
removeNodeFromMap(n) {
|
|
407
|
+
const path = this.nodePathMap.get(n);
|
|
408
|
+
if (path !== undefined) {
|
|
409
|
+
this.pathNodeMap.delete(path);
|
|
410
|
+
}
|
|
411
|
+
this.nodePathMap.delete(n);
|
|
412
|
+
if (n.childNodes) {
|
|
413
|
+
n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode));
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
reset() {
|
|
417
|
+
this.pathNodeMap = new Map;
|
|
418
|
+
this.nodeMetaMap = new WeakMap;
|
|
419
|
+
this.nodePathMap = new WeakMap;
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
function maskInputValue({
|
|
423
|
+
element,
|
|
424
|
+
maskInputOptions,
|
|
425
|
+
tagName,
|
|
426
|
+
type,
|
|
427
|
+
value,
|
|
428
|
+
maskInputFn
|
|
429
|
+
}) {
|
|
430
|
+
let text = value || "";
|
|
431
|
+
const actualType = type && toLowerCase(type);
|
|
432
|
+
if (maskInputOptions[tagName.toLowerCase()] || actualType && maskInputOptions[actualType]) {
|
|
433
|
+
if (maskInputFn) {
|
|
434
|
+
text = maskInputFn(text, element);
|
|
435
|
+
} else {
|
|
436
|
+
text = "*".repeat(text.length);
|
|
437
|
+
}
|
|
438
|
+
} else {
|
|
439
|
+
text = redactPII(text);
|
|
440
|
+
}
|
|
441
|
+
return text;
|
|
442
|
+
}
|
|
443
|
+
function toLowerCase(str) {
|
|
444
|
+
return str.toLowerCase();
|
|
445
|
+
}
|
|
446
|
+
function is2DCanvasBlank(canvas) {
|
|
447
|
+
const ctx = canvas.getContext("2d");
|
|
448
|
+
if (!ctx)
|
|
449
|
+
return true;
|
|
450
|
+
const chunkSize = 50;
|
|
451
|
+
for (let x = 0;x < canvas.width; x += chunkSize) {
|
|
452
|
+
for (let y = 0;y < canvas.height; y += chunkSize) {
|
|
453
|
+
const getImageData = ctx.getImageData;
|
|
454
|
+
const originalGetImageData = ORIGINAL_ATTRIBUTE_NAME in getImageData ? getImageData[ORIGINAL_ATTRIBUTE_NAME] : getImageData;
|
|
455
|
+
const pixelBuffer = new Uint32Array(originalGetImageData.call(ctx, x, y, Math.min(chunkSize, canvas.width - x), Math.min(chunkSize, canvas.height - y)).data.buffer);
|
|
456
|
+
if (pixelBuffer.some((pixel) => pixel !== 0))
|
|
457
|
+
return false;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
return true;
|
|
461
|
+
}
|
|
462
|
+
function getInputType(element) {
|
|
463
|
+
const type = element.type;
|
|
464
|
+
return element.hasAttribute("data-rr-is-password") ? "password" : type ? toLowerCase(type) : null;
|
|
465
|
+
}
|
|
466
|
+
function extractFileExtension(path, baseURL) {
|
|
467
|
+
let url;
|
|
468
|
+
try {
|
|
469
|
+
url = new URL(path, baseURL ?? window.location.href);
|
|
470
|
+
} catch (_err) {
|
|
471
|
+
return null;
|
|
472
|
+
}
|
|
473
|
+
const regex = /\.([0-9a-z]+)(?:$)/i;
|
|
474
|
+
const match = url.pathname.match(regex);
|
|
475
|
+
return match?.[1] ?? null;
|
|
476
|
+
}
|
|
477
|
+
function extractOrigin(url) {
|
|
478
|
+
let origin = "";
|
|
479
|
+
if (url.indexOf("//") > -1) {
|
|
480
|
+
origin = url.split("/").slice(0, 3).join("/");
|
|
481
|
+
} else {
|
|
482
|
+
origin = url.split("/")[0];
|
|
483
|
+
}
|
|
484
|
+
origin = origin.split("?")[0];
|
|
485
|
+
return origin;
|
|
486
|
+
}
|
|
487
|
+
function absolutifyURLs(cssText, href) {
|
|
488
|
+
return (cssText || "").replace(URL_IN_CSS_REF, (origin, quote1, path1, quote2, path2, path3) => {
|
|
489
|
+
const filePath = path1 || path2 || path3;
|
|
490
|
+
const maybeQuote = quote1 || quote2 || "";
|
|
491
|
+
if (!filePath) {
|
|
492
|
+
return origin;
|
|
493
|
+
}
|
|
494
|
+
if (URL_PROTOCOL_MATCH.test(filePath) || URL_WWW_MATCH.test(filePath)) {
|
|
495
|
+
return `url(${maybeQuote}${filePath}${maybeQuote})`;
|
|
496
|
+
}
|
|
497
|
+
if (DATA_URI.test(filePath)) {
|
|
498
|
+
return `url(${maybeQuote}${filePath}${maybeQuote})`;
|
|
499
|
+
}
|
|
500
|
+
if (filePath[0] === "/") {
|
|
501
|
+
return `url(${maybeQuote}${extractOrigin(href) + filePath}${maybeQuote})`;
|
|
502
|
+
}
|
|
503
|
+
const stack = href.split("/");
|
|
504
|
+
const parts = filePath.split("/");
|
|
505
|
+
stack.pop();
|
|
506
|
+
for (const part of parts) {
|
|
507
|
+
if (part === ".") {} else if (part === "..") {
|
|
508
|
+
stack.pop();
|
|
509
|
+
} else {
|
|
510
|
+
stack.push(part);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
return `url(${maybeQuote}${stack.join("/")}${maybeQuote})`;
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
function normalizeCssString(cssText) {
|
|
517
|
+
return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, "");
|
|
518
|
+
}
|
|
519
|
+
function splitCssText(cssText, style) {
|
|
520
|
+
const childNodes2 = Array.from(style.childNodes);
|
|
521
|
+
const splits = [];
|
|
522
|
+
if (childNodes2.length > 1 && cssText && typeof cssText === "string") {
|
|
523
|
+
const cssTextNorm = normalizeCssString(cssText);
|
|
524
|
+
for (let i = 1;i < childNodes2.length; i++) {
|
|
525
|
+
const childNode = childNodes2[i];
|
|
526
|
+
if (childNode.textContent && typeof childNode.textContent === "string") {
|
|
527
|
+
const textContentNorm = normalizeCssString(childNode.textContent);
|
|
528
|
+
for (let j = 3;j < textContentNorm.length; j++) {
|
|
529
|
+
const bit = textContentNorm.substring(0, j);
|
|
530
|
+
if (cssTextNorm.split(bit).length === 2) {
|
|
531
|
+
const splitNorm = cssTextNorm.indexOf(bit);
|
|
532
|
+
for (let k = splitNorm;k < cssText.length; k++) {
|
|
533
|
+
if (normalizeCssString(cssText.substring(0, k)).length === splitNorm) {
|
|
534
|
+
splits.push(cssText.substring(0, k));
|
|
535
|
+
cssText = cssText.substring(k);
|
|
536
|
+
break;
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
break;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
splits.push(cssText);
|
|
546
|
+
return splits;
|
|
547
|
+
}
|
|
548
|
+
function markCssSplits(cssText, style) {
|
|
549
|
+
return splitCssText(cssText, style).join("/* rr_split */");
|
|
550
|
+
}
|
|
551
|
+
var IGNORED_PATH = "__ignored__", ORIGINAL_ATTRIBUTE_NAME = "__rrweb_original__", URL_IN_CSS_REF, URL_PROTOCOL_MATCH, URL_WWW_MATCH, DATA_URI;
|
|
552
|
+
var init_snapshot_utils = __esm(() => {
|
|
553
|
+
init_src();
|
|
554
|
+
init_dom();
|
|
555
|
+
init_redact_pii();
|
|
556
|
+
URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm;
|
|
557
|
+
URL_PROTOCOL_MATCH = /^(?:[a-z+]+:)?\/\//i;
|
|
558
|
+
URL_WWW_MATCH = /^www\..*/i;
|
|
559
|
+
DATA_URI = /^(data:)([^,]*),(.*)/i;
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
// ../rrweb-record/src/snapshot.ts
|
|
563
|
+
function getValidTagName(element) {
|
|
564
|
+
if (element instanceof HTMLFormElement) {
|
|
565
|
+
return "form";
|
|
566
|
+
}
|
|
567
|
+
const processedTagName = toLowerCase(element.tagName);
|
|
568
|
+
if (tagNameRegex.test(processedTagName)) {
|
|
569
|
+
return "div";
|
|
570
|
+
}
|
|
571
|
+
return processedTagName;
|
|
572
|
+
}
|
|
573
|
+
function getAbsoluteSrcsetString(doc, attributeValue) {
|
|
574
|
+
if (attributeValue.trim() === "") {
|
|
575
|
+
return attributeValue;
|
|
576
|
+
}
|
|
577
|
+
let pos = 0;
|
|
578
|
+
function collectCharacters(regEx) {
|
|
579
|
+
let chars;
|
|
580
|
+
const match = regEx.exec(attributeValue.substring(pos));
|
|
581
|
+
if (match) {
|
|
582
|
+
chars = match[0];
|
|
583
|
+
pos += chars.length;
|
|
584
|
+
return chars;
|
|
585
|
+
}
|
|
586
|
+
return "";
|
|
587
|
+
}
|
|
588
|
+
const output = [];
|
|
589
|
+
while (true) {
|
|
590
|
+
collectCharacters(SRCSET_COMMAS_OR_SPACES);
|
|
591
|
+
if (pos >= attributeValue.length) {
|
|
592
|
+
break;
|
|
593
|
+
}
|
|
594
|
+
let url = collectCharacters(SRCSET_NOT_SPACES);
|
|
595
|
+
if (url.slice(-1) === ",") {
|
|
596
|
+
url = absoluteToDoc(doc, url.substring(0, url.length - 1));
|
|
597
|
+
output.push(url);
|
|
598
|
+
} else {
|
|
599
|
+
let descriptorsStr = "";
|
|
600
|
+
url = absoluteToDoc(doc, url);
|
|
601
|
+
let inParens = false;
|
|
602
|
+
while (true) {
|
|
603
|
+
const c = attributeValue.charAt(pos);
|
|
604
|
+
if (c === "") {
|
|
605
|
+
output.push((url + descriptorsStr).trim());
|
|
606
|
+
break;
|
|
607
|
+
}
|
|
608
|
+
if (!inParens) {
|
|
609
|
+
if (c === ",") {
|
|
610
|
+
pos += 1;
|
|
611
|
+
output.push((url + descriptorsStr).trim());
|
|
612
|
+
break;
|
|
613
|
+
}
|
|
614
|
+
if (c === "(") {
|
|
615
|
+
inParens = true;
|
|
616
|
+
}
|
|
617
|
+
} else {
|
|
618
|
+
if (c === ")") {
|
|
619
|
+
inParens = false;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
descriptorsStr += c;
|
|
623
|
+
pos += 1;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
return output.join(", ");
|
|
628
|
+
}
|
|
629
|
+
function absoluteToDoc(doc, attributeValue) {
|
|
630
|
+
if (!attributeValue || attributeValue.trim() === "") {
|
|
631
|
+
return attributeValue;
|
|
632
|
+
}
|
|
633
|
+
return getHref(doc, attributeValue);
|
|
634
|
+
}
|
|
635
|
+
function isSVGElement(el) {
|
|
636
|
+
return Boolean(el.tagName === "svg" || el.ownerSVGElement);
|
|
637
|
+
}
|
|
638
|
+
function getHref(doc, customHref) {
|
|
639
|
+
let a = cachedDocument.get(doc);
|
|
640
|
+
if (!a) {
|
|
641
|
+
a = doc.createElement("a");
|
|
642
|
+
cachedDocument.set(doc, a);
|
|
643
|
+
}
|
|
644
|
+
if (!customHref) {
|
|
645
|
+
customHref = "";
|
|
646
|
+
} else if (customHref.startsWith("blob:") || customHref.startsWith("data:")) {
|
|
647
|
+
return customHref;
|
|
648
|
+
}
|
|
649
|
+
a.setAttribute("href", customHref);
|
|
650
|
+
return a.href;
|
|
651
|
+
}
|
|
652
|
+
function transformAttribute(doc, tagName, name, value) {
|
|
653
|
+
if (!value) {
|
|
654
|
+
return value;
|
|
655
|
+
}
|
|
656
|
+
if (name === "src" || name === "href" && !(tagName === "use" && value[0] === "#")) {
|
|
657
|
+
return absoluteToDoc(doc, value);
|
|
658
|
+
}
|
|
659
|
+
if (name === "xlink:href" && value[0] !== "#") {
|
|
660
|
+
return absoluteToDoc(doc, value);
|
|
661
|
+
}
|
|
662
|
+
if (name === "background" && (tagName === "table" || tagName === "td" || tagName === "th")) {
|
|
663
|
+
return absoluteToDoc(doc, value);
|
|
664
|
+
}
|
|
665
|
+
if (name === "srcset") {
|
|
666
|
+
return getAbsoluteSrcsetString(doc, value);
|
|
667
|
+
}
|
|
668
|
+
if (name === "style") {
|
|
669
|
+
return absolutifyURLs(value, getHref(doc));
|
|
670
|
+
}
|
|
671
|
+
if (tagName === "object" && name === "data") {
|
|
672
|
+
return absoluteToDoc(doc, value);
|
|
673
|
+
}
|
|
674
|
+
return value;
|
|
675
|
+
}
|
|
676
|
+
function ignoreAttribute(tagName, name, _value) {
|
|
677
|
+
return (tagName === "video" || tagName === "audio") && name === "autoplay";
|
|
678
|
+
}
|
|
679
|
+
function _isBlockedElement(element, blockClass, blockSelector) {
|
|
680
|
+
try {
|
|
681
|
+
if (typeof blockClass === "string") {
|
|
682
|
+
if (element.classList.contains(blockClass)) {
|
|
683
|
+
return true;
|
|
684
|
+
}
|
|
685
|
+
} else {
|
|
686
|
+
for (let eIndex = element.classList.length;eIndex--; ) {
|
|
687
|
+
const className = element.classList[eIndex];
|
|
688
|
+
if (blockClass.test(className)) {
|
|
689
|
+
return true;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
if (blockSelector) {
|
|
694
|
+
return element.matches(blockSelector);
|
|
695
|
+
}
|
|
696
|
+
} catch (_e) {}
|
|
697
|
+
return false;
|
|
698
|
+
}
|
|
699
|
+
function classMatchesRegex(node, regex, checkAncestors) {
|
|
700
|
+
if (!node)
|
|
701
|
+
return false;
|
|
702
|
+
if (node.nodeType !== node.ELEMENT_NODE) {
|
|
703
|
+
if (!checkAncestors)
|
|
704
|
+
return false;
|
|
705
|
+
return classMatchesRegex(dom_default.parentNode(node), regex, checkAncestors);
|
|
706
|
+
}
|
|
707
|
+
for (let eIndex = node.classList.length;eIndex--; ) {
|
|
708
|
+
const className = node.classList[eIndex];
|
|
709
|
+
if (regex.test(className)) {
|
|
710
|
+
return true;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
if (!checkAncestors)
|
|
714
|
+
return false;
|
|
715
|
+
return classMatchesRegex(dom_default.parentNode(node), regex, checkAncestors);
|
|
716
|
+
}
|
|
717
|
+
function needMaskingText(node, maskTextClass, maskTextSelector, checkAncestors) {
|
|
718
|
+
let el;
|
|
719
|
+
if (isElement(node)) {
|
|
720
|
+
el = node;
|
|
721
|
+
if (!dom_default.childNodes(el).length) {
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
} else if (dom_default.parentElement(node) === null) {
|
|
725
|
+
return false;
|
|
726
|
+
} else {
|
|
727
|
+
el = dom_default.parentElement(node);
|
|
728
|
+
}
|
|
729
|
+
try {
|
|
730
|
+
if (typeof maskTextClass === "string") {
|
|
731
|
+
if (checkAncestors) {
|
|
732
|
+
if (el.closest(`.${maskTextClass}`))
|
|
733
|
+
return true;
|
|
734
|
+
} else {
|
|
735
|
+
if (el.classList.contains(maskTextClass))
|
|
736
|
+
return true;
|
|
737
|
+
}
|
|
738
|
+
} else {
|
|
739
|
+
if (classMatchesRegex(el, maskTextClass, checkAncestors))
|
|
740
|
+
return true;
|
|
741
|
+
}
|
|
742
|
+
if (maskTextSelector) {
|
|
743
|
+
if (checkAncestors) {
|
|
744
|
+
if (el.closest(maskTextSelector))
|
|
745
|
+
return true;
|
|
746
|
+
} else {
|
|
747
|
+
if (el.matches(maskTextSelector))
|
|
748
|
+
return true;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
} catch (_e) {}
|
|
752
|
+
return false;
|
|
753
|
+
}
|
|
754
|
+
function onceIframeLoaded(iframeEl, listener, iframeLoadTimeout) {
|
|
755
|
+
const win = iframeEl.contentWindow;
|
|
756
|
+
if (!win) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
let fired = false;
|
|
760
|
+
let readyState;
|
|
761
|
+
try {
|
|
762
|
+
readyState = win.document.readyState;
|
|
763
|
+
} catch (_error) {
|
|
764
|
+
return;
|
|
765
|
+
}
|
|
766
|
+
if (readyState !== "complete") {
|
|
767
|
+
const timer = setTimeout(() => {
|
|
768
|
+
if (!fired) {
|
|
769
|
+
listener();
|
|
770
|
+
fired = true;
|
|
771
|
+
}
|
|
772
|
+
}, iframeLoadTimeout);
|
|
773
|
+
iframeEl.addEventListener("load", () => {
|
|
774
|
+
clearTimeout(timer);
|
|
775
|
+
fired = true;
|
|
776
|
+
listener();
|
|
777
|
+
});
|
|
778
|
+
return;
|
|
779
|
+
}
|
|
780
|
+
const blankUrl = "about:blank";
|
|
781
|
+
if (win.location.href !== blankUrl || iframeEl.src === blankUrl || iframeEl.src === "") {
|
|
782
|
+
setTimeout(listener, 0);
|
|
783
|
+
return iframeEl.addEventListener("load", listener);
|
|
784
|
+
}
|
|
785
|
+
iframeEl.addEventListener("load", listener);
|
|
786
|
+
}
|
|
787
|
+
function onceStylesheetLoaded(link, listener, styleSheetLoadTimeout) {
|
|
788
|
+
let fired = false;
|
|
789
|
+
let styleSheetLoaded;
|
|
790
|
+
try {
|
|
791
|
+
styleSheetLoaded = link.sheet;
|
|
792
|
+
} catch (_error) {
|
|
793
|
+
return;
|
|
794
|
+
}
|
|
795
|
+
if (styleSheetLoaded)
|
|
796
|
+
return;
|
|
797
|
+
const timer = setTimeout(() => {
|
|
798
|
+
if (!fired) {
|
|
799
|
+
listener();
|
|
800
|
+
fired = true;
|
|
801
|
+
}
|
|
802
|
+
}, styleSheetLoadTimeout);
|
|
803
|
+
link.addEventListener("load", () => {
|
|
804
|
+
clearTimeout(timer);
|
|
805
|
+
fired = true;
|
|
806
|
+
listener();
|
|
807
|
+
});
|
|
808
|
+
}
|
|
809
|
+
function serializeNode(n, options) {
|
|
810
|
+
const {
|
|
811
|
+
doc,
|
|
812
|
+
mirror,
|
|
813
|
+
blockClass,
|
|
814
|
+
blockSelector,
|
|
815
|
+
needsMask,
|
|
816
|
+
inlineStylesheet,
|
|
817
|
+
maskInputOptions = {},
|
|
818
|
+
maskTextFn,
|
|
819
|
+
maskInputFn,
|
|
820
|
+
dataURLOptions = {},
|
|
821
|
+
inlineImages,
|
|
822
|
+
recordCanvas,
|
|
823
|
+
keepIframeSrcFn,
|
|
824
|
+
newlyAddedElement = false,
|
|
825
|
+
cssCaptured = false
|
|
826
|
+
} = options;
|
|
827
|
+
const rootId = getRootId(doc, mirror);
|
|
828
|
+
switch (n.nodeType) {
|
|
829
|
+
case n.DOCUMENT_NODE:
|
|
830
|
+
if (n.compatMode !== "CSS1Compat") {
|
|
831
|
+
return {
|
|
832
|
+
type: 0 /* Document */,
|
|
833
|
+
childNodes: [],
|
|
834
|
+
compatMode: n.compatMode
|
|
835
|
+
};
|
|
836
|
+
}
|
|
837
|
+
return {
|
|
838
|
+
type: 0 /* Document */,
|
|
839
|
+
childNodes: []
|
|
840
|
+
};
|
|
841
|
+
case n.DOCUMENT_TYPE_NODE:
|
|
842
|
+
return {
|
|
843
|
+
type: 1 /* DocumentType */,
|
|
844
|
+
name: n.name,
|
|
845
|
+
publicId: n.publicId,
|
|
846
|
+
systemId: n.systemId,
|
|
847
|
+
rootId
|
|
848
|
+
};
|
|
849
|
+
case n.ELEMENT_NODE:
|
|
850
|
+
return serializeElementNode(n, {
|
|
851
|
+
doc,
|
|
852
|
+
blockClass,
|
|
853
|
+
blockSelector,
|
|
854
|
+
inlineStylesheet,
|
|
855
|
+
maskInputOptions,
|
|
856
|
+
maskInputFn,
|
|
857
|
+
dataURLOptions,
|
|
858
|
+
inlineImages,
|
|
859
|
+
recordCanvas,
|
|
860
|
+
keepIframeSrcFn,
|
|
861
|
+
newlyAddedElement,
|
|
862
|
+
rootId
|
|
863
|
+
});
|
|
864
|
+
case n.TEXT_NODE:
|
|
865
|
+
return serializeTextNode(n, {
|
|
866
|
+
doc,
|
|
867
|
+
needsMask,
|
|
868
|
+
maskTextFn,
|
|
869
|
+
rootId,
|
|
870
|
+
cssCaptured
|
|
871
|
+
});
|
|
872
|
+
case n.CDATA_SECTION_NODE:
|
|
873
|
+
return {
|
|
874
|
+
type: 4 /* CDATA */,
|
|
875
|
+
textContent: "",
|
|
876
|
+
rootId
|
|
877
|
+
};
|
|
878
|
+
case n.COMMENT_NODE:
|
|
879
|
+
return {
|
|
880
|
+
type: 5 /* Comment */,
|
|
881
|
+
textContent: dom_default.textContent(n) || "",
|
|
882
|
+
rootId
|
|
883
|
+
};
|
|
884
|
+
default:
|
|
885
|
+
return false;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
function getRootId(doc, mirror) {
|
|
889
|
+
if (!mirror.hasNode(doc))
|
|
890
|
+
return;
|
|
891
|
+
const docPath = mirror.getPath(doc);
|
|
892
|
+
return docPath === "" ? undefined : docPath;
|
|
893
|
+
}
|
|
894
|
+
function serializeTextNode(n, options) {
|
|
895
|
+
const { needsMask, maskTextFn, rootId, cssCaptured } = options;
|
|
896
|
+
const parent = dom_default.parentNode(n);
|
|
897
|
+
const parentTagName = parent && parent.tagName;
|
|
898
|
+
let textContent2 = "";
|
|
899
|
+
const isStyle = parentTagName === "STYLE" ? true : undefined;
|
|
900
|
+
const isScript = parentTagName === "SCRIPT" ? true : undefined;
|
|
901
|
+
if (isScript) {
|
|
902
|
+
textContent2 = "";
|
|
903
|
+
} else if (!cssCaptured) {
|
|
904
|
+
textContent2 = dom_default.textContent(n);
|
|
905
|
+
if (isStyle && textContent2) {
|
|
906
|
+
textContent2 = absolutifyURLs(textContent2, getHref(options.doc));
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
if (!isStyle && !isScript && textContent2 && needsMask) {
|
|
910
|
+
textContent2 = maskTextFn ? maskTextFn(textContent2, dom_default.parentElement(n)) : textContent2.replace(/[\S]/g, "*");
|
|
911
|
+
}
|
|
912
|
+
if (!isStyle && !isScript && textContent2) {
|
|
913
|
+
textContent2 = redactPII(textContent2);
|
|
914
|
+
}
|
|
915
|
+
return {
|
|
916
|
+
type: 3 /* Text */,
|
|
917
|
+
textContent: textContent2 || "",
|
|
918
|
+
rootId
|
|
919
|
+
};
|
|
920
|
+
}
|
|
921
|
+
function serializeElementNode(n, options) {
|
|
922
|
+
const {
|
|
923
|
+
doc,
|
|
924
|
+
blockClass,
|
|
925
|
+
blockSelector,
|
|
926
|
+
inlineStylesheet,
|
|
927
|
+
maskInputOptions = {},
|
|
928
|
+
maskInputFn,
|
|
929
|
+
dataURLOptions = {},
|
|
930
|
+
inlineImages,
|
|
931
|
+
recordCanvas,
|
|
932
|
+
keepIframeSrcFn,
|
|
933
|
+
newlyAddedElement = false,
|
|
934
|
+
rootId
|
|
935
|
+
} = options;
|
|
936
|
+
const needBlock = _isBlockedElement(n, blockClass, blockSelector);
|
|
937
|
+
const tagName = getValidTagName(n);
|
|
938
|
+
let attributes = {};
|
|
939
|
+
const len = n.attributes.length;
|
|
940
|
+
for (let i = 0;i < len; i++) {
|
|
941
|
+
const attr = n.attributes[i];
|
|
942
|
+
if (!ignoreAttribute(tagName, attr.name, attr.value)) {
|
|
943
|
+
attributes[attr.name] = transformAttribute(doc, tagName, toLowerCase(attr.name), attr.value);
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
if (tagName === "link" && inlineStylesheet) {
|
|
947
|
+
const stylesheet = Array.from(doc.styleSheets).find((s) => {
|
|
948
|
+
return s.href === n.href;
|
|
949
|
+
});
|
|
950
|
+
let cssText = null;
|
|
951
|
+
if (stylesheet) {
|
|
952
|
+
cssText = stringifyStylesheet(stylesheet);
|
|
953
|
+
}
|
|
954
|
+
if (cssText) {
|
|
955
|
+
attributes.rel = undefined;
|
|
956
|
+
attributes.href = undefined;
|
|
957
|
+
attributes._cssText = cssText;
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
if (tagName === "style" && n.sheet) {
|
|
961
|
+
let cssText = stringifyStylesheet(n.sheet);
|
|
962
|
+
if (cssText) {
|
|
963
|
+
if (n.childNodes.length > 1) {
|
|
964
|
+
cssText = markCssSplits(cssText, n);
|
|
965
|
+
}
|
|
966
|
+
attributes._cssText = cssText;
|
|
967
|
+
}
|
|
968
|
+
}
|
|
969
|
+
if (tagName === "input" || tagName === "textarea" || tagName === "select") {
|
|
970
|
+
const value = n.value;
|
|
971
|
+
const checked = n.checked;
|
|
972
|
+
if (attributes.type !== "radio" && attributes.type !== "checkbox" && attributes.type !== "submit" && attributes.type !== "button" && value) {
|
|
973
|
+
attributes.value = maskInputValue({
|
|
974
|
+
element: n,
|
|
975
|
+
type: getInputType(n),
|
|
976
|
+
tagName,
|
|
977
|
+
value,
|
|
978
|
+
maskInputOptions,
|
|
979
|
+
maskInputFn
|
|
980
|
+
});
|
|
981
|
+
} else if (checked) {
|
|
982
|
+
attributes.checked = checked;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
if (tagName === "option") {
|
|
986
|
+
if (n.selected && !maskInputOptions.select) {
|
|
987
|
+
attributes.selected = true;
|
|
988
|
+
} else {
|
|
989
|
+
attributes.selected = undefined;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
if (tagName === "dialog" && n.open) {
|
|
993
|
+
attributes.rr_open_mode = n.matches("dialog:modal") ? "modal" : "non-modal";
|
|
994
|
+
}
|
|
995
|
+
if (tagName === "canvas" && recordCanvas) {
|
|
996
|
+
if (n.__context === "2d") {
|
|
997
|
+
if (!is2DCanvasBlank(n)) {
|
|
998
|
+
attributes.rr_dataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
999
|
+
}
|
|
1000
|
+
} else if (!("__context" in n)) {
|
|
1001
|
+
const canvasDataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
1002
|
+
const blankCanvas = doc.createElement("canvas");
|
|
1003
|
+
blankCanvas.width = n.width;
|
|
1004
|
+
blankCanvas.height = n.height;
|
|
1005
|
+
const blankCanvasDataURL = blankCanvas.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
1006
|
+
if (canvasDataURL !== blankCanvasDataURL) {
|
|
1007
|
+
attributes.rr_dataURL = canvasDataURL;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
if (tagName === "img" && inlineImages) {
|
|
1012
|
+
if (!canvasService) {
|
|
1013
|
+
canvasService = doc.createElement("canvas");
|
|
1014
|
+
canvasCtx = canvasService.getContext("2d");
|
|
1015
|
+
}
|
|
1016
|
+
const image = n;
|
|
1017
|
+
const imageSrc = image.currentSrc || image.getAttribute("src") || "<unknown-src>";
|
|
1018
|
+
const priorCrossOrigin = image.crossOrigin;
|
|
1019
|
+
const recordInlineImage = () => {
|
|
1020
|
+
image.removeEventListener("load", recordInlineImage);
|
|
1021
|
+
try {
|
|
1022
|
+
canvasService.width = image.naturalWidth;
|
|
1023
|
+
canvasService.height = image.naturalHeight;
|
|
1024
|
+
canvasCtx?.drawImage(image, 0, 0);
|
|
1025
|
+
attributes.rr_dataURL = canvasService?.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
1026
|
+
} catch (err) {
|
|
1027
|
+
if (image.crossOrigin !== "anonymous") {
|
|
1028
|
+
image.crossOrigin = "anonymous";
|
|
1029
|
+
if (image.complete && image.naturalWidth !== 0)
|
|
1030
|
+
recordInlineImage();
|
|
1031
|
+
else
|
|
1032
|
+
image.addEventListener("load", recordInlineImage);
|
|
1033
|
+
return;
|
|
1034
|
+
}
|
|
1035
|
+
console.warn(`Cannot inline img src=${imageSrc}! Error: ${err}`);
|
|
1036
|
+
}
|
|
1037
|
+
if (image.crossOrigin === "anonymous") {
|
|
1038
|
+
priorCrossOrigin ? attributes.crossOrigin = priorCrossOrigin : image.removeAttribute("crossorigin");
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
if (image.complete && image.naturalWidth !== 0)
|
|
1042
|
+
recordInlineImage();
|
|
1043
|
+
else
|
|
1044
|
+
image.addEventListener("load", recordInlineImage);
|
|
1045
|
+
}
|
|
1046
|
+
if (tagName === "audio" || tagName === "video") {
|
|
1047
|
+
const mediaAttributes = attributes;
|
|
1048
|
+
mediaAttributes.rr_mediaState = n.paused ? "paused" : "played";
|
|
1049
|
+
mediaAttributes.rr_mediaCurrentTime = n.currentTime;
|
|
1050
|
+
mediaAttributes.rr_mediaPlaybackRate = n.playbackRate;
|
|
1051
|
+
mediaAttributes.rr_mediaMuted = n.muted;
|
|
1052
|
+
mediaAttributes.rr_mediaLoop = n.loop;
|
|
1053
|
+
mediaAttributes.rr_mediaVolume = n.volume;
|
|
1054
|
+
}
|
|
1055
|
+
if (!newlyAddedElement) {
|
|
1056
|
+
if (n.scrollLeft) {
|
|
1057
|
+
attributes.rr_scrollLeft = n.scrollLeft;
|
|
1058
|
+
}
|
|
1059
|
+
if (n.scrollTop) {
|
|
1060
|
+
attributes.rr_scrollTop = n.scrollTop;
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
if (needBlock) {
|
|
1064
|
+
const { width, height } = n.getBoundingClientRect();
|
|
1065
|
+
attributes = {
|
|
1066
|
+
class: attributes.class ?? null,
|
|
1067
|
+
rr_width: `${width}px`,
|
|
1068
|
+
rr_height: `${height}px`
|
|
1069
|
+
};
|
|
1070
|
+
}
|
|
1071
|
+
if (tagName === "iframe" && !keepIframeSrcFn(attributes.src)) {
|
|
1072
|
+
if (!n.contentDocument) {
|
|
1073
|
+
attributes.rr_src = attributes.src ?? null;
|
|
1074
|
+
}
|
|
1075
|
+
attributes.src = undefined;
|
|
1076
|
+
}
|
|
1077
|
+
let isCustomElement;
|
|
1078
|
+
try {
|
|
1079
|
+
if (customElements.get(tagName))
|
|
1080
|
+
isCustomElement = true;
|
|
1081
|
+
} catch (_e) {}
|
|
1082
|
+
return {
|
|
1083
|
+
type: 2 /* Element */,
|
|
1084
|
+
tagName,
|
|
1085
|
+
attributes,
|
|
1086
|
+
childNodes: [],
|
|
1087
|
+
isSVG: isSVGElement(n) || undefined,
|
|
1088
|
+
needBlock,
|
|
1089
|
+
rootId,
|
|
1090
|
+
isCustom: isCustomElement
|
|
1091
|
+
};
|
|
1092
|
+
}
|
|
1093
|
+
function lowerIfExists(maybeAttr) {
|
|
1094
|
+
if (maybeAttr === undefined || maybeAttr === null) {
|
|
1095
|
+
return "";
|
|
1096
|
+
}
|
|
1097
|
+
return maybeAttr.toLowerCase();
|
|
1098
|
+
}
|
|
1099
|
+
function slimDOMExcluded(sn, slimDOMOptions) {
|
|
1100
|
+
if (slimDOMOptions.comment && sn.type === 5 /* Comment */) {
|
|
1101
|
+
return true;
|
|
1102
|
+
}
|
|
1103
|
+
if (sn.type === 2 /* Element */) {
|
|
1104
|
+
if (slimDOMOptions.script && (sn.tagName === "script" || sn.tagName === "link" && (sn.attributes.rel === "preload" || sn.attributes.rel === "modulepreload") && sn.attributes.as === "script" || sn.tagName === "link" && sn.attributes.rel === "prefetch" && typeof sn.attributes.href === "string" && extractFileExtension(sn.attributes.href) === "js")) {
|
|
1105
|
+
return true;
|
|
1106
|
+
}
|
|
1107
|
+
if (slimDOMOptions.headFavicon && (sn.tagName === "link" && sn.attributes.rel === "shortcut icon" || sn.tagName === "meta" && (lowerIfExists(sn.attributes.name).match(/^msapplication-tile(image|color)$/) || lowerIfExists(sn.attributes.name) === "application-name" || lowerIfExists(sn.attributes.rel) === "icon" || lowerIfExists(sn.attributes.rel) === "apple-touch-icon" || lowerIfExists(sn.attributes.rel) === "shortcut icon"))) {
|
|
1108
|
+
return true;
|
|
1109
|
+
}
|
|
1110
|
+
if (sn.tagName === "meta") {
|
|
1111
|
+
if (slimDOMOptions.headMetaDescKeywords && lowerIfExists(sn.attributes.name).match(/^description|keywords$/)) {
|
|
1112
|
+
return true;
|
|
1113
|
+
}
|
|
1114
|
+
if (slimDOMOptions.headMetaSocial && (lowerIfExists(sn.attributes.property).match(/^(og|twitter|fb):/) || lowerIfExists(sn.attributes.name).match(/^(og|twitter):/) || lowerIfExists(sn.attributes.name) === "pinterest")) {
|
|
1115
|
+
return true;
|
|
1116
|
+
}
|
|
1117
|
+
if (slimDOMOptions.headMetaRobots && (lowerIfExists(sn.attributes.name) === "robots" || lowerIfExists(sn.attributes.name) === "googlebot" || lowerIfExists(sn.attributes.name) === "bingbot")) {
|
|
1118
|
+
return true;
|
|
1119
|
+
}
|
|
1120
|
+
if (slimDOMOptions.headMetaHttpEquiv && sn.attributes["http-equiv"] !== undefined) {
|
|
1121
|
+
return true;
|
|
1122
|
+
}
|
|
1123
|
+
if (slimDOMOptions.headMetaAuthorship && (lowerIfExists(sn.attributes.name) === "author" || lowerIfExists(sn.attributes.name) === "generator" || lowerIfExists(sn.attributes.name) === "framework" || lowerIfExists(sn.attributes.name) === "publisher" || lowerIfExists(sn.attributes.name) === "progid" || lowerIfExists(sn.attributes.property).match(/^article:/) || lowerIfExists(sn.attributes.property).match(/^product:/))) {
|
|
1124
|
+
return true;
|
|
1125
|
+
}
|
|
1126
|
+
if (slimDOMOptions.headMetaVerification && (lowerIfExists(sn.attributes.name) === "google-site-verification" || lowerIfExists(sn.attributes.name) === "yandex-verification" || lowerIfExists(sn.attributes.name) === "csrf-token" || lowerIfExists(sn.attributes.name) === "p:domain_verify" || lowerIfExists(sn.attributes.name) === "verify-v1" || lowerIfExists(sn.attributes.name) === "verification" || lowerIfExists(sn.attributes.name) === "shopify-checkout-api-token")) {
|
|
1127
|
+
return true;
|
|
1128
|
+
}
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
return false;
|
|
1132
|
+
}
|
|
1133
|
+
function serializeNodeWithId(n, options) {
|
|
1134
|
+
const {
|
|
1135
|
+
doc,
|
|
1136
|
+
mirror,
|
|
1137
|
+
blockClass,
|
|
1138
|
+
blockSelector,
|
|
1139
|
+
maskTextClass,
|
|
1140
|
+
maskTextSelector,
|
|
1141
|
+
skipChild = false,
|
|
1142
|
+
inlineStylesheet = true,
|
|
1143
|
+
maskInputOptions = {},
|
|
1144
|
+
maskTextFn,
|
|
1145
|
+
maskInputFn,
|
|
1146
|
+
slimDOMOptions,
|
|
1147
|
+
dataURLOptions = {},
|
|
1148
|
+
inlineImages = false,
|
|
1149
|
+
recordCanvas = false,
|
|
1150
|
+
onSerialize,
|
|
1151
|
+
onIframeLoad,
|
|
1152
|
+
iframeLoadTimeout = 5000,
|
|
1153
|
+
onStylesheetLoad,
|
|
1154
|
+
stylesheetLoadTimeout = 5000,
|
|
1155
|
+
keepIframeSrcFn = () => false,
|
|
1156
|
+
newlyAddedElement = false,
|
|
1157
|
+
cssCaptured = false,
|
|
1158
|
+
_parentPath,
|
|
1159
|
+
_childIndex
|
|
1160
|
+
} = options;
|
|
1161
|
+
let { needsMask } = options;
|
|
1162
|
+
let { preserveWhiteSpace = true } = options;
|
|
1163
|
+
if (!needsMask) {
|
|
1164
|
+
const checkAncestors = needsMask === undefined;
|
|
1165
|
+
needsMask = needMaskingText(n, maskTextClass, maskTextSelector, checkAncestors);
|
|
1166
|
+
}
|
|
1167
|
+
const _serializedNode = serializeNode(n, {
|
|
1168
|
+
doc,
|
|
1169
|
+
mirror,
|
|
1170
|
+
blockClass,
|
|
1171
|
+
blockSelector,
|
|
1172
|
+
needsMask,
|
|
1173
|
+
inlineStylesheet,
|
|
1174
|
+
maskInputOptions,
|
|
1175
|
+
maskTextFn,
|
|
1176
|
+
maskInputFn,
|
|
1177
|
+
dataURLOptions,
|
|
1178
|
+
inlineImages,
|
|
1179
|
+
recordCanvas,
|
|
1180
|
+
keepIframeSrcFn,
|
|
1181
|
+
newlyAddedElement,
|
|
1182
|
+
cssCaptured
|
|
1183
|
+
});
|
|
1184
|
+
if (!_serializedNode) {
|
|
1185
|
+
console.warn(n, "not serialized");
|
|
1186
|
+
return null;
|
|
1187
|
+
}
|
|
1188
|
+
let path;
|
|
1189
|
+
if (_parentPath !== undefined && _childIndex !== undefined) {
|
|
1190
|
+
path = _parentPath === "" ? `${_childIndex}` : `${_parentPath}.${_childIndex}`;
|
|
1191
|
+
} else if (mirror.hasNode(n)) {
|
|
1192
|
+
path = mirror.getPath(n);
|
|
1193
|
+
} else {
|
|
1194
|
+
path = mirror.computePath(n);
|
|
1195
|
+
}
|
|
1196
|
+
if (!mirror.hasNode(n) && (slimDOMExcluded(_serializedNode, slimDOMOptions) || !preserveWhiteSpace && _serializedNode.type === 3 /* Text */ && !_serializedNode.textContent.replace(/^\s+|\s+$/gm, "").length)) {
|
|
1197
|
+
mirror.setPath(n, IGNORED_PATH);
|
|
1198
|
+
mirror.setMeta(n, { ..._serializedNode, path: IGNORED_PATH });
|
|
1199
|
+
return null;
|
|
1200
|
+
}
|
|
1201
|
+
const serializedNode = Object.assign(_serializedNode, { path });
|
|
1202
|
+
mirror.setPath(n, path);
|
|
1203
|
+
mirror.setMeta(n, serializedNode);
|
|
1204
|
+
if (onSerialize) {
|
|
1205
|
+
onSerialize(n);
|
|
1206
|
+
}
|
|
1207
|
+
let recordChild = !skipChild;
|
|
1208
|
+
if (serializedNode.type === 2 /* Element */) {
|
|
1209
|
+
recordChild = recordChild && !serializedNode.needBlock;
|
|
1210
|
+
serializedNode.needBlock = undefined;
|
|
1211
|
+
const shadowRootEl = dom_default.shadowRoot(n);
|
|
1212
|
+
if (shadowRootEl && isNativeShadowDom(shadowRootEl))
|
|
1213
|
+
serializedNode.isShadowHost = true;
|
|
1214
|
+
}
|
|
1215
|
+
if ((serializedNode.type === 0 /* Document */ || serializedNode.type === 2 /* Element */) && recordChild) {
|
|
1216
|
+
if (slimDOMOptions.headWhitespace && serializedNode.type === 2 /* Element */ && serializedNode.tagName === "head") {
|
|
1217
|
+
preserveWhiteSpace = false;
|
|
1218
|
+
}
|
|
1219
|
+
const bypassOptions = {
|
|
1220
|
+
doc,
|
|
1221
|
+
mirror,
|
|
1222
|
+
blockClass,
|
|
1223
|
+
blockSelector,
|
|
1224
|
+
needsMask,
|
|
1225
|
+
maskTextClass,
|
|
1226
|
+
maskTextSelector,
|
|
1227
|
+
skipChild,
|
|
1228
|
+
inlineStylesheet,
|
|
1229
|
+
maskInputOptions,
|
|
1230
|
+
maskTextFn,
|
|
1231
|
+
maskInputFn,
|
|
1232
|
+
slimDOMOptions,
|
|
1233
|
+
dataURLOptions,
|
|
1234
|
+
inlineImages,
|
|
1235
|
+
recordCanvas,
|
|
1236
|
+
preserveWhiteSpace,
|
|
1237
|
+
onSerialize,
|
|
1238
|
+
onIframeLoad,
|
|
1239
|
+
iframeLoadTimeout,
|
|
1240
|
+
onStylesheetLoad,
|
|
1241
|
+
stylesheetLoadTimeout,
|
|
1242
|
+
keepIframeSrcFn,
|
|
1243
|
+
cssCaptured: false,
|
|
1244
|
+
_parentPath: path,
|
|
1245
|
+
_childIndex: 0
|
|
1246
|
+
};
|
|
1247
|
+
if (serializedNode.type === 2 /* Element */ && serializedNode.tagName === "textarea" && serializedNode.attributes?.value !== undefined) {} else {
|
|
1248
|
+
if (serializedNode.type === 2 /* Element */ && serializedNode.attributes?._cssText !== undefined && typeof serializedNode.attributes._cssText === "string") {
|
|
1249
|
+
bypassOptions.cssCaptured = true;
|
|
1250
|
+
}
|
|
1251
|
+
let childIndex = 0;
|
|
1252
|
+
for (const childN of Array.from(dom_default.childNodes(n))) {
|
|
1253
|
+
bypassOptions._childIndex = childIndex;
|
|
1254
|
+
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
|
|
1255
|
+
if (serializedChildNode) {
|
|
1256
|
+
if (!serializedNode.childNodes)
|
|
1257
|
+
serializedNode.childNodes = [];
|
|
1258
|
+
serializedNode.childNodes.push(serializedChildNode);
|
|
1259
|
+
}
|
|
1260
|
+
childIndex++;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
let shadowRootEl = null;
|
|
1264
|
+
if (isElement(n) && (shadowRootEl = dom_default.shadowRoot(n))) {
|
|
1265
|
+
let shadowChildIndex = dom_default.childNodes(n).length;
|
|
1266
|
+
for (const childN of Array.from(dom_default.childNodes(shadowRootEl))) {
|
|
1267
|
+
bypassOptions._childIndex = shadowChildIndex;
|
|
1268
|
+
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
|
|
1269
|
+
if (serializedChildNode) {
|
|
1270
|
+
isNativeShadowDom(shadowRootEl) && (serializedChildNode.isShadow = true);
|
|
1271
|
+
if (!serializedNode.childNodes)
|
|
1272
|
+
serializedNode.childNodes = [];
|
|
1273
|
+
serializedNode.childNodes.push(serializedChildNode);
|
|
1274
|
+
}
|
|
1275
|
+
shadowChildIndex++;
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
const parent = dom_default.parentNode(n);
|
|
1280
|
+
if (parent && isShadowRoot(parent) && isNativeShadowDom(parent)) {
|
|
1281
|
+
serializedNode.isShadow = true;
|
|
1282
|
+
}
|
|
1283
|
+
if (serializedNode.type === 2 /* Element */ && serializedNode.tagName === "iframe") {
|
|
1284
|
+
onceIframeLoaded(n, () => {
|
|
1285
|
+
const iframeDoc = n.contentDocument;
|
|
1286
|
+
if (iframeDoc && onIframeLoad) {
|
|
1287
|
+
const serializedIframeNode = serializeNodeWithId(iframeDoc, {
|
|
1288
|
+
doc: iframeDoc,
|
|
1289
|
+
mirror,
|
|
1290
|
+
blockClass,
|
|
1291
|
+
blockSelector,
|
|
1292
|
+
needsMask,
|
|
1293
|
+
maskTextClass,
|
|
1294
|
+
maskTextSelector,
|
|
1295
|
+
skipChild: false,
|
|
1296
|
+
inlineStylesheet,
|
|
1297
|
+
maskInputOptions,
|
|
1298
|
+
maskTextFn,
|
|
1299
|
+
maskInputFn,
|
|
1300
|
+
slimDOMOptions,
|
|
1301
|
+
dataURLOptions,
|
|
1302
|
+
inlineImages,
|
|
1303
|
+
recordCanvas,
|
|
1304
|
+
preserveWhiteSpace,
|
|
1305
|
+
onSerialize,
|
|
1306
|
+
onIframeLoad,
|
|
1307
|
+
iframeLoadTimeout,
|
|
1308
|
+
onStylesheetLoad,
|
|
1309
|
+
stylesheetLoadTimeout,
|
|
1310
|
+
keepIframeSrcFn
|
|
1311
|
+
});
|
|
1312
|
+
if (serializedIframeNode) {
|
|
1313
|
+
onIframeLoad(n, serializedIframeNode);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}, iframeLoadTimeout);
|
|
1317
|
+
}
|
|
1318
|
+
if (serializedNode.type === 2 /* Element */ && serializedNode.tagName === "link" && typeof serializedNode.attributes?.rel === "string" && (serializedNode.attributes.rel === "stylesheet" || serializedNode.attributes.rel === "preload" && typeof serializedNode.attributes.href === "string" && extractFileExtension(serializedNode.attributes.href) === "css")) {
|
|
1319
|
+
onceStylesheetLoaded(n, () => {
|
|
1320
|
+
if (onStylesheetLoad) {
|
|
1321
|
+
const serializedLinkNode = serializeNodeWithId(n, {
|
|
1322
|
+
doc,
|
|
1323
|
+
mirror,
|
|
1324
|
+
blockClass,
|
|
1325
|
+
blockSelector,
|
|
1326
|
+
needsMask,
|
|
1327
|
+
maskTextClass,
|
|
1328
|
+
maskTextSelector,
|
|
1329
|
+
skipChild: false,
|
|
1330
|
+
inlineStylesheet,
|
|
1331
|
+
maskInputOptions,
|
|
1332
|
+
maskTextFn,
|
|
1333
|
+
maskInputFn,
|
|
1334
|
+
slimDOMOptions,
|
|
1335
|
+
dataURLOptions,
|
|
1336
|
+
inlineImages,
|
|
1337
|
+
recordCanvas,
|
|
1338
|
+
preserveWhiteSpace,
|
|
1339
|
+
onSerialize,
|
|
1340
|
+
onIframeLoad,
|
|
1341
|
+
iframeLoadTimeout,
|
|
1342
|
+
onStylesheetLoad,
|
|
1343
|
+
stylesheetLoadTimeout,
|
|
1344
|
+
keepIframeSrcFn
|
|
1345
|
+
});
|
|
1346
|
+
if (serializedLinkNode) {
|
|
1347
|
+
onStylesheetLoad(n, serializedLinkNode);
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
}, stylesheetLoadTimeout);
|
|
1351
|
+
}
|
|
1352
|
+
return serializedNode;
|
|
1353
|
+
}
|
|
1354
|
+
function snapshot(n, options) {
|
|
1355
|
+
const {
|
|
1356
|
+
mirror = new PathMirror,
|
|
1357
|
+
blockClass = "rr-block",
|
|
1358
|
+
blockSelector = null,
|
|
1359
|
+
maskTextClass = "rr-mask",
|
|
1360
|
+
maskTextSelector = null,
|
|
1361
|
+
inlineStylesheet = true,
|
|
1362
|
+
inlineImages = false,
|
|
1363
|
+
recordCanvas = false,
|
|
1364
|
+
maskAllInputs = true,
|
|
1365
|
+
maskTextFn,
|
|
1366
|
+
maskInputFn,
|
|
1367
|
+
slimDOM = false,
|
|
1368
|
+
dataURLOptions,
|
|
1369
|
+
preserveWhiteSpace,
|
|
1370
|
+
onSerialize,
|
|
1371
|
+
onIframeLoad,
|
|
1372
|
+
iframeLoadTimeout,
|
|
1373
|
+
onStylesheetLoad,
|
|
1374
|
+
stylesheetLoadTimeout,
|
|
1375
|
+
keepIframeSrcFn = () => false
|
|
1376
|
+
} = options || {};
|
|
1377
|
+
const maskInputOptions = maskAllInputs === true ? {
|
|
1378
|
+
color: true,
|
|
1379
|
+
date: true,
|
|
1380
|
+
"datetime-local": true,
|
|
1381
|
+
email: true,
|
|
1382
|
+
month: true,
|
|
1383
|
+
number: true,
|
|
1384
|
+
range: true,
|
|
1385
|
+
search: true,
|
|
1386
|
+
tel: true,
|
|
1387
|
+
text: true,
|
|
1388
|
+
time: true,
|
|
1389
|
+
url: true,
|
|
1390
|
+
week: true,
|
|
1391
|
+
textarea: true,
|
|
1392
|
+
select: true,
|
|
1393
|
+
password: true
|
|
1394
|
+
} : maskAllInputs === false ? {
|
|
1395
|
+
password: true
|
|
1396
|
+
} : maskAllInputs;
|
|
1397
|
+
const slimDOMOptions = slimDOM === true || slimDOM === "all" ? {
|
|
1398
|
+
script: true,
|
|
1399
|
+
comment: true,
|
|
1400
|
+
headFavicon: true,
|
|
1401
|
+
headWhitespace: true,
|
|
1402
|
+
headMetaDescKeywords: slimDOM === "all",
|
|
1403
|
+
headMetaSocial: true,
|
|
1404
|
+
headMetaRobots: true,
|
|
1405
|
+
headMetaHttpEquiv: true,
|
|
1406
|
+
headMetaAuthorship: true,
|
|
1407
|
+
headMetaVerification: true
|
|
1408
|
+
} : slimDOM === false ? {} : slimDOM;
|
|
1409
|
+
return serializeNodeWithId(n, {
|
|
1410
|
+
doc: n,
|
|
1411
|
+
mirror,
|
|
1412
|
+
blockClass,
|
|
1413
|
+
blockSelector,
|
|
1414
|
+
maskTextClass,
|
|
1415
|
+
maskTextSelector,
|
|
1416
|
+
skipChild: false,
|
|
1417
|
+
inlineStylesheet,
|
|
1418
|
+
maskInputOptions,
|
|
1419
|
+
maskTextFn,
|
|
1420
|
+
maskInputFn,
|
|
1421
|
+
slimDOMOptions,
|
|
1422
|
+
dataURLOptions,
|
|
1423
|
+
inlineImages,
|
|
1424
|
+
recordCanvas,
|
|
1425
|
+
preserveWhiteSpace,
|
|
1426
|
+
onSerialize,
|
|
1427
|
+
onIframeLoad,
|
|
1428
|
+
iframeLoadTimeout,
|
|
1429
|
+
onStylesheetLoad,
|
|
1430
|
+
stylesheetLoadTimeout,
|
|
1431
|
+
keepIframeSrcFn,
|
|
1432
|
+
newlyAddedElement: false
|
|
1433
|
+
});
|
|
1434
|
+
}
|
|
1435
|
+
var tagNameRegex, canvasService, canvasCtx, SRCSET_NOT_SPACES, SRCSET_COMMAS_OR_SPACES, cachedDocument, snapshot_default;
|
|
1436
|
+
var init_snapshot = __esm(() => {
|
|
1437
|
+
init_src();
|
|
1438
|
+
init_dom();
|
|
1439
|
+
init_redact_pii();
|
|
1440
|
+
init_snapshot_utils();
|
|
1441
|
+
tagNameRegex = /[^a-z0-9-_:]/;
|
|
1442
|
+
SRCSET_NOT_SPACES = /^[^ \t\n\r\u000c]+/;
|
|
1443
|
+
SRCSET_COMMAS_OR_SPACES = /^[, \t\n\r\u000c]+/;
|
|
1444
|
+
cachedDocument = new WeakMap;
|
|
1445
|
+
snapshot_default = snapshot;
|
|
1446
|
+
});
|
|
1447
|
+
|
|
1448
|
+
// ../rrweb-record/src/utils.ts
|
|
1449
|
+
function on(type, fn, target = document) {
|
|
1450
|
+
const options = { capture: true, passive: true };
|
|
1451
|
+
target.addEventListener(type, fn, options);
|
|
1452
|
+
return () => target.removeEventListener(type, fn, options);
|
|
1453
|
+
}
|
|
1454
|
+
function throttle(func, wait, options = {}) {
|
|
1455
|
+
let timeout = null;
|
|
1456
|
+
let previous = 0;
|
|
1457
|
+
return (...args) => {
|
|
1458
|
+
const now = Date.now();
|
|
1459
|
+
if (!previous && options.leading === false) {
|
|
1460
|
+
previous = now;
|
|
1461
|
+
}
|
|
1462
|
+
const remaining = wait - (now - previous);
|
|
1463
|
+
if (remaining <= 0 || remaining > wait) {
|
|
1464
|
+
if (timeout) {
|
|
1465
|
+
clearTimeout(timeout);
|
|
1466
|
+
timeout = null;
|
|
1467
|
+
}
|
|
1468
|
+
previous = now;
|
|
1469
|
+
func(args[0]);
|
|
1470
|
+
} else if (!timeout && options.trailing !== false) {
|
|
1471
|
+
timeout = setTimeout(() => {
|
|
1472
|
+
previous = options.leading === false ? 0 : Date.now();
|
|
1473
|
+
timeout = null;
|
|
1474
|
+
func(args[0]);
|
|
1475
|
+
}, remaining);
|
|
1476
|
+
}
|
|
1477
|
+
};
|
|
1478
|
+
}
|
|
1479
|
+
function hookSetter(target, key, d, isRevoked, win = window) {
|
|
1480
|
+
const original = win.Object.getOwnPropertyDescriptor(target, key);
|
|
1481
|
+
win.Object.defineProperty(target, key, isRevoked ? d : {
|
|
1482
|
+
set(value) {
|
|
1483
|
+
setTimeout(() => {
|
|
1484
|
+
d.set?.call(this, value);
|
|
1485
|
+
}, 0);
|
|
1486
|
+
if (original?.set) {
|
|
1487
|
+
original.set.call(this, value);
|
|
1488
|
+
}
|
|
1489
|
+
}
|
|
1490
|
+
});
|
|
1491
|
+
return () => hookSetter(target, key, original || {}, true);
|
|
1492
|
+
}
|
|
1493
|
+
function patch(source, name, replacement) {
|
|
1494
|
+
try {
|
|
1495
|
+
if (!(name in source)) {
|
|
1496
|
+
return () => {};
|
|
1497
|
+
}
|
|
1498
|
+
const original = source[name];
|
|
1499
|
+
const wrapped = replacement(original);
|
|
1500
|
+
if (typeof wrapped === "function") {
|
|
1501
|
+
wrapped.prototype = wrapped.prototype || {};
|
|
1502
|
+
Object.defineProperties(wrapped, {
|
|
1503
|
+
__rrweb_original__: {
|
|
1504
|
+
enumerable: false,
|
|
1505
|
+
value: original
|
|
1506
|
+
}
|
|
1507
|
+
});
|
|
1508
|
+
}
|
|
1509
|
+
source[name] = wrapped;
|
|
1510
|
+
return () => {
|
|
1511
|
+
source[name] = original;
|
|
1512
|
+
};
|
|
1513
|
+
} catch {
|
|
1514
|
+
return () => {};
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
function getWindowScroll(win) {
|
|
1518
|
+
const doc = win.document;
|
|
1519
|
+
return {
|
|
1520
|
+
left: doc.scrollingElement ? doc.scrollingElement.scrollLeft : win.pageXOffset !== undefined ? win.pageXOffset : doc.documentElement.scrollLeft || doc?.body && dom_default.parentElement(doc.body)?.scrollLeft || doc?.body?.scrollLeft || 0,
|
|
1521
|
+
top: doc.scrollingElement ? doc.scrollingElement.scrollTop : win.pageYOffset !== undefined ? win.pageYOffset : doc?.documentElement.scrollTop || doc?.body && dom_default.parentElement(doc.body)?.scrollTop || doc?.body?.scrollTop || 0
|
|
1522
|
+
};
|
|
1523
|
+
}
|
|
1524
|
+
function getWindowHeight() {
|
|
1525
|
+
return window.innerHeight || document.documentElement?.clientHeight || document.body?.clientHeight;
|
|
1526
|
+
}
|
|
1527
|
+
function getWindowWidth() {
|
|
1528
|
+
return window.innerWidth || document.documentElement?.clientWidth || document.body?.clientWidth;
|
|
1529
|
+
}
|
|
1530
|
+
function closestElementOfNode(node) {
|
|
1531
|
+
if (!node) {
|
|
1532
|
+
return null;
|
|
1533
|
+
}
|
|
1534
|
+
const el = node.nodeType === node.ELEMENT_NODE ? node : dom_default.parentElement(node);
|
|
1535
|
+
return el;
|
|
1536
|
+
}
|
|
1537
|
+
function isBlocked(node, blockClass, blockSelector, checkAncestors) {
|
|
1538
|
+
if (!node) {
|
|
1539
|
+
return false;
|
|
1540
|
+
}
|
|
1541
|
+
const el = closestElementOfNode(node);
|
|
1542
|
+
if (!el) {
|
|
1543
|
+
return false;
|
|
1544
|
+
}
|
|
1545
|
+
try {
|
|
1546
|
+
if (typeof blockClass === "string") {
|
|
1547
|
+
if (el.classList.contains(blockClass))
|
|
1548
|
+
return true;
|
|
1549
|
+
if (checkAncestors && el.closest(`.${blockClass}`) !== null)
|
|
1550
|
+
return true;
|
|
1551
|
+
} else {
|
|
1552
|
+
if (classMatchesRegex(el, blockClass, checkAncestors))
|
|
1553
|
+
return true;
|
|
1554
|
+
}
|
|
1555
|
+
} catch (_e) {}
|
|
1556
|
+
if (blockSelector) {
|
|
1557
|
+
if (el.matches(blockSelector))
|
|
1558
|
+
return true;
|
|
1559
|
+
if (checkAncestors && el.closest(blockSelector) !== null)
|
|
1560
|
+
return true;
|
|
1561
|
+
}
|
|
1562
|
+
return false;
|
|
1563
|
+
}
|
|
1564
|
+
function isSerialized(n, mirror) {
|
|
1565
|
+
return mirror.isSerialized(n);
|
|
1566
|
+
}
|
|
1567
|
+
function isIgnored(n, mirror, slimDOMOptions) {
|
|
1568
|
+
if (n.tagName === "TITLE" && slimDOMOptions.headTitleMutations) {
|
|
1569
|
+
return true;
|
|
1570
|
+
}
|
|
1571
|
+
return mirror.isIgnored(n);
|
|
1572
|
+
}
|
|
1573
|
+
function isAncestorRemoved(target, mirror) {
|
|
1574
|
+
if (isShadowRoot(target)) {
|
|
1575
|
+
return false;
|
|
1576
|
+
}
|
|
1577
|
+
if (!mirror.isSerialized(target)) {
|
|
1578
|
+
return true;
|
|
1579
|
+
}
|
|
1580
|
+
const parent = dom_default.parentNode(target);
|
|
1581
|
+
if (parent && parent.nodeType === target.DOCUMENT_NODE) {
|
|
1582
|
+
return false;
|
|
1583
|
+
}
|
|
1584
|
+
if (!parent) {
|
|
1585
|
+
return true;
|
|
1586
|
+
}
|
|
1587
|
+
return isAncestorRemoved(parent, mirror);
|
|
1588
|
+
}
|
|
1589
|
+
function legacy_isTouchEvent(event) {
|
|
1590
|
+
return Boolean(event.changedTouches);
|
|
1591
|
+
}
|
|
1592
|
+
function isSerializedIframe(n, mirror) {
|
|
1593
|
+
return Boolean(n.nodeName === "IFRAME" && mirror.getMeta(n));
|
|
1594
|
+
}
|
|
1595
|
+
function isSerializedStylesheet(n, mirror) {
|
|
1596
|
+
return Boolean(n.nodeName === "LINK" && n.nodeType === n.ELEMENT_NODE && n.getAttribute && n.getAttribute("rel") === "stylesheet" && mirror.getMeta(n));
|
|
1597
|
+
}
|
|
1598
|
+
function hasShadowRoot(n) {
|
|
1599
|
+
if (!n)
|
|
1600
|
+
return false;
|
|
1601
|
+
if (typeof n.RRNodeType === "number" && "shadowRoot" in n) {
|
|
1602
|
+
return Boolean(n.shadowRoot);
|
|
1603
|
+
}
|
|
1604
|
+
return Boolean(dom_default.shadowRoot(n));
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
class StyleSheetMirror {
|
|
1608
|
+
id = 1;
|
|
1609
|
+
styleIDMap = new WeakMap;
|
|
1610
|
+
idStyleMap = new Map;
|
|
1611
|
+
getId(stylesheet) {
|
|
1612
|
+
return this.styleIDMap.get(stylesheet) ?? -1;
|
|
1613
|
+
}
|
|
1614
|
+
has(stylesheet) {
|
|
1615
|
+
return this.styleIDMap.has(stylesheet);
|
|
1616
|
+
}
|
|
1617
|
+
add(stylesheet, id) {
|
|
1618
|
+
if (this.has(stylesheet))
|
|
1619
|
+
return this.getId(stylesheet);
|
|
1620
|
+
let newId;
|
|
1621
|
+
if (id === undefined) {
|
|
1622
|
+
newId = this.id++;
|
|
1623
|
+
} else
|
|
1624
|
+
newId = id;
|
|
1625
|
+
this.styleIDMap.set(stylesheet, newId);
|
|
1626
|
+
this.idStyleMap.set(newId, stylesheet);
|
|
1627
|
+
return newId;
|
|
1628
|
+
}
|
|
1629
|
+
getStyle(id) {
|
|
1630
|
+
return this.idStyleMap.get(id) || null;
|
|
1631
|
+
}
|
|
1632
|
+
reset() {
|
|
1633
|
+
this.styleIDMap = new WeakMap;
|
|
1634
|
+
this.idStyleMap = new Map;
|
|
1635
|
+
this.id = 1;
|
|
1636
|
+
}
|
|
1637
|
+
generateId() {
|
|
1638
|
+
return this.id++;
|
|
1639
|
+
}
|
|
1640
|
+
}
|
|
1641
|
+
function getShadowHost(n) {
|
|
1642
|
+
let shadowHost = null;
|
|
1643
|
+
if ("getRootNode" in n && dom_default.getRootNode(n)?.nodeType === Node.DOCUMENT_FRAGMENT_NODE && dom_default.host(dom_default.getRootNode(n)))
|
|
1644
|
+
shadowHost = dom_default.host(dom_default.getRootNode(n));
|
|
1645
|
+
return shadowHost;
|
|
1646
|
+
}
|
|
1647
|
+
function getRootShadowHost(n) {
|
|
1648
|
+
let rootShadowHost = n;
|
|
1649
|
+
let shadowHost;
|
|
1650
|
+
while (shadowHost = getShadowHost(rootShadowHost))
|
|
1651
|
+
rootShadowHost = shadowHost;
|
|
1652
|
+
return rootShadowHost;
|
|
1653
|
+
}
|
|
1654
|
+
function shadowHostInDom(n) {
|
|
1655
|
+
const doc = n.ownerDocument;
|
|
1656
|
+
if (!doc)
|
|
1657
|
+
return false;
|
|
1658
|
+
const shadowHost = getRootShadowHost(n);
|
|
1659
|
+
return dom_default.contains(doc, shadowHost);
|
|
1660
|
+
}
|
|
1661
|
+
function inDom(n) {
|
|
1662
|
+
const doc = n.ownerDocument;
|
|
1663
|
+
if (!doc)
|
|
1664
|
+
return false;
|
|
1665
|
+
return dom_default.contains(doc, n) || shadowHostInDom(n);
|
|
1666
|
+
}
|
|
1667
|
+
var nowTimestamp;
|
|
1668
|
+
var init_utils = __esm(() => {
|
|
1669
|
+
init_dom();
|
|
1670
|
+
init_snapshot();
|
|
1671
|
+
init_snapshot_utils();
|
|
1672
|
+
nowTimestamp = Date.now;
|
|
1673
|
+
if (!/* @__PURE__ */ /[1-9][0-9]{12}/.test(Date.now().toString())) {
|
|
1674
|
+
nowTimestamp = () => Date.now();
|
|
1675
|
+
}
|
|
1676
|
+
});
|
|
1677
|
+
|
|
1678
|
+
// ../rrweb-record/src/record/error-handler.ts
|
|
1679
|
+
function registerErrorHandler(handler) {
|
|
1680
|
+
errorHandler = handler;
|
|
1681
|
+
}
|
|
1682
|
+
function unregisterErrorHandler() {
|
|
1683
|
+
errorHandler = undefined;
|
|
1684
|
+
}
|
|
1685
|
+
var errorHandler, callbackWrapper = (cb) => {
|
|
1686
|
+
if (!errorHandler) {
|
|
1687
|
+
return cb;
|
|
1688
|
+
}
|
|
1689
|
+
const rrwebWrapped = (...rest) => {
|
|
1690
|
+
try {
|
|
1691
|
+
return cb(...rest);
|
|
1692
|
+
} catch (error) {
|
|
1693
|
+
if (errorHandler && errorHandler(error) === true) {
|
|
1694
|
+
return;
|
|
1695
|
+
}
|
|
1696
|
+
throw error;
|
|
1697
|
+
}
|
|
1698
|
+
};
|
|
1699
|
+
return rrwebWrapped;
|
|
1700
|
+
};
|
|
1701
|
+
|
|
1702
|
+
// ../rrweb-record/src/record/observers/font-observer.ts
|
|
1703
|
+
var exports_font_observer = {};
|
|
1704
|
+
__export(exports_font_observer, {
|
|
1705
|
+
initFontObserver: () => initFontObserver
|
|
1706
|
+
});
|
|
1707
|
+
function initFontObserver({ fontCb, doc }) {
|
|
1708
|
+
const win = doc.defaultView;
|
|
1709
|
+
if (!win) {
|
|
1710
|
+
return () => {};
|
|
1711
|
+
}
|
|
1712
|
+
const handlers = [];
|
|
1713
|
+
const fontMap = new WeakMap;
|
|
1714
|
+
const originalFontFace = win.FontFace;
|
|
1715
|
+
win.FontFace = function FontFace(family, source, descriptors) {
|
|
1716
|
+
const fontFace = new originalFontFace(family, source, descriptors);
|
|
1717
|
+
fontMap.set(fontFace, {
|
|
1718
|
+
family,
|
|
1719
|
+
buffer: typeof source !== "string",
|
|
1720
|
+
descriptors,
|
|
1721
|
+
fontSource: typeof source === "string" ? source : JSON.stringify(Array.from(new Uint8Array(source instanceof ArrayBuffer ? source : source.buffer)))
|
|
1722
|
+
});
|
|
1723
|
+
return fontFace;
|
|
1724
|
+
};
|
|
1725
|
+
const restoreHandler = patch(doc.fonts, "add", (original) => function(fontFace) {
|
|
1726
|
+
setTimeout(callbackWrapper(() => {
|
|
1727
|
+
const p = fontMap.get(fontFace);
|
|
1728
|
+
if (p) {
|
|
1729
|
+
fontCb(p);
|
|
1730
|
+
fontMap.delete(fontFace);
|
|
1731
|
+
}
|
|
1732
|
+
}), 0);
|
|
1733
|
+
return original.apply(this, [fontFace]);
|
|
1734
|
+
});
|
|
1735
|
+
handlers.push(() => {
|
|
1736
|
+
win.FontFace = originalFontFace;
|
|
1737
|
+
});
|
|
1738
|
+
handlers.push(restoreHandler);
|
|
1739
|
+
return callbackWrapper(() => {
|
|
1740
|
+
handlers.forEach((h) => h());
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
var init_font_observer = __esm(() => {
|
|
1744
|
+
init_utils();
|
|
1745
|
+
});
|
|
1746
|
+
|
|
1747
|
+
// ../../node_modules/.bun/base64-arraybuffer@1.0.2/node_modules/base64-arraybuffer/dist/base64-arraybuffer.es5.js
|
|
1748
|
+
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", lookup, i, encode = function(arraybuffer) {
|
|
1749
|
+
var bytes = new Uint8Array(arraybuffer), i2, len = bytes.length, base64 = "";
|
|
1750
|
+
for (i2 = 0;i2 < len; i2 += 3) {
|
|
1751
|
+
base64 += chars[bytes[i2] >> 2];
|
|
1752
|
+
base64 += chars[(bytes[i2] & 3) << 4 | bytes[i2 + 1] >> 4];
|
|
1753
|
+
base64 += chars[(bytes[i2 + 1] & 15) << 2 | bytes[i2 + 2] >> 6];
|
|
1754
|
+
base64 += chars[bytes[i2 + 2] & 63];
|
|
1755
|
+
}
|
|
1756
|
+
if (len % 3 === 2) {
|
|
1757
|
+
base64 = base64.substring(0, base64.length - 1) + "=";
|
|
1758
|
+
} else if (len % 3 === 1) {
|
|
1759
|
+
base64 = base64.substring(0, base64.length - 2) + "==";
|
|
1760
|
+
}
|
|
1761
|
+
return base64;
|
|
1762
|
+
};
|
|
1763
|
+
var init_base64_arraybuffer_es5 = __esm(() => {
|
|
1764
|
+
lookup = typeof Uint8Array === "undefined" ? [] : new Uint8Array(256);
|
|
1765
|
+
for (i = 0;i < chars.length; i++) {
|
|
1766
|
+
lookup[chars.charCodeAt(i)] = i;
|
|
1767
|
+
}
|
|
1768
|
+
});
|
|
1769
|
+
|
|
1770
|
+
// ../rrweb-record/src/record/observers/canvas/serialize-args.ts
|
|
1771
|
+
function variableListFor(ctx, ctor) {
|
|
1772
|
+
let contextMap = canvasVarMap.get(ctx);
|
|
1773
|
+
if (!contextMap) {
|
|
1774
|
+
contextMap = new Map;
|
|
1775
|
+
canvasVarMap.set(ctx, contextMap);
|
|
1776
|
+
}
|
|
1777
|
+
if (!contextMap.has(ctor)) {
|
|
1778
|
+
contextMap.set(ctor, []);
|
|
1779
|
+
}
|
|
1780
|
+
return contextMap.get(ctor);
|
|
1781
|
+
}
|
|
1782
|
+
function serializeArg(value, win, ctx) {
|
|
1783
|
+
if (Array.isArray(value)) {
|
|
1784
|
+
return value.map((arg) => serializeArg(arg, win, ctx));
|
|
1785
|
+
}
|
|
1786
|
+
if (value === null) {
|
|
1787
|
+
return value;
|
|
1788
|
+
}
|
|
1789
|
+
if (value instanceof Float32Array || value instanceof Float64Array || value instanceof Int32Array || value instanceof Uint32Array || value instanceof Uint8Array || value instanceof Uint16Array || value instanceof Int16Array || value instanceof Int8Array || value instanceof Uint8ClampedArray) {
|
|
1790
|
+
const name = value.constructor.name;
|
|
1791
|
+
return {
|
|
1792
|
+
rr_type: name,
|
|
1793
|
+
args: [Object.values(value)]
|
|
1794
|
+
};
|
|
1795
|
+
}
|
|
1796
|
+
if (value instanceof ArrayBuffer) {
|
|
1797
|
+
const name = value.constructor.name;
|
|
1798
|
+
const base64 = encode(value);
|
|
1799
|
+
return {
|
|
1800
|
+
rr_type: name,
|
|
1801
|
+
base64
|
|
1802
|
+
};
|
|
1803
|
+
}
|
|
1804
|
+
if (value instanceof DataView) {
|
|
1805
|
+
const name = value.constructor.name;
|
|
1806
|
+
return {
|
|
1807
|
+
rr_type: name,
|
|
1808
|
+
args: [serializeArg(value.buffer, win, ctx), value.byteOffset, value.byteLength]
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
if (value instanceof HTMLImageElement) {
|
|
1812
|
+
const name = value.constructor.name;
|
|
1813
|
+
const { src } = value;
|
|
1814
|
+
return {
|
|
1815
|
+
rr_type: name,
|
|
1816
|
+
src
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
if (value instanceof HTMLCanvasElement) {
|
|
1820
|
+
const name = "HTMLImageElement";
|
|
1821
|
+
const src = value.toDataURL();
|
|
1822
|
+
return {
|
|
1823
|
+
rr_type: name,
|
|
1824
|
+
src
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
if (value instanceof ImageData) {
|
|
1828
|
+
const name = value.constructor.name;
|
|
1829
|
+
return {
|
|
1830
|
+
rr_type: name,
|
|
1831
|
+
args: [serializeArg(value.data, win, ctx), value.width, value.height]
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
if (isInstanceOfWebGLObject(value, win) || typeof value === "object") {
|
|
1835
|
+
const name = value.constructor.name;
|
|
1836
|
+
const index = saveWebGLVar(value, win, ctx);
|
|
1837
|
+
return {
|
|
1838
|
+
rr_type: name,
|
|
1839
|
+
index
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
return value;
|
|
1843
|
+
}
|
|
1844
|
+
var canvasVarMap, saveWebGLVar = (value, win, ctx) => {
|
|
1845
|
+
if (!value || !(isInstanceOfWebGLObject(value, win) || typeof value === "object"))
|
|
1846
|
+
return;
|
|
1847
|
+
const name = value.constructor.name;
|
|
1848
|
+
const list = variableListFor(ctx, name);
|
|
1849
|
+
let index = list.indexOf(value);
|
|
1850
|
+
if (index === -1) {
|
|
1851
|
+
index = list.length;
|
|
1852
|
+
list.push(value);
|
|
1853
|
+
}
|
|
1854
|
+
return index;
|
|
1855
|
+
}, serializeArgs = (args, win, ctx) => {
|
|
1856
|
+
return args.map((arg) => serializeArg(arg, win, ctx));
|
|
1857
|
+
}, isInstanceOfWebGLObject = (value, win) => {
|
|
1858
|
+
const webGLConstructorNames = [
|
|
1859
|
+
"WebGLActiveInfo",
|
|
1860
|
+
"WebGLBuffer",
|
|
1861
|
+
"WebGLFramebuffer",
|
|
1862
|
+
"WebGLProgram",
|
|
1863
|
+
"WebGLRenderbuffer",
|
|
1864
|
+
"WebGLShader",
|
|
1865
|
+
"WebGLShaderPrecisionFormat",
|
|
1866
|
+
"WebGLTexture",
|
|
1867
|
+
"WebGLUniformLocation",
|
|
1868
|
+
"WebGLVertexArrayObject",
|
|
1869
|
+
"WebGLVertexArrayObjectOES"
|
|
1870
|
+
];
|
|
1871
|
+
const supportedWebGLConstructorNames = webGLConstructorNames.filter((name) => typeof win[name] === "function");
|
|
1872
|
+
return Boolean(supportedWebGLConstructorNames.find((name) => value instanceof win[name]));
|
|
1873
|
+
};
|
|
1874
|
+
var init_serialize_args = __esm(() => {
|
|
1875
|
+
init_base64_arraybuffer_es5();
|
|
1876
|
+
canvasVarMap = new Map;
|
|
1877
|
+
});
|
|
1878
|
+
|
|
1879
|
+
// ../rrweb-record/src/record/observers/canvas/2d.ts
|
|
1880
|
+
function initCanvas2DMutationObserver(cb, win, blockClass, blockSelector) {
|
|
1881
|
+
const handlers = [];
|
|
1882
|
+
const props2D = Object.getOwnPropertyNames(win.CanvasRenderingContext2D.prototype);
|
|
1883
|
+
for (const prop of props2D) {
|
|
1884
|
+
try {
|
|
1885
|
+
if (typeof win.CanvasRenderingContext2D.prototype[prop] !== "function") {
|
|
1886
|
+
continue;
|
|
1887
|
+
}
|
|
1888
|
+
const restoreHandler = patch(win.CanvasRenderingContext2D.prototype, prop, (original) => function(...args) {
|
|
1889
|
+
if (!isBlocked(this.canvas, blockClass, blockSelector, true)) {
|
|
1890
|
+
setTimeout(() => {
|
|
1891
|
+
const recordArgs = serializeArgs(args, win, this);
|
|
1892
|
+
cb(this.canvas, {
|
|
1893
|
+
type: 0 /* 2D */,
|
|
1894
|
+
property: prop,
|
|
1895
|
+
args: recordArgs
|
|
1896
|
+
});
|
|
1897
|
+
}, 0);
|
|
1898
|
+
}
|
|
1899
|
+
return original.apply(this, args);
|
|
1900
|
+
});
|
|
1901
|
+
handlers.push(restoreHandler);
|
|
1902
|
+
} catch {
|
|
1903
|
+
const hookHandler = hookSetter(win.CanvasRenderingContext2D.prototype, prop, {
|
|
1904
|
+
set(v) {
|
|
1905
|
+
cb(this.canvas, {
|
|
1906
|
+
type: 0 /* 2D */,
|
|
1907
|
+
property: prop,
|
|
1908
|
+
args: [v],
|
|
1909
|
+
setter: true
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
});
|
|
1913
|
+
handlers.push(hookHandler);
|
|
1914
|
+
}
|
|
1915
|
+
}
|
|
1916
|
+
return () => {
|
|
1917
|
+
handlers.forEach((h) => h());
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
var init_2d = __esm(() => {
|
|
1921
|
+
init_src();
|
|
1922
|
+
init_utils();
|
|
1923
|
+
init_serialize_args();
|
|
1924
|
+
});
|
|
1925
|
+
|
|
1926
|
+
// ../rrweb-record/src/record/observers/canvas/canvas.ts
|
|
1927
|
+
function getNormalizedContextName(contextType) {
|
|
1928
|
+
return contextType === "experimental-webgl" ? "webgl" : contextType;
|
|
1929
|
+
}
|
|
1930
|
+
function initCanvasContextObserver(win, blockClass, blockSelector, setPreserveDrawingBufferToTrue) {
|
|
1931
|
+
const handlers = [];
|
|
1932
|
+
try {
|
|
1933
|
+
const restoreHandler = patch(win.HTMLCanvasElement.prototype, "getContext", (original) => function(contextType, ...args) {
|
|
1934
|
+
if (!isBlocked(this, blockClass, blockSelector, true)) {
|
|
1935
|
+
const ctxName = getNormalizedContextName(contextType);
|
|
1936
|
+
if (!("__context" in this))
|
|
1937
|
+
this.__context = ctxName;
|
|
1938
|
+
if (setPreserveDrawingBufferToTrue && ["webgl", "webgl2"].includes(ctxName)) {
|
|
1939
|
+
if (args[0] && typeof args[0] === "object") {
|
|
1940
|
+
const contextAttributes = args[0];
|
|
1941
|
+
if (!contextAttributes.preserveDrawingBuffer) {
|
|
1942
|
+
contextAttributes.preserveDrawingBuffer = true;
|
|
1943
|
+
}
|
|
1944
|
+
} else {
|
|
1945
|
+
args.splice(0, 1, {
|
|
1946
|
+
preserveDrawingBuffer: true
|
|
1947
|
+
});
|
|
1948
|
+
}
|
|
1949
|
+
}
|
|
1950
|
+
}
|
|
1951
|
+
return original.apply(this, [contextType, ...args]);
|
|
1952
|
+
});
|
|
1953
|
+
handlers.push(restoreHandler);
|
|
1954
|
+
} catch {
|
|
1955
|
+
console.error("failed to patch HTMLCanvasElement.prototype.getContext");
|
|
1956
|
+
}
|
|
1957
|
+
return () => {
|
|
1958
|
+
handlers.forEach((h) => h());
|
|
1959
|
+
};
|
|
1960
|
+
}
|
|
1961
|
+
var init_canvas = __esm(() => {
|
|
1962
|
+
init_utils();
|
|
1963
|
+
});
|
|
1964
|
+
|
|
1965
|
+
// ../rrweb-record/src/record/observers/canvas/webgl.ts
|
|
1966
|
+
function patchGLPrototype(prototype, type, cb, blockClass, blockSelector, win) {
|
|
1967
|
+
const handlers = [];
|
|
1968
|
+
const props = Object.getOwnPropertyNames(prototype);
|
|
1969
|
+
for (const prop of props) {
|
|
1970
|
+
if (["isContextLost", "canvas", "drawingBufferWidth", "drawingBufferHeight"].includes(prop)) {
|
|
1971
|
+
continue;
|
|
1972
|
+
}
|
|
1973
|
+
try {
|
|
1974
|
+
if (typeof prototype[prop] !== "function") {
|
|
1975
|
+
continue;
|
|
1976
|
+
}
|
|
1977
|
+
const restoreHandler = patch(prototype, prop, (original) => function(...args) {
|
|
1978
|
+
const result = original.apply(this, args);
|
|
1979
|
+
saveWebGLVar(result, win, this);
|
|
1980
|
+
if ("tagName" in this.canvas && !isBlocked(this.canvas, blockClass, blockSelector, true)) {
|
|
1981
|
+
const recordArgs = serializeArgs(args, win, this);
|
|
1982
|
+
const mutation = {
|
|
1983
|
+
type,
|
|
1984
|
+
property: prop,
|
|
1985
|
+
args: recordArgs
|
|
1986
|
+
};
|
|
1987
|
+
cb(this.canvas, mutation);
|
|
1988
|
+
}
|
|
1989
|
+
return result;
|
|
1990
|
+
});
|
|
1991
|
+
handlers.push(restoreHandler);
|
|
1992
|
+
} catch {
|
|
1993
|
+
const hookHandler = hookSetter(prototype, prop, {
|
|
1994
|
+
set(v) {
|
|
1995
|
+
cb(this.canvas, {
|
|
1996
|
+
type,
|
|
1997
|
+
property: prop,
|
|
1998
|
+
args: [v],
|
|
1999
|
+
setter: true
|
|
2000
|
+
});
|
|
2001
|
+
}
|
|
2002
|
+
});
|
|
2003
|
+
handlers.push(hookHandler);
|
|
2004
|
+
}
|
|
2005
|
+
}
|
|
2006
|
+
return handlers;
|
|
2007
|
+
}
|
|
2008
|
+
function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector) {
|
|
2009
|
+
const handlers = [];
|
|
2010
|
+
handlers.push(...patchGLPrototype(win.WebGLRenderingContext.prototype, 1 /* WebGL */, cb, blockClass, blockSelector, win));
|
|
2011
|
+
if (typeof win.WebGL2RenderingContext !== "undefined") {
|
|
2012
|
+
handlers.push(...patchGLPrototype(win.WebGL2RenderingContext.prototype, 2 /* WebGL2 */, cb, blockClass, blockSelector, win));
|
|
2013
|
+
}
|
|
2014
|
+
return () => {
|
|
2015
|
+
handlers.forEach((h) => h());
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
var init_webgl = __esm(() => {
|
|
2019
|
+
init_src();
|
|
2020
|
+
init_utils();
|
|
2021
|
+
init_serialize_args();
|
|
2022
|
+
});
|
|
2023
|
+
|
|
2024
|
+
// ../rrweb-record/src/record/observers/canvas/canvas-manager.ts
|
|
2025
|
+
var exports_canvas_manager = {};
|
|
2026
|
+
__export(exports_canvas_manager, {
|
|
2027
|
+
CanvasManager: () => CanvasManager
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
class CanvasManager {
|
|
2031
|
+
pendingCanvasMutations = new Map;
|
|
2032
|
+
rafStamps = { latestId: 0, invokeId: null };
|
|
2033
|
+
mirror;
|
|
2034
|
+
mutationCb;
|
|
2035
|
+
resetObservers;
|
|
2036
|
+
frozen = false;
|
|
2037
|
+
locked = false;
|
|
2038
|
+
reset() {
|
|
2039
|
+
this.pendingCanvasMutations.clear();
|
|
2040
|
+
this.resetObservers?.();
|
|
2041
|
+
}
|
|
2042
|
+
freeze() {
|
|
2043
|
+
this.frozen = true;
|
|
2044
|
+
}
|
|
2045
|
+
unfreeze() {
|
|
2046
|
+
this.frozen = false;
|
|
2047
|
+
}
|
|
2048
|
+
lock() {
|
|
2049
|
+
this.locked = true;
|
|
2050
|
+
}
|
|
2051
|
+
unlock() {
|
|
2052
|
+
this.locked = false;
|
|
2053
|
+
}
|
|
2054
|
+
constructor(options) {
|
|
2055
|
+
const {
|
|
2056
|
+
sampling = "all",
|
|
2057
|
+
win,
|
|
2058
|
+
blockClass,
|
|
2059
|
+
blockSelector,
|
|
2060
|
+
recordCanvas,
|
|
2061
|
+
dataURLOptions
|
|
2062
|
+
} = options;
|
|
2063
|
+
this.mutationCb = options.mutationCb;
|
|
2064
|
+
this.mirror = options.mirror;
|
|
2065
|
+
if (recordCanvas && sampling === "all")
|
|
2066
|
+
this.initCanvasMutationObserver(win, blockClass, blockSelector);
|
|
2067
|
+
if (recordCanvas && typeof sampling === "number")
|
|
2068
|
+
this.initCanvasFPSObserver(sampling, win, blockClass, blockSelector, {
|
|
2069
|
+
dataURLOptions
|
|
2070
|
+
});
|
|
2071
|
+
}
|
|
2072
|
+
processMutation = (target, mutation) => {
|
|
2073
|
+
const newFrame = this.rafStamps.invokeId && this.rafStamps.latestId !== this.rafStamps.invokeId;
|
|
2074
|
+
if (newFrame || !this.rafStamps.invokeId)
|
|
2075
|
+
this.rafStamps.invokeId = this.rafStamps.latestId;
|
|
2076
|
+
if (!this.pendingCanvasMutations.has(target)) {
|
|
2077
|
+
this.pendingCanvasMutations.set(target, []);
|
|
2078
|
+
}
|
|
2079
|
+
this.pendingCanvasMutations.get(target)?.push(mutation);
|
|
2080
|
+
};
|
|
2081
|
+
initCanvasFPSObserver(fps, win, blockClass, blockSelector, options) {
|
|
2082
|
+
const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, true);
|
|
2083
|
+
const snapshotInProgressMap = new Map;
|
|
2084
|
+
let nextWorkerId = 1;
|
|
2085
|
+
const workerIdToPath = new Map;
|
|
2086
|
+
const worker = {
|
|
2087
|
+
postMessage() {},
|
|
2088
|
+
onmessage() {}
|
|
2089
|
+
};
|
|
2090
|
+
worker.onmessage = (e) => {
|
|
2091
|
+
const workerPath = workerIdToPath.get(e.data.id) ?? "";
|
|
2092
|
+
snapshotInProgressMap.set(workerPath, false);
|
|
2093
|
+
if (!("base64" in e.data))
|
|
2094
|
+
return;
|
|
2095
|
+
const { base64, type, width, height } = e.data;
|
|
2096
|
+
this.mutationCb({
|
|
2097
|
+
path: workerPath,
|
|
2098
|
+
type: 0 /* 2D */,
|
|
2099
|
+
commands: [
|
|
2100
|
+
{
|
|
2101
|
+
property: "clearRect",
|
|
2102
|
+
args: [0, 0, width, height]
|
|
2103
|
+
},
|
|
2104
|
+
{
|
|
2105
|
+
property: "drawImage",
|
|
2106
|
+
args: [
|
|
2107
|
+
{
|
|
2108
|
+
rr_type: "ImageBitmap",
|
|
2109
|
+
args: [
|
|
2110
|
+
{
|
|
2111
|
+
rr_type: "Blob",
|
|
2112
|
+
data: [{ rr_type: "ArrayBuffer", base64 }],
|
|
2113
|
+
type
|
|
2114
|
+
}
|
|
2115
|
+
]
|
|
2116
|
+
},
|
|
2117
|
+
0,
|
|
2118
|
+
0
|
|
2119
|
+
]
|
|
2120
|
+
}
|
|
2121
|
+
]
|
|
2122
|
+
});
|
|
2123
|
+
};
|
|
2124
|
+
const timeBetweenSnapshots = 1000 / fps;
|
|
2125
|
+
let lastSnapshotTime = 0;
|
|
2126
|
+
let rafId;
|
|
2127
|
+
const getCanvas = () => {
|
|
2128
|
+
const matchedCanvas = [];
|
|
2129
|
+
win.document.querySelectorAll("canvas").forEach((canvas) => {
|
|
2130
|
+
if (!isBlocked(canvas, blockClass, blockSelector, true)) {
|
|
2131
|
+
matchedCanvas.push(canvas);
|
|
2132
|
+
}
|
|
2133
|
+
});
|
|
2134
|
+
return matchedCanvas;
|
|
2135
|
+
};
|
|
2136
|
+
const takeCanvasSnapshots = (timestamp) => {
|
|
2137
|
+
if (lastSnapshotTime && timestamp - lastSnapshotTime < timeBetweenSnapshots) {
|
|
2138
|
+
rafId = requestAnimationFrame(takeCanvasSnapshots);
|
|
2139
|
+
return;
|
|
2140
|
+
}
|
|
2141
|
+
lastSnapshotTime = timestamp;
|
|
2142
|
+
getCanvas().forEach(async (canvas) => {
|
|
2143
|
+
const canvasPath = this.mirror.getPath(canvas);
|
|
2144
|
+
if (snapshotInProgressMap.get(canvasPath))
|
|
2145
|
+
return;
|
|
2146
|
+
if (canvas.width === 0 || canvas.height === 0)
|
|
2147
|
+
return;
|
|
2148
|
+
snapshotInProgressMap.set(canvasPath, true);
|
|
2149
|
+
if (["webgl", "webgl2"].includes(canvas.__context)) {
|
|
2150
|
+
const context = canvas.getContext(canvas.__context);
|
|
2151
|
+
if (context?.getContextAttributes()?.preserveDrawingBuffer === false) {
|
|
2152
|
+
context.clear(context.COLOR_BUFFER_BIT);
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
const bitmap = await createImageBitmap(canvas);
|
|
2156
|
+
const workerId = nextWorkerId++;
|
|
2157
|
+
workerIdToPath.set(workerId, canvasPath);
|
|
2158
|
+
worker.postMessage({
|
|
2159
|
+
id: workerId,
|
|
2160
|
+
bitmap,
|
|
2161
|
+
width: canvas.width,
|
|
2162
|
+
height: canvas.height,
|
|
2163
|
+
dataURLOptions: options.dataURLOptions
|
|
2164
|
+
}, [bitmap]);
|
|
2165
|
+
});
|
|
2166
|
+
rafId = requestAnimationFrame(takeCanvasSnapshots);
|
|
2167
|
+
};
|
|
2168
|
+
rafId = requestAnimationFrame(takeCanvasSnapshots);
|
|
2169
|
+
this.resetObservers = () => {
|
|
2170
|
+
canvasContextReset();
|
|
2171
|
+
cancelAnimationFrame(rafId);
|
|
2172
|
+
};
|
|
2173
|
+
}
|
|
2174
|
+
initCanvasMutationObserver(win, blockClass, blockSelector) {
|
|
2175
|
+
this.startRAFTimestamping();
|
|
2176
|
+
this.startPendingCanvasMutationFlusher();
|
|
2177
|
+
const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, false);
|
|
2178
|
+
const canvas2DReset = initCanvas2DMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector);
|
|
2179
|
+
const canvasWebGL1and2Reset = initCanvasWebGLMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector);
|
|
2180
|
+
this.resetObservers = () => {
|
|
2181
|
+
canvasContextReset();
|
|
2182
|
+
canvas2DReset();
|
|
2183
|
+
canvasWebGL1and2Reset();
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2186
|
+
startPendingCanvasMutationFlusher() {
|
|
2187
|
+
requestAnimationFrame(() => this.flushPendingCanvasMutations());
|
|
2188
|
+
}
|
|
2189
|
+
startRAFTimestamping() {
|
|
2190
|
+
const setLatestRAFTimestamp = (timestamp) => {
|
|
2191
|
+
this.rafStamps.latestId = timestamp;
|
|
2192
|
+
requestAnimationFrame(setLatestRAFTimestamp);
|
|
2193
|
+
};
|
|
2194
|
+
requestAnimationFrame(setLatestRAFTimestamp);
|
|
2195
|
+
}
|
|
2196
|
+
flushPendingCanvasMutations() {
|
|
2197
|
+
this.pendingCanvasMutations.forEach((_values, canvas) => {
|
|
2198
|
+
const canvasPath = this.mirror.getPath(canvas);
|
|
2199
|
+
this.flushPendingCanvasMutationFor(canvas, canvasPath);
|
|
2200
|
+
});
|
|
2201
|
+
requestAnimationFrame(() => this.flushPendingCanvasMutations());
|
|
2202
|
+
}
|
|
2203
|
+
flushPendingCanvasMutationFor(canvas, path) {
|
|
2204
|
+
if (this.frozen || this.locked) {
|
|
2205
|
+
return;
|
|
2206
|
+
}
|
|
2207
|
+
const valuesWithType = this.pendingCanvasMutations.get(canvas);
|
|
2208
|
+
if (!valuesWithType || !path)
|
|
2209
|
+
return;
|
|
2210
|
+
const values = valuesWithType.map((value) => {
|
|
2211
|
+
const { type: type2, ...rest } = value;
|
|
2212
|
+
return rest;
|
|
2213
|
+
});
|
|
2214
|
+
const { type } = valuesWithType[0];
|
|
2215
|
+
this.mutationCb({ path, type, commands: values });
|
|
2216
|
+
this.pendingCanvasMutations.delete(canvas);
|
|
2217
|
+
}
|
|
2218
|
+
}
|
|
2219
|
+
var init_canvas_manager = __esm(() => {
|
|
2220
|
+
init_src();
|
|
2221
|
+
init_utils();
|
|
2222
|
+
init_2d();
|
|
2223
|
+
init_canvas();
|
|
2224
|
+
init_webgl();
|
|
2225
|
+
});
|
|
2226
|
+
|
|
2227
|
+
// ../rrweb-record/src/record/index.ts
|
|
2228
|
+
init_src();
|
|
2229
|
+
init_dom();
|
|
2230
|
+
init_snapshot();
|
|
2231
|
+
init_snapshot_utils();
|
|
2232
|
+
init_utils();
|
|
2233
|
+
|
|
2234
|
+
// ../rrweb-record/src/record/iframe-manager.ts
|
|
2235
|
+
init_src();
|
|
2236
|
+
|
|
2237
|
+
// ../rrweb-record/src/record/cross-origin-iframe-mirror.ts
|
|
2238
|
+
class CrossOriginIframeMirror {
|
|
2239
|
+
generateIdFn;
|
|
2240
|
+
iframeLocalToParentMap = new WeakMap;
|
|
2241
|
+
iframeParentToLocalMap = new WeakMap;
|
|
2242
|
+
constructor(generateIdFn) {
|
|
2243
|
+
this.generateIdFn = generateIdFn;
|
|
2244
|
+
}
|
|
2245
|
+
getPath(iframe, remotePath, localToParentMap, parentToLocalMap) {
|
|
2246
|
+
const l2p = localToParentMap || this.getLocalToParentMap(iframe);
|
|
2247
|
+
const p2l = parentToLocalMap || this.getParentToLocalMap(iframe);
|
|
2248
|
+
let parentPath = l2p.get(remotePath);
|
|
2249
|
+
if (parentPath === undefined) {
|
|
2250
|
+
parentPath = this.generateIdFn();
|
|
2251
|
+
l2p.set(remotePath, parentPath);
|
|
2252
|
+
p2l.set(parentPath, remotePath);
|
|
2253
|
+
}
|
|
2254
|
+
return parentPath;
|
|
2255
|
+
}
|
|
2256
|
+
getId = this.getPath;
|
|
2257
|
+
getPaths(iframe, remotePaths) {
|
|
2258
|
+
const l2p = this.getLocalToParentMap(iframe);
|
|
2259
|
+
const p2l = this.getParentToLocalMap(iframe);
|
|
2260
|
+
return remotePaths.map((p) => this.getPath(iframe, p, l2p, p2l));
|
|
2261
|
+
}
|
|
2262
|
+
getIds = this.getPaths;
|
|
2263
|
+
getRemotePath(iframe, parentPath, map) {
|
|
2264
|
+
const p2l = map || this.getParentToLocalMap(iframe);
|
|
2265
|
+
if (typeof parentPath !== typeof this.generateIdFn())
|
|
2266
|
+
return parentPath;
|
|
2267
|
+
const remotePath = p2l.get(parentPath);
|
|
2268
|
+
if (remotePath === undefined) {
|
|
2269
|
+
return typeof parentPath === "string" ? "" : -1;
|
|
2270
|
+
}
|
|
2271
|
+
return remotePath;
|
|
2272
|
+
}
|
|
2273
|
+
getRemotePaths(iframe, parentPaths) {
|
|
2274
|
+
const p2l = this.getParentToLocalMap(iframe);
|
|
2275
|
+
return parentPaths.map((p) => this.getRemotePath(iframe, p, p2l));
|
|
2276
|
+
}
|
|
2277
|
+
getRemoteId = this.getRemotePath;
|
|
2278
|
+
getRemoteIds = this.getRemotePaths;
|
|
2279
|
+
reset(iframe) {
|
|
2280
|
+
if (!iframe) {
|
|
2281
|
+
this.iframeLocalToParentMap = new WeakMap;
|
|
2282
|
+
this.iframeParentToLocalMap = new WeakMap;
|
|
2283
|
+
return;
|
|
2284
|
+
}
|
|
2285
|
+
this.iframeLocalToParentMap.delete(iframe);
|
|
2286
|
+
this.iframeParentToLocalMap.delete(iframe);
|
|
2287
|
+
}
|
|
2288
|
+
getLocalToParentMap(iframe) {
|
|
2289
|
+
let map = this.iframeLocalToParentMap.get(iframe);
|
|
2290
|
+
if (!map) {
|
|
2291
|
+
map = new Map;
|
|
2292
|
+
this.iframeLocalToParentMap.set(iframe, map);
|
|
2293
|
+
}
|
|
2294
|
+
return map;
|
|
2295
|
+
}
|
|
2296
|
+
getParentToLocalMap(iframe) {
|
|
2297
|
+
let map = this.iframeParentToLocalMap.get(iframe);
|
|
2298
|
+
if (!map) {
|
|
2299
|
+
map = new Map;
|
|
2300
|
+
this.iframeParentToLocalMap.set(iframe, map);
|
|
2301
|
+
}
|
|
2302
|
+
return map;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
// ../rrweb-record/src/record/iframe-manager.ts
|
|
2307
|
+
var _crossOriginPathCounter = 1;
|
|
2308
|
+
function genCrossOriginPath() {
|
|
2309
|
+
return `__xo_${_crossOriginPathCounter++}`;
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
class IframeManager {
|
|
2313
|
+
iframes = new WeakMap;
|
|
2314
|
+
crossOriginIframeMap = new WeakMap;
|
|
2315
|
+
crossOriginIframeMirror = new CrossOriginIframeMirror(genCrossOriginPath);
|
|
2316
|
+
crossOriginIframeStyleMirror;
|
|
2317
|
+
crossOriginIframeRootIdMap = new WeakMap;
|
|
2318
|
+
mirror;
|
|
2319
|
+
mutationCb;
|
|
2320
|
+
wrappedEmit;
|
|
2321
|
+
loadListener;
|
|
2322
|
+
stylesheetManager;
|
|
2323
|
+
recordCrossOriginIframes;
|
|
2324
|
+
constructor(options) {
|
|
2325
|
+
this.mutationCb = options.mutationCb;
|
|
2326
|
+
this.wrappedEmit = options.wrappedEmit;
|
|
2327
|
+
this.stylesheetManager = options.stylesheetManager;
|
|
2328
|
+
this.recordCrossOriginIframes = options.recordCrossOriginIframes;
|
|
2329
|
+
this.crossOriginIframeStyleMirror = new CrossOriginIframeMirror(this.stylesheetManager.styleMirror.generateId.bind(this.stylesheetManager.styleMirror));
|
|
2330
|
+
this.mirror = options.mirror;
|
|
2331
|
+
if (this.recordCrossOriginIframes) {
|
|
2332
|
+
window.addEventListener("message", this.handleMessage.bind(this));
|
|
2333
|
+
}
|
|
2334
|
+
}
|
|
2335
|
+
addIframe(iframeEl) {
|
|
2336
|
+
this.iframes.set(iframeEl, true);
|
|
2337
|
+
if (iframeEl.contentWindow)
|
|
2338
|
+
this.crossOriginIframeMap.set(iframeEl.contentWindow, iframeEl);
|
|
2339
|
+
}
|
|
2340
|
+
addLoadListener(cb) {
|
|
2341
|
+
this.loadListener = cb;
|
|
2342
|
+
}
|
|
2343
|
+
attachIframe(iframeEl, childSn) {
|
|
2344
|
+
this.mutationCb({
|
|
2345
|
+
adds: [
|
|
2346
|
+
{
|
|
2347
|
+
parentPath: this.mirror.getPath(iframeEl),
|
|
2348
|
+
nextPath: null,
|
|
2349
|
+
node: childSn
|
|
2350
|
+
}
|
|
2351
|
+
],
|
|
2352
|
+
removes: [],
|
|
2353
|
+
texts: [],
|
|
2354
|
+
attributes: [],
|
|
2355
|
+
isAttachIframe: true
|
|
2356
|
+
});
|
|
2357
|
+
if (this.recordCrossOriginIframes)
|
|
2358
|
+
iframeEl.contentWindow?.addEventListener("message", this.handleMessage.bind(this));
|
|
2359
|
+
this.loadListener?.(iframeEl);
|
|
2360
|
+
if (iframeEl.contentDocument?.adoptedStyleSheets && iframeEl.contentDocument.adoptedStyleSheets.length > 0)
|
|
2361
|
+
this.stylesheetManager.adoptStyleSheets(iframeEl.contentDocument.adoptedStyleSheets, this.mirror.getPath(iframeEl.contentDocument));
|
|
2362
|
+
}
|
|
2363
|
+
handleMessage(message) {
|
|
2364
|
+
const crossOriginMessageEvent = message;
|
|
2365
|
+
if (crossOriginMessageEvent.data.type !== "rrweb" || crossOriginMessageEvent.origin !== crossOriginMessageEvent.data.origin)
|
|
2366
|
+
return;
|
|
2367
|
+
const iframeSourceWindow = message.source;
|
|
2368
|
+
if (!iframeSourceWindow)
|
|
2369
|
+
return;
|
|
2370
|
+
const iframeEl = this.crossOriginIframeMap.get(message.source);
|
|
2371
|
+
if (!iframeEl)
|
|
2372
|
+
return;
|
|
2373
|
+
const transformedEvent = this.transformCrossOriginEvent(iframeEl, crossOriginMessageEvent.data.event);
|
|
2374
|
+
if (transformedEvent)
|
|
2375
|
+
this.wrappedEmit(transformedEvent, crossOriginMessageEvent.data.isCheckout);
|
|
2376
|
+
}
|
|
2377
|
+
transformCrossOriginEvent(iframeEl, e) {
|
|
2378
|
+
switch (e.type) {
|
|
2379
|
+
case 7 /* Pageview */: {
|
|
2380
|
+
this.crossOriginIframeMirror.reset(iframeEl);
|
|
2381
|
+
this.crossOriginIframeStyleMirror.reset(iframeEl);
|
|
2382
|
+
this.replacePathOnNode(e.data.node, iframeEl);
|
|
2383
|
+
const pvRootPath = e.data.node.path;
|
|
2384
|
+
this.crossOriginIframeRootIdMap.set(iframeEl, pvRootPath);
|
|
2385
|
+
this.patchRootIdOnNode(e.data.node, pvRootPath);
|
|
2386
|
+
return {
|
|
2387
|
+
timestamp: e.timestamp,
|
|
2388
|
+
type: 3 /* IncrementalSnapshot */,
|
|
2389
|
+
data: {
|
|
2390
|
+
source: 0 /* Mutation */,
|
|
2391
|
+
adds: [
|
|
2392
|
+
{
|
|
2393
|
+
parentPath: this.mirror.getPath(iframeEl),
|
|
2394
|
+
nextPath: null,
|
|
2395
|
+
node: e.data.node
|
|
2396
|
+
}
|
|
2397
|
+
],
|
|
2398
|
+
removes: [],
|
|
2399
|
+
texts: [],
|
|
2400
|
+
attributes: [],
|
|
2401
|
+
isAttachIframe: true
|
|
2402
|
+
}
|
|
2403
|
+
};
|
|
2404
|
+
}
|
|
2405
|
+
case 2 /* FullSnapshot */: {
|
|
2406
|
+
this.crossOriginIframeMirror.reset(iframeEl);
|
|
2407
|
+
this.crossOriginIframeStyleMirror.reset(iframeEl);
|
|
2408
|
+
this.replacePathOnNode(e.data.node, iframeEl);
|
|
2409
|
+
const rootPath = e.data.node.path;
|
|
2410
|
+
this.crossOriginIframeRootIdMap.set(iframeEl, rootPath);
|
|
2411
|
+
this.patchRootIdOnNode(e.data.node, rootPath);
|
|
2412
|
+
return {
|
|
2413
|
+
timestamp: e.timestamp,
|
|
2414
|
+
type: 3 /* IncrementalSnapshot */,
|
|
2415
|
+
data: {
|
|
2416
|
+
source: 0 /* Mutation */,
|
|
2417
|
+
adds: [
|
|
2418
|
+
{
|
|
2419
|
+
parentPath: this.mirror.getPath(iframeEl),
|
|
2420
|
+
nextPath: null,
|
|
2421
|
+
node: e.data.node
|
|
2422
|
+
}
|
|
2423
|
+
],
|
|
2424
|
+
removes: [],
|
|
2425
|
+
texts: [],
|
|
2426
|
+
attributes: [],
|
|
2427
|
+
isAttachIframe: true
|
|
2428
|
+
}
|
|
2429
|
+
};
|
|
2430
|
+
}
|
|
2431
|
+
case 4 /* Meta */:
|
|
2432
|
+
case 1 /* Load */:
|
|
2433
|
+
case 0 /* DomContentLoaded */: {
|
|
2434
|
+
return false;
|
|
2435
|
+
}
|
|
2436
|
+
case 6 /* Plugin */: {
|
|
2437
|
+
return e;
|
|
2438
|
+
}
|
|
2439
|
+
case 5 /* Custom */: {
|
|
2440
|
+
this.replacePaths(e.data.payload, iframeEl, [
|
|
2441
|
+
"path",
|
|
2442
|
+
"parentPath",
|
|
2443
|
+
"previousPath",
|
|
2444
|
+
"nextPath"
|
|
2445
|
+
]);
|
|
2446
|
+
return e;
|
|
2447
|
+
}
|
|
2448
|
+
case 3 /* IncrementalSnapshot */: {
|
|
2449
|
+
switch (e.data.source) {
|
|
2450
|
+
case 0 /* Mutation */: {
|
|
2451
|
+
e.data.adds.forEach((n) => {
|
|
2452
|
+
this.replacePaths(n, iframeEl, ["parentPath", "nextPath", "previousPath"]);
|
|
2453
|
+
this.replacePathOnNode(n.node, iframeEl);
|
|
2454
|
+
const rootPath = this.crossOriginIframeRootIdMap.get(iframeEl);
|
|
2455
|
+
rootPath && this.patchRootIdOnNode(n.node, rootPath);
|
|
2456
|
+
});
|
|
2457
|
+
e.data.removes.forEach((n) => {
|
|
2458
|
+
this.replacePaths(n, iframeEl, ["parentPath", "path"]);
|
|
2459
|
+
});
|
|
2460
|
+
e.data.attributes.forEach((n) => {
|
|
2461
|
+
this.replacePaths(n, iframeEl, ["path"]);
|
|
2462
|
+
});
|
|
2463
|
+
e.data.texts.forEach((n) => {
|
|
2464
|
+
this.replacePaths(n, iframeEl, ["path"]);
|
|
2465
|
+
});
|
|
2466
|
+
return e;
|
|
2467
|
+
}
|
|
2468
|
+
case 12 /* Drag */:
|
|
2469
|
+
case 6 /* TouchMove */:
|
|
2470
|
+
case 1 /* MouseMove */: {
|
|
2471
|
+
e.data.positions.forEach((p) => {
|
|
2472
|
+
this.replacePaths(p, iframeEl, ["path"]);
|
|
2473
|
+
});
|
|
2474
|
+
return e;
|
|
2475
|
+
}
|
|
2476
|
+
case 4 /* ViewportResize */: {
|
|
2477
|
+
return false;
|
|
2478
|
+
}
|
|
2479
|
+
case 7 /* MediaInteraction */:
|
|
2480
|
+
case 2 /* MouseInteraction */:
|
|
2481
|
+
case 3 /* Scroll */:
|
|
2482
|
+
case 9 /* CanvasMutation */:
|
|
2483
|
+
case 5 /* Input */: {
|
|
2484
|
+
this.replacePaths(e.data, iframeEl, ["path"]);
|
|
2485
|
+
return e;
|
|
2486
|
+
}
|
|
2487
|
+
case 8 /* StyleSheetRule */:
|
|
2488
|
+
case 13 /* StyleDeclaration */: {
|
|
2489
|
+
this.replacePaths(e.data, iframeEl, ["path"]);
|
|
2490
|
+
this.replaceStyleIds(e.data, iframeEl, ["styleId"]);
|
|
2491
|
+
return e;
|
|
2492
|
+
}
|
|
2493
|
+
case 10 /* Font */: {
|
|
2494
|
+
return e;
|
|
2495
|
+
}
|
|
2496
|
+
case 14 /* Selection */: {
|
|
2497
|
+
e.data.ranges.forEach((range) => {
|
|
2498
|
+
this.replacePaths(range, iframeEl, ["start", "end"]);
|
|
2499
|
+
});
|
|
2500
|
+
return e;
|
|
2501
|
+
}
|
|
2502
|
+
case 15 /* AdoptedStyleSheet */: {
|
|
2503
|
+
this.replacePaths(e.data, iframeEl, ["path"]);
|
|
2504
|
+
this.replaceStyleIds(e.data, iframeEl, ["styleIds"]);
|
|
2505
|
+
e.data.styles?.forEach((style) => {
|
|
2506
|
+
this.replaceStyleIds(style, iframeEl, ["styleId"]);
|
|
2507
|
+
});
|
|
2508
|
+
return e;
|
|
2509
|
+
}
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
}
|
|
2513
|
+
return false;
|
|
2514
|
+
}
|
|
2515
|
+
replace(iframeMirror, obj, iframeEl, keys) {
|
|
2516
|
+
for (const key of keys) {
|
|
2517
|
+
if (!Array.isArray(obj[key]) && typeof obj[key] !== "string" && typeof obj[key] !== "number")
|
|
2518
|
+
continue;
|
|
2519
|
+
if (Array.isArray(obj[key])) {
|
|
2520
|
+
obj[key] = iframeMirror.getPaths(iframeEl, obj[key]);
|
|
2521
|
+
} else {
|
|
2522
|
+
obj[key] = iframeMirror.getPath(iframeEl, obj[key]);
|
|
2523
|
+
}
|
|
2524
|
+
}
|
|
2525
|
+
return obj;
|
|
2526
|
+
}
|
|
2527
|
+
replacePaths(obj, iframeEl, keys) {
|
|
2528
|
+
return this.replace(this.crossOriginIframeMirror, obj, iframeEl, keys);
|
|
2529
|
+
}
|
|
2530
|
+
replaceStyleIds(obj, iframeEl, keys) {
|
|
2531
|
+
return this.replace(this.crossOriginIframeStyleMirror, obj, iframeEl, keys);
|
|
2532
|
+
}
|
|
2533
|
+
replacePathOnNode(node, iframeEl) {
|
|
2534
|
+
this.replacePaths(node, iframeEl, ["path", "rootId"]);
|
|
2535
|
+
if ("childNodes" in node) {
|
|
2536
|
+
node.childNodes.forEach((child) => {
|
|
2537
|
+
this.replacePathOnNode(child, iframeEl);
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
}
|
|
2541
|
+
patchRootIdOnNode(node, rootPath) {
|
|
2542
|
+
if (node.type !== 0 /* Document */ && !node.rootId)
|
|
2543
|
+
node.rootId = rootPath;
|
|
2544
|
+
if ("childNodes" in node) {
|
|
2545
|
+
node.childNodes.forEach((child) => {
|
|
2546
|
+
this.patchRootIdOnNode(child, rootPath);
|
|
2547
|
+
});
|
|
2548
|
+
}
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
// ../rrweb-record/src/record/observer.ts
|
|
2553
|
+
init_src();
|
|
2554
|
+
init_dom();
|
|
2555
|
+
init_snapshot_utils();
|
|
2556
|
+
init_utils();
|
|
2557
|
+
|
|
2558
|
+
// ../rrweb-record/src/record/mutation.ts
|
|
2559
|
+
init_dom();
|
|
2560
|
+
init_redact_pii();
|
|
2561
|
+
init_snapshot();
|
|
2562
|
+
init_snapshot_utils();
|
|
2563
|
+
init_utils();
|
|
2564
|
+
function isNodeInLinkedList(n) {
|
|
2565
|
+
return "__ln" in n;
|
|
2566
|
+
}
|
|
2567
|
+
|
|
2568
|
+
class DoubleLinkedList {
|
|
2569
|
+
length = 0;
|
|
2570
|
+
head = null;
|
|
2571
|
+
tail = null;
|
|
2572
|
+
get(position) {
|
|
2573
|
+
if (position >= this.length) {
|
|
2574
|
+
throw new Error("Position outside of list range");
|
|
2575
|
+
}
|
|
2576
|
+
let current = this.head;
|
|
2577
|
+
for (let index = 0;index < position; index++) {
|
|
2578
|
+
current = current?.next || null;
|
|
2579
|
+
}
|
|
2580
|
+
return current;
|
|
2581
|
+
}
|
|
2582
|
+
addNode(n) {
|
|
2583
|
+
const node = {
|
|
2584
|
+
value: n,
|
|
2585
|
+
previous: null,
|
|
2586
|
+
next: null
|
|
2587
|
+
};
|
|
2588
|
+
n.__ln = node;
|
|
2589
|
+
if (n.previousSibling && isNodeInLinkedList(n.previousSibling)) {
|
|
2590
|
+
const current = n.previousSibling.__ln.next;
|
|
2591
|
+
node.next = current;
|
|
2592
|
+
node.previous = n.previousSibling.__ln;
|
|
2593
|
+
n.previousSibling.__ln.next = node;
|
|
2594
|
+
if (current) {
|
|
2595
|
+
current.previous = node;
|
|
2596
|
+
}
|
|
2597
|
+
} else if (n.nextSibling && isNodeInLinkedList(n.nextSibling) && n.nextSibling.__ln.previous) {
|
|
2598
|
+
const current = n.nextSibling.__ln.previous;
|
|
2599
|
+
node.previous = current;
|
|
2600
|
+
node.next = n.nextSibling.__ln;
|
|
2601
|
+
n.nextSibling.__ln.previous = node;
|
|
2602
|
+
if (current) {
|
|
2603
|
+
current.next = node;
|
|
2604
|
+
}
|
|
2605
|
+
} else {
|
|
2606
|
+
if (this.head) {
|
|
2607
|
+
this.head.previous = node;
|
|
2608
|
+
}
|
|
2609
|
+
node.next = this.head;
|
|
2610
|
+
this.head = node;
|
|
2611
|
+
}
|
|
2612
|
+
if (node.next === null) {
|
|
2613
|
+
this.tail = node;
|
|
2614
|
+
}
|
|
2615
|
+
this.length++;
|
|
2616
|
+
}
|
|
2617
|
+
removeNode(n) {
|
|
2618
|
+
const current = n.__ln;
|
|
2619
|
+
if (!this.head) {
|
|
2620
|
+
return;
|
|
2621
|
+
}
|
|
2622
|
+
if (!current.previous) {
|
|
2623
|
+
this.head = current.next;
|
|
2624
|
+
if (this.head) {
|
|
2625
|
+
this.head.previous = null;
|
|
2626
|
+
} else {
|
|
2627
|
+
this.tail = null;
|
|
2628
|
+
}
|
|
2629
|
+
} else {
|
|
2630
|
+
current.previous.next = current.next;
|
|
2631
|
+
if (current.next) {
|
|
2632
|
+
current.next.previous = current.previous;
|
|
2633
|
+
} else {
|
|
2634
|
+
this.tail = current.previous;
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
if (n.__ln) {
|
|
2638
|
+
n.__ln = undefined;
|
|
2639
|
+
}
|
|
2640
|
+
this.length--;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
var moveKey = (path, parentPath) => `${path}@${parentPath}`;
|
|
2644
|
+
|
|
2645
|
+
class MutationBuffer {
|
|
2646
|
+
frozen = false;
|
|
2647
|
+
locked = false;
|
|
2648
|
+
rafScheduled = false;
|
|
2649
|
+
texts = [];
|
|
2650
|
+
attributes = [];
|
|
2651
|
+
attributeMap = new WeakMap;
|
|
2652
|
+
removes = [];
|
|
2653
|
+
mapRemoves = [];
|
|
2654
|
+
movedMap = {};
|
|
2655
|
+
addedSet = new Set;
|
|
2656
|
+
movedSet = new Set;
|
|
2657
|
+
droppedSet = new Set;
|
|
2658
|
+
removesSubTreeCache = new Set;
|
|
2659
|
+
mutationCb;
|
|
2660
|
+
blockClass;
|
|
2661
|
+
blockSelector;
|
|
2662
|
+
maskTextClass;
|
|
2663
|
+
maskTextSelector;
|
|
2664
|
+
inlineStylesheet;
|
|
2665
|
+
maskInputOptions;
|
|
2666
|
+
maskTextFn;
|
|
2667
|
+
maskInputFn;
|
|
2668
|
+
keepIframeSrcFn;
|
|
2669
|
+
recordCanvas;
|
|
2670
|
+
inlineImages;
|
|
2671
|
+
slimDOMOptions;
|
|
2672
|
+
dataURLOptions;
|
|
2673
|
+
doc;
|
|
2674
|
+
mirror;
|
|
2675
|
+
iframeManager;
|
|
2676
|
+
stylesheetManager;
|
|
2677
|
+
shadowDomManager;
|
|
2678
|
+
canvasManager = null;
|
|
2679
|
+
processedNodeManager;
|
|
2680
|
+
unattachedDoc;
|
|
2681
|
+
init(options) {
|
|
2682
|
+
[
|
|
2683
|
+
"mutationCb",
|
|
2684
|
+
"blockClass",
|
|
2685
|
+
"blockSelector",
|
|
2686
|
+
"maskTextClass",
|
|
2687
|
+
"maskTextSelector",
|
|
2688
|
+
"inlineStylesheet",
|
|
2689
|
+
"maskInputOptions",
|
|
2690
|
+
"maskTextFn",
|
|
2691
|
+
"maskInputFn",
|
|
2692
|
+
"keepIframeSrcFn",
|
|
2693
|
+
"recordCanvas",
|
|
2694
|
+
"inlineImages",
|
|
2695
|
+
"slimDOMOptions",
|
|
2696
|
+
"dataURLOptions",
|
|
2697
|
+
"doc",
|
|
2698
|
+
"mirror",
|
|
2699
|
+
"iframeManager",
|
|
2700
|
+
"stylesheetManager",
|
|
2701
|
+
"shadowDomManager",
|
|
2702
|
+
"canvasManager",
|
|
2703
|
+
"processedNodeManager"
|
|
2704
|
+
].forEach((key) => {
|
|
2705
|
+
this[key] = options[key];
|
|
2706
|
+
});
|
|
2707
|
+
}
|
|
2708
|
+
setCanvasManager(cm) {
|
|
2709
|
+
this.canvasManager = cm;
|
|
2710
|
+
}
|
|
2711
|
+
freeze() {
|
|
2712
|
+
this.frozen = true;
|
|
2713
|
+
this.canvasManager?.freeze();
|
|
2714
|
+
}
|
|
2715
|
+
unfreeze() {
|
|
2716
|
+
this.frozen = false;
|
|
2717
|
+
this.canvasManager?.unfreeze();
|
|
2718
|
+
this.emit();
|
|
2719
|
+
}
|
|
2720
|
+
isFrozen() {
|
|
2721
|
+
return this.frozen;
|
|
2722
|
+
}
|
|
2723
|
+
lock() {
|
|
2724
|
+
this.locked = true;
|
|
2725
|
+
this.canvasManager?.lock();
|
|
2726
|
+
}
|
|
2727
|
+
unlock() {
|
|
2728
|
+
this.locked = false;
|
|
2729
|
+
this.canvasManager?.unlock();
|
|
2730
|
+
this.emit();
|
|
2731
|
+
}
|
|
2732
|
+
unlockAndDrop() {
|
|
2733
|
+
this.dropPending();
|
|
2734
|
+
this.locked = false;
|
|
2735
|
+
this.canvasManager.unlock();
|
|
2736
|
+
}
|
|
2737
|
+
reset() {
|
|
2738
|
+
this.shadowDomManager.reset();
|
|
2739
|
+
this.canvasManager?.reset();
|
|
2740
|
+
}
|
|
2741
|
+
dropPending() {
|
|
2742
|
+
while (this.mapRemoves.length) {
|
|
2743
|
+
this.mirror.removeNodeFromMap(this.mapRemoves.shift());
|
|
2744
|
+
}
|
|
2745
|
+
this.texts = [];
|
|
2746
|
+
this.attributes = [];
|
|
2747
|
+
this.attributeMap = new WeakMap;
|
|
2748
|
+
this.removes = [];
|
|
2749
|
+
this.addedSet = new Set;
|
|
2750
|
+
this.movedSet = new Set;
|
|
2751
|
+
this.droppedSet = new Set;
|
|
2752
|
+
this.removesSubTreeCache = new Set;
|
|
2753
|
+
this.movedMap = {};
|
|
2754
|
+
}
|
|
2755
|
+
processMutations = (mutations) => {
|
|
2756
|
+
mutations.forEach(this.processMutation);
|
|
2757
|
+
if (!this.rafScheduled && !this.frozen && !this.locked) {
|
|
2758
|
+
this.rafScheduled = true;
|
|
2759
|
+
requestAnimationFrame(() => {
|
|
2760
|
+
this.rafScheduled = false;
|
|
2761
|
+
this.emit();
|
|
2762
|
+
});
|
|
2763
|
+
}
|
|
2764
|
+
};
|
|
2765
|
+
emit = () => {
|
|
2766
|
+
if (this.frozen || this.locked) {
|
|
2767
|
+
return;
|
|
2768
|
+
}
|
|
2769
|
+
const adds = [];
|
|
2770
|
+
const addedPaths = new Set;
|
|
2771
|
+
const addList = new DoubleLinkedList;
|
|
2772
|
+
const getNextPath = (n) => {
|
|
2773
|
+
let ns = n;
|
|
2774
|
+
while (ns = ns?.nextSibling ?? null) {
|
|
2775
|
+
if (this.mirror.isSerialized(ns)) {
|
|
2776
|
+
return this.mirror.getPath(ns);
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
return null;
|
|
2780
|
+
};
|
|
2781
|
+
const getPreviousPath = (n) => {
|
|
2782
|
+
let ps = n;
|
|
2783
|
+
while (ps = ps?.previousSibling ?? null) {
|
|
2784
|
+
if (this.mirror.isSerialized(ps)) {
|
|
2785
|
+
return this.mirror.getPath(ps);
|
|
2786
|
+
}
|
|
2787
|
+
}
|
|
2788
|
+
return null;
|
|
2789
|
+
};
|
|
2790
|
+
const pushAdd = (n) => {
|
|
2791
|
+
const parent = dom_default.parentNode(n);
|
|
2792
|
+
if (!parent || !inDom(n)) {
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
let cssCaptured = false;
|
|
2796
|
+
if (n.nodeType === Node.TEXT_NODE) {
|
|
2797
|
+
const parentTag = parent.tagName;
|
|
2798
|
+
if (parentTag === "TEXTAREA") {
|
|
2799
|
+
return;
|
|
2800
|
+
}
|
|
2801
|
+
if (parentTag === "STYLE" && this.addedSet.has(parent)) {
|
|
2802
|
+
cssCaptured = true;
|
|
2803
|
+
}
|
|
2804
|
+
}
|
|
2805
|
+
const parentPath = isShadowRoot(parent) ? this.mirror.getPath(getShadowHost(n)) : this.mirror.getPath(parent);
|
|
2806
|
+
const afterPath = getNextPath(n);
|
|
2807
|
+
const beforePath = getPreviousPath(n);
|
|
2808
|
+
if (!parentPath && parentPath !== "" || afterPath === "") {}
|
|
2809
|
+
if (!this.mirror.isSerialized(parent) && !isShadowRoot(parent)) {
|
|
2810
|
+
return addList.addNode(n);
|
|
2811
|
+
}
|
|
2812
|
+
const sn = serializeNodeWithId(n, {
|
|
2813
|
+
doc: this.doc,
|
|
2814
|
+
mirror: this.mirror,
|
|
2815
|
+
blockClass: this.blockClass,
|
|
2816
|
+
blockSelector: this.blockSelector,
|
|
2817
|
+
maskTextClass: this.maskTextClass,
|
|
2818
|
+
maskTextSelector: this.maskTextSelector,
|
|
2819
|
+
skipChild: true,
|
|
2820
|
+
newlyAddedElement: true,
|
|
2821
|
+
inlineStylesheet: this.inlineStylesheet,
|
|
2822
|
+
maskInputOptions: this.maskInputOptions,
|
|
2823
|
+
maskTextFn: this.maskTextFn,
|
|
2824
|
+
maskInputFn: this.maskInputFn,
|
|
2825
|
+
slimDOMOptions: this.slimDOMOptions,
|
|
2826
|
+
dataURLOptions: this.dataURLOptions,
|
|
2827
|
+
recordCanvas: this.recordCanvas,
|
|
2828
|
+
inlineImages: this.inlineImages,
|
|
2829
|
+
onSerialize: (currentN) => {
|
|
2830
|
+
if (isSerializedIframe(currentN, this.mirror)) {
|
|
2831
|
+
this.iframeManager.addIframe(currentN);
|
|
2832
|
+
}
|
|
2833
|
+
if (isSerializedStylesheet(currentN, this.mirror)) {
|
|
2834
|
+
this.stylesheetManager.trackLinkElement(currentN);
|
|
2835
|
+
}
|
|
2836
|
+
if (hasShadowRoot(n)) {
|
|
2837
|
+
this.shadowDomManager.addShadowRoot(dom_default.shadowRoot(n), this.doc);
|
|
2838
|
+
}
|
|
2839
|
+
},
|
|
2840
|
+
onIframeLoad: (iframe, childSn) => {
|
|
2841
|
+
this.iframeManager.attachIframe(iframe, childSn);
|
|
2842
|
+
this.shadowDomManager.observeAttachShadow(iframe);
|
|
2843
|
+
},
|
|
2844
|
+
onStylesheetLoad: (link, childSn) => {
|
|
2845
|
+
this.stylesheetManager.attachLinkElement(link, childSn);
|
|
2846
|
+
},
|
|
2847
|
+
cssCaptured
|
|
2848
|
+
});
|
|
2849
|
+
if (sn) {
|
|
2850
|
+
adds.push({
|
|
2851
|
+
parentPath,
|
|
2852
|
+
previousPath: beforePath,
|
|
2853
|
+
nextPath: afterPath,
|
|
2854
|
+
node: sn
|
|
2855
|
+
});
|
|
2856
|
+
addedPaths.add(sn.path);
|
|
2857
|
+
}
|
|
2858
|
+
};
|
|
2859
|
+
while (this.mapRemoves.length) {
|
|
2860
|
+
this.mirror.removeNodeFromMap(this.mapRemoves.shift());
|
|
2861
|
+
}
|
|
2862
|
+
for (const n of this.movedSet) {
|
|
2863
|
+
if (isParentRemoved(this.removesSubTreeCache, n, this.mirror) && !this.movedSet.has(dom_default.parentNode(n))) {
|
|
2864
|
+
continue;
|
|
2865
|
+
}
|
|
2866
|
+
pushAdd(n);
|
|
2867
|
+
}
|
|
2868
|
+
for (const n of this.addedSet) {
|
|
2869
|
+
if (!isAncestorInSet(this.droppedSet, n) && !isParentRemoved(this.removesSubTreeCache, n, this.mirror)) {
|
|
2870
|
+
pushAdd(n);
|
|
2871
|
+
} else if (isAncestorInSet(this.movedSet, n)) {
|
|
2872
|
+
pushAdd(n);
|
|
2873
|
+
} else {
|
|
2874
|
+
this.droppedSet.add(n);
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
let candidate = null;
|
|
2878
|
+
while (addList.length) {
|
|
2879
|
+
let node = null;
|
|
2880
|
+
if (candidate) {
|
|
2881
|
+
const parentNode2 = dom_default.parentNode(candidate.value);
|
|
2882
|
+
const parentSerialized = parentNode2 && this.mirror.isSerialized(parentNode2);
|
|
2883
|
+
const afterPath = getNextPath(candidate.value);
|
|
2884
|
+
if (parentSerialized && afterPath !== IGNORED_PATH) {
|
|
2885
|
+
node = candidate;
|
|
2886
|
+
}
|
|
2887
|
+
}
|
|
2888
|
+
if (!node) {
|
|
2889
|
+
let tailNode = addList.tail;
|
|
2890
|
+
while (tailNode) {
|
|
2891
|
+
const _node = tailNode;
|
|
2892
|
+
tailNode = tailNode.previous;
|
|
2893
|
+
if (_node) {
|
|
2894
|
+
const parentNode2 = dom_default.parentNode(_node.value);
|
|
2895
|
+
const parentSerialized = parentNode2 && this.mirror.isSerialized(parentNode2);
|
|
2896
|
+
const afterPath = getNextPath(_node.value);
|
|
2897
|
+
if (afterPath === IGNORED_PATH)
|
|
2898
|
+
continue;
|
|
2899
|
+
if (parentSerialized) {
|
|
2900
|
+
node = _node;
|
|
2901
|
+
break;
|
|
2902
|
+
}
|
|
2903
|
+
const unhandledNode = _node.value;
|
|
2904
|
+
const parent = dom_default.parentNode(unhandledNode);
|
|
2905
|
+
if (parent && parent.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
|
|
2906
|
+
const shadowHost = dom_default.host(parent);
|
|
2907
|
+
if (this.mirror.isSerialized(shadowHost)) {
|
|
2908
|
+
node = _node;
|
|
2909
|
+
break;
|
|
2910
|
+
}
|
|
2911
|
+
}
|
|
2912
|
+
}
|
|
2913
|
+
}
|
|
2914
|
+
}
|
|
2915
|
+
if (!node) {
|
|
2916
|
+
while (addList.head) {
|
|
2917
|
+
addList.removeNode(addList.head.value);
|
|
2918
|
+
}
|
|
2919
|
+
break;
|
|
2920
|
+
}
|
|
2921
|
+
candidate = node.previous;
|
|
2922
|
+
addList.removeNode(node.value);
|
|
2923
|
+
pushAdd(node.value);
|
|
2924
|
+
}
|
|
2925
|
+
const payload = {
|
|
2926
|
+
texts: this.texts.map((text) => {
|
|
2927
|
+
const n = text.node;
|
|
2928
|
+
const parent = dom_default.parentNode(n);
|
|
2929
|
+
if (parent && parent.tagName === "TEXTAREA") {
|
|
2930
|
+
this.genTextAreaValueMutation(parent);
|
|
2931
|
+
}
|
|
2932
|
+
return {
|
|
2933
|
+
path: this.mirror.getPath(n),
|
|
2934
|
+
value: text.value
|
|
2935
|
+
};
|
|
2936
|
+
}).filter((text) => !addedPaths.has(text.path)).filter((text) => text.path !== "" && text.path !== IGNORED_PATH),
|
|
2937
|
+
attributes: this.attributes.map((attribute) => {
|
|
2938
|
+
const { attributes } = attribute;
|
|
2939
|
+
if (typeof attributes.style === "string") {
|
|
2940
|
+
const diffAsStr = JSON.stringify(attribute.styleDiff);
|
|
2941
|
+
const unchangedAsStr = JSON.stringify(attribute._unchangedStyles);
|
|
2942
|
+
if (diffAsStr.length < attributes.style.length) {
|
|
2943
|
+
if ((diffAsStr + unchangedAsStr).split("var(").length === attributes.style.split("var(").length) {
|
|
2944
|
+
attributes.style = attribute.styleDiff;
|
|
2945
|
+
}
|
|
2946
|
+
}
|
|
2947
|
+
}
|
|
2948
|
+
return {
|
|
2949
|
+
path: this.mirror.getPath(attribute.node),
|
|
2950
|
+
attributes
|
|
2951
|
+
};
|
|
2952
|
+
}).filter((attribute) => !addedPaths.has(attribute.path)).filter((attribute) => attribute.path !== "" && attribute.path !== IGNORED_PATH),
|
|
2953
|
+
removes: this.removes,
|
|
2954
|
+
adds
|
|
2955
|
+
};
|
|
2956
|
+
if (!payload.texts.length && !payload.attributes.length && !payload.removes.length && !payload.adds.length) {
|
|
2957
|
+
return;
|
|
2958
|
+
}
|
|
2959
|
+
this.texts = [];
|
|
2960
|
+
this.attributes = [];
|
|
2961
|
+
this.attributeMap = new WeakMap;
|
|
2962
|
+
this.removes = [];
|
|
2963
|
+
this.addedSet = new Set;
|
|
2964
|
+
this.movedSet = new Set;
|
|
2965
|
+
this.droppedSet = new Set;
|
|
2966
|
+
this.removesSubTreeCache = new Set;
|
|
2967
|
+
this.movedMap = {};
|
|
2968
|
+
this.mutationCb(payload);
|
|
2969
|
+
};
|
|
2970
|
+
genTextAreaValueMutation = (textarea) => {
|
|
2971
|
+
let item = this.attributeMap.get(textarea);
|
|
2972
|
+
if (!item) {
|
|
2973
|
+
item = {
|
|
2974
|
+
node: textarea,
|
|
2975
|
+
attributes: {},
|
|
2976
|
+
styleDiff: {},
|
|
2977
|
+
_unchangedStyles: {}
|
|
2978
|
+
};
|
|
2979
|
+
this.attributes.push(item);
|
|
2980
|
+
this.attributeMap.set(textarea, item);
|
|
2981
|
+
}
|
|
2982
|
+
item.attributes.value = Array.from(dom_default.childNodes(textarea), (cn) => dom_default.textContent(cn) || "").join("");
|
|
2983
|
+
};
|
|
2984
|
+
processMutation = (m) => {
|
|
2985
|
+
if (isIgnored(m.target, this.mirror, this.slimDOMOptions)) {
|
|
2986
|
+
return;
|
|
2987
|
+
}
|
|
2988
|
+
switch (m.type) {
|
|
2989
|
+
case "characterData": {
|
|
2990
|
+
const value = dom_default.textContent(m.target);
|
|
2991
|
+
if (!isBlocked(m.target, this.blockClass, this.blockSelector, false) && value !== m.oldValue) {
|
|
2992
|
+
const masked = needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, true) && value ? this.maskTextFn ? this.maskTextFn(value, closestElementOfNode(m.target)) : value.replace(/[\S]/g, "*") : value;
|
|
2993
|
+
this.texts.push({
|
|
2994
|
+
value: masked ? redactPII(masked) : masked,
|
|
2995
|
+
node: m.target
|
|
2996
|
+
});
|
|
2997
|
+
}
|
|
2998
|
+
break;
|
|
2999
|
+
}
|
|
3000
|
+
case "attributes": {
|
|
3001
|
+
const target = m.target;
|
|
3002
|
+
let attributeName = m.attributeName;
|
|
3003
|
+
let value = m.target.getAttribute(attributeName);
|
|
3004
|
+
if (attributeName === "value") {
|
|
3005
|
+
const type = getInputType(target);
|
|
3006
|
+
value = maskInputValue({
|
|
3007
|
+
element: target,
|
|
3008
|
+
maskInputOptions: this.maskInputOptions,
|
|
3009
|
+
tagName: target.tagName,
|
|
3010
|
+
type,
|
|
3011
|
+
value,
|
|
3012
|
+
maskInputFn: this.maskInputFn
|
|
3013
|
+
});
|
|
3014
|
+
}
|
|
3015
|
+
if (isBlocked(m.target, this.blockClass, this.blockSelector, false) || value === m.oldValue) {
|
|
3016
|
+
return;
|
|
3017
|
+
}
|
|
3018
|
+
let item = this.attributeMap.get(m.target);
|
|
3019
|
+
if (target.tagName === "IFRAME" && attributeName === "src" && !this.keepIframeSrcFn(value)) {
|
|
3020
|
+
if (!target.contentDocument) {
|
|
3021
|
+
attributeName = "rr_src";
|
|
3022
|
+
} else {
|
|
3023
|
+
return;
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
if (!item) {
|
|
3027
|
+
item = {
|
|
3028
|
+
node: m.target,
|
|
3029
|
+
attributes: {},
|
|
3030
|
+
styleDiff: {},
|
|
3031
|
+
_unchangedStyles: {}
|
|
3032
|
+
};
|
|
3033
|
+
this.attributes.push(item);
|
|
3034
|
+
this.attributeMap.set(m.target, item);
|
|
3035
|
+
}
|
|
3036
|
+
if (attributeName === "type" && target.tagName === "INPUT" && (m.oldValue || "").toLowerCase() === "password") {
|
|
3037
|
+
target.setAttribute("data-rr-is-password", "true");
|
|
3038
|
+
}
|
|
3039
|
+
if (!ignoreAttribute(target.tagName, attributeName, value)) {
|
|
3040
|
+
item.attributes[attributeName] = transformAttribute(this.doc, toLowerCase(target.tagName), toLowerCase(attributeName), value);
|
|
3041
|
+
if (attributeName === "style") {
|
|
3042
|
+
if (!this.unattachedDoc) {
|
|
3043
|
+
try {
|
|
3044
|
+
this.unattachedDoc = document.implementation.createHTMLDocument();
|
|
3045
|
+
} catch (_e) {
|
|
3046
|
+
this.unattachedDoc = this.doc;
|
|
3047
|
+
}
|
|
3048
|
+
}
|
|
3049
|
+
const old = this.unattachedDoc.createElement("span");
|
|
3050
|
+
if (m.oldValue) {
|
|
3051
|
+
old.setAttribute("style", m.oldValue);
|
|
3052
|
+
}
|
|
3053
|
+
for (const pname of Array.from(target.style)) {
|
|
3054
|
+
const newValue = target.style.getPropertyValue(pname);
|
|
3055
|
+
const newPriority = target.style.getPropertyPriority(pname);
|
|
3056
|
+
if (newValue !== old.style.getPropertyValue(pname) || newPriority !== old.style.getPropertyPriority(pname)) {
|
|
3057
|
+
if (newPriority === "") {
|
|
3058
|
+
item.styleDiff[pname] = newValue;
|
|
3059
|
+
} else {
|
|
3060
|
+
item.styleDiff[pname] = [newValue, newPriority];
|
|
3061
|
+
}
|
|
3062
|
+
} else {
|
|
3063
|
+
item._unchangedStyles[pname] = [newValue, newPriority];
|
|
3064
|
+
}
|
|
3065
|
+
}
|
|
3066
|
+
for (const pname of Array.from(old.style)) {
|
|
3067
|
+
if (target.style.getPropertyValue(pname) === "") {
|
|
3068
|
+
item.styleDiff[pname] = false;
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
} else if (attributeName === "open" && target.tagName === "DIALOG") {
|
|
3072
|
+
if (target.matches("dialog:modal")) {
|
|
3073
|
+
item.attributes.rr_open_mode = "modal";
|
|
3074
|
+
} else {
|
|
3075
|
+
item.attributes.rr_open_mode = "non-modal";
|
|
3076
|
+
}
|
|
3077
|
+
}
|
|
3078
|
+
}
|
|
3079
|
+
break;
|
|
3080
|
+
}
|
|
3081
|
+
case "childList": {
|
|
3082
|
+
if (isBlocked(m.target, this.blockClass, this.blockSelector, true))
|
|
3083
|
+
return;
|
|
3084
|
+
if (m.target.tagName === "TEXTAREA") {
|
|
3085
|
+
this.genTextAreaValueMutation(m.target);
|
|
3086
|
+
return;
|
|
3087
|
+
}
|
|
3088
|
+
m.addedNodes.forEach((n) => this.genAdds(n, m.target));
|
|
3089
|
+
m.removedNodes.forEach((n) => {
|
|
3090
|
+
const nodePath = this.mirror.getPath(n);
|
|
3091
|
+
const parentPath = isShadowRoot(m.target) ? this.mirror.getPath(dom_default.host(m.target)) : this.mirror.getPath(m.target);
|
|
3092
|
+
if (isBlocked(m.target, this.blockClass, this.blockSelector, false) || isIgnored(n, this.mirror, this.slimDOMOptions) || !isSerialized(n, this.mirror)) {
|
|
3093
|
+
return;
|
|
3094
|
+
}
|
|
3095
|
+
if (this.addedSet.has(n)) {
|
|
3096
|
+
deepDelete(this.addedSet, n);
|
|
3097
|
+
this.droppedSet.add(n);
|
|
3098
|
+
} else if (this.addedSet.has(m.target) && !this.mirror.hasNode(n)) {} else if (isAncestorRemoved(m.target, this.mirror)) {} else if (this.movedSet.has(n) && this.movedMap[moveKey(nodePath, parentPath)]) {
|
|
3099
|
+
deepDelete(this.movedSet, n);
|
|
3100
|
+
} else {
|
|
3101
|
+
this.removes.push({
|
|
3102
|
+
parentPath,
|
|
3103
|
+
path: nodePath,
|
|
3104
|
+
isShadow: isShadowRoot(m.target) && isNativeShadowDom(m.target) ? true : undefined
|
|
3105
|
+
});
|
|
3106
|
+
processRemoves(n, this.removesSubTreeCache);
|
|
3107
|
+
}
|
|
3108
|
+
this.mapRemoves.push(n);
|
|
3109
|
+
});
|
|
3110
|
+
break;
|
|
3111
|
+
}
|
|
3112
|
+
default:
|
|
3113
|
+
break;
|
|
3114
|
+
}
|
|
3115
|
+
};
|
|
3116
|
+
genAdds = (n, target) => {
|
|
3117
|
+
if (this.processedNodeManager.inOtherBuffer(n, this))
|
|
3118
|
+
return;
|
|
3119
|
+
if (this.addedSet.has(n) || this.movedSet.has(n))
|
|
3120
|
+
return;
|
|
3121
|
+
if (this.mirror.hasNode(n)) {
|
|
3122
|
+
if (isIgnored(n, this.mirror, this.slimDOMOptions)) {
|
|
3123
|
+
return;
|
|
3124
|
+
}
|
|
3125
|
+
this.movedSet.add(n);
|
|
3126
|
+
if (target && this.mirror.hasNode(target)) {
|
|
3127
|
+
const targetPath = this.mirror.getPath(target);
|
|
3128
|
+
if (targetPath && targetPath !== IGNORED_PATH) {
|
|
3129
|
+
this.movedMap[moveKey(this.mirror.getPath(n), targetPath)] = true;
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3132
|
+
} else {
|
|
3133
|
+
this.addedSet.add(n);
|
|
3134
|
+
this.droppedSet.delete(n);
|
|
3135
|
+
}
|
|
3136
|
+
if (!isBlocked(n, this.blockClass, this.blockSelector, false)) {
|
|
3137
|
+
dom_default.childNodes(n).forEach((childN) => this.genAdds(childN));
|
|
3138
|
+
if (hasShadowRoot(n)) {
|
|
3139
|
+
dom_default.childNodes(dom_default.shadowRoot(n)).forEach((childN) => {
|
|
3140
|
+
this.processedNodeManager.add(childN, this);
|
|
3141
|
+
this.genAdds(childN, n);
|
|
3142
|
+
});
|
|
3143
|
+
}
|
|
3144
|
+
}
|
|
3145
|
+
};
|
|
3146
|
+
}
|
|
3147
|
+
function deepDelete(addsSet, n) {
|
|
3148
|
+
addsSet.delete(n);
|
|
3149
|
+
dom_default.childNodes(n).forEach((childN) => deepDelete(addsSet, childN));
|
|
3150
|
+
}
|
|
3151
|
+
function processRemoves(n, cache) {
|
|
3152
|
+
const queue = [n];
|
|
3153
|
+
while (queue.length) {
|
|
3154
|
+
const next = queue.pop();
|
|
3155
|
+
if (cache.has(next))
|
|
3156
|
+
continue;
|
|
3157
|
+
cache.add(next);
|
|
3158
|
+
dom_default.childNodes(next).forEach((n2) => queue.push(n2));
|
|
3159
|
+
}
|
|
3160
|
+
return;
|
|
3161
|
+
}
|
|
3162
|
+
function isParentRemoved(removes, n, mirror) {
|
|
3163
|
+
if (removes.size === 0)
|
|
3164
|
+
return false;
|
|
3165
|
+
return _isParentRemoved(removes, n, mirror);
|
|
3166
|
+
}
|
|
3167
|
+
function _isParentRemoved(removes, n, _mirror) {
|
|
3168
|
+
const node = dom_default.parentNode(n);
|
|
3169
|
+
if (!node)
|
|
3170
|
+
return false;
|
|
3171
|
+
return removes.has(node);
|
|
3172
|
+
}
|
|
3173
|
+
function isAncestorInSet(set, n) {
|
|
3174
|
+
if (set.size === 0)
|
|
3175
|
+
return false;
|
|
3176
|
+
return _isAncestorInSet(set, n);
|
|
3177
|
+
}
|
|
3178
|
+
function _isAncestorInSet(set, n) {
|
|
3179
|
+
const parent = dom_default.parentNode(n);
|
|
3180
|
+
if (!parent) {
|
|
3181
|
+
return false;
|
|
3182
|
+
}
|
|
3183
|
+
if (set.has(parent)) {
|
|
3184
|
+
return true;
|
|
3185
|
+
}
|
|
3186
|
+
return _isAncestorInSet(set, parent);
|
|
3187
|
+
}
|
|
3188
|
+
|
|
3189
|
+
// ../rrweb-record/src/record/observer.ts
|
|
3190
|
+
var mutationBuffers = [];
|
|
3191
|
+
var observerBufferPairs = [];
|
|
3192
|
+
function flushMutationObservers() {
|
|
3193
|
+
for (const { observer, buffer } of observerBufferPairs) {
|
|
3194
|
+
const records = observer.takeRecords();
|
|
3195
|
+
if (records.length > 0) {
|
|
3196
|
+
buffer.processMutations(records);
|
|
3197
|
+
}
|
|
3198
|
+
}
|
|
3199
|
+
}
|
|
3200
|
+
function getEventTarget(event) {
|
|
3201
|
+
try {
|
|
3202
|
+
if ("composedPath" in event) {
|
|
3203
|
+
const path = event.composedPath();
|
|
3204
|
+
if (path.length) {
|
|
3205
|
+
return path[0];
|
|
3206
|
+
}
|
|
3207
|
+
} else if ("path" in event && event.path.length) {
|
|
3208
|
+
return event.path[0];
|
|
3209
|
+
}
|
|
3210
|
+
} catch {}
|
|
3211
|
+
return event?.target;
|
|
3212
|
+
}
|
|
3213
|
+
function initMutationObserver(options, rootEl) {
|
|
3214
|
+
const mutationBuffer = new MutationBuffer;
|
|
3215
|
+
mutationBuffers.push(mutationBuffer);
|
|
3216
|
+
mutationBuffer.init(options);
|
|
3217
|
+
const observer = new (mutationObserverCtor())(callbackWrapper(mutationBuffer.processMutations.bind(mutationBuffer)));
|
|
3218
|
+
observer.observe(rootEl, {
|
|
3219
|
+
attributes: true,
|
|
3220
|
+
attributeOldValue: true,
|
|
3221
|
+
characterData: true,
|
|
3222
|
+
characterDataOldValue: true,
|
|
3223
|
+
childList: true,
|
|
3224
|
+
subtree: true
|
|
3225
|
+
});
|
|
3226
|
+
observerBufferPairs.push({ observer, buffer: mutationBuffer });
|
|
3227
|
+
return observer;
|
|
3228
|
+
}
|
|
3229
|
+
function initMoveObserver({ mousemoveCb, sampling, doc, mirror }) {
|
|
3230
|
+
if (sampling.mousemove === false) {
|
|
3231
|
+
return () => {};
|
|
3232
|
+
}
|
|
3233
|
+
const threshold = typeof sampling.mousemove === "number" ? sampling.mousemove : 50;
|
|
3234
|
+
const callbackThreshold = typeof sampling.mousemoveCallback === "number" ? sampling.mousemoveCallback : 500;
|
|
3235
|
+
let positions = [];
|
|
3236
|
+
let timeBaseline;
|
|
3237
|
+
const wrappedCb = throttle(callbackWrapper((source) => {
|
|
3238
|
+
const totalOffset = Date.now() - timeBaseline;
|
|
3239
|
+
mousemoveCb(positions.map((p) => {
|
|
3240
|
+
p.timeOffset -= totalOffset;
|
|
3241
|
+
return p;
|
|
3242
|
+
}), source);
|
|
3243
|
+
positions = [];
|
|
3244
|
+
timeBaseline = null;
|
|
3245
|
+
}), callbackThreshold);
|
|
3246
|
+
const updatePosition = callbackWrapper(throttle(callbackWrapper((evt) => {
|
|
3247
|
+
const target = getEventTarget(evt);
|
|
3248
|
+
const { clientX, clientY } = legacy_isTouchEvent(evt) ? evt.changedTouches[0] : evt;
|
|
3249
|
+
if (!timeBaseline) {
|
|
3250
|
+
timeBaseline = nowTimestamp();
|
|
3251
|
+
}
|
|
3252
|
+
positions.push({
|
|
3253
|
+
x: clientX,
|
|
3254
|
+
y: clientY,
|
|
3255
|
+
path: mirror.getPath(target),
|
|
3256
|
+
timeOffset: nowTimestamp() - timeBaseline
|
|
3257
|
+
});
|
|
3258
|
+
wrappedCb(typeof DragEvent !== "undefined" && evt instanceof DragEvent ? 12 /* Drag */ : evt instanceof MouseEvent ? 1 /* MouseMove */ : 6 /* TouchMove */);
|
|
3259
|
+
}), threshold, {
|
|
3260
|
+
trailing: false
|
|
3261
|
+
}));
|
|
3262
|
+
const handlers = [
|
|
3263
|
+
on("mousemove", updatePosition, doc),
|
|
3264
|
+
on("touchmove", updatePosition, doc),
|
|
3265
|
+
on("drag", updatePosition, doc)
|
|
3266
|
+
];
|
|
3267
|
+
return callbackWrapper(() => {
|
|
3268
|
+
handlers.forEach((h) => h());
|
|
3269
|
+
});
|
|
3270
|
+
}
|
|
3271
|
+
function initMouseInteractionObserver({
|
|
3272
|
+
mouseInteractionCb,
|
|
3273
|
+
doc,
|
|
3274
|
+
mirror,
|
|
3275
|
+
blockClass,
|
|
3276
|
+
blockSelector,
|
|
3277
|
+
sampling
|
|
3278
|
+
}) {
|
|
3279
|
+
if (sampling.mouseInteraction === false) {
|
|
3280
|
+
return () => {};
|
|
3281
|
+
}
|
|
3282
|
+
const disableMap = sampling.mouseInteraction === true || sampling.mouseInteraction === undefined ? {} : sampling.mouseInteraction;
|
|
3283
|
+
const handlers = [];
|
|
3284
|
+
let currentPointerType = null;
|
|
3285
|
+
const getHandler = (eventKey) => {
|
|
3286
|
+
return (event) => {
|
|
3287
|
+
const target = getEventTarget(event);
|
|
3288
|
+
if (isBlocked(target, blockClass, blockSelector, true)) {
|
|
3289
|
+
return;
|
|
3290
|
+
}
|
|
3291
|
+
let pointerType = null;
|
|
3292
|
+
let thisEventKey = eventKey;
|
|
3293
|
+
if ("pointerType" in event) {
|
|
3294
|
+
switch (event.pointerType) {
|
|
3295
|
+
case "mouse":
|
|
3296
|
+
pointerType = 0 /* Mouse */;
|
|
3297
|
+
break;
|
|
3298
|
+
case "touch":
|
|
3299
|
+
pointerType = 2 /* Touch */;
|
|
3300
|
+
break;
|
|
3301
|
+
case "pen":
|
|
3302
|
+
pointerType = 1 /* Pen */;
|
|
3303
|
+
break;
|
|
3304
|
+
}
|
|
3305
|
+
if (pointerType === 2 /* Touch */) {
|
|
3306
|
+
if (MouseInteractions[eventKey] === 1 /* MouseDown */) {
|
|
3307
|
+
thisEventKey = "TouchStart";
|
|
3308
|
+
} else if (MouseInteractions[eventKey] === 0 /* MouseUp */) {
|
|
3309
|
+
thisEventKey = "TouchEnd";
|
|
3310
|
+
}
|
|
3311
|
+
} else if (pointerType === 1 /* Pen */) {}
|
|
3312
|
+
} else if (legacy_isTouchEvent(event)) {
|
|
3313
|
+
pointerType = 2 /* Touch */;
|
|
3314
|
+
}
|
|
3315
|
+
if (pointerType !== null) {
|
|
3316
|
+
currentPointerType = pointerType;
|
|
3317
|
+
if (thisEventKey.startsWith("Touch") && pointerType === 2 /* Touch */ || thisEventKey.startsWith("Mouse") && pointerType === 0 /* Mouse */) {
|
|
3318
|
+
pointerType = null;
|
|
3319
|
+
}
|
|
3320
|
+
} else if (MouseInteractions[eventKey] === 2 /* Click */) {
|
|
3321
|
+
pointerType = currentPointerType;
|
|
3322
|
+
currentPointerType = null;
|
|
3323
|
+
}
|
|
3324
|
+
const e = legacy_isTouchEvent(event) ? event.changedTouches[0] : event;
|
|
3325
|
+
if (!e) {
|
|
3326
|
+
return;
|
|
3327
|
+
}
|
|
3328
|
+
const path = mirror.getPath(target);
|
|
3329
|
+
const { clientX, clientY } = e;
|
|
3330
|
+
callbackWrapper(mouseInteractionCb)({
|
|
3331
|
+
type: MouseInteractions[thisEventKey],
|
|
3332
|
+
path,
|
|
3333
|
+
x: clientX,
|
|
3334
|
+
y: clientY,
|
|
3335
|
+
...pointerType !== null && { pointerType }
|
|
3336
|
+
});
|
|
3337
|
+
};
|
|
3338
|
+
};
|
|
3339
|
+
Object.keys(MouseInteractions).filter((key) => Number.isNaN(Number(key)) && !key.endsWith("_Departed") && disableMap[key] !== false).forEach((eventKey) => {
|
|
3340
|
+
let eventName = toLowerCase(eventKey);
|
|
3341
|
+
const handler = getHandler(eventKey);
|
|
3342
|
+
if (window.PointerEvent) {
|
|
3343
|
+
switch (MouseInteractions[eventKey]) {
|
|
3344
|
+
case 1 /* MouseDown */:
|
|
3345
|
+
case 0 /* MouseUp */:
|
|
3346
|
+
eventName = eventName.replace("mouse", "pointer");
|
|
3347
|
+
break;
|
|
3348
|
+
case 7 /* TouchStart */:
|
|
3349
|
+
case 9 /* TouchEnd */:
|
|
3350
|
+
return;
|
|
3351
|
+
}
|
|
3352
|
+
}
|
|
3353
|
+
handlers.push(on(eventName, handler, doc));
|
|
3354
|
+
});
|
|
3355
|
+
return callbackWrapper(() => {
|
|
3356
|
+
handlers.forEach((h) => h());
|
|
3357
|
+
});
|
|
3358
|
+
}
|
|
3359
|
+
function initScrollObserver({
|
|
3360
|
+
scrollCb,
|
|
3361
|
+
doc,
|
|
3362
|
+
mirror,
|
|
3363
|
+
blockClass,
|
|
3364
|
+
blockSelector,
|
|
3365
|
+
sampling
|
|
3366
|
+
}) {
|
|
3367
|
+
const updatePosition = callbackWrapper(throttle(callbackWrapper((evt) => {
|
|
3368
|
+
const target = getEventTarget(evt);
|
|
3369
|
+
if (!target || isBlocked(target, blockClass, blockSelector, true)) {
|
|
3370
|
+
return;
|
|
3371
|
+
}
|
|
3372
|
+
const path = mirror.getPath(target);
|
|
3373
|
+
if (target === doc && doc.defaultView) {
|
|
3374
|
+
const scrollLeftTop = getWindowScroll(doc.defaultView);
|
|
3375
|
+
scrollCb({
|
|
3376
|
+
path,
|
|
3377
|
+
x: scrollLeftTop.left,
|
|
3378
|
+
y: scrollLeftTop.top
|
|
3379
|
+
});
|
|
3380
|
+
} else {
|
|
3381
|
+
scrollCb({
|
|
3382
|
+
path,
|
|
3383
|
+
x: target.scrollLeft,
|
|
3384
|
+
y: target.scrollTop
|
|
3385
|
+
});
|
|
3386
|
+
}
|
|
3387
|
+
}), sampling.scroll || 100));
|
|
3388
|
+
return on("scroll", updatePosition, doc);
|
|
3389
|
+
}
|
|
3390
|
+
function initViewportResizeObserver({ viewportResizeCb }, { win }) {
|
|
3391
|
+
let lastH = -1;
|
|
3392
|
+
let lastW = -1;
|
|
3393
|
+
const updateDimension = callbackWrapper(throttle(callbackWrapper(() => {
|
|
3394
|
+
const height = getWindowHeight();
|
|
3395
|
+
const width = getWindowWidth();
|
|
3396
|
+
if (lastH !== height || lastW !== width) {
|
|
3397
|
+
viewportResizeCb({
|
|
3398
|
+
width: Number(width),
|
|
3399
|
+
height: Number(height)
|
|
3400
|
+
});
|
|
3401
|
+
lastH = height;
|
|
3402
|
+
lastW = width;
|
|
3403
|
+
}
|
|
3404
|
+
}), 200));
|
|
3405
|
+
return on("resize", updateDimension, win);
|
|
3406
|
+
}
|
|
3407
|
+
var INPUT_TAGS = ["INPUT", "TEXTAREA", "SELECT"];
|
|
3408
|
+
var lastInputValueMap = new WeakMap;
|
|
3409
|
+
function initInputObserver({
|
|
3410
|
+
inputCb,
|
|
3411
|
+
doc,
|
|
3412
|
+
mirror,
|
|
3413
|
+
blockClass,
|
|
3414
|
+
blockSelector,
|
|
3415
|
+
ignoreClass,
|
|
3416
|
+
ignoreSelector,
|
|
3417
|
+
maskInputOptions,
|
|
3418
|
+
maskInputFn,
|
|
3419
|
+
sampling
|
|
3420
|
+
}) {
|
|
3421
|
+
function eventHandler(event) {
|
|
3422
|
+
let target = getEventTarget(event);
|
|
3423
|
+
const tagName = target?.tagName;
|
|
3424
|
+
if (target && tagName === "OPTION") {
|
|
3425
|
+
target = dom_default.parentElement(target);
|
|
3426
|
+
}
|
|
3427
|
+
if (!target || !tagName || INPUT_TAGS.indexOf(tagName) < 0 || isBlocked(target, blockClass, blockSelector, true)) {
|
|
3428
|
+
return;
|
|
3429
|
+
}
|
|
3430
|
+
if (target.classList.contains(ignoreClass) || ignoreSelector && target.matches(ignoreSelector)) {
|
|
3431
|
+
return;
|
|
3432
|
+
}
|
|
3433
|
+
let text = target.value;
|
|
3434
|
+
let isChecked = false;
|
|
3435
|
+
const type = getInputType(target) || "";
|
|
3436
|
+
if (type === "radio" || type === "checkbox") {
|
|
3437
|
+
isChecked = target.checked;
|
|
3438
|
+
} else if (maskInputOptions[tagName.toLowerCase()] || maskInputOptions[type]) {
|
|
3439
|
+
text = maskInputValue({
|
|
3440
|
+
element: target,
|
|
3441
|
+
maskInputOptions,
|
|
3442
|
+
tagName,
|
|
3443
|
+
type,
|
|
3444
|
+
value: text,
|
|
3445
|
+
maskInputFn
|
|
3446
|
+
});
|
|
3447
|
+
}
|
|
3448
|
+
cbWithDedup(target, { text, isChecked });
|
|
3449
|
+
const name = target.name;
|
|
3450
|
+
if (type === "radio" && name && isChecked) {
|
|
3451
|
+
doc.querySelectorAll(`input[type="radio"][name="${name}"]`).forEach((el) => {
|
|
3452
|
+
if (el !== target) {
|
|
3453
|
+
const text2 = el.value;
|
|
3454
|
+
cbWithDedup(el, { text: text2, isChecked: !isChecked });
|
|
3455
|
+
}
|
|
3456
|
+
});
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3459
|
+
function cbWithDedup(target, v) {
|
|
3460
|
+
const lastInputValue = lastInputValueMap.get(target);
|
|
3461
|
+
if (!lastInputValue || lastInputValue.text !== v.text || lastInputValue.isChecked !== v.isChecked) {
|
|
3462
|
+
lastInputValueMap.set(target, v);
|
|
3463
|
+
const path = mirror.getPath(target);
|
|
3464
|
+
callbackWrapper(inputCb)({
|
|
3465
|
+
...v,
|
|
3466
|
+
path
|
|
3467
|
+
});
|
|
3468
|
+
}
|
|
3469
|
+
}
|
|
3470
|
+
const events = sampling.input === "last" ? ["change"] : ["input", "change"];
|
|
3471
|
+
const handlers = events.map((eventName) => on(eventName, callbackWrapper(eventHandler), doc));
|
|
3472
|
+
const currentWindow = doc.defaultView;
|
|
3473
|
+
if (!currentWindow) {
|
|
3474
|
+
return () => {
|
|
3475
|
+
handlers.forEach((h) => h());
|
|
3476
|
+
};
|
|
3477
|
+
}
|
|
3478
|
+
const propertyDescriptor = currentWindow.Object.getOwnPropertyDescriptor(currentWindow.HTMLInputElement.prototype, "value");
|
|
3479
|
+
const hookProperties = [
|
|
3480
|
+
[currentWindow.HTMLInputElement.prototype, "value"],
|
|
3481
|
+
[currentWindow.HTMLInputElement.prototype, "checked"],
|
|
3482
|
+
[currentWindow.HTMLSelectElement.prototype, "value"],
|
|
3483
|
+
[currentWindow.HTMLTextAreaElement.prototype, "value"],
|
|
3484
|
+
[currentWindow.HTMLSelectElement.prototype, "selectedIndex"],
|
|
3485
|
+
[currentWindow.HTMLOptionElement.prototype, "selected"]
|
|
3486
|
+
];
|
|
3487
|
+
if (propertyDescriptor?.set) {
|
|
3488
|
+
handlers.push(...hookProperties.map((p) => hookSetter(p[0], p[1], {
|
|
3489
|
+
set() {
|
|
3490
|
+
callbackWrapper(eventHandler)({
|
|
3491
|
+
target: this,
|
|
3492
|
+
isTrusted: false
|
|
3493
|
+
});
|
|
3494
|
+
}
|
|
3495
|
+
}, false, currentWindow)));
|
|
3496
|
+
}
|
|
3497
|
+
return callbackWrapper(() => {
|
|
3498
|
+
handlers.forEach((h) => h());
|
|
3499
|
+
});
|
|
3500
|
+
}
|
|
3501
|
+
function getNestedCSSRulePositions(rule) {
|
|
3502
|
+
const positions = [];
|
|
3503
|
+
function recurse(childRule, pos) {
|
|
3504
|
+
if (hasNestedCSSRule("CSSGroupingRule") && childRule.parentRule instanceof CSSGroupingRule || hasNestedCSSRule("CSSMediaRule") && childRule.parentRule instanceof CSSMediaRule || hasNestedCSSRule("CSSSupportsRule") && childRule.parentRule instanceof CSSSupportsRule || hasNestedCSSRule("CSSConditionRule") && childRule.parentRule instanceof CSSConditionRule) {
|
|
3505
|
+
const rules = Array.from(childRule.parentRule.cssRules);
|
|
3506
|
+
const index = rules.indexOf(childRule);
|
|
3507
|
+
pos.unshift(index);
|
|
3508
|
+
} else if (childRule.parentStyleSheet) {
|
|
3509
|
+
const rules = Array.from(childRule.parentStyleSheet.cssRules);
|
|
3510
|
+
const index = rules.indexOf(childRule);
|
|
3511
|
+
pos.unshift(index);
|
|
3512
|
+
}
|
|
3513
|
+
return pos;
|
|
3514
|
+
}
|
|
3515
|
+
return recurse(rule, positions);
|
|
3516
|
+
}
|
|
3517
|
+
function getPathAndStyleId(sheet, mirror, styleMirror) {
|
|
3518
|
+
let path;
|
|
3519
|
+
let styleId;
|
|
3520
|
+
if (!sheet)
|
|
3521
|
+
return {};
|
|
3522
|
+
if (sheet.ownerNode)
|
|
3523
|
+
path = mirror.getPath(sheet.ownerNode);
|
|
3524
|
+
else
|
|
3525
|
+
styleId = styleMirror.getId(sheet);
|
|
3526
|
+
return {
|
|
3527
|
+
styleId,
|
|
3528
|
+
path
|
|
3529
|
+
};
|
|
3530
|
+
}
|
|
3531
|
+
function initStyleSheetObserver({ styleSheetRuleCb, mirror, stylesheetManager }, { win }) {
|
|
3532
|
+
if (!win.CSSStyleSheet || !win.CSSStyleSheet.prototype) {
|
|
3533
|
+
return () => {};
|
|
3534
|
+
}
|
|
3535
|
+
const insertRule = win.CSSStyleSheet.prototype.insertRule;
|
|
3536
|
+
win.CSSStyleSheet.prototype.insertRule = new Proxy(insertRule, {
|
|
3537
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3538
|
+
const [rule, index] = argumentsList;
|
|
3539
|
+
const { path, styleId } = getPathAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
3540
|
+
if (path || styleId && styleId !== -1) {
|
|
3541
|
+
styleSheetRuleCb({
|
|
3542
|
+
path,
|
|
3543
|
+
styleId,
|
|
3544
|
+
adds: [{ rule, index }]
|
|
3545
|
+
});
|
|
3546
|
+
}
|
|
3547
|
+
return target.apply(thisArg, argumentsList);
|
|
3548
|
+
})
|
|
3549
|
+
});
|
|
3550
|
+
const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
|
|
3551
|
+
win.CSSStyleSheet.prototype.deleteRule = new Proxy(deleteRule, {
|
|
3552
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3553
|
+
const [index] = argumentsList;
|
|
3554
|
+
const { path, styleId } = getPathAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
3555
|
+
if (path || styleId && styleId !== -1) {
|
|
3556
|
+
styleSheetRuleCb({
|
|
3557
|
+
path,
|
|
3558
|
+
styleId,
|
|
3559
|
+
removes: [{ index }]
|
|
3560
|
+
});
|
|
3561
|
+
}
|
|
3562
|
+
return target.apply(thisArg, argumentsList);
|
|
3563
|
+
})
|
|
3564
|
+
});
|
|
3565
|
+
let replace;
|
|
3566
|
+
if (win.CSSStyleSheet.prototype.replace) {
|
|
3567
|
+
replace = win.CSSStyleSheet.prototype.replace;
|
|
3568
|
+
win.CSSStyleSheet.prototype.replace = new Proxy(replace, {
|
|
3569
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3570
|
+
const [text] = argumentsList;
|
|
3571
|
+
const { path, styleId } = getPathAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
3572
|
+
if (path || styleId && styleId !== -1) {
|
|
3573
|
+
styleSheetRuleCb({
|
|
3574
|
+
path,
|
|
3575
|
+
styleId,
|
|
3576
|
+
replace: text
|
|
3577
|
+
});
|
|
3578
|
+
}
|
|
3579
|
+
return target.apply(thisArg, argumentsList);
|
|
3580
|
+
})
|
|
3581
|
+
});
|
|
3582
|
+
}
|
|
3583
|
+
let replaceSync;
|
|
3584
|
+
if (win.CSSStyleSheet.prototype.replaceSync) {
|
|
3585
|
+
replaceSync = win.CSSStyleSheet.prototype.replaceSync;
|
|
3586
|
+
win.CSSStyleSheet.prototype.replaceSync = new Proxy(replaceSync, {
|
|
3587
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3588
|
+
const [text] = argumentsList;
|
|
3589
|
+
const { path, styleId } = getPathAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
3590
|
+
if (path || styleId && styleId !== -1) {
|
|
3591
|
+
styleSheetRuleCb({
|
|
3592
|
+
path,
|
|
3593
|
+
styleId,
|
|
3594
|
+
replaceSync: text
|
|
3595
|
+
});
|
|
3596
|
+
}
|
|
3597
|
+
return target.apply(thisArg, argumentsList);
|
|
3598
|
+
})
|
|
3599
|
+
});
|
|
3600
|
+
}
|
|
3601
|
+
const supportedNestedCSSRuleTypes = {};
|
|
3602
|
+
if (canMonkeyPatchNestedCSSRule("CSSGroupingRule")) {
|
|
3603
|
+
supportedNestedCSSRuleTypes.CSSGroupingRule = win.CSSGroupingRule;
|
|
3604
|
+
} else {
|
|
3605
|
+
if (canMonkeyPatchNestedCSSRule("CSSMediaRule")) {
|
|
3606
|
+
supportedNestedCSSRuleTypes.CSSMediaRule = win.CSSMediaRule;
|
|
3607
|
+
}
|
|
3608
|
+
if (canMonkeyPatchNestedCSSRule("CSSConditionRule")) {
|
|
3609
|
+
supportedNestedCSSRuleTypes.CSSConditionRule = win.CSSConditionRule;
|
|
3610
|
+
}
|
|
3611
|
+
if (canMonkeyPatchNestedCSSRule("CSSSupportsRule")) {
|
|
3612
|
+
supportedNestedCSSRuleTypes.CSSSupportsRule = win.CSSSupportsRule;
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
const unmodifiedFunctions = {};
|
|
3616
|
+
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
|
|
3617
|
+
unmodifiedFunctions[typeKey] = {
|
|
3618
|
+
insertRule: type.prototype.insertRule,
|
|
3619
|
+
deleteRule: type.prototype.deleteRule
|
|
3620
|
+
};
|
|
3621
|
+
type.prototype.insertRule = new Proxy(unmodifiedFunctions[typeKey].insertRule, {
|
|
3622
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3623
|
+
const [rule, index] = argumentsList;
|
|
3624
|
+
const { path, styleId } = getPathAndStyleId(thisArg.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
3625
|
+
if (path || styleId && styleId !== -1) {
|
|
3626
|
+
styleSheetRuleCb({
|
|
3627
|
+
path,
|
|
3628
|
+
styleId,
|
|
3629
|
+
adds: [
|
|
3630
|
+
{
|
|
3631
|
+
rule,
|
|
3632
|
+
index: [
|
|
3633
|
+
...getNestedCSSRulePositions(thisArg),
|
|
3634
|
+
index || 0
|
|
3635
|
+
]
|
|
3636
|
+
}
|
|
3637
|
+
]
|
|
3638
|
+
});
|
|
3639
|
+
}
|
|
3640
|
+
return target.apply(thisArg, argumentsList);
|
|
3641
|
+
})
|
|
3642
|
+
});
|
|
3643
|
+
type.prototype.deleteRule = new Proxy(unmodifiedFunctions[typeKey].deleteRule, {
|
|
3644
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3645
|
+
const [index] = argumentsList;
|
|
3646
|
+
const { path, styleId } = getPathAndStyleId(thisArg.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
3647
|
+
if (path || styleId && styleId !== -1) {
|
|
3648
|
+
styleSheetRuleCb({
|
|
3649
|
+
path,
|
|
3650
|
+
styleId,
|
|
3651
|
+
removes: [{ index: [...getNestedCSSRulePositions(thisArg), index] }]
|
|
3652
|
+
});
|
|
3653
|
+
}
|
|
3654
|
+
return target.apply(thisArg, argumentsList);
|
|
3655
|
+
})
|
|
3656
|
+
});
|
|
3657
|
+
});
|
|
3658
|
+
return callbackWrapper(() => {
|
|
3659
|
+
win.CSSStyleSheet.prototype.insertRule = insertRule;
|
|
3660
|
+
win.CSSStyleSheet.prototype.deleteRule = deleteRule;
|
|
3661
|
+
replace && (win.CSSStyleSheet.prototype.replace = replace);
|
|
3662
|
+
replaceSync && (win.CSSStyleSheet.prototype.replaceSync = replaceSync);
|
|
3663
|
+
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
|
|
3664
|
+
type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
|
|
3665
|
+
type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
|
|
3666
|
+
});
|
|
3667
|
+
});
|
|
3668
|
+
}
|
|
3669
|
+
function initAdoptedStyleSheetObserver({ mirror, stylesheetManager }, host2) {
|
|
3670
|
+
let hostPath = null;
|
|
3671
|
+
if (host2.nodeName === "#document")
|
|
3672
|
+
hostPath = mirror.getPath(host2);
|
|
3673
|
+
else
|
|
3674
|
+
hostPath = mirror.getPath(dom_default.host(host2));
|
|
3675
|
+
const patchTarget = host2.nodeName === "#document" ? host2.defaultView?.Document : host2.ownerDocument?.defaultView?.ShadowRoot;
|
|
3676
|
+
const originalPropertyDescriptor = patchTarget?.prototype ? Object.getOwnPropertyDescriptor(patchTarget?.prototype, "adoptedStyleSheets") : undefined;
|
|
3677
|
+
if (hostPath === null || !patchTarget || !originalPropertyDescriptor)
|
|
3678
|
+
return () => {};
|
|
3679
|
+
Object.defineProperty(host2, "adoptedStyleSheets", {
|
|
3680
|
+
configurable: originalPropertyDescriptor.configurable,
|
|
3681
|
+
enumerable: originalPropertyDescriptor.enumerable,
|
|
3682
|
+
get() {
|
|
3683
|
+
return originalPropertyDescriptor.get?.call(this);
|
|
3684
|
+
},
|
|
3685
|
+
set(sheets) {
|
|
3686
|
+
const result = originalPropertyDescriptor.set?.call(this, sheets);
|
|
3687
|
+
if (hostPath !== null) {
|
|
3688
|
+
try {
|
|
3689
|
+
stylesheetManager.adoptStyleSheets(sheets, hostPath);
|
|
3690
|
+
} catch (_e) {}
|
|
3691
|
+
}
|
|
3692
|
+
return result;
|
|
3693
|
+
}
|
|
3694
|
+
});
|
|
3695
|
+
return callbackWrapper(() => {
|
|
3696
|
+
Object.defineProperty(host2, "adoptedStyleSheets", {
|
|
3697
|
+
configurable: originalPropertyDescriptor.configurable,
|
|
3698
|
+
enumerable: originalPropertyDescriptor.enumerable,
|
|
3699
|
+
get: originalPropertyDescriptor.get,
|
|
3700
|
+
set: originalPropertyDescriptor.set
|
|
3701
|
+
});
|
|
3702
|
+
});
|
|
3703
|
+
}
|
|
3704
|
+
function initStyleDeclarationObserver({ styleDeclarationCb, mirror, ignoreCSSAttributes, stylesheetManager }, { win }) {
|
|
3705
|
+
const setProperty = win.CSSStyleDeclaration.prototype.setProperty;
|
|
3706
|
+
win.CSSStyleDeclaration.prototype.setProperty = new Proxy(setProperty, {
|
|
3707
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3708
|
+
const [property, value, priority] = argumentsList;
|
|
3709
|
+
if (ignoreCSSAttributes.has(property)) {
|
|
3710
|
+
return setProperty.apply(thisArg, [property, value, priority]);
|
|
3711
|
+
}
|
|
3712
|
+
const { path, styleId } = getPathAndStyleId(thisArg.parentRule?.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
3713
|
+
if (path || styleId && styleId !== -1) {
|
|
3714
|
+
styleDeclarationCb({
|
|
3715
|
+
path,
|
|
3716
|
+
styleId,
|
|
3717
|
+
set: {
|
|
3718
|
+
property,
|
|
3719
|
+
value,
|
|
3720
|
+
priority
|
|
3721
|
+
},
|
|
3722
|
+
index: getNestedCSSRulePositions(thisArg.parentRule)
|
|
3723
|
+
});
|
|
3724
|
+
}
|
|
3725
|
+
return target.apply(thisArg, argumentsList);
|
|
3726
|
+
})
|
|
3727
|
+
});
|
|
3728
|
+
const removeProperty = win.CSSStyleDeclaration.prototype.removeProperty;
|
|
3729
|
+
win.CSSStyleDeclaration.prototype.removeProperty = new Proxy(removeProperty, {
|
|
3730
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
3731
|
+
const [property] = argumentsList;
|
|
3732
|
+
if (ignoreCSSAttributes.has(property)) {
|
|
3733
|
+
return removeProperty.apply(thisArg, [property]);
|
|
3734
|
+
}
|
|
3735
|
+
const { path, styleId } = getPathAndStyleId(thisArg.parentRule?.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
3736
|
+
if (path || styleId && styleId !== -1) {
|
|
3737
|
+
styleDeclarationCb({
|
|
3738
|
+
path,
|
|
3739
|
+
styleId,
|
|
3740
|
+
remove: {
|
|
3741
|
+
property
|
|
3742
|
+
},
|
|
3743
|
+
index: getNestedCSSRulePositions(thisArg.parentRule)
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
return target.apply(thisArg, argumentsList);
|
|
3747
|
+
})
|
|
3748
|
+
});
|
|
3749
|
+
return callbackWrapper(() => {
|
|
3750
|
+
win.CSSStyleDeclaration.prototype.setProperty = setProperty;
|
|
3751
|
+
win.CSSStyleDeclaration.prototype.removeProperty = removeProperty;
|
|
3752
|
+
});
|
|
3753
|
+
}
|
|
3754
|
+
function initMediaInteractionObserver({
|
|
3755
|
+
mediaInteractionCb,
|
|
3756
|
+
blockClass,
|
|
3757
|
+
blockSelector,
|
|
3758
|
+
mirror,
|
|
3759
|
+
sampling,
|
|
3760
|
+
doc
|
|
3761
|
+
}) {
|
|
3762
|
+
const handler = callbackWrapper((type) => throttle(callbackWrapper((event) => {
|
|
3763
|
+
const target = getEventTarget(event);
|
|
3764
|
+
if (!target || isBlocked(target, blockClass, blockSelector, true)) {
|
|
3765
|
+
return;
|
|
3766
|
+
}
|
|
3767
|
+
const { currentTime, volume, muted, playbackRate, loop } = target;
|
|
3768
|
+
mediaInteractionCb({
|
|
3769
|
+
type,
|
|
3770
|
+
path: mirror.getPath(target),
|
|
3771
|
+
currentTime,
|
|
3772
|
+
volume,
|
|
3773
|
+
muted,
|
|
3774
|
+
playbackRate,
|
|
3775
|
+
loop
|
|
3776
|
+
});
|
|
3777
|
+
}), sampling.media || 500));
|
|
3778
|
+
const handlers = [
|
|
3779
|
+
on("play", handler(0 /* Play */), doc),
|
|
3780
|
+
on("pause", handler(1 /* Pause */), doc),
|
|
3781
|
+
on("seeked", handler(2 /* Seeked */), doc),
|
|
3782
|
+
on("volumechange", handler(3 /* VolumeChange */), doc),
|
|
3783
|
+
on("ratechange", handler(4 /* RateChange */), doc)
|
|
3784
|
+
];
|
|
3785
|
+
return callbackWrapper(() => {
|
|
3786
|
+
handlers.forEach((h) => h());
|
|
3787
|
+
});
|
|
3788
|
+
}
|
|
3789
|
+
function initSelectionObserver(param) {
|
|
3790
|
+
const { doc, mirror, blockClass, blockSelector, selectionCb } = param;
|
|
3791
|
+
let collapsed = true;
|
|
3792
|
+
const updateSelection = callbackWrapper(() => {
|
|
3793
|
+
const selection = doc.getSelection();
|
|
3794
|
+
if (!selection || collapsed && selection?.isCollapsed)
|
|
3795
|
+
return;
|
|
3796
|
+
collapsed = selection.isCollapsed || false;
|
|
3797
|
+
const ranges = [];
|
|
3798
|
+
const count = selection.rangeCount || 0;
|
|
3799
|
+
for (let i = 0;i < count; i++) {
|
|
3800
|
+
const range = selection.getRangeAt(i);
|
|
3801
|
+
const { startContainer, startOffset, endContainer, endOffset } = range;
|
|
3802
|
+
const blocked = isBlocked(startContainer, blockClass, blockSelector, true) || isBlocked(endContainer, blockClass, blockSelector, true);
|
|
3803
|
+
if (blocked)
|
|
3804
|
+
continue;
|
|
3805
|
+
ranges.push({
|
|
3806
|
+
start: mirror.getPath(startContainer),
|
|
3807
|
+
startOffset,
|
|
3808
|
+
end: mirror.getPath(endContainer),
|
|
3809
|
+
endOffset
|
|
3810
|
+
});
|
|
3811
|
+
}
|
|
3812
|
+
selectionCb({ ranges });
|
|
3813
|
+
});
|
|
3814
|
+
updateSelection();
|
|
3815
|
+
return on("selectionchange", updateSelection);
|
|
3816
|
+
}
|
|
3817
|
+
function initCustomElementObserver({ doc, customElementCb }) {
|
|
3818
|
+
const win = doc.defaultView;
|
|
3819
|
+
if (!win || !win.customElements)
|
|
3820
|
+
return () => {};
|
|
3821
|
+
const restoreHandler = patch(win.customElements, "define", (original) => function(name, constructor, options) {
|
|
3822
|
+
try {
|
|
3823
|
+
customElementCb({
|
|
3824
|
+
define: {
|
|
3825
|
+
name
|
|
3826
|
+
}
|
|
3827
|
+
});
|
|
3828
|
+
} catch (_e) {
|
|
3829
|
+
console.warn(`Custom element callback failed for ${name}`);
|
|
3830
|
+
}
|
|
3831
|
+
return original.apply(this, [name, constructor, options]);
|
|
3832
|
+
});
|
|
3833
|
+
return restoreHandler;
|
|
3834
|
+
}
|
|
3835
|
+
function initObservers(o) {
|
|
3836
|
+
const currentWindow = o.doc.defaultView;
|
|
3837
|
+
if (!currentWindow) {
|
|
3838
|
+
return () => {};
|
|
3839
|
+
}
|
|
3840
|
+
const mutationObserver = initMutationObserver(o, o.doc);
|
|
3841
|
+
const mousemoveHandler = initMoveObserver(o);
|
|
3842
|
+
const mouseInteractionHandler = initMouseInteractionObserver(o);
|
|
3843
|
+
const scrollHandler = initScrollObserver(o);
|
|
3844
|
+
const viewportResizeHandler = initViewportResizeObserver(o, {
|
|
3845
|
+
win: currentWindow
|
|
3846
|
+
});
|
|
3847
|
+
const inputHandler = initInputObserver(o);
|
|
3848
|
+
const mediaInteractionHandler = initMediaInteractionObserver(o);
|
|
3849
|
+
const styleSheetObserver = initStyleSheetObserver(o, { win: currentWindow });
|
|
3850
|
+
const adoptedStyleSheetObserver = initAdoptedStyleSheetObserver(o, o.doc);
|
|
3851
|
+
const styleDeclarationObserver = initStyleDeclarationObserver(o, {
|
|
3852
|
+
win: currentWindow
|
|
3853
|
+
});
|
|
3854
|
+
let fontObserver = () => {};
|
|
3855
|
+
if (o.collectFonts) {
|
|
3856
|
+
Promise.resolve().then(() => (init_font_observer(), exports_font_observer)).then(({ initFontObserver: initFontObserver2 }) => {
|
|
3857
|
+
fontObserver = initFontObserver2(o);
|
|
3858
|
+
});
|
|
3859
|
+
}
|
|
3860
|
+
const selectionObserver = initSelectionObserver(o);
|
|
3861
|
+
const customElementObserver = initCustomElementObserver(o);
|
|
3862
|
+
return callbackWrapper(() => {
|
|
3863
|
+
mutationBuffers.forEach((b) => b.reset());
|
|
3864
|
+
mutationObserver.disconnect();
|
|
3865
|
+
mousemoveHandler();
|
|
3866
|
+
mouseInteractionHandler();
|
|
3867
|
+
scrollHandler();
|
|
3868
|
+
viewportResizeHandler();
|
|
3869
|
+
inputHandler();
|
|
3870
|
+
mediaInteractionHandler();
|
|
3871
|
+
styleSheetObserver();
|
|
3872
|
+
adoptedStyleSheetObserver();
|
|
3873
|
+
styleDeclarationObserver();
|
|
3874
|
+
fontObserver();
|
|
3875
|
+
selectionObserver();
|
|
3876
|
+
customElementObserver();
|
|
3877
|
+
});
|
|
3878
|
+
}
|
|
3879
|
+
function hasNestedCSSRule(prop) {
|
|
3880
|
+
return typeof window[prop] !== "undefined";
|
|
3881
|
+
}
|
|
3882
|
+
function canMonkeyPatchNestedCSSRule(prop) {
|
|
3883
|
+
return Boolean(typeof window[prop] !== "undefined" && window[prop].prototype && "insertRule" in window[prop].prototype && "deleteRule" in window[prop].prototype);
|
|
3884
|
+
}
|
|
3885
|
+
|
|
3886
|
+
// ../rrweb-record/src/record/processed-node-manager.ts
|
|
3887
|
+
class ProcessedNodeManager {
|
|
3888
|
+
nodeMap = new WeakMap;
|
|
3889
|
+
active = false;
|
|
3890
|
+
inOtherBuffer(node, thisBuffer) {
|
|
3891
|
+
const buffers = this.nodeMap.get(node);
|
|
3892
|
+
return buffers && Array.from(buffers).some((buffer) => buffer !== thisBuffer);
|
|
3893
|
+
}
|
|
3894
|
+
add(node, buffer) {
|
|
3895
|
+
if (!this.active) {
|
|
3896
|
+
this.active = true;
|
|
3897
|
+
requestAnimationFrame(() => {
|
|
3898
|
+
this.nodeMap = new WeakMap;
|
|
3899
|
+
this.active = false;
|
|
3900
|
+
});
|
|
3901
|
+
}
|
|
3902
|
+
this.nodeMap.set(node, (this.nodeMap.get(node) || new Set).add(buffer));
|
|
3903
|
+
}
|
|
3904
|
+
destroy() {}
|
|
3905
|
+
}
|
|
3906
|
+
|
|
3907
|
+
// ../rrweb-record/src/record/shadow-dom-manager.ts
|
|
3908
|
+
init_dom();
|
|
3909
|
+
init_snapshot_utils();
|
|
3910
|
+
init_utils();
|
|
3911
|
+
class ShadowDomManager {
|
|
3912
|
+
shadowDoms = new WeakSet;
|
|
3913
|
+
mutationCb;
|
|
3914
|
+
scrollCb;
|
|
3915
|
+
bypassOptions;
|
|
3916
|
+
mirror;
|
|
3917
|
+
restoreHandlers = [];
|
|
3918
|
+
constructor(options) {
|
|
3919
|
+
this.mutationCb = options.mutationCb;
|
|
3920
|
+
this.scrollCb = options.scrollCb;
|
|
3921
|
+
this.bypassOptions = options.bypassOptions;
|
|
3922
|
+
this.mirror = options.mirror;
|
|
3923
|
+
this.init();
|
|
3924
|
+
}
|
|
3925
|
+
init() {
|
|
3926
|
+
this.reset();
|
|
3927
|
+
this.patchAttachShadow(Element, document);
|
|
3928
|
+
}
|
|
3929
|
+
addShadowRoot(shadowRoot2, doc) {
|
|
3930
|
+
if (!isNativeShadowDom(shadowRoot2))
|
|
3931
|
+
return;
|
|
3932
|
+
if (this.shadowDoms.has(shadowRoot2))
|
|
3933
|
+
return;
|
|
3934
|
+
this.shadowDoms.add(shadowRoot2);
|
|
3935
|
+
const observer = initMutationObserver({
|
|
3936
|
+
...this.bypassOptions,
|
|
3937
|
+
doc,
|
|
3938
|
+
mutationCb: this.mutationCb,
|
|
3939
|
+
mirror: this.mirror,
|
|
3940
|
+
shadowDomManager: this
|
|
3941
|
+
}, shadowRoot2);
|
|
3942
|
+
this.restoreHandlers.push(() => observer.disconnect());
|
|
3943
|
+
this.restoreHandlers.push(initScrollObserver({
|
|
3944
|
+
...this.bypassOptions,
|
|
3945
|
+
scrollCb: this.scrollCb,
|
|
3946
|
+
doc: shadowRoot2,
|
|
3947
|
+
mirror: this.mirror
|
|
3948
|
+
}));
|
|
3949
|
+
setTimeout(() => {
|
|
3950
|
+
if (shadowRoot2.adoptedStyleSheets && shadowRoot2.adoptedStyleSheets.length > 0)
|
|
3951
|
+
this.bypassOptions.stylesheetManager.adoptStyleSheets(shadowRoot2.adoptedStyleSheets, this.mirror.getPath(dom_default.host(shadowRoot2)));
|
|
3952
|
+
this.restoreHandlers.push(initAdoptedStyleSheetObserver({
|
|
3953
|
+
mirror: this.mirror,
|
|
3954
|
+
stylesheetManager: this.bypassOptions.stylesheetManager
|
|
3955
|
+
}, shadowRoot2));
|
|
3956
|
+
}, 0);
|
|
3957
|
+
}
|
|
3958
|
+
observeAttachShadow(iframeElement) {
|
|
3959
|
+
if (!iframeElement.contentWindow || !iframeElement.contentDocument)
|
|
3960
|
+
return;
|
|
3961
|
+
this.patchAttachShadow(iframeElement.contentWindow.Element, iframeElement.contentDocument);
|
|
3962
|
+
}
|
|
3963
|
+
patchAttachShadow(element, doc) {
|
|
3964
|
+
const manager = this;
|
|
3965
|
+
this.restoreHandlers.push(patch(element.prototype, "attachShadow", (original) => function(option) {
|
|
3966
|
+
const sRoot = original.call(this, option);
|
|
3967
|
+
const shadowRootEl = dom_default.shadowRoot(this);
|
|
3968
|
+
if (shadowRootEl && inDom(this))
|
|
3969
|
+
manager.addShadowRoot(shadowRootEl, doc);
|
|
3970
|
+
return sRoot;
|
|
3971
|
+
}));
|
|
3972
|
+
}
|
|
3973
|
+
reset() {
|
|
3974
|
+
this.restoreHandlers.forEach((handler) => {
|
|
3975
|
+
try {
|
|
3976
|
+
handler();
|
|
3977
|
+
} catch (_e) {}
|
|
3978
|
+
});
|
|
3979
|
+
this.restoreHandlers = [];
|
|
3980
|
+
this.shadowDoms = new WeakSet;
|
|
3981
|
+
}
|
|
3982
|
+
}
|
|
3983
|
+
|
|
3984
|
+
// ../rrweb-record/src/record/stylesheet-manager.ts
|
|
3985
|
+
init_snapshot_utils();
|
|
3986
|
+
init_utils();
|
|
3987
|
+
|
|
3988
|
+
class StylesheetManager {
|
|
3989
|
+
trackedLinkElements = new WeakSet;
|
|
3990
|
+
mutationCb;
|
|
3991
|
+
adoptedStyleSheetCb;
|
|
3992
|
+
styleMirror = new StyleSheetMirror;
|
|
3993
|
+
constructor(options) {
|
|
3994
|
+
this.mutationCb = options.mutationCb;
|
|
3995
|
+
this.adoptedStyleSheetCb = options.adoptedStyleSheetCb;
|
|
3996
|
+
}
|
|
3997
|
+
attachLinkElement(linkEl, childSn) {
|
|
3998
|
+
if ("_cssText" in childSn.attributes)
|
|
3999
|
+
this.mutationCb({
|
|
4000
|
+
adds: [],
|
|
4001
|
+
removes: [],
|
|
4002
|
+
texts: [],
|
|
4003
|
+
attributes: [
|
|
4004
|
+
{
|
|
4005
|
+
path: childSn.path,
|
|
4006
|
+
attributes: childSn.attributes
|
|
4007
|
+
}
|
|
4008
|
+
]
|
|
4009
|
+
});
|
|
4010
|
+
this.trackLinkElement(linkEl);
|
|
4011
|
+
}
|
|
4012
|
+
trackLinkElement(linkEl) {
|
|
4013
|
+
if (this.trackedLinkElements.has(linkEl))
|
|
4014
|
+
return;
|
|
4015
|
+
this.trackedLinkElements.add(linkEl);
|
|
4016
|
+
this.trackStylesheetInLinkElement(linkEl);
|
|
4017
|
+
}
|
|
4018
|
+
adoptStyleSheets(sheets, hostPath) {
|
|
4019
|
+
if (sheets.length === 0)
|
|
4020
|
+
return;
|
|
4021
|
+
const adoptedStyleSheetData = {
|
|
4022
|
+
path: hostPath,
|
|
4023
|
+
styleIds: []
|
|
4024
|
+
};
|
|
4025
|
+
const styles = [];
|
|
4026
|
+
for (const sheet of sheets) {
|
|
4027
|
+
let styleId;
|
|
4028
|
+
if (!this.styleMirror.has(sheet)) {
|
|
4029
|
+
styleId = this.styleMirror.add(sheet);
|
|
4030
|
+
styles.push({
|
|
4031
|
+
styleId,
|
|
4032
|
+
rules: Array.from(sheet.cssRules || sheet.rules, (r, index) => ({
|
|
4033
|
+
rule: stringifyRule(r, sheet.href),
|
|
4034
|
+
index
|
|
4035
|
+
}))
|
|
4036
|
+
});
|
|
4037
|
+
} else
|
|
4038
|
+
styleId = this.styleMirror.getId(sheet);
|
|
4039
|
+
adoptedStyleSheetData.styleIds.push(styleId);
|
|
4040
|
+
}
|
|
4041
|
+
if (styles.length > 0)
|
|
4042
|
+
adoptedStyleSheetData.styles = styles;
|
|
4043
|
+
this.adoptedStyleSheetCb(adoptedStyleSheetData);
|
|
4044
|
+
}
|
|
4045
|
+
reset() {
|
|
4046
|
+
this.styleMirror.reset();
|
|
4047
|
+
this.trackedLinkElements = new WeakSet;
|
|
4048
|
+
}
|
|
4049
|
+
trackStylesheetInLinkElement(_linkEl) {}
|
|
4050
|
+
}
|
|
4051
|
+
|
|
4052
|
+
// ../rrweb-record/src/record/index.ts
|
|
4053
|
+
var wrappedEmit;
|
|
4054
|
+
var takeFullSnapshot;
|
|
4055
|
+
var recording = false;
|
|
4056
|
+
var mirror = createMirror();
|
|
4057
|
+
function record(options = {}) {
|
|
4058
|
+
const {
|
|
4059
|
+
emit,
|
|
4060
|
+
initialPageMetadata,
|
|
4061
|
+
blockClass = "rr-block",
|
|
4062
|
+
blockSelector = null,
|
|
4063
|
+
ignoreClass = "rr-ignore",
|
|
4064
|
+
ignoreSelector = null,
|
|
4065
|
+
maskTextClass = "rr-mask",
|
|
4066
|
+
maskTextSelector = null,
|
|
4067
|
+
inlineStylesheet = true,
|
|
4068
|
+
maskAllInputs,
|
|
4069
|
+
maskInputOptions: _maskInputOptions,
|
|
4070
|
+
slimDOMOptions: _slimDOMOptions,
|
|
4071
|
+
maskInputFn,
|
|
4072
|
+
maskTextFn,
|
|
4073
|
+
sampling = {},
|
|
4074
|
+
dataURLOptions = {},
|
|
4075
|
+
recordCanvas = false,
|
|
4076
|
+
recordCrossOriginIframes = false,
|
|
4077
|
+
collectFonts = false,
|
|
4078
|
+
inlineImages = false,
|
|
4079
|
+
keepIframeSrcFn = () => false,
|
|
4080
|
+
ignoreCSSAttributes = new Set([]),
|
|
4081
|
+
errorHandler: errorHandler2
|
|
4082
|
+
} = options;
|
|
4083
|
+
registerErrorHandler(errorHandler2);
|
|
4084
|
+
const inEmittingFrame = recordCrossOriginIframes ? window.parent === window : true;
|
|
4085
|
+
let passEmitsToParent = false;
|
|
4086
|
+
if (!inEmittingFrame) {
|
|
4087
|
+
try {
|
|
4088
|
+
if (window.parent.document) {
|
|
4089
|
+
passEmitsToParent = false;
|
|
4090
|
+
}
|
|
4091
|
+
} catch (_e) {
|
|
4092
|
+
passEmitsToParent = true;
|
|
4093
|
+
}
|
|
4094
|
+
}
|
|
4095
|
+
if (inEmittingFrame && !emit) {
|
|
4096
|
+
throw new Error("emit function is required");
|
|
4097
|
+
}
|
|
4098
|
+
if (!inEmittingFrame && !passEmitsToParent) {
|
|
4099
|
+
return () => {};
|
|
4100
|
+
}
|
|
4101
|
+
mirror.reset();
|
|
4102
|
+
const maskInputOptions = maskAllInputs === false ? _maskInputOptions !== undefined ? _maskInputOptions : { password: true } : {
|
|
4103
|
+
color: true,
|
|
4104
|
+
date: true,
|
|
4105
|
+
"datetime-local": true,
|
|
4106
|
+
email: true,
|
|
4107
|
+
month: true,
|
|
4108
|
+
number: true,
|
|
4109
|
+
range: true,
|
|
4110
|
+
search: true,
|
|
4111
|
+
tel: true,
|
|
4112
|
+
text: true,
|
|
4113
|
+
time: true,
|
|
4114
|
+
url: true,
|
|
4115
|
+
week: true,
|
|
4116
|
+
textarea: true,
|
|
4117
|
+
select: true,
|
|
4118
|
+
password: true
|
|
4119
|
+
};
|
|
4120
|
+
const slimDOMOptions = _slimDOMOptions === true || _slimDOMOptions === "all" ? {
|
|
4121
|
+
script: true,
|
|
4122
|
+
comment: true,
|
|
4123
|
+
headFavicon: true,
|
|
4124
|
+
headWhitespace: true,
|
|
4125
|
+
headMetaSocial: true,
|
|
4126
|
+
headMetaRobots: true,
|
|
4127
|
+
headMetaHttpEquiv: true,
|
|
4128
|
+
headMetaVerification: true,
|
|
4129
|
+
headMetaAuthorship: _slimDOMOptions === "all",
|
|
4130
|
+
headMetaDescKeywords: _slimDOMOptions === "all",
|
|
4131
|
+
headTitleMutations: _slimDOMOptions === "all"
|
|
4132
|
+
} : _slimDOMOptions ? _slimDOMOptions : {};
|
|
4133
|
+
wrappedEmit = (r, isCheckout) => {
|
|
4134
|
+
const e = r;
|
|
4135
|
+
e.timestamp = nowTimestamp();
|
|
4136
|
+
if (mutationBuffers[0]?.isFrozen() && e.type !== 7 /* Pageview */ && !(e.type === 3 /* IncrementalSnapshot */ && e.data.source === 0 /* Mutation */)) {
|
|
4137
|
+
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
4138
|
+
}
|
|
4139
|
+
if (inEmittingFrame) {
|
|
4140
|
+
emit?.(e, isCheckout);
|
|
4141
|
+
} else if (passEmitsToParent) {
|
|
4142
|
+
const message = {
|
|
4143
|
+
type: "rrweb",
|
|
4144
|
+
event: e,
|
|
4145
|
+
origin: window.location.origin,
|
|
4146
|
+
isCheckout
|
|
4147
|
+
};
|
|
4148
|
+
window.parent.postMessage(message, "*");
|
|
4149
|
+
}
|
|
4150
|
+
};
|
|
4151
|
+
const wrappedMutationEmit = (m) => {
|
|
4152
|
+
wrappedEmit({
|
|
4153
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4154
|
+
data: {
|
|
4155
|
+
source: 0 /* Mutation */,
|
|
4156
|
+
...m
|
|
4157
|
+
}
|
|
4158
|
+
});
|
|
4159
|
+
};
|
|
4160
|
+
const wrappedScrollEmit = (p) => wrappedEmit({
|
|
4161
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4162
|
+
data: {
|
|
4163
|
+
source: 3 /* Scroll */,
|
|
4164
|
+
...p
|
|
4165
|
+
}
|
|
4166
|
+
});
|
|
4167
|
+
const wrappedCanvasMutationEmit = (p) => wrappedEmit({
|
|
4168
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4169
|
+
data: {
|
|
4170
|
+
source: 9 /* CanvasMutation */,
|
|
4171
|
+
...p
|
|
4172
|
+
}
|
|
4173
|
+
});
|
|
4174
|
+
const wrappedAdoptedStyleSheetEmit = (a) => wrappedEmit({
|
|
4175
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4176
|
+
data: {
|
|
4177
|
+
source: 15 /* AdoptedStyleSheet */,
|
|
4178
|
+
...a
|
|
4179
|
+
}
|
|
4180
|
+
});
|
|
4181
|
+
const stylesheetManager = new StylesheetManager({
|
|
4182
|
+
mutationCb: wrappedMutationEmit,
|
|
4183
|
+
adoptedStyleSheetCb: wrappedAdoptedStyleSheetEmit
|
|
4184
|
+
});
|
|
4185
|
+
const iframeManager = new IframeManager({
|
|
4186
|
+
mirror,
|
|
4187
|
+
mutationCb: wrappedMutationEmit,
|
|
4188
|
+
stylesheetManager,
|
|
4189
|
+
recordCrossOriginIframes,
|
|
4190
|
+
wrappedEmit
|
|
4191
|
+
});
|
|
4192
|
+
const processedNodeManager = new ProcessedNodeManager;
|
|
4193
|
+
let canvasManager = null;
|
|
4194
|
+
if (recordCanvas) {
|
|
4195
|
+
Promise.resolve().then(() => (init_canvas_manager(), exports_canvas_manager)).then(({ CanvasManager: CanvasManager2 }) => {
|
|
4196
|
+
canvasManager = new CanvasManager2({
|
|
4197
|
+
recordCanvas,
|
|
4198
|
+
mutationCb: wrappedCanvasMutationEmit,
|
|
4199
|
+
win: window,
|
|
4200
|
+
blockClass,
|
|
4201
|
+
blockSelector,
|
|
4202
|
+
mirror,
|
|
4203
|
+
sampling: sampling.canvas,
|
|
4204
|
+
dataURLOptions
|
|
4205
|
+
});
|
|
4206
|
+
for (const buf of mutationBuffers) {
|
|
4207
|
+
buf.setCanvasManager(canvasManager);
|
|
4208
|
+
}
|
|
4209
|
+
});
|
|
4210
|
+
}
|
|
4211
|
+
const shadowDomManager = new ShadowDomManager({
|
|
4212
|
+
mutationCb: wrappedMutationEmit,
|
|
4213
|
+
scrollCb: wrappedScrollEmit,
|
|
4214
|
+
bypassOptions: {
|
|
4215
|
+
blockClass,
|
|
4216
|
+
blockSelector,
|
|
4217
|
+
maskTextClass,
|
|
4218
|
+
maskTextSelector,
|
|
4219
|
+
inlineStylesheet,
|
|
4220
|
+
maskInputOptions,
|
|
4221
|
+
dataURLOptions,
|
|
4222
|
+
maskTextFn,
|
|
4223
|
+
maskInputFn,
|
|
4224
|
+
recordCanvas,
|
|
4225
|
+
inlineImages,
|
|
4226
|
+
sampling,
|
|
4227
|
+
slimDOMOptions,
|
|
4228
|
+
iframeManager,
|
|
4229
|
+
stylesheetManager,
|
|
4230
|
+
canvasManager,
|
|
4231
|
+
keepIframeSrcFn,
|
|
4232
|
+
processedNodeManager
|
|
4233
|
+
},
|
|
4234
|
+
mirror
|
|
4235
|
+
});
|
|
4236
|
+
takeFullSnapshot = (isCheckout = false, pageMetadata) => {
|
|
4237
|
+
stylesheetManager.reset();
|
|
4238
|
+
shadowDomManager.init();
|
|
4239
|
+
mutationBuffers.forEach((buf) => buf.lock());
|
|
4240
|
+
const node = snapshot_default(document, {
|
|
4241
|
+
mirror,
|
|
4242
|
+
blockClass,
|
|
4243
|
+
blockSelector,
|
|
4244
|
+
maskTextClass,
|
|
4245
|
+
maskTextSelector,
|
|
4246
|
+
inlineStylesheet,
|
|
4247
|
+
maskAllInputs: maskInputOptions,
|
|
4248
|
+
maskTextFn,
|
|
4249
|
+
maskInputFn,
|
|
4250
|
+
slimDOM: slimDOMOptions,
|
|
4251
|
+
dataURLOptions,
|
|
4252
|
+
recordCanvas,
|
|
4253
|
+
inlineImages,
|
|
4254
|
+
onSerialize: (n) => {
|
|
4255
|
+
if (isSerializedIframe(n, mirror)) {
|
|
4256
|
+
iframeManager.addIframe(n);
|
|
4257
|
+
}
|
|
4258
|
+
if (isSerializedStylesheet(n, mirror)) {
|
|
4259
|
+
stylesheetManager.trackLinkElement(n);
|
|
4260
|
+
}
|
|
4261
|
+
if (hasShadowRoot(n)) {
|
|
4262
|
+
shadowDomManager.addShadowRoot(dom_default.shadowRoot(n), document);
|
|
4263
|
+
}
|
|
4264
|
+
},
|
|
4265
|
+
onIframeLoad: (iframe, childSn) => {
|
|
4266
|
+
iframeManager.attachIframe(iframe, childSn);
|
|
4267
|
+
shadowDomManager.observeAttachShadow(iframe);
|
|
4268
|
+
},
|
|
4269
|
+
onStylesheetLoad: (linkEl, childSn) => {
|
|
4270
|
+
stylesheetManager.attachLinkElement(linkEl, childSn);
|
|
4271
|
+
},
|
|
4272
|
+
keepIframeSrcFn
|
|
4273
|
+
});
|
|
4274
|
+
if (!node) {
|
|
4275
|
+
return console.warn("Failed to snapshot the document");
|
|
4276
|
+
}
|
|
4277
|
+
wrappedEmit({
|
|
4278
|
+
type: 7 /* Pageview */,
|
|
4279
|
+
data: {
|
|
4280
|
+
href: window.location.href,
|
|
4281
|
+
width: getWindowWidth(),
|
|
4282
|
+
height: getWindowHeight(),
|
|
4283
|
+
node,
|
|
4284
|
+
initialOffset: getWindowScroll(window),
|
|
4285
|
+
...pageMetadata
|
|
4286
|
+
}
|
|
4287
|
+
}, isCheckout);
|
|
4288
|
+
mutationBuffers.forEach((buf) => buf.unlock());
|
|
4289
|
+
if (document.adoptedStyleSheets && document.adoptedStyleSheets.length > 0)
|
|
4290
|
+
stylesheetManager.adoptStyleSheets(document.adoptedStyleSheets, mirror.getPath(document));
|
|
4291
|
+
};
|
|
4292
|
+
try {
|
|
4293
|
+
const handlers = [];
|
|
4294
|
+
const observe = (doc) => {
|
|
4295
|
+
return callbackWrapper(initObservers)({
|
|
4296
|
+
mutationCb: wrappedMutationEmit,
|
|
4297
|
+
mousemoveCb: (positions, source) => wrappedEmit({
|
|
4298
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4299
|
+
data: {
|
|
4300
|
+
source,
|
|
4301
|
+
positions
|
|
4302
|
+
}
|
|
4303
|
+
}),
|
|
4304
|
+
mouseInteractionCb: (d) => wrappedEmit({
|
|
4305
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4306
|
+
data: {
|
|
4307
|
+
source: 2 /* MouseInteraction */,
|
|
4308
|
+
...d
|
|
4309
|
+
}
|
|
4310
|
+
}),
|
|
4311
|
+
scrollCb: wrappedScrollEmit,
|
|
4312
|
+
viewportResizeCb: (d) => wrappedEmit({
|
|
4313
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4314
|
+
data: {
|
|
4315
|
+
source: 4 /* ViewportResize */,
|
|
4316
|
+
...d
|
|
4317
|
+
}
|
|
4318
|
+
}),
|
|
4319
|
+
inputCb: (v) => wrappedEmit({
|
|
4320
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4321
|
+
data: {
|
|
4322
|
+
source: 5 /* Input */,
|
|
4323
|
+
...v
|
|
4324
|
+
}
|
|
4325
|
+
}),
|
|
4326
|
+
mediaInteractionCb: (p) => wrappedEmit({
|
|
4327
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4328
|
+
data: {
|
|
4329
|
+
source: 7 /* MediaInteraction */,
|
|
4330
|
+
...p
|
|
4331
|
+
}
|
|
4332
|
+
}),
|
|
4333
|
+
styleSheetRuleCb: (r) => wrappedEmit({
|
|
4334
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4335
|
+
data: {
|
|
4336
|
+
source: 8 /* StyleSheetRule */,
|
|
4337
|
+
...r
|
|
4338
|
+
}
|
|
4339
|
+
}),
|
|
4340
|
+
styleDeclarationCb: (r) => wrappedEmit({
|
|
4341
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4342
|
+
data: {
|
|
4343
|
+
source: 13 /* StyleDeclaration */,
|
|
4344
|
+
...r
|
|
4345
|
+
}
|
|
4346
|
+
}),
|
|
4347
|
+
canvasMutationCb: wrappedCanvasMutationEmit,
|
|
4348
|
+
fontCb: (p) => wrappedEmit({
|
|
4349
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4350
|
+
data: {
|
|
4351
|
+
source: 10 /* Font */,
|
|
4352
|
+
...p
|
|
4353
|
+
}
|
|
4354
|
+
}),
|
|
4355
|
+
selectionCb: (p) => {
|
|
4356
|
+
wrappedEmit({
|
|
4357
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4358
|
+
data: {
|
|
4359
|
+
source: 14 /* Selection */,
|
|
4360
|
+
...p
|
|
4361
|
+
}
|
|
4362
|
+
});
|
|
4363
|
+
},
|
|
4364
|
+
customElementCb: (c) => {
|
|
4365
|
+
wrappedEmit({
|
|
4366
|
+
type: 3 /* IncrementalSnapshot */,
|
|
4367
|
+
data: {
|
|
4368
|
+
source: 16 /* CustomElement */,
|
|
4369
|
+
...c
|
|
4370
|
+
}
|
|
4371
|
+
});
|
|
4372
|
+
},
|
|
4373
|
+
blockClass,
|
|
4374
|
+
ignoreClass,
|
|
4375
|
+
ignoreSelector,
|
|
4376
|
+
maskTextClass,
|
|
4377
|
+
maskTextSelector,
|
|
4378
|
+
maskInputOptions,
|
|
4379
|
+
inlineStylesheet,
|
|
4380
|
+
sampling,
|
|
4381
|
+
recordCanvas,
|
|
4382
|
+
inlineImages,
|
|
4383
|
+
collectFonts,
|
|
4384
|
+
doc,
|
|
4385
|
+
maskInputFn,
|
|
4386
|
+
maskTextFn,
|
|
4387
|
+
keepIframeSrcFn,
|
|
4388
|
+
blockSelector,
|
|
4389
|
+
slimDOMOptions,
|
|
4390
|
+
dataURLOptions,
|
|
4391
|
+
mirror,
|
|
4392
|
+
iframeManager,
|
|
4393
|
+
stylesheetManager,
|
|
4394
|
+
shadowDomManager,
|
|
4395
|
+
processedNodeManager,
|
|
4396
|
+
canvasManager,
|
|
4397
|
+
ignoreCSSAttributes
|
|
4398
|
+
});
|
|
4399
|
+
};
|
|
4400
|
+
iframeManager.addLoadListener((iframeEl) => {
|
|
4401
|
+
try {
|
|
4402
|
+
handlers.push(observe(iframeEl.contentDocument));
|
|
4403
|
+
} catch (error) {
|
|
4404
|
+
console.warn(error);
|
|
4405
|
+
}
|
|
4406
|
+
});
|
|
4407
|
+
const init = () => {
|
|
4408
|
+
takeFullSnapshot(false, initialPageMetadata);
|
|
4409
|
+
handlers.push(observe(document));
|
|
4410
|
+
recording = true;
|
|
4411
|
+
};
|
|
4412
|
+
if (document.readyState === "interactive" || document.readyState === "complete") {
|
|
4413
|
+
init();
|
|
4414
|
+
} else {
|
|
4415
|
+
handlers.push(on("DOMContentLoaded", () => {
|
|
4416
|
+
wrappedEmit({
|
|
4417
|
+
type: 0 /* DomContentLoaded */,
|
|
4418
|
+
data: {}
|
|
4419
|
+
});
|
|
4420
|
+
}));
|
|
4421
|
+
handlers.push(on("load", () => {
|
|
4422
|
+
wrappedEmit({
|
|
4423
|
+
type: 1 /* Load */,
|
|
4424
|
+
data: {}
|
|
4425
|
+
});
|
|
4426
|
+
init();
|
|
4427
|
+
}, window));
|
|
4428
|
+
}
|
|
4429
|
+
return () => {
|
|
4430
|
+
handlers.forEach((h) => h());
|
|
4431
|
+
processedNodeManager.destroy();
|
|
4432
|
+
recording = false;
|
|
4433
|
+
unregisterErrorHandler();
|
|
4434
|
+
};
|
|
4435
|
+
} catch (error) {
|
|
4436
|
+
console.warn(error);
|
|
4437
|
+
}
|
|
4438
|
+
}
|
|
4439
|
+
record.addCustomEvent = (tag, payload) => {
|
|
4440
|
+
if (!recording) {
|
|
4441
|
+
throw new Error("please add custom event after start recording");
|
|
4442
|
+
}
|
|
4443
|
+
wrappedEmit({
|
|
4444
|
+
type: 5 /* Custom */,
|
|
4445
|
+
data: {
|
|
4446
|
+
tag,
|
|
4447
|
+
payload
|
|
4448
|
+
}
|
|
4449
|
+
});
|
|
4450
|
+
};
|
|
4451
|
+
record.freezePage = () => {
|
|
4452
|
+
mutationBuffers.forEach((buf) => buf.freeze());
|
|
4453
|
+
};
|
|
4454
|
+
record.takeFullSnapshot = (isCheckout) => {
|
|
4455
|
+
if (!recording) {
|
|
4456
|
+
throw new Error("please take full snapshot after start recording");
|
|
4457
|
+
}
|
|
4458
|
+
takeFullSnapshot(isCheckout);
|
|
4459
|
+
};
|
|
4460
|
+
record.takePageviewSnapshot = (metadata) => {
|
|
4461
|
+
if (!recording) {
|
|
4462
|
+
throw new Error("please take pageview snapshot after start recording");
|
|
4463
|
+
}
|
|
4464
|
+
flushMutationObservers();
|
|
4465
|
+
mutationBuffers.forEach((buf) => buf.dropPending());
|
|
4466
|
+
takeFullSnapshot(false, metadata);
|
|
4467
|
+
};
|
|
4468
|
+
record.mirror = mirror;
|
|
4469
|
+
var record_default = record;
|
|
4470
|
+
|
|
4471
|
+
// ../rrweb-record/src/index.ts
|
|
4472
|
+
init_snapshot_utils();
|
|
4473
|
+
|
|
4474
|
+
// src/persistence.ts
|
|
4475
|
+
var VISITOR_COOKIE = "__ld_vid";
|
|
4476
|
+
var SESSION_COOKIE = "__ld_sid";
|
|
4477
|
+
var VISITOR_MAX_AGE = 365 * 24 * 60 * 60;
|
|
4478
|
+
var SESSION_MAX_AGE = 30 * 60;
|
|
4479
|
+
function getCookie(name) {
|
|
4480
|
+
const match = document.cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]*)`));
|
|
4481
|
+
return match?.[1] ? decodeURIComponent(match[1]) : null;
|
|
4482
|
+
}
|
|
4483
|
+
function setCookie(name, value, maxAge) {
|
|
4484
|
+
document.cookie = `${name}=${encodeURIComponent(value)};path=/;max-age=${maxAge};SameSite=Lax`;
|
|
4485
|
+
}
|
|
4486
|
+
function deleteCookie(name) {
|
|
4487
|
+
document.cookie = `${name}=;path=/;max-age=0;SameSite=Lax`;
|
|
4488
|
+
}
|
|
4489
|
+
function createCookiePersistence() {
|
|
4490
|
+
return {
|
|
4491
|
+
mode: "cookie",
|
|
4492
|
+
getVisitorId() {
|
|
4493
|
+
return getCookie(VISITOR_COOKIE);
|
|
4494
|
+
},
|
|
4495
|
+
getSessionId() {
|
|
4496
|
+
return getCookie(SESSION_COOKIE);
|
|
4497
|
+
},
|
|
4498
|
+
setVisitorId(id) {
|
|
4499
|
+
setCookie(VISITOR_COOKIE, id, VISITOR_MAX_AGE);
|
|
4500
|
+
},
|
|
4501
|
+
setSessionId(id) {
|
|
4502
|
+
setCookie(SESSION_COOKIE, id, SESSION_MAX_AGE);
|
|
4503
|
+
},
|
|
4504
|
+
touchSession() {
|
|
4505
|
+
const sid = getCookie(SESSION_COOKIE);
|
|
4506
|
+
if (sid)
|
|
4507
|
+
setCookie(SESSION_COOKIE, sid, SESSION_MAX_AGE);
|
|
4508
|
+
},
|
|
4509
|
+
clear() {
|
|
4510
|
+
deleteCookie(VISITOR_COOKIE);
|
|
4511
|
+
deleteCookie(SESSION_COOKIE);
|
|
4512
|
+
}
|
|
4513
|
+
};
|
|
4514
|
+
}
|
|
4515
|
+
function createCookielessPersistence() {
|
|
4516
|
+
return {
|
|
4517
|
+
mode: "cookieless",
|
|
4518
|
+
getVisitorId: () => null,
|
|
4519
|
+
getSessionId: () => null,
|
|
4520
|
+
setVisitorId: () => {},
|
|
4521
|
+
setSessionId: () => {},
|
|
4522
|
+
touchSession: () => {},
|
|
4523
|
+
clear: () => {}
|
|
4524
|
+
};
|
|
4525
|
+
}
|
|
4526
|
+
function createPersistence(mode) {
|
|
4527
|
+
return mode === "cookie" ? createCookiePersistence() : createCookielessPersistence();
|
|
4528
|
+
}
|
|
4529
|
+
|
|
4530
|
+
// src/recorder-core.ts
|
|
4531
|
+
var DEFAULT_ENDPOINT = "https://ingest.lunardinos.com";
|
|
4532
|
+
async function gzipCompress(input) {
|
|
4533
|
+
try {
|
|
4534
|
+
if (typeof CompressionStream === "undefined")
|
|
4535
|
+
return null;
|
|
4536
|
+
const blob = new Blob([input]);
|
|
4537
|
+
const stream = blob.stream().pipeThrough(new CompressionStream("gzip"));
|
|
4538
|
+
return await new Response(stream).blob();
|
|
4539
|
+
} catch {
|
|
4540
|
+
return null;
|
|
4541
|
+
}
|
|
4542
|
+
}
|
|
4543
|
+
var INTERACTIVE_TAGS = new Set(["a", "button", "input", "select", "textarea"]);
|
|
4544
|
+
function findInteractiveElement(target) {
|
|
4545
|
+
let el = target;
|
|
4546
|
+
while (el && el !== document.body) {
|
|
4547
|
+
if (INTERACTIVE_TAGS.has(el.tagName.toLowerCase()) || el.getAttribute("role")) {
|
|
4548
|
+
return el;
|
|
4549
|
+
}
|
|
4550
|
+
el = el.parentElement;
|
|
4551
|
+
}
|
|
4552
|
+
return target;
|
|
4553
|
+
}
|
|
4554
|
+
function getDirectText(el) {
|
|
4555
|
+
const text = el.innerText?.trim().slice(0, 80);
|
|
4556
|
+
return text || null;
|
|
4557
|
+
}
|
|
4558
|
+
function truncateText(text) {
|
|
4559
|
+
if (!text)
|
|
4560
|
+
return null;
|
|
4561
|
+
return text.length > 40 ? `${text.slice(0, 37)}...` : text;
|
|
4562
|
+
}
|
|
4563
|
+
function extractUtmParams() {
|
|
4564
|
+
const params = new URLSearchParams(window.location.search);
|
|
4565
|
+
const utm = {};
|
|
4566
|
+
for (const key of ["utm_source", "utm_medium", "utm_campaign", "utm_term", "utm_content"]) {
|
|
4567
|
+
const val = params.get(key);
|
|
4568
|
+
if (val)
|
|
4569
|
+
utm[key] = val;
|
|
4570
|
+
}
|
|
4571
|
+
return utm;
|
|
4572
|
+
}
|
|
4573
|
+
function createLunarDinosRecorder(config) {
|
|
4574
|
+
const { apiKey, endpoint = DEFAULT_ENDPOINT, rrwebOptions = {}, batchInterval = 2000 } = config;
|
|
4575
|
+
const defaultRrwebOptions = {
|
|
4576
|
+
inlineImages: true
|
|
4577
|
+
};
|
|
4578
|
+
const url = `${endpoint}/api/events`;
|
|
4579
|
+
let persistence = createPersistence(config.defaultPersistence ?? "cookie");
|
|
4580
|
+
function beaconUrl() {
|
|
4581
|
+
const u = new URL(url);
|
|
4582
|
+
u.searchParams.set("key", apiKey);
|
|
4583
|
+
if (persistence.mode === "cookieless")
|
|
4584
|
+
u.searchParams.set("cookieless", "1");
|
|
4585
|
+
return u.toString();
|
|
4586
|
+
}
|
|
4587
|
+
function send(body, headers) {
|
|
4588
|
+
const reqHeaders = {
|
|
4589
|
+
...headers,
|
|
4590
|
+
Authorization: `Bearer ${apiKey}`
|
|
4591
|
+
};
|
|
4592
|
+
if (persistence.mode === "cookieless") {
|
|
4593
|
+
reqHeaders["X-LD-Cookieless"] = "1";
|
|
4594
|
+
}
|
|
4595
|
+
fetch(url, {
|
|
4596
|
+
method: "POST",
|
|
4597
|
+
headers: reqHeaders,
|
|
4598
|
+
body
|
|
4599
|
+
}).catch(() => {});
|
|
4600
|
+
}
|
|
4601
|
+
function sendViaBeacon(json) {
|
|
4602
|
+
try {
|
|
4603
|
+
const blob = new Blob([json], { type: "text/plain" });
|
|
4604
|
+
const sent = navigator.sendBeacon(beaconUrl(), blob);
|
|
4605
|
+
if (sent)
|
|
4606
|
+
return;
|
|
4607
|
+
} catch {}
|
|
4608
|
+
try {
|
|
4609
|
+
fetch(beaconUrl(), {
|
|
4610
|
+
method: "POST",
|
|
4611
|
+
body: json,
|
|
4612
|
+
headers: { "Content-Type": "application/json" },
|
|
4613
|
+
keepalive: true
|
|
4614
|
+
}).catch(() => {});
|
|
4615
|
+
} catch {}
|
|
4616
|
+
}
|
|
4617
|
+
let events = [];
|
|
4618
|
+
let sessionId = null;
|
|
4619
|
+
let visitorId = null;
|
|
4620
|
+
let stopFn = null;
|
|
4621
|
+
let intervalId = null;
|
|
4622
|
+
let recording2 = false;
|
|
4623
|
+
let pendingClickContext = null;
|
|
4624
|
+
let pendingInputContext = null;
|
|
4625
|
+
function captureSubmit(e) {
|
|
4626
|
+
if (!recording2)
|
|
4627
|
+
return;
|
|
4628
|
+
const form = e.target;
|
|
4629
|
+
const formName = form.getAttribute("name") ?? form.getAttribute("id") ?? form.getAttribute("aria-label") ?? null;
|
|
4630
|
+
const formAction = form.getAttribute("action") ?? null;
|
|
4631
|
+
try {
|
|
4632
|
+
record_default.addCustomEvent("submit", { formName, formAction });
|
|
4633
|
+
} catch {}
|
|
4634
|
+
}
|
|
4635
|
+
function captureInputContext(e) {
|
|
4636
|
+
const el = e.target;
|
|
4637
|
+
const tag = el.tagName?.toLowerCase();
|
|
4638
|
+
if (tag !== "input" && tag !== "select" && tag !== "textarea")
|
|
4639
|
+
return;
|
|
4640
|
+
const inputEl = el;
|
|
4641
|
+
const inputName = inputEl.getAttribute("name") ?? inputEl.getAttribute("id") ?? inputEl.getAttribute("aria-label") ?? (tag !== "select" ? inputEl.getAttribute("placeholder") : null) ?? (() => {
|
|
4642
|
+
const id = inputEl.id;
|
|
4643
|
+
if (id) {
|
|
4644
|
+
const label = document.querySelector(`label[for="${id}"]`);
|
|
4645
|
+
if (label)
|
|
4646
|
+
return truncateText(label.textContent?.trim() ?? null);
|
|
4647
|
+
}
|
|
4648
|
+
const parentLabel = inputEl.closest("label");
|
|
4649
|
+
return truncateText(parentLabel?.textContent?.trim() ?? null);
|
|
4650
|
+
})() ?? null;
|
|
4651
|
+
pendingInputContext = { inputTag: tag, inputName };
|
|
4652
|
+
}
|
|
4653
|
+
function captureClickContext(e) {
|
|
4654
|
+
const raw = e.target;
|
|
4655
|
+
const clicked = findInteractiveElement(raw);
|
|
4656
|
+
const tag = clicked.tagName?.toLowerCase() ?? "unknown";
|
|
4657
|
+
const TAG_ROLES = {
|
|
4658
|
+
button: "button",
|
|
4659
|
+
a: "link",
|
|
4660
|
+
input: "textbox",
|
|
4661
|
+
select: "combobox",
|
|
4662
|
+
textarea: "textbox"
|
|
4663
|
+
};
|
|
4664
|
+
const role = clicked.getAttribute("role") ?? TAG_ROLES[tag] ?? null;
|
|
4665
|
+
const name = clicked.getAttribute("aria-label") ?? clicked.getAttribute("name") ?? clicked.getAttribute("title") ?? truncateText(getDirectText(clicked)) ?? clicked.querySelector("[aria-label]")?.getAttribute("aria-label") ?? null;
|
|
4666
|
+
const href = tag === "a" ? clicked.getAttribute("href") : clicked.closest("a")?.getAttribute("href") ?? null;
|
|
4667
|
+
pendingClickContext = { clickTag: tag, clickRole: role, clickName: name, clickHref: href };
|
|
4668
|
+
}
|
|
4669
|
+
function flush(options) {
|
|
4670
|
+
if (events.length === 0 || !sessionId)
|
|
4671
|
+
return;
|
|
4672
|
+
const batch = events.splice(0);
|
|
4673
|
+
const id = sessionId;
|
|
4674
|
+
const vid = visitorId;
|
|
4675
|
+
const payload = { sessionId: id, events: batch };
|
|
4676
|
+
if (vid)
|
|
4677
|
+
payload.visitorId = vid;
|
|
4678
|
+
const json = JSON.stringify(payload);
|
|
4679
|
+
persistence.touchSession();
|
|
4680
|
+
if (options?.beacon) {
|
|
4681
|
+
sendViaBeacon(json);
|
|
4682
|
+
return;
|
|
4683
|
+
}
|
|
4684
|
+
gzipCompress(json).then((compressed) => {
|
|
4685
|
+
if (compressed && compressed.size < json.length) {
|
|
4686
|
+
send(compressed, {
|
|
4687
|
+
"Content-Type": "application/json",
|
|
4688
|
+
"Content-Encoding": "gzip"
|
|
4689
|
+
});
|
|
4690
|
+
} else {
|
|
4691
|
+
send(json, { "Content-Type": "application/json" });
|
|
4692
|
+
}
|
|
4693
|
+
});
|
|
4694
|
+
}
|
|
4695
|
+
function identify(payload) {
|
|
4696
|
+
if (!recording2)
|
|
4697
|
+
return;
|
|
4698
|
+
try {
|
|
4699
|
+
record_default.addCustomEvent("identify", payload);
|
|
4700
|
+
} catch {}
|
|
4701
|
+
flush();
|
|
4702
|
+
}
|
|
4703
|
+
function emitPageEvent(payload) {
|
|
4704
|
+
if (!recording2)
|
|
4705
|
+
return;
|
|
4706
|
+
try {
|
|
4707
|
+
record_default.takePageviewSnapshot({
|
|
4708
|
+
href: payload.href,
|
|
4709
|
+
title: payload.title,
|
|
4710
|
+
routePattern: payload.routePattern ?? undefined,
|
|
4711
|
+
params: payload.params,
|
|
4712
|
+
referrer: payload.referrer ?? externalReferrer()
|
|
4713
|
+
});
|
|
4714
|
+
} catch {}
|
|
4715
|
+
}
|
|
4716
|
+
function captureError(e) {
|
|
4717
|
+
if (!recording2)
|
|
4718
|
+
return;
|
|
4719
|
+
try {
|
|
4720
|
+
record_default.addCustomEvent("error", {
|
|
4721
|
+
message: e.message ?? "Unknown error",
|
|
4722
|
+
source: e.filename ?? null
|
|
4723
|
+
});
|
|
4724
|
+
} catch {}
|
|
4725
|
+
}
|
|
4726
|
+
function captureRejection(e) {
|
|
4727
|
+
if (!recording2)
|
|
4728
|
+
return;
|
|
4729
|
+
try {
|
|
4730
|
+
const message = e.reason instanceof Error ? e.reason.message : String(e.reason ?? "Unhandled rejection");
|
|
4731
|
+
record_default.addCustomEvent("error", {
|
|
4732
|
+
message,
|
|
4733
|
+
source: null
|
|
4734
|
+
});
|
|
4735
|
+
} catch {}
|
|
4736
|
+
}
|
|
4737
|
+
function externalReferrer() {
|
|
4738
|
+
const ref = document.referrer;
|
|
4739
|
+
if (!ref)
|
|
4740
|
+
return null;
|
|
4741
|
+
try {
|
|
4742
|
+
return new URL(ref).origin === window.location.origin ? null : ref;
|
|
4743
|
+
} catch {
|
|
4744
|
+
return ref;
|
|
4745
|
+
}
|
|
4746
|
+
}
|
|
4747
|
+
function emitSessionMeta() {
|
|
4748
|
+
try {
|
|
4749
|
+
const utm = extractUtmParams();
|
|
4750
|
+
record_default.addCustomEvent("session:meta", {
|
|
4751
|
+
referrer: externalReferrer(),
|
|
4752
|
+
landingPage: window.location.pathname,
|
|
4753
|
+
...utm
|
|
4754
|
+
});
|
|
4755
|
+
} catch {}
|
|
4756
|
+
}
|
|
4757
|
+
function start(optionsOrSessionId) {
|
|
4758
|
+
if (recording2)
|
|
4759
|
+
return sessionId;
|
|
4760
|
+
const startOpts = typeof optionsOrSessionId === "string" ? { sessionId: optionsOrSessionId } : optionsOrSessionId ?? {};
|
|
4761
|
+
const existingSessionId = startOpts.sessionId;
|
|
4762
|
+
const SESSION_STORAGE_KEY = "__ld_sid";
|
|
4763
|
+
let isNewSession = false;
|
|
4764
|
+
if (persistence.mode === "cookie") {
|
|
4765
|
+
const persistedSession = persistence.getSessionId();
|
|
4766
|
+
const storedSession = typeof sessionStorage !== "undefined" ? sessionStorage.getItem(SESSION_STORAGE_KEY) : null;
|
|
4767
|
+
isNewSession = !persistedSession && !storedSession;
|
|
4768
|
+
sessionId = persistedSession || storedSession || existingSessionId || crypto.randomUUID();
|
|
4769
|
+
persistence.setSessionId(sessionId);
|
|
4770
|
+
if (typeof sessionStorage !== "undefined") {
|
|
4771
|
+
sessionStorage.setItem(SESSION_STORAGE_KEY, sessionId);
|
|
4772
|
+
}
|
|
4773
|
+
} else {
|
|
4774
|
+
sessionId = existingSessionId || crypto.randomUUID();
|
|
4775
|
+
}
|
|
4776
|
+
visitorId = persistence.getVisitorId();
|
|
4777
|
+
if (!visitorId && persistence.mode === "cookie") {
|
|
4778
|
+
visitorId = crypto.randomUUID();
|
|
4779
|
+
persistence.setVisitorId(visitorId);
|
|
4780
|
+
}
|
|
4781
|
+
events = [];
|
|
4782
|
+
recording2 = true;
|
|
4783
|
+
document.addEventListener("click", captureClickContext, true);
|
|
4784
|
+
document.addEventListener("input", captureInputContext, true);
|
|
4785
|
+
document.addEventListener("change", captureInputContext, true);
|
|
4786
|
+
document.addEventListener("submit", captureSubmit, true);
|
|
4787
|
+
window.addEventListener("error", captureError);
|
|
4788
|
+
window.addEventListener("unhandledrejection", captureRejection);
|
|
4789
|
+
stopFn = record_default({
|
|
4790
|
+
...defaultRrwebOptions,
|
|
4791
|
+
...rrwebOptions,
|
|
4792
|
+
initialPageMetadata: startOpts.pageMetadata ? {
|
|
4793
|
+
href: startOpts.pageMetadata.href,
|
|
4794
|
+
title: startOpts.pageMetadata.title,
|
|
4795
|
+
routePattern: startOpts.pageMetadata.routePattern ?? undefined,
|
|
4796
|
+
params: startOpts.pageMetadata.params,
|
|
4797
|
+
referrer: startOpts.pageMetadata.referrer ?? undefined
|
|
4798
|
+
} : undefined,
|
|
4799
|
+
emit(event) {
|
|
4800
|
+
const ev = event;
|
|
4801
|
+
if (ev.type === 3 && ev.data?.source === 2 && ev.data?.type === 2 && pendingClickContext) {
|
|
4802
|
+
const d = ev.data;
|
|
4803
|
+
d.clickTag = pendingClickContext.clickTag;
|
|
4804
|
+
d.clickRole = pendingClickContext.clickRole;
|
|
4805
|
+
d.clickName = pendingClickContext.clickName;
|
|
4806
|
+
d.clickHref = pendingClickContext.clickHref;
|
|
4807
|
+
pendingClickContext = null;
|
|
4808
|
+
}
|
|
4809
|
+
if (ev.type === 3 && ev.data?.source === 5 && pendingInputContext) {
|
|
4810
|
+
const d = ev.data;
|
|
4811
|
+
d.inputTag = pendingInputContext.inputTag;
|
|
4812
|
+
d.inputName = pendingInputContext.inputName;
|
|
4813
|
+
pendingInputContext = null;
|
|
4814
|
+
}
|
|
4815
|
+
events.push(event);
|
|
4816
|
+
}
|
|
4817
|
+
});
|
|
4818
|
+
if (persistence.mode === "cookieless" || isNewSession) {
|
|
4819
|
+
emitSessionMeta();
|
|
4820
|
+
}
|
|
4821
|
+
flush();
|
|
4822
|
+
intervalId = setInterval(flush, batchInterval);
|
|
4823
|
+
return sessionId;
|
|
4824
|
+
}
|
|
4825
|
+
function stop() {
|
|
4826
|
+
if (!recording2)
|
|
4827
|
+
return;
|
|
4828
|
+
document.removeEventListener("click", captureClickContext, true);
|
|
4829
|
+
document.removeEventListener("input", captureInputContext, true);
|
|
4830
|
+
document.removeEventListener("change", captureInputContext, true);
|
|
4831
|
+
document.removeEventListener("submit", captureSubmit, true);
|
|
4832
|
+
window.removeEventListener("error", captureError);
|
|
4833
|
+
window.removeEventListener("unhandledrejection", captureRejection);
|
|
4834
|
+
try {
|
|
4835
|
+
record_default.addCustomEvent("session:end", {});
|
|
4836
|
+
} catch {}
|
|
4837
|
+
flush();
|
|
4838
|
+
if (intervalId) {
|
|
4839
|
+
clearInterval(intervalId);
|
|
4840
|
+
intervalId = null;
|
|
4841
|
+
}
|
|
4842
|
+
stopFn?.();
|
|
4843
|
+
stopFn = null;
|
|
4844
|
+
recording2 = false;
|
|
4845
|
+
sessionId = null;
|
|
4846
|
+
visitorId = null;
|
|
4847
|
+
events = [];
|
|
4848
|
+
pendingClickContext = null;
|
|
4849
|
+
pendingInputContext = null;
|
|
4850
|
+
}
|
|
4851
|
+
function setPersistence(mode) {
|
|
4852
|
+
const oldMode = persistence.mode;
|
|
4853
|
+
if (oldMode === mode)
|
|
4854
|
+
return;
|
|
4855
|
+
if (oldMode === "cookieless" && mode === "cookie") {
|
|
4856
|
+
persistence.clear();
|
|
4857
|
+
persistence = createPersistence("cookie");
|
|
4858
|
+
const newVisitorId = crypto.randomUUID();
|
|
4859
|
+
persistence.setVisitorId(newVisitorId);
|
|
4860
|
+
if (sessionId)
|
|
4861
|
+
persistence.setSessionId(sessionId);
|
|
4862
|
+
const oldVisitorId = visitorId;
|
|
4863
|
+
visitorId = newVisitorId;
|
|
4864
|
+
if (recording2 && oldVisitorId !== newVisitorId) {
|
|
4865
|
+
try {
|
|
4866
|
+
record_default.addCustomEvent("visitor:link", {
|
|
4867
|
+
previousVisitorId: oldVisitorId,
|
|
4868
|
+
newVisitorId
|
|
4869
|
+
});
|
|
4870
|
+
} catch {}
|
|
4871
|
+
}
|
|
4872
|
+
} else if (oldMode === "cookie" && mode === "cookieless") {
|
|
4873
|
+
persistence.clear();
|
|
4874
|
+
persistence = createPersistence("cookieless");
|
|
4875
|
+
visitorId = null;
|
|
4876
|
+
}
|
|
4877
|
+
}
|
|
4878
|
+
return {
|
|
4879
|
+
start,
|
|
4880
|
+
stop,
|
|
4881
|
+
flush,
|
|
4882
|
+
getSessionId: () => sessionId,
|
|
4883
|
+
getVisitorId: () => visitorId,
|
|
4884
|
+
isRecording: () => recording2,
|
|
4885
|
+
emitPageEvent,
|
|
4886
|
+
identify,
|
|
4887
|
+
setPersistence
|
|
4888
|
+
};
|
|
4889
|
+
}
|
|
4890
|
+
export {
|
|
4891
|
+
createLunarDinosRecorder
|
|
4892
|
+
};
|