@sentry/replay 7.66.0 → 7.67.0-beta.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/cjs/index.js +2281 -1084
- package/cjs/index.js.map +1 -1
- package/esm/index.js +2281 -1084
- package/esm/index.js.map +1 -1
- package/package.json +7 -7
- package/types/constants.d.ts +2 -0
- package/types/constants.d.ts.map +1 -1
- package/types/coreHandlers/handleClick.d.ts.map +1 -1
- package/types/coreHandlers/handleDom.d.ts +1 -2
- package/types/coreHandlers/handleDom.d.ts.map +1 -1
- package/types/index.d.ts +2 -1
- package/types/index.d.ts.map +1 -1
- package/types/integration.d.ts +1 -1
- package/types/integration.d.ts.map +1 -1
- package/types/replay.d.ts +7 -1
- package/types/replay.d.ts.map +1 -1
- package/types/session/Session.d.ts.map +1 -1
- package/types/session/loadOrCreateSession.d.ts +2 -1
- package/types/session/loadOrCreateSession.d.ts.map +1 -1
- package/types/session/shouldRefreshSession.d.ts +4 -0
- package/types/session/shouldRefreshSession.d.ts.map +1 -0
- package/types/types/deprecated.d.ts +16 -0
- package/types/types/deprecated.d.ts.map +1 -0
- package/types/types/replay.d.ts +9 -9
- package/types/types/replay.d.ts.map +1 -1
- package/types/types/replayFrame.d.ts +45 -45
- package/types/types/replayFrame.d.ts.map +1 -1
- package/types/types/rrweb.d.ts +14 -16
- package/types/types/rrweb.d.ts.map +1 -1
- package/types/util/createBreadcrumb.d.ts +2 -2
- package/types/util/createBreadcrumb.d.ts.map +1 -1
- package/types/util/getPrivacyOptions.d.ts +0 -2
- package/types/util/getPrivacyOptions.d.ts.map +1 -1
- package/types/util/handleRecordingEmit.d.ts +2 -2
- package/types/util/handleRecordingEmit.d.ts.map +1 -1
- package/types/util/maskAttribute.d.ts +15 -0
- package/types/util/maskAttribute.d.ts.map +1 -0
- package/types/session/maybeRefreshSession.d.ts +0 -11
- package/types/session/maybeRefreshSession.d.ts.map +0 -1
package/cjs/index.js
CHANGED
|
@@ -63,44 +63,135 @@ var NodeType$1;
|
|
|
63
63
|
NodeType[NodeType["Comment"] = 5] = "Comment";
|
|
64
64
|
})(NodeType$1 || (NodeType$1 = {}));
|
|
65
65
|
|
|
66
|
-
function isElement(n) {
|
|
66
|
+
function isElement$1(n) {
|
|
67
67
|
return n.nodeType === n.ELEMENT_NODE;
|
|
68
68
|
}
|
|
69
69
|
function isShadowRoot(n) {
|
|
70
70
|
const host = n === null || n === void 0 ? void 0 : n.host;
|
|
71
|
-
return Boolean(host
|
|
71
|
+
return Boolean((host === null || host === void 0 ? void 0 : host.shadowRoot) === n);
|
|
72
72
|
}
|
|
73
|
-
function
|
|
74
|
-
|
|
75
|
-
|
|
73
|
+
function isNativeShadowDom(shadowRoot) {
|
|
74
|
+
return Object.prototype.toString.call(shadowRoot) === '[object ShadowRoot]';
|
|
75
|
+
}
|
|
76
|
+
function fixBrowserCompatibilityIssuesInCSS(cssText) {
|
|
77
|
+
if (cssText.includes(' background-clip: text;') &&
|
|
78
|
+
!cssText.includes(' -webkit-background-clip: text;')) {
|
|
79
|
+
cssText = cssText.replace(' background-clip: text;', ' -webkit-background-clip: text; background-clip: text;');
|
|
76
80
|
}
|
|
77
|
-
|
|
78
|
-
return (maskInputOptions[tagName.toLowerCase()] ||
|
|
79
|
-
(actualType && maskInputOptions[actualType]) ||
|
|
80
|
-
actualType === 'password' ||
|
|
81
|
-
(tagName === 'input' && !type && maskInputOptions['text']));
|
|
81
|
+
return cssText;
|
|
82
82
|
}
|
|
83
|
-
function
|
|
84
|
-
|
|
83
|
+
function getCssRulesString(s) {
|
|
84
|
+
try {
|
|
85
|
+
const rules = s.rules || s.cssRules;
|
|
86
|
+
return rules
|
|
87
|
+
? fixBrowserCompatibilityIssuesInCSS(Array.from(rules).map(getCssRuleString).join(''))
|
|
88
|
+
: null;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
85
93
|
}
|
|
86
|
-
function
|
|
87
|
-
let
|
|
88
|
-
if (
|
|
89
|
-
|
|
94
|
+
function getCssRuleString(rule) {
|
|
95
|
+
let cssStringified = rule.cssText;
|
|
96
|
+
if (isCSSImportRule(rule)) {
|
|
97
|
+
try {
|
|
98
|
+
cssStringified = getCssRulesString(rule.styleSheet) || cssStringified;
|
|
99
|
+
}
|
|
100
|
+
catch (_a) {
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return validateStringifiedCssRule(cssStringified);
|
|
104
|
+
}
|
|
105
|
+
function validateStringifiedCssRule(cssStringified) {
|
|
106
|
+
if (cssStringified.includes(':')) {
|
|
107
|
+
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
108
|
+
return cssStringified.replace(regex, '$1\\$2');
|
|
109
|
+
}
|
|
110
|
+
return cssStringified;
|
|
111
|
+
}
|
|
112
|
+
function isCSSImportRule(rule) {
|
|
113
|
+
return 'styleSheet' in rule;
|
|
114
|
+
}
|
|
115
|
+
class Mirror {
|
|
116
|
+
constructor() {
|
|
117
|
+
this.idNodeMap = new Map();
|
|
118
|
+
this.nodeMetaMap = new WeakMap();
|
|
90
119
|
}
|
|
91
|
-
|
|
92
|
-
|
|
120
|
+
getId(n) {
|
|
121
|
+
var _a;
|
|
122
|
+
if (!n)
|
|
123
|
+
return -1;
|
|
124
|
+
const id = (_a = this.getMeta(n)) === null || _a === void 0 ? void 0 : _a.id;
|
|
125
|
+
return id !== null && id !== void 0 ? id : -1;
|
|
126
|
+
}
|
|
127
|
+
getNode(id) {
|
|
128
|
+
return this.idNodeMap.get(id) || null;
|
|
129
|
+
}
|
|
130
|
+
getIds() {
|
|
131
|
+
return Array.from(this.idNodeMap.keys());
|
|
132
|
+
}
|
|
133
|
+
getMeta(n) {
|
|
134
|
+
return this.nodeMetaMap.get(n) || null;
|
|
93
135
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
136
|
+
removeNodeFromMap(n) {
|
|
137
|
+
const id = this.getId(n);
|
|
138
|
+
this.idNodeMap.delete(id);
|
|
139
|
+
if (n.childNodes) {
|
|
140
|
+
n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode));
|
|
98
141
|
}
|
|
99
|
-
|
|
100
|
-
|
|
142
|
+
}
|
|
143
|
+
has(id) {
|
|
144
|
+
return this.idNodeMap.has(id);
|
|
145
|
+
}
|
|
146
|
+
hasNode(node) {
|
|
147
|
+
return this.nodeMetaMap.has(node);
|
|
148
|
+
}
|
|
149
|
+
add(n, meta) {
|
|
150
|
+
const id = meta.id;
|
|
151
|
+
this.idNodeMap.set(id, n);
|
|
152
|
+
this.nodeMetaMap.set(n, meta);
|
|
153
|
+
}
|
|
154
|
+
replace(id, n) {
|
|
155
|
+
const oldNode = this.getNode(id);
|
|
156
|
+
if (oldNode) {
|
|
157
|
+
const meta = this.nodeMetaMap.get(oldNode);
|
|
158
|
+
if (meta)
|
|
159
|
+
this.nodeMetaMap.set(n, meta);
|
|
101
160
|
}
|
|
161
|
+
this.idNodeMap.set(id, n);
|
|
162
|
+
}
|
|
163
|
+
reset() {
|
|
164
|
+
this.idNodeMap = new Map();
|
|
165
|
+
this.nodeMetaMap = new WeakMap();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
function createMirror() {
|
|
169
|
+
return new Mirror();
|
|
170
|
+
}
|
|
171
|
+
function shouldMaskInput({ maskInputOptions, tagName, type, }) {
|
|
172
|
+
if (tagName === 'OPTION') {
|
|
173
|
+
tagName = 'SELECT';
|
|
174
|
+
}
|
|
175
|
+
return Boolean(maskInputOptions[tagName.toLowerCase()] ||
|
|
176
|
+
(type && maskInputOptions[type]) ||
|
|
177
|
+
type === 'password' ||
|
|
178
|
+
(tagName === 'INPUT' && !type && maskInputOptions['text']));
|
|
179
|
+
}
|
|
180
|
+
function maskInputValue({ isMasked, element, value, maskInputFn, }) {
|
|
181
|
+
let text = value || '';
|
|
182
|
+
if (!isMasked) {
|
|
183
|
+
return text;
|
|
184
|
+
}
|
|
185
|
+
if (maskInputFn) {
|
|
186
|
+
text = maskInputFn(text, element);
|
|
102
187
|
}
|
|
103
|
-
return text;
|
|
188
|
+
return '*'.repeat(text.length);
|
|
189
|
+
}
|
|
190
|
+
function toLowerCase(str) {
|
|
191
|
+
return str.toLowerCase();
|
|
192
|
+
}
|
|
193
|
+
function toUpperCase(str) {
|
|
194
|
+
return str.toUpperCase();
|
|
104
195
|
}
|
|
105
196
|
const ORIGINAL_ATTRIBUTE_NAME = '__rrweb_original__';
|
|
106
197
|
function is2DCanvasBlank(canvas) {
|
|
@@ -126,11 +217,11 @@ function getInputType(element) {
|
|
|
126
217
|
return element.hasAttribute('data-rr-is-password')
|
|
127
218
|
? 'password'
|
|
128
219
|
: type
|
|
129
|
-
?
|
|
220
|
+
?
|
|
221
|
+
toLowerCase(type)
|
|
130
222
|
: null;
|
|
131
223
|
}
|
|
132
224
|
function getInputValue(el, tagName, type) {
|
|
133
|
-
typeof type === 'string' ? type.toLowerCase() : '';
|
|
134
225
|
if (tagName === 'INPUT' && (type === 'radio' || type === 'checkbox')) {
|
|
135
226
|
return el.getAttribute('value') || '';
|
|
136
227
|
}
|
|
@@ -140,9 +231,6 @@ function getInputValue(el, tagName, type) {
|
|
|
140
231
|
let _id = 1;
|
|
141
232
|
const tagNameRegex = new RegExp('[^a-z0-9-_:]');
|
|
142
233
|
const IGNORED_NODE = -2;
|
|
143
|
-
function defaultMaskFn(str) {
|
|
144
|
-
return str ? str.replace(/[\S]/g, '*') : '';
|
|
145
|
-
}
|
|
146
234
|
function genId() {
|
|
147
235
|
return _id++;
|
|
148
236
|
}
|
|
@@ -150,42 +238,12 @@ function getValidTagName(element) {
|
|
|
150
238
|
if (element instanceof HTMLFormElement) {
|
|
151
239
|
return 'form';
|
|
152
240
|
}
|
|
153
|
-
const processedTagName = element.tagName
|
|
241
|
+
const processedTagName = toLowerCase(element.tagName);
|
|
154
242
|
if (tagNameRegex.test(processedTagName)) {
|
|
155
243
|
return 'div';
|
|
156
244
|
}
|
|
157
245
|
return processedTagName;
|
|
158
246
|
}
|
|
159
|
-
function getCssRulesString(s) {
|
|
160
|
-
try {
|
|
161
|
-
const rules = s.rules || s.cssRules;
|
|
162
|
-
return rules ? Array.from(rules).map(getCssRuleString).join('') : null;
|
|
163
|
-
}
|
|
164
|
-
catch (error) {
|
|
165
|
-
return null;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
function getCssRuleString(rule) {
|
|
169
|
-
let cssStringified = rule.cssText;
|
|
170
|
-
if (isCSSImportRule(rule)) {
|
|
171
|
-
try {
|
|
172
|
-
cssStringified = getCssRulesString(rule.styleSheet) || cssStringified;
|
|
173
|
-
}
|
|
174
|
-
catch (_a) {
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return validateStringifiedCssRule(cssStringified);
|
|
178
|
-
}
|
|
179
|
-
function validateStringifiedCssRule(cssStringified) {
|
|
180
|
-
if (cssStringified.indexOf(':') > -1) {
|
|
181
|
-
const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
|
|
182
|
-
return cssStringified.replace(regex, '$1\\$2');
|
|
183
|
-
}
|
|
184
|
-
return cssStringified;
|
|
185
|
-
}
|
|
186
|
-
function isCSSImportRule(rule) {
|
|
187
|
-
return 'styleSheet' in rule;
|
|
188
|
-
}
|
|
189
247
|
function stringifyStyleSheet(sheet) {
|
|
190
248
|
return sheet.cssRules
|
|
191
249
|
? Array.from(sheet.cssRules)
|
|
@@ -207,7 +265,8 @@ function extractOrigin(url) {
|
|
|
207
265
|
let canvasService;
|
|
208
266
|
let canvasCtx;
|
|
209
267
|
const URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm;
|
|
210
|
-
const
|
|
268
|
+
const URL_PROTOCOL_MATCH = /^(?:[a-z+]+:)?\/\//i;
|
|
269
|
+
const URL_WWW_MATCH = /^www\..*/i;
|
|
211
270
|
const DATA_URI = /^(data:)([^,]*),(.*)/i;
|
|
212
271
|
function absoluteToStylesheet(cssText, href) {
|
|
213
272
|
return (cssText || '').replace(URL_IN_CSS_REF, (origin, quote1, path1, quote2, path2, path3) => {
|
|
@@ -216,7 +275,7 @@ function absoluteToStylesheet(cssText, href) {
|
|
|
216
275
|
if (!filePath) {
|
|
217
276
|
return origin;
|
|
218
277
|
}
|
|
219
|
-
if (
|
|
278
|
+
if (URL_PROTOCOL_MATCH.test(filePath) || URL_WWW_MATCH.test(filePath)) {
|
|
220
279
|
return `url(${maybeQuote}${filePath}${maybeQuote})`;
|
|
221
280
|
}
|
|
222
281
|
if (DATA_URI.test(filePath)) {
|
|
@@ -251,7 +310,7 @@ function getAbsoluteSrcsetString(doc, attributeValue) {
|
|
|
251
310
|
let pos = 0;
|
|
252
311
|
function collectCharacters(regEx) {
|
|
253
312
|
let chars;
|
|
254
|
-
|
|
313
|
+
const match = regEx.exec(attributeValue.substring(pos));
|
|
255
314
|
if (match) {
|
|
256
315
|
chars = match[0];
|
|
257
316
|
pos += chars.length;
|
|
@@ -259,7 +318,7 @@ function getAbsoluteSrcsetString(doc, attributeValue) {
|
|
|
259
318
|
}
|
|
260
319
|
return '';
|
|
261
320
|
}
|
|
262
|
-
|
|
321
|
+
const output = [];
|
|
263
322
|
while (true) {
|
|
264
323
|
collectCharacters(SRCSET_COMMAS_OR_SPACES);
|
|
265
324
|
if (pos >= attributeValue.length) {
|
|
@@ -275,7 +334,7 @@ function getAbsoluteSrcsetString(doc, attributeValue) {
|
|
|
275
334
|
url = absoluteToDoc(doc, url);
|
|
276
335
|
let inParens = false;
|
|
277
336
|
while (true) {
|
|
278
|
-
|
|
337
|
+
const c = attributeValue.charAt(pos);
|
|
279
338
|
if (c === '') {
|
|
280
339
|
output.push((url + descriptorsStr).trim());
|
|
281
340
|
break;
|
|
@@ -318,13 +377,12 @@ function getHref() {
|
|
|
318
377
|
a.href = '';
|
|
319
378
|
return a.href;
|
|
320
379
|
}
|
|
321
|
-
function transformAttribute(doc,
|
|
380
|
+
function transformAttribute(doc, tagName, name, value, element, maskAttributeFn) {
|
|
322
381
|
if (!value) {
|
|
323
382
|
return value;
|
|
324
383
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
if (name === 'src' || name === 'href') {
|
|
384
|
+
if (name === 'src' ||
|
|
385
|
+
(name === 'href' && !(tagName === 'use' && value[0] === '#'))) {
|
|
328
386
|
return absoluteToDoc(doc, value);
|
|
329
387
|
}
|
|
330
388
|
else if (name === 'xlink:href' && value[0] !== '#') {
|
|
@@ -343,79 +401,113 @@ function transformAttribute(doc, element, _tagName, _name, value, maskAllText, u
|
|
|
343
401
|
else if (tagName === 'object' && name === 'data') {
|
|
344
402
|
return absoluteToDoc(doc, value);
|
|
345
403
|
}
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
return maskTextFn ? maskTextFn(value) : defaultMaskFn(value);
|
|
404
|
+
if (typeof maskAttributeFn === 'function') {
|
|
405
|
+
return maskAttributeFn(name, value, element);
|
|
349
406
|
}
|
|
350
407
|
return value;
|
|
351
408
|
}
|
|
352
|
-
function
|
|
353
|
-
|
|
354
|
-
return false;
|
|
355
|
-
}
|
|
356
|
-
return (['placeholder', 'title', 'aria-label'].indexOf(attribute) > -1 ||
|
|
357
|
-
(tagName === 'input' &&
|
|
358
|
-
attribute === 'value' &&
|
|
359
|
-
element.hasAttribute('type') &&
|
|
360
|
-
['submit', 'button'].indexOf(element.getAttribute('type').toLowerCase()) > -1));
|
|
409
|
+
function ignoreAttribute(tagName, name, _value) {
|
|
410
|
+
return (tagName === 'video' || tagName === 'audio') && name === 'autoplay';
|
|
361
411
|
}
|
|
362
412
|
function _isBlockedElement(element, blockClass, blockSelector, unblockSelector) {
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
if (typeof blockClass === 'string') {
|
|
367
|
-
if (element.classList.contains(blockClass)) {
|
|
368
|
-
return true;
|
|
413
|
+
try {
|
|
414
|
+
if (unblockSelector && element.matches(unblockSelector)) {
|
|
415
|
+
return false;
|
|
369
416
|
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
for (let eIndex = 0; eIndex < element.classList.length; eIndex++) {
|
|
373
|
-
const className = element.classList[eIndex];
|
|
374
|
-
if (blockClass.test(className)) {
|
|
417
|
+
if (typeof blockClass === 'string') {
|
|
418
|
+
if (element.classList.contains(blockClass)) {
|
|
375
419
|
return true;
|
|
376
420
|
}
|
|
377
421
|
}
|
|
422
|
+
else {
|
|
423
|
+
for (let eIndex = element.classList.length; eIndex--;) {
|
|
424
|
+
const className = element.classList[eIndex];
|
|
425
|
+
if (blockClass.test(className)) {
|
|
426
|
+
return true;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
if (blockSelector) {
|
|
431
|
+
return element.matches(blockSelector);
|
|
432
|
+
}
|
|
378
433
|
}
|
|
379
|
-
|
|
380
|
-
return element.matches(blockSelector);
|
|
434
|
+
catch (e) {
|
|
381
435
|
}
|
|
382
436
|
return false;
|
|
383
437
|
}
|
|
384
|
-
function
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
if (node.nodeType !== node.ELEMENT_NODE) {
|
|
389
|
-
return needMaskingText(node.parentNode, maskTextClass, maskTextSelector, unmaskTextSelector, maskAllText);
|
|
390
|
-
}
|
|
391
|
-
if (unmaskTextSelector) {
|
|
392
|
-
if (node.matches(unmaskTextSelector) ||
|
|
393
|
-
node.closest(unmaskTextSelector)) {
|
|
394
|
-
return false;
|
|
395
|
-
}
|
|
396
|
-
}
|
|
397
|
-
if (maskAllText) {
|
|
398
|
-
return true;
|
|
399
|
-
}
|
|
400
|
-
if (typeof maskTextClass === 'string') {
|
|
401
|
-
if (node.classList.contains(maskTextClass)) {
|
|
438
|
+
function elementClassMatchesRegex(el, regex) {
|
|
439
|
+
for (let eIndex = el.classList.length; eIndex--;) {
|
|
440
|
+
const className = el.classList[eIndex];
|
|
441
|
+
if (regex.test(className)) {
|
|
402
442
|
return true;
|
|
403
443
|
}
|
|
404
444
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
445
|
+
return false;
|
|
446
|
+
}
|
|
447
|
+
function distanceToMatch(node, matchPredicate, limit = Infinity, distance = 0) {
|
|
448
|
+
if (!node)
|
|
449
|
+
return -1;
|
|
450
|
+
if (node.nodeType !== node.ELEMENT_NODE)
|
|
451
|
+
return -1;
|
|
452
|
+
if (distance > limit)
|
|
453
|
+
return -1;
|
|
454
|
+
if (matchPredicate(node))
|
|
455
|
+
return distance;
|
|
456
|
+
return distanceToMatch(node.parentNode, matchPredicate, limit, distance + 1);
|
|
457
|
+
}
|
|
458
|
+
function createMatchPredicate(className, selector) {
|
|
459
|
+
return (node) => {
|
|
460
|
+
const el = node;
|
|
461
|
+
if (el === null)
|
|
462
|
+
return false;
|
|
463
|
+
if (className) {
|
|
464
|
+
if (typeof className === 'string') {
|
|
465
|
+
if (el.matches(`.${className}`))
|
|
466
|
+
return true;
|
|
467
|
+
}
|
|
468
|
+
else if (elementClassMatchesRegex(el, className)) {
|
|
409
469
|
return true;
|
|
410
470
|
}
|
|
411
471
|
}
|
|
412
|
-
|
|
413
|
-
if (maskTextSelector) {
|
|
414
|
-
if (node.matches(maskTextSelector)) {
|
|
472
|
+
if (selector && el.matches(selector))
|
|
415
473
|
return true;
|
|
474
|
+
return false;
|
|
475
|
+
};
|
|
476
|
+
}
|
|
477
|
+
function needMaskingText(node, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, maskAllText) {
|
|
478
|
+
try {
|
|
479
|
+
const el = node.nodeType === node.ELEMENT_NODE
|
|
480
|
+
? node
|
|
481
|
+
: node.parentElement;
|
|
482
|
+
if (el === null)
|
|
483
|
+
return false;
|
|
484
|
+
let maskDistance = -1;
|
|
485
|
+
let unmaskDistance = -1;
|
|
486
|
+
if (maskAllText) {
|
|
487
|
+
unmaskDistance = distanceToMatch(el, createMatchPredicate(unmaskTextClass, unmaskTextSelector));
|
|
488
|
+
if (unmaskDistance < 0) {
|
|
489
|
+
return true;
|
|
490
|
+
}
|
|
491
|
+
maskDistance = distanceToMatch(el, createMatchPredicate(maskTextClass, maskTextSelector), unmaskDistance >= 0 ? unmaskDistance : Infinity);
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
maskDistance = distanceToMatch(el, createMatchPredicate(maskTextClass, maskTextSelector));
|
|
495
|
+
if (maskDistance < 0) {
|
|
496
|
+
return false;
|
|
497
|
+
}
|
|
498
|
+
unmaskDistance = distanceToMatch(el, createMatchPredicate(unmaskTextClass, unmaskTextSelector), maskDistance >= 0 ? maskDistance : Infinity);
|
|
416
499
|
}
|
|
500
|
+
return maskDistance >= 0
|
|
501
|
+
? unmaskDistance >= 0
|
|
502
|
+
? maskDistance <= unmaskDistance
|
|
503
|
+
: true
|
|
504
|
+
: unmaskDistance >= 0
|
|
505
|
+
? false
|
|
506
|
+
: !!maskAllText;
|
|
507
|
+
}
|
|
508
|
+
catch (e) {
|
|
417
509
|
}
|
|
418
|
-
return
|
|
510
|
+
return !!maskAllText;
|
|
419
511
|
}
|
|
420
512
|
function onceIframeLoaded(iframeEl, listener, iframeLoadTimeout) {
|
|
421
513
|
const win = iframeEl.contentWindow;
|
|
@@ -449,18 +541,36 @@ function onceIframeLoaded(iframeEl, listener, iframeLoadTimeout) {
|
|
|
449
541
|
iframeEl.src === blankUrl ||
|
|
450
542
|
iframeEl.src === '') {
|
|
451
543
|
setTimeout(listener, 0);
|
|
452
|
-
return;
|
|
544
|
+
return iframeEl.addEventListener('load', listener);
|
|
453
545
|
}
|
|
454
546
|
iframeEl.addEventListener('load', listener);
|
|
455
547
|
}
|
|
456
|
-
function
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
548
|
+
function onceStylesheetLoaded(link, listener, styleSheetLoadTimeout) {
|
|
549
|
+
let fired = false;
|
|
550
|
+
let styleSheetLoaded;
|
|
551
|
+
try {
|
|
552
|
+
styleSheetLoaded = link.sheet;
|
|
553
|
+
}
|
|
554
|
+
catch (error) {
|
|
555
|
+
return;
|
|
463
556
|
}
|
|
557
|
+
if (styleSheetLoaded)
|
|
558
|
+
return;
|
|
559
|
+
const timer = setTimeout(() => {
|
|
560
|
+
if (!fired) {
|
|
561
|
+
listener();
|
|
562
|
+
fired = true;
|
|
563
|
+
}
|
|
564
|
+
}, styleSheetLoadTimeout);
|
|
565
|
+
link.addEventListener('load', () => {
|
|
566
|
+
clearTimeout(timer);
|
|
567
|
+
fired = true;
|
|
568
|
+
listener();
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
function serializeNode(n, options) {
|
|
572
|
+
const { doc, mirror, blockClass, blockSelector, unblockSelector, maskAllText, maskAttributeFn, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, inlineStylesheet, maskInputOptions = {}, maskTextFn, maskInputFn, dataURLOptions = {}, inlineImages, recordCanvas, keepIframeSrcFn, newlyAddedElement = false, } = options;
|
|
573
|
+
const rootId = getRootId(doc, mirror);
|
|
464
574
|
switch (n.nodeType) {
|
|
465
575
|
case n.DOCUMENT_NODE:
|
|
466
576
|
if (n.compatMode !== 'CSS1Compat') {
|
|
@@ -468,14 +578,12 @@ function serializeNode(n, options) {
|
|
|
468
578
|
type: NodeType$1.Document,
|
|
469
579
|
childNodes: [],
|
|
470
580
|
compatMode: n.compatMode,
|
|
471
|
-
rootId,
|
|
472
581
|
};
|
|
473
582
|
}
|
|
474
583
|
else {
|
|
475
584
|
return {
|
|
476
585
|
type: NodeType$1.Document,
|
|
477
586
|
childNodes: [],
|
|
478
|
-
rootId,
|
|
479
587
|
};
|
|
480
588
|
}
|
|
481
589
|
case n.DOCUMENT_TYPE_NODE:
|
|
@@ -487,202 +595,39 @@ function serializeNode(n, options) {
|
|
|
487
595
|
rootId,
|
|
488
596
|
};
|
|
489
597
|
case n.ELEMENT_NODE:
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
cssText = getCssRulesString(stylesheet);
|
|
505
|
-
}
|
|
506
|
-
if (cssText) {
|
|
507
|
-
delete attributes.rel;
|
|
508
|
-
delete attributes.href;
|
|
509
|
-
attributes._cssText = absoluteToStylesheet(cssText, stylesheet.href);
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
if (tagName === 'style' &&
|
|
513
|
-
n.sheet &&
|
|
514
|
-
!(n.innerText ||
|
|
515
|
-
n.textContent ||
|
|
516
|
-
'').trim().length) {
|
|
517
|
-
const cssText = getCssRulesString(n.sheet);
|
|
518
|
-
if (cssText) {
|
|
519
|
-
attributes._cssText = absoluteToStylesheet(cssText, getHref());
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
if (tagName === 'input' ||
|
|
523
|
-
tagName === 'textarea' ||
|
|
524
|
-
tagName === 'select' ||
|
|
525
|
-
tagName === 'option') {
|
|
526
|
-
const el = n;
|
|
527
|
-
const type = getInputType(el);
|
|
528
|
-
const value = getInputValue(el, tagName.toUpperCase(), type);
|
|
529
|
-
const checked = n.checked;
|
|
530
|
-
if (type !== 'submit' &&
|
|
531
|
-
type !== 'button' &&
|
|
532
|
-
value) {
|
|
533
|
-
attributes.value = maskInputValue({
|
|
534
|
-
input: el,
|
|
535
|
-
type,
|
|
536
|
-
tagName,
|
|
537
|
-
value,
|
|
538
|
-
maskInputSelector,
|
|
539
|
-
unmaskInputSelector,
|
|
540
|
-
maskInputOptions,
|
|
541
|
-
maskInputFn,
|
|
542
|
-
});
|
|
543
|
-
}
|
|
544
|
-
if (checked) {
|
|
545
|
-
attributes.checked = checked;
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
if (tagName === 'option') {
|
|
549
|
-
if (n.selected && !maskInputOptions['select']) {
|
|
550
|
-
attributes.selected = true;
|
|
551
|
-
}
|
|
552
|
-
else {
|
|
553
|
-
delete attributes.selected;
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
if (tagName === 'canvas' && recordCanvas) {
|
|
557
|
-
if (n.__context === '2d') {
|
|
558
|
-
if (!is2DCanvasBlank(n)) {
|
|
559
|
-
attributes.rr_dataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
else if (!('__context' in n)) {
|
|
563
|
-
const canvasDataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
564
|
-
const blankCanvas = document.createElement('canvas');
|
|
565
|
-
blankCanvas.width = n.width;
|
|
566
|
-
blankCanvas.height = n.height;
|
|
567
|
-
const blankCanvasDataURL = blankCanvas.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
568
|
-
if (canvasDataURL !== blankCanvasDataURL) {
|
|
569
|
-
attributes.rr_dataURL = canvasDataURL;
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
if (tagName === 'img' && inlineImages) {
|
|
574
|
-
if (!canvasService) {
|
|
575
|
-
canvasService = doc.createElement('canvas');
|
|
576
|
-
canvasCtx = canvasService.getContext('2d');
|
|
577
|
-
}
|
|
578
|
-
const image = n;
|
|
579
|
-
const oldValue = image.crossOrigin;
|
|
580
|
-
image.crossOrigin = 'anonymous';
|
|
581
|
-
const recordInlineImage = () => {
|
|
582
|
-
try {
|
|
583
|
-
canvasService.width = image.naturalWidth;
|
|
584
|
-
canvasService.height = image.naturalHeight;
|
|
585
|
-
canvasCtx.drawImage(image, 0, 0);
|
|
586
|
-
attributes.rr_dataURL = canvasService.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
587
|
-
}
|
|
588
|
-
catch (err) {
|
|
589
|
-
console.warn(`Cannot inline img src=${image.currentSrc}! Error: ${err}`);
|
|
590
|
-
}
|
|
591
|
-
oldValue
|
|
592
|
-
? (attributes.crossOrigin = oldValue)
|
|
593
|
-
: delete attributes.crossOrigin;
|
|
594
|
-
};
|
|
595
|
-
if (image.complete && image.naturalWidth !== 0)
|
|
596
|
-
recordInlineImage();
|
|
597
|
-
else
|
|
598
|
-
image.onload = recordInlineImage;
|
|
599
|
-
}
|
|
600
|
-
if (tagName === 'audio' || tagName === 'video') {
|
|
601
|
-
attributes.rr_mediaState = n.paused
|
|
602
|
-
? 'paused'
|
|
603
|
-
: 'played';
|
|
604
|
-
attributes.rr_mediaCurrentTime = n.currentTime;
|
|
605
|
-
}
|
|
606
|
-
if (n.scrollLeft) {
|
|
607
|
-
attributes.rr_scrollLeft = n.scrollLeft;
|
|
608
|
-
}
|
|
609
|
-
if (n.scrollTop) {
|
|
610
|
-
attributes.rr_scrollTop = n.scrollTop;
|
|
611
|
-
}
|
|
612
|
-
if (needBlock) {
|
|
613
|
-
const { width, height } = n.getBoundingClientRect();
|
|
614
|
-
attributes = {
|
|
615
|
-
class: attributes.class,
|
|
616
|
-
rr_width: `${width}px`,
|
|
617
|
-
rr_height: `${height}px`,
|
|
618
|
-
};
|
|
619
|
-
}
|
|
620
|
-
if (tagName === 'iframe' && !keepIframeSrcFn(attributes.src)) {
|
|
621
|
-
if (!n.contentDocument) {
|
|
622
|
-
attributes.rr_src = attributes.src;
|
|
623
|
-
}
|
|
624
|
-
delete attributes.src;
|
|
625
|
-
}
|
|
626
|
-
return {
|
|
627
|
-
type: NodeType$1.Element,
|
|
628
|
-
tagName,
|
|
629
|
-
attributes,
|
|
630
|
-
childNodes: [],
|
|
631
|
-
isSVG: isSVGElement(n) || undefined,
|
|
632
|
-
needBlock,
|
|
598
|
+
return serializeElementNode(n, {
|
|
599
|
+
doc,
|
|
600
|
+
blockClass,
|
|
601
|
+
blockSelector,
|
|
602
|
+
unblockSelector,
|
|
603
|
+
inlineStylesheet,
|
|
604
|
+
maskAttributeFn,
|
|
605
|
+
maskInputOptions,
|
|
606
|
+
maskInputFn,
|
|
607
|
+
dataURLOptions,
|
|
608
|
+
inlineImages,
|
|
609
|
+
recordCanvas,
|
|
610
|
+
keepIframeSrcFn,
|
|
611
|
+
newlyAddedElement,
|
|
633
612
|
rootId,
|
|
634
|
-
|
|
613
|
+
maskAllText,
|
|
614
|
+
maskTextClass,
|
|
615
|
+
unmaskTextClass,
|
|
616
|
+
maskTextSelector,
|
|
617
|
+
unmaskTextSelector,
|
|
618
|
+
});
|
|
635
619
|
case n.TEXT_NODE:
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
textContent = stringifyStyleSheet(n.parentNode.sheet);
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
catch (err) {
|
|
649
|
-
console.warn(`Cannot get CSS styles from text's parentNode. Error: ${err}`, n);
|
|
650
|
-
}
|
|
651
|
-
textContent = absoluteToStylesheet(textContent, getHref());
|
|
652
|
-
}
|
|
653
|
-
if (isScript) {
|
|
654
|
-
textContent = 'SCRIPT_PLACEHOLDER';
|
|
655
|
-
}
|
|
656
|
-
if (parentTagName === 'TEXTAREA' && textContent) {
|
|
657
|
-
textContent = '';
|
|
658
|
-
}
|
|
659
|
-
else if (parentTagName === 'OPTION' && textContent) {
|
|
660
|
-
const option = n.parentNode;
|
|
661
|
-
textContent = maskInputValue({
|
|
662
|
-
input: option,
|
|
663
|
-
type: null,
|
|
664
|
-
tagName: parentTagName,
|
|
665
|
-
value: textContent,
|
|
666
|
-
maskInputSelector,
|
|
667
|
-
unmaskInputSelector,
|
|
668
|
-
maskInputOptions,
|
|
669
|
-
maskInputFn,
|
|
670
|
-
});
|
|
671
|
-
}
|
|
672
|
-
else if (!isStyle &&
|
|
673
|
-
!isScript &&
|
|
674
|
-
needMaskingText(n, maskTextClass, maskTextSelector, unmaskTextSelector, maskAllText) &&
|
|
675
|
-
textContent) {
|
|
676
|
-
textContent = maskTextFn
|
|
677
|
-
? maskTextFn(textContent)
|
|
678
|
-
: defaultMaskFn(textContent);
|
|
679
|
-
}
|
|
680
|
-
return {
|
|
681
|
-
type: NodeType$1.Text,
|
|
682
|
-
textContent: textContent || '',
|
|
683
|
-
isStyle,
|
|
620
|
+
return serializeTextNode(n, {
|
|
621
|
+
maskAllText,
|
|
622
|
+
maskTextClass,
|
|
623
|
+
unmaskTextClass,
|
|
624
|
+
maskTextSelector,
|
|
625
|
+
unmaskTextSelector,
|
|
626
|
+
maskTextFn,
|
|
627
|
+
maskInputOptions,
|
|
628
|
+
maskInputFn,
|
|
684
629
|
rootId,
|
|
685
|
-
};
|
|
630
|
+
});
|
|
686
631
|
case n.CDATA_SECTION_NODE:
|
|
687
632
|
return {
|
|
688
633
|
type: NodeType$1.CDATA,
|
|
@@ -699,30 +644,249 @@ function serializeNode(n, options) {
|
|
|
699
644
|
return false;
|
|
700
645
|
}
|
|
701
646
|
}
|
|
702
|
-
function
|
|
703
|
-
if (
|
|
704
|
-
return
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
647
|
+
function getRootId(doc, mirror) {
|
|
648
|
+
if (!mirror.hasNode(doc))
|
|
649
|
+
return undefined;
|
|
650
|
+
const docId = mirror.getId(doc);
|
|
651
|
+
return docId === 1 ? undefined : docId;
|
|
652
|
+
}
|
|
653
|
+
function serializeTextNode(n, options) {
|
|
654
|
+
var _a;
|
|
655
|
+
const { maskAllText, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, maskTextFn, maskInputOptions, maskInputFn, rootId, } = options;
|
|
656
|
+
const parentTagName = n.parentNode && n.parentNode.tagName;
|
|
657
|
+
let textContent = n.textContent;
|
|
658
|
+
const isStyle = parentTagName === 'STYLE' ? true : undefined;
|
|
659
|
+
const isScript = parentTagName === 'SCRIPT' ? true : undefined;
|
|
660
|
+
const isTextarea = parentTagName === 'TEXTAREA' ? true : undefined;
|
|
661
|
+
if (isStyle && textContent) {
|
|
662
|
+
try {
|
|
663
|
+
if (n.nextSibling || n.previousSibling) {
|
|
664
|
+
}
|
|
665
|
+
else if ((_a = n.parentNode.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) {
|
|
666
|
+
textContent = stringifyStyleSheet(n.parentNode.sheet);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
catch (err) {
|
|
670
|
+
console.warn(`Cannot get CSS styles from text's parentNode. Error: ${err}`, n);
|
|
671
|
+
}
|
|
672
|
+
textContent = absoluteToStylesheet(textContent, getHref());
|
|
673
|
+
}
|
|
674
|
+
if (isScript) {
|
|
675
|
+
textContent = 'SCRIPT_PLACEHOLDER';
|
|
676
|
+
}
|
|
677
|
+
const forceMask = needMaskingText(n, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, maskAllText);
|
|
678
|
+
if (!isStyle && !isScript && !isTextarea && textContent && forceMask) {
|
|
679
|
+
textContent = maskTextFn
|
|
680
|
+
? maskTextFn(textContent)
|
|
681
|
+
: textContent.replace(/[\S]/g, '*');
|
|
682
|
+
}
|
|
683
|
+
if (isTextarea && textContent && (maskInputOptions.textarea || forceMask)) {
|
|
684
|
+
textContent = maskInputFn
|
|
685
|
+
? maskInputFn(textContent, n.parentNode)
|
|
686
|
+
: textContent.replace(/[\S]/g, '*');
|
|
687
|
+
}
|
|
688
|
+
if (parentTagName === 'OPTION' && textContent) {
|
|
689
|
+
const isInputMasked = shouldMaskInput({
|
|
690
|
+
type: null,
|
|
691
|
+
tagName: parentTagName,
|
|
692
|
+
maskInputOptions,
|
|
693
|
+
});
|
|
694
|
+
textContent = maskInputValue({
|
|
695
|
+
isMasked: needMaskingText(n, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, isInputMasked),
|
|
696
|
+
element: n,
|
|
697
|
+
value: textContent,
|
|
698
|
+
maskInputFn,
|
|
699
|
+
});
|
|
708
700
|
}
|
|
701
|
+
return {
|
|
702
|
+
type: NodeType$1.Text,
|
|
703
|
+
textContent: textContent || '',
|
|
704
|
+
isStyle,
|
|
705
|
+
rootId,
|
|
706
|
+
};
|
|
709
707
|
}
|
|
710
|
-
function
|
|
711
|
-
|
|
712
|
-
|
|
708
|
+
function serializeElementNode(n, options) {
|
|
709
|
+
const { doc, blockClass, blockSelector, unblockSelector, inlineStylesheet, maskInputOptions = {}, maskAttributeFn, maskInputFn, dataURLOptions = {}, inlineImages, recordCanvas, keepIframeSrcFn, newlyAddedElement = false, rootId, maskAllText, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, } = options;
|
|
710
|
+
const needBlock = _isBlockedElement(n, blockClass, blockSelector, unblockSelector);
|
|
711
|
+
const tagName = getValidTagName(n);
|
|
712
|
+
let attributes = {};
|
|
713
|
+
const len = n.attributes.length;
|
|
714
|
+
for (let i = 0; i < len; i++) {
|
|
715
|
+
const attr = n.attributes[i];
|
|
716
|
+
if (!ignoreAttribute(tagName, attr.name, attr.value)) {
|
|
717
|
+
attributes[attr.name] = transformAttribute(doc, tagName, toLowerCase(attr.name), attr.value, n, maskAttributeFn);
|
|
718
|
+
}
|
|
713
719
|
}
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
720
|
+
if (tagName === 'link' && inlineStylesheet) {
|
|
721
|
+
const stylesheet = Array.from(doc.styleSheets).find((s) => {
|
|
722
|
+
return s.href === n.href;
|
|
723
|
+
});
|
|
724
|
+
let cssText = null;
|
|
725
|
+
if (stylesheet) {
|
|
726
|
+
cssText = getCssRulesString(stylesheet);
|
|
727
|
+
}
|
|
728
|
+
if (cssText) {
|
|
729
|
+
delete attributes.rel;
|
|
730
|
+
delete attributes.href;
|
|
731
|
+
attributes._cssText = absoluteToStylesheet(cssText, stylesheet.href);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
if (tagName === 'style' &&
|
|
735
|
+
n.sheet &&
|
|
736
|
+
!(n.innerText || n.textContent || '').trim().length) {
|
|
737
|
+
const cssText = getCssRulesString(n.sheet);
|
|
738
|
+
if (cssText) {
|
|
739
|
+
attributes._cssText = absoluteToStylesheet(cssText, getHref());
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
if (tagName === 'input' ||
|
|
743
|
+
tagName === 'textarea' ||
|
|
744
|
+
tagName === 'select' ||
|
|
745
|
+
tagName === 'option') {
|
|
746
|
+
const el = n;
|
|
747
|
+
const type = getInputType(el);
|
|
748
|
+
const value = getInputValue(el, toUpperCase(tagName), type);
|
|
749
|
+
const checked = el.checked;
|
|
750
|
+
if (type !== 'submit' && type !== 'button' && value) {
|
|
751
|
+
const forceMask = needMaskingText(el, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, shouldMaskInput({
|
|
752
|
+
type,
|
|
753
|
+
tagName: toUpperCase(tagName),
|
|
754
|
+
maskInputOptions,
|
|
755
|
+
}));
|
|
756
|
+
attributes.value = maskInputValue({
|
|
757
|
+
isMasked: forceMask,
|
|
758
|
+
element: el,
|
|
759
|
+
value,
|
|
760
|
+
maskInputFn,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (checked) {
|
|
764
|
+
attributes.checked = checked;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (tagName === 'option') {
|
|
768
|
+
if (n.selected && !maskInputOptions['select']) {
|
|
769
|
+
attributes.selected = true;
|
|
770
|
+
}
|
|
771
|
+
else {
|
|
772
|
+
delete attributes.selected;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
if (tagName === 'canvas' && recordCanvas) {
|
|
776
|
+
if (n.__context === '2d') {
|
|
777
|
+
if (!is2DCanvasBlank(n)) {
|
|
778
|
+
attributes.rr_dataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
else if (!('__context' in n)) {
|
|
782
|
+
const canvasDataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
783
|
+
const blankCanvas = document.createElement('canvas');
|
|
784
|
+
blankCanvas.width = n.width;
|
|
785
|
+
blankCanvas.height = n.height;
|
|
786
|
+
const blankCanvasDataURL = blankCanvas.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
787
|
+
if (canvasDataURL !== blankCanvasDataURL) {
|
|
788
|
+
attributes.rr_dataURL = canvasDataURL;
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
}
|
|
792
|
+
if (tagName === 'img' && inlineImages) {
|
|
793
|
+
if (!canvasService) {
|
|
794
|
+
canvasService = doc.createElement('canvas');
|
|
795
|
+
canvasCtx = canvasService.getContext('2d');
|
|
796
|
+
}
|
|
797
|
+
const image = n;
|
|
798
|
+
const oldValue = image.crossOrigin;
|
|
799
|
+
image.crossOrigin = 'anonymous';
|
|
800
|
+
const recordInlineImage = () => {
|
|
801
|
+
image.removeEventListener('load', recordInlineImage);
|
|
802
|
+
try {
|
|
803
|
+
canvasService.width = image.naturalWidth;
|
|
804
|
+
canvasService.height = image.naturalHeight;
|
|
805
|
+
canvasCtx.drawImage(image, 0, 0);
|
|
806
|
+
attributes.rr_dataURL = canvasService.toDataURL(dataURLOptions.type, dataURLOptions.quality);
|
|
807
|
+
}
|
|
808
|
+
catch (err) {
|
|
809
|
+
console.warn(`Cannot inline img src=${image.currentSrc}! Error: ${err}`);
|
|
810
|
+
}
|
|
811
|
+
oldValue
|
|
812
|
+
? (attributes.crossOrigin = oldValue)
|
|
813
|
+
: image.removeAttribute('crossorigin');
|
|
814
|
+
};
|
|
815
|
+
if (image.complete && image.naturalWidth !== 0)
|
|
816
|
+
recordInlineImage();
|
|
817
|
+
else
|
|
818
|
+
image.addEventListener('load', recordInlineImage);
|
|
819
|
+
}
|
|
820
|
+
if (tagName === 'audio' || tagName === 'video') {
|
|
821
|
+
attributes.rr_mediaState = n.paused
|
|
822
|
+
? 'paused'
|
|
823
|
+
: 'played';
|
|
824
|
+
attributes.rr_mediaCurrentTime = n.currentTime;
|
|
825
|
+
}
|
|
826
|
+
if (!newlyAddedElement) {
|
|
827
|
+
if (n.scrollLeft) {
|
|
828
|
+
attributes.rr_scrollLeft = n.scrollLeft;
|
|
829
|
+
}
|
|
830
|
+
if (n.scrollTop) {
|
|
831
|
+
attributes.rr_scrollTop = n.scrollTop;
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
if (needBlock) {
|
|
835
|
+
const { width, height } = n.getBoundingClientRect();
|
|
836
|
+
attributes = {
|
|
837
|
+
class: attributes.class,
|
|
838
|
+
rr_width: `${width}px`,
|
|
839
|
+
rr_height: `${height}px`,
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
if (tagName === 'iframe' && !keepIframeSrcFn(attributes.src)) {
|
|
843
|
+
if (!n.contentDocument) {
|
|
844
|
+
attributes.rr_src = attributes.src;
|
|
845
|
+
}
|
|
846
|
+
delete attributes.src;
|
|
847
|
+
}
|
|
848
|
+
let isCustomElement;
|
|
849
|
+
try {
|
|
850
|
+
if (customElements.get(tagName))
|
|
851
|
+
isCustomElement = true;
|
|
852
|
+
}
|
|
853
|
+
catch (e) {
|
|
854
|
+
}
|
|
855
|
+
return {
|
|
856
|
+
type: NodeType$1.Element,
|
|
857
|
+
tagName,
|
|
858
|
+
attributes,
|
|
859
|
+
childNodes: [],
|
|
860
|
+
isSVG: isSVGElement(n) || undefined,
|
|
861
|
+
needBlock,
|
|
862
|
+
rootId,
|
|
863
|
+
isCustom: isCustomElement,
|
|
864
|
+
};
|
|
865
|
+
}
|
|
866
|
+
function lowerIfExists(maybeAttr) {
|
|
867
|
+
if (maybeAttr === undefined || maybeAttr === null) {
|
|
868
|
+
return '';
|
|
869
|
+
}
|
|
870
|
+
else {
|
|
871
|
+
return maybeAttr.toLowerCase();
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
function slimDOMExcluded(sn, slimDOMOptions) {
|
|
875
|
+
if (slimDOMOptions.comment && sn.type === NodeType$1.Comment) {
|
|
876
|
+
return true;
|
|
877
|
+
}
|
|
878
|
+
else if (sn.type === NodeType$1.Element) {
|
|
879
|
+
if (slimDOMOptions.script &&
|
|
880
|
+
(sn.tagName === 'script' ||
|
|
881
|
+
(sn.tagName === 'link' &&
|
|
882
|
+
(sn.attributes.rel === 'preload' ||
|
|
883
|
+
sn.attributes.rel === 'modulepreload') &&
|
|
884
|
+
sn.attributes.as === 'script') ||
|
|
885
|
+
(sn.tagName === 'link' &&
|
|
886
|
+
sn.attributes.rel === 'prefetch' &&
|
|
887
|
+
typeof sn.attributes.href === 'string' &&
|
|
888
|
+
sn.attributes.href.endsWith('.js')))) {
|
|
889
|
+
return true;
|
|
726
890
|
}
|
|
727
891
|
else if (slimDOMOptions.headFavicon &&
|
|
728
892
|
((sn.tagName === 'link' && sn.attributes.rel === 'shortcut icon') ||
|
|
@@ -780,35 +944,37 @@ function slimDOMExcluded(sn, slimDOMOptions) {
|
|
|
780
944
|
return false;
|
|
781
945
|
}
|
|
782
946
|
function serializeNodeWithId(n, options) {
|
|
783
|
-
const { doc,
|
|
947
|
+
const { doc, mirror, blockClass, blockSelector, unblockSelector, maskAllText, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, skipChild = false, inlineStylesheet = true, maskInputOptions = {}, maskAttributeFn, maskTextFn, maskInputFn, slimDOMOptions, dataURLOptions = {}, inlineImages = false, recordCanvas = false, onSerialize, onIframeLoad, iframeLoadTimeout = 5000, onStylesheetLoad, stylesheetLoadTimeout = 5000, keepIframeSrcFn = () => false, newlyAddedElement = false, } = options;
|
|
784
948
|
let { preserveWhiteSpace = true } = options;
|
|
785
949
|
const _serializedNode = serializeNode(n, {
|
|
786
950
|
doc,
|
|
951
|
+
mirror,
|
|
787
952
|
blockClass,
|
|
788
953
|
blockSelector,
|
|
954
|
+
maskAllText,
|
|
789
955
|
unblockSelector,
|
|
790
956
|
maskTextClass,
|
|
957
|
+
unmaskTextClass,
|
|
791
958
|
maskTextSelector,
|
|
792
959
|
unmaskTextSelector,
|
|
793
960
|
inlineStylesheet,
|
|
794
|
-
maskInputSelector,
|
|
795
|
-
unmaskInputSelector,
|
|
796
|
-
maskAllText,
|
|
797
961
|
maskInputOptions,
|
|
962
|
+
maskAttributeFn,
|
|
798
963
|
maskTextFn,
|
|
799
964
|
maskInputFn,
|
|
800
965
|
dataURLOptions,
|
|
801
966
|
inlineImages,
|
|
802
967
|
recordCanvas,
|
|
803
968
|
keepIframeSrcFn,
|
|
969
|
+
newlyAddedElement,
|
|
804
970
|
});
|
|
805
971
|
if (!_serializedNode) {
|
|
806
972
|
console.warn(n, 'not serialized');
|
|
807
973
|
return null;
|
|
808
974
|
}
|
|
809
975
|
let id;
|
|
810
|
-
if (
|
|
811
|
-
id = n
|
|
976
|
+
if (mirror.hasNode(n)) {
|
|
977
|
+
id = mirror.getId(n);
|
|
812
978
|
}
|
|
813
979
|
else if (slimDOMExcluded(_serializedNode, slimDOMOptions) ||
|
|
814
980
|
(!preserveWhiteSpace &&
|
|
@@ -821,11 +987,10 @@ function serializeNodeWithId(n, options) {
|
|
|
821
987
|
id = genId();
|
|
822
988
|
}
|
|
823
989
|
const serializedNode = Object.assign(_serializedNode, { id });
|
|
824
|
-
n
|
|
990
|
+
mirror.add(n, serializedNode);
|
|
825
991
|
if (id === IGNORED_NODE) {
|
|
826
992
|
return null;
|
|
827
993
|
}
|
|
828
|
-
map[id] = n;
|
|
829
994
|
if (onSerialize) {
|
|
830
995
|
onSerialize(n);
|
|
831
996
|
}
|
|
@@ -833,32 +998,33 @@ function serializeNodeWithId(n, options) {
|
|
|
833
998
|
if (serializedNode.type === NodeType$1.Element) {
|
|
834
999
|
recordChild = recordChild && !serializedNode.needBlock;
|
|
835
1000
|
delete serializedNode.needBlock;
|
|
836
|
-
|
|
1001
|
+
const shadowRoot = n.shadowRoot;
|
|
1002
|
+
if (shadowRoot && isNativeShadowDom(shadowRoot))
|
|
837
1003
|
serializedNode.isShadowHost = true;
|
|
838
1004
|
}
|
|
839
1005
|
if ((serializedNode.type === NodeType$1.Document ||
|
|
840
1006
|
serializedNode.type === NodeType$1.Element) &&
|
|
841
1007
|
recordChild) {
|
|
842
1008
|
if (slimDOMOptions.headWhitespace &&
|
|
843
|
-
|
|
844
|
-
|
|
1009
|
+
serializedNode.type === NodeType$1.Element &&
|
|
1010
|
+
serializedNode.tagName === 'head') {
|
|
845
1011
|
preserveWhiteSpace = false;
|
|
846
1012
|
}
|
|
847
1013
|
const bypassOptions = {
|
|
848
1014
|
doc,
|
|
849
|
-
|
|
1015
|
+
mirror,
|
|
850
1016
|
blockClass,
|
|
851
1017
|
blockSelector,
|
|
1018
|
+
maskAllText,
|
|
852
1019
|
unblockSelector,
|
|
853
1020
|
maskTextClass,
|
|
1021
|
+
unmaskTextClass,
|
|
854
1022
|
maskTextSelector,
|
|
855
1023
|
unmaskTextSelector,
|
|
856
1024
|
skipChild,
|
|
857
1025
|
inlineStylesheet,
|
|
858
|
-
maskInputSelector,
|
|
859
|
-
unmaskInputSelector,
|
|
860
|
-
maskAllText,
|
|
861
1026
|
maskInputOptions,
|
|
1027
|
+
maskAttributeFn,
|
|
862
1028
|
maskTextFn,
|
|
863
1029
|
maskInputFn,
|
|
864
1030
|
slimDOMOptions,
|
|
@@ -869,6 +1035,8 @@ function serializeNodeWithId(n, options) {
|
|
|
869
1035
|
onSerialize,
|
|
870
1036
|
onIframeLoad,
|
|
871
1037
|
iframeLoadTimeout,
|
|
1038
|
+
onStylesheetLoad,
|
|
1039
|
+
stylesheetLoadTimeout,
|
|
872
1040
|
keepIframeSrcFn,
|
|
873
1041
|
};
|
|
874
1042
|
for (const childN of Array.from(n.childNodes)) {
|
|
@@ -877,17 +1045,20 @@ function serializeNodeWithId(n, options) {
|
|
|
877
1045
|
serializedNode.childNodes.push(serializedChildNode);
|
|
878
1046
|
}
|
|
879
1047
|
}
|
|
880
|
-
if (isElement(n) && n.shadowRoot) {
|
|
1048
|
+
if (isElement$1(n) && n.shadowRoot) {
|
|
881
1049
|
for (const childN of Array.from(n.shadowRoot.childNodes)) {
|
|
882
1050
|
const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
|
|
883
1051
|
if (serializedChildNode) {
|
|
884
|
-
|
|
1052
|
+
isNativeShadowDom(n.shadowRoot) &&
|
|
1053
|
+
(serializedChildNode.isShadow = true);
|
|
885
1054
|
serializedNode.childNodes.push(serializedChildNode);
|
|
886
1055
|
}
|
|
887
1056
|
}
|
|
888
1057
|
}
|
|
889
1058
|
}
|
|
890
|
-
if (n.parentNode &&
|
|
1059
|
+
if (n.parentNode &&
|
|
1060
|
+
isShadowRoot(n.parentNode) &&
|
|
1061
|
+
isNativeShadowDom(n.parentNode)) {
|
|
891
1062
|
serializedNode.isShadow = true;
|
|
892
1063
|
}
|
|
893
1064
|
if (serializedNode.type === NodeType$1.Element &&
|
|
@@ -897,19 +1068,19 @@ function serializeNodeWithId(n, options) {
|
|
|
897
1068
|
if (iframeDoc && onIframeLoad) {
|
|
898
1069
|
const serializedIframeNode = serializeNodeWithId(iframeDoc, {
|
|
899
1070
|
doc: iframeDoc,
|
|
900
|
-
|
|
1071
|
+
mirror,
|
|
901
1072
|
blockClass,
|
|
902
1073
|
blockSelector,
|
|
903
1074
|
unblockSelector,
|
|
1075
|
+
maskAllText,
|
|
904
1076
|
maskTextClass,
|
|
1077
|
+
unmaskTextClass,
|
|
905
1078
|
maskTextSelector,
|
|
906
1079
|
unmaskTextSelector,
|
|
907
1080
|
skipChild: false,
|
|
908
1081
|
inlineStylesheet,
|
|
909
|
-
maskInputSelector,
|
|
910
|
-
unmaskInputSelector,
|
|
911
|
-
maskAllText,
|
|
912
1082
|
maskInputOptions,
|
|
1083
|
+
maskAttributeFn,
|
|
913
1084
|
maskTextFn,
|
|
914
1085
|
maskInputFn,
|
|
915
1086
|
slimDOMOptions,
|
|
@@ -920,6 +1091,8 @@ function serializeNodeWithId(n, options) {
|
|
|
920
1091
|
onSerialize,
|
|
921
1092
|
onIframeLoad,
|
|
922
1093
|
iframeLoadTimeout,
|
|
1094
|
+
onStylesheetLoad,
|
|
1095
|
+
stylesheetLoadTimeout,
|
|
923
1096
|
keepIframeSrcFn,
|
|
924
1097
|
});
|
|
925
1098
|
if (serializedIframeNode) {
|
|
@@ -928,11 +1101,50 @@ function serializeNodeWithId(n, options) {
|
|
|
928
1101
|
}
|
|
929
1102
|
}, iframeLoadTimeout);
|
|
930
1103
|
}
|
|
1104
|
+
if (serializedNode.type === NodeType$1.Element &&
|
|
1105
|
+
serializedNode.tagName === 'link' &&
|
|
1106
|
+
serializedNode.attributes.rel === 'stylesheet') {
|
|
1107
|
+
onceStylesheetLoaded(n, () => {
|
|
1108
|
+
if (onStylesheetLoad) {
|
|
1109
|
+
const serializedLinkNode = serializeNodeWithId(n, {
|
|
1110
|
+
doc,
|
|
1111
|
+
mirror,
|
|
1112
|
+
blockClass,
|
|
1113
|
+
blockSelector,
|
|
1114
|
+
unblockSelector,
|
|
1115
|
+
maskAllText,
|
|
1116
|
+
maskTextClass,
|
|
1117
|
+
unmaskTextClass,
|
|
1118
|
+
maskTextSelector,
|
|
1119
|
+
unmaskTextSelector,
|
|
1120
|
+
skipChild: false,
|
|
1121
|
+
inlineStylesheet,
|
|
1122
|
+
maskInputOptions,
|
|
1123
|
+
maskAttributeFn,
|
|
1124
|
+
maskTextFn,
|
|
1125
|
+
maskInputFn,
|
|
1126
|
+
slimDOMOptions,
|
|
1127
|
+
dataURLOptions,
|
|
1128
|
+
inlineImages,
|
|
1129
|
+
recordCanvas,
|
|
1130
|
+
preserveWhiteSpace,
|
|
1131
|
+
onSerialize,
|
|
1132
|
+
onIframeLoad,
|
|
1133
|
+
iframeLoadTimeout,
|
|
1134
|
+
onStylesheetLoad,
|
|
1135
|
+
stylesheetLoadTimeout,
|
|
1136
|
+
keepIframeSrcFn,
|
|
1137
|
+
});
|
|
1138
|
+
if (serializedLinkNode) {
|
|
1139
|
+
onStylesheetLoad(n, serializedLinkNode);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
}, stylesheetLoadTimeout);
|
|
1143
|
+
}
|
|
931
1144
|
return serializedNode;
|
|
932
1145
|
}
|
|
933
1146
|
function snapshot(n, options) {
|
|
934
|
-
const { blockClass = 'rr-block', blockSelector = null, unblockSelector = null, maskTextClass = 'rr-mask', maskTextSelector = null, unmaskTextSelector = null, inlineStylesheet = true, inlineImages = false, recordCanvas = false,
|
|
935
|
-
const idNodeMap = {};
|
|
1147
|
+
const { mirror = new Mirror(), blockClass = 'rr-block', blockSelector = null, unblockSelector = null, maskAllText = false, maskTextClass = 'rr-mask', unmaskTextClass = null, maskTextSelector = null, unmaskTextSelector = null, inlineStylesheet = true, inlineImages = false, recordCanvas = false, maskAllInputs = false, maskAttributeFn, maskTextFn, maskInputFn, slimDOM = false, dataURLOptions, preserveWhiteSpace, onSerialize, onIframeLoad, iframeLoadTimeout, onStylesheetLoad, stylesheetLoadTimeout, keepIframeSrcFn = () => false, } = options || {};
|
|
936
1148
|
const maskInputOptions = maskAllInputs === true
|
|
937
1149
|
? {
|
|
938
1150
|
color: true,
|
|
@@ -971,147 +1183,43 @@ function snapshot(n, options) {
|
|
|
971
1183
|
: slimDOM === false
|
|
972
1184
|
? {}
|
|
973
1185
|
: slimDOM;
|
|
974
|
-
return
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1186
|
+
return serializeNodeWithId(n, {
|
|
1187
|
+
doc: n,
|
|
1188
|
+
mirror,
|
|
1189
|
+
blockClass,
|
|
1190
|
+
blockSelector,
|
|
1191
|
+
unblockSelector,
|
|
1192
|
+
maskAllText,
|
|
1193
|
+
maskTextClass,
|
|
1194
|
+
unmaskTextClass,
|
|
1195
|
+
maskTextSelector,
|
|
1196
|
+
unmaskTextSelector,
|
|
1197
|
+
skipChild: false,
|
|
1198
|
+
inlineStylesheet,
|
|
1199
|
+
maskInputOptions,
|
|
1200
|
+
maskAttributeFn,
|
|
1201
|
+
maskTextFn,
|
|
1202
|
+
maskInputFn,
|
|
1203
|
+
slimDOMOptions,
|
|
1204
|
+
dataURLOptions,
|
|
1205
|
+
inlineImages,
|
|
1206
|
+
recordCanvas,
|
|
1207
|
+
preserveWhiteSpace,
|
|
1208
|
+
onSerialize,
|
|
1209
|
+
onIframeLoad,
|
|
1210
|
+
iframeLoadTimeout,
|
|
1211
|
+
onStylesheetLoad,
|
|
1212
|
+
stylesheetLoadTimeout,
|
|
1213
|
+
keepIframeSrcFn,
|
|
1214
|
+
newlyAddedElement: false,
|
|
1215
|
+
});
|
|
1004
1216
|
}
|
|
1005
|
-
function skipAttribute(tagName, attributeName, value) {
|
|
1006
|
-
return ((tagName === 'video' || tagName === 'audio') && attributeName === 'autoplay');
|
|
1007
|
-
}
|
|
1008
|
-
|
|
1009
|
-
var EventType;
|
|
1010
|
-
(function (EventType) {
|
|
1011
|
-
EventType[EventType["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
1012
|
-
EventType[EventType["Load"] = 1] = "Load";
|
|
1013
|
-
EventType[EventType["FullSnapshot"] = 2] = "FullSnapshot";
|
|
1014
|
-
EventType[EventType["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
|
|
1015
|
-
EventType[EventType["Meta"] = 4] = "Meta";
|
|
1016
|
-
EventType[EventType["Custom"] = 5] = "Custom";
|
|
1017
|
-
EventType[EventType["Plugin"] = 6] = "Plugin";
|
|
1018
|
-
})(EventType || (EventType = {}));
|
|
1019
|
-
var IncrementalSource;
|
|
1020
|
-
(function (IncrementalSource) {
|
|
1021
|
-
IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
|
|
1022
|
-
IncrementalSource[IncrementalSource["MouseMove"] = 1] = "MouseMove";
|
|
1023
|
-
IncrementalSource[IncrementalSource["MouseInteraction"] = 2] = "MouseInteraction";
|
|
1024
|
-
IncrementalSource[IncrementalSource["Scroll"] = 3] = "Scroll";
|
|
1025
|
-
IncrementalSource[IncrementalSource["ViewportResize"] = 4] = "ViewportResize";
|
|
1026
|
-
IncrementalSource[IncrementalSource["Input"] = 5] = "Input";
|
|
1027
|
-
IncrementalSource[IncrementalSource["TouchMove"] = 6] = "TouchMove";
|
|
1028
|
-
IncrementalSource[IncrementalSource["MediaInteraction"] = 7] = "MediaInteraction";
|
|
1029
|
-
IncrementalSource[IncrementalSource["StyleSheetRule"] = 8] = "StyleSheetRule";
|
|
1030
|
-
IncrementalSource[IncrementalSource["CanvasMutation"] = 9] = "CanvasMutation";
|
|
1031
|
-
IncrementalSource[IncrementalSource["Font"] = 10] = "Font";
|
|
1032
|
-
IncrementalSource[IncrementalSource["Log"] = 11] = "Log";
|
|
1033
|
-
IncrementalSource[IncrementalSource["Drag"] = 12] = "Drag";
|
|
1034
|
-
IncrementalSource[IncrementalSource["StyleDeclaration"] = 13] = "StyleDeclaration";
|
|
1035
|
-
})(IncrementalSource || (IncrementalSource = {}));
|
|
1036
|
-
var MouseInteractions;
|
|
1037
|
-
(function (MouseInteractions) {
|
|
1038
|
-
MouseInteractions[MouseInteractions["MouseUp"] = 0] = "MouseUp";
|
|
1039
|
-
MouseInteractions[MouseInteractions["MouseDown"] = 1] = "MouseDown";
|
|
1040
|
-
MouseInteractions[MouseInteractions["Click"] = 2] = "Click";
|
|
1041
|
-
MouseInteractions[MouseInteractions["ContextMenu"] = 3] = "ContextMenu";
|
|
1042
|
-
MouseInteractions[MouseInteractions["DblClick"] = 4] = "DblClick";
|
|
1043
|
-
MouseInteractions[MouseInteractions["Focus"] = 5] = "Focus";
|
|
1044
|
-
MouseInteractions[MouseInteractions["Blur"] = 6] = "Blur";
|
|
1045
|
-
MouseInteractions[MouseInteractions["TouchStart"] = 7] = "TouchStart";
|
|
1046
|
-
MouseInteractions[MouseInteractions["TouchMove_Departed"] = 8] = "TouchMove_Departed";
|
|
1047
|
-
MouseInteractions[MouseInteractions["TouchEnd"] = 9] = "TouchEnd";
|
|
1048
|
-
MouseInteractions[MouseInteractions["TouchCancel"] = 10] = "TouchCancel";
|
|
1049
|
-
})(MouseInteractions || (MouseInteractions = {}));
|
|
1050
|
-
var CanvasContext;
|
|
1051
|
-
(function (CanvasContext) {
|
|
1052
|
-
CanvasContext[CanvasContext["2D"] = 0] = "2D";
|
|
1053
|
-
CanvasContext[CanvasContext["WebGL"] = 1] = "WebGL";
|
|
1054
|
-
CanvasContext[CanvasContext["WebGL2"] = 2] = "WebGL2";
|
|
1055
|
-
})(CanvasContext || (CanvasContext = {}));
|
|
1056
|
-
var MediaInteractions;
|
|
1057
|
-
(function (MediaInteractions) {
|
|
1058
|
-
MediaInteractions[MediaInteractions["Play"] = 0] = "Play";
|
|
1059
|
-
MediaInteractions[MediaInteractions["Pause"] = 1] = "Pause";
|
|
1060
|
-
MediaInteractions[MediaInteractions["Seeked"] = 2] = "Seeked";
|
|
1061
|
-
MediaInteractions[MediaInteractions["VolumeChange"] = 3] = "VolumeChange";
|
|
1062
|
-
})(MediaInteractions || (MediaInteractions = {}));
|
|
1063
|
-
var ReplayerEvents;
|
|
1064
|
-
(function (ReplayerEvents) {
|
|
1065
|
-
ReplayerEvents["Start"] = "start";
|
|
1066
|
-
ReplayerEvents["Pause"] = "pause";
|
|
1067
|
-
ReplayerEvents["Resume"] = "resume";
|
|
1068
|
-
ReplayerEvents["Resize"] = "resize";
|
|
1069
|
-
ReplayerEvents["Finish"] = "finish";
|
|
1070
|
-
ReplayerEvents["FullsnapshotRebuilded"] = "fullsnapshot-rebuilded";
|
|
1071
|
-
ReplayerEvents["LoadStylesheetStart"] = "load-stylesheet-start";
|
|
1072
|
-
ReplayerEvents["LoadStylesheetEnd"] = "load-stylesheet-end";
|
|
1073
|
-
ReplayerEvents["SkipStart"] = "skip-start";
|
|
1074
|
-
ReplayerEvents["SkipEnd"] = "skip-end";
|
|
1075
|
-
ReplayerEvents["MouseInteraction"] = "mouse-interaction";
|
|
1076
|
-
ReplayerEvents["EventCast"] = "event-cast";
|
|
1077
|
-
ReplayerEvents["CustomEvent"] = "custom-event";
|
|
1078
|
-
ReplayerEvents["Flush"] = "flush";
|
|
1079
|
-
ReplayerEvents["StateChange"] = "state-change";
|
|
1080
|
-
ReplayerEvents["PlayBack"] = "play-back";
|
|
1081
|
-
})(ReplayerEvents || (ReplayerEvents = {}));
|
|
1082
1217
|
|
|
1083
1218
|
function on(type, fn, target = document) {
|
|
1084
1219
|
const options = { capture: true, passive: true };
|
|
1085
1220
|
target.addEventListener(type, fn, options);
|
|
1086
1221
|
return () => target.removeEventListener(type, fn, options);
|
|
1087
1222
|
}
|
|
1088
|
-
function createMirror() {
|
|
1089
|
-
return {
|
|
1090
|
-
map: {},
|
|
1091
|
-
getId(n) {
|
|
1092
|
-
if (!n || !n.__sn) {
|
|
1093
|
-
return -1;
|
|
1094
|
-
}
|
|
1095
|
-
return n.__sn.id;
|
|
1096
|
-
},
|
|
1097
|
-
getNode(id) {
|
|
1098
|
-
return this.map[id] || null;
|
|
1099
|
-
},
|
|
1100
|
-
removeNodeFromMap(n) {
|
|
1101
|
-
const id = n.__sn && n.__sn.id;
|
|
1102
|
-
delete this.map[id];
|
|
1103
|
-
if (n.childNodes) {
|
|
1104
|
-
n.childNodes.forEach((child) => this.removeNodeFromMap(child));
|
|
1105
|
-
}
|
|
1106
|
-
},
|
|
1107
|
-
has(id) {
|
|
1108
|
-
return this.map.hasOwnProperty(id);
|
|
1109
|
-
},
|
|
1110
|
-
reset() {
|
|
1111
|
-
this.map = {};
|
|
1112
|
-
},
|
|
1113
|
-
};
|
|
1114
|
-
}
|
|
1115
1223
|
const DEPARTED_MIRROR_ACCESS_WARNING = 'Please stop import mirror directly. Instead of that,' +
|
|
1116
1224
|
'\r\n' +
|
|
1117
1225
|
'now you can use replayer.getMirror() to access the mirror instance of a replayer,' +
|
|
@@ -1151,14 +1259,13 @@ if (typeof window !== 'undefined' && window.Proxy && window.Reflect) {
|
|
|
1151
1259
|
function throttle$1(func, wait, options = {}) {
|
|
1152
1260
|
let timeout = null;
|
|
1153
1261
|
let previous = 0;
|
|
1154
|
-
return function (
|
|
1155
|
-
|
|
1262
|
+
return function (...args) {
|
|
1263
|
+
const now = Date.now();
|
|
1156
1264
|
if (!previous && options.leading === false) {
|
|
1157
1265
|
previous = now;
|
|
1158
1266
|
}
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
let args = arguments;
|
|
1267
|
+
const remaining = wait - (now - previous);
|
|
1268
|
+
const context = this;
|
|
1162
1269
|
if (remaining <= 0 || remaining > wait) {
|
|
1163
1270
|
if (timeout) {
|
|
1164
1271
|
clearTimeout(timeout);
|
|
@@ -1195,7 +1302,8 @@ function hookSetter(target, key, d, isRevoked, win = window) {
|
|
|
1195
1302
|
function patch(source, name, replacement) {
|
|
1196
1303
|
try {
|
|
1197
1304
|
if (!(name in source)) {
|
|
1198
|
-
return () => {
|
|
1305
|
+
return () => {
|
|
1306
|
+
};
|
|
1199
1307
|
}
|
|
1200
1308
|
const original = source[name];
|
|
1201
1309
|
const wrapped = replacement(original);
|
|
@@ -1214,9 +1322,36 @@ function patch(source, name, replacement) {
|
|
|
1214
1322
|
};
|
|
1215
1323
|
}
|
|
1216
1324
|
catch (_a) {
|
|
1217
|
-
return () => {
|
|
1325
|
+
return () => {
|
|
1326
|
+
};
|
|
1218
1327
|
}
|
|
1219
1328
|
}
|
|
1329
|
+
let nowTimestamp = Date.now;
|
|
1330
|
+
if (!(/[1-9][0-9]{12}/.test(Date.now().toString()))) {
|
|
1331
|
+
nowTimestamp = () => new Date().getTime();
|
|
1332
|
+
}
|
|
1333
|
+
function getWindowScroll(win) {
|
|
1334
|
+
var _a, _b, _c, _d, _e, _f;
|
|
1335
|
+
const doc = win.document;
|
|
1336
|
+
return {
|
|
1337
|
+
left: doc.scrollingElement
|
|
1338
|
+
? doc.scrollingElement.scrollLeft
|
|
1339
|
+
: win.pageXOffset !== undefined
|
|
1340
|
+
? win.pageXOffset
|
|
1341
|
+
: (doc === null || doc === void 0 ? void 0 : doc.documentElement.scrollLeft) ||
|
|
1342
|
+
((_b = (_a = doc === null || doc === void 0 ? void 0 : doc.body) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.scrollLeft) ||
|
|
1343
|
+
((_c = doc === null || doc === void 0 ? void 0 : doc.body) === null || _c === void 0 ? void 0 : _c.scrollLeft) ||
|
|
1344
|
+
0,
|
|
1345
|
+
top: doc.scrollingElement
|
|
1346
|
+
? doc.scrollingElement.scrollTop
|
|
1347
|
+
: win.pageYOffset !== undefined
|
|
1348
|
+
? win.pageYOffset
|
|
1349
|
+
: (doc === null || doc === void 0 ? void 0 : doc.documentElement.scrollTop) ||
|
|
1350
|
+
((_e = (_d = doc === null || doc === void 0 ? void 0 : doc.body) === null || _d === void 0 ? void 0 : _d.parentElement) === null || _e === void 0 ? void 0 : _e.scrollTop) ||
|
|
1351
|
+
((_f = doc === null || doc === void 0 ? void 0 : doc.body) === null || _f === void 0 ? void 0 : _f.scrollTop) ||
|
|
1352
|
+
0,
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1220
1355
|
function getWindowHeight() {
|
|
1221
1356
|
return (window.innerHeight ||
|
|
1222
1357
|
(document.documentElement && document.documentElement.clientHeight) ||
|
|
@@ -1227,48 +1362,38 @@ function getWindowWidth() {
|
|
|
1227
1362
|
(document.documentElement && document.documentElement.clientWidth) ||
|
|
1228
1363
|
(document.body && document.body.clientWidth));
|
|
1229
1364
|
}
|
|
1230
|
-
function isBlocked(node, blockClass, blockSelector, unblockSelector) {
|
|
1365
|
+
function isBlocked(node, blockClass, blockSelector, unblockSelector, checkAncestors) {
|
|
1231
1366
|
if (!node) {
|
|
1232
1367
|
return false;
|
|
1233
1368
|
}
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
else {
|
|
1249
|
-
!needUnblock &&
|
|
1250
|
-
node.classList.forEach((className) => {
|
|
1251
|
-
if (blockClass.test(className)) {
|
|
1252
|
-
needBlock = true;
|
|
1253
|
-
}
|
|
1254
|
-
});
|
|
1255
|
-
}
|
|
1256
|
-
if (!needBlock && blockSelector) {
|
|
1257
|
-
needBlock = node.matches(blockSelector);
|
|
1258
|
-
}
|
|
1259
|
-
return ((!needUnblock && needBlock) ||
|
|
1260
|
-
isBlocked(node.parentNode, blockClass, blockSelector, unblockSelector));
|
|
1369
|
+
const el = node.nodeType === node.ELEMENT_NODE
|
|
1370
|
+
? node
|
|
1371
|
+
: node.parentElement;
|
|
1372
|
+
if (!el)
|
|
1373
|
+
return false;
|
|
1374
|
+
const blockedPredicate = createMatchPredicate(blockClass, blockSelector);
|
|
1375
|
+
if (!checkAncestors) {
|
|
1376
|
+
const isUnblocked = unblockSelector && el.matches(unblockSelector);
|
|
1377
|
+
return blockedPredicate(el) && !isUnblocked;
|
|
1378
|
+
}
|
|
1379
|
+
const blockDistance = distanceToMatch(el, blockedPredicate);
|
|
1380
|
+
let unblockDistance = -1;
|
|
1381
|
+
if (blockDistance < 0) {
|
|
1382
|
+
return false;
|
|
1261
1383
|
}
|
|
1262
|
-
if (
|
|
1263
|
-
|
|
1384
|
+
if (unblockSelector) {
|
|
1385
|
+
unblockDistance = distanceToMatch(el, createMatchPredicate(null, unblockSelector));
|
|
1264
1386
|
}
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
function isIgnored(n) {
|
|
1268
|
-
if ('__sn' in n) {
|
|
1269
|
-
return n.__sn.id === IGNORED_NODE;
|
|
1387
|
+
if (blockDistance > -1 && unblockDistance < 0) {
|
|
1388
|
+
return true;
|
|
1270
1389
|
}
|
|
1271
|
-
return
|
|
1390
|
+
return blockDistance < unblockDistance;
|
|
1391
|
+
}
|
|
1392
|
+
function isSerialized(n, mirror) {
|
|
1393
|
+
return mirror.getId(n) !== -1;
|
|
1394
|
+
}
|
|
1395
|
+
function isIgnored(n, mirror) {
|
|
1396
|
+
return mirror.getId(n) === IGNORED_NODE;
|
|
1272
1397
|
}
|
|
1273
1398
|
function isAncestorRemoved(target, mirror) {
|
|
1274
1399
|
if (isShadowRoot(target)) {
|
|
@@ -1287,7 +1412,7 @@ function isAncestorRemoved(target, mirror) {
|
|
|
1287
1412
|
}
|
|
1288
1413
|
return isAncestorRemoved(target.parentNode, mirror);
|
|
1289
1414
|
}
|
|
1290
|
-
function
|
|
1415
|
+
function legacy_isTouchEvent(event) {
|
|
1291
1416
|
return Boolean(event.changedTouches);
|
|
1292
1417
|
}
|
|
1293
1418
|
function polyfill(win = window) {
|
|
@@ -1300,8 +1425,9 @@ function polyfill(win = window) {
|
|
|
1300
1425
|
.forEach;
|
|
1301
1426
|
}
|
|
1302
1427
|
if (!Node.prototype.contains) {
|
|
1303
|
-
Node.prototype.contains =
|
|
1304
|
-
|
|
1428
|
+
Node.prototype.contains = (...args) => {
|
|
1429
|
+
let node = args[0];
|
|
1430
|
+
if (!(0 in args)) {
|
|
1305
1431
|
throw new TypeError('1 argument is required');
|
|
1306
1432
|
}
|
|
1307
1433
|
do {
|
|
@@ -1313,15 +1439,142 @@ function polyfill(win = window) {
|
|
|
1313
1439
|
};
|
|
1314
1440
|
}
|
|
1315
1441
|
}
|
|
1316
|
-
function
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
return
|
|
1442
|
+
function isSerializedIframe(n, mirror) {
|
|
1443
|
+
return Boolean(n.nodeName === 'IFRAME' && mirror.getMeta(n));
|
|
1444
|
+
}
|
|
1445
|
+
function isSerializedStylesheet(n, mirror) {
|
|
1446
|
+
return Boolean(n.nodeName === 'LINK' &&
|
|
1447
|
+
n.nodeType === n.ELEMENT_NODE &&
|
|
1448
|
+
n.getAttribute &&
|
|
1449
|
+
n.getAttribute('rel') === 'stylesheet' &&
|
|
1450
|
+
mirror.getMeta(n));
|
|
1321
1451
|
}
|
|
1322
1452
|
function hasShadowRoot(n) {
|
|
1323
1453
|
return Boolean(n === null || n === void 0 ? void 0 : n.shadowRoot);
|
|
1324
1454
|
}
|
|
1455
|
+
class StyleSheetMirror {
|
|
1456
|
+
constructor() {
|
|
1457
|
+
this.id = 1;
|
|
1458
|
+
this.styleIDMap = new WeakMap();
|
|
1459
|
+
this.idStyleMap = new Map();
|
|
1460
|
+
}
|
|
1461
|
+
getId(stylesheet) {
|
|
1462
|
+
var _a;
|
|
1463
|
+
return (_a = this.styleIDMap.get(stylesheet)) !== null && _a !== void 0 ? _a : -1;
|
|
1464
|
+
}
|
|
1465
|
+
has(stylesheet) {
|
|
1466
|
+
return this.styleIDMap.has(stylesheet);
|
|
1467
|
+
}
|
|
1468
|
+
add(stylesheet, id) {
|
|
1469
|
+
if (this.has(stylesheet))
|
|
1470
|
+
return this.getId(stylesheet);
|
|
1471
|
+
let newId;
|
|
1472
|
+
if (id === undefined) {
|
|
1473
|
+
newId = this.id++;
|
|
1474
|
+
}
|
|
1475
|
+
else
|
|
1476
|
+
newId = id;
|
|
1477
|
+
this.styleIDMap.set(stylesheet, newId);
|
|
1478
|
+
this.idStyleMap.set(newId, stylesheet);
|
|
1479
|
+
return newId;
|
|
1480
|
+
}
|
|
1481
|
+
getStyle(id) {
|
|
1482
|
+
return this.idStyleMap.get(id) || null;
|
|
1483
|
+
}
|
|
1484
|
+
reset() {
|
|
1485
|
+
this.styleIDMap = new WeakMap();
|
|
1486
|
+
this.idStyleMap = new Map();
|
|
1487
|
+
this.id = 1;
|
|
1488
|
+
}
|
|
1489
|
+
generateId() {
|
|
1490
|
+
return this.id++;
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
function getShadowHost(n) {
|
|
1494
|
+
var _a, _b;
|
|
1495
|
+
let shadowHost = null;
|
|
1496
|
+
if (((_b = (_a = n.getRootNode) === null || _a === void 0 ? void 0 : _a.call(n)) === null || _b === void 0 ? void 0 : _b.nodeType) === Node.DOCUMENT_FRAGMENT_NODE &&
|
|
1497
|
+
n.getRootNode().host)
|
|
1498
|
+
shadowHost = n.getRootNode().host;
|
|
1499
|
+
return shadowHost;
|
|
1500
|
+
}
|
|
1501
|
+
function getRootShadowHost(n) {
|
|
1502
|
+
let rootShadowHost = n;
|
|
1503
|
+
let shadowHost;
|
|
1504
|
+
while ((shadowHost = getShadowHost(rootShadowHost)))
|
|
1505
|
+
rootShadowHost = shadowHost;
|
|
1506
|
+
return rootShadowHost;
|
|
1507
|
+
}
|
|
1508
|
+
function shadowHostInDom(n) {
|
|
1509
|
+
const doc = n.ownerDocument;
|
|
1510
|
+
if (!doc)
|
|
1511
|
+
return false;
|
|
1512
|
+
const shadowHost = getRootShadowHost(n);
|
|
1513
|
+
return doc.contains(shadowHost);
|
|
1514
|
+
}
|
|
1515
|
+
function inDom(n) {
|
|
1516
|
+
const doc = n.ownerDocument;
|
|
1517
|
+
if (!doc)
|
|
1518
|
+
return false;
|
|
1519
|
+
return doc.contains(n) || shadowHostInDom(n);
|
|
1520
|
+
}
|
|
1521
|
+
|
|
1522
|
+
var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
1523
|
+
EventType2[EventType2["DomContentLoaded"] = 0] = "DomContentLoaded";
|
|
1524
|
+
EventType2[EventType2["Load"] = 1] = "Load";
|
|
1525
|
+
EventType2[EventType2["FullSnapshot"] = 2] = "FullSnapshot";
|
|
1526
|
+
EventType2[EventType2["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
|
|
1527
|
+
EventType2[EventType2["Meta"] = 4] = "Meta";
|
|
1528
|
+
EventType2[EventType2["Custom"] = 5] = "Custom";
|
|
1529
|
+
EventType2[EventType2["Plugin"] = 6] = "Plugin";
|
|
1530
|
+
return EventType2;
|
|
1531
|
+
})(EventType || {});
|
|
1532
|
+
var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
|
|
1533
|
+
IncrementalSource2[IncrementalSource2["Mutation"] = 0] = "Mutation";
|
|
1534
|
+
IncrementalSource2[IncrementalSource2["MouseMove"] = 1] = "MouseMove";
|
|
1535
|
+
IncrementalSource2[IncrementalSource2["MouseInteraction"] = 2] = "MouseInteraction";
|
|
1536
|
+
IncrementalSource2[IncrementalSource2["Scroll"] = 3] = "Scroll";
|
|
1537
|
+
IncrementalSource2[IncrementalSource2["ViewportResize"] = 4] = "ViewportResize";
|
|
1538
|
+
IncrementalSource2[IncrementalSource2["Input"] = 5] = "Input";
|
|
1539
|
+
IncrementalSource2[IncrementalSource2["TouchMove"] = 6] = "TouchMove";
|
|
1540
|
+
IncrementalSource2[IncrementalSource2["MediaInteraction"] = 7] = "MediaInteraction";
|
|
1541
|
+
IncrementalSource2[IncrementalSource2["StyleSheetRule"] = 8] = "StyleSheetRule";
|
|
1542
|
+
IncrementalSource2[IncrementalSource2["CanvasMutation"] = 9] = "CanvasMutation";
|
|
1543
|
+
IncrementalSource2[IncrementalSource2["Font"] = 10] = "Font";
|
|
1544
|
+
IncrementalSource2[IncrementalSource2["Log"] = 11] = "Log";
|
|
1545
|
+
IncrementalSource2[IncrementalSource2["Drag"] = 12] = "Drag";
|
|
1546
|
+
IncrementalSource2[IncrementalSource2["StyleDeclaration"] = 13] = "StyleDeclaration";
|
|
1547
|
+
IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
|
|
1548
|
+
IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
|
|
1549
|
+
IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
|
|
1550
|
+
return IncrementalSource2;
|
|
1551
|
+
})(IncrementalSource || {});
|
|
1552
|
+
var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
|
|
1553
|
+
MouseInteractions2[MouseInteractions2["MouseUp"] = 0] = "MouseUp";
|
|
1554
|
+
MouseInteractions2[MouseInteractions2["MouseDown"] = 1] = "MouseDown";
|
|
1555
|
+
MouseInteractions2[MouseInteractions2["Click"] = 2] = "Click";
|
|
1556
|
+
MouseInteractions2[MouseInteractions2["ContextMenu"] = 3] = "ContextMenu";
|
|
1557
|
+
MouseInteractions2[MouseInteractions2["DblClick"] = 4] = "DblClick";
|
|
1558
|
+
MouseInteractions2[MouseInteractions2["Focus"] = 5] = "Focus";
|
|
1559
|
+
MouseInteractions2[MouseInteractions2["Blur"] = 6] = "Blur";
|
|
1560
|
+
MouseInteractions2[MouseInteractions2["TouchStart"] = 7] = "TouchStart";
|
|
1561
|
+
MouseInteractions2[MouseInteractions2["TouchMove_Departed"] = 8] = "TouchMove_Departed";
|
|
1562
|
+
MouseInteractions2[MouseInteractions2["TouchEnd"] = 9] = "TouchEnd";
|
|
1563
|
+
MouseInteractions2[MouseInteractions2["TouchCancel"] = 10] = "TouchCancel";
|
|
1564
|
+
return MouseInteractions2;
|
|
1565
|
+
})(MouseInteractions || {});
|
|
1566
|
+
var PointerTypes = /* @__PURE__ */ ((PointerTypes2) => {
|
|
1567
|
+
PointerTypes2[PointerTypes2["Mouse"] = 0] = "Mouse";
|
|
1568
|
+
PointerTypes2[PointerTypes2["Pen"] = 1] = "Pen";
|
|
1569
|
+
PointerTypes2[PointerTypes2["Touch"] = 2] = "Touch";
|
|
1570
|
+
return PointerTypes2;
|
|
1571
|
+
})(PointerTypes || {});
|
|
1572
|
+
var CanvasContext = /* @__PURE__ */ ((CanvasContext2) => {
|
|
1573
|
+
CanvasContext2[CanvasContext2["2D"] = 0] = "2D";
|
|
1574
|
+
CanvasContext2[CanvasContext2["WebGL"] = 1] = "WebGL";
|
|
1575
|
+
CanvasContext2[CanvasContext2["WebGL2"] = 2] = "WebGL2";
|
|
1576
|
+
return CanvasContext2;
|
|
1577
|
+
})(CanvasContext || {});
|
|
1325
1578
|
|
|
1326
1579
|
function isNodeInLinkedList(n) {
|
|
1327
1580
|
return '__ln' in n;
|
|
@@ -1330,6 +1583,7 @@ class DoubleLinkedList {
|
|
|
1330
1583
|
constructor() {
|
|
1331
1584
|
this.length = 0;
|
|
1332
1585
|
this.head = null;
|
|
1586
|
+
this.tail = null;
|
|
1333
1587
|
}
|
|
1334
1588
|
get(position) {
|
|
1335
1589
|
if (position >= this.length) {
|
|
@@ -1375,6 +1629,9 @@ class DoubleLinkedList {
|
|
|
1375
1629
|
node.next = this.head;
|
|
1376
1630
|
this.head = node;
|
|
1377
1631
|
}
|
|
1632
|
+
if (node.next === null) {
|
|
1633
|
+
this.tail = node;
|
|
1634
|
+
}
|
|
1378
1635
|
this.length++;
|
|
1379
1636
|
}
|
|
1380
1637
|
removeNode(n) {
|
|
@@ -1387,12 +1644,18 @@ class DoubleLinkedList {
|
|
|
1387
1644
|
if (this.head) {
|
|
1388
1645
|
this.head.previous = null;
|
|
1389
1646
|
}
|
|
1647
|
+
else {
|
|
1648
|
+
this.tail = null;
|
|
1649
|
+
}
|
|
1390
1650
|
}
|
|
1391
1651
|
else {
|
|
1392
1652
|
current.previous.next = current.next;
|
|
1393
1653
|
if (current.next) {
|
|
1394
1654
|
current.next.previous = current.previous;
|
|
1395
1655
|
}
|
|
1656
|
+
else {
|
|
1657
|
+
this.tail = current.previous;
|
|
1658
|
+
}
|
|
1396
1659
|
}
|
|
1397
1660
|
if (n.__ln) {
|
|
1398
1661
|
delete n.__ln;
|
|
@@ -1401,9 +1664,6 @@ class DoubleLinkedList {
|
|
|
1401
1664
|
}
|
|
1402
1665
|
}
|
|
1403
1666
|
const moveKey = (id, parentId) => `${id}@${parentId}`;
|
|
1404
|
-
function isINode(n) {
|
|
1405
|
-
return '__sn' in n;
|
|
1406
|
-
}
|
|
1407
1667
|
class MutationBuffer {
|
|
1408
1668
|
constructor() {
|
|
1409
1669
|
this.frozen = false;
|
|
@@ -1425,6 +1685,7 @@ class MutationBuffer {
|
|
|
1425
1685
|
return;
|
|
1426
1686
|
}
|
|
1427
1687
|
const adds = [];
|
|
1688
|
+
const addedIds = new Set();
|
|
1428
1689
|
const addList = new DoubleLinkedList();
|
|
1429
1690
|
const getNextId = (n) => {
|
|
1430
1691
|
let ns = n;
|
|
@@ -1436,59 +1697,56 @@ class MutationBuffer {
|
|
|
1436
1697
|
return nextId;
|
|
1437
1698
|
};
|
|
1438
1699
|
const pushAdd = (n) => {
|
|
1439
|
-
|
|
1440
|
-
const shadowHost = n.getRootNode
|
|
1441
|
-
? (_a = n.getRootNode()) === null || _a === void 0 ? void 0 : _a.host
|
|
1442
|
-
: null;
|
|
1443
|
-
let rootShadowHost = shadowHost;
|
|
1444
|
-
while ((_c = (_b = rootShadowHost === null || rootShadowHost === void 0 ? void 0 : rootShadowHost.getRootNode) === null || _b === void 0 ? void 0 : _b.call(rootShadowHost)) === null || _c === void 0 ? void 0 : _c.host)
|
|
1445
|
-
rootShadowHost =
|
|
1446
|
-
((_e = (_d = rootShadowHost === null || rootShadowHost === void 0 ? void 0 : rootShadowHost.getRootNode) === null || _d === void 0 ? void 0 : _d.call(rootShadowHost)) === null || _e === void 0 ? void 0 : _e.host) ||
|
|
1447
|
-
null;
|
|
1448
|
-
const notInDoc = !this.doc.contains(n) &&
|
|
1449
|
-
(!rootShadowHost || !this.doc.contains(rootShadowHost));
|
|
1450
|
-
if (!n.parentNode || notInDoc) {
|
|
1700
|
+
if (!n.parentNode || !inDom(n)) {
|
|
1451
1701
|
return;
|
|
1452
1702
|
}
|
|
1453
1703
|
const parentId = isShadowRoot(n.parentNode)
|
|
1454
|
-
? this.mirror.getId(
|
|
1704
|
+
? this.mirror.getId(getShadowHost(n))
|
|
1455
1705
|
: this.mirror.getId(n.parentNode);
|
|
1456
1706
|
const nextId = getNextId(n);
|
|
1457
1707
|
if (parentId === -1 || nextId === -1) {
|
|
1458
1708
|
return addList.addNode(n);
|
|
1459
1709
|
}
|
|
1460
|
-
|
|
1710
|
+
const sn = serializeNodeWithId(n, {
|
|
1461
1711
|
doc: this.doc,
|
|
1462
|
-
|
|
1712
|
+
mirror: this.mirror,
|
|
1463
1713
|
blockClass: this.blockClass,
|
|
1464
1714
|
blockSelector: this.blockSelector,
|
|
1715
|
+
maskAllText: this.maskAllText,
|
|
1465
1716
|
unblockSelector: this.unblockSelector,
|
|
1466
1717
|
maskTextClass: this.maskTextClass,
|
|
1718
|
+
unmaskTextClass: this.unmaskTextClass,
|
|
1467
1719
|
maskTextSelector: this.maskTextSelector,
|
|
1468
1720
|
unmaskTextSelector: this.unmaskTextSelector,
|
|
1469
|
-
maskInputSelector: this.maskInputSelector,
|
|
1470
|
-
unmaskInputSelector: this.unmaskInputSelector,
|
|
1471
1721
|
skipChild: true,
|
|
1722
|
+
newlyAddedElement: true,
|
|
1472
1723
|
inlineStylesheet: this.inlineStylesheet,
|
|
1473
|
-
maskAllText: this.maskAllText,
|
|
1474
1724
|
maskInputOptions: this.maskInputOptions,
|
|
1725
|
+
maskAttributeFn: this.maskAttributeFn,
|
|
1475
1726
|
maskTextFn: this.maskTextFn,
|
|
1476
1727
|
maskInputFn: this.maskInputFn,
|
|
1477
1728
|
slimDOMOptions: this.slimDOMOptions,
|
|
1729
|
+
dataURLOptions: this.dataURLOptions,
|
|
1478
1730
|
recordCanvas: this.recordCanvas,
|
|
1479
1731
|
inlineImages: this.inlineImages,
|
|
1480
1732
|
onSerialize: (currentN) => {
|
|
1481
|
-
if (
|
|
1733
|
+
if (isSerializedIframe(currentN, this.mirror)) {
|
|
1482
1734
|
this.iframeManager.addIframe(currentN);
|
|
1483
1735
|
}
|
|
1736
|
+
if (isSerializedStylesheet(currentN, this.mirror)) {
|
|
1737
|
+
this.stylesheetManager.trackLinkElement(currentN);
|
|
1738
|
+
}
|
|
1484
1739
|
if (hasShadowRoot(n)) {
|
|
1485
|
-
this.shadowDomManager.addShadowRoot(n.shadowRoot,
|
|
1740
|
+
this.shadowDomManager.addShadowRoot(n.shadowRoot, this.doc);
|
|
1486
1741
|
}
|
|
1487
1742
|
},
|
|
1488
1743
|
onIframeLoad: (iframe, childSn) => {
|
|
1489
1744
|
this.iframeManager.attachIframe(iframe, childSn);
|
|
1490
1745
|
this.shadowDomManager.observeAttachShadow(iframe);
|
|
1491
1746
|
},
|
|
1747
|
+
onStylesheetLoad: (link, childSn) => {
|
|
1748
|
+
this.stylesheetManager.attachLinkElement(link, childSn);
|
|
1749
|
+
},
|
|
1492
1750
|
});
|
|
1493
1751
|
if (sn) {
|
|
1494
1752
|
adds.push({
|
|
@@ -1496,6 +1754,7 @@ class MutationBuffer {
|
|
|
1496
1754
|
nextId,
|
|
1497
1755
|
node: sn,
|
|
1498
1756
|
});
|
|
1757
|
+
addedIds.add(sn.id);
|
|
1499
1758
|
}
|
|
1500
1759
|
};
|
|
1501
1760
|
while (this.mapRemoves.length) {
|
|
@@ -1531,15 +1790,33 @@ class MutationBuffer {
|
|
|
1531
1790
|
}
|
|
1532
1791
|
}
|
|
1533
1792
|
if (!node) {
|
|
1534
|
-
|
|
1535
|
-
|
|
1793
|
+
let tailNode = addList.tail;
|
|
1794
|
+
while (tailNode) {
|
|
1795
|
+
const _node = tailNode;
|
|
1796
|
+
tailNode = tailNode.previous;
|
|
1536
1797
|
if (_node) {
|
|
1537
1798
|
const parentId = this.mirror.getId(_node.value.parentNode);
|
|
1538
1799
|
const nextId = getNextId(_node.value);
|
|
1539
|
-
if (
|
|
1800
|
+
if (nextId === -1)
|
|
1801
|
+
continue;
|
|
1802
|
+
else if (parentId !== -1) {
|
|
1540
1803
|
node = _node;
|
|
1541
1804
|
break;
|
|
1542
1805
|
}
|
|
1806
|
+
else {
|
|
1807
|
+
const unhandledNode = _node.value;
|
|
1808
|
+
if (unhandledNode.parentNode &&
|
|
1809
|
+
unhandledNode.parentNode.nodeType ===
|
|
1810
|
+
Node.DOCUMENT_FRAGMENT_NODE) {
|
|
1811
|
+
const shadowHost = unhandledNode.parentNode
|
|
1812
|
+
.host;
|
|
1813
|
+
const parentId = this.mirror.getId(shadowHost);
|
|
1814
|
+
if (parentId !== -1) {
|
|
1815
|
+
node = _node;
|
|
1816
|
+
break;
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1543
1820
|
}
|
|
1544
1821
|
}
|
|
1545
1822
|
}
|
|
@@ -1559,12 +1836,27 @@ class MutationBuffer {
|
|
|
1559
1836
|
id: this.mirror.getId(text.node),
|
|
1560
1837
|
value: text.value,
|
|
1561
1838
|
}))
|
|
1839
|
+
.filter((text) => !addedIds.has(text.id))
|
|
1562
1840
|
.filter((text) => this.mirror.has(text.id)),
|
|
1563
1841
|
attributes: this.attributes
|
|
1564
|
-
.map((attribute) =>
|
|
1565
|
-
|
|
1566
|
-
attributes
|
|
1567
|
-
|
|
1842
|
+
.map((attribute) => {
|
|
1843
|
+
const { attributes } = attribute;
|
|
1844
|
+
if (typeof attributes.style === 'string') {
|
|
1845
|
+
const diffAsStr = JSON.stringify(attribute.styleDiff);
|
|
1846
|
+
const unchangedAsStr = JSON.stringify(attribute._unchangedStyles);
|
|
1847
|
+
if (diffAsStr.length < attributes.style.length) {
|
|
1848
|
+
if ((diffAsStr + unchangedAsStr).split('var(').length ===
|
|
1849
|
+
attributes.style.split('var(').length) {
|
|
1850
|
+
attributes.style = attribute.styleDiff;
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
return {
|
|
1855
|
+
id: this.mirror.getId(attribute.node),
|
|
1856
|
+
attributes: attributes,
|
|
1857
|
+
};
|
|
1858
|
+
})
|
|
1859
|
+
.filter((attribute) => !addedIds.has(attribute.id))
|
|
1568
1860
|
.filter((attribute) => this.mirror.has(attribute.id)),
|
|
1569
1861
|
removes: this.removes,
|
|
1570
1862
|
adds,
|
|
@@ -1585,15 +1877,23 @@ class MutationBuffer {
|
|
|
1585
1877
|
this.mutationCb(payload);
|
|
1586
1878
|
};
|
|
1587
1879
|
this.processMutation = (m) => {
|
|
1588
|
-
if (isIgnored(m.target)) {
|
|
1880
|
+
if (isIgnored(m.target, this.mirror)) {
|
|
1589
1881
|
return;
|
|
1590
1882
|
}
|
|
1883
|
+
let unattachedDoc;
|
|
1884
|
+
try {
|
|
1885
|
+
unattachedDoc = document.implementation.createHTMLDocument();
|
|
1886
|
+
}
|
|
1887
|
+
catch (e) {
|
|
1888
|
+
unattachedDoc = this.doc;
|
|
1889
|
+
}
|
|
1591
1890
|
switch (m.type) {
|
|
1592
1891
|
case 'characterData': {
|
|
1593
1892
|
const value = m.target.textContent;
|
|
1594
|
-
if (!isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector) &&
|
|
1893
|
+
if (!isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, false) &&
|
|
1894
|
+
value !== m.oldValue) {
|
|
1595
1895
|
this.texts.push({
|
|
1596
|
-
value: needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, this.unmaskTextSelector, this.maskAllText) && value
|
|
1896
|
+
value: needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, this.unmaskTextClass, this.unmaskTextSelector, this.maskAllText) && value
|
|
1597
1897
|
? this.maskTextFn
|
|
1598
1898
|
? this.maskTextFn(value)
|
|
1599
1899
|
: value.replace(/[\S]/g, '*')
|
|
@@ -1605,83 +1905,99 @@ class MutationBuffer {
|
|
|
1605
1905
|
}
|
|
1606
1906
|
case 'attributes': {
|
|
1607
1907
|
const target = m.target;
|
|
1608
|
-
let
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1908
|
+
let attributeName = m.attributeName;
|
|
1909
|
+
let value = m.target.getAttribute(attributeName);
|
|
1910
|
+
if (attributeName === 'value') {
|
|
1911
|
+
const type = getInputType(target);
|
|
1912
|
+
const tagName = target.tagName;
|
|
1913
|
+
value = getInputValue(target, tagName, type);
|
|
1914
|
+
const isInputMasked = shouldMaskInput({
|
|
1614
1915
|
maskInputOptions: this.maskInputOptions,
|
|
1615
|
-
tagName
|
|
1616
|
-
type
|
|
1916
|
+
tagName,
|
|
1917
|
+
type,
|
|
1918
|
+
});
|
|
1919
|
+
const forceMask = needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, this.unmaskTextClass, this.unmaskTextSelector, isInputMasked);
|
|
1920
|
+
value = maskInputValue({
|
|
1921
|
+
isMasked: forceMask,
|
|
1922
|
+
element: target,
|
|
1617
1923
|
value,
|
|
1618
1924
|
maskInputFn: this.maskInputFn,
|
|
1619
1925
|
});
|
|
1620
1926
|
}
|
|
1621
|
-
if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector) ||
|
|
1927
|
+
if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, false) ||
|
|
1928
|
+
value === m.oldValue) {
|
|
1622
1929
|
return;
|
|
1623
1930
|
}
|
|
1624
1931
|
let item = this.attributes.find((a) => a.node === m.target);
|
|
1932
|
+
if (target.tagName === 'IFRAME' &&
|
|
1933
|
+
attributeName === 'src' &&
|
|
1934
|
+
!this.keepIframeSrcFn(value)) {
|
|
1935
|
+
if (!target.contentDocument) {
|
|
1936
|
+
attributeName = 'rr_src';
|
|
1937
|
+
}
|
|
1938
|
+
else {
|
|
1939
|
+
return;
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1625
1942
|
if (!item) {
|
|
1626
1943
|
item = {
|
|
1627
1944
|
node: m.target,
|
|
1628
1945
|
attributes: {},
|
|
1946
|
+
styleDiff: {},
|
|
1947
|
+
_unchangedStyles: {},
|
|
1629
1948
|
};
|
|
1630
1949
|
this.attributes.push(item);
|
|
1631
1950
|
}
|
|
1632
|
-
if (
|
|
1951
|
+
if (attributeName === 'type' &&
|
|
1633
1952
|
target.tagName === 'INPUT' &&
|
|
1634
1953
|
(m.oldValue || '').toLowerCase() === 'password') {
|
|
1635
1954
|
target.setAttribute('data-rr-is-password', 'true');
|
|
1636
1955
|
}
|
|
1637
|
-
if (
|
|
1638
|
-
|
|
1639
|
-
if (
|
|
1640
|
-
old.
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
item.attributes.style = {};
|
|
1645
|
-
}
|
|
1646
|
-
try {
|
|
1647
|
-
const styleObj = item.attributes.style;
|
|
1956
|
+
if (!ignoreAttribute(target.tagName, attributeName)) {
|
|
1957
|
+
item.attributes[attributeName] = transformAttribute(this.doc, toLowerCase(target.tagName), toLowerCase(attributeName), value, target, this.maskAttributeFn);
|
|
1958
|
+
if (attributeName === 'style') {
|
|
1959
|
+
const old = unattachedDoc.createElement('span');
|
|
1960
|
+
if (m.oldValue) {
|
|
1961
|
+
old.setAttribute('style', m.oldValue);
|
|
1962
|
+
}
|
|
1648
1963
|
for (const pname of Array.from(target.style)) {
|
|
1649
1964
|
const newValue = target.style.getPropertyValue(pname);
|
|
1650
1965
|
const newPriority = target.style.getPropertyPriority(pname);
|
|
1651
1966
|
if (newValue !== old.style.getPropertyValue(pname) ||
|
|
1652
1967
|
newPriority !== old.style.getPropertyPriority(pname)) {
|
|
1653
1968
|
if (newPriority === '') {
|
|
1654
|
-
|
|
1969
|
+
item.styleDiff[pname] = newValue;
|
|
1655
1970
|
}
|
|
1656
1971
|
else {
|
|
1657
|
-
|
|
1972
|
+
item.styleDiff[pname] = [newValue, newPriority];
|
|
1658
1973
|
}
|
|
1659
1974
|
}
|
|
1975
|
+
else {
|
|
1976
|
+
item._unchangedStyles[pname] = [newValue, newPriority];
|
|
1977
|
+
}
|
|
1660
1978
|
}
|
|
1661
1979
|
for (const pname of Array.from(old.style)) {
|
|
1662
1980
|
if (target.style.getPropertyValue(pname) === '') {
|
|
1663
|
-
|
|
1981
|
+
item.styleDiff[pname] = false;
|
|
1664
1982
|
}
|
|
1665
1983
|
}
|
|
1666
1984
|
}
|
|
1667
|
-
catch (error) {
|
|
1668
|
-
console.warn('[rrweb] Error when parsing update to style attribute:', error);
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
1671
|
-
else {
|
|
1672
|
-
const element = m.target;
|
|
1673
|
-
item.attributes[m.attributeName] = transformAttribute(this.doc, element, element.tagName, m.attributeName, value, this.maskAllText, this.unmaskTextSelector, this.maskTextFn);
|
|
1674
1985
|
}
|
|
1675
1986
|
break;
|
|
1676
1987
|
}
|
|
1677
1988
|
case 'childList': {
|
|
1989
|
+
if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, true)) {
|
|
1990
|
+
return;
|
|
1991
|
+
}
|
|
1678
1992
|
m.addedNodes.forEach((n) => this.genAdds(n, m.target));
|
|
1679
1993
|
m.removedNodes.forEach((n) => {
|
|
1680
1994
|
const nodeId = this.mirror.getId(n);
|
|
1681
1995
|
const parentId = isShadowRoot(m.target)
|
|
1682
1996
|
? this.mirror.getId(m.target.host)
|
|
1683
1997
|
: this.mirror.getId(m.target);
|
|
1684
|
-
if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector) ||
|
|
1998
|
+
if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, false) ||
|
|
1999
|
+
isIgnored(n, this.mirror) ||
|
|
2000
|
+
!isSerialized(n, this.mirror)) {
|
|
1685
2001
|
return;
|
|
1686
2002
|
}
|
|
1687
2003
|
if (this.addedSet.has(n)) {
|
|
@@ -1698,7 +2014,9 @@ class MutationBuffer {
|
|
|
1698
2014
|
this.removes.push({
|
|
1699
2015
|
parentId,
|
|
1700
2016
|
id: nodeId,
|
|
1701
|
-
isShadow: isShadowRoot(m.target)
|
|
2017
|
+
isShadow: isShadowRoot(m.target) && isNativeShadowDom(m.target)
|
|
2018
|
+
? true
|
|
2019
|
+
: undefined,
|
|
1702
2020
|
});
|
|
1703
2021
|
}
|
|
1704
2022
|
this.mapRemoves.push(n);
|
|
@@ -1708,28 +2026,36 @@ class MutationBuffer {
|
|
|
1708
2026
|
}
|
|
1709
2027
|
};
|
|
1710
2028
|
this.genAdds = (n, target) => {
|
|
1711
|
-
if (
|
|
2029
|
+
if (this.processedNodeManager.inOtherBuffer(n, this))
|
|
1712
2030
|
return;
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
2031
|
+
if (this.addedSet.has(n) || this.movedSet.has(n))
|
|
2032
|
+
return;
|
|
2033
|
+
if (this.mirror.hasNode(n)) {
|
|
2034
|
+
if (isIgnored(n, this.mirror)) {
|
|
1716
2035
|
return;
|
|
1717
2036
|
}
|
|
1718
2037
|
this.movedSet.add(n);
|
|
1719
2038
|
let targetId = null;
|
|
1720
|
-
if (target &&
|
|
1721
|
-
targetId =
|
|
2039
|
+
if (target && this.mirror.hasNode(target)) {
|
|
2040
|
+
targetId = this.mirror.getId(target);
|
|
1722
2041
|
}
|
|
1723
|
-
if (targetId) {
|
|
1724
|
-
this.movedMap[moveKey(
|
|
2042
|
+
if (targetId && targetId !== -1) {
|
|
2043
|
+
this.movedMap[moveKey(this.mirror.getId(n), targetId)] = true;
|
|
1725
2044
|
}
|
|
1726
2045
|
}
|
|
1727
2046
|
else {
|
|
1728
2047
|
this.addedSet.add(n);
|
|
1729
2048
|
this.droppedSet.delete(n);
|
|
1730
2049
|
}
|
|
1731
|
-
if (!isBlocked(n, this.blockClass, this.blockSelector, this.unblockSelector))
|
|
2050
|
+
if (!isBlocked(n, this.blockClass, this.blockSelector, this.unblockSelector, false)) {
|
|
1732
2051
|
n.childNodes.forEach((childN) => this.genAdds(childN));
|
|
2052
|
+
if (hasShadowRoot(n)) {
|
|
2053
|
+
n.shadowRoot.childNodes.forEach((childN) => {
|
|
2054
|
+
this.processedNodeManager.add(childN, this);
|
|
2055
|
+
this.genAdds(childN, n);
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
}
|
|
1733
2059
|
};
|
|
1734
2060
|
}
|
|
1735
2061
|
init(options) {
|
|
@@ -1738,24 +2064,28 @@ class MutationBuffer {
|
|
|
1738
2064
|
'blockClass',
|
|
1739
2065
|
'blockSelector',
|
|
1740
2066
|
'unblockSelector',
|
|
2067
|
+
'maskAllText',
|
|
1741
2068
|
'maskTextClass',
|
|
2069
|
+
'unmaskTextClass',
|
|
1742
2070
|
'maskTextSelector',
|
|
1743
2071
|
'unmaskTextSelector',
|
|
1744
|
-
'maskInputSelector',
|
|
1745
|
-
'unmaskInputSelector',
|
|
1746
2072
|
'inlineStylesheet',
|
|
1747
|
-
'maskAllText',
|
|
1748
2073
|
'maskInputOptions',
|
|
2074
|
+
'maskAttributeFn',
|
|
1749
2075
|
'maskTextFn',
|
|
1750
2076
|
'maskInputFn',
|
|
2077
|
+
'keepIframeSrcFn',
|
|
1751
2078
|
'recordCanvas',
|
|
1752
2079
|
'inlineImages',
|
|
1753
2080
|
'slimDOMOptions',
|
|
2081
|
+
'dataURLOptions',
|
|
1754
2082
|
'doc',
|
|
1755
2083
|
'mirror',
|
|
1756
2084
|
'iframeManager',
|
|
2085
|
+
'stylesheetManager',
|
|
1757
2086
|
'shadowDomManager',
|
|
1758
2087
|
'canvasManager',
|
|
2088
|
+
'processedNodeManager',
|
|
1759
2089
|
].forEach((key) => {
|
|
1760
2090
|
this[key] = options[key];
|
|
1761
2091
|
});
|
|
@@ -1791,6 +2121,11 @@ function deepDelete(addsSet, n) {
|
|
|
1791
2121
|
n.childNodes.forEach((childN) => deepDelete(addsSet, childN));
|
|
1792
2122
|
}
|
|
1793
2123
|
function isParentRemoved(removes, n, mirror) {
|
|
2124
|
+
if (removes.length === 0)
|
|
2125
|
+
return false;
|
|
2126
|
+
return _isParentRemoved(removes, n, mirror);
|
|
2127
|
+
}
|
|
2128
|
+
function _isParentRemoved(removes, n, mirror) {
|
|
1794
2129
|
const { parentNode } = n;
|
|
1795
2130
|
if (!parentNode) {
|
|
1796
2131
|
return false;
|
|
@@ -1799,9 +2134,14 @@ function isParentRemoved(removes, n, mirror) {
|
|
|
1799
2134
|
if (removes.some((r) => r.id === parentId)) {
|
|
1800
2135
|
return true;
|
|
1801
2136
|
}
|
|
1802
|
-
return
|
|
2137
|
+
return _isParentRemoved(removes, parentNode, mirror);
|
|
1803
2138
|
}
|
|
1804
2139
|
function isAncestorInSet(set, n) {
|
|
2140
|
+
if (set.size === 0)
|
|
2141
|
+
return false;
|
|
2142
|
+
return _isAncestorInSet(set, n);
|
|
2143
|
+
}
|
|
2144
|
+
function _isAncestorInSet(set, n) {
|
|
1805
2145
|
const { parentNode } = n;
|
|
1806
2146
|
if (!parentNode) {
|
|
1807
2147
|
return false;
|
|
@@ -1809,23 +2149,31 @@ function isAncestorInSet(set, n) {
|
|
|
1809
2149
|
if (set.has(parentNode)) {
|
|
1810
2150
|
return true;
|
|
1811
2151
|
}
|
|
1812
|
-
return
|
|
2152
|
+
return _isAncestorInSet(set, parentNode);
|
|
1813
2153
|
}
|
|
1814
2154
|
|
|
2155
|
+
let errorHandler;
|
|
2156
|
+
function registerErrorHandler(handler) {
|
|
2157
|
+
errorHandler = handler;
|
|
2158
|
+
}
|
|
2159
|
+
function unregisterErrorHandler() {
|
|
2160
|
+
errorHandler = undefined;
|
|
2161
|
+
}
|
|
1815
2162
|
const callbackWrapper = (cb) => {
|
|
1816
|
-
|
|
2163
|
+
if (!errorHandler) {
|
|
2164
|
+
return cb;
|
|
2165
|
+
}
|
|
2166
|
+
const rrwebWrapped = ((...rest) => {
|
|
1817
2167
|
try {
|
|
1818
2168
|
return cb(...rest);
|
|
1819
2169
|
}
|
|
1820
2170
|
catch (error) {
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
}
|
|
1824
|
-
catch (_a) {
|
|
2171
|
+
if (errorHandler && errorHandler(error) === true) {
|
|
2172
|
+
return;
|
|
1825
2173
|
}
|
|
1826
2174
|
throw error;
|
|
1827
2175
|
}
|
|
1828
|
-
};
|
|
2176
|
+
});
|
|
1829
2177
|
return rrwebWrapped;
|
|
1830
2178
|
};
|
|
1831
2179
|
|
|
@@ -1842,7 +2190,8 @@ function getEventTarget(event) {
|
|
|
1842
2190
|
return event.path[0];
|
|
1843
2191
|
}
|
|
1844
2192
|
}
|
|
1845
|
-
catch (_a) {
|
|
2193
|
+
catch (_a) {
|
|
2194
|
+
}
|
|
1846
2195
|
return event && event.target;
|
|
1847
2196
|
}
|
|
1848
2197
|
function initMutationObserver(options, rootEl) {
|
|
@@ -1861,7 +2210,7 @@ function initMutationObserver(options, rootEl) {
|
|
|
1861
2210
|
if (options.onMutation && options.onMutation(mutations) === false) {
|
|
1862
2211
|
return;
|
|
1863
2212
|
}
|
|
1864
|
-
mutationBuffer.processMutations(mutations);
|
|
2213
|
+
mutationBuffer.processMutations.bind(mutationBuffer)(mutations);
|
|
1865
2214
|
}));
|
|
1866
2215
|
observer.observe(rootEl, {
|
|
1867
2216
|
attributes: true,
|
|
@@ -1875,7 +2224,8 @@ function initMutationObserver(options, rootEl) {
|
|
|
1875
2224
|
}
|
|
1876
2225
|
function initMoveObserver({ mousemoveCb, sampling, doc, mirror, }) {
|
|
1877
2226
|
if (sampling.mousemove === false) {
|
|
1878
|
-
return () => {
|
|
2227
|
+
return () => {
|
|
2228
|
+
};
|
|
1879
2229
|
}
|
|
1880
2230
|
const threshold = typeof sampling.mousemove === 'number' ? sampling.mousemove : 50;
|
|
1881
2231
|
const callbackThreshold = typeof sampling.mousemoveCallback === 'number'
|
|
@@ -1883,41 +2233,41 @@ function initMoveObserver({ mousemoveCb, sampling, doc, mirror, }) {
|
|
|
1883
2233
|
: 500;
|
|
1884
2234
|
let positions = [];
|
|
1885
2235
|
let timeBaseline;
|
|
1886
|
-
const wrappedCb = throttle$1((source) => {
|
|
2236
|
+
const wrappedCb = throttle$1(callbackWrapper((source) => {
|
|
1887
2237
|
const totalOffset = Date.now() - timeBaseline;
|
|
1888
|
-
|
|
2238
|
+
mousemoveCb(positions.map((p) => {
|
|
1889
2239
|
p.timeOffset -= totalOffset;
|
|
1890
2240
|
return p;
|
|
1891
2241
|
}), source);
|
|
1892
2242
|
positions = [];
|
|
1893
2243
|
timeBaseline = null;
|
|
1894
|
-
}, callbackThreshold);
|
|
1895
|
-
const updatePosition = throttle$1((evt) => {
|
|
2244
|
+
}), callbackThreshold);
|
|
2245
|
+
const updatePosition = callbackWrapper(throttle$1(callbackWrapper((evt) => {
|
|
1896
2246
|
const target = getEventTarget(evt);
|
|
1897
|
-
const { clientX, clientY } =
|
|
2247
|
+
const { clientX, clientY } = legacy_isTouchEvent(evt)
|
|
1898
2248
|
? evt.changedTouches[0]
|
|
1899
2249
|
: evt;
|
|
1900
2250
|
if (!timeBaseline) {
|
|
1901
|
-
timeBaseline =
|
|
2251
|
+
timeBaseline = nowTimestamp();
|
|
1902
2252
|
}
|
|
1903
2253
|
positions.push({
|
|
1904
2254
|
x: clientX,
|
|
1905
2255
|
y: clientY,
|
|
1906
2256
|
id: mirror.getId(target),
|
|
1907
|
-
timeOffset:
|
|
2257
|
+
timeOffset: nowTimestamp() - timeBaseline,
|
|
1908
2258
|
});
|
|
1909
2259
|
wrappedCb(typeof DragEvent !== 'undefined' && evt instanceof DragEvent
|
|
1910
2260
|
? IncrementalSource.Drag
|
|
1911
2261
|
: evt instanceof MouseEvent
|
|
1912
2262
|
? IncrementalSource.MouseMove
|
|
1913
2263
|
: IncrementalSource.TouchMove);
|
|
1914
|
-
}, threshold, {
|
|
2264
|
+
}), threshold, {
|
|
1915
2265
|
trailing: false,
|
|
1916
|
-
});
|
|
2266
|
+
}));
|
|
1917
2267
|
const handlers = [
|
|
1918
|
-
on('mousemove',
|
|
1919
|
-
on('touchmove',
|
|
1920
|
-
on('drag',
|
|
2268
|
+
on('mousemove', updatePosition, doc),
|
|
2269
|
+
on('touchmove', updatePosition, doc),
|
|
2270
|
+
on('drag', updatePosition, doc),
|
|
1921
2271
|
];
|
|
1922
2272
|
return callbackWrapper(() => {
|
|
1923
2273
|
handlers.forEach((h) => h());
|
|
@@ -1925,31 +2275,68 @@ function initMoveObserver({ mousemoveCb, sampling, doc, mirror, }) {
|
|
|
1925
2275
|
}
|
|
1926
2276
|
function initMouseInteractionObserver({ mouseInteractionCb, doc, mirror, blockClass, blockSelector, unblockSelector, sampling, }) {
|
|
1927
2277
|
if (sampling.mouseInteraction === false) {
|
|
1928
|
-
return () => {
|
|
1929
|
-
|
|
2278
|
+
return () => {
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
1930
2281
|
const disableMap = sampling.mouseInteraction === true ||
|
|
1931
2282
|
sampling.mouseInteraction === undefined
|
|
1932
2283
|
? {}
|
|
1933
2284
|
: sampling.mouseInteraction;
|
|
1934
2285
|
const handlers = [];
|
|
2286
|
+
let currentPointerType = null;
|
|
1935
2287
|
const getHandler = (eventKey) => {
|
|
1936
2288
|
return (event) => {
|
|
1937
2289
|
const target = getEventTarget(event);
|
|
1938
|
-
if (isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
2290
|
+
if (isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
|
|
1939
2291
|
return;
|
|
1940
2292
|
}
|
|
1941
|
-
|
|
2293
|
+
let pointerType = null;
|
|
2294
|
+
let thisEventKey = eventKey;
|
|
2295
|
+
if ('pointerType' in event) {
|
|
2296
|
+
switch (event.pointerType) {
|
|
2297
|
+
case 'mouse':
|
|
2298
|
+
pointerType = PointerTypes.Mouse;
|
|
2299
|
+
break;
|
|
2300
|
+
case 'touch':
|
|
2301
|
+
pointerType = PointerTypes.Touch;
|
|
2302
|
+
break;
|
|
2303
|
+
case 'pen':
|
|
2304
|
+
pointerType = PointerTypes.Pen;
|
|
2305
|
+
break;
|
|
2306
|
+
}
|
|
2307
|
+
if (pointerType === PointerTypes.Touch) {
|
|
2308
|
+
if (MouseInteractions[eventKey] === MouseInteractions.MouseDown) {
|
|
2309
|
+
thisEventKey = 'TouchStart';
|
|
2310
|
+
}
|
|
2311
|
+
else if (MouseInteractions[eventKey] === MouseInteractions.MouseUp) {
|
|
2312
|
+
thisEventKey = 'TouchEnd';
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
else if (pointerType === PointerTypes.Pen) ;
|
|
2316
|
+
}
|
|
2317
|
+
else if (legacy_isTouchEvent(event)) {
|
|
2318
|
+
pointerType = PointerTypes.Touch;
|
|
2319
|
+
}
|
|
2320
|
+
if (pointerType !== null) {
|
|
2321
|
+
currentPointerType = pointerType;
|
|
2322
|
+
if ((thisEventKey.startsWith('Touch') &&
|
|
2323
|
+
pointerType === PointerTypes.Touch) ||
|
|
2324
|
+
(thisEventKey.startsWith('Mouse') &&
|
|
2325
|
+
pointerType === PointerTypes.Mouse)) {
|
|
2326
|
+
pointerType = null;
|
|
2327
|
+
}
|
|
2328
|
+
}
|
|
2329
|
+
else if (MouseInteractions[eventKey] === MouseInteractions.Click) {
|
|
2330
|
+
pointerType = currentPointerType;
|
|
2331
|
+
currentPointerType = null;
|
|
2332
|
+
}
|
|
2333
|
+
const e = legacy_isTouchEvent(event) ? event.changedTouches[0] : event;
|
|
1942
2334
|
if (!e) {
|
|
1943
2335
|
return;
|
|
1944
2336
|
}
|
|
1945
2337
|
const id = mirror.getId(target);
|
|
1946
2338
|
const { clientX, clientY } = e;
|
|
1947
|
-
callbackWrapper(mouseInteractionCb)({
|
|
1948
|
-
type: MouseInteractions[eventKey],
|
|
1949
|
-
id,
|
|
1950
|
-
x: clientX,
|
|
1951
|
-
y: clientY,
|
|
1952
|
-
});
|
|
2339
|
+
callbackWrapper(mouseInteractionCb)(Object.assign({ type: MouseInteractions[thisEventKey], id, x: clientX, y: clientY }, (pointerType !== null && { pointerType })));
|
|
1953
2340
|
};
|
|
1954
2341
|
};
|
|
1955
2342
|
Object.keys(MouseInteractions)
|
|
@@ -1957,8 +2344,19 @@ function initMouseInteractionObserver({ mouseInteractionCb, doc, mirror, blockCl
|
|
|
1957
2344
|
!key.endsWith('_Departed') &&
|
|
1958
2345
|
disableMap[key] !== false)
|
|
1959
2346
|
.forEach((eventKey) => {
|
|
1960
|
-
|
|
1961
|
-
const handler =
|
|
2347
|
+
let eventName = toLowerCase(eventKey);
|
|
2348
|
+
const handler = getHandler(eventKey);
|
|
2349
|
+
if (window.PointerEvent) {
|
|
2350
|
+
switch (MouseInteractions[eventKey]) {
|
|
2351
|
+
case MouseInteractions.MouseDown:
|
|
2352
|
+
case MouseInteractions.MouseUp:
|
|
2353
|
+
eventName = eventName.replace('mouse', 'pointer');
|
|
2354
|
+
break;
|
|
2355
|
+
case MouseInteractions.TouchStart:
|
|
2356
|
+
case MouseInteractions.TouchEnd:
|
|
2357
|
+
return;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
1962
2360
|
handlers.push(on(eventName, handler, doc));
|
|
1963
2361
|
});
|
|
1964
2362
|
return callbackWrapper(() => {
|
|
@@ -1966,47 +2364,47 @@ function initMouseInteractionObserver({ mouseInteractionCb, doc, mirror, blockCl
|
|
|
1966
2364
|
});
|
|
1967
2365
|
}
|
|
1968
2366
|
function initScrollObserver({ scrollCb, doc, mirror, blockClass, blockSelector, unblockSelector, sampling, }) {
|
|
1969
|
-
const updatePosition = throttle$1((evt) => {
|
|
2367
|
+
const updatePosition = callbackWrapper(throttle$1(callbackWrapper((evt) => {
|
|
1970
2368
|
const target = getEventTarget(evt);
|
|
1971
2369
|
if (!target ||
|
|
1972
|
-
isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
2370
|
+
isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
|
|
1973
2371
|
return;
|
|
1974
2372
|
}
|
|
1975
2373
|
const id = mirror.getId(target);
|
|
1976
|
-
if (target === doc) {
|
|
1977
|
-
const
|
|
1978
|
-
|
|
2374
|
+
if (target === doc && doc.defaultView) {
|
|
2375
|
+
const scrollLeftTop = getWindowScroll(doc.defaultView);
|
|
2376
|
+
scrollCb({
|
|
1979
2377
|
id,
|
|
1980
|
-
x:
|
|
1981
|
-
y:
|
|
2378
|
+
x: scrollLeftTop.left,
|
|
2379
|
+
y: scrollLeftTop.top,
|
|
1982
2380
|
});
|
|
1983
2381
|
}
|
|
1984
2382
|
else {
|
|
1985
|
-
|
|
2383
|
+
scrollCb({
|
|
1986
2384
|
id,
|
|
1987
2385
|
x: target.scrollLeft,
|
|
1988
2386
|
y: target.scrollTop,
|
|
1989
2387
|
});
|
|
1990
2388
|
}
|
|
1991
|
-
}, sampling.scroll || 100);
|
|
1992
|
-
return on('scroll',
|
|
2389
|
+
}), sampling.scroll || 100));
|
|
2390
|
+
return on('scroll', updatePosition, doc);
|
|
1993
2391
|
}
|
|
1994
|
-
function initViewportResizeObserver({ viewportResizeCb, }) {
|
|
2392
|
+
function initViewportResizeObserver({ viewportResizeCb }, { win }) {
|
|
1995
2393
|
let lastH = -1;
|
|
1996
2394
|
let lastW = -1;
|
|
1997
|
-
const updateDimension = throttle$1(() => {
|
|
2395
|
+
const updateDimension = callbackWrapper(throttle$1(callbackWrapper(() => {
|
|
1998
2396
|
const height = getWindowHeight();
|
|
1999
2397
|
const width = getWindowWidth();
|
|
2000
2398
|
if (lastH !== height || lastW !== width) {
|
|
2001
|
-
|
|
2399
|
+
viewportResizeCb({
|
|
2002
2400
|
width: Number(width),
|
|
2003
2401
|
height: Number(height),
|
|
2004
2402
|
});
|
|
2005
2403
|
lastH = height;
|
|
2006
2404
|
lastW = width;
|
|
2007
2405
|
}
|
|
2008
|
-
}, 200);
|
|
2009
|
-
return on('resize',
|
|
2406
|
+
}), 200));
|
|
2407
|
+
return on('resize', updateDimension, win);
|
|
2010
2408
|
}
|
|
2011
2409
|
function wrapEventWithUserTriggeredFlag(v, enable) {
|
|
2012
2410
|
const value = Object.assign({}, v);
|
|
@@ -2016,47 +2414,42 @@ function wrapEventWithUserTriggeredFlag(v, enable) {
|
|
|
2016
2414
|
}
|
|
2017
2415
|
const INPUT_TAGS = ['INPUT', 'TEXTAREA', 'SELECT'];
|
|
2018
2416
|
const lastInputValueMap = new WeakMap();
|
|
2019
|
-
function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, unblockSelector, ignoreClass, ignoreSelector,
|
|
2417
|
+
function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, unblockSelector, ignoreClass, ignoreSelector, maskInputOptions, maskInputFn, sampling, userTriggeredOnInput, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, }) {
|
|
2020
2418
|
function eventHandler(event) {
|
|
2021
2419
|
let target = getEventTarget(event);
|
|
2022
|
-
const tagName = target && target.tagName;
|
|
2023
2420
|
const userTriggered = event.isTrusted;
|
|
2421
|
+
const tagName = target && toUpperCase(target.tagName);
|
|
2024
2422
|
if (tagName === 'OPTION')
|
|
2025
2423
|
target = target.parentElement;
|
|
2026
2424
|
if (!target ||
|
|
2027
2425
|
!tagName ||
|
|
2028
2426
|
INPUT_TAGS.indexOf(tagName) < 0 ||
|
|
2029
|
-
isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
2427
|
+
isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
|
|
2030
2428
|
return;
|
|
2031
2429
|
}
|
|
2032
2430
|
const el = target;
|
|
2033
|
-
const type = getInputType(el);
|
|
2034
2431
|
if (el.classList.contains(ignoreClass) ||
|
|
2035
2432
|
(ignoreSelector && el.matches(ignoreSelector))) {
|
|
2036
2433
|
return;
|
|
2037
2434
|
}
|
|
2435
|
+
const type = getInputType(target);
|
|
2038
2436
|
let text = getInputValue(el, tagName, type);
|
|
2039
2437
|
let isChecked = false;
|
|
2040
|
-
|
|
2041
|
-
isChecked = target.checked;
|
|
2042
|
-
}
|
|
2043
|
-
if (hasInputMaskOptions({
|
|
2438
|
+
const isInputMasked = shouldMaskInput({
|
|
2044
2439
|
maskInputOptions,
|
|
2045
|
-
maskInputSelector,
|
|
2046
2440
|
tagName,
|
|
2047
2441
|
type,
|
|
2048
|
-
})
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
maskInputSelector,
|
|
2053
|
-
unmaskInputSelector,
|
|
2054
|
-
tagName,
|
|
2055
|
-
type,
|
|
2056
|
-
value: text,
|
|
2057
|
-
maskInputFn,
|
|
2058
|
-
});
|
|
2442
|
+
});
|
|
2443
|
+
const forceMask = needMaskingText(target, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, isInputMasked);
|
|
2444
|
+
if (type === 'radio' || type === 'checkbox') {
|
|
2445
|
+
isChecked = target.checked;
|
|
2059
2446
|
}
|
|
2447
|
+
text = maskInputValue({
|
|
2448
|
+
isMasked: forceMask,
|
|
2449
|
+
element: target,
|
|
2450
|
+
value: text,
|
|
2451
|
+
maskInputFn,
|
|
2452
|
+
});
|
|
2060
2453
|
cbWithDedup(target, callbackWrapper(wrapEventWithUserTriggeredFlag)({ text, isChecked, userTriggered }, userTriggeredOnInput));
|
|
2061
2454
|
const name = target.name;
|
|
2062
2455
|
if (type === 'radio' && name && isChecked) {
|
|
@@ -2065,12 +2458,8 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
2065
2458
|
.forEach((el) => {
|
|
2066
2459
|
if (el !== target) {
|
|
2067
2460
|
const text = maskInputValue({
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
maskInputSelector,
|
|
2071
|
-
unmaskInputSelector,
|
|
2072
|
-
tagName,
|
|
2073
|
-
type,
|
|
2461
|
+
isMasked: forceMask,
|
|
2462
|
+
element: el,
|
|
2074
2463
|
value: getInputValue(el, tagName, type),
|
|
2075
2464
|
maskInputFn,
|
|
2076
2465
|
});
|
|
@@ -2090,26 +2479,35 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
|
|
|
2090
2479
|
lastInputValue.isChecked !== v.isChecked) {
|
|
2091
2480
|
lastInputValueMap.set(target, v);
|
|
2092
2481
|
const id = mirror.getId(target);
|
|
2093
|
-
inputCb(Object.assign(Object.assign({}, v), { id }));
|
|
2482
|
+
callbackWrapper(inputCb)(Object.assign(Object.assign({}, v), { id }));
|
|
2094
2483
|
}
|
|
2095
2484
|
}
|
|
2096
2485
|
const events = sampling.input === 'last' ? ['change'] : ['input', 'change'];
|
|
2097
2486
|
const handlers = events.map((eventName) => on(eventName, callbackWrapper(eventHandler), doc));
|
|
2098
|
-
const
|
|
2487
|
+
const currentWindow = doc.defaultView;
|
|
2488
|
+
if (!currentWindow) {
|
|
2489
|
+
return () => {
|
|
2490
|
+
handlers.forEach((h) => h());
|
|
2491
|
+
};
|
|
2492
|
+
}
|
|
2493
|
+
const propertyDescriptor = currentWindow.Object.getOwnPropertyDescriptor(currentWindow.HTMLInputElement.prototype, 'value');
|
|
2099
2494
|
const hookProperties = [
|
|
2100
|
-
[HTMLInputElement.prototype, 'value'],
|
|
2101
|
-
[HTMLInputElement.prototype, 'checked'],
|
|
2102
|
-
[HTMLSelectElement.prototype, 'value'],
|
|
2103
|
-
[HTMLTextAreaElement.prototype, 'value'],
|
|
2104
|
-
[HTMLSelectElement.prototype, 'selectedIndex'],
|
|
2105
|
-
[HTMLOptionElement.prototype, 'selected'],
|
|
2495
|
+
[currentWindow.HTMLInputElement.prototype, 'value'],
|
|
2496
|
+
[currentWindow.HTMLInputElement.prototype, 'checked'],
|
|
2497
|
+
[currentWindow.HTMLSelectElement.prototype, 'value'],
|
|
2498
|
+
[currentWindow.HTMLTextAreaElement.prototype, 'value'],
|
|
2499
|
+
[currentWindow.HTMLSelectElement.prototype, 'selectedIndex'],
|
|
2500
|
+
[currentWindow.HTMLOptionElement.prototype, 'selected'],
|
|
2106
2501
|
];
|
|
2107
2502
|
if (propertyDescriptor && propertyDescriptor.set) {
|
|
2108
2503
|
handlers.push(...hookProperties.map((p) => hookSetter(p[0], p[1], {
|
|
2109
2504
|
set() {
|
|
2110
|
-
callbackWrapper(eventHandler)({
|
|
2505
|
+
callbackWrapper(eventHandler)({
|
|
2506
|
+
target: this,
|
|
2507
|
+
isTrusted: false,
|
|
2508
|
+
});
|
|
2111
2509
|
},
|
|
2112
|
-
})));
|
|
2510
|
+
}, false, currentWindow)));
|
|
2113
2511
|
}
|
|
2114
2512
|
return callbackWrapper(() => {
|
|
2115
2513
|
handlers.forEach((h) => h());
|
|
@@ -2130,7 +2528,7 @@ function getNestedCSSRulePositions(rule) {
|
|
|
2130
2528
|
const index = rules.indexOf(childRule);
|
|
2131
2529
|
pos.unshift(index);
|
|
2132
2530
|
}
|
|
2133
|
-
else {
|
|
2531
|
+
else if (childRule.parentStyleSheet) {
|
|
2134
2532
|
const rules = Array.from(childRule.parentStyleSheet.cssRules);
|
|
2135
2533
|
const index = rules.indexOf(childRule);
|
|
2136
2534
|
pos.unshift(index);
|
|
@@ -2139,18 +2537,33 @@ function getNestedCSSRulePositions(rule) {
|
|
|
2139
2537
|
}
|
|
2140
2538
|
return recurse(rule, positions);
|
|
2141
2539
|
}
|
|
2142
|
-
function
|
|
2540
|
+
function getIdAndStyleId(sheet, mirror, styleMirror) {
|
|
2541
|
+
let id, styleId;
|
|
2542
|
+
if (!sheet)
|
|
2543
|
+
return {};
|
|
2544
|
+
if (sheet.ownerNode)
|
|
2545
|
+
id = mirror.getId(sheet.ownerNode);
|
|
2546
|
+
else
|
|
2547
|
+
styleId = styleMirror.getId(sheet);
|
|
2548
|
+
return {
|
|
2549
|
+
styleId,
|
|
2550
|
+
id,
|
|
2551
|
+
};
|
|
2552
|
+
}
|
|
2553
|
+
function initStyleSheetObserver({ styleSheetRuleCb, mirror, stylesheetManager }, { win }) {
|
|
2143
2554
|
if (!win.CSSStyleSheet || !win.CSSStyleSheet.prototype) {
|
|
2144
|
-
return () => {
|
|
2555
|
+
return () => {
|
|
2556
|
+
};
|
|
2145
2557
|
}
|
|
2146
2558
|
const insertRule = win.CSSStyleSheet.prototype.insertRule;
|
|
2147
2559
|
win.CSSStyleSheet.prototype.insertRule = new Proxy(insertRule, {
|
|
2148
2560
|
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2149
2561
|
const [rule, index] = argumentsList;
|
|
2150
|
-
const id =
|
|
2151
|
-
if (id !== -1) {
|
|
2562
|
+
const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
2563
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2152
2564
|
styleSheetRuleCb({
|
|
2153
2565
|
id,
|
|
2566
|
+
styleId,
|
|
2154
2567
|
adds: [{ rule, index }],
|
|
2155
2568
|
});
|
|
2156
2569
|
}
|
|
@@ -2161,16 +2574,53 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
|
|
|
2161
2574
|
win.CSSStyleSheet.prototype.deleteRule = new Proxy(deleteRule, {
|
|
2162
2575
|
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2163
2576
|
const [index] = argumentsList;
|
|
2164
|
-
const id =
|
|
2165
|
-
if (id !== -1) {
|
|
2577
|
+
const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
2578
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2166
2579
|
styleSheetRuleCb({
|
|
2167
2580
|
id,
|
|
2581
|
+
styleId,
|
|
2168
2582
|
removes: [{ index }],
|
|
2169
2583
|
});
|
|
2170
2584
|
}
|
|
2171
2585
|
return target.apply(thisArg, argumentsList);
|
|
2172
2586
|
}),
|
|
2173
2587
|
});
|
|
2588
|
+
let replace;
|
|
2589
|
+
if (win.CSSStyleSheet.prototype.replace) {
|
|
2590
|
+
replace = win.CSSStyleSheet.prototype.replace;
|
|
2591
|
+
win.CSSStyleSheet.prototype.replace = new Proxy(replace, {
|
|
2592
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2593
|
+
const [text] = argumentsList;
|
|
2594
|
+
const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
2595
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2596
|
+
styleSheetRuleCb({
|
|
2597
|
+
id,
|
|
2598
|
+
styleId,
|
|
2599
|
+
replace: text,
|
|
2600
|
+
});
|
|
2601
|
+
}
|
|
2602
|
+
return target.apply(thisArg, argumentsList);
|
|
2603
|
+
}),
|
|
2604
|
+
});
|
|
2605
|
+
}
|
|
2606
|
+
let replaceSync;
|
|
2607
|
+
if (win.CSSStyleSheet.prototype.replaceSync) {
|
|
2608
|
+
replaceSync = win.CSSStyleSheet.prototype.replaceSync;
|
|
2609
|
+
win.CSSStyleSheet.prototype.replaceSync = new Proxy(replaceSync, {
|
|
2610
|
+
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2611
|
+
const [text] = argumentsList;
|
|
2612
|
+
const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
|
|
2613
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2614
|
+
styleSheetRuleCb({
|
|
2615
|
+
id,
|
|
2616
|
+
styleId,
|
|
2617
|
+
replaceSync: text,
|
|
2618
|
+
});
|
|
2619
|
+
}
|
|
2620
|
+
return target.apply(thisArg, argumentsList);
|
|
2621
|
+
}),
|
|
2622
|
+
});
|
|
2623
|
+
}
|
|
2174
2624
|
const supportedNestedCSSRuleTypes = {};
|
|
2175
2625
|
if (canMonkeyPatchNestedCSSRule('CSSGroupingRule')) {
|
|
2176
2626
|
supportedNestedCSSRuleTypes.CSSGroupingRule = win.CSSGroupingRule;
|
|
@@ -2195,10 +2645,11 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
|
|
|
2195
2645
|
type.prototype.insertRule = new Proxy(unmodifiedFunctions[typeKey].insertRule, {
|
|
2196
2646
|
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2197
2647
|
const [rule, index] = argumentsList;
|
|
2198
|
-
const id =
|
|
2199
|
-
if (id !== -1) {
|
|
2648
|
+
const { id, styleId } = getIdAndStyleId(thisArg.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
2649
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2200
2650
|
styleSheetRuleCb({
|
|
2201
2651
|
id,
|
|
2652
|
+
styleId,
|
|
2202
2653
|
adds: [
|
|
2203
2654
|
{
|
|
2204
2655
|
rule,
|
|
@@ -2216,10 +2667,11 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
|
|
|
2216
2667
|
type.prototype.deleteRule = new Proxy(unmodifiedFunctions[typeKey].deleteRule, {
|
|
2217
2668
|
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2218
2669
|
const [index] = argumentsList;
|
|
2219
|
-
const id =
|
|
2220
|
-
if (id !== -1) {
|
|
2670
|
+
const { id, styleId } = getIdAndStyleId(thisArg.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
2671
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2221
2672
|
styleSheetRuleCb({
|
|
2222
2673
|
id,
|
|
2674
|
+
styleId,
|
|
2223
2675
|
removes: [
|
|
2224
2676
|
{ index: [...getNestedCSSRulePositions(thisArg), index] },
|
|
2225
2677
|
],
|
|
@@ -2232,22 +2684,74 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
|
|
|
2232
2684
|
return callbackWrapper(() => {
|
|
2233
2685
|
win.CSSStyleSheet.prototype.insertRule = insertRule;
|
|
2234
2686
|
win.CSSStyleSheet.prototype.deleteRule = deleteRule;
|
|
2687
|
+
replace && (win.CSSStyleSheet.prototype.replace = replace);
|
|
2688
|
+
replaceSync && (win.CSSStyleSheet.prototype.replaceSync = replaceSync);
|
|
2235
2689
|
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
|
|
2236
2690
|
type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
|
|
2237
2691
|
type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
|
|
2238
2692
|
});
|
|
2239
2693
|
});
|
|
2240
2694
|
}
|
|
2241
|
-
function
|
|
2695
|
+
function initAdoptedStyleSheetObserver({ mirror, stylesheetManager, }, host) {
|
|
2696
|
+
var _a, _b, _c;
|
|
2697
|
+
let hostId = null;
|
|
2698
|
+
if (host.nodeName === '#document')
|
|
2699
|
+
hostId = mirror.getId(host);
|
|
2700
|
+
else
|
|
2701
|
+
hostId = mirror.getId(host.host);
|
|
2702
|
+
const patchTarget = host.nodeName === '#document'
|
|
2703
|
+
? (_a = host.defaultView) === null || _a === void 0 ? void 0 : _a.Document
|
|
2704
|
+
: (_c = (_b = host.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView) === null || _c === void 0 ? void 0 : _c.ShadowRoot;
|
|
2705
|
+
const originalPropertyDescriptor = Object.getOwnPropertyDescriptor(patchTarget === null || patchTarget === void 0 ? void 0 : patchTarget.prototype, 'adoptedStyleSheets');
|
|
2706
|
+
if (hostId === null ||
|
|
2707
|
+
hostId === -1 ||
|
|
2708
|
+
!patchTarget ||
|
|
2709
|
+
!originalPropertyDescriptor)
|
|
2710
|
+
return () => {
|
|
2711
|
+
};
|
|
2712
|
+
Object.defineProperty(host, 'adoptedStyleSheets', {
|
|
2713
|
+
configurable: originalPropertyDescriptor.configurable,
|
|
2714
|
+
enumerable: originalPropertyDescriptor.enumerable,
|
|
2715
|
+
get() {
|
|
2716
|
+
var _a;
|
|
2717
|
+
return (_a = originalPropertyDescriptor.get) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
2718
|
+
},
|
|
2719
|
+
set(sheets) {
|
|
2720
|
+
var _a;
|
|
2721
|
+
const result = (_a = originalPropertyDescriptor.set) === null || _a === void 0 ? void 0 : _a.call(this, sheets);
|
|
2722
|
+
if (hostId !== null && hostId !== -1) {
|
|
2723
|
+
try {
|
|
2724
|
+
stylesheetManager.adoptStyleSheets(sheets, hostId);
|
|
2725
|
+
}
|
|
2726
|
+
catch (e) {
|
|
2727
|
+
}
|
|
2728
|
+
}
|
|
2729
|
+
return result;
|
|
2730
|
+
},
|
|
2731
|
+
});
|
|
2732
|
+
return callbackWrapper(() => {
|
|
2733
|
+
Object.defineProperty(host, 'adoptedStyleSheets', {
|
|
2734
|
+
configurable: originalPropertyDescriptor.configurable,
|
|
2735
|
+
enumerable: originalPropertyDescriptor.enumerable,
|
|
2736
|
+
get: originalPropertyDescriptor.get,
|
|
2737
|
+
set: originalPropertyDescriptor.set,
|
|
2738
|
+
});
|
|
2739
|
+
});
|
|
2740
|
+
}
|
|
2741
|
+
function initStyleDeclarationObserver({ styleDeclarationCb, mirror, ignoreCSSAttributes, stylesheetManager, }, { win }) {
|
|
2242
2742
|
const setProperty = win.CSSStyleDeclaration.prototype.setProperty;
|
|
2243
2743
|
win.CSSStyleDeclaration.prototype.setProperty = new Proxy(setProperty, {
|
|
2244
2744
|
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2245
|
-
var _a
|
|
2745
|
+
var _a;
|
|
2246
2746
|
const [property, value, priority] = argumentsList;
|
|
2247
|
-
|
|
2248
|
-
|
|
2747
|
+
if (ignoreCSSAttributes.has(property)) {
|
|
2748
|
+
return setProperty.apply(thisArg, [property, value, priority]);
|
|
2749
|
+
}
|
|
2750
|
+
const { id, styleId } = getIdAndStyleId((_a = thisArg.parentRule) === null || _a === void 0 ? void 0 : _a.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
2751
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2249
2752
|
styleDeclarationCb({
|
|
2250
2753
|
id,
|
|
2754
|
+
styleId,
|
|
2251
2755
|
set: {
|
|
2252
2756
|
property,
|
|
2253
2757
|
value,
|
|
@@ -2262,12 +2766,16 @@ function initStyleDeclarationObserver({ styleDeclarationCb, mirror }, { win }) {
|
|
|
2262
2766
|
const removeProperty = win.CSSStyleDeclaration.prototype.removeProperty;
|
|
2263
2767
|
win.CSSStyleDeclaration.prototype.removeProperty = new Proxy(removeProperty, {
|
|
2264
2768
|
apply: callbackWrapper((target, thisArg, argumentsList) => {
|
|
2265
|
-
var _a
|
|
2769
|
+
var _a;
|
|
2266
2770
|
const [property] = argumentsList;
|
|
2267
|
-
|
|
2268
|
-
|
|
2771
|
+
if (ignoreCSSAttributes.has(property)) {
|
|
2772
|
+
return removeProperty.apply(thisArg, [property]);
|
|
2773
|
+
}
|
|
2774
|
+
const { id, styleId } = getIdAndStyleId((_a = thisArg.parentRule) === null || _a === void 0 ? void 0 : _a.parentStyleSheet, mirror, stylesheetManager.styleMirror);
|
|
2775
|
+
if ((id && id !== -1) || (styleId && styleId !== -1)) {
|
|
2269
2776
|
styleDeclarationCb({
|
|
2270
2777
|
id,
|
|
2778
|
+
styleId,
|
|
2271
2779
|
remove: {
|
|
2272
2780
|
property,
|
|
2273
2781
|
},
|
|
@@ -2282,27 +2790,29 @@ function initStyleDeclarationObserver({ styleDeclarationCb, mirror }, { win }) {
|
|
|
2282
2790
|
win.CSSStyleDeclaration.prototype.removeProperty = removeProperty;
|
|
2283
2791
|
});
|
|
2284
2792
|
}
|
|
2285
|
-
function initMediaInteractionObserver({ mediaInteractionCb, blockClass, blockSelector, unblockSelector, mirror, sampling, }) {
|
|
2286
|
-
const handler = (type) => throttle$1(callbackWrapper((event) => {
|
|
2793
|
+
function initMediaInteractionObserver({ mediaInteractionCb, blockClass, blockSelector, unblockSelector, mirror, sampling, doc, }) {
|
|
2794
|
+
const handler = callbackWrapper((type) => throttle$1(callbackWrapper((event) => {
|
|
2287
2795
|
const target = getEventTarget(event);
|
|
2288
2796
|
if (!target ||
|
|
2289
|
-
isBlocked(target, blockClass, blockSelector, unblockSelector)) {
|
|
2797
|
+
isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
|
|
2290
2798
|
return;
|
|
2291
2799
|
}
|
|
2292
|
-
const { currentTime, volume, muted } = target;
|
|
2800
|
+
const { currentTime, volume, muted, playbackRate } = target;
|
|
2293
2801
|
mediaInteractionCb({
|
|
2294
2802
|
type,
|
|
2295
2803
|
id: mirror.getId(target),
|
|
2296
2804
|
currentTime,
|
|
2297
2805
|
volume,
|
|
2298
2806
|
muted,
|
|
2807
|
+
playbackRate,
|
|
2299
2808
|
});
|
|
2300
|
-
}), sampling.media || 500);
|
|
2809
|
+
}), sampling.media || 500));
|
|
2301
2810
|
const handlers = [
|
|
2302
|
-
on('play', handler(0)),
|
|
2303
|
-
on('pause', handler(1)),
|
|
2304
|
-
on('seeked', handler(2)),
|
|
2305
|
-
on('volumechange', handler(3)),
|
|
2811
|
+
on('play', handler(0), doc),
|
|
2812
|
+
on('pause', handler(1), doc),
|
|
2813
|
+
on('seeked', handler(2), doc),
|
|
2814
|
+
on('volumechange', handler(3), doc),
|
|
2815
|
+
on('ratechange', handler(4), doc),
|
|
2306
2816
|
];
|
|
2307
2817
|
return callbackWrapper(() => {
|
|
2308
2818
|
handlers.forEach((h) => h());
|
|
@@ -2311,7 +2821,8 @@ function initMediaInteractionObserver({ mediaInteractionCb, blockClass, blockSel
|
|
|
2311
2821
|
function initFontObserver({ fontCb, doc }) {
|
|
2312
2822
|
const win = doc.defaultView;
|
|
2313
2823
|
if (!win) {
|
|
2314
|
-
return () => {
|
|
2824
|
+
return () => {
|
|
2825
|
+
};
|
|
2315
2826
|
}
|
|
2316
2827
|
const handlers = [];
|
|
2317
2828
|
const fontMap = new WeakMap();
|
|
@@ -2324,20 +2835,19 @@ function initFontObserver({ fontCb, doc }) {
|
|
|
2324
2835
|
descriptors,
|
|
2325
2836
|
fontSource: typeof source === 'string'
|
|
2326
2837
|
? source
|
|
2327
|
-
:
|
|
2328
|
-
JSON.stringify(Array.from(new Uint8Array(source))),
|
|
2838
|
+
: JSON.stringify(Array.from(new Uint8Array(source))),
|
|
2329
2839
|
});
|
|
2330
2840
|
return fontFace;
|
|
2331
2841
|
};
|
|
2332
2842
|
const restoreHandler = patch(doc.fonts, 'add', function (original) {
|
|
2333
2843
|
return function (fontFace) {
|
|
2334
|
-
setTimeout(() => {
|
|
2844
|
+
setTimeout(callbackWrapper(() => {
|
|
2335
2845
|
const p = fontMap.get(fontFace);
|
|
2336
2846
|
if (p) {
|
|
2337
2847
|
fontCb(p);
|
|
2338
2848
|
fontMap.delete(fontFace);
|
|
2339
2849
|
}
|
|
2340
|
-
}, 0);
|
|
2850
|
+
}), 0);
|
|
2341
2851
|
return original.apply(this, [fontFace]);
|
|
2342
2852
|
};
|
|
2343
2853
|
});
|
|
@@ -2349,8 +2859,59 @@ function initFontObserver({ fontCb, doc }) {
|
|
|
2349
2859
|
handlers.forEach((h) => h());
|
|
2350
2860
|
});
|
|
2351
2861
|
}
|
|
2862
|
+
function initSelectionObserver(param) {
|
|
2863
|
+
const { doc, mirror, blockClass, blockSelector, unblockSelector, selectionCb, } = param;
|
|
2864
|
+
let collapsed = true;
|
|
2865
|
+
const updateSelection = callbackWrapper(() => {
|
|
2866
|
+
const selection = doc.getSelection();
|
|
2867
|
+
if (!selection || (collapsed && (selection === null || selection === void 0 ? void 0 : selection.isCollapsed)))
|
|
2868
|
+
return;
|
|
2869
|
+
collapsed = selection.isCollapsed || false;
|
|
2870
|
+
const ranges = [];
|
|
2871
|
+
const count = selection.rangeCount || 0;
|
|
2872
|
+
for (let i = 0; i < count; i++) {
|
|
2873
|
+
const range = selection.getRangeAt(i);
|
|
2874
|
+
const { startContainer, startOffset, endContainer, endOffset } = range;
|
|
2875
|
+
const blocked = isBlocked(startContainer, blockClass, blockSelector, unblockSelector, true) ||
|
|
2876
|
+
isBlocked(endContainer, blockClass, blockSelector, unblockSelector, true);
|
|
2877
|
+
if (blocked)
|
|
2878
|
+
continue;
|
|
2879
|
+
ranges.push({
|
|
2880
|
+
start: mirror.getId(startContainer),
|
|
2881
|
+
startOffset,
|
|
2882
|
+
end: mirror.getId(endContainer),
|
|
2883
|
+
endOffset,
|
|
2884
|
+
});
|
|
2885
|
+
}
|
|
2886
|
+
selectionCb({ ranges });
|
|
2887
|
+
});
|
|
2888
|
+
updateSelection();
|
|
2889
|
+
return on('selectionchange', updateSelection);
|
|
2890
|
+
}
|
|
2891
|
+
function initCustomElementObserver({ doc, customElementCb, }) {
|
|
2892
|
+
const win = doc.defaultView;
|
|
2893
|
+
if (!win || !win.customElements) {
|
|
2894
|
+
return () => {
|
|
2895
|
+
};
|
|
2896
|
+
}
|
|
2897
|
+
const restoreHandler = patch(win.customElements, 'define', function (original) {
|
|
2898
|
+
return function (name, constructor, options) {
|
|
2899
|
+
try {
|
|
2900
|
+
customElementCb({
|
|
2901
|
+
define: {
|
|
2902
|
+
name,
|
|
2903
|
+
},
|
|
2904
|
+
});
|
|
2905
|
+
}
|
|
2906
|
+
catch (e) {
|
|
2907
|
+
}
|
|
2908
|
+
return original.apply(this, [name, constructor, options]);
|
|
2909
|
+
};
|
|
2910
|
+
});
|
|
2911
|
+
return restoreHandler;
|
|
2912
|
+
}
|
|
2352
2913
|
function mergeHooks(o, hooks) {
|
|
2353
|
-
const { mutationCb, mousemoveCb, mouseInteractionCb, scrollCb, viewportResizeCb, inputCb, mediaInteractionCb, styleSheetRuleCb, styleDeclarationCb, canvasMutationCb, fontCb, } = o;
|
|
2914
|
+
const { mutationCb, mousemoveCb, mouseInteractionCb, scrollCb, viewportResizeCb, inputCb, mediaInteractionCb, styleSheetRuleCb, styleDeclarationCb, canvasMutationCb, fontCb, selectionCb, customElementCb, } = o;
|
|
2354
2915
|
o.mutationCb = (...p) => {
|
|
2355
2916
|
if (hooks.mutation) {
|
|
2356
2917
|
hooks.mutation(...p);
|
|
@@ -2417,25 +2978,46 @@ function mergeHooks(o, hooks) {
|
|
|
2417
2978
|
}
|
|
2418
2979
|
fontCb(...p);
|
|
2419
2980
|
};
|
|
2981
|
+
o.selectionCb = (...p) => {
|
|
2982
|
+
if (hooks.selection) {
|
|
2983
|
+
hooks.selection(...p);
|
|
2984
|
+
}
|
|
2985
|
+
selectionCb(...p);
|
|
2986
|
+
};
|
|
2987
|
+
o.customElementCb = (...c) => {
|
|
2988
|
+
if (hooks.customElement) {
|
|
2989
|
+
hooks.customElement(...c);
|
|
2990
|
+
}
|
|
2991
|
+
customElementCb(...c);
|
|
2992
|
+
};
|
|
2420
2993
|
}
|
|
2421
2994
|
function initObservers(o, hooks = {}) {
|
|
2422
2995
|
const currentWindow = o.doc.defaultView;
|
|
2423
2996
|
if (!currentWindow) {
|
|
2424
|
-
return () => {
|
|
2997
|
+
return () => {
|
|
2998
|
+
};
|
|
2425
2999
|
}
|
|
2426
3000
|
mergeHooks(o, hooks);
|
|
2427
3001
|
const mutationObserver = initMutationObserver(o, o.doc);
|
|
2428
3002
|
const mousemoveHandler = initMoveObserver(o);
|
|
2429
3003
|
const mouseInteractionHandler = initMouseInteractionObserver(o);
|
|
2430
3004
|
const scrollHandler = initScrollObserver(o);
|
|
2431
|
-
const viewportResizeHandler = initViewportResizeObserver(o
|
|
3005
|
+
const viewportResizeHandler = initViewportResizeObserver(o, {
|
|
3006
|
+
win: currentWindow,
|
|
3007
|
+
});
|
|
2432
3008
|
const inputHandler = initInputObserver(o);
|
|
2433
3009
|
const mediaInteractionHandler = initMediaInteractionObserver(o);
|
|
2434
3010
|
const styleSheetObserver = initStyleSheetObserver(o, { win: currentWindow });
|
|
3011
|
+
const adoptedStyleSheetObserver = initAdoptedStyleSheetObserver(o, o.doc);
|
|
2435
3012
|
const styleDeclarationObserver = initStyleDeclarationObserver(o, {
|
|
2436
3013
|
win: currentWindow,
|
|
2437
3014
|
});
|
|
2438
|
-
const fontObserver = o.collectFonts
|
|
3015
|
+
const fontObserver = o.collectFonts
|
|
3016
|
+
? initFontObserver(o)
|
|
3017
|
+
: () => {
|
|
3018
|
+
};
|
|
3019
|
+
const selectionObserver = initSelectionObserver(o);
|
|
3020
|
+
const customElementObserver = initCustomElementObserver(o);
|
|
2439
3021
|
const pluginHandlers = [];
|
|
2440
3022
|
for (const plugin of o.plugins) {
|
|
2441
3023
|
pluginHandlers.push(plugin.observer(plugin.callback, currentWindow, plugin.options));
|
|
@@ -2449,13 +3031,12 @@ function initObservers(o, hooks = {}) {
|
|
|
2449
3031
|
viewportResizeHandler();
|
|
2450
3032
|
inputHandler();
|
|
2451
3033
|
mediaInteractionHandler();
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
}
|
|
2456
|
-
catch (e) {
|
|
2457
|
-
}
|
|
3034
|
+
styleSheetObserver();
|
|
3035
|
+
adoptedStyleSheetObserver();
|
|
3036
|
+
styleDeclarationObserver();
|
|
2458
3037
|
fontObserver();
|
|
3038
|
+
selectionObserver();
|
|
3039
|
+
customElementObserver();
|
|
2459
3040
|
pluginHandlers.forEach((h) => h());
|
|
2460
3041
|
});
|
|
2461
3042
|
}
|
|
@@ -2469,13 +3050,88 @@ function canMonkeyPatchNestedCSSRule(prop) {
|
|
|
2469
3050
|
'deleteRule' in window[prop].prototype);
|
|
2470
3051
|
}
|
|
2471
3052
|
|
|
3053
|
+
class CrossOriginIframeMirror {
|
|
3054
|
+
constructor(generateIdFn) {
|
|
3055
|
+
this.generateIdFn = generateIdFn;
|
|
3056
|
+
this.iframeIdToRemoteIdMap = new WeakMap();
|
|
3057
|
+
this.iframeRemoteIdToIdMap = new WeakMap();
|
|
3058
|
+
}
|
|
3059
|
+
getId(iframe, remoteId, idToRemoteMap, remoteToIdMap) {
|
|
3060
|
+
const idToRemoteIdMap = idToRemoteMap || this.getIdToRemoteIdMap(iframe);
|
|
3061
|
+
const remoteIdToIdMap = remoteToIdMap || this.getRemoteIdToIdMap(iframe);
|
|
3062
|
+
let id = idToRemoteIdMap.get(remoteId);
|
|
3063
|
+
if (!id) {
|
|
3064
|
+
id = this.generateIdFn();
|
|
3065
|
+
idToRemoteIdMap.set(remoteId, id);
|
|
3066
|
+
remoteIdToIdMap.set(id, remoteId);
|
|
3067
|
+
}
|
|
3068
|
+
return id;
|
|
3069
|
+
}
|
|
3070
|
+
getIds(iframe, remoteId) {
|
|
3071
|
+
const idToRemoteIdMap = this.getIdToRemoteIdMap(iframe);
|
|
3072
|
+
const remoteIdToIdMap = this.getRemoteIdToIdMap(iframe);
|
|
3073
|
+
return remoteId.map((id) => this.getId(iframe, id, idToRemoteIdMap, remoteIdToIdMap));
|
|
3074
|
+
}
|
|
3075
|
+
getRemoteId(iframe, id, map) {
|
|
3076
|
+
const remoteIdToIdMap = map || this.getRemoteIdToIdMap(iframe);
|
|
3077
|
+
if (typeof id !== 'number')
|
|
3078
|
+
return id;
|
|
3079
|
+
const remoteId = remoteIdToIdMap.get(id);
|
|
3080
|
+
if (!remoteId)
|
|
3081
|
+
return -1;
|
|
3082
|
+
return remoteId;
|
|
3083
|
+
}
|
|
3084
|
+
getRemoteIds(iframe, ids) {
|
|
3085
|
+
const remoteIdToIdMap = this.getRemoteIdToIdMap(iframe);
|
|
3086
|
+
return ids.map((id) => this.getRemoteId(iframe, id, remoteIdToIdMap));
|
|
3087
|
+
}
|
|
3088
|
+
reset(iframe) {
|
|
3089
|
+
if (!iframe) {
|
|
3090
|
+
this.iframeIdToRemoteIdMap = new WeakMap();
|
|
3091
|
+
this.iframeRemoteIdToIdMap = new WeakMap();
|
|
3092
|
+
return;
|
|
3093
|
+
}
|
|
3094
|
+
this.iframeIdToRemoteIdMap.delete(iframe);
|
|
3095
|
+
this.iframeRemoteIdToIdMap.delete(iframe);
|
|
3096
|
+
}
|
|
3097
|
+
getIdToRemoteIdMap(iframe) {
|
|
3098
|
+
let idToRemoteIdMap = this.iframeIdToRemoteIdMap.get(iframe);
|
|
3099
|
+
if (!idToRemoteIdMap) {
|
|
3100
|
+
idToRemoteIdMap = new Map();
|
|
3101
|
+
this.iframeIdToRemoteIdMap.set(iframe, idToRemoteIdMap);
|
|
3102
|
+
}
|
|
3103
|
+
return idToRemoteIdMap;
|
|
3104
|
+
}
|
|
3105
|
+
getRemoteIdToIdMap(iframe) {
|
|
3106
|
+
let remoteIdToIdMap = this.iframeRemoteIdToIdMap.get(iframe);
|
|
3107
|
+
if (!remoteIdToIdMap) {
|
|
3108
|
+
remoteIdToIdMap = new Map();
|
|
3109
|
+
this.iframeRemoteIdToIdMap.set(iframe, remoteIdToIdMap);
|
|
3110
|
+
}
|
|
3111
|
+
return remoteIdToIdMap;
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
|
|
2472
3115
|
class IframeManager {
|
|
2473
3116
|
constructor(options) {
|
|
2474
3117
|
this.iframes = new WeakMap();
|
|
3118
|
+
this.crossOriginIframeMap = new WeakMap();
|
|
3119
|
+
this.crossOriginIframeMirror = new CrossOriginIframeMirror(genId);
|
|
3120
|
+
this.crossOriginIframeRootIdMap = new WeakMap();
|
|
2475
3121
|
this.mutationCb = options.mutationCb;
|
|
3122
|
+
this.wrappedEmit = options.wrappedEmit;
|
|
3123
|
+
this.stylesheetManager = options.stylesheetManager;
|
|
3124
|
+
this.recordCrossOriginIframes = options.recordCrossOriginIframes;
|
|
3125
|
+
this.crossOriginIframeStyleMirror = new CrossOriginIframeMirror(this.stylesheetManager.styleMirror.generateId.bind(this.stylesheetManager.styleMirror));
|
|
3126
|
+
this.mirror = options.mirror;
|
|
3127
|
+
if (this.recordCrossOriginIframes) {
|
|
3128
|
+
window.addEventListener('message', this.handleMessage.bind(this));
|
|
3129
|
+
}
|
|
2476
3130
|
}
|
|
2477
3131
|
addIframe(iframeEl) {
|
|
2478
3132
|
this.iframes.set(iframeEl, true);
|
|
3133
|
+
if (iframeEl.contentWindow)
|
|
3134
|
+
this.crossOriginIframeMap.set(iframeEl.contentWindow, iframeEl);
|
|
2479
3135
|
}
|
|
2480
3136
|
addLoadListener(cb) {
|
|
2481
3137
|
this.loadListener = cb;
|
|
@@ -2485,7 +3141,7 @@ class IframeManager {
|
|
|
2485
3141
|
this.mutationCb({
|
|
2486
3142
|
adds: [
|
|
2487
3143
|
{
|
|
2488
|
-
parentId:
|
|
3144
|
+
parentId: this.mirror.getId(iframeEl),
|
|
2489
3145
|
nextId: null,
|
|
2490
3146
|
node: childSn,
|
|
2491
3147
|
},
|
|
@@ -2496,49 +3152,239 @@ class IframeManager {
|
|
|
2496
3152
|
isAttachIframe: true,
|
|
2497
3153
|
});
|
|
2498
3154
|
(_a = this.loadListener) === null || _a === void 0 ? void 0 : _a.call(this, iframeEl);
|
|
3155
|
+
if (iframeEl.contentDocument &&
|
|
3156
|
+
iframeEl.contentDocument.adoptedStyleSheets &&
|
|
3157
|
+
iframeEl.contentDocument.adoptedStyleSheets.length > 0)
|
|
3158
|
+
this.stylesheetManager.adoptStyleSheets(iframeEl.contentDocument.adoptedStyleSheets, this.mirror.getId(iframeEl.contentDocument));
|
|
3159
|
+
}
|
|
3160
|
+
handleMessage(message) {
|
|
3161
|
+
const crossOriginMessageEvent = message;
|
|
3162
|
+
if (crossOriginMessageEvent.data.type !== 'rrweb' ||
|
|
3163
|
+
crossOriginMessageEvent.origin !== crossOriginMessageEvent.data.origin)
|
|
3164
|
+
return;
|
|
3165
|
+
const iframeSourceWindow = message.source;
|
|
3166
|
+
if (!iframeSourceWindow)
|
|
3167
|
+
return;
|
|
3168
|
+
const iframeEl = this.crossOriginIframeMap.get(message.source);
|
|
3169
|
+
if (!iframeEl)
|
|
3170
|
+
return;
|
|
3171
|
+
const transformedEvent = this.transformCrossOriginEvent(iframeEl, crossOriginMessageEvent.data.event);
|
|
3172
|
+
if (transformedEvent)
|
|
3173
|
+
this.wrappedEmit(transformedEvent, crossOriginMessageEvent.data.isCheckout);
|
|
3174
|
+
}
|
|
3175
|
+
transformCrossOriginEvent(iframeEl, e) {
|
|
3176
|
+
var _a;
|
|
3177
|
+
switch (e.type) {
|
|
3178
|
+
case EventType.FullSnapshot: {
|
|
3179
|
+
this.crossOriginIframeMirror.reset(iframeEl);
|
|
3180
|
+
this.crossOriginIframeStyleMirror.reset(iframeEl);
|
|
3181
|
+
this.replaceIdOnNode(e.data.node, iframeEl);
|
|
3182
|
+
const rootId = e.data.node.id;
|
|
3183
|
+
this.crossOriginIframeRootIdMap.set(iframeEl, rootId);
|
|
3184
|
+
this.patchRootIdOnNode(e.data.node, rootId);
|
|
3185
|
+
return {
|
|
3186
|
+
timestamp: e.timestamp,
|
|
3187
|
+
type: EventType.IncrementalSnapshot,
|
|
3188
|
+
data: {
|
|
3189
|
+
source: IncrementalSource.Mutation,
|
|
3190
|
+
adds: [
|
|
3191
|
+
{
|
|
3192
|
+
parentId: this.mirror.getId(iframeEl),
|
|
3193
|
+
nextId: null,
|
|
3194
|
+
node: e.data.node,
|
|
3195
|
+
},
|
|
3196
|
+
],
|
|
3197
|
+
removes: [],
|
|
3198
|
+
texts: [],
|
|
3199
|
+
attributes: [],
|
|
3200
|
+
isAttachIframe: true,
|
|
3201
|
+
},
|
|
3202
|
+
};
|
|
3203
|
+
}
|
|
3204
|
+
case EventType.Meta:
|
|
3205
|
+
case EventType.Load:
|
|
3206
|
+
case EventType.DomContentLoaded: {
|
|
3207
|
+
return false;
|
|
3208
|
+
}
|
|
3209
|
+
case EventType.Plugin: {
|
|
3210
|
+
return e;
|
|
3211
|
+
}
|
|
3212
|
+
case EventType.Custom: {
|
|
3213
|
+
this.replaceIds(e.data.payload, iframeEl, ['id', 'parentId', 'previousId', 'nextId']);
|
|
3214
|
+
return e;
|
|
3215
|
+
}
|
|
3216
|
+
case EventType.IncrementalSnapshot: {
|
|
3217
|
+
switch (e.data.source) {
|
|
3218
|
+
case IncrementalSource.Mutation: {
|
|
3219
|
+
e.data.adds.forEach((n) => {
|
|
3220
|
+
this.replaceIds(n, iframeEl, [
|
|
3221
|
+
'parentId',
|
|
3222
|
+
'nextId',
|
|
3223
|
+
'previousId',
|
|
3224
|
+
]);
|
|
3225
|
+
this.replaceIdOnNode(n.node, iframeEl);
|
|
3226
|
+
const rootId = this.crossOriginIframeRootIdMap.get(iframeEl);
|
|
3227
|
+
rootId && this.patchRootIdOnNode(n.node, rootId);
|
|
3228
|
+
});
|
|
3229
|
+
e.data.removes.forEach((n) => {
|
|
3230
|
+
this.replaceIds(n, iframeEl, ['parentId', 'id']);
|
|
3231
|
+
});
|
|
3232
|
+
e.data.attributes.forEach((n) => {
|
|
3233
|
+
this.replaceIds(n, iframeEl, ['id']);
|
|
3234
|
+
});
|
|
3235
|
+
e.data.texts.forEach((n) => {
|
|
3236
|
+
this.replaceIds(n, iframeEl, ['id']);
|
|
3237
|
+
});
|
|
3238
|
+
return e;
|
|
3239
|
+
}
|
|
3240
|
+
case IncrementalSource.Drag:
|
|
3241
|
+
case IncrementalSource.TouchMove:
|
|
3242
|
+
case IncrementalSource.MouseMove: {
|
|
3243
|
+
e.data.positions.forEach((p) => {
|
|
3244
|
+
this.replaceIds(p, iframeEl, ['id']);
|
|
3245
|
+
});
|
|
3246
|
+
return e;
|
|
3247
|
+
}
|
|
3248
|
+
case IncrementalSource.ViewportResize: {
|
|
3249
|
+
return false;
|
|
3250
|
+
}
|
|
3251
|
+
case IncrementalSource.MediaInteraction:
|
|
3252
|
+
case IncrementalSource.MouseInteraction:
|
|
3253
|
+
case IncrementalSource.Scroll:
|
|
3254
|
+
case IncrementalSource.CanvasMutation:
|
|
3255
|
+
case IncrementalSource.Input: {
|
|
3256
|
+
this.replaceIds(e.data, iframeEl, ['id']);
|
|
3257
|
+
return e;
|
|
3258
|
+
}
|
|
3259
|
+
case IncrementalSource.StyleSheetRule:
|
|
3260
|
+
case IncrementalSource.StyleDeclaration: {
|
|
3261
|
+
this.replaceIds(e.data, iframeEl, ['id']);
|
|
3262
|
+
this.replaceStyleIds(e.data, iframeEl, ['styleId']);
|
|
3263
|
+
return e;
|
|
3264
|
+
}
|
|
3265
|
+
case IncrementalSource.Font: {
|
|
3266
|
+
return e;
|
|
3267
|
+
}
|
|
3268
|
+
case IncrementalSource.Selection: {
|
|
3269
|
+
e.data.ranges.forEach((range) => {
|
|
3270
|
+
this.replaceIds(range, iframeEl, ['start', 'end']);
|
|
3271
|
+
});
|
|
3272
|
+
return e;
|
|
3273
|
+
}
|
|
3274
|
+
case IncrementalSource.AdoptedStyleSheet: {
|
|
3275
|
+
this.replaceIds(e.data, iframeEl, ['id']);
|
|
3276
|
+
this.replaceStyleIds(e.data, iframeEl, ['styleIds']);
|
|
3277
|
+
(_a = e.data.styles) === null || _a === void 0 ? void 0 : _a.forEach((style) => {
|
|
3278
|
+
this.replaceStyleIds(style, iframeEl, ['styleId']);
|
|
3279
|
+
});
|
|
3280
|
+
return e;
|
|
3281
|
+
}
|
|
3282
|
+
}
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
return false;
|
|
3286
|
+
}
|
|
3287
|
+
replace(iframeMirror, obj, iframeEl, keys) {
|
|
3288
|
+
for (const key of keys) {
|
|
3289
|
+
if (!Array.isArray(obj[key]) && typeof obj[key] !== 'number')
|
|
3290
|
+
continue;
|
|
3291
|
+
if (Array.isArray(obj[key])) {
|
|
3292
|
+
obj[key] = iframeMirror.getIds(iframeEl, obj[key]);
|
|
3293
|
+
}
|
|
3294
|
+
else {
|
|
3295
|
+
obj[key] = iframeMirror.getId(iframeEl, obj[key]);
|
|
3296
|
+
}
|
|
3297
|
+
}
|
|
3298
|
+
return obj;
|
|
3299
|
+
}
|
|
3300
|
+
replaceIds(obj, iframeEl, keys) {
|
|
3301
|
+
return this.replace(this.crossOriginIframeMirror, obj, iframeEl, keys);
|
|
3302
|
+
}
|
|
3303
|
+
replaceStyleIds(obj, iframeEl, keys) {
|
|
3304
|
+
return this.replace(this.crossOriginIframeStyleMirror, obj, iframeEl, keys);
|
|
3305
|
+
}
|
|
3306
|
+
replaceIdOnNode(node, iframeEl) {
|
|
3307
|
+
this.replaceIds(node, iframeEl, ['id', 'rootId']);
|
|
3308
|
+
if ('childNodes' in node) {
|
|
3309
|
+
node.childNodes.forEach((child) => {
|
|
3310
|
+
this.replaceIdOnNode(child, iframeEl);
|
|
3311
|
+
});
|
|
3312
|
+
}
|
|
3313
|
+
}
|
|
3314
|
+
patchRootIdOnNode(node, rootId) {
|
|
3315
|
+
if (node.type !== NodeType$1.Document && !node.rootId)
|
|
3316
|
+
node.rootId = rootId;
|
|
3317
|
+
if ('childNodes' in node) {
|
|
3318
|
+
node.childNodes.forEach((child) => {
|
|
3319
|
+
this.patchRootIdOnNode(child, rootId);
|
|
3320
|
+
});
|
|
3321
|
+
}
|
|
2499
3322
|
}
|
|
2500
3323
|
}
|
|
2501
3324
|
|
|
2502
3325
|
class ShadowDomManager {
|
|
2503
3326
|
constructor(options) {
|
|
2504
|
-
this.
|
|
3327
|
+
this.shadowDoms = new WeakSet();
|
|
3328
|
+
this.restoreHandlers = [];
|
|
2505
3329
|
this.mutationCb = options.mutationCb;
|
|
2506
3330
|
this.scrollCb = options.scrollCb;
|
|
2507
3331
|
this.bypassOptions = options.bypassOptions;
|
|
2508
3332
|
this.mirror = options.mirror;
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
manager.addShadowRoot(this.shadowRoot, this.ownerDocument);
|
|
2515
|
-
return shadowRoot;
|
|
2516
|
-
};
|
|
2517
|
-
}));
|
|
3333
|
+
this.init();
|
|
3334
|
+
}
|
|
3335
|
+
init() {
|
|
3336
|
+
this.reset();
|
|
3337
|
+
this.patchAttachShadow(Element, document);
|
|
2518
3338
|
}
|
|
2519
3339
|
addShadowRoot(shadowRoot, doc) {
|
|
2520
|
-
|
|
2521
|
-
|
|
3340
|
+
if (!isNativeShadowDom(shadowRoot))
|
|
3341
|
+
return;
|
|
3342
|
+
if (this.shadowDoms.has(shadowRoot))
|
|
3343
|
+
return;
|
|
3344
|
+
this.shadowDoms.add(shadowRoot);
|
|
3345
|
+
const observer = initMutationObserver(Object.assign(Object.assign({}, this.bypassOptions), { doc, mutationCb: this.mutationCb, mirror: this.mirror, shadowDomManager: this }), shadowRoot);
|
|
3346
|
+
this.restoreHandlers.push(() => observer.disconnect());
|
|
3347
|
+
this.restoreHandlers.push(initScrollObserver(Object.assign(Object.assign({}, this.bypassOptions), { scrollCb: this.scrollCb, doc: shadowRoot, mirror: this.mirror })));
|
|
3348
|
+
setTimeout(() => {
|
|
3349
|
+
if (shadowRoot.adoptedStyleSheets &&
|
|
3350
|
+
shadowRoot.adoptedStyleSheets.length > 0)
|
|
3351
|
+
this.bypassOptions.stylesheetManager.adoptStyleSheets(shadowRoot.adoptedStyleSheets, this.mirror.getId(shadowRoot.host));
|
|
3352
|
+
this.restoreHandlers.push(initAdoptedStyleSheetObserver({
|
|
3353
|
+
mirror: this.mirror,
|
|
3354
|
+
stylesheetManager: this.bypassOptions.stylesheetManager,
|
|
3355
|
+
}, shadowRoot));
|
|
3356
|
+
}, 0);
|
|
2522
3357
|
}
|
|
2523
3358
|
observeAttachShadow(iframeElement) {
|
|
2524
|
-
if (iframeElement.contentWindow)
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
3359
|
+
if (!iframeElement.contentWindow || !iframeElement.contentDocument)
|
|
3360
|
+
return;
|
|
3361
|
+
this.patchAttachShadow(iframeElement.contentWindow.Element, iframeElement.contentDocument);
|
|
3362
|
+
}
|
|
3363
|
+
patchAttachShadow(element, doc) {
|
|
3364
|
+
const manager = this;
|
|
3365
|
+
this.restoreHandlers.push(patch(element.prototype, 'attachShadow', function (original) {
|
|
3366
|
+
return function (option) {
|
|
3367
|
+
const shadowRoot = original.call(this, option);
|
|
3368
|
+
if (this.shadowRoot && inDom(this))
|
|
3369
|
+
manager.addShadowRoot(this.shadowRoot, doc);
|
|
3370
|
+
return shadowRoot;
|
|
3371
|
+
};
|
|
3372
|
+
}));
|
|
2535
3373
|
}
|
|
2536
3374
|
reset() {
|
|
2537
|
-
this.
|
|
3375
|
+
this.restoreHandlers.forEach((handler) => {
|
|
3376
|
+
try {
|
|
3377
|
+
handler();
|
|
3378
|
+
}
|
|
3379
|
+
catch (e) {
|
|
3380
|
+
}
|
|
3381
|
+
});
|
|
3382
|
+
this.restoreHandlers = [];
|
|
3383
|
+
this.shadowDoms = new WeakSet();
|
|
2538
3384
|
}
|
|
2539
3385
|
}
|
|
2540
3386
|
|
|
2541
|
-
|
|
3387
|
+
/*! *****************************************************************************
|
|
2542
3388
|
Copyright (c) Microsoft Corporation.
|
|
2543
3389
|
|
|
2544
3390
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
@@ -2565,85 +3411,19 @@ function __rest(s, e) {
|
|
|
2565
3411
|
return t;
|
|
2566
3412
|
}
|
|
2567
3413
|
|
|
2568
|
-
function
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
try {
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
const restoreHandler = patch(win.CanvasRenderingContext2D.prototype, prop, function (original) {
|
|
2577
|
-
return function (...args) {
|
|
2578
|
-
if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector)) {
|
|
2579
|
-
setTimeout(() => {
|
|
2580
|
-
const recordArgs = [...args];
|
|
2581
|
-
if (prop === 'drawImage') {
|
|
2582
|
-
if (recordArgs[0] &&
|
|
2583
|
-
recordArgs[0] instanceof HTMLCanvasElement) {
|
|
2584
|
-
const canvas = recordArgs[0];
|
|
2585
|
-
const ctx = canvas.getContext('2d');
|
|
2586
|
-
let imgd = ctx === null || ctx === void 0 ? void 0 : ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
2587
|
-
let pix = imgd === null || imgd === void 0 ? void 0 : imgd.data;
|
|
2588
|
-
recordArgs[0] = JSON.stringify(pix);
|
|
2589
|
-
}
|
|
2590
|
-
}
|
|
2591
|
-
cb(this.canvas, {
|
|
2592
|
-
type: CanvasContext['2D'],
|
|
2593
|
-
property: prop,
|
|
2594
|
-
args: recordArgs,
|
|
2595
|
-
});
|
|
2596
|
-
}, 0);
|
|
2597
|
-
}
|
|
2598
|
-
return original.apply(this, args);
|
|
2599
|
-
};
|
|
2600
|
-
});
|
|
2601
|
-
handlers.push(restoreHandler);
|
|
2602
|
-
}
|
|
2603
|
-
catch (_a) {
|
|
2604
|
-
const hookHandler = hookSetter(win.CanvasRenderingContext2D.prototype, prop, {
|
|
2605
|
-
set(v) {
|
|
2606
|
-
cb(this.canvas, {
|
|
2607
|
-
type: CanvasContext['2D'],
|
|
2608
|
-
property: prop,
|
|
2609
|
-
args: [v],
|
|
2610
|
-
setter: true,
|
|
2611
|
-
});
|
|
2612
|
-
},
|
|
2613
|
-
});
|
|
2614
|
-
handlers.push(hookHandler);
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
return () => {
|
|
2618
|
-
handlers.forEach((h) => h());
|
|
2619
|
-
};
|
|
2620
|
-
}
|
|
2621
|
-
|
|
2622
|
-
function initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector) {
|
|
2623
|
-
const handlers = [];
|
|
2624
|
-
try {
|
|
2625
|
-
const restoreHandler = patch(win.HTMLCanvasElement.prototype, 'getContext', function (original) {
|
|
2626
|
-
return function (contextType, ...args) {
|
|
2627
|
-
if (!isBlocked(this, blockClass, blockSelector, unblockSelector)) {
|
|
2628
|
-
if (!('__context' in this))
|
|
2629
|
-
this.__context = contextType;
|
|
2630
|
-
}
|
|
2631
|
-
return original.apply(this, [contextType, ...args]);
|
|
2632
|
-
};
|
|
2633
|
-
});
|
|
2634
|
-
handlers.push(restoreHandler);
|
|
2635
|
-
}
|
|
2636
|
-
catch (_a) {
|
|
2637
|
-
console.error('failed to patch HTMLCanvasElement.prototype.getContext');
|
|
2638
|
-
}
|
|
2639
|
-
return () => {
|
|
2640
|
-
handlers.forEach((h) => h());
|
|
2641
|
-
};
|
|
3414
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
3415
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3416
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
3417
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
3418
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
3419
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
3420
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
3421
|
+
});
|
|
2642
3422
|
}
|
|
2643
3423
|
|
|
2644
3424
|
/*
|
|
2645
|
-
* base64-arraybuffer 1.0.
|
|
2646
|
-
* Copyright (c)
|
|
3425
|
+
* base64-arraybuffer 1.0.1 <https://github.com/niklasvh/base64-arraybuffer>
|
|
3426
|
+
* Copyright (c) 2021 Niklas von Hertzen <https://hertzen.com>
|
|
2647
3427
|
* Released under MIT License
|
|
2648
3428
|
*/
|
|
2649
3429
|
var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
|
@@ -2669,12 +3449,12 @@ var encode = function (arraybuffer) {
|
|
|
2669
3449
|
return base64;
|
|
2670
3450
|
};
|
|
2671
3451
|
|
|
2672
|
-
const
|
|
3452
|
+
const canvasVarMap = new Map();
|
|
2673
3453
|
function variableListFor(ctx, ctor) {
|
|
2674
|
-
let contextMap =
|
|
3454
|
+
let contextMap = canvasVarMap.get(ctx);
|
|
2675
3455
|
if (!contextMap) {
|
|
2676
3456
|
contextMap = new Map();
|
|
2677
|
-
|
|
3457
|
+
canvasVarMap.set(ctx, contextMap);
|
|
2678
3458
|
}
|
|
2679
3459
|
if (!contextMap.has(ctor)) {
|
|
2680
3460
|
contextMap.set(ctor, []);
|
|
@@ -2743,6 +3523,14 @@ function serializeArg(value, win, ctx) {
|
|
|
2743
3523
|
src,
|
|
2744
3524
|
};
|
|
2745
3525
|
}
|
|
3526
|
+
else if (value instanceof HTMLCanvasElement) {
|
|
3527
|
+
const name = 'HTMLImageElement';
|
|
3528
|
+
const src = value.toDataURL();
|
|
3529
|
+
return {
|
|
3530
|
+
rr_type: name,
|
|
3531
|
+
src,
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
2746
3534
|
else if (value instanceof ImageData) {
|
|
2747
3535
|
const name = value.constructor.name;
|
|
2748
3536
|
return {
|
|
@@ -2758,33 +3546,125 @@ function serializeArg(value, win, ctx) {
|
|
|
2758
3546
|
index: index,
|
|
2759
3547
|
};
|
|
2760
3548
|
}
|
|
2761
|
-
return value;
|
|
3549
|
+
return value;
|
|
3550
|
+
}
|
|
3551
|
+
const serializeArgs = (args, win, ctx) => {
|
|
3552
|
+
return [...args].map((arg) => serializeArg(arg, win, ctx));
|
|
3553
|
+
};
|
|
3554
|
+
const isInstanceOfWebGLObject = (value, win) => {
|
|
3555
|
+
const webGLConstructorNames = [
|
|
3556
|
+
'WebGLActiveInfo',
|
|
3557
|
+
'WebGLBuffer',
|
|
3558
|
+
'WebGLFramebuffer',
|
|
3559
|
+
'WebGLProgram',
|
|
3560
|
+
'WebGLRenderbuffer',
|
|
3561
|
+
'WebGLShader',
|
|
3562
|
+
'WebGLShaderPrecisionFormat',
|
|
3563
|
+
'WebGLTexture',
|
|
3564
|
+
'WebGLUniformLocation',
|
|
3565
|
+
'WebGLVertexArrayObject',
|
|
3566
|
+
'WebGLVertexArrayObjectOES',
|
|
3567
|
+
];
|
|
3568
|
+
const supportedWebGLConstructorNames = webGLConstructorNames.filter((name) => typeof win[name] === 'function');
|
|
3569
|
+
return Boolean(supportedWebGLConstructorNames.find((name) => value instanceof win[name]));
|
|
3570
|
+
};
|
|
3571
|
+
|
|
3572
|
+
function initCanvas2DMutationObserver(cb, win, blockClass, blockSelector, unblockSelector) {
|
|
3573
|
+
const handlers = [];
|
|
3574
|
+
const props2D = Object.getOwnPropertyNames(win.CanvasRenderingContext2D.prototype);
|
|
3575
|
+
for (const prop of props2D) {
|
|
3576
|
+
try {
|
|
3577
|
+
if (typeof win.CanvasRenderingContext2D.prototype[prop] !== 'function') {
|
|
3578
|
+
continue;
|
|
3579
|
+
}
|
|
3580
|
+
const restoreHandler = patch(win.CanvasRenderingContext2D.prototype, prop, function (original) {
|
|
3581
|
+
return function (...args) {
|
|
3582
|
+
if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector, true)) {
|
|
3583
|
+
setTimeout(() => {
|
|
3584
|
+
const recordArgs = serializeArgs([...args], win, this);
|
|
3585
|
+
cb(this.canvas, {
|
|
3586
|
+
type: CanvasContext['2D'],
|
|
3587
|
+
property: prop,
|
|
3588
|
+
args: recordArgs,
|
|
3589
|
+
});
|
|
3590
|
+
}, 0);
|
|
3591
|
+
}
|
|
3592
|
+
return original.apply(this, args);
|
|
3593
|
+
};
|
|
3594
|
+
});
|
|
3595
|
+
handlers.push(restoreHandler);
|
|
3596
|
+
}
|
|
3597
|
+
catch (_a) {
|
|
3598
|
+
const hookHandler = hookSetter(win.CanvasRenderingContext2D.prototype, prop, {
|
|
3599
|
+
set(v) {
|
|
3600
|
+
cb(this.canvas, {
|
|
3601
|
+
type: CanvasContext['2D'],
|
|
3602
|
+
property: prop,
|
|
3603
|
+
args: [v],
|
|
3604
|
+
setter: true,
|
|
3605
|
+
});
|
|
3606
|
+
},
|
|
3607
|
+
});
|
|
3608
|
+
handlers.push(hookHandler);
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
return () => {
|
|
3612
|
+
handlers.forEach((h) => h());
|
|
3613
|
+
};
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3616
|
+
function getNormalizedContextName(contextType) {
|
|
3617
|
+
return contextType === 'experimental-webgl' ? 'webgl' : contextType;
|
|
3618
|
+
}
|
|
3619
|
+
function initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector, setPreserveDrawingBufferToTrue) {
|
|
3620
|
+
const handlers = [];
|
|
3621
|
+
try {
|
|
3622
|
+
const restoreHandler = patch(win.HTMLCanvasElement.prototype, 'getContext', function (original) {
|
|
3623
|
+
return function (contextType, ...args) {
|
|
3624
|
+
if (!isBlocked(this, blockClass, blockSelector, unblockSelector, true)) {
|
|
3625
|
+
const ctxName = getNormalizedContextName(contextType);
|
|
3626
|
+
if (!('__context' in this))
|
|
3627
|
+
this.__context = ctxName;
|
|
3628
|
+
if (setPreserveDrawingBufferToTrue &&
|
|
3629
|
+
['webgl', 'webgl2'].includes(ctxName)) {
|
|
3630
|
+
if (args[0] && typeof args[0] === 'object') {
|
|
3631
|
+
const contextAttributes = args[0];
|
|
3632
|
+
if (!contextAttributes.preserveDrawingBuffer) {
|
|
3633
|
+
contextAttributes.preserveDrawingBuffer = true;
|
|
3634
|
+
}
|
|
3635
|
+
}
|
|
3636
|
+
else {
|
|
3637
|
+
args.splice(0, 1, {
|
|
3638
|
+
preserveDrawingBuffer: true,
|
|
3639
|
+
});
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
}
|
|
3643
|
+
return original.apply(this, [contextType, ...args]);
|
|
3644
|
+
};
|
|
3645
|
+
});
|
|
3646
|
+
handlers.push(restoreHandler);
|
|
3647
|
+
}
|
|
3648
|
+
catch (_a) {
|
|
3649
|
+
console.error('failed to patch HTMLCanvasElement.prototype.getContext');
|
|
3650
|
+
}
|
|
3651
|
+
return () => {
|
|
3652
|
+
handlers.forEach((h) => h());
|
|
3653
|
+
};
|
|
2762
3654
|
}
|
|
2763
|
-
const serializeArgs = (args, win, ctx) => {
|
|
2764
|
-
return [...args].map((arg) => serializeArg(arg, win, ctx));
|
|
2765
|
-
};
|
|
2766
|
-
const isInstanceOfWebGLObject = (value, win) => {
|
|
2767
|
-
const webGLConstructorNames = [
|
|
2768
|
-
'WebGLActiveInfo',
|
|
2769
|
-
'WebGLBuffer',
|
|
2770
|
-
'WebGLFramebuffer',
|
|
2771
|
-
'WebGLProgram',
|
|
2772
|
-
'WebGLRenderbuffer',
|
|
2773
|
-
'WebGLShader',
|
|
2774
|
-
'WebGLShaderPrecisionFormat',
|
|
2775
|
-
'WebGLTexture',
|
|
2776
|
-
'WebGLUniformLocation',
|
|
2777
|
-
'WebGLVertexArrayObject',
|
|
2778
|
-
'WebGLVertexArrayObjectOES',
|
|
2779
|
-
];
|
|
2780
|
-
const supportedWebGLConstructorNames = webGLConstructorNames.filter((name) => typeof win[name] === 'function');
|
|
2781
|
-
return Boolean(supportedWebGLConstructorNames.find((name) => value instanceof win[name]));
|
|
2782
|
-
};
|
|
2783
3655
|
|
|
2784
|
-
function patchGLPrototype(prototype, type, cb, blockClass,
|
|
3656
|
+
function patchGLPrototype(prototype, type, cb, blockClass, blockSelector, unblockSelector, mirror, win) {
|
|
2785
3657
|
const handlers = [];
|
|
2786
3658
|
const props = Object.getOwnPropertyNames(prototype);
|
|
2787
3659
|
for (const prop of props) {
|
|
3660
|
+
if ([
|
|
3661
|
+
'isContextLost',
|
|
3662
|
+
'canvas',
|
|
3663
|
+
'drawingBufferWidth',
|
|
3664
|
+
'drawingBufferHeight',
|
|
3665
|
+
].includes(prop)) {
|
|
3666
|
+
continue;
|
|
3667
|
+
}
|
|
2788
3668
|
try {
|
|
2789
3669
|
if (typeof prototype[prop] !== 'function') {
|
|
2790
3670
|
continue;
|
|
@@ -2792,10 +3672,9 @@ function patchGLPrototype(prototype, type, cb, blockClass, unblockSelector, bloc
|
|
|
2792
3672
|
const restoreHandler = patch(prototype, prop, function (original) {
|
|
2793
3673
|
return function (...args) {
|
|
2794
3674
|
const result = original.apply(this, args);
|
|
2795
|
-
saveWebGLVar(result, win,
|
|
2796
|
-
if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector)) {
|
|
2797
|
-
const
|
|
2798
|
-
const recordArgs = serializeArgs([...args], win, prototype);
|
|
3675
|
+
saveWebGLVar(result, win, this);
|
|
3676
|
+
if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector, true)) {
|
|
3677
|
+
const recordArgs = serializeArgs([...args], win, this);
|
|
2799
3678
|
const mutation = {
|
|
2800
3679
|
type,
|
|
2801
3680
|
property: prop,
|
|
@@ -2835,7 +3714,64 @@ function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector, unb
|
|
|
2835
3714
|
};
|
|
2836
3715
|
}
|
|
2837
3716
|
|
|
3717
|
+
function decodeBase64(base64, enableUnicode) {
|
|
3718
|
+
var binaryString = atob(base64);
|
|
3719
|
+
if (enableUnicode) {
|
|
3720
|
+
var binaryView = new Uint8Array(binaryString.length);
|
|
3721
|
+
for (var i = 0, n = binaryString.length; i < n; ++i) {
|
|
3722
|
+
binaryView[i] = binaryString.charCodeAt(i);
|
|
3723
|
+
}
|
|
3724
|
+
return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));
|
|
3725
|
+
}
|
|
3726
|
+
return binaryString;
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
function createURL(base64, sourcemapArg, enableUnicodeArg) {
|
|
3730
|
+
var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
|
|
3731
|
+
var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
|
|
3732
|
+
var source = decodeBase64(base64, enableUnicode);
|
|
3733
|
+
var start = source.indexOf('\n', 10) + 1;
|
|
3734
|
+
var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
|
|
3735
|
+
var blob = new Blob([body], { type: 'application/javascript' });
|
|
3736
|
+
return URL.createObjectURL(blob);
|
|
3737
|
+
}
|
|
3738
|
+
|
|
3739
|
+
function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
|
|
3740
|
+
var url;
|
|
3741
|
+
return function WorkerFactory(options) {
|
|
3742
|
+
url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
|
|
3743
|
+
return new Worker(url, options);
|
|
3744
|
+
};
|
|
3745
|
+
}
|
|
3746
|
+
|
|
3747
|
+
var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIC8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KICAgIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLg0KDQogICAgUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55DQogICAgcHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLg0KDQogICAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEgNCiAgICBSRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkNCiAgICBBTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsDQogICAgSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NDQogICAgTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1INCiAgICBPVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SDQogICAgUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS4NCiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqLw0KDQogICAgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikgew0KICAgICAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH0NCiAgICAgICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7DQogICAgICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9DQogICAgICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvclsidGhyb3ciXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9DQogICAgICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfQ0KICAgICAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpOw0KICAgICAgICB9KTsNCiAgICB9CgogICAgLyoKICAgICAqIGJhc2U2NC1hcnJheWJ1ZmZlciAxLjAuMSA8aHR0cHM6Ly9naXRodWIuY29tL25pa2xhc3ZoL2Jhc2U2NC1hcnJheWJ1ZmZlcj4KICAgICAqIENvcHlyaWdodCAoYykgMjAyMSBOaWtsYXMgdm9uIEhlcnR6ZW4gPGh0dHBzOi8vaGVydHplbi5jb20+CiAgICAgKiBSZWxlYXNlZCB1bmRlciBNSVQgTGljZW5zZQogICAgICovCiAgICB2YXIgY2hhcnMgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyc7CiAgICAvLyBVc2UgYSBsb29rdXAgdGFibGUgdG8gZmluZCB0aGUgaW5kZXguCiAgICB2YXIgbG9va3VwID0gdHlwZW9mIFVpbnQ4QXJyYXkgPT09ICd1bmRlZmluZWQnID8gW10gOiBuZXcgVWludDhBcnJheSgyNTYpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGFycy5sZW5ndGg7IGkrKykgewogICAgICAgIGxvb2t1cFtjaGFycy5jaGFyQ29kZUF0KGkpXSA9IGk7CiAgICB9CiAgICB2YXIgZW5jb2RlID0gZnVuY3Rpb24gKGFycmF5YnVmZmVyKSB7CiAgICAgICAgdmFyIGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlidWZmZXIpLCBpLCBsZW4gPSBieXRlcy5sZW5ndGgsIGJhc2U2NCA9ICcnOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkgKz0gMykgewogICAgICAgICAgICBiYXNlNjQgKz0gY2hhcnNbYnl0ZXNbaV0gPj4gMl07CiAgICAgICAgICAgIGJhc2U2NCArPSBjaGFyc1soKGJ5dGVzW2ldICYgMykgPDwgNCkgfCAoYnl0ZXNbaSArIDFdID4+IDQpXTsKICAgICAgICAgICAgYmFzZTY0ICs9IGNoYXJzWygoYnl0ZXNbaSArIDFdICYgMTUpIDw8IDIpIHwgKGJ5dGVzW2kgKyAyXSA+PiA2KV07CiAgICAgICAgICAgIGJhc2U2NCArPSBjaGFyc1tieXRlc1tpICsgMl0gJiA2M107CiAgICAgICAgfQogICAgICAgIGlmIChsZW4gJSAzID09PSAyKSB7CiAgICAgICAgICAgIGJhc2U2NCA9IGJhc2U2NC5zdWJzdHJpbmcoMCwgYmFzZTY0Lmxlbmd0aCAtIDEpICsgJz0nOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChsZW4gJSAzID09PSAxKSB7CiAgICAgICAgICAgIGJhc2U2NCA9IGJhc2U2NC5zdWJzdHJpbmcoMCwgYmFzZTY0Lmxlbmd0aCAtIDIpICsgJz09JzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJhc2U2NDsKICAgIH07CgogICAgY29uc3QgbGFzdEJsb2JNYXAgPSBuZXcgTWFwKCk7DQogICAgY29uc3QgdHJhbnNwYXJlbnRCbG9iTWFwID0gbmV3IE1hcCgpOw0KICAgIGZ1bmN0aW9uIGdldFRyYW5zcGFyZW50QmxvYkZvcih3aWR0aCwgaGVpZ2h0LCBkYXRhVVJMT3B0aW9ucykgew0KICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgew0KICAgICAgICAgICAgY29uc3QgaWQgPSBgJHt3aWR0aH0tJHtoZWlnaHR9YDsNCiAgICAgICAgICAgIGlmICgnT2Zmc2NyZWVuQ2FudmFzJyBpbiBnbG9iYWxUaGlzKSB7DQogICAgICAgICAgICAgICAgaWYgKHRyYW5zcGFyZW50QmxvYk1hcC5oYXMoaWQpKQ0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNwYXJlbnRCbG9iTWFwLmdldChpZCk7DQogICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2NyZWVuID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsNCiAgICAgICAgICAgICAgICBvZmZzY3JlZW4uZ2V0Q29udGV4dCgnMmQnKTsNCiAgICAgICAgICAgICAgICBjb25zdCBibG9iID0geWllbGQgb2Zmc2NyZWVuLmNvbnZlcnRUb0Jsb2IoZGF0YVVSTE9wdGlvbnMpOw0KICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0geWllbGQgYmxvYi5hcnJheUJ1ZmZlcigpOw0KICAgICAgICAgICAgICAgIGNvbnN0IGJhc2U2NCA9IGVuY29kZShhcnJheUJ1ZmZlcik7DQogICAgICAgICAgICAgICAgdHJhbnNwYXJlbnRCbG9iTWFwLnNldChpZCwgYmFzZTY0KTsNCiAgICAgICAgICAgICAgICByZXR1cm4gYmFzZTY0Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAgICAgcmV0dXJuICcnOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9KTsNCiAgICB9DQogICAgY29uc3Qgd29ya2VyID0gc2VsZjsNCiAgICB3b3JrZXIub25tZXNzYWdlID0gZnVuY3Rpb24gKGUpIHsNCiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsNCiAgICAgICAgICAgIGlmICgnT2Zmc2NyZWVuQ2FudmFzJyBpbiBnbG9iYWxUaGlzKSB7DQogICAgICAgICAgICAgICAgY29uc3QgeyBpZCwgYml0bWFwLCB3aWR0aCwgaGVpZ2h0LCBkYXRhVVJMT3B0aW9ucyB9ID0gZS5kYXRhOw0KICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zcGFyZW50QmFzZTY0ID0gZ2V0VHJhbnNwYXJlbnRCbG9iRm9yKHdpZHRoLCBoZWlnaHQsIGRhdGFVUkxPcHRpb25zKTsNCiAgICAgICAgICAgICAgICBjb25zdCBvZmZzY3JlZW4gPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOw0KICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IG9mZnNjcmVlbi5nZXRDb250ZXh0KCcyZCcpOw0KICAgICAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2UoYml0bWFwLCAwLCAwKTsNCiAgICAgICAgICAgICAgICBiaXRtYXAuY2xvc2UoKTsNCiAgICAgICAgICAgICAgICBjb25zdCBibG9iID0geWllbGQgb2Zmc2NyZWVuLmNvbnZlcnRUb0Jsb2IoZGF0YVVSTE9wdGlvbnMpOw0KICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBibG9iLnR5cGU7DQogICAgICAgICAgICAgICAgY29uc3QgYXJyYXlCdWZmZXIgPSB5aWVsZCBibG9iLmFycmF5QnVmZmVyKCk7DQogICAgICAgICAgICAgICAgY29uc3QgYmFzZTY0ID0gZW5jb2RlKGFycmF5QnVmZmVyKTsNCiAgICAgICAgICAgICAgICBpZiAoIWxhc3RCbG9iTWFwLmhhcyhpZCkgJiYgKHlpZWxkIHRyYW5zcGFyZW50QmFzZTY0KSA9PT0gYmFzZTY0KSB7DQogICAgICAgICAgICAgICAgICAgIGxhc3RCbG9iTWFwLnNldChpZCwgYmFzZTY0KTsNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdvcmtlci5wb3N0TWVzc2FnZSh7IGlkIH0pOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBpZiAobGFzdEJsb2JNYXAuZ2V0KGlkKSA9PT0gYmFzZTY0KQ0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQgfSk7DQogICAgICAgICAgICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKHsNCiAgICAgICAgICAgICAgICAgICAgaWQsDQogICAgICAgICAgICAgICAgICAgIHR5cGUsDQogICAgICAgICAgICAgICAgICAgIGJhc2U2NCwNCiAgICAgICAgICAgICAgICAgICAgd2lkdGgsDQogICAgICAgICAgICAgICAgICAgIGhlaWdodCwNCiAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICBsYXN0QmxvYk1hcC5zZXQoaWQsIGJhc2U2NCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICByZXR1cm4gd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQ6IGUuZGF0YS5pZCB9KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgfTsKCn0pKCk7Cgo=', null, false);
|
|
3748
|
+
|
|
2838
3749
|
class CanvasManager {
|
|
3750
|
+
constructor(options) {
|
|
3751
|
+
this.pendingCanvasMutations = new Map();
|
|
3752
|
+
this.rafStamps = { latestId: 0, invokeId: null };
|
|
3753
|
+
this.frozen = false;
|
|
3754
|
+
this.locked = false;
|
|
3755
|
+
this.processMutation = (target, mutation) => {
|
|
3756
|
+
const newFrame = this.rafStamps.invokeId &&
|
|
3757
|
+
this.rafStamps.latestId !== this.rafStamps.invokeId;
|
|
3758
|
+
if (newFrame || !this.rafStamps.invokeId)
|
|
3759
|
+
this.rafStamps.invokeId = this.rafStamps.latestId;
|
|
3760
|
+
if (!this.pendingCanvasMutations.has(target)) {
|
|
3761
|
+
this.pendingCanvasMutations.set(target, []);
|
|
3762
|
+
}
|
|
3763
|
+
this.pendingCanvasMutations.get(target).push(mutation);
|
|
3764
|
+
};
|
|
3765
|
+
const { sampling = 'all', win, blockClass, blockSelector, unblockSelector, recordCanvas, dataURLOptions, } = options;
|
|
3766
|
+
this.mutationCb = options.mutationCb;
|
|
3767
|
+
this.mirror = options.mirror;
|
|
3768
|
+
if (recordCanvas && sampling === 'all')
|
|
3769
|
+
this.initCanvasMutationObserver(win, blockClass, blockSelector, unblockSelector);
|
|
3770
|
+
if (recordCanvas && typeof sampling === 'number')
|
|
3771
|
+
this.initCanvasFPSObserver(sampling, win, blockClass, blockSelector, unblockSelector, {
|
|
3772
|
+
dataURLOptions,
|
|
3773
|
+
});
|
|
3774
|
+
}
|
|
2839
3775
|
reset() {
|
|
2840
3776
|
this.pendingCanvasMutations.clear();
|
|
2841
3777
|
this.resetObservers && this.resetObservers();
|
|
@@ -2852,31 +3788,98 @@ class CanvasManager {
|
|
|
2852
3788
|
unlock() {
|
|
2853
3789
|
this.locked = false;
|
|
2854
3790
|
}
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
3791
|
+
initCanvasFPSObserver(fps, win, blockClass, blockSelector, unblockSelector, options) {
|
|
3792
|
+
const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector, true);
|
|
3793
|
+
const snapshotInProgressMap = new Map();
|
|
3794
|
+
const worker = new WorkerFactory();
|
|
3795
|
+
worker.onmessage = (e) => {
|
|
3796
|
+
const { id } = e.data;
|
|
3797
|
+
snapshotInProgressMap.set(id, false);
|
|
3798
|
+
if (!('base64' in e.data))
|
|
3799
|
+
return;
|
|
3800
|
+
const { base64, type, width, height } = e.data;
|
|
3801
|
+
this.mutationCb({
|
|
3802
|
+
id,
|
|
3803
|
+
type: CanvasContext['2D'],
|
|
3804
|
+
commands: [
|
|
3805
|
+
{
|
|
3806
|
+
property: 'clearRect',
|
|
3807
|
+
args: [0, 0, width, height],
|
|
3808
|
+
},
|
|
3809
|
+
{
|
|
3810
|
+
property: 'drawImage',
|
|
3811
|
+
args: [
|
|
3812
|
+
{
|
|
3813
|
+
rr_type: 'ImageBitmap',
|
|
3814
|
+
args: [
|
|
3815
|
+
{
|
|
3816
|
+
rr_type: 'Blob',
|
|
3817
|
+
data: [{ rr_type: 'ArrayBuffer', base64 }],
|
|
3818
|
+
type,
|
|
3819
|
+
},
|
|
3820
|
+
],
|
|
3821
|
+
},
|
|
3822
|
+
0,
|
|
3823
|
+
0,
|
|
3824
|
+
],
|
|
3825
|
+
},
|
|
3826
|
+
],
|
|
3827
|
+
});
|
|
3828
|
+
};
|
|
3829
|
+
const timeBetweenSnapshots = 1000 / fps;
|
|
3830
|
+
let lastSnapshotTime = 0;
|
|
3831
|
+
let rafId;
|
|
3832
|
+
const getCanvas = () => {
|
|
3833
|
+
const matchedCanvas = [];
|
|
3834
|
+
win.document.querySelectorAll('canvas').forEach((canvas) => {
|
|
3835
|
+
if (!isBlocked(canvas, blockClass, blockSelector, unblockSelector, true)) {
|
|
3836
|
+
matchedCanvas.push(canvas);
|
|
3837
|
+
}
|
|
3838
|
+
});
|
|
3839
|
+
return matchedCanvas;
|
|
3840
|
+
};
|
|
3841
|
+
const takeCanvasSnapshots = (timestamp) => {
|
|
3842
|
+
if (lastSnapshotTime &&
|
|
3843
|
+
timestamp - lastSnapshotTime < timeBetweenSnapshots) {
|
|
3844
|
+
rafId = requestAnimationFrame(takeCanvasSnapshots);
|
|
3845
|
+
return;
|
|
2867
3846
|
}
|
|
2868
|
-
|
|
3847
|
+
lastSnapshotTime = timestamp;
|
|
3848
|
+
getCanvas()
|
|
3849
|
+
.forEach((canvas) => __awaiter(this, void 0, void 0, function* () {
|
|
3850
|
+
var _a;
|
|
3851
|
+
const id = this.mirror.getId(canvas);
|
|
3852
|
+
if (snapshotInProgressMap.get(id))
|
|
3853
|
+
return;
|
|
3854
|
+
snapshotInProgressMap.set(id, true);
|
|
3855
|
+
if (['webgl', 'webgl2'].includes(canvas.__context)) {
|
|
3856
|
+
const context = canvas.getContext(canvas.__context);
|
|
3857
|
+
if (((_a = context === null || context === void 0 ? void 0 : context.getContextAttributes()) === null || _a === void 0 ? void 0 : _a.preserveDrawingBuffer) === false) {
|
|
3858
|
+
context.clear(context.COLOR_BUFFER_BIT);
|
|
3859
|
+
}
|
|
3860
|
+
}
|
|
3861
|
+
const bitmap = yield createImageBitmap(canvas);
|
|
3862
|
+
worker.postMessage({
|
|
3863
|
+
id,
|
|
3864
|
+
bitmap,
|
|
3865
|
+
width: canvas.width,
|
|
3866
|
+
height: canvas.height,
|
|
3867
|
+
dataURLOptions: options.dataURLOptions,
|
|
3868
|
+
}, [bitmap]);
|
|
3869
|
+
}));
|
|
3870
|
+
rafId = requestAnimationFrame(takeCanvasSnapshots);
|
|
3871
|
+
};
|
|
3872
|
+
rafId = requestAnimationFrame(takeCanvasSnapshots);
|
|
3873
|
+
this.resetObservers = () => {
|
|
3874
|
+
canvasContextReset();
|
|
3875
|
+
cancelAnimationFrame(rafId);
|
|
2869
3876
|
};
|
|
2870
|
-
this.mutationCb = options.mutationCb;
|
|
2871
|
-
this.mirror = options.mirror;
|
|
2872
|
-
if (options.recordCanvas === true)
|
|
2873
|
-
this.initCanvasMutationObserver(options.win, options.blockClass, options.blockSelector, options.unblockSelector);
|
|
2874
3877
|
}
|
|
2875
|
-
initCanvasMutationObserver(win, blockClass,
|
|
3878
|
+
initCanvasMutationObserver(win, blockClass, blockSelector, unblockSelector) {
|
|
2876
3879
|
this.startRAFTimestamping();
|
|
2877
3880
|
this.startPendingCanvasMutationFlusher();
|
|
2878
|
-
const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector);
|
|
2879
|
-
const canvas2DReset = initCanvas2DMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector, unblockSelector
|
|
3881
|
+
const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector, false);
|
|
3882
|
+
const canvas2DReset = initCanvas2DMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector, unblockSelector);
|
|
2880
3883
|
const canvasWebGL1and2Reset = initCanvasWebGLMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector, unblockSelector, this.mirror);
|
|
2881
3884
|
this.resetObservers = () => {
|
|
2882
3885
|
canvasContextReset();
|
|
@@ -2918,20 +3921,136 @@ class CanvasManager {
|
|
|
2918
3921
|
}
|
|
2919
3922
|
}
|
|
2920
3923
|
|
|
3924
|
+
class StylesheetManager {
|
|
3925
|
+
constructor(options) {
|
|
3926
|
+
this.trackedLinkElements = new WeakSet();
|
|
3927
|
+
this.styleMirror = new StyleSheetMirror();
|
|
3928
|
+
this.mutationCb = options.mutationCb;
|
|
3929
|
+
this.adoptedStyleSheetCb = options.adoptedStyleSheetCb;
|
|
3930
|
+
}
|
|
3931
|
+
attachLinkElement(linkEl, childSn) {
|
|
3932
|
+
if ('_cssText' in childSn.attributes)
|
|
3933
|
+
this.mutationCb({
|
|
3934
|
+
adds: [],
|
|
3935
|
+
removes: [],
|
|
3936
|
+
texts: [],
|
|
3937
|
+
attributes: [
|
|
3938
|
+
{
|
|
3939
|
+
id: childSn.id,
|
|
3940
|
+
attributes: childSn
|
|
3941
|
+
.attributes,
|
|
3942
|
+
},
|
|
3943
|
+
],
|
|
3944
|
+
});
|
|
3945
|
+
this.trackLinkElement(linkEl);
|
|
3946
|
+
}
|
|
3947
|
+
trackLinkElement(linkEl) {
|
|
3948
|
+
if (this.trackedLinkElements.has(linkEl))
|
|
3949
|
+
return;
|
|
3950
|
+
this.trackedLinkElements.add(linkEl);
|
|
3951
|
+
this.trackStylesheetInLinkElement(linkEl);
|
|
3952
|
+
}
|
|
3953
|
+
adoptStyleSheets(sheets, hostId) {
|
|
3954
|
+
if (sheets.length === 0)
|
|
3955
|
+
return;
|
|
3956
|
+
const adoptedStyleSheetData = {
|
|
3957
|
+
id: hostId,
|
|
3958
|
+
styleIds: [],
|
|
3959
|
+
};
|
|
3960
|
+
const styles = [];
|
|
3961
|
+
for (const sheet of sheets) {
|
|
3962
|
+
let styleId;
|
|
3963
|
+
if (!this.styleMirror.has(sheet)) {
|
|
3964
|
+
styleId = this.styleMirror.add(sheet);
|
|
3965
|
+
const rules = Array.from(sheet.rules || CSSRule);
|
|
3966
|
+
styles.push({
|
|
3967
|
+
styleId,
|
|
3968
|
+
rules: rules.map((r, index) => {
|
|
3969
|
+
return {
|
|
3970
|
+
rule: getCssRuleString(r),
|
|
3971
|
+
index,
|
|
3972
|
+
};
|
|
3973
|
+
}),
|
|
3974
|
+
});
|
|
3975
|
+
}
|
|
3976
|
+
else
|
|
3977
|
+
styleId = this.styleMirror.getId(sheet);
|
|
3978
|
+
adoptedStyleSheetData.styleIds.push(styleId);
|
|
3979
|
+
}
|
|
3980
|
+
if (styles.length > 0)
|
|
3981
|
+
adoptedStyleSheetData.styles = styles;
|
|
3982
|
+
this.adoptedStyleSheetCb(adoptedStyleSheetData);
|
|
3983
|
+
}
|
|
3984
|
+
reset() {
|
|
3985
|
+
this.styleMirror.reset();
|
|
3986
|
+
this.trackedLinkElements = new WeakSet();
|
|
3987
|
+
}
|
|
3988
|
+
trackStylesheetInLinkElement(linkEl) {
|
|
3989
|
+
}
|
|
3990
|
+
}
|
|
3991
|
+
|
|
3992
|
+
class ProcessedNodeManager {
|
|
3993
|
+
constructor() {
|
|
3994
|
+
this.nodeMap = new WeakMap();
|
|
3995
|
+
this.loop = true;
|
|
3996
|
+
this.periodicallyClear();
|
|
3997
|
+
}
|
|
3998
|
+
periodicallyClear() {
|
|
3999
|
+
requestAnimationFrame(() => {
|
|
4000
|
+
this.clear();
|
|
4001
|
+
if (this.loop)
|
|
4002
|
+
this.periodicallyClear();
|
|
4003
|
+
});
|
|
4004
|
+
}
|
|
4005
|
+
inOtherBuffer(node, thisBuffer) {
|
|
4006
|
+
const buffers = this.nodeMap.get(node);
|
|
4007
|
+
return (buffers && Array.from(buffers).some((buffer) => buffer !== thisBuffer));
|
|
4008
|
+
}
|
|
4009
|
+
add(node, buffer) {
|
|
4010
|
+
this.nodeMap.set(node, (this.nodeMap.get(node) || new Set()).add(buffer));
|
|
4011
|
+
}
|
|
4012
|
+
clear() {
|
|
4013
|
+
this.nodeMap = new WeakMap();
|
|
4014
|
+
}
|
|
4015
|
+
destroy() {
|
|
4016
|
+
this.loop = false;
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
|
|
2921
4020
|
function wrapEvent(e) {
|
|
2922
|
-
return Object.assign(Object.assign({}, e), { timestamp:
|
|
4021
|
+
return Object.assign(Object.assign({}, e), { timestamp: nowTimestamp() });
|
|
2923
4022
|
}
|
|
2924
4023
|
let wrappedEmit;
|
|
2925
4024
|
let takeFullSnapshot;
|
|
4025
|
+
let canvasManager;
|
|
4026
|
+
let recording = false;
|
|
2926
4027
|
const mirror = createMirror();
|
|
2927
4028
|
function record(options = {}) {
|
|
2928
|
-
const { emit, checkoutEveryNms, checkoutEveryNth, blockClass = 'rr-block', blockSelector = null, unblockSelector = null, ignoreClass = 'rr-ignore', ignoreSelector = null, maskTextClass = 'rr-mask',
|
|
2929
|
-
|
|
4029
|
+
const { emit, checkoutEveryNms, checkoutEveryNth, blockClass = 'rr-block', blockSelector = null, unblockSelector = null, ignoreClass = 'rr-ignore', ignoreSelector = null, maskAllText = false, maskTextClass = 'rr-mask', unmaskTextClass = null, maskTextSelector = null, unmaskTextSelector = null, inlineStylesheet = true, maskAllInputs, maskInputOptions: _maskInputOptions, slimDOMOptions: _slimDOMOptions, maskAttributeFn, maskInputFn, maskTextFn, hooks, packFn, sampling = {}, dataURLOptions = {}, mousemoveWait, recordCanvas = false, recordCrossOriginIframes = false, recordAfter = options.recordAfter === 'DOMContentLoaded'
|
|
4030
|
+
? options.recordAfter
|
|
4031
|
+
: 'load', userTriggeredOnInput = false, collectFonts = false, inlineImages = false, plugins, keepIframeSrcFn = () => false, ignoreCSSAttributes = new Set([]), errorHandler, onMutation, } = options;
|
|
4032
|
+
registerErrorHandler(errorHandler);
|
|
4033
|
+
const inEmittingFrame = recordCrossOriginIframes
|
|
4034
|
+
? window.parent === window
|
|
4035
|
+
: true;
|
|
4036
|
+
let passEmitsToParent = false;
|
|
4037
|
+
if (!inEmittingFrame) {
|
|
4038
|
+
try {
|
|
4039
|
+
if (window.parent.document) {
|
|
4040
|
+
passEmitsToParent = false;
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
4043
|
+
catch (e) {
|
|
4044
|
+
passEmitsToParent = true;
|
|
4045
|
+
}
|
|
4046
|
+
}
|
|
4047
|
+
if (inEmittingFrame && !emit) {
|
|
2930
4048
|
throw new Error('emit function is required');
|
|
2931
4049
|
}
|
|
2932
4050
|
if (mousemoveWait !== undefined && sampling.mousemove === undefined) {
|
|
2933
4051
|
sampling.mousemove = mousemoveWait;
|
|
2934
4052
|
}
|
|
4053
|
+
mirror.reset();
|
|
2935
4054
|
const maskInputOptions = maskAllInputs === true
|
|
2936
4055
|
? {
|
|
2937
4056
|
color: true,
|
|
@@ -2980,7 +4099,8 @@ function record(options = {}) {
|
|
|
2980
4099
|
e = plugin.eventProcessor(e);
|
|
2981
4100
|
}
|
|
2982
4101
|
}
|
|
2983
|
-
if (packFn
|
|
4102
|
+
if (packFn &&
|
|
4103
|
+
!passEmitsToParent) {
|
|
2984
4104
|
e = packFn(e);
|
|
2985
4105
|
}
|
|
2986
4106
|
return e;
|
|
@@ -2993,7 +4113,18 @@ function record(options = {}) {
|
|
|
2993
4113
|
e.data.source === IncrementalSource.Mutation)) {
|
|
2994
4114
|
mutationBuffers.forEach((buf) => buf.unfreeze());
|
|
2995
4115
|
}
|
|
2996
|
-
|
|
4116
|
+
if (inEmittingFrame) {
|
|
4117
|
+
emit === null || emit === void 0 ? void 0 : emit(eventProcessor(e), isCheckout);
|
|
4118
|
+
}
|
|
4119
|
+
else if (passEmitsToParent) {
|
|
4120
|
+
const message = {
|
|
4121
|
+
type: 'rrweb',
|
|
4122
|
+
event: eventProcessor(e),
|
|
4123
|
+
origin: window.location.origin,
|
|
4124
|
+
isCheckout,
|
|
4125
|
+
};
|
|
4126
|
+
window.parent.postMessage(message, '*');
|
|
4127
|
+
}
|
|
2997
4128
|
if (e.type === EventType.FullSnapshot) {
|
|
2998
4129
|
lastFullSnapshotEvent = e;
|
|
2999
4130
|
incrementalSnapshotCount = 0;
|
|
@@ -3026,10 +4157,31 @@ function record(options = {}) {
|
|
|
3026
4157
|
type: EventType.IncrementalSnapshot,
|
|
3027
4158
|
data: Object.assign({ source: IncrementalSource.CanvasMutation }, p),
|
|
3028
4159
|
}));
|
|
4160
|
+
const wrappedAdoptedStyleSheetEmit = (a) => wrappedEmit(wrapEvent({
|
|
4161
|
+
type: EventType.IncrementalSnapshot,
|
|
4162
|
+
data: Object.assign({ source: IncrementalSource.AdoptedStyleSheet }, a),
|
|
4163
|
+
}));
|
|
4164
|
+
const stylesheetManager = new StylesheetManager({
|
|
4165
|
+
mutationCb: wrappedMutationEmit,
|
|
4166
|
+
adoptedStyleSheetCb: wrappedAdoptedStyleSheetEmit,
|
|
4167
|
+
});
|
|
3029
4168
|
const iframeManager = new IframeManager({
|
|
4169
|
+
mirror,
|
|
3030
4170
|
mutationCb: wrappedMutationEmit,
|
|
4171
|
+
stylesheetManager: stylesheetManager,
|
|
4172
|
+
recordCrossOriginIframes,
|
|
4173
|
+
wrappedEmit,
|
|
3031
4174
|
});
|
|
3032
|
-
const
|
|
4175
|
+
for (const plugin of plugins || []) {
|
|
4176
|
+
if (plugin.getMirror)
|
|
4177
|
+
plugin.getMirror({
|
|
4178
|
+
nodeMirror: mirror,
|
|
4179
|
+
crossOriginIframeMirror: iframeManager.crossOriginIframeMirror,
|
|
4180
|
+
crossOriginIframeStyleMirror: iframeManager.crossOriginIframeStyleMirror,
|
|
4181
|
+
});
|
|
4182
|
+
}
|
|
4183
|
+
const processedNodeManager = new ProcessedNodeManager();
|
|
4184
|
+
canvasManager = new CanvasManager({
|
|
3033
4185
|
recordCanvas,
|
|
3034
4186
|
mutationCb: wrappedCanvasMutationEmit,
|
|
3035
4187
|
win: window,
|
|
@@ -3037,6 +4189,8 @@ function record(options = {}) {
|
|
|
3037
4189
|
blockSelector,
|
|
3038
4190
|
unblockSelector,
|
|
3039
4191
|
mirror,
|
|
4192
|
+
sampling: sampling.canvas,
|
|
4193
|
+
dataURLOptions,
|
|
3040
4194
|
});
|
|
3041
4195
|
const shadowDomManager = new ShadowDomManager({
|
|
3042
4196
|
mutationCb: wrappedMutationEmit,
|
|
@@ -3046,14 +4200,15 @@ function record(options = {}) {
|
|
|
3046
4200
|
blockClass,
|
|
3047
4201
|
blockSelector,
|
|
3048
4202
|
unblockSelector,
|
|
4203
|
+
maskAllText,
|
|
3049
4204
|
maskTextClass,
|
|
4205
|
+
unmaskTextClass,
|
|
3050
4206
|
maskTextSelector,
|
|
3051
4207
|
unmaskTextSelector,
|
|
3052
|
-
maskInputSelector,
|
|
3053
|
-
unmaskInputSelector,
|
|
3054
4208
|
inlineStylesheet,
|
|
3055
|
-
maskAllText,
|
|
3056
4209
|
maskInputOptions,
|
|
4210
|
+
dataURLOptions,
|
|
4211
|
+
maskAttributeFn,
|
|
3057
4212
|
maskTextFn,
|
|
3058
4213
|
maskInputFn,
|
|
3059
4214
|
recordCanvas,
|
|
@@ -3061,12 +4216,14 @@ function record(options = {}) {
|
|
|
3061
4216
|
sampling,
|
|
3062
4217
|
slimDOMOptions,
|
|
3063
4218
|
iframeManager,
|
|
4219
|
+
stylesheetManager,
|
|
3064
4220
|
canvasManager,
|
|
4221
|
+
keepIframeSrcFn,
|
|
4222
|
+
processedNodeManager,
|
|
3065
4223
|
},
|
|
3066
4224
|
mirror,
|
|
3067
4225
|
});
|
|
3068
4226
|
takeFullSnapshot = (isCheckout = false) => {
|
|
3069
|
-
var _a, _b, _c, _d;
|
|
3070
4227
|
wrappedEmit(wrapEvent({
|
|
3071
4228
|
type: EventType.Meta,
|
|
3072
4229
|
data: {
|
|
@@ -3075,27 +4232,35 @@ function record(options = {}) {
|
|
|
3075
4232
|
height: getWindowHeight(),
|
|
3076
4233
|
},
|
|
3077
4234
|
}), isCheckout);
|
|
4235
|
+
stylesheetManager.reset();
|
|
4236
|
+
shadowDomManager.init();
|
|
3078
4237
|
mutationBuffers.forEach((buf) => buf.lock());
|
|
3079
|
-
const
|
|
4238
|
+
const node = snapshot(document, {
|
|
4239
|
+
mirror,
|
|
3080
4240
|
blockClass,
|
|
3081
4241
|
blockSelector,
|
|
3082
4242
|
unblockSelector,
|
|
4243
|
+
maskAllText,
|
|
3083
4244
|
maskTextClass,
|
|
4245
|
+
unmaskTextClass,
|
|
3084
4246
|
maskTextSelector,
|
|
3085
4247
|
unmaskTextSelector,
|
|
3086
|
-
maskInputSelector,
|
|
3087
|
-
unmaskInputSelector,
|
|
3088
4248
|
inlineStylesheet,
|
|
3089
|
-
maskAllText,
|
|
3090
4249
|
maskAllInputs: maskInputOptions,
|
|
4250
|
+
maskAttributeFn,
|
|
4251
|
+
maskInputFn,
|
|
3091
4252
|
maskTextFn,
|
|
3092
4253
|
slimDOM: slimDOMOptions,
|
|
4254
|
+
dataURLOptions,
|
|
3093
4255
|
recordCanvas,
|
|
3094
4256
|
inlineImages,
|
|
3095
4257
|
onSerialize: (n) => {
|
|
3096
|
-
if (
|
|
4258
|
+
if (isSerializedIframe(n, mirror)) {
|
|
3097
4259
|
iframeManager.addIframe(n);
|
|
3098
4260
|
}
|
|
4261
|
+
if (isSerializedStylesheet(n, mirror)) {
|
|
4262
|
+
stylesheetManager.trackLinkElement(n);
|
|
4263
|
+
}
|
|
3099
4264
|
if (hasShadowRoot(n)) {
|
|
3100
4265
|
shadowDomManager.addShadowRoot(n.shadowRoot, document);
|
|
3101
4266
|
}
|
|
@@ -3104,42 +4269,27 @@ function record(options = {}) {
|
|
|
3104
4269
|
iframeManager.attachIframe(iframe, childSn);
|
|
3105
4270
|
shadowDomManager.observeAttachShadow(iframe);
|
|
3106
4271
|
},
|
|
4272
|
+
onStylesheetLoad: (linkEl, childSn) => {
|
|
4273
|
+
stylesheetManager.attachLinkElement(linkEl, childSn);
|
|
4274
|
+
},
|
|
3107
4275
|
keepIframeSrcFn,
|
|
3108
4276
|
});
|
|
3109
4277
|
if (!node) {
|
|
3110
4278
|
return console.warn('Failed to snapshot the document');
|
|
3111
4279
|
}
|
|
3112
|
-
mirror.map = idNodeMap;
|
|
3113
4280
|
wrappedEmit(wrapEvent({
|
|
3114
4281
|
type: EventType.FullSnapshot,
|
|
3115
4282
|
data: {
|
|
3116
4283
|
node,
|
|
3117
|
-
initialOffset:
|
|
3118
|
-
left: window.pageXOffset !== undefined
|
|
3119
|
-
? window.pageXOffset
|
|
3120
|
-
: (document === null || document === void 0 ? void 0 : document.documentElement.scrollLeft) ||
|
|
3121
|
-
((_b = (_a = document === null || document === void 0 ? void 0 : document.body) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.scrollLeft) ||
|
|
3122
|
-
(document === null || document === void 0 ? void 0 : document.body.scrollLeft) ||
|
|
3123
|
-
0,
|
|
3124
|
-
top: window.pageYOffset !== undefined
|
|
3125
|
-
? window.pageYOffset
|
|
3126
|
-
: (document === null || document === void 0 ? void 0 : document.documentElement.scrollTop) ||
|
|
3127
|
-
((_d = (_c = document === null || document === void 0 ? void 0 : document.body) === null || _c === void 0 ? void 0 : _c.parentElement) === null || _d === void 0 ? void 0 : _d.scrollTop) ||
|
|
3128
|
-
(document === null || document === void 0 ? void 0 : document.body.scrollTop) ||
|
|
3129
|
-
0,
|
|
3130
|
-
},
|
|
4284
|
+
initialOffset: getWindowScroll(window),
|
|
3131
4285
|
},
|
|
3132
|
-
}));
|
|
4286
|
+
}), isCheckout);
|
|
3133
4287
|
mutationBuffers.forEach((buf) => buf.unlock());
|
|
4288
|
+
if (document.adoptedStyleSheets && document.adoptedStyleSheets.length > 0)
|
|
4289
|
+
stylesheetManager.adoptStyleSheets(document.adoptedStyleSheets, mirror.getId(document));
|
|
3134
4290
|
};
|
|
3135
4291
|
try {
|
|
3136
4292
|
const handlers = [];
|
|
3137
|
-
handlers.push(on('DOMContentLoaded', () => {
|
|
3138
|
-
wrappedEmit(wrapEvent({
|
|
3139
|
-
type: EventType.DomContentLoaded,
|
|
3140
|
-
data: {},
|
|
3141
|
-
}));
|
|
3142
|
-
}));
|
|
3143
4293
|
const observe = (doc) => {
|
|
3144
4294
|
var _a;
|
|
3145
4295
|
return callbackWrapper(initObservers)({
|
|
@@ -3182,14 +4332,26 @@ function record(options = {}) {
|
|
|
3182
4332
|
type: EventType.IncrementalSnapshot,
|
|
3183
4333
|
data: Object.assign({ source: IncrementalSource.Font }, p),
|
|
3184
4334
|
})),
|
|
4335
|
+
selectionCb: (p) => {
|
|
4336
|
+
wrappedEmit(wrapEvent({
|
|
4337
|
+
type: EventType.IncrementalSnapshot,
|
|
4338
|
+
data: Object.assign({ source: IncrementalSource.Selection }, p),
|
|
4339
|
+
}));
|
|
4340
|
+
},
|
|
4341
|
+
customElementCb: (c) => {
|
|
4342
|
+
wrappedEmit(wrapEvent({
|
|
4343
|
+
type: EventType.IncrementalSnapshot,
|
|
4344
|
+
data: Object.assign({ source: IncrementalSource.CustomElement }, c),
|
|
4345
|
+
}));
|
|
4346
|
+
},
|
|
3185
4347
|
blockClass,
|
|
3186
4348
|
ignoreClass,
|
|
3187
4349
|
ignoreSelector,
|
|
4350
|
+
maskAllText,
|
|
3188
4351
|
maskTextClass,
|
|
4352
|
+
unmaskTextClass,
|
|
3189
4353
|
maskTextSelector,
|
|
3190
4354
|
unmaskTextSelector,
|
|
3191
|
-
maskInputSelector,
|
|
3192
|
-
unmaskInputSelector,
|
|
3193
4355
|
maskInputOptions,
|
|
3194
4356
|
inlineStylesheet,
|
|
3195
4357
|
sampling,
|
|
@@ -3198,16 +4360,21 @@ function record(options = {}) {
|
|
|
3198
4360
|
userTriggeredOnInput,
|
|
3199
4361
|
collectFonts,
|
|
3200
4362
|
doc,
|
|
3201
|
-
|
|
4363
|
+
maskAttributeFn,
|
|
3202
4364
|
maskInputFn,
|
|
3203
4365
|
maskTextFn,
|
|
4366
|
+
keepIframeSrcFn,
|
|
3204
4367
|
blockSelector,
|
|
3205
4368
|
unblockSelector,
|
|
3206
4369
|
slimDOMOptions,
|
|
4370
|
+
dataURLOptions,
|
|
3207
4371
|
mirror,
|
|
3208
4372
|
iframeManager,
|
|
4373
|
+
stylesheetManager,
|
|
3209
4374
|
shadowDomManager,
|
|
4375
|
+
processedNodeManager,
|
|
3210
4376
|
canvasManager,
|
|
4377
|
+
ignoreCSSAttributes,
|
|
3211
4378
|
plugins: ((_a = plugins === null || plugins === void 0 ? void 0 : plugins.filter((p) => p.observer)) === null || _a === void 0 ? void 0 : _a.map((p) => ({
|
|
3212
4379
|
observer: p.observer,
|
|
3213
4380
|
options: p.options,
|
|
@@ -3232,22 +4399,35 @@ function record(options = {}) {
|
|
|
3232
4399
|
const init = () => {
|
|
3233
4400
|
takeFullSnapshot();
|
|
3234
4401
|
handlers.push(observe(document));
|
|
4402
|
+
recording = true;
|
|
3235
4403
|
};
|
|
3236
4404
|
if (document.readyState === 'interactive' ||
|
|
3237
4405
|
document.readyState === 'complete') {
|
|
3238
4406
|
init();
|
|
3239
4407
|
}
|
|
3240
4408
|
else {
|
|
4409
|
+
handlers.push(on('DOMContentLoaded', () => {
|
|
4410
|
+
wrappedEmit(wrapEvent({
|
|
4411
|
+
type: EventType.DomContentLoaded,
|
|
4412
|
+
data: {},
|
|
4413
|
+
}));
|
|
4414
|
+
if (recordAfter === 'DOMContentLoaded')
|
|
4415
|
+
init();
|
|
4416
|
+
}));
|
|
3241
4417
|
handlers.push(on('load', () => {
|
|
3242
4418
|
wrappedEmit(wrapEvent({
|
|
3243
4419
|
type: EventType.Load,
|
|
3244
4420
|
data: {},
|
|
3245
4421
|
}));
|
|
3246
|
-
|
|
4422
|
+
if (recordAfter === 'load')
|
|
4423
|
+
init();
|
|
3247
4424
|
}, window));
|
|
3248
4425
|
}
|
|
3249
4426
|
return () => {
|
|
3250
4427
|
handlers.forEach((h) => h());
|
|
4428
|
+
processedNodeManager.destroy();
|
|
4429
|
+
recording = false;
|
|
4430
|
+
unregisterErrorHandler();
|
|
3251
4431
|
};
|
|
3252
4432
|
}
|
|
3253
4433
|
catch (error) {
|
|
@@ -3255,7 +4435,7 @@ function record(options = {}) {
|
|
|
3255
4435
|
}
|
|
3256
4436
|
}
|
|
3257
4437
|
record.addCustomEvent = (tag, payload) => {
|
|
3258
|
-
if (!
|
|
4438
|
+
if (!recording) {
|
|
3259
4439
|
throw new Error('please add custom event after start recording');
|
|
3260
4440
|
}
|
|
3261
4441
|
wrappedEmit(wrapEvent({
|
|
@@ -3270,7 +4450,7 @@ record.freezePage = () => {
|
|
|
3270
4450
|
mutationBuffers.forEach((buf) => buf.freeze());
|
|
3271
4451
|
};
|
|
3272
4452
|
record.takeFullSnapshot = (isCheckout) => {
|
|
3273
|
-
if (!
|
|
4453
|
+
if (!recording) {
|
|
3274
4454
|
throw new Error('please take full snapshot after start recording');
|
|
3275
4455
|
}
|
|
3276
4456
|
takeFullSnapshot(isCheckout);
|
|
@@ -3766,27 +4946,25 @@ const handleDomListener = (
|
|
|
3766
4946
|
|
|
3767
4947
|
/** Get the base DOM breadcrumb. */
|
|
3768
4948
|
function getBaseDomBreadcrumb(target, message) {
|
|
3769
|
-
|
|
3770
|
-
const
|
|
4949
|
+
const nodeId = record.mirror.getId(target);
|
|
4950
|
+
const node = nodeId && record.mirror.getNode(nodeId);
|
|
4951
|
+
const meta = node && record.mirror.getMeta(node);
|
|
4952
|
+
const element = meta && isElement(meta) ? meta : null;
|
|
3771
4953
|
|
|
3772
4954
|
return {
|
|
3773
4955
|
message,
|
|
3774
|
-
data:
|
|
4956
|
+
data: element
|
|
3775
4957
|
? {
|
|
3776
|
-
nodeId
|
|
4958
|
+
nodeId,
|
|
3777
4959
|
node: {
|
|
3778
|
-
id:
|
|
3779
|
-
tagName:
|
|
3780
|
-
textContent:
|
|
3781
|
-
|
|
3782
|
-
|
|
3783
|
-
|
|
3784
|
-
|
|
3785
|
-
|
|
3786
|
-
.map(text => (text ).trim())
|
|
3787
|
-
.join('')
|
|
3788
|
-
: '',
|
|
3789
|
-
attributes: getAttributesToRecord(serializedNode.attributes),
|
|
4960
|
+
id: nodeId,
|
|
4961
|
+
tagName: element.tagName,
|
|
4962
|
+
textContent: Array.from(element.childNodes)
|
|
4963
|
+
.map((node) => node.type === NodeType.Text && node.textContent)
|
|
4964
|
+
.filter(Boolean) // filter out empty values
|
|
4965
|
+
.map(text => (text ).trim())
|
|
4966
|
+
.join(''),
|
|
4967
|
+
attributes: getAttributesToRecord(element.attributes),
|
|
3790
4968
|
},
|
|
3791
4969
|
}
|
|
3792
4970
|
: {},
|
|
@@ -3823,8 +5001,8 @@ function getDomTarget(handlerData) {
|
|
|
3823
5001
|
return { target, message };
|
|
3824
5002
|
}
|
|
3825
5003
|
|
|
3826
|
-
function
|
|
3827
|
-
return
|
|
5004
|
+
function isElement(node) {
|
|
5005
|
+
return node.type === NodeType.Element;
|
|
3828
5006
|
}
|
|
3829
5007
|
|
|
3830
5008
|
/** Handle keyboard events & create breadcrumbs. */
|
|
@@ -4562,7 +5740,6 @@ function makeSession(session) {
|
|
|
4562
5740
|
const lastActivity = session.lastActivity || now;
|
|
4563
5741
|
const segmentId = session.segmentId || 0;
|
|
4564
5742
|
const sampled = session.sampled;
|
|
4565
|
-
const shouldRefresh = typeof session.shouldRefresh === 'boolean' ? session.shouldRefresh : true;
|
|
4566
5743
|
const previousSessionId = session.previousSessionId;
|
|
4567
5744
|
|
|
4568
5745
|
return {
|
|
@@ -4571,7 +5748,6 @@ function makeSession(session) {
|
|
|
4571
5748
|
lastActivity,
|
|
4572
5749
|
segmentId,
|
|
4573
5750
|
sampled,
|
|
4574
|
-
shouldRefresh,
|
|
4575
5751
|
previousSessionId,
|
|
4576
5752
|
};
|
|
4577
5753
|
}
|
|
@@ -4666,46 +5842,19 @@ function isSessionExpired(session, timeouts, targetTime = +new Date()) {
|
|
|
4666
5842
|
);
|
|
4667
5843
|
}
|
|
4668
5844
|
|
|
4669
|
-
/**
|
|
4670
|
-
|
|
4671
|
-
* The refreshed version may be unsampled.
|
|
4672
|
-
* You can check if the session has changed by comparing the session IDs.
|
|
4673
|
-
*/
|
|
4674
|
-
function maybeRefreshSession(
|
|
4675
|
-
session,
|
|
4676
|
-
{
|
|
4677
|
-
timeouts,
|
|
4678
|
-
traceInternals,
|
|
4679
|
-
}
|
|
4680
|
-
|
|
4681
|
-
,
|
|
4682
|
-
sessionOptions,
|
|
4683
|
-
) {
|
|
5845
|
+
/** If the session should be refreshed or not. */
|
|
5846
|
+
function shouldRefreshSession(session, timeouts) {
|
|
4684
5847
|
// If not expired, all good, just keep the session
|
|
4685
5848
|
if (!isSessionExpired(session, timeouts)) {
|
|
4686
|
-
return
|
|
4687
|
-
}
|
|
4688
|
-
|
|
4689
|
-
const isBuffering = session.sampled === 'buffer';
|
|
4690
|
-
|
|
4691
|
-
// If we are buffering & the session may be refreshed, just return it
|
|
4692
|
-
if (isBuffering && session.shouldRefresh) {
|
|
4693
|
-
return session;
|
|
5849
|
+
return false;
|
|
4694
5850
|
}
|
|
4695
5851
|
|
|
4696
|
-
// If we are buffering &
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
logInfoNextTick('[Replay] Session should not be refreshed', traceInternals);
|
|
4700
|
-
return makeSession({ sampled: false });
|
|
5852
|
+
// If we are buffering & haven't ever flushed yet, always continue
|
|
5853
|
+
if (session.sampled === 'buffer' && session.segmentId === 0) {
|
|
5854
|
+
return false;
|
|
4701
5855
|
}
|
|
4702
5856
|
|
|
4703
|
-
|
|
4704
|
-
logInfoNextTick('[Replay] Session has expired, creating new one...', traceInternals);
|
|
4705
|
-
|
|
4706
|
-
const newSession = createSession(sessionOptions, { previousSessionId: session.id });
|
|
4707
|
-
|
|
4708
|
-
return newSession;
|
|
5857
|
+
return true;
|
|
4709
5858
|
}
|
|
4710
5859
|
|
|
4711
5860
|
/**
|
|
@@ -4713,27 +5862,33 @@ function maybeRefreshSession(
|
|
|
4713
5862
|
* Returns a session that may be unsampled.
|
|
4714
5863
|
*/
|
|
4715
5864
|
function loadOrCreateSession(
|
|
4716
|
-
currentSession,
|
|
4717
5865
|
{
|
|
4718
5866
|
timeouts,
|
|
4719
5867
|
traceInternals,
|
|
5868
|
+
previousSessionId,
|
|
4720
5869
|
}
|
|
4721
5870
|
|
|
4722
5871
|
,
|
|
4723
5872
|
sessionOptions,
|
|
4724
5873
|
) {
|
|
4725
|
-
|
|
4726
|
-
const existingSession = currentSession || (sessionOptions.stickySession && fetchSession(traceInternals));
|
|
5874
|
+
const existingSession = sessionOptions.stickySession && fetchSession(traceInternals);
|
|
4727
5875
|
|
|
4728
5876
|
// No session exists yet, just create a new one
|
|
4729
5877
|
if (!existingSession) {
|
|
4730
|
-
logInfoNextTick('[Replay]
|
|
4731
|
-
return createSession(sessionOptions);
|
|
5878
|
+
logInfoNextTick('[Replay] Creating new session', traceInternals);
|
|
5879
|
+
return createSession(sessionOptions, { previousSessionId });
|
|
4732
5880
|
}
|
|
4733
5881
|
|
|
4734
|
-
|
|
5882
|
+
if (!shouldRefreshSession(existingSession, timeouts)) {
|
|
5883
|
+
return existingSession;
|
|
5884
|
+
}
|
|
5885
|
+
|
|
5886
|
+
logInfoNextTick('[Replay] Session in sessionStorage is expired, creating new one...');
|
|
5887
|
+
return createSession(sessionOptions, { previousSessionId: existingSession.id });
|
|
4735
5888
|
}
|
|
4736
5889
|
|
|
5890
|
+
const ReplayEventTypeCustom = 5;
|
|
5891
|
+
|
|
4737
5892
|
function isCustomEvent(event) {
|
|
4738
5893
|
return event.type === EventType.Custom;
|
|
4739
5894
|
}
|
|
@@ -6629,9 +7784,7 @@ function createLargestContentfulPaint(
|
|
|
6629
7784
|
data: {
|
|
6630
7785
|
value, // LCP "duration" in ms
|
|
6631
7786
|
size,
|
|
6632
|
-
|
|
6633
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6634
|
-
nodeId: record.mirror.getId(entry.element ),
|
|
7787
|
+
nodeId: record.mirror.getId(entry.element),
|
|
6635
7788
|
},
|
|
6636
7789
|
};
|
|
6637
7790
|
}
|
|
@@ -7325,7 +8478,7 @@ class ReplayContainer {
|
|
|
7325
8478
|
* Initializes the plugin based on sampling configuration. Should not be
|
|
7326
8479
|
* called outside of constructor.
|
|
7327
8480
|
*/
|
|
7328
|
-
initializeSampling() {
|
|
8481
|
+
initializeSampling(previousSessionId) {
|
|
7329
8482
|
const { errorSampleRate, sessionSampleRate } = this._options;
|
|
7330
8483
|
|
|
7331
8484
|
// If neither sample rate is > 0, then do nothing - user will need to call one of
|
|
@@ -7336,7 +8489,7 @@ class ReplayContainer {
|
|
|
7336
8489
|
|
|
7337
8490
|
// Otherwise if there is _any_ sample rate set, try to load an existing
|
|
7338
8491
|
// session, or create a new one.
|
|
7339
|
-
this._initializeSessionForSampling();
|
|
8492
|
+
this._initializeSessionForSampling(previousSessionId);
|
|
7340
8493
|
|
|
7341
8494
|
if (!this.session) {
|
|
7342
8495
|
// This should not happen, something wrong has occurred
|
|
@@ -7381,7 +8534,6 @@ class ReplayContainer {
|
|
|
7381
8534
|
logInfoNextTick('[Replay] Starting replay in session mode', this._options._experiments.traceInternals);
|
|
7382
8535
|
|
|
7383
8536
|
const session = loadOrCreateSession(
|
|
7384
|
-
this.session,
|
|
7385
8537
|
{
|
|
7386
8538
|
timeouts: this.timeouts,
|
|
7387
8539
|
traceInternals: this._options._experiments.traceInternals,
|
|
@@ -7411,7 +8563,6 @@ class ReplayContainer {
|
|
|
7411
8563
|
logInfoNextTick('[Replay] Starting replay in buffer mode', this._options._experiments.traceInternals);
|
|
7412
8564
|
|
|
7413
8565
|
const session = loadOrCreateSession(
|
|
7414
|
-
this.session,
|
|
7415
8566
|
{
|
|
7416
8567
|
timeouts: this.timeouts,
|
|
7417
8568
|
traceInternals: this._options._experiments.traceInternals,
|
|
@@ -7479,15 +8630,18 @@ class ReplayContainer {
|
|
|
7479
8630
|
return;
|
|
7480
8631
|
}
|
|
7481
8632
|
|
|
8633
|
+
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
8634
|
+
// enter into an infinite loop when `stop()` is called while flushing.
|
|
8635
|
+
this._isEnabled = false;
|
|
8636
|
+
|
|
7482
8637
|
try {
|
|
7483
8638
|
logInfo(
|
|
7484
|
-
`[Replay] Stopping Replay${reason ? ` triggered by ${reason}` : ''}
|
|
8639
|
+
`[Replay] Stopping Replay${reason ? ` triggered by ${reason}` : ''} ${new Date().toISOString()} ${
|
|
8640
|
+
this._isEnabled
|
|
8641
|
+
}`,
|
|
7485
8642
|
this._options._experiments.traceInternals,
|
|
7486
8643
|
);
|
|
7487
8644
|
|
|
7488
|
-
// We can't move `_isEnabled` after awaiting a flush, otherwise we can
|
|
7489
|
-
// enter into an infinite loop when `stop()` is called while flushing.
|
|
7490
|
-
this._isEnabled = false;
|
|
7491
8645
|
this._removeListeners();
|
|
7492
8646
|
this.stopRecording();
|
|
7493
8647
|
|
|
@@ -7581,16 +8735,6 @@ class ReplayContainer {
|
|
|
7581
8735
|
|
|
7582
8736
|
// Once this session ends, we do not want to refresh it
|
|
7583
8737
|
if (this.session) {
|
|
7584
|
-
this.session.shouldRefresh = false;
|
|
7585
|
-
|
|
7586
|
-
// It's possible that the session lifespan is > max session lifespan
|
|
7587
|
-
// because we have been buffering beyond max session lifespan (we ignore
|
|
7588
|
-
// expiration given that `shouldRefresh` is true). Since we flip
|
|
7589
|
-
// `shouldRefresh`, the session could be considered expired due to
|
|
7590
|
-
// lifespan, which is not what we want. Update session start date to be
|
|
7591
|
-
// the current timestamp, so that session is not considered to be
|
|
7592
|
-
// expired. This means that max replay duration can be MAX_SESSION_LIFE +
|
|
7593
|
-
// (length of buffer), which we are ok with.
|
|
7594
8738
|
this._updateUserActivity(activityTime);
|
|
7595
8739
|
this._updateSessionActivity(activityTime);
|
|
7596
8740
|
this._maybeSaveSession();
|
|
@@ -7752,7 +8896,11 @@ class ReplayContainer {
|
|
|
7752
8896
|
}
|
|
7753
8897
|
|
|
7754
8898
|
// Session is expired, trigger a full snapshot (which will create a new session)
|
|
7755
|
-
this.
|
|
8899
|
+
if (this.isPaused()) {
|
|
8900
|
+
this.resume();
|
|
8901
|
+
} else {
|
|
8902
|
+
this._triggerFullSnapshot();
|
|
8903
|
+
}
|
|
7756
8904
|
|
|
7757
8905
|
return false;
|
|
7758
8906
|
}
|
|
@@ -7795,7 +8943,7 @@ class ReplayContainer {
|
|
|
7795
8943
|
|
|
7796
8944
|
this.addUpdate(() => {
|
|
7797
8945
|
void addEvent(this, {
|
|
7798
|
-
type:
|
|
8946
|
+
type: ReplayEventTypeCustom,
|
|
7799
8947
|
timestamp: breadcrumb.timestamp || 0,
|
|
7800
8948
|
data: {
|
|
7801
8949
|
tag: 'breadcrumb',
|
|
@@ -7842,6 +8990,7 @@ class ReplayContainer {
|
|
|
7842
8990
|
|
|
7843
8991
|
// Need to set as enabled before we start recording, as `record()` can trigger a flush with a new checkout
|
|
7844
8992
|
this._isEnabled = true;
|
|
8993
|
+
this._isPaused = false;
|
|
7845
8994
|
|
|
7846
8995
|
this.startRecording();
|
|
7847
8996
|
}
|
|
@@ -7858,16 +9007,16 @@ class ReplayContainer {
|
|
|
7858
9007
|
/**
|
|
7859
9008
|
* Loads (or refreshes) the current session.
|
|
7860
9009
|
*/
|
|
7861
|
-
_initializeSessionForSampling() {
|
|
9010
|
+
_initializeSessionForSampling(previousSessionId) {
|
|
7862
9011
|
// Whenever there is _any_ error sample rate, we always allow buffering
|
|
7863
9012
|
// Because we decide on sampling when an error occurs, we need to buffer at all times if sampling for errors
|
|
7864
9013
|
const allowBuffering = this._options.errorSampleRate > 0;
|
|
7865
9014
|
|
|
7866
9015
|
const session = loadOrCreateSession(
|
|
7867
|
-
this.session,
|
|
7868
9016
|
{
|
|
7869
9017
|
timeouts: this.timeouts,
|
|
7870
9018
|
traceInternals: this._options._experiments.traceInternals,
|
|
9019
|
+
previousSessionId,
|
|
7871
9020
|
},
|
|
7872
9021
|
{
|
|
7873
9022
|
stickySession: this._options.stickySession,
|
|
@@ -7892,36 +9041,27 @@ class ReplayContainer {
|
|
|
7892
9041
|
|
|
7893
9042
|
const currentSession = this.session;
|
|
7894
9043
|
|
|
7895
|
-
|
|
7896
|
-
currentSession
|
|
7897
|
-
{
|
|
7898
|
-
timeouts: this.timeouts,
|
|
7899
|
-
traceInternals: this._options._experiments.traceInternals,
|
|
7900
|
-
},
|
|
7901
|
-
{
|
|
7902
|
-
stickySession: Boolean(this._options.stickySession),
|
|
7903
|
-
sessionSampleRate: this._options.sessionSampleRate,
|
|
7904
|
-
allowBuffering: this._options.errorSampleRate > 0,
|
|
7905
|
-
},
|
|
7906
|
-
);
|
|
7907
|
-
|
|
7908
|
-
const isNew = newSession.id !== currentSession.id;
|
|
7909
|
-
|
|
7910
|
-
// If session was newly created (i.e. was not loaded from storage), then
|
|
7911
|
-
// enable flag to create the root replay
|
|
7912
|
-
if (isNew) {
|
|
7913
|
-
this.setInitialState();
|
|
7914
|
-
this.session = newSession;
|
|
7915
|
-
}
|
|
7916
|
-
|
|
7917
|
-
if (!this.session.sampled) {
|
|
7918
|
-
void this.stop({ reason: 'session not refreshed' });
|
|
9044
|
+
if (shouldRefreshSession(currentSession, this.timeouts)) {
|
|
9045
|
+
void this._refreshSession(currentSession);
|
|
7919
9046
|
return false;
|
|
7920
9047
|
}
|
|
7921
9048
|
|
|
7922
9049
|
return true;
|
|
7923
9050
|
}
|
|
7924
9051
|
|
|
9052
|
+
/**
|
|
9053
|
+
* Refresh a session with a new one.
|
|
9054
|
+
* This stops the current session (without forcing a flush, as that would never work since we are expired),
|
|
9055
|
+
* and then does a new sampling based on the refreshed session.
|
|
9056
|
+
*/
|
|
9057
|
+
async _refreshSession(session) {
|
|
9058
|
+
if (!this._isEnabled) {
|
|
9059
|
+
return;
|
|
9060
|
+
}
|
|
9061
|
+
await this.stop({ reason: 'refresh session' });
|
|
9062
|
+
this.initializeSampling(session.id);
|
|
9063
|
+
}
|
|
9064
|
+
|
|
7925
9065
|
/**
|
|
7926
9066
|
* Adds listeners to record events for the replay
|
|
7927
9067
|
*/
|
|
@@ -8178,7 +9318,9 @@ class ReplayContainer {
|
|
|
8178
9318
|
* Should never be called directly, only by `flush`
|
|
8179
9319
|
*/
|
|
8180
9320
|
async _runFlush() {
|
|
8181
|
-
|
|
9321
|
+
const replayId = this.getSessionId();
|
|
9322
|
+
|
|
9323
|
+
if (!this.session || !this.eventBuffer || !replayId) {
|
|
8182
9324
|
(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && utils.logger.error('[Replay] No session or eventBuffer found to flush.');
|
|
8183
9325
|
return;
|
|
8184
9326
|
}
|
|
@@ -8198,13 +9340,15 @@ class ReplayContainer {
|
|
|
8198
9340
|
return;
|
|
8199
9341
|
}
|
|
8200
9342
|
|
|
9343
|
+
// if this changed in the meanwhile, e.g. because the session was refreshed or similar, we abort here
|
|
9344
|
+
if (replayId !== this.getSessionId()) {
|
|
9345
|
+
return;
|
|
9346
|
+
}
|
|
9347
|
+
|
|
8201
9348
|
try {
|
|
8202
9349
|
// This uses the data from the eventBuffer, so we need to call this before `finish()
|
|
8203
9350
|
this._updateInitialTimestampFromEventBuffer();
|
|
8204
9351
|
|
|
8205
|
-
// Note this empties the event buffer regardless of outcome of sending replay
|
|
8206
|
-
const recordingData = await this.eventBuffer.finish();
|
|
8207
|
-
|
|
8208
9352
|
const timestamp = Date.now();
|
|
8209
9353
|
|
|
8210
9354
|
// Check total duration again, to avoid sending outdated stuff
|
|
@@ -8214,14 +9358,14 @@ class ReplayContainer {
|
|
|
8214
9358
|
throw new Error('Session is too long, not sending replay');
|
|
8215
9359
|
}
|
|
8216
9360
|
|
|
8217
|
-
// NOTE: Copy values from instance members, as it's possible they could
|
|
8218
|
-
// change before the flush finishes.
|
|
8219
|
-
const replayId = this.session.id;
|
|
8220
9361
|
const eventContext = this._popEventContext();
|
|
8221
9362
|
// Always increment segmentId regardless of outcome of sending replay
|
|
8222
9363
|
const segmentId = this.session.segmentId++;
|
|
8223
9364
|
this._maybeSaveSession();
|
|
8224
9365
|
|
|
9366
|
+
// Note this empties the event buffer regardless of outcome of sending replay
|
|
9367
|
+
const recordingData = await this.eventBuffer.finish();
|
|
9368
|
+
|
|
8225
9369
|
await sendReplay({
|
|
8226
9370
|
replayId,
|
|
8227
9371
|
recordingData,
|
|
@@ -8428,8 +9572,6 @@ function getPrivacyOptions({
|
|
|
8428
9572
|
// We are making the decision to make text and input selectors the same
|
|
8429
9573
|
maskTextSelector: maskSelector,
|
|
8430
9574
|
unmaskTextSelector: unmaskSelector,
|
|
8431
|
-
maskInputSelector: maskSelector,
|
|
8432
|
-
unmaskInputSelector: unmaskSelector,
|
|
8433
9575
|
|
|
8434
9576
|
blockSelector: getOption(
|
|
8435
9577
|
block,
|
|
@@ -8465,6 +9607,39 @@ function isElectronNodeRenderer() {
|
|
|
8465
9607
|
return typeof process !== 'undefined' && (process ).type === 'renderer';
|
|
8466
9608
|
}
|
|
8467
9609
|
|
|
9610
|
+
/**
|
|
9611
|
+
* Masks an attribute if necessary, otherwise return attribute value as-is.
|
|
9612
|
+
*/
|
|
9613
|
+
function maskAttribute({
|
|
9614
|
+
el,
|
|
9615
|
+
key,
|
|
9616
|
+
maskAttributes,
|
|
9617
|
+
maskAllText,
|
|
9618
|
+
privacyOptions,
|
|
9619
|
+
value,
|
|
9620
|
+
}) {
|
|
9621
|
+
// We only mask attributes if `maskAllText` is true
|
|
9622
|
+
if (!maskAllText) {
|
|
9623
|
+
return value;
|
|
9624
|
+
}
|
|
9625
|
+
|
|
9626
|
+
// unmaskTextSelector takes precendence
|
|
9627
|
+
if (privacyOptions.unmaskTextSelector && el.matches(privacyOptions.unmaskTextSelector)) {
|
|
9628
|
+
return value;
|
|
9629
|
+
}
|
|
9630
|
+
|
|
9631
|
+
if (
|
|
9632
|
+
maskAttributes.includes(key) ||
|
|
9633
|
+
// Need to mask `value` attribute for `<input>` if it's a button-like
|
|
9634
|
+
// type
|
|
9635
|
+
(key === 'value' && el.tagName === 'INPUT' && ['submit', 'button'].includes(el.getAttribute('type') || ''))
|
|
9636
|
+
) {
|
|
9637
|
+
return value.replace(/[\S]/g, '*');
|
|
9638
|
+
}
|
|
9639
|
+
|
|
9640
|
+
return value;
|
|
9641
|
+
}
|
|
9642
|
+
|
|
8468
9643
|
const MEDIA_SELECTORS =
|
|
8469
9644
|
'img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]';
|
|
8470
9645
|
|
|
@@ -8523,6 +9698,7 @@ class Replay {
|
|
|
8523
9698
|
networkResponseHeaders = [],
|
|
8524
9699
|
|
|
8525
9700
|
mask = [],
|
|
9701
|
+
maskAttributes = ['title', 'placeholder'],
|
|
8526
9702
|
unmask = [],
|
|
8527
9703
|
block = [],
|
|
8528
9704
|
unblock = [],
|
|
@@ -8546,25 +9722,36 @@ class Replay {
|
|
|
8546
9722
|
} = {}) {
|
|
8547
9723
|
this.name = Replay.id;
|
|
8548
9724
|
|
|
9725
|
+
const privacyOptions = getPrivacyOptions({
|
|
9726
|
+
mask,
|
|
9727
|
+
unmask,
|
|
9728
|
+
block,
|
|
9729
|
+
unblock,
|
|
9730
|
+
ignore,
|
|
9731
|
+
blockClass,
|
|
9732
|
+
blockSelector,
|
|
9733
|
+
maskTextClass,
|
|
9734
|
+
maskTextSelector,
|
|
9735
|
+
ignoreClass,
|
|
9736
|
+
});
|
|
9737
|
+
|
|
8549
9738
|
this._recordingOptions = {
|
|
8550
9739
|
maskAllInputs,
|
|
8551
9740
|
maskAllText,
|
|
8552
9741
|
maskInputOptions: { ...(maskInputOptions || {}), password: true },
|
|
8553
9742
|
maskTextFn: maskFn,
|
|
8554
9743
|
maskInputFn: maskFn,
|
|
9744
|
+
maskAttributeFn: (key, value, el) =>
|
|
9745
|
+
maskAttribute({
|
|
9746
|
+
maskAttributes,
|
|
9747
|
+
maskAllText,
|
|
9748
|
+
privacyOptions,
|
|
9749
|
+
key,
|
|
9750
|
+
value,
|
|
9751
|
+
el,
|
|
9752
|
+
}),
|
|
8555
9753
|
|
|
8556
|
-
...
|
|
8557
|
-
mask,
|
|
8558
|
-
unmask,
|
|
8559
|
-
block,
|
|
8560
|
-
unblock,
|
|
8561
|
-
ignore,
|
|
8562
|
-
blockClass,
|
|
8563
|
-
blockSelector,
|
|
8564
|
-
maskTextClass,
|
|
8565
|
-
maskTextSelector,
|
|
8566
|
-
ignoreClass,
|
|
8567
|
-
}),
|
|
9754
|
+
...privacyOptions,
|
|
8568
9755
|
|
|
8569
9756
|
// Our defaults
|
|
8570
9757
|
slimDOMOptions: 'all',
|
|
@@ -8574,6 +9761,16 @@ class Replay {
|
|
|
8574
9761
|
// collect fonts, but be aware that `sentry.io` needs to be an allowed
|
|
8575
9762
|
// origin for playback
|
|
8576
9763
|
collectFonts: true,
|
|
9764
|
+
errorHandler: (err) => {
|
|
9765
|
+
try {
|
|
9766
|
+
// @ts-ignore Set this so that replay SDK can ignore errors originating from rrweb
|
|
9767
|
+
err.__rrweb__ = true;
|
|
9768
|
+
} catch (e) {
|
|
9769
|
+
// avoid any potential hazards here
|
|
9770
|
+
}
|
|
9771
|
+
// return true to suppress throwing the error inside of rrweb
|
|
9772
|
+
return true;
|
|
9773
|
+
},
|
|
8577
9774
|
};
|
|
8578
9775
|
|
|
8579
9776
|
this._initialOptions = {
|