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