@sentry/replay 7.72.0 → 7.74.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 CHANGED
@@ -63,44 +63,159 @@ var NodeType$1;
63
63
  NodeType[NodeType["Comment"] = 5] = "Comment";
64
64
  })(NodeType$1 || (NodeType$1 = {}));
65
65
 
66
- function isElement(n) {
66
+ function isElement$1(n) {
67
67
  return n.nodeType === n.ELEMENT_NODE;
68
68
  }
69
69
  function isShadowRoot(n) {
70
70
  const host = n === null || n === void 0 ? void 0 : n.host;
71
- return Boolean(host && host.shadowRoot && host.shadowRoot === n);
71
+ return Boolean((host === null || host === void 0 ? void 0 : host.shadowRoot) === n);
72
72
  }
73
- function isInputTypeMasked({ maskInputOptions, tagName, type, }) {
74
- if (tagName.toLowerCase() === 'option') {
75
- tagName = 'select';
73
+ function isNativeShadowDom(shadowRoot) {
74
+ return Object.prototype.toString.call(shadowRoot) === '[object ShadowRoot]';
75
+ }
76
+ function fixBrowserCompatibilityIssuesInCSS(cssText) {
77
+ if (cssText.includes(' background-clip: text;') &&
78
+ !cssText.includes(' -webkit-background-clip: text;')) {
79
+ cssText = cssText.replace(' background-clip: text;', ' -webkit-background-clip: text; background-clip: text;');
76
80
  }
77
- const actualType = typeof type === 'string' ? type.toLowerCase() : undefined;
78
- return (maskInputOptions[tagName.toLowerCase()] ||
79
- (actualType && maskInputOptions[actualType]) ||
80
- actualType === 'password' ||
81
- (tagName === 'input' && !type && maskInputOptions['text']));
81
+ return cssText;
82
82
  }
83
- function hasInputMaskOptions({ tagName, type, maskInputOptions, maskInputSelector, }) {
84
- return (maskInputSelector || isInputTypeMasked({ maskInputOptions, tagName, type }));
83
+ function escapeImportStatement(rule) {
84
+ const { cssText } = rule;
85
+ if (cssText.split('"').length < 3)
86
+ return cssText;
87
+ const statement = ['@import', `url(${JSON.stringify(rule.href)})`];
88
+ if (rule.layerName === '') {
89
+ statement.push(`layer`);
90
+ }
91
+ else if (rule.layerName) {
92
+ statement.push(`layer(${rule.layerName})`);
93
+ }
94
+ if (rule.supportsText) {
95
+ statement.push(`supports(${rule.supportsText})`);
96
+ }
97
+ if (rule.media.length) {
98
+ statement.push(rule.media.mediaText);
99
+ }
100
+ return statement.join(' ') + ';';
85
101
  }
86
- function maskInputValue({ input, maskInputSelector, unmaskInputSelector, maskInputOptions, tagName, type, value, maskInputFn, }) {
87
- let text = value || '';
88
- if (unmaskInputSelector && input.matches(unmaskInputSelector)) {
89
- return text;
102
+ function stringifyStylesheet(s) {
103
+ try {
104
+ const rules = s.rules || s.cssRules;
105
+ return rules
106
+ ? fixBrowserCompatibilityIssuesInCSS(Array.from(rules, stringifyRule).join(''))
107
+ : null;
90
108
  }
91
- if (input.hasAttribute('data-rr-is-password')) {
92
- type = 'password';
109
+ catch (error) {
110
+ return null;
93
111
  }
94
- if (isInputTypeMasked({ maskInputOptions, tagName, type }) ||
95
- (maskInputSelector && input.matches(maskInputSelector))) {
96
- if (maskInputFn) {
97
- text = maskInputFn(text);
112
+ }
113
+ function stringifyRule(rule) {
114
+ let importStringified;
115
+ if (isCSSImportRule(rule)) {
116
+ try {
117
+ importStringified =
118
+ stringifyStylesheet(rule.styleSheet) ||
119
+ escapeImportStatement(rule);
98
120
  }
99
- else {
100
- text = '*'.repeat(text.length);
121
+ catch (error) {
122
+ }
123
+ }
124
+ else if (isCSSStyleRule(rule) && rule.selectorText.includes(':')) {
125
+ return fixSafariColons(rule.cssText);
126
+ }
127
+ return importStringified || rule.cssText;
128
+ }
129
+ function fixSafariColons(cssStringified) {
130
+ const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
131
+ return cssStringified.replace(regex, '$1\\$2');
132
+ }
133
+ function isCSSImportRule(rule) {
134
+ return 'styleSheet' in rule;
135
+ }
136
+ function isCSSStyleRule(rule) {
137
+ return 'selectorText' in rule;
138
+ }
139
+ class Mirror {
140
+ constructor() {
141
+ this.idNodeMap = new Map();
142
+ this.nodeMetaMap = new WeakMap();
143
+ }
144
+ getId(n) {
145
+ var _a;
146
+ if (!n)
147
+ return -1;
148
+ const id = (_a = this.getMeta(n)) === null || _a === void 0 ? void 0 : _a.id;
149
+ return id !== null && id !== void 0 ? id : -1;
150
+ }
151
+ getNode(id) {
152
+ return this.idNodeMap.get(id) || null;
153
+ }
154
+ getIds() {
155
+ return Array.from(this.idNodeMap.keys());
156
+ }
157
+ getMeta(n) {
158
+ return this.nodeMetaMap.get(n) || null;
159
+ }
160
+ removeNodeFromMap(n) {
161
+ const id = this.getId(n);
162
+ this.idNodeMap.delete(id);
163
+ if (n.childNodes) {
164
+ n.childNodes.forEach((childNode) => this.removeNodeFromMap(childNode));
101
165
  }
102
166
  }
103
- return text;
167
+ has(id) {
168
+ return this.idNodeMap.has(id);
169
+ }
170
+ hasNode(node) {
171
+ return this.nodeMetaMap.has(node);
172
+ }
173
+ add(n, meta) {
174
+ const id = meta.id;
175
+ this.idNodeMap.set(id, n);
176
+ this.nodeMetaMap.set(n, meta);
177
+ }
178
+ replace(id, n) {
179
+ const oldNode = this.getNode(id);
180
+ if (oldNode) {
181
+ const meta = this.nodeMetaMap.get(oldNode);
182
+ if (meta)
183
+ this.nodeMetaMap.set(n, meta);
184
+ }
185
+ this.idNodeMap.set(id, n);
186
+ }
187
+ reset() {
188
+ this.idNodeMap = new Map();
189
+ this.nodeMetaMap = new WeakMap();
190
+ }
191
+ }
192
+ function createMirror() {
193
+ return new Mirror();
194
+ }
195
+ function shouldMaskInput({ maskInputOptions, tagName, type, }) {
196
+ if (tagName === 'OPTION') {
197
+ tagName = 'SELECT';
198
+ }
199
+ return Boolean(maskInputOptions[tagName.toLowerCase()] ||
200
+ (type && maskInputOptions[type]) ||
201
+ type === 'password' ||
202
+ (tagName === 'INPUT' && !type && maskInputOptions['text']));
203
+ }
204
+ function maskInputValue({ isMasked, element, value, maskInputFn, }) {
205
+ let text = value || '';
206
+ if (!isMasked) {
207
+ return text;
208
+ }
209
+ if (maskInputFn) {
210
+ text = maskInputFn(text, element);
211
+ }
212
+ return '*'.repeat(text.length);
213
+ }
214
+ function toLowerCase(str) {
215
+ return str.toLowerCase();
216
+ }
217
+ function toUpperCase(str) {
218
+ return str.toUpperCase();
104
219
  }
105
220
  const ORIGINAL_ATTRIBUTE_NAME = '__rrweb_original__';
106
221
  function is2DCanvasBlank(canvas) {
@@ -126,11 +241,11 @@ function getInputType(element) {
126
241
  return element.hasAttribute('data-rr-is-password')
127
242
  ? 'password'
128
243
  : type
129
- ? type.toLowerCase()
244
+ ?
245
+ toLowerCase(type)
130
246
  : null;
131
247
  }
132
248
  function getInputValue(el, tagName, type) {
133
- typeof type === 'string' ? type.toLowerCase() : '';
134
249
  if (tagName === 'INPUT' && (type === 'radio' || type === 'checkbox')) {
135
250
  return el.getAttribute('value') || '';
136
251
  }
@@ -140,9 +255,6 @@ function getInputValue(el, tagName, type) {
140
255
  let _id = 1;
141
256
  const tagNameRegex = new RegExp('[^a-z0-9-_:]');
142
257
  const IGNORED_NODE = -2;
143
- function defaultMaskFn(str) {
144
- return str ? str.replace(/[\S]/g, '*') : '';
145
- }
146
258
  function genId() {
147
259
  return _id++;
148
260
  }
@@ -150,49 +262,12 @@ function getValidTagName(element) {
150
262
  if (element instanceof HTMLFormElement) {
151
263
  return 'form';
152
264
  }
153
- const processedTagName = element.tagName.toLowerCase().trim();
265
+ const processedTagName = toLowerCase(element.tagName);
154
266
  if (tagNameRegex.test(processedTagName)) {
155
267
  return 'div';
156
268
  }
157
269
  return processedTagName;
158
270
  }
159
- function getCssRulesString(s) {
160
- try {
161
- const rules = s.rules || s.cssRules;
162
- return rules ? Array.from(rules).map(getCssRuleString).join('') : null;
163
- }
164
- catch (error) {
165
- return null;
166
- }
167
- }
168
- function getCssRuleString(rule) {
169
- let cssStringified = rule.cssText;
170
- if (isCSSImportRule(rule)) {
171
- try {
172
- cssStringified = getCssRulesString(rule.styleSheet) || cssStringified;
173
- }
174
- catch (_a) {
175
- }
176
- }
177
- return validateStringifiedCssRule(cssStringified);
178
- }
179
- function validateStringifiedCssRule(cssStringified) {
180
- if (cssStringified.indexOf(':') > -1) {
181
- const regex = /(\[(?:[\w-]+)[^\\])(:(?:[\w-]+)\])/gm;
182
- return cssStringified.replace(regex, '$1\\$2');
183
- }
184
- return cssStringified;
185
- }
186
- function isCSSImportRule(rule) {
187
- return 'styleSheet' in rule;
188
- }
189
- function stringifyStyleSheet(sheet) {
190
- return sheet.cssRules
191
- ? Array.from(sheet.cssRules)
192
- .map((rule) => rule.cssText ? validateStringifiedCssRule(rule.cssText) : '')
193
- .join('')
194
- : '';
195
- }
196
271
  function extractOrigin(url) {
197
272
  let origin = '';
198
273
  if (url.indexOf('//') > -1) {
@@ -207,7 +282,8 @@ function extractOrigin(url) {
207
282
  let canvasService;
208
283
  let canvasCtx;
209
284
  const URL_IN_CSS_REF = /url\((?:(')([^']*)'|(")(.*?)"|([^)]*))\)/gm;
210
- const RELATIVE_PATH = /^(?!www\.|(?:http|ftp)s?:\/\/|[A-Za-z]:\\|\/\/|#).*/;
285
+ const URL_PROTOCOL_MATCH = /^(?:[a-z+]+:)?\/\//i;
286
+ const URL_WWW_MATCH = /^www\..*/i;
211
287
  const DATA_URI = /^(data:)([^,]*),(.*)/i;
212
288
  function absoluteToStylesheet(cssText, href) {
213
289
  return (cssText || '').replace(URL_IN_CSS_REF, (origin, quote1, path1, quote2, path2, path3) => {
@@ -216,7 +292,7 @@ function absoluteToStylesheet(cssText, href) {
216
292
  if (!filePath) {
217
293
  return origin;
218
294
  }
219
- if (!RELATIVE_PATH.test(filePath)) {
295
+ if (URL_PROTOCOL_MATCH.test(filePath) || URL_WWW_MATCH.test(filePath)) {
220
296
  return `url(${maybeQuote}${filePath}${maybeQuote})`;
221
297
  }
222
298
  if (DATA_URI.test(filePath)) {
@@ -251,7 +327,7 @@ function getAbsoluteSrcsetString(doc, attributeValue) {
251
327
  let pos = 0;
252
328
  function collectCharacters(regEx) {
253
329
  let chars;
254
- let match = regEx.exec(attributeValue.substring(pos));
330
+ const match = regEx.exec(attributeValue.substring(pos));
255
331
  if (match) {
256
332
  chars = match[0];
257
333
  pos += chars.length;
@@ -259,7 +335,7 @@ function getAbsoluteSrcsetString(doc, attributeValue) {
259
335
  }
260
336
  return '';
261
337
  }
262
- let output = [];
338
+ const output = [];
263
339
  while (true) {
264
340
  collectCharacters(SRCSET_COMMAS_OR_SPACES);
265
341
  if (pos >= attributeValue.length) {
@@ -275,7 +351,7 @@ function getAbsoluteSrcsetString(doc, attributeValue) {
275
351
  url = absoluteToDoc(doc, url);
276
352
  let inParens = false;
277
353
  while (true) {
278
- let c = attributeValue.charAt(pos);
354
+ const c = attributeValue.charAt(pos);
279
355
  if (c === '') {
280
356
  output.push((url + descriptorsStr).trim());
281
357
  break;
@@ -318,13 +394,12 @@ function getHref() {
318
394
  a.href = '';
319
395
  return a.href;
320
396
  }
321
- function transformAttribute(doc, element, _tagName, _name, value, maskAllText, unmaskTextSelector, maskTextFn) {
397
+ function transformAttribute(doc, tagName, name, value, element, maskAttributeFn) {
322
398
  if (!value) {
323
399
  return value;
324
400
  }
325
- const name = _name.toLowerCase();
326
- const tagName = _tagName.toLowerCase();
327
- if (name === 'src' || name === 'href') {
401
+ if (name === 'src' ||
402
+ (name === 'href' && !(tagName === 'use' && value[0] === '#'))) {
328
403
  return absoluteToDoc(doc, value);
329
404
  }
330
405
  else if (name === 'xlink:href' && value[0] !== '#') {
@@ -343,79 +418,113 @@ function transformAttribute(doc, element, _tagName, _name, value, maskAllText, u
343
418
  else if (tagName === 'object' && name === 'data') {
344
419
  return absoluteToDoc(doc, value);
345
420
  }
346
- else if (maskAllText &&
347
- _shouldMaskAttribute(element, name, tagName, unmaskTextSelector)) {
348
- return maskTextFn ? maskTextFn(value) : defaultMaskFn(value);
421
+ if (typeof maskAttributeFn === 'function') {
422
+ return maskAttributeFn(name, value, element);
349
423
  }
350
424
  return value;
351
425
  }
352
- function _shouldMaskAttribute(element, attribute, tagName, unmaskTextSelector) {
353
- if (unmaskTextSelector && element.matches(unmaskTextSelector)) {
354
- return false;
355
- }
356
- return (['placeholder', 'title', 'aria-label'].indexOf(attribute) > -1 ||
357
- (tagName === 'input' &&
358
- attribute === 'value' &&
359
- element.hasAttribute('type') &&
360
- ['submit', 'button'].indexOf(element.getAttribute('type').toLowerCase()) > -1));
426
+ function ignoreAttribute(tagName, name, _value) {
427
+ return (tagName === 'video' || tagName === 'audio') && name === 'autoplay';
361
428
  }
362
429
  function _isBlockedElement(element, blockClass, blockSelector, unblockSelector) {
363
- if (unblockSelector && element.matches(unblockSelector)) {
364
- return false;
365
- }
366
- if (typeof blockClass === 'string') {
367
- if (element.classList.contains(blockClass)) {
368
- return true;
430
+ try {
431
+ if (unblockSelector && element.matches(unblockSelector)) {
432
+ return false;
369
433
  }
370
- }
371
- else {
372
- for (let eIndex = 0; eIndex < element.classList.length; eIndex++) {
373
- const className = element.classList[eIndex];
374
- if (blockClass.test(className)) {
434
+ if (typeof blockClass === 'string') {
435
+ if (element.classList.contains(blockClass)) {
375
436
  return true;
376
437
  }
377
438
  }
439
+ else {
440
+ for (let eIndex = element.classList.length; eIndex--;) {
441
+ const className = element.classList[eIndex];
442
+ if (blockClass.test(className)) {
443
+ return true;
444
+ }
445
+ }
446
+ }
447
+ if (blockSelector) {
448
+ return element.matches(blockSelector);
449
+ }
378
450
  }
379
- if (blockSelector) {
380
- return element.matches(blockSelector);
451
+ catch (e) {
381
452
  }
382
453
  return false;
383
454
  }
384
- function needMaskingText(node, maskTextClass, maskTextSelector, unmaskTextSelector, maskAllText) {
385
- if (!node) {
386
- return false;
387
- }
388
- if (node.nodeType !== node.ELEMENT_NODE) {
389
- return needMaskingText(node.parentNode, maskTextClass, maskTextSelector, unmaskTextSelector, maskAllText);
390
- }
391
- if (unmaskTextSelector) {
392
- if (node.matches(unmaskTextSelector) ||
393
- node.closest(unmaskTextSelector)) {
394
- return false;
395
- }
396
- }
397
- if (maskAllText) {
398
- return true;
399
- }
400
- if (typeof maskTextClass === 'string') {
401
- if (node.classList.contains(maskTextClass)) {
455
+ function elementClassMatchesRegex(el, regex) {
456
+ for (let eIndex = el.classList.length; eIndex--;) {
457
+ const className = el.classList[eIndex];
458
+ if (regex.test(className)) {
402
459
  return true;
403
460
  }
404
461
  }
405
- else {
406
- for (let eIndex = 0; eIndex < node.classList.length; eIndex++) {
407
- const className = node.classList[eIndex];
408
- if (maskTextClass.test(className)) {
462
+ return false;
463
+ }
464
+ function distanceToMatch(node, matchPredicate, limit = Infinity, distance = 0) {
465
+ if (!node)
466
+ return -1;
467
+ if (node.nodeType !== node.ELEMENT_NODE)
468
+ return -1;
469
+ if (distance > limit)
470
+ return -1;
471
+ if (matchPredicate(node))
472
+ return distance;
473
+ return distanceToMatch(node.parentNode, matchPredicate, limit, distance + 1);
474
+ }
475
+ function createMatchPredicate(className, selector) {
476
+ return (node) => {
477
+ const el = node;
478
+ if (el === null)
479
+ return false;
480
+ if (className) {
481
+ if (typeof className === 'string') {
482
+ if (el.matches(`.${className}`))
483
+ return true;
484
+ }
485
+ else if (elementClassMatchesRegex(el, className)) {
409
486
  return true;
410
487
  }
411
488
  }
412
- }
413
- if (maskTextSelector) {
414
- if (node.matches(maskTextSelector)) {
489
+ if (selector && el.matches(selector))
415
490
  return true;
491
+ return false;
492
+ };
493
+ }
494
+ function needMaskingText(node, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, maskAllText) {
495
+ try {
496
+ const el = node.nodeType === node.ELEMENT_NODE
497
+ ? node
498
+ : node.parentElement;
499
+ if (el === null)
500
+ return false;
501
+ let maskDistance = -1;
502
+ let unmaskDistance = -1;
503
+ if (maskAllText) {
504
+ unmaskDistance = distanceToMatch(el, createMatchPredicate(unmaskTextClass, unmaskTextSelector));
505
+ if (unmaskDistance < 0) {
506
+ return true;
507
+ }
508
+ maskDistance = distanceToMatch(el, createMatchPredicate(maskTextClass, maskTextSelector), unmaskDistance >= 0 ? unmaskDistance : Infinity);
509
+ }
510
+ else {
511
+ maskDistance = distanceToMatch(el, createMatchPredicate(maskTextClass, maskTextSelector));
512
+ if (maskDistance < 0) {
513
+ return false;
514
+ }
515
+ unmaskDistance = distanceToMatch(el, createMatchPredicate(unmaskTextClass, unmaskTextSelector), maskDistance >= 0 ? maskDistance : Infinity);
416
516
  }
517
+ return maskDistance >= 0
518
+ ? unmaskDistance >= 0
519
+ ? maskDistance <= unmaskDistance
520
+ : true
521
+ : unmaskDistance >= 0
522
+ ? false
523
+ : !!maskAllText;
524
+ }
525
+ catch (e) {
417
526
  }
418
- return needMaskingText(node.parentNode, maskTextClass, maskTextSelector, unmaskTextSelector, maskAllText);
527
+ return !!maskAllText;
419
528
  }
420
529
  function onceIframeLoaded(iframeEl, listener, iframeLoadTimeout) {
421
530
  const win = iframeEl.contentWindow;
@@ -449,18 +558,36 @@ function onceIframeLoaded(iframeEl, listener, iframeLoadTimeout) {
449
558
  iframeEl.src === blankUrl ||
450
559
  iframeEl.src === '') {
451
560
  setTimeout(listener, 0);
452
- return;
561
+ return iframeEl.addEventListener('load', listener);
453
562
  }
454
563
  iframeEl.addEventListener('load', listener);
455
564
  }
456
- function serializeNode(n, options) {
457
- var _a;
458
- const { doc, blockClass, blockSelector, unblockSelector, maskTextClass, maskTextSelector, unmaskTextSelector, inlineStylesheet, maskInputSelector, unmaskInputSelector, maskAllText, maskInputOptions = {}, maskTextFn, maskInputFn, dataURLOptions = {}, inlineImages, recordCanvas, keepIframeSrcFn, } = options;
459
- let rootId;
460
- if (doc.__sn) {
461
- const docId = doc.__sn.id;
462
- rootId = docId === 1 ? undefined : docId;
565
+ function onceStylesheetLoaded(link, listener, styleSheetLoadTimeout) {
566
+ let fired = false;
567
+ let styleSheetLoaded;
568
+ try {
569
+ styleSheetLoaded = link.sheet;
570
+ }
571
+ catch (error) {
572
+ return;
463
573
  }
574
+ if (styleSheetLoaded)
575
+ return;
576
+ const timer = setTimeout(() => {
577
+ if (!fired) {
578
+ listener();
579
+ fired = true;
580
+ }
581
+ }, styleSheetLoadTimeout);
582
+ link.addEventListener('load', () => {
583
+ clearTimeout(timer);
584
+ fired = true;
585
+ listener();
586
+ });
587
+ }
588
+ function serializeNode(n, options) {
589
+ const { doc, mirror, blockClass, blockSelector, unblockSelector, maskAllText, maskAttributeFn, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, inlineStylesheet, maskInputOptions = {}, maskTextFn, maskInputFn, dataURLOptions = {}, inlineImages, recordCanvas, keepIframeSrcFn, newlyAddedElement = false, } = options;
590
+ const rootId = getRootId(doc, mirror);
464
591
  switch (n.nodeType) {
465
592
  case n.DOCUMENT_NODE:
466
593
  if (n.compatMode !== 'CSS1Compat') {
@@ -468,14 +595,12 @@ function serializeNode(n, options) {
468
595
  type: NodeType$1.Document,
469
596
  childNodes: [],
470
597
  compatMode: n.compatMode,
471
- rootId,
472
598
  };
473
599
  }
474
600
  else {
475
601
  return {
476
602
  type: NodeType$1.Document,
477
603
  childNodes: [],
478
- rootId,
479
604
  };
480
605
  }
481
606
  case n.DOCUMENT_TYPE_NODE:
@@ -487,202 +612,39 @@ function serializeNode(n, options) {
487
612
  rootId,
488
613
  };
489
614
  case n.ELEMENT_NODE:
490
- const needBlock = _isBlockedElement(n, blockClass, blockSelector, unblockSelector);
491
- const tagName = getValidTagName(n);
492
- let attributes = {};
493
- for (const { name, value } of Array.from(n.attributes)) {
494
- if (!skipAttribute(tagName, name)) {
495
- attributes[name] = transformAttribute(doc, n, tagName, name, value, maskAllText, unmaskTextSelector, maskTextFn);
496
- }
497
- }
498
- if (tagName === 'link' && inlineStylesheet) {
499
- const stylesheet = Array.from(doc.styleSheets).find((s) => {
500
- return s.href === n.href;
501
- });
502
- let cssText = null;
503
- if (stylesheet) {
504
- cssText = getCssRulesString(stylesheet);
505
- }
506
- if (cssText) {
507
- delete attributes.rel;
508
- delete attributes.href;
509
- attributes._cssText = absoluteToStylesheet(cssText, stylesheet.href);
510
- }
511
- }
512
- if (tagName === 'style' &&
513
- n.sheet &&
514
- !(n.innerText ||
515
- n.textContent ||
516
- '').trim().length) {
517
- const cssText = getCssRulesString(n.sheet);
518
- if (cssText) {
519
- attributes._cssText = absoluteToStylesheet(cssText, getHref());
520
- }
521
- }
522
- if (tagName === 'input' ||
523
- tagName === 'textarea' ||
524
- tagName === 'select' ||
525
- tagName === 'option') {
526
- const el = n;
527
- const type = getInputType(el);
528
- const value = getInputValue(el, tagName.toUpperCase(), type);
529
- const checked = n.checked;
530
- if (type !== 'submit' &&
531
- type !== 'button' &&
532
- value) {
533
- attributes.value = maskInputValue({
534
- input: el,
535
- type,
536
- tagName,
537
- value,
538
- maskInputSelector,
539
- unmaskInputSelector,
540
- maskInputOptions,
541
- maskInputFn,
542
- });
543
- }
544
- if (checked) {
545
- attributes.checked = checked;
546
- }
547
- }
548
- if (tagName === 'option') {
549
- if (n.selected && !maskInputOptions['select']) {
550
- attributes.selected = true;
551
- }
552
- else {
553
- delete attributes.selected;
554
- }
555
- }
556
- if (tagName === 'canvas' && recordCanvas) {
557
- if (n.__context === '2d') {
558
- if (!is2DCanvasBlank(n)) {
559
- attributes.rr_dataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
560
- }
561
- }
562
- else if (!('__context' in n)) {
563
- const canvasDataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
564
- const blankCanvas = document.createElement('canvas');
565
- blankCanvas.width = n.width;
566
- blankCanvas.height = n.height;
567
- const blankCanvasDataURL = blankCanvas.toDataURL(dataURLOptions.type, dataURLOptions.quality);
568
- if (canvasDataURL !== blankCanvasDataURL) {
569
- attributes.rr_dataURL = canvasDataURL;
570
- }
571
- }
572
- }
573
- if (tagName === 'img' && inlineImages) {
574
- if (!canvasService) {
575
- canvasService = doc.createElement('canvas');
576
- canvasCtx = canvasService.getContext('2d');
577
- }
578
- const image = n;
579
- const oldValue = image.crossOrigin;
580
- image.crossOrigin = 'anonymous';
581
- const recordInlineImage = () => {
582
- try {
583
- canvasService.width = image.naturalWidth;
584
- canvasService.height = image.naturalHeight;
585
- canvasCtx.drawImage(image, 0, 0);
586
- attributes.rr_dataURL = canvasService.toDataURL(dataURLOptions.type, dataURLOptions.quality);
587
- }
588
- catch (err) {
589
- console.warn(`Cannot inline img src=${image.currentSrc}! Error: ${err}`);
590
- }
591
- oldValue
592
- ? (attributes.crossOrigin = oldValue)
593
- : delete attributes.crossOrigin;
594
- };
595
- if (image.complete && image.naturalWidth !== 0)
596
- recordInlineImage();
597
- else
598
- image.onload = recordInlineImage;
599
- }
600
- if (tagName === 'audio' || tagName === 'video') {
601
- attributes.rr_mediaState = n.paused
602
- ? 'paused'
603
- : 'played';
604
- attributes.rr_mediaCurrentTime = n.currentTime;
605
- }
606
- if (n.scrollLeft) {
607
- attributes.rr_scrollLeft = n.scrollLeft;
608
- }
609
- if (n.scrollTop) {
610
- attributes.rr_scrollTop = n.scrollTop;
611
- }
612
- if (needBlock) {
613
- const { width, height } = n.getBoundingClientRect();
614
- attributes = {
615
- class: attributes.class,
616
- rr_width: `${width}px`,
617
- rr_height: `${height}px`,
618
- };
619
- }
620
- if (tagName === 'iframe' && !keepIframeSrcFn(attributes.src)) {
621
- if (!n.contentDocument) {
622
- attributes.rr_src = attributes.src;
623
- }
624
- delete attributes.src;
625
- }
626
- return {
627
- type: NodeType$1.Element,
628
- tagName,
629
- attributes,
630
- childNodes: [],
631
- isSVG: isSVGElement(n) || undefined,
632
- needBlock,
615
+ return serializeElementNode(n, {
616
+ doc,
617
+ blockClass,
618
+ blockSelector,
619
+ unblockSelector,
620
+ inlineStylesheet,
621
+ maskAttributeFn,
622
+ maskInputOptions,
623
+ maskInputFn,
624
+ dataURLOptions,
625
+ inlineImages,
626
+ recordCanvas,
627
+ keepIframeSrcFn,
628
+ newlyAddedElement,
633
629
  rootId,
634
- };
630
+ maskAllText,
631
+ maskTextClass,
632
+ unmaskTextClass,
633
+ maskTextSelector,
634
+ unmaskTextSelector,
635
+ });
635
636
  case n.TEXT_NODE:
636
- const parentTagName = n.parentNode && n.parentNode.tagName;
637
- let textContent = n.textContent;
638
- const isStyle = parentTagName === 'STYLE' ? true : undefined;
639
- const isScript = parentTagName === 'SCRIPT' ? true : undefined;
640
- if (isStyle && textContent) {
641
- try {
642
- if (n.nextSibling || n.previousSibling) {
643
- }
644
- else if ((_a = n.parentNode.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) {
645
- textContent = stringifyStyleSheet(n.parentNode.sheet);
646
- }
647
- }
648
- catch (err) {
649
- console.warn(`Cannot get CSS styles from text's parentNode. Error: ${err}`, n);
650
- }
651
- textContent = absoluteToStylesheet(textContent, getHref());
652
- }
653
- if (isScript) {
654
- textContent = 'SCRIPT_PLACEHOLDER';
655
- }
656
- if (parentTagName === 'TEXTAREA' && textContent) {
657
- textContent = '';
658
- }
659
- else if (parentTagName === 'OPTION' && textContent) {
660
- const option = n.parentNode;
661
- textContent = maskInputValue({
662
- input: option,
663
- type: null,
664
- tagName: parentTagName,
665
- value: textContent,
666
- maskInputSelector,
667
- unmaskInputSelector,
668
- maskInputOptions,
669
- maskInputFn,
670
- });
671
- }
672
- else if (!isStyle &&
673
- !isScript &&
674
- needMaskingText(n, maskTextClass, maskTextSelector, unmaskTextSelector, maskAllText) &&
675
- textContent) {
676
- textContent = maskTextFn
677
- ? maskTextFn(textContent)
678
- : defaultMaskFn(textContent);
679
- }
680
- return {
681
- type: NodeType$1.Text,
682
- textContent: textContent || '',
683
- isStyle,
637
+ return serializeTextNode(n, {
638
+ maskAllText,
639
+ maskTextClass,
640
+ unmaskTextClass,
641
+ maskTextSelector,
642
+ unmaskTextSelector,
643
+ maskTextFn,
644
+ maskInputOptions,
645
+ maskInputFn,
684
646
  rootId,
685
- };
647
+ });
686
648
  case n.CDATA_SECTION_NODE:
687
649
  return {
688
650
  type: NodeType$1.CDATA,
@@ -699,6 +661,225 @@ function serializeNode(n, options) {
699
661
  return false;
700
662
  }
701
663
  }
664
+ function getRootId(doc, mirror) {
665
+ if (!mirror.hasNode(doc))
666
+ return undefined;
667
+ const docId = mirror.getId(doc);
668
+ return docId === 1 ? undefined : docId;
669
+ }
670
+ function serializeTextNode(n, options) {
671
+ var _a;
672
+ const { maskAllText, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, maskTextFn, maskInputOptions, maskInputFn, rootId, } = options;
673
+ const parentTagName = n.parentNode && n.parentNode.tagName;
674
+ let textContent = n.textContent;
675
+ const isStyle = parentTagName === 'STYLE' ? true : undefined;
676
+ const isScript = parentTagName === 'SCRIPT' ? true : undefined;
677
+ const isTextarea = parentTagName === 'TEXTAREA' ? true : undefined;
678
+ if (isStyle && textContent) {
679
+ try {
680
+ if (n.nextSibling || n.previousSibling) {
681
+ }
682
+ else if ((_a = n.parentNode.sheet) === null || _a === void 0 ? void 0 : _a.cssRules) {
683
+ textContent = stringifyStylesheet(n.parentNode.sheet);
684
+ }
685
+ }
686
+ catch (err) {
687
+ console.warn(`Cannot get CSS styles from text's parentNode. Error: ${err}`, n);
688
+ }
689
+ textContent = absoluteToStylesheet(textContent, getHref());
690
+ }
691
+ if (isScript) {
692
+ textContent = 'SCRIPT_PLACEHOLDER';
693
+ }
694
+ const forceMask = needMaskingText(n, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, maskAllText);
695
+ if (!isStyle && !isScript && !isTextarea && textContent && forceMask) {
696
+ textContent = maskTextFn
697
+ ? maskTextFn(textContent)
698
+ : textContent.replace(/[\S]/g, '*');
699
+ }
700
+ if (isTextarea && textContent && (maskInputOptions.textarea || forceMask)) {
701
+ textContent = maskInputFn
702
+ ? maskInputFn(textContent, n.parentNode)
703
+ : textContent.replace(/[\S]/g, '*');
704
+ }
705
+ if (parentTagName === 'OPTION' && textContent) {
706
+ const isInputMasked = shouldMaskInput({
707
+ type: null,
708
+ tagName: parentTagName,
709
+ maskInputOptions,
710
+ });
711
+ textContent = maskInputValue({
712
+ isMasked: needMaskingText(n, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, isInputMasked),
713
+ element: n,
714
+ value: textContent,
715
+ maskInputFn,
716
+ });
717
+ }
718
+ return {
719
+ type: NodeType$1.Text,
720
+ textContent: textContent || '',
721
+ isStyle,
722
+ rootId,
723
+ };
724
+ }
725
+ function serializeElementNode(n, options) {
726
+ const { doc, blockClass, blockSelector, unblockSelector, inlineStylesheet, maskInputOptions = {}, maskAttributeFn, maskInputFn, dataURLOptions = {}, inlineImages, recordCanvas, keepIframeSrcFn, newlyAddedElement = false, rootId, maskAllText, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, } = options;
727
+ const needBlock = _isBlockedElement(n, blockClass, blockSelector, unblockSelector);
728
+ const tagName = getValidTagName(n);
729
+ let attributes = {};
730
+ const len = n.attributes.length;
731
+ for (let i = 0; i < len; i++) {
732
+ const attr = n.attributes[i];
733
+ if (!ignoreAttribute(tagName, attr.name, attr.value)) {
734
+ attributes[attr.name] = transformAttribute(doc, tagName, toLowerCase(attr.name), attr.value, n, maskAttributeFn);
735
+ }
736
+ }
737
+ if (tagName === 'link' && inlineStylesheet) {
738
+ const stylesheet = Array.from(doc.styleSheets).find((s) => {
739
+ return s.href === n.href;
740
+ });
741
+ let cssText = null;
742
+ if (stylesheet) {
743
+ cssText = stringifyStylesheet(stylesheet);
744
+ }
745
+ if (cssText) {
746
+ delete attributes.rel;
747
+ delete attributes.href;
748
+ attributes._cssText = absoluteToStylesheet(cssText, stylesheet.href);
749
+ }
750
+ }
751
+ if (tagName === 'style' &&
752
+ n.sheet &&
753
+ !(n.innerText || n.textContent || '').trim().length) {
754
+ const cssText = stringifyStylesheet(n.sheet);
755
+ if (cssText) {
756
+ attributes._cssText = absoluteToStylesheet(cssText, getHref());
757
+ }
758
+ }
759
+ if (tagName === 'input' ||
760
+ tagName === 'textarea' ||
761
+ tagName === 'select' ||
762
+ tagName === 'option') {
763
+ const el = n;
764
+ const type = getInputType(el);
765
+ const value = getInputValue(el, toUpperCase(tagName), type);
766
+ const checked = el.checked;
767
+ if (type !== 'submit' && type !== 'button' && value) {
768
+ const forceMask = needMaskingText(el, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, shouldMaskInput({
769
+ type,
770
+ tagName: toUpperCase(tagName),
771
+ maskInputOptions,
772
+ }));
773
+ attributes.value = maskInputValue({
774
+ isMasked: forceMask,
775
+ element: el,
776
+ value,
777
+ maskInputFn,
778
+ });
779
+ }
780
+ if (checked) {
781
+ attributes.checked = checked;
782
+ }
783
+ }
784
+ if (tagName === 'option') {
785
+ if (n.selected && !maskInputOptions['select']) {
786
+ attributes.selected = true;
787
+ }
788
+ else {
789
+ delete attributes.selected;
790
+ }
791
+ }
792
+ if (tagName === 'canvas' && recordCanvas) {
793
+ if (n.__context === '2d') {
794
+ if (!is2DCanvasBlank(n)) {
795
+ attributes.rr_dataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
796
+ }
797
+ }
798
+ else if (!('__context' in n)) {
799
+ const canvasDataURL = n.toDataURL(dataURLOptions.type, dataURLOptions.quality);
800
+ const blankCanvas = document.createElement('canvas');
801
+ blankCanvas.width = n.width;
802
+ blankCanvas.height = n.height;
803
+ const blankCanvasDataURL = blankCanvas.toDataURL(dataURLOptions.type, dataURLOptions.quality);
804
+ if (canvasDataURL !== blankCanvasDataURL) {
805
+ attributes.rr_dataURL = canvasDataURL;
806
+ }
807
+ }
808
+ }
809
+ if (tagName === 'img' && inlineImages) {
810
+ if (!canvasService) {
811
+ canvasService = doc.createElement('canvas');
812
+ canvasCtx = canvasService.getContext('2d');
813
+ }
814
+ const image = n;
815
+ const oldValue = image.crossOrigin;
816
+ image.crossOrigin = 'anonymous';
817
+ const recordInlineImage = () => {
818
+ image.removeEventListener('load', recordInlineImage);
819
+ try {
820
+ canvasService.width = image.naturalWidth;
821
+ canvasService.height = image.naturalHeight;
822
+ canvasCtx.drawImage(image, 0, 0);
823
+ attributes.rr_dataURL = canvasService.toDataURL(dataURLOptions.type, dataURLOptions.quality);
824
+ }
825
+ catch (err) {
826
+ console.warn(`Cannot inline img src=${image.currentSrc}! Error: ${err}`);
827
+ }
828
+ oldValue
829
+ ? (attributes.crossOrigin = oldValue)
830
+ : image.removeAttribute('crossorigin');
831
+ };
832
+ if (image.complete && image.naturalWidth !== 0)
833
+ recordInlineImage();
834
+ else
835
+ image.addEventListener('load', recordInlineImage);
836
+ }
837
+ if (tagName === 'audio' || tagName === 'video') {
838
+ attributes.rr_mediaState = n.paused
839
+ ? 'paused'
840
+ : 'played';
841
+ attributes.rr_mediaCurrentTime = n.currentTime;
842
+ }
843
+ if (!newlyAddedElement) {
844
+ if (n.scrollLeft) {
845
+ attributes.rr_scrollLeft = n.scrollLeft;
846
+ }
847
+ if (n.scrollTop) {
848
+ attributes.rr_scrollTop = n.scrollTop;
849
+ }
850
+ }
851
+ if (needBlock) {
852
+ const { width, height } = n.getBoundingClientRect();
853
+ attributes = {
854
+ class: attributes.class,
855
+ rr_width: `${width}px`,
856
+ rr_height: `${height}px`,
857
+ };
858
+ }
859
+ if (tagName === 'iframe' && !keepIframeSrcFn(attributes.src)) {
860
+ if (!n.contentDocument) {
861
+ attributes.rr_src = attributes.src;
862
+ }
863
+ delete attributes.src;
864
+ }
865
+ let isCustomElement;
866
+ try {
867
+ if (customElements.get(tagName))
868
+ isCustomElement = true;
869
+ }
870
+ catch (e) {
871
+ }
872
+ return {
873
+ type: NodeType$1.Element,
874
+ tagName,
875
+ attributes,
876
+ childNodes: [],
877
+ isSVG: isSVGElement(n) || undefined,
878
+ needBlock,
879
+ rootId,
880
+ isCustom: isCustomElement,
881
+ };
882
+ }
702
883
  function lowerIfExists(maybeAttr) {
703
884
  if (maybeAttr === undefined || maybeAttr === null) {
704
885
  return '';
@@ -780,35 +961,37 @@ function slimDOMExcluded(sn, slimDOMOptions) {
780
961
  return false;
781
962
  }
782
963
  function serializeNodeWithId(n, options) {
783
- const { doc, map, blockClass, blockSelector, unblockSelector, maskTextClass, maskTextSelector, unmaskTextSelector, skipChild = false, inlineStylesheet = true, maskInputSelector, unmaskInputSelector, maskAllText, maskInputOptions = {}, maskTextFn, maskInputFn, slimDOMOptions, dataURLOptions = {}, inlineImages = false, recordCanvas = false, onSerialize, onIframeLoad, iframeLoadTimeout = 5000, keepIframeSrcFn = () => false, } = options;
964
+ const { doc, mirror, blockClass, blockSelector, unblockSelector, maskAllText, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, skipChild = false, inlineStylesheet = true, maskInputOptions = {}, maskAttributeFn, maskTextFn, maskInputFn, slimDOMOptions, dataURLOptions = {}, inlineImages = false, recordCanvas = false, onSerialize, onIframeLoad, iframeLoadTimeout = 5000, onStylesheetLoad, stylesheetLoadTimeout = 5000, keepIframeSrcFn = () => false, newlyAddedElement = false, } = options;
784
965
  let { preserveWhiteSpace = true } = options;
785
966
  const _serializedNode = serializeNode(n, {
786
967
  doc,
968
+ mirror,
787
969
  blockClass,
788
970
  blockSelector,
971
+ maskAllText,
789
972
  unblockSelector,
790
973
  maskTextClass,
974
+ unmaskTextClass,
791
975
  maskTextSelector,
792
976
  unmaskTextSelector,
793
977
  inlineStylesheet,
794
- maskInputSelector,
795
- unmaskInputSelector,
796
- maskAllText,
797
978
  maskInputOptions,
979
+ maskAttributeFn,
798
980
  maskTextFn,
799
981
  maskInputFn,
800
982
  dataURLOptions,
801
983
  inlineImages,
802
984
  recordCanvas,
803
985
  keepIframeSrcFn,
986
+ newlyAddedElement,
804
987
  });
805
988
  if (!_serializedNode) {
806
989
  console.warn(n, 'not serialized');
807
990
  return null;
808
991
  }
809
992
  let id;
810
- if ('__sn' in n) {
811
- id = n.__sn.id;
993
+ if (mirror.hasNode(n)) {
994
+ id = mirror.getId(n);
812
995
  }
813
996
  else if (slimDOMExcluded(_serializedNode, slimDOMOptions) ||
814
997
  (!preserveWhiteSpace &&
@@ -821,11 +1004,10 @@ function serializeNodeWithId(n, options) {
821
1004
  id = genId();
822
1005
  }
823
1006
  const serializedNode = Object.assign(_serializedNode, { id });
824
- n.__sn = serializedNode;
1007
+ mirror.add(n, serializedNode);
825
1008
  if (id === IGNORED_NODE) {
826
1009
  return null;
827
1010
  }
828
- map[id] = n;
829
1011
  if (onSerialize) {
830
1012
  onSerialize(n);
831
1013
  }
@@ -833,32 +1015,33 @@ function serializeNodeWithId(n, options) {
833
1015
  if (serializedNode.type === NodeType$1.Element) {
834
1016
  recordChild = recordChild && !serializedNode.needBlock;
835
1017
  delete serializedNode.needBlock;
836
- if (n.shadowRoot)
1018
+ const shadowRoot = n.shadowRoot;
1019
+ if (shadowRoot && isNativeShadowDom(shadowRoot))
837
1020
  serializedNode.isShadowHost = true;
838
1021
  }
839
1022
  if ((serializedNode.type === NodeType$1.Document ||
840
1023
  serializedNode.type === NodeType$1.Element) &&
841
1024
  recordChild) {
842
1025
  if (slimDOMOptions.headWhitespace &&
843
- _serializedNode.type === NodeType$1.Element &&
844
- _serializedNode.tagName === 'head') {
1026
+ serializedNode.type === NodeType$1.Element &&
1027
+ serializedNode.tagName === 'head') {
845
1028
  preserveWhiteSpace = false;
846
1029
  }
847
1030
  const bypassOptions = {
848
1031
  doc,
849
- map,
1032
+ mirror,
850
1033
  blockClass,
851
1034
  blockSelector,
1035
+ maskAllText,
852
1036
  unblockSelector,
853
1037
  maskTextClass,
1038
+ unmaskTextClass,
854
1039
  maskTextSelector,
855
1040
  unmaskTextSelector,
856
1041
  skipChild,
857
1042
  inlineStylesheet,
858
- maskInputSelector,
859
- unmaskInputSelector,
860
- maskAllText,
861
1043
  maskInputOptions,
1044
+ maskAttributeFn,
862
1045
  maskTextFn,
863
1046
  maskInputFn,
864
1047
  slimDOMOptions,
@@ -869,6 +1052,8 @@ function serializeNodeWithId(n, options) {
869
1052
  onSerialize,
870
1053
  onIframeLoad,
871
1054
  iframeLoadTimeout,
1055
+ onStylesheetLoad,
1056
+ stylesheetLoadTimeout,
872
1057
  keepIframeSrcFn,
873
1058
  };
874
1059
  for (const childN of Array.from(n.childNodes)) {
@@ -877,17 +1062,20 @@ function serializeNodeWithId(n, options) {
877
1062
  serializedNode.childNodes.push(serializedChildNode);
878
1063
  }
879
1064
  }
880
- if (isElement(n) && n.shadowRoot) {
1065
+ if (isElement$1(n) && n.shadowRoot) {
881
1066
  for (const childN of Array.from(n.shadowRoot.childNodes)) {
882
1067
  const serializedChildNode = serializeNodeWithId(childN, bypassOptions);
883
1068
  if (serializedChildNode) {
884
- serializedChildNode.isShadow = true;
1069
+ isNativeShadowDom(n.shadowRoot) &&
1070
+ (serializedChildNode.isShadow = true);
885
1071
  serializedNode.childNodes.push(serializedChildNode);
886
1072
  }
887
1073
  }
888
1074
  }
889
1075
  }
890
- if (n.parentNode && isShadowRoot(n.parentNode)) {
1076
+ if (n.parentNode &&
1077
+ isShadowRoot(n.parentNode) &&
1078
+ isNativeShadowDom(n.parentNode)) {
891
1079
  serializedNode.isShadow = true;
892
1080
  }
893
1081
  if (serializedNode.type === NodeType$1.Element &&
@@ -897,19 +1085,19 @@ function serializeNodeWithId(n, options) {
897
1085
  if (iframeDoc && onIframeLoad) {
898
1086
  const serializedIframeNode = serializeNodeWithId(iframeDoc, {
899
1087
  doc: iframeDoc,
900
- map,
1088
+ mirror,
901
1089
  blockClass,
902
1090
  blockSelector,
903
1091
  unblockSelector,
1092
+ maskAllText,
904
1093
  maskTextClass,
1094
+ unmaskTextClass,
905
1095
  maskTextSelector,
906
1096
  unmaskTextSelector,
907
1097
  skipChild: false,
908
1098
  inlineStylesheet,
909
- maskInputSelector,
910
- unmaskInputSelector,
911
- maskAllText,
912
1099
  maskInputOptions,
1100
+ maskAttributeFn,
913
1101
  maskTextFn,
914
1102
  maskInputFn,
915
1103
  slimDOMOptions,
@@ -920,6 +1108,8 @@ function serializeNodeWithId(n, options) {
920
1108
  onSerialize,
921
1109
  onIframeLoad,
922
1110
  iframeLoadTimeout,
1111
+ onStylesheetLoad,
1112
+ stylesheetLoadTimeout,
923
1113
  keepIframeSrcFn,
924
1114
  });
925
1115
  if (serializedIframeNode) {
@@ -928,11 +1118,50 @@ function serializeNodeWithId(n, options) {
928
1118
  }
929
1119
  }, iframeLoadTimeout);
930
1120
  }
1121
+ if (serializedNode.type === NodeType$1.Element &&
1122
+ serializedNode.tagName === 'link' &&
1123
+ serializedNode.attributes.rel === 'stylesheet') {
1124
+ onceStylesheetLoaded(n, () => {
1125
+ if (onStylesheetLoad) {
1126
+ const serializedLinkNode = serializeNodeWithId(n, {
1127
+ doc,
1128
+ mirror,
1129
+ blockClass,
1130
+ blockSelector,
1131
+ unblockSelector,
1132
+ maskAllText,
1133
+ maskTextClass,
1134
+ unmaskTextClass,
1135
+ maskTextSelector,
1136
+ unmaskTextSelector,
1137
+ skipChild: false,
1138
+ inlineStylesheet,
1139
+ maskInputOptions,
1140
+ maskAttributeFn,
1141
+ maskTextFn,
1142
+ maskInputFn,
1143
+ slimDOMOptions,
1144
+ dataURLOptions,
1145
+ inlineImages,
1146
+ recordCanvas,
1147
+ preserveWhiteSpace,
1148
+ onSerialize,
1149
+ onIframeLoad,
1150
+ iframeLoadTimeout,
1151
+ onStylesheetLoad,
1152
+ stylesheetLoadTimeout,
1153
+ keepIframeSrcFn,
1154
+ });
1155
+ if (serializedLinkNode) {
1156
+ onStylesheetLoad(n, serializedLinkNode);
1157
+ }
1158
+ }
1159
+ }, stylesheetLoadTimeout);
1160
+ }
931
1161
  return serializedNode;
932
1162
  }
933
1163
  function snapshot(n, options) {
934
- const { blockClass = 'rr-block', blockSelector = null, unblockSelector = null, maskTextClass = 'rr-mask', maskTextSelector = null, unmaskTextSelector = null, inlineStylesheet = true, inlineImages = false, recordCanvas = false, maskInputSelector = null, unmaskInputSelector = null, maskAllText = false, maskAllInputs = false, maskTextFn, maskInputFn, slimDOM = false, dataURLOptions, preserveWhiteSpace, onSerialize, onIframeLoad, iframeLoadTimeout, keepIframeSrcFn = () => false, } = options || {};
935
- const idNodeMap = {};
1164
+ const { mirror = new Mirror(), blockClass = 'rr-block', blockSelector = null, unblockSelector = null, maskAllText = false, maskTextClass = 'rr-mask', unmaskTextClass = null, maskTextSelector = null, unmaskTextSelector = null, inlineStylesheet = true, inlineImages = false, recordCanvas = false, maskAllInputs = false, maskAttributeFn, maskTextFn, maskInputFn, slimDOM = false, dataURLOptions, preserveWhiteSpace, onSerialize, onIframeLoad, iframeLoadTimeout, onStylesheetLoad, stylesheetLoadTimeout, keepIframeSrcFn = () => false, } = options || {};
936
1165
  const maskInputOptions = maskAllInputs === true
937
1166
  ? {
938
1167
  color: true,
@@ -971,147 +1200,43 @@ function snapshot(n, options) {
971
1200
  : slimDOM === false
972
1201
  ? {}
973
1202
  : slimDOM;
974
- return [
975
- serializeNodeWithId(n, {
976
- doc: n,
977
- map: idNodeMap,
978
- blockClass,
979
- blockSelector,
980
- unblockSelector,
981
- maskTextClass,
982
- maskTextSelector,
983
- unmaskTextSelector,
984
- skipChild: false,
985
- inlineStylesheet,
986
- maskInputSelector,
987
- unmaskInputSelector,
988
- maskAllText,
989
- maskInputOptions,
990
- maskTextFn,
991
- maskInputFn,
992
- slimDOMOptions,
993
- dataURLOptions,
994
- inlineImages,
995
- recordCanvas,
996
- preserveWhiteSpace,
997
- onSerialize,
998
- onIframeLoad,
999
- iframeLoadTimeout,
1000
- keepIframeSrcFn,
1001
- }),
1002
- idNodeMap,
1003
- ];
1203
+ return serializeNodeWithId(n, {
1204
+ doc: n,
1205
+ mirror,
1206
+ blockClass,
1207
+ blockSelector,
1208
+ unblockSelector,
1209
+ maskAllText,
1210
+ maskTextClass,
1211
+ unmaskTextClass,
1212
+ maskTextSelector,
1213
+ unmaskTextSelector,
1214
+ skipChild: false,
1215
+ inlineStylesheet,
1216
+ maskInputOptions,
1217
+ maskAttributeFn,
1218
+ maskTextFn,
1219
+ maskInputFn,
1220
+ slimDOMOptions,
1221
+ dataURLOptions,
1222
+ inlineImages,
1223
+ recordCanvas,
1224
+ preserveWhiteSpace,
1225
+ onSerialize,
1226
+ onIframeLoad,
1227
+ iframeLoadTimeout,
1228
+ onStylesheetLoad,
1229
+ stylesheetLoadTimeout,
1230
+ keepIframeSrcFn,
1231
+ newlyAddedElement: false,
1232
+ });
1004
1233
  }
1005
- function skipAttribute(tagName, attributeName, value) {
1006
- return ((tagName === 'video' || tagName === 'audio') && attributeName === 'autoplay');
1007
- }
1008
-
1009
- var EventType;
1010
- (function (EventType) {
1011
- EventType[EventType["DomContentLoaded"] = 0] = "DomContentLoaded";
1012
- EventType[EventType["Load"] = 1] = "Load";
1013
- EventType[EventType["FullSnapshot"] = 2] = "FullSnapshot";
1014
- EventType[EventType["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
1015
- EventType[EventType["Meta"] = 4] = "Meta";
1016
- EventType[EventType["Custom"] = 5] = "Custom";
1017
- EventType[EventType["Plugin"] = 6] = "Plugin";
1018
- })(EventType || (EventType = {}));
1019
- var IncrementalSource;
1020
- (function (IncrementalSource) {
1021
- IncrementalSource[IncrementalSource["Mutation"] = 0] = "Mutation";
1022
- IncrementalSource[IncrementalSource["MouseMove"] = 1] = "MouseMove";
1023
- IncrementalSource[IncrementalSource["MouseInteraction"] = 2] = "MouseInteraction";
1024
- IncrementalSource[IncrementalSource["Scroll"] = 3] = "Scroll";
1025
- IncrementalSource[IncrementalSource["ViewportResize"] = 4] = "ViewportResize";
1026
- IncrementalSource[IncrementalSource["Input"] = 5] = "Input";
1027
- IncrementalSource[IncrementalSource["TouchMove"] = 6] = "TouchMove";
1028
- IncrementalSource[IncrementalSource["MediaInteraction"] = 7] = "MediaInteraction";
1029
- IncrementalSource[IncrementalSource["StyleSheetRule"] = 8] = "StyleSheetRule";
1030
- IncrementalSource[IncrementalSource["CanvasMutation"] = 9] = "CanvasMutation";
1031
- IncrementalSource[IncrementalSource["Font"] = 10] = "Font";
1032
- IncrementalSource[IncrementalSource["Log"] = 11] = "Log";
1033
- IncrementalSource[IncrementalSource["Drag"] = 12] = "Drag";
1034
- IncrementalSource[IncrementalSource["StyleDeclaration"] = 13] = "StyleDeclaration";
1035
- })(IncrementalSource || (IncrementalSource = {}));
1036
- var MouseInteractions;
1037
- (function (MouseInteractions) {
1038
- MouseInteractions[MouseInteractions["MouseUp"] = 0] = "MouseUp";
1039
- MouseInteractions[MouseInteractions["MouseDown"] = 1] = "MouseDown";
1040
- MouseInteractions[MouseInteractions["Click"] = 2] = "Click";
1041
- MouseInteractions[MouseInteractions["ContextMenu"] = 3] = "ContextMenu";
1042
- MouseInteractions[MouseInteractions["DblClick"] = 4] = "DblClick";
1043
- MouseInteractions[MouseInteractions["Focus"] = 5] = "Focus";
1044
- MouseInteractions[MouseInteractions["Blur"] = 6] = "Blur";
1045
- MouseInteractions[MouseInteractions["TouchStart"] = 7] = "TouchStart";
1046
- MouseInteractions[MouseInteractions["TouchMove_Departed"] = 8] = "TouchMove_Departed";
1047
- MouseInteractions[MouseInteractions["TouchEnd"] = 9] = "TouchEnd";
1048
- MouseInteractions[MouseInteractions["TouchCancel"] = 10] = "TouchCancel";
1049
- })(MouseInteractions || (MouseInteractions = {}));
1050
- var CanvasContext;
1051
- (function (CanvasContext) {
1052
- CanvasContext[CanvasContext["2D"] = 0] = "2D";
1053
- CanvasContext[CanvasContext["WebGL"] = 1] = "WebGL";
1054
- CanvasContext[CanvasContext["WebGL2"] = 2] = "WebGL2";
1055
- })(CanvasContext || (CanvasContext = {}));
1056
- var MediaInteractions;
1057
- (function (MediaInteractions) {
1058
- MediaInteractions[MediaInteractions["Play"] = 0] = "Play";
1059
- MediaInteractions[MediaInteractions["Pause"] = 1] = "Pause";
1060
- MediaInteractions[MediaInteractions["Seeked"] = 2] = "Seeked";
1061
- MediaInteractions[MediaInteractions["VolumeChange"] = 3] = "VolumeChange";
1062
- })(MediaInteractions || (MediaInteractions = {}));
1063
- var ReplayerEvents;
1064
- (function (ReplayerEvents) {
1065
- ReplayerEvents["Start"] = "start";
1066
- ReplayerEvents["Pause"] = "pause";
1067
- ReplayerEvents["Resume"] = "resume";
1068
- ReplayerEvents["Resize"] = "resize";
1069
- ReplayerEvents["Finish"] = "finish";
1070
- ReplayerEvents["FullsnapshotRebuilded"] = "fullsnapshot-rebuilded";
1071
- ReplayerEvents["LoadStylesheetStart"] = "load-stylesheet-start";
1072
- ReplayerEvents["LoadStylesheetEnd"] = "load-stylesheet-end";
1073
- ReplayerEvents["SkipStart"] = "skip-start";
1074
- ReplayerEvents["SkipEnd"] = "skip-end";
1075
- ReplayerEvents["MouseInteraction"] = "mouse-interaction";
1076
- ReplayerEvents["EventCast"] = "event-cast";
1077
- ReplayerEvents["CustomEvent"] = "custom-event";
1078
- ReplayerEvents["Flush"] = "flush";
1079
- ReplayerEvents["StateChange"] = "state-change";
1080
- ReplayerEvents["PlayBack"] = "play-back";
1081
- })(ReplayerEvents || (ReplayerEvents = {}));
1082
1234
 
1083
1235
  function on(type, fn, target = document) {
1084
1236
  const options = { capture: true, passive: true };
1085
1237
  target.addEventListener(type, fn, options);
1086
1238
  return () => target.removeEventListener(type, fn, options);
1087
1239
  }
1088
- function createMirror() {
1089
- return {
1090
- map: {},
1091
- getId(n) {
1092
- if (!n || !n.__sn) {
1093
- return -1;
1094
- }
1095
- return n.__sn.id;
1096
- },
1097
- getNode(id) {
1098
- return this.map[id] || null;
1099
- },
1100
- removeNodeFromMap(n) {
1101
- const id = n.__sn && n.__sn.id;
1102
- delete this.map[id];
1103
- if (n.childNodes) {
1104
- n.childNodes.forEach((child) => this.removeNodeFromMap(child));
1105
- }
1106
- },
1107
- has(id) {
1108
- return this.map.hasOwnProperty(id);
1109
- },
1110
- reset() {
1111
- this.map = {};
1112
- },
1113
- };
1114
- }
1115
1240
  const DEPARTED_MIRROR_ACCESS_WARNING = 'Please stop import mirror directly. Instead of that,' +
1116
1241
  '\r\n' +
1117
1242
  'now you can use replayer.getMirror() to access the mirror instance of a replayer,' +
@@ -1151,14 +1276,13 @@ if (typeof window !== 'undefined' && window.Proxy && window.Reflect) {
1151
1276
  function throttle$1(func, wait, options = {}) {
1152
1277
  let timeout = null;
1153
1278
  let previous = 0;
1154
- return function (arg) {
1155
- let now = Date.now();
1279
+ return function (...args) {
1280
+ const now = Date.now();
1156
1281
  if (!previous && options.leading === false) {
1157
1282
  previous = now;
1158
1283
  }
1159
- let remaining = wait - (now - previous);
1160
- let context = this;
1161
- let args = arguments;
1284
+ const remaining = wait - (now - previous);
1285
+ const context = this;
1162
1286
  if (remaining <= 0 || remaining > wait) {
1163
1287
  if (timeout) {
1164
1288
  clearTimeout(timeout);
@@ -1195,7 +1319,8 @@ function hookSetter(target, key, d, isRevoked, win = window) {
1195
1319
  function patch(source, name, replacement) {
1196
1320
  try {
1197
1321
  if (!(name in source)) {
1198
- return () => { };
1322
+ return () => {
1323
+ };
1199
1324
  }
1200
1325
  const original = source[name];
1201
1326
  const wrapped = replacement(original);
@@ -1214,9 +1339,36 @@ function patch(source, name, replacement) {
1214
1339
  };
1215
1340
  }
1216
1341
  catch (_a) {
1217
- return () => { };
1342
+ return () => {
1343
+ };
1218
1344
  }
1219
1345
  }
1346
+ let nowTimestamp = Date.now;
1347
+ if (!(/[1-9][0-9]{12}/.test(Date.now().toString()))) {
1348
+ nowTimestamp = () => new Date().getTime();
1349
+ }
1350
+ function getWindowScroll(win) {
1351
+ var _a, _b, _c, _d, _e, _f;
1352
+ const doc = win.document;
1353
+ return {
1354
+ left: doc.scrollingElement
1355
+ ? doc.scrollingElement.scrollLeft
1356
+ : win.pageXOffset !== undefined
1357
+ ? win.pageXOffset
1358
+ : (doc === null || doc === void 0 ? void 0 : doc.documentElement.scrollLeft) ||
1359
+ ((_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) ||
1360
+ ((_c = doc === null || doc === void 0 ? void 0 : doc.body) === null || _c === void 0 ? void 0 : _c.scrollLeft) ||
1361
+ 0,
1362
+ top: doc.scrollingElement
1363
+ ? doc.scrollingElement.scrollTop
1364
+ : win.pageYOffset !== undefined
1365
+ ? win.pageYOffset
1366
+ : (doc === null || doc === void 0 ? void 0 : doc.documentElement.scrollTop) ||
1367
+ ((_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) ||
1368
+ ((_f = doc === null || doc === void 0 ? void 0 : doc.body) === null || _f === void 0 ? void 0 : _f.scrollTop) ||
1369
+ 0,
1370
+ };
1371
+ }
1220
1372
  function getWindowHeight() {
1221
1373
  return (window.innerHeight ||
1222
1374
  (document.documentElement && document.documentElement.clientHeight) ||
@@ -1227,48 +1379,38 @@ function getWindowWidth() {
1227
1379
  (document.documentElement && document.documentElement.clientWidth) ||
1228
1380
  (document.body && document.body.clientWidth));
1229
1381
  }
1230
- function isBlocked(node, blockClass, blockSelector, unblockSelector) {
1382
+ function isBlocked(node, blockClass, blockSelector, unblockSelector, checkAncestors) {
1231
1383
  if (!node) {
1232
1384
  return false;
1233
1385
  }
1234
- if (node.nodeType === node.ELEMENT_NODE) {
1235
- let needBlock = false;
1236
- const needUnblock = unblockSelector && node.matches(unblockSelector);
1237
- if (typeof blockClass === 'string') {
1238
- if (node.closest !== undefined) {
1239
- needBlock =
1240
- !needUnblock &&
1241
- node.closest('.' + blockClass) !== null;
1242
- }
1243
- else {
1244
- needBlock =
1245
- !needUnblock && node.classList.contains(blockClass);
1246
- }
1247
- }
1248
- else {
1249
- !needUnblock &&
1250
- node.classList.forEach((className) => {
1251
- if (blockClass.test(className)) {
1252
- needBlock = true;
1253
- }
1254
- });
1255
- }
1256
- if (!needBlock && blockSelector) {
1257
- needBlock = node.matches(blockSelector);
1258
- }
1259
- return ((!needUnblock && needBlock) ||
1260
- isBlocked(node.parentNode, blockClass, blockSelector, unblockSelector));
1386
+ const el = node.nodeType === node.ELEMENT_NODE
1387
+ ? node
1388
+ : node.parentElement;
1389
+ if (!el)
1390
+ return false;
1391
+ const blockedPredicate = createMatchPredicate(blockClass, blockSelector);
1392
+ if (!checkAncestors) {
1393
+ const isUnblocked = unblockSelector && el.matches(unblockSelector);
1394
+ return blockedPredicate(el) && !isUnblocked;
1395
+ }
1396
+ const blockDistance = distanceToMatch(el, blockedPredicate);
1397
+ let unblockDistance = -1;
1398
+ if (blockDistance < 0) {
1399
+ return false;
1261
1400
  }
1262
- if (node.nodeType === node.TEXT_NODE) {
1263
- return isBlocked(node.parentNode, blockClass, blockSelector, unblockSelector);
1401
+ if (unblockSelector) {
1402
+ unblockDistance = distanceToMatch(el, createMatchPredicate(null, unblockSelector));
1264
1403
  }
1265
- return isBlocked(node.parentNode, blockClass, blockSelector, unblockSelector);
1266
- }
1267
- function isIgnored(n) {
1268
- if ('__sn' in n) {
1269
- return n.__sn.id === IGNORED_NODE;
1404
+ if (blockDistance > -1 && unblockDistance < 0) {
1405
+ return true;
1270
1406
  }
1271
- return false;
1407
+ return blockDistance < unblockDistance;
1408
+ }
1409
+ function isSerialized(n, mirror) {
1410
+ return mirror.getId(n) !== -1;
1411
+ }
1412
+ function isIgnored(n, mirror) {
1413
+ return mirror.getId(n) === IGNORED_NODE;
1272
1414
  }
1273
1415
  function isAncestorRemoved(target, mirror) {
1274
1416
  if (isShadowRoot(target)) {
@@ -1287,7 +1429,7 @@ function isAncestorRemoved(target, mirror) {
1287
1429
  }
1288
1430
  return isAncestorRemoved(target.parentNode, mirror);
1289
1431
  }
1290
- function isTouchEvent(event) {
1432
+ function legacy_isTouchEvent(event) {
1291
1433
  return Boolean(event.changedTouches);
1292
1434
  }
1293
1435
  function polyfill(win = window) {
@@ -1300,8 +1442,9 @@ function polyfill(win = window) {
1300
1442
  .forEach;
1301
1443
  }
1302
1444
  if (!Node.prototype.contains) {
1303
- Node.prototype.contains = function contains(node) {
1304
- if (!(0 in arguments)) {
1445
+ Node.prototype.contains = (...args) => {
1446
+ let node = args[0];
1447
+ if (!(0 in args)) {
1305
1448
  throw new TypeError('1 argument is required');
1306
1449
  }
1307
1450
  do {
@@ -1313,15 +1456,142 @@ function polyfill(win = window) {
1313
1456
  };
1314
1457
  }
1315
1458
  }
1316
- function isIframeINode(node) {
1317
- if ('__sn' in node) {
1318
- return (node.__sn.type === NodeType$1.Element && node.__sn.tagName === 'iframe');
1319
- }
1320
- return false;
1459
+ function isSerializedIframe(n, mirror) {
1460
+ return Boolean(n.nodeName === 'IFRAME' && mirror.getMeta(n));
1461
+ }
1462
+ function isSerializedStylesheet(n, mirror) {
1463
+ return Boolean(n.nodeName === 'LINK' &&
1464
+ n.nodeType === n.ELEMENT_NODE &&
1465
+ n.getAttribute &&
1466
+ n.getAttribute('rel') === 'stylesheet' &&
1467
+ mirror.getMeta(n));
1321
1468
  }
1322
1469
  function hasShadowRoot(n) {
1323
1470
  return Boolean(n === null || n === void 0 ? void 0 : n.shadowRoot);
1324
1471
  }
1472
+ class StyleSheetMirror {
1473
+ constructor() {
1474
+ this.id = 1;
1475
+ this.styleIDMap = new WeakMap();
1476
+ this.idStyleMap = new Map();
1477
+ }
1478
+ getId(stylesheet) {
1479
+ var _a;
1480
+ return (_a = this.styleIDMap.get(stylesheet)) !== null && _a !== void 0 ? _a : -1;
1481
+ }
1482
+ has(stylesheet) {
1483
+ return this.styleIDMap.has(stylesheet);
1484
+ }
1485
+ add(stylesheet, id) {
1486
+ if (this.has(stylesheet))
1487
+ return this.getId(stylesheet);
1488
+ let newId;
1489
+ if (id === undefined) {
1490
+ newId = this.id++;
1491
+ }
1492
+ else
1493
+ newId = id;
1494
+ this.styleIDMap.set(stylesheet, newId);
1495
+ this.idStyleMap.set(newId, stylesheet);
1496
+ return newId;
1497
+ }
1498
+ getStyle(id) {
1499
+ return this.idStyleMap.get(id) || null;
1500
+ }
1501
+ reset() {
1502
+ this.styleIDMap = new WeakMap();
1503
+ this.idStyleMap = new Map();
1504
+ this.id = 1;
1505
+ }
1506
+ generateId() {
1507
+ return this.id++;
1508
+ }
1509
+ }
1510
+ function getShadowHost(n) {
1511
+ var _a, _b;
1512
+ let shadowHost = null;
1513
+ 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 &&
1514
+ n.getRootNode().host)
1515
+ shadowHost = n.getRootNode().host;
1516
+ return shadowHost;
1517
+ }
1518
+ function getRootShadowHost(n) {
1519
+ let rootShadowHost = n;
1520
+ let shadowHost;
1521
+ while ((shadowHost = getShadowHost(rootShadowHost)))
1522
+ rootShadowHost = shadowHost;
1523
+ return rootShadowHost;
1524
+ }
1525
+ function shadowHostInDom(n) {
1526
+ const doc = n.ownerDocument;
1527
+ if (!doc)
1528
+ return false;
1529
+ const shadowHost = getRootShadowHost(n);
1530
+ return doc.contains(shadowHost);
1531
+ }
1532
+ function inDom(n) {
1533
+ const doc = n.ownerDocument;
1534
+ if (!doc)
1535
+ return false;
1536
+ return doc.contains(n) || shadowHostInDom(n);
1537
+ }
1538
+
1539
+ var EventType = /* @__PURE__ */ ((EventType2) => {
1540
+ EventType2[EventType2["DomContentLoaded"] = 0] = "DomContentLoaded";
1541
+ EventType2[EventType2["Load"] = 1] = "Load";
1542
+ EventType2[EventType2["FullSnapshot"] = 2] = "FullSnapshot";
1543
+ EventType2[EventType2["IncrementalSnapshot"] = 3] = "IncrementalSnapshot";
1544
+ EventType2[EventType2["Meta"] = 4] = "Meta";
1545
+ EventType2[EventType2["Custom"] = 5] = "Custom";
1546
+ EventType2[EventType2["Plugin"] = 6] = "Plugin";
1547
+ return EventType2;
1548
+ })(EventType || {});
1549
+ var IncrementalSource = /* @__PURE__ */ ((IncrementalSource2) => {
1550
+ IncrementalSource2[IncrementalSource2["Mutation"] = 0] = "Mutation";
1551
+ IncrementalSource2[IncrementalSource2["MouseMove"] = 1] = "MouseMove";
1552
+ IncrementalSource2[IncrementalSource2["MouseInteraction"] = 2] = "MouseInteraction";
1553
+ IncrementalSource2[IncrementalSource2["Scroll"] = 3] = "Scroll";
1554
+ IncrementalSource2[IncrementalSource2["ViewportResize"] = 4] = "ViewportResize";
1555
+ IncrementalSource2[IncrementalSource2["Input"] = 5] = "Input";
1556
+ IncrementalSource2[IncrementalSource2["TouchMove"] = 6] = "TouchMove";
1557
+ IncrementalSource2[IncrementalSource2["MediaInteraction"] = 7] = "MediaInteraction";
1558
+ IncrementalSource2[IncrementalSource2["StyleSheetRule"] = 8] = "StyleSheetRule";
1559
+ IncrementalSource2[IncrementalSource2["CanvasMutation"] = 9] = "CanvasMutation";
1560
+ IncrementalSource2[IncrementalSource2["Font"] = 10] = "Font";
1561
+ IncrementalSource2[IncrementalSource2["Log"] = 11] = "Log";
1562
+ IncrementalSource2[IncrementalSource2["Drag"] = 12] = "Drag";
1563
+ IncrementalSource2[IncrementalSource2["StyleDeclaration"] = 13] = "StyleDeclaration";
1564
+ IncrementalSource2[IncrementalSource2["Selection"] = 14] = "Selection";
1565
+ IncrementalSource2[IncrementalSource2["AdoptedStyleSheet"] = 15] = "AdoptedStyleSheet";
1566
+ IncrementalSource2[IncrementalSource2["CustomElement"] = 16] = "CustomElement";
1567
+ return IncrementalSource2;
1568
+ })(IncrementalSource || {});
1569
+ var MouseInteractions = /* @__PURE__ */ ((MouseInteractions2) => {
1570
+ MouseInteractions2[MouseInteractions2["MouseUp"] = 0] = "MouseUp";
1571
+ MouseInteractions2[MouseInteractions2["MouseDown"] = 1] = "MouseDown";
1572
+ MouseInteractions2[MouseInteractions2["Click"] = 2] = "Click";
1573
+ MouseInteractions2[MouseInteractions2["ContextMenu"] = 3] = "ContextMenu";
1574
+ MouseInteractions2[MouseInteractions2["DblClick"] = 4] = "DblClick";
1575
+ MouseInteractions2[MouseInteractions2["Focus"] = 5] = "Focus";
1576
+ MouseInteractions2[MouseInteractions2["Blur"] = 6] = "Blur";
1577
+ MouseInteractions2[MouseInteractions2["TouchStart"] = 7] = "TouchStart";
1578
+ MouseInteractions2[MouseInteractions2["TouchMove_Departed"] = 8] = "TouchMove_Departed";
1579
+ MouseInteractions2[MouseInteractions2["TouchEnd"] = 9] = "TouchEnd";
1580
+ MouseInteractions2[MouseInteractions2["TouchCancel"] = 10] = "TouchCancel";
1581
+ return MouseInteractions2;
1582
+ })(MouseInteractions || {});
1583
+ var PointerTypes = /* @__PURE__ */ ((PointerTypes2) => {
1584
+ PointerTypes2[PointerTypes2["Mouse"] = 0] = "Mouse";
1585
+ PointerTypes2[PointerTypes2["Pen"] = 1] = "Pen";
1586
+ PointerTypes2[PointerTypes2["Touch"] = 2] = "Touch";
1587
+ return PointerTypes2;
1588
+ })(PointerTypes || {});
1589
+ var CanvasContext = /* @__PURE__ */ ((CanvasContext2) => {
1590
+ CanvasContext2[CanvasContext2["2D"] = 0] = "2D";
1591
+ CanvasContext2[CanvasContext2["WebGL"] = 1] = "WebGL";
1592
+ CanvasContext2[CanvasContext2["WebGL2"] = 2] = "WebGL2";
1593
+ return CanvasContext2;
1594
+ })(CanvasContext || {});
1325
1595
 
1326
1596
  function isNodeInLinkedList(n) {
1327
1597
  return '__ln' in n;
@@ -1330,6 +1600,7 @@ class DoubleLinkedList {
1330
1600
  constructor() {
1331
1601
  this.length = 0;
1332
1602
  this.head = null;
1603
+ this.tail = null;
1333
1604
  }
1334
1605
  get(position) {
1335
1606
  if (position >= this.length) {
@@ -1375,6 +1646,9 @@ class DoubleLinkedList {
1375
1646
  node.next = this.head;
1376
1647
  this.head = node;
1377
1648
  }
1649
+ if (node.next === null) {
1650
+ this.tail = node;
1651
+ }
1378
1652
  this.length++;
1379
1653
  }
1380
1654
  removeNode(n) {
@@ -1387,12 +1661,18 @@ class DoubleLinkedList {
1387
1661
  if (this.head) {
1388
1662
  this.head.previous = null;
1389
1663
  }
1664
+ else {
1665
+ this.tail = null;
1666
+ }
1390
1667
  }
1391
1668
  else {
1392
1669
  current.previous.next = current.next;
1393
1670
  if (current.next) {
1394
1671
  current.next.previous = current.previous;
1395
1672
  }
1673
+ else {
1674
+ this.tail = current.previous;
1675
+ }
1396
1676
  }
1397
1677
  if (n.__ln) {
1398
1678
  delete n.__ln;
@@ -1401,9 +1681,6 @@ class DoubleLinkedList {
1401
1681
  }
1402
1682
  }
1403
1683
  const moveKey = (id, parentId) => `${id}@${parentId}`;
1404
- function isINode(n) {
1405
- return '__sn' in n;
1406
- }
1407
1684
  class MutationBuffer {
1408
1685
  constructor() {
1409
1686
  this.frozen = false;
@@ -1425,6 +1702,7 @@ class MutationBuffer {
1425
1702
  return;
1426
1703
  }
1427
1704
  const adds = [];
1705
+ const addedIds = new Set();
1428
1706
  const addList = new DoubleLinkedList();
1429
1707
  const getNextId = (n) => {
1430
1708
  let ns = n;
@@ -1436,59 +1714,56 @@ class MutationBuffer {
1436
1714
  return nextId;
1437
1715
  };
1438
1716
  const pushAdd = (n) => {
1439
- var _a, _b, _c, _d, _e;
1440
- const shadowHost = n.getRootNode
1441
- ? (_a = n.getRootNode()) === null || _a === void 0 ? void 0 : _a.host
1442
- : null;
1443
- let rootShadowHost = shadowHost;
1444
- while ((_c = (_b = rootShadowHost === null || rootShadowHost === void 0 ? void 0 : rootShadowHost.getRootNode) === null || _b === void 0 ? void 0 : _b.call(rootShadowHost)) === null || _c === void 0 ? void 0 : _c.host)
1445
- rootShadowHost =
1446
- ((_e = (_d = rootShadowHost === null || rootShadowHost === void 0 ? void 0 : rootShadowHost.getRootNode) === null || _d === void 0 ? void 0 : _d.call(rootShadowHost)) === null || _e === void 0 ? void 0 : _e.host) ||
1447
- null;
1448
- const notInDoc = !this.doc.contains(n) &&
1449
- (!rootShadowHost || !this.doc.contains(rootShadowHost));
1450
- if (!n.parentNode || notInDoc) {
1717
+ if (!n.parentNode || !inDom(n)) {
1451
1718
  return;
1452
1719
  }
1453
1720
  const parentId = isShadowRoot(n.parentNode)
1454
- ? this.mirror.getId(shadowHost)
1721
+ ? this.mirror.getId(getShadowHost(n))
1455
1722
  : this.mirror.getId(n.parentNode);
1456
1723
  const nextId = getNextId(n);
1457
1724
  if (parentId === -1 || nextId === -1) {
1458
1725
  return addList.addNode(n);
1459
1726
  }
1460
- let sn = serializeNodeWithId(n, {
1727
+ const sn = serializeNodeWithId(n, {
1461
1728
  doc: this.doc,
1462
- map: this.mirror.map,
1729
+ mirror: this.mirror,
1463
1730
  blockClass: this.blockClass,
1464
1731
  blockSelector: this.blockSelector,
1732
+ maskAllText: this.maskAllText,
1465
1733
  unblockSelector: this.unblockSelector,
1466
1734
  maskTextClass: this.maskTextClass,
1735
+ unmaskTextClass: this.unmaskTextClass,
1467
1736
  maskTextSelector: this.maskTextSelector,
1468
1737
  unmaskTextSelector: this.unmaskTextSelector,
1469
- maskInputSelector: this.maskInputSelector,
1470
- unmaskInputSelector: this.unmaskInputSelector,
1471
1738
  skipChild: true,
1739
+ newlyAddedElement: true,
1472
1740
  inlineStylesheet: this.inlineStylesheet,
1473
- maskAllText: this.maskAllText,
1474
1741
  maskInputOptions: this.maskInputOptions,
1742
+ maskAttributeFn: this.maskAttributeFn,
1475
1743
  maskTextFn: this.maskTextFn,
1476
1744
  maskInputFn: this.maskInputFn,
1477
1745
  slimDOMOptions: this.slimDOMOptions,
1746
+ dataURLOptions: this.dataURLOptions,
1478
1747
  recordCanvas: this.recordCanvas,
1479
1748
  inlineImages: this.inlineImages,
1480
1749
  onSerialize: (currentN) => {
1481
- if (isIframeINode(currentN)) {
1750
+ if (isSerializedIframe(currentN, this.mirror)) {
1482
1751
  this.iframeManager.addIframe(currentN);
1483
1752
  }
1753
+ if (isSerializedStylesheet(currentN, this.mirror)) {
1754
+ this.stylesheetManager.trackLinkElement(currentN);
1755
+ }
1484
1756
  if (hasShadowRoot(n)) {
1485
- this.shadowDomManager.addShadowRoot(n.shadowRoot, document);
1757
+ this.shadowDomManager.addShadowRoot(n.shadowRoot, this.doc);
1486
1758
  }
1487
1759
  },
1488
1760
  onIframeLoad: (iframe, childSn) => {
1489
1761
  this.iframeManager.attachIframe(iframe, childSn);
1490
1762
  this.shadowDomManager.observeAttachShadow(iframe);
1491
1763
  },
1764
+ onStylesheetLoad: (link, childSn) => {
1765
+ this.stylesheetManager.attachLinkElement(link, childSn);
1766
+ },
1492
1767
  });
1493
1768
  if (sn) {
1494
1769
  adds.push({
@@ -1496,6 +1771,7 @@ class MutationBuffer {
1496
1771
  nextId,
1497
1772
  node: sn,
1498
1773
  });
1774
+ addedIds.add(sn.id);
1499
1775
  }
1500
1776
  };
1501
1777
  while (this.mapRemoves.length) {
@@ -1531,15 +1807,33 @@ class MutationBuffer {
1531
1807
  }
1532
1808
  }
1533
1809
  if (!node) {
1534
- for (let index = addList.length - 1; index >= 0; index--) {
1535
- const _node = addList.get(index);
1810
+ let tailNode = addList.tail;
1811
+ while (tailNode) {
1812
+ const _node = tailNode;
1813
+ tailNode = tailNode.previous;
1536
1814
  if (_node) {
1537
1815
  const parentId = this.mirror.getId(_node.value.parentNode);
1538
1816
  const nextId = getNextId(_node.value);
1539
- if (parentId !== -1 && nextId !== -1) {
1817
+ if (nextId === -1)
1818
+ continue;
1819
+ else if (parentId !== -1) {
1540
1820
  node = _node;
1541
1821
  break;
1542
1822
  }
1823
+ else {
1824
+ const unhandledNode = _node.value;
1825
+ if (unhandledNode.parentNode &&
1826
+ unhandledNode.parentNode.nodeType ===
1827
+ Node.DOCUMENT_FRAGMENT_NODE) {
1828
+ const shadowHost = unhandledNode.parentNode
1829
+ .host;
1830
+ const parentId = this.mirror.getId(shadowHost);
1831
+ if (parentId !== -1) {
1832
+ node = _node;
1833
+ break;
1834
+ }
1835
+ }
1836
+ }
1543
1837
  }
1544
1838
  }
1545
1839
  }
@@ -1559,12 +1853,27 @@ class MutationBuffer {
1559
1853
  id: this.mirror.getId(text.node),
1560
1854
  value: text.value,
1561
1855
  }))
1856
+ .filter((text) => !addedIds.has(text.id))
1562
1857
  .filter((text) => this.mirror.has(text.id)),
1563
1858
  attributes: this.attributes
1564
- .map((attribute) => ({
1565
- id: this.mirror.getId(attribute.node),
1566
- attributes: attribute.attributes,
1567
- }))
1859
+ .map((attribute) => {
1860
+ const { attributes } = attribute;
1861
+ if (typeof attributes.style === 'string') {
1862
+ const diffAsStr = JSON.stringify(attribute.styleDiff);
1863
+ const unchangedAsStr = JSON.stringify(attribute._unchangedStyles);
1864
+ if (diffAsStr.length < attributes.style.length) {
1865
+ if ((diffAsStr + unchangedAsStr).split('var(').length ===
1866
+ attributes.style.split('var(').length) {
1867
+ attributes.style = attribute.styleDiff;
1868
+ }
1869
+ }
1870
+ }
1871
+ return {
1872
+ id: this.mirror.getId(attribute.node),
1873
+ attributes: attributes,
1874
+ };
1875
+ })
1876
+ .filter((attribute) => !addedIds.has(attribute.id))
1568
1877
  .filter((attribute) => this.mirror.has(attribute.id)),
1569
1878
  removes: this.removes,
1570
1879
  adds,
@@ -1585,15 +1894,23 @@ class MutationBuffer {
1585
1894
  this.mutationCb(payload);
1586
1895
  };
1587
1896
  this.processMutation = (m) => {
1588
- if (isIgnored(m.target)) {
1897
+ if (isIgnored(m.target, this.mirror)) {
1589
1898
  return;
1590
1899
  }
1900
+ let unattachedDoc;
1901
+ try {
1902
+ unattachedDoc = document.implementation.createHTMLDocument();
1903
+ }
1904
+ catch (e) {
1905
+ unattachedDoc = this.doc;
1906
+ }
1591
1907
  switch (m.type) {
1592
1908
  case 'characterData': {
1593
1909
  const value = m.target.textContent;
1594
- if (!isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector) && value !== m.oldValue) {
1910
+ if (!isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, false) &&
1911
+ value !== m.oldValue) {
1595
1912
  this.texts.push({
1596
- value: needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, this.unmaskTextSelector, this.maskAllText) && value
1913
+ value: needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, this.unmaskTextClass, this.unmaskTextSelector, this.maskAllText) && value
1597
1914
  ? this.maskTextFn
1598
1915
  ? this.maskTextFn(value)
1599
1916
  : value.replace(/[\S]/g, '*')
@@ -1605,83 +1922,99 @@ class MutationBuffer {
1605
1922
  }
1606
1923
  case 'attributes': {
1607
1924
  const target = m.target;
1608
- let value = target.getAttribute(m.attributeName);
1609
- if (m.attributeName === 'value') {
1610
- value = maskInputValue({
1611
- input: target,
1612
- maskInputSelector: this.maskInputSelector,
1613
- unmaskInputSelector: this.unmaskInputSelector,
1925
+ let attributeName = m.attributeName;
1926
+ let value = m.target.getAttribute(attributeName);
1927
+ if (attributeName === 'value') {
1928
+ const type = getInputType(target);
1929
+ const tagName = target.tagName;
1930
+ value = getInputValue(target, tagName, type);
1931
+ const isInputMasked = shouldMaskInput({
1614
1932
  maskInputOptions: this.maskInputOptions,
1615
- tagName: target.tagName,
1616
- type: target.getAttribute('type'),
1933
+ tagName,
1934
+ type,
1935
+ });
1936
+ const forceMask = needMaskingText(m.target, this.maskTextClass, this.maskTextSelector, this.unmaskTextClass, this.unmaskTextSelector, isInputMasked);
1937
+ value = maskInputValue({
1938
+ isMasked: forceMask,
1939
+ element: target,
1617
1940
  value,
1618
1941
  maskInputFn: this.maskInputFn,
1619
1942
  });
1620
1943
  }
1621
- if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector) || value === m.oldValue) {
1944
+ if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, false) ||
1945
+ value === m.oldValue) {
1622
1946
  return;
1623
1947
  }
1624
1948
  let item = this.attributes.find((a) => a.node === m.target);
1949
+ if (target.tagName === 'IFRAME' &&
1950
+ attributeName === 'src' &&
1951
+ !this.keepIframeSrcFn(value)) {
1952
+ if (!target.contentDocument) {
1953
+ attributeName = 'rr_src';
1954
+ }
1955
+ else {
1956
+ return;
1957
+ }
1958
+ }
1625
1959
  if (!item) {
1626
1960
  item = {
1627
1961
  node: m.target,
1628
1962
  attributes: {},
1963
+ styleDiff: {},
1964
+ _unchangedStyles: {},
1629
1965
  };
1630
1966
  this.attributes.push(item);
1631
1967
  }
1632
- if (m.attributeName === 'type' &&
1968
+ if (attributeName === 'type' &&
1633
1969
  target.tagName === 'INPUT' &&
1634
1970
  (m.oldValue || '').toLowerCase() === 'password') {
1635
1971
  target.setAttribute('data-rr-is-password', 'true');
1636
1972
  }
1637
- if (m.attributeName === 'style') {
1638
- const old = this.doc.createElement('span');
1639
- if (m.oldValue) {
1640
- old.setAttribute('style', m.oldValue);
1641
- }
1642
- if (item.attributes.style === undefined ||
1643
- item.attributes.style === null) {
1644
- item.attributes.style = {};
1645
- }
1646
- try {
1647
- const styleObj = item.attributes.style;
1973
+ if (!ignoreAttribute(target.tagName, attributeName)) {
1974
+ item.attributes[attributeName] = transformAttribute(this.doc, toLowerCase(target.tagName), toLowerCase(attributeName), value, target, this.maskAttributeFn);
1975
+ if (attributeName === 'style') {
1976
+ const old = unattachedDoc.createElement('span');
1977
+ if (m.oldValue) {
1978
+ old.setAttribute('style', m.oldValue);
1979
+ }
1648
1980
  for (const pname of Array.from(target.style)) {
1649
1981
  const newValue = target.style.getPropertyValue(pname);
1650
1982
  const newPriority = target.style.getPropertyPriority(pname);
1651
1983
  if (newValue !== old.style.getPropertyValue(pname) ||
1652
1984
  newPriority !== old.style.getPropertyPriority(pname)) {
1653
1985
  if (newPriority === '') {
1654
- styleObj[pname] = newValue;
1986
+ item.styleDiff[pname] = newValue;
1655
1987
  }
1656
1988
  else {
1657
- styleObj[pname] = [newValue, newPriority];
1989
+ item.styleDiff[pname] = [newValue, newPriority];
1658
1990
  }
1659
1991
  }
1992
+ else {
1993
+ item._unchangedStyles[pname] = [newValue, newPriority];
1994
+ }
1660
1995
  }
1661
1996
  for (const pname of Array.from(old.style)) {
1662
1997
  if (target.style.getPropertyValue(pname) === '') {
1663
- styleObj[pname] = false;
1998
+ item.styleDiff[pname] = false;
1664
1999
  }
1665
2000
  }
1666
2001
  }
1667
- catch (error) {
1668
- console.warn('[rrweb] Error when parsing update to style attribute:', error);
1669
- }
1670
- }
1671
- else {
1672
- const element = m.target;
1673
- item.attributes[m.attributeName] = transformAttribute(this.doc, element, element.tagName, m.attributeName, value, this.maskAllText, this.unmaskTextSelector, this.maskTextFn);
1674
2002
  }
1675
2003
  break;
1676
2004
  }
1677
2005
  case 'childList': {
2006
+ if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, true)) {
2007
+ return;
2008
+ }
1678
2009
  m.addedNodes.forEach((n) => this.genAdds(n, m.target));
1679
2010
  m.removedNodes.forEach((n) => {
1680
2011
  const nodeId = this.mirror.getId(n);
1681
2012
  const parentId = isShadowRoot(m.target)
1682
2013
  ? this.mirror.getId(m.target.host)
1683
2014
  : this.mirror.getId(m.target);
1684
- if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector) || isIgnored(n)) {
2015
+ if (isBlocked(m.target, this.blockClass, this.blockSelector, this.unblockSelector, false) ||
2016
+ isIgnored(n, this.mirror) ||
2017
+ !isSerialized(n, this.mirror)) {
1685
2018
  return;
1686
2019
  }
1687
2020
  if (this.addedSet.has(n)) {
@@ -1698,7 +2031,9 @@ class MutationBuffer {
1698
2031
  this.removes.push({
1699
2032
  parentId,
1700
2033
  id: nodeId,
1701
- isShadow: isShadowRoot(m.target) ? true : undefined,
2034
+ isShadow: isShadowRoot(m.target) && isNativeShadowDom(m.target)
2035
+ ? true
2036
+ : undefined,
1702
2037
  });
1703
2038
  }
1704
2039
  this.mapRemoves.push(n);
@@ -1708,28 +2043,36 @@ class MutationBuffer {
1708
2043
  }
1709
2044
  };
1710
2045
  this.genAdds = (n, target) => {
1711
- if (target && isBlocked(target, this.blockClass, this.blockSelector, this.unblockSelector)) {
2046
+ if (this.processedNodeManager.inOtherBuffer(n, this))
1712
2047
  return;
1713
- }
1714
- if (isINode(n)) {
1715
- if (isIgnored(n)) {
2048
+ if (this.addedSet.has(n) || this.movedSet.has(n))
2049
+ return;
2050
+ if (this.mirror.hasNode(n)) {
2051
+ if (isIgnored(n, this.mirror)) {
1716
2052
  return;
1717
2053
  }
1718
2054
  this.movedSet.add(n);
1719
2055
  let targetId = null;
1720
- if (target && isINode(target)) {
1721
- targetId = target.__sn.id;
2056
+ if (target && this.mirror.hasNode(target)) {
2057
+ targetId = this.mirror.getId(target);
1722
2058
  }
1723
- if (targetId) {
1724
- this.movedMap[moveKey(n.__sn.id, targetId)] = true;
2059
+ if (targetId && targetId !== -1) {
2060
+ this.movedMap[moveKey(this.mirror.getId(n), targetId)] = true;
1725
2061
  }
1726
2062
  }
1727
2063
  else {
1728
2064
  this.addedSet.add(n);
1729
2065
  this.droppedSet.delete(n);
1730
2066
  }
1731
- if (!isBlocked(n, this.blockClass, this.blockSelector, this.unblockSelector))
2067
+ if (!isBlocked(n, this.blockClass, this.blockSelector, this.unblockSelector, false)) {
1732
2068
  n.childNodes.forEach((childN) => this.genAdds(childN));
2069
+ if (hasShadowRoot(n)) {
2070
+ n.shadowRoot.childNodes.forEach((childN) => {
2071
+ this.processedNodeManager.add(childN, this);
2072
+ this.genAdds(childN, n);
2073
+ });
2074
+ }
2075
+ }
1733
2076
  };
1734
2077
  }
1735
2078
  init(options) {
@@ -1738,24 +2081,28 @@ class MutationBuffer {
1738
2081
  'blockClass',
1739
2082
  'blockSelector',
1740
2083
  'unblockSelector',
2084
+ 'maskAllText',
1741
2085
  'maskTextClass',
2086
+ 'unmaskTextClass',
1742
2087
  'maskTextSelector',
1743
2088
  'unmaskTextSelector',
1744
- 'maskInputSelector',
1745
- 'unmaskInputSelector',
1746
2089
  'inlineStylesheet',
1747
- 'maskAllText',
1748
2090
  'maskInputOptions',
2091
+ 'maskAttributeFn',
1749
2092
  'maskTextFn',
1750
2093
  'maskInputFn',
2094
+ 'keepIframeSrcFn',
1751
2095
  'recordCanvas',
1752
2096
  'inlineImages',
1753
2097
  'slimDOMOptions',
2098
+ 'dataURLOptions',
1754
2099
  'doc',
1755
2100
  'mirror',
1756
2101
  'iframeManager',
2102
+ 'stylesheetManager',
1757
2103
  'shadowDomManager',
1758
2104
  'canvasManager',
2105
+ 'processedNodeManager',
1759
2106
  ].forEach((key) => {
1760
2107
  this[key] = options[key];
1761
2108
  });
@@ -1791,6 +2138,11 @@ function deepDelete(addsSet, n) {
1791
2138
  n.childNodes.forEach((childN) => deepDelete(addsSet, childN));
1792
2139
  }
1793
2140
  function isParentRemoved(removes, n, mirror) {
2141
+ if (removes.length === 0)
2142
+ return false;
2143
+ return _isParentRemoved(removes, n, mirror);
2144
+ }
2145
+ function _isParentRemoved(removes, n, mirror) {
1794
2146
  const { parentNode } = n;
1795
2147
  if (!parentNode) {
1796
2148
  return false;
@@ -1799,9 +2151,14 @@ function isParentRemoved(removes, n, mirror) {
1799
2151
  if (removes.some((r) => r.id === parentId)) {
1800
2152
  return true;
1801
2153
  }
1802
- return isParentRemoved(removes, parentNode, mirror);
2154
+ return _isParentRemoved(removes, parentNode, mirror);
1803
2155
  }
1804
2156
  function isAncestorInSet(set, n) {
2157
+ if (set.size === 0)
2158
+ return false;
2159
+ return _isAncestorInSet(set, n);
2160
+ }
2161
+ function _isAncestorInSet(set, n) {
1805
2162
  const { parentNode } = n;
1806
2163
  if (!parentNode) {
1807
2164
  return false;
@@ -1809,23 +2166,32 @@ function isAncestorInSet(set, n) {
1809
2166
  if (set.has(parentNode)) {
1810
2167
  return true;
1811
2168
  }
1812
- return isAncestorInSet(set, parentNode);
2169
+ return _isAncestorInSet(set, parentNode);
1813
2170
  }
1814
2171
 
2172
+ let errorHandler;
2173
+ function registerErrorHandler(handler) {
2174
+ errorHandler = handler;
2175
+ }
2176
+ function unregisterErrorHandler() {
2177
+ errorHandler = undefined;
2178
+ }
1815
2179
  const callbackWrapper = (cb) => {
1816
- const rrwebWrapped = (...rest) => {
2180
+ if (!errorHandler) {
2181
+ return cb;
2182
+ }
2183
+ const rrwebWrapped = ((...rest) => {
1817
2184
  try {
1818
2185
  return cb(...rest);
1819
2186
  }
1820
2187
  catch (error) {
1821
- try {
1822
- error.__rrweb__ = true;
1823
- }
1824
- catch (_a) {
2188
+ if (errorHandler && errorHandler(error) === true) {
2189
+ return () => {
2190
+ };
1825
2191
  }
1826
2192
  throw error;
1827
2193
  }
1828
- };
2194
+ });
1829
2195
  return rrwebWrapped;
1830
2196
  };
1831
2197
 
@@ -1842,7 +2208,8 @@ function getEventTarget(event) {
1842
2208
  return event.path[0];
1843
2209
  }
1844
2210
  }
1845
- catch (_a) { }
2211
+ catch (_a) {
2212
+ }
1846
2213
  return event && event.target;
1847
2214
  }
1848
2215
  function initMutationObserver(options, rootEl) {
@@ -1861,7 +2228,7 @@ function initMutationObserver(options, rootEl) {
1861
2228
  if (options.onMutation && options.onMutation(mutations) === false) {
1862
2229
  return;
1863
2230
  }
1864
- mutationBuffer.processMutations(mutations);
2231
+ mutationBuffer.processMutations.bind(mutationBuffer)(mutations);
1865
2232
  }));
1866
2233
  observer.observe(rootEl, {
1867
2234
  attributes: true,
@@ -1875,7 +2242,8 @@ function initMutationObserver(options, rootEl) {
1875
2242
  }
1876
2243
  function initMoveObserver({ mousemoveCb, sampling, doc, mirror, }) {
1877
2244
  if (sampling.mousemove === false) {
1878
- return () => { };
2245
+ return () => {
2246
+ };
1879
2247
  }
1880
2248
  const threshold = typeof sampling.mousemove === 'number' ? sampling.mousemove : 50;
1881
2249
  const callbackThreshold = typeof sampling.mousemoveCallback === 'number'
@@ -1883,41 +2251,41 @@ function initMoveObserver({ mousemoveCb, sampling, doc, mirror, }) {
1883
2251
  : 500;
1884
2252
  let positions = [];
1885
2253
  let timeBaseline;
1886
- const wrappedCb = throttle$1((source) => {
2254
+ const wrappedCb = throttle$1(callbackWrapper((source) => {
1887
2255
  const totalOffset = Date.now() - timeBaseline;
1888
- callbackWrapper(mousemoveCb)(positions.map((p) => {
2256
+ mousemoveCb(positions.map((p) => {
1889
2257
  p.timeOffset -= totalOffset;
1890
2258
  return p;
1891
2259
  }), source);
1892
2260
  positions = [];
1893
2261
  timeBaseline = null;
1894
- }, callbackThreshold);
1895
- const updatePosition = throttle$1((evt) => {
2262
+ }), callbackThreshold);
2263
+ const updatePosition = callbackWrapper(throttle$1(callbackWrapper((evt) => {
1896
2264
  const target = getEventTarget(evt);
1897
- const { clientX, clientY } = isTouchEvent(evt)
2265
+ const { clientX, clientY } = legacy_isTouchEvent(evt)
1898
2266
  ? evt.changedTouches[0]
1899
2267
  : evt;
1900
2268
  if (!timeBaseline) {
1901
- timeBaseline = Date.now();
2269
+ timeBaseline = nowTimestamp();
1902
2270
  }
1903
2271
  positions.push({
1904
2272
  x: clientX,
1905
2273
  y: clientY,
1906
2274
  id: mirror.getId(target),
1907
- timeOffset: Date.now() - timeBaseline,
2275
+ timeOffset: nowTimestamp() - timeBaseline,
1908
2276
  });
1909
2277
  wrappedCb(typeof DragEvent !== 'undefined' && evt instanceof DragEvent
1910
2278
  ? IncrementalSource.Drag
1911
2279
  : evt instanceof MouseEvent
1912
2280
  ? IncrementalSource.MouseMove
1913
2281
  : IncrementalSource.TouchMove);
1914
- }, threshold, {
2282
+ }), threshold, {
1915
2283
  trailing: false,
1916
- });
2284
+ }));
1917
2285
  const handlers = [
1918
- on('mousemove', callbackWrapper(updatePosition), doc),
1919
- on('touchmove', callbackWrapper(updatePosition), doc),
1920
- on('drag', callbackWrapper(updatePosition), doc),
2286
+ on('mousemove', updatePosition, doc),
2287
+ on('touchmove', updatePosition, doc),
2288
+ on('drag', updatePosition, doc),
1921
2289
  ];
1922
2290
  return callbackWrapper(() => {
1923
2291
  handlers.forEach((h) => h());
@@ -1925,31 +2293,68 @@ function initMoveObserver({ mousemoveCb, sampling, doc, mirror, }) {
1925
2293
  }
1926
2294
  function initMouseInteractionObserver({ mouseInteractionCb, doc, mirror, blockClass, blockSelector, unblockSelector, sampling, }) {
1927
2295
  if (sampling.mouseInteraction === false) {
1928
- return () => { };
2296
+ return () => {
2297
+ };
1929
2298
  }
1930
2299
  const disableMap = sampling.mouseInteraction === true ||
1931
2300
  sampling.mouseInteraction === undefined
1932
2301
  ? {}
1933
2302
  : sampling.mouseInteraction;
1934
2303
  const handlers = [];
2304
+ let currentPointerType = null;
1935
2305
  const getHandler = (eventKey) => {
1936
2306
  return (event) => {
1937
2307
  const target = getEventTarget(event);
1938
- if (isBlocked(target, blockClass, blockSelector, unblockSelector)) {
2308
+ if (isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
1939
2309
  return;
1940
2310
  }
1941
- const e = isTouchEvent(event) ? event.changedTouches[0] : event;
2311
+ let pointerType = null;
2312
+ let thisEventKey = eventKey;
2313
+ if ('pointerType' in event) {
2314
+ switch (event.pointerType) {
2315
+ case 'mouse':
2316
+ pointerType = PointerTypes.Mouse;
2317
+ break;
2318
+ case 'touch':
2319
+ pointerType = PointerTypes.Touch;
2320
+ break;
2321
+ case 'pen':
2322
+ pointerType = PointerTypes.Pen;
2323
+ break;
2324
+ }
2325
+ if (pointerType === PointerTypes.Touch) {
2326
+ if (MouseInteractions[eventKey] === MouseInteractions.MouseDown) {
2327
+ thisEventKey = 'TouchStart';
2328
+ }
2329
+ else if (MouseInteractions[eventKey] === MouseInteractions.MouseUp) {
2330
+ thisEventKey = 'TouchEnd';
2331
+ }
2332
+ }
2333
+ else if (pointerType === PointerTypes.Pen) ;
2334
+ }
2335
+ else if (legacy_isTouchEvent(event)) {
2336
+ pointerType = PointerTypes.Touch;
2337
+ }
2338
+ if (pointerType !== null) {
2339
+ currentPointerType = pointerType;
2340
+ if ((thisEventKey.startsWith('Touch') &&
2341
+ pointerType === PointerTypes.Touch) ||
2342
+ (thisEventKey.startsWith('Mouse') &&
2343
+ pointerType === PointerTypes.Mouse)) {
2344
+ pointerType = null;
2345
+ }
2346
+ }
2347
+ else if (MouseInteractions[eventKey] === MouseInteractions.Click) {
2348
+ pointerType = currentPointerType;
2349
+ currentPointerType = null;
2350
+ }
2351
+ const e = legacy_isTouchEvent(event) ? event.changedTouches[0] : event;
1942
2352
  if (!e) {
1943
2353
  return;
1944
2354
  }
1945
2355
  const id = mirror.getId(target);
1946
2356
  const { clientX, clientY } = e;
1947
- callbackWrapper(mouseInteractionCb)({
1948
- type: MouseInteractions[eventKey],
1949
- id,
1950
- x: clientX,
1951
- y: clientY,
1952
- });
2357
+ callbackWrapper(mouseInteractionCb)(Object.assign({ type: MouseInteractions[thisEventKey], id, x: clientX, y: clientY }, (pointerType !== null && { pointerType })));
1953
2358
  };
1954
2359
  };
1955
2360
  Object.keys(MouseInteractions)
@@ -1957,8 +2362,19 @@ function initMouseInteractionObserver({ mouseInteractionCb, doc, mirror, blockCl
1957
2362
  !key.endsWith('_Departed') &&
1958
2363
  disableMap[key] !== false)
1959
2364
  .forEach((eventKey) => {
1960
- const eventName = eventKey.toLowerCase();
1961
- const handler = callbackWrapper(getHandler(eventKey));
2365
+ let eventName = toLowerCase(eventKey);
2366
+ const handler = getHandler(eventKey);
2367
+ if (window.PointerEvent) {
2368
+ switch (MouseInteractions[eventKey]) {
2369
+ case MouseInteractions.MouseDown:
2370
+ case MouseInteractions.MouseUp:
2371
+ eventName = eventName.replace('mouse', 'pointer');
2372
+ break;
2373
+ case MouseInteractions.TouchStart:
2374
+ case MouseInteractions.TouchEnd:
2375
+ return;
2376
+ }
2377
+ }
1962
2378
  handlers.push(on(eventName, handler, doc));
1963
2379
  });
1964
2380
  return callbackWrapper(() => {
@@ -1966,47 +2382,47 @@ function initMouseInteractionObserver({ mouseInteractionCb, doc, mirror, blockCl
1966
2382
  });
1967
2383
  }
1968
2384
  function initScrollObserver({ scrollCb, doc, mirror, blockClass, blockSelector, unblockSelector, sampling, }) {
1969
- const updatePosition = throttle$1((evt) => {
2385
+ const updatePosition = callbackWrapper(throttle$1(callbackWrapper((evt) => {
1970
2386
  const target = getEventTarget(evt);
1971
2387
  if (!target ||
1972
- isBlocked(target, blockClass, blockSelector, unblockSelector)) {
2388
+ isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
1973
2389
  return;
1974
2390
  }
1975
2391
  const id = mirror.getId(target);
1976
- if (target === doc) {
1977
- const scrollEl = (doc.scrollingElement || doc.documentElement);
1978
- callbackWrapper(scrollCb)({
2392
+ if (target === doc && doc.defaultView) {
2393
+ const scrollLeftTop = getWindowScroll(doc.defaultView);
2394
+ scrollCb({
1979
2395
  id,
1980
- x: scrollEl.scrollLeft,
1981
- y: scrollEl.scrollTop,
2396
+ x: scrollLeftTop.left,
2397
+ y: scrollLeftTop.top,
1982
2398
  });
1983
2399
  }
1984
2400
  else {
1985
- callbackWrapper(scrollCb)({
2401
+ scrollCb({
1986
2402
  id,
1987
2403
  x: target.scrollLeft,
1988
2404
  y: target.scrollTop,
1989
2405
  });
1990
2406
  }
1991
- }, sampling.scroll || 100);
1992
- return on('scroll', callbackWrapper(updatePosition), doc);
2407
+ }), sampling.scroll || 100));
2408
+ return on('scroll', updatePosition, doc);
1993
2409
  }
1994
- function initViewportResizeObserver({ viewportResizeCb, }) {
2410
+ function initViewportResizeObserver({ viewportResizeCb }, { win }) {
1995
2411
  let lastH = -1;
1996
2412
  let lastW = -1;
1997
- const updateDimension = throttle$1(() => {
2413
+ const updateDimension = callbackWrapper(throttle$1(callbackWrapper(() => {
1998
2414
  const height = getWindowHeight();
1999
2415
  const width = getWindowWidth();
2000
2416
  if (lastH !== height || lastW !== width) {
2001
- callbackWrapper(viewportResizeCb)({
2417
+ viewportResizeCb({
2002
2418
  width: Number(width),
2003
2419
  height: Number(height),
2004
2420
  });
2005
2421
  lastH = height;
2006
2422
  lastW = width;
2007
2423
  }
2008
- }, 200);
2009
- return on('resize', callbackWrapper(updateDimension), window);
2424
+ }), 200));
2425
+ return on('resize', updateDimension, win);
2010
2426
  }
2011
2427
  function wrapEventWithUserTriggeredFlag(v, enable) {
2012
2428
  const value = Object.assign({}, v);
@@ -2016,47 +2432,42 @@ function wrapEventWithUserTriggeredFlag(v, enable) {
2016
2432
  }
2017
2433
  const INPUT_TAGS = ['INPUT', 'TEXTAREA', 'SELECT'];
2018
2434
  const lastInputValueMap = new WeakMap();
2019
- function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, unblockSelector, ignoreClass, ignoreSelector, maskInputSelector, unmaskInputSelector, maskInputOptions, maskInputFn, sampling, userTriggeredOnInput, }) {
2435
+ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, unblockSelector, ignoreClass, ignoreSelector, maskInputOptions, maskInputFn, sampling, userTriggeredOnInput, maskTextClass, unmaskTextClass, maskTextSelector, unmaskTextSelector, }) {
2020
2436
  function eventHandler(event) {
2021
2437
  let target = getEventTarget(event);
2022
- const tagName = target && target.tagName;
2023
2438
  const userTriggered = event.isTrusted;
2439
+ const tagName = target && toUpperCase(target.tagName);
2024
2440
  if (tagName === 'OPTION')
2025
2441
  target = target.parentElement;
2026
2442
  if (!target ||
2027
2443
  !tagName ||
2028
2444
  INPUT_TAGS.indexOf(tagName) < 0 ||
2029
- isBlocked(target, blockClass, blockSelector, unblockSelector)) {
2445
+ isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
2030
2446
  return;
2031
2447
  }
2032
2448
  const el = target;
2033
- const type = getInputType(el);
2034
2449
  if (el.classList.contains(ignoreClass) ||
2035
2450
  (ignoreSelector && el.matches(ignoreSelector))) {
2036
2451
  return;
2037
2452
  }
2453
+ const type = getInputType(target);
2038
2454
  let text = getInputValue(el, tagName, type);
2039
2455
  let isChecked = false;
2040
- if (type === 'radio' || type === 'checkbox') {
2041
- isChecked = target.checked;
2042
- }
2043
- if (hasInputMaskOptions({
2456
+ const isInputMasked = shouldMaskInput({
2044
2457
  maskInputOptions,
2045
- maskInputSelector,
2046
2458
  tagName,
2047
2459
  type,
2048
- })) {
2049
- text = maskInputValue({
2050
- input: el,
2051
- maskInputOptions,
2052
- maskInputSelector,
2053
- unmaskInputSelector,
2054
- tagName,
2055
- type,
2056
- value: text,
2057
- maskInputFn,
2058
- });
2460
+ });
2461
+ const forceMask = needMaskingText(target, maskTextClass, maskTextSelector, unmaskTextClass, unmaskTextSelector, isInputMasked);
2462
+ if (type === 'radio' || type === 'checkbox') {
2463
+ isChecked = target.checked;
2059
2464
  }
2465
+ text = maskInputValue({
2466
+ isMasked: forceMask,
2467
+ element: target,
2468
+ value: text,
2469
+ maskInputFn,
2470
+ });
2060
2471
  cbWithDedup(target, callbackWrapper(wrapEventWithUserTriggeredFlag)({ text, isChecked, userTriggered }, userTriggeredOnInput));
2061
2472
  const name = target.name;
2062
2473
  if (type === 'radio' && name && isChecked) {
@@ -2065,12 +2476,8 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
2065
2476
  .forEach((el) => {
2066
2477
  if (el !== target) {
2067
2478
  const text = maskInputValue({
2068
- input: el,
2069
- maskInputOptions,
2070
- maskInputSelector,
2071
- unmaskInputSelector,
2072
- tagName,
2073
- type,
2479
+ isMasked: forceMask,
2480
+ element: el,
2074
2481
  value: getInputValue(el, tagName, type),
2075
2482
  maskInputFn,
2076
2483
  });
@@ -2090,26 +2497,35 @@ function initInputObserver({ inputCb, doc, mirror, blockClass, blockSelector, un
2090
2497
  lastInputValue.isChecked !== v.isChecked) {
2091
2498
  lastInputValueMap.set(target, v);
2092
2499
  const id = mirror.getId(target);
2093
- inputCb(Object.assign(Object.assign({}, v), { id }));
2500
+ callbackWrapper(inputCb)(Object.assign(Object.assign({}, v), { id }));
2094
2501
  }
2095
2502
  }
2096
2503
  const events = sampling.input === 'last' ? ['change'] : ['input', 'change'];
2097
2504
  const handlers = events.map((eventName) => on(eventName, callbackWrapper(eventHandler), doc));
2098
- const propertyDescriptor = Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value');
2505
+ const currentWindow = doc.defaultView;
2506
+ if (!currentWindow) {
2507
+ return () => {
2508
+ handlers.forEach((h) => h());
2509
+ };
2510
+ }
2511
+ const propertyDescriptor = currentWindow.Object.getOwnPropertyDescriptor(currentWindow.HTMLInputElement.prototype, 'value');
2099
2512
  const hookProperties = [
2100
- [HTMLInputElement.prototype, 'value'],
2101
- [HTMLInputElement.prototype, 'checked'],
2102
- [HTMLSelectElement.prototype, 'value'],
2103
- [HTMLTextAreaElement.prototype, 'value'],
2104
- [HTMLSelectElement.prototype, 'selectedIndex'],
2105
- [HTMLOptionElement.prototype, 'selected'],
2513
+ [currentWindow.HTMLInputElement.prototype, 'value'],
2514
+ [currentWindow.HTMLInputElement.prototype, 'checked'],
2515
+ [currentWindow.HTMLSelectElement.prototype, 'value'],
2516
+ [currentWindow.HTMLTextAreaElement.prototype, 'value'],
2517
+ [currentWindow.HTMLSelectElement.prototype, 'selectedIndex'],
2518
+ [currentWindow.HTMLOptionElement.prototype, 'selected'],
2106
2519
  ];
2107
2520
  if (propertyDescriptor && propertyDescriptor.set) {
2108
2521
  handlers.push(...hookProperties.map((p) => hookSetter(p[0], p[1], {
2109
2522
  set() {
2110
- callbackWrapper(eventHandler)({ target: this });
2523
+ callbackWrapper(eventHandler)({
2524
+ target: this,
2525
+ isTrusted: false,
2526
+ });
2111
2527
  },
2112
- })));
2528
+ }, false, currentWindow)));
2113
2529
  }
2114
2530
  return callbackWrapper(() => {
2115
2531
  handlers.forEach((h) => h());
@@ -2130,7 +2546,7 @@ function getNestedCSSRulePositions(rule) {
2130
2546
  const index = rules.indexOf(childRule);
2131
2547
  pos.unshift(index);
2132
2548
  }
2133
- else {
2549
+ else if (childRule.parentStyleSheet) {
2134
2550
  const rules = Array.from(childRule.parentStyleSheet.cssRules);
2135
2551
  const index = rules.indexOf(childRule);
2136
2552
  pos.unshift(index);
@@ -2139,18 +2555,33 @@ function getNestedCSSRulePositions(rule) {
2139
2555
  }
2140
2556
  return recurse(rule, positions);
2141
2557
  }
2142
- function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
2558
+ function getIdAndStyleId(sheet, mirror, styleMirror) {
2559
+ let id, styleId;
2560
+ if (!sheet)
2561
+ return {};
2562
+ if (sheet.ownerNode)
2563
+ id = mirror.getId(sheet.ownerNode);
2564
+ else
2565
+ styleId = styleMirror.getId(sheet);
2566
+ return {
2567
+ styleId,
2568
+ id,
2569
+ };
2570
+ }
2571
+ function initStyleSheetObserver({ styleSheetRuleCb, mirror, stylesheetManager }, { win }) {
2143
2572
  if (!win.CSSStyleSheet || !win.CSSStyleSheet.prototype) {
2144
- return () => { };
2573
+ return () => {
2574
+ };
2145
2575
  }
2146
2576
  const insertRule = win.CSSStyleSheet.prototype.insertRule;
2147
2577
  win.CSSStyleSheet.prototype.insertRule = new Proxy(insertRule, {
2148
2578
  apply: callbackWrapper((target, thisArg, argumentsList) => {
2149
2579
  const [rule, index] = argumentsList;
2150
- const id = mirror.getId(thisArg.ownerNode);
2151
- if (id !== -1) {
2580
+ const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
2581
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2152
2582
  styleSheetRuleCb({
2153
2583
  id,
2584
+ styleId,
2154
2585
  adds: [{ rule, index }],
2155
2586
  });
2156
2587
  }
@@ -2161,16 +2592,53 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
2161
2592
  win.CSSStyleSheet.prototype.deleteRule = new Proxy(deleteRule, {
2162
2593
  apply: callbackWrapper((target, thisArg, argumentsList) => {
2163
2594
  const [index] = argumentsList;
2164
- const id = mirror.getId(thisArg.ownerNode);
2165
- if (id !== -1) {
2595
+ const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
2596
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2166
2597
  styleSheetRuleCb({
2167
2598
  id,
2599
+ styleId,
2168
2600
  removes: [{ index }],
2169
2601
  });
2170
2602
  }
2171
2603
  return target.apply(thisArg, argumentsList);
2172
2604
  }),
2173
2605
  });
2606
+ let replace;
2607
+ if (win.CSSStyleSheet.prototype.replace) {
2608
+ replace = win.CSSStyleSheet.prototype.replace;
2609
+ win.CSSStyleSheet.prototype.replace = new Proxy(replace, {
2610
+ apply: callbackWrapper((target, thisArg, argumentsList) => {
2611
+ const [text] = argumentsList;
2612
+ const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
2613
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2614
+ styleSheetRuleCb({
2615
+ id,
2616
+ styleId,
2617
+ replace: text,
2618
+ });
2619
+ }
2620
+ return target.apply(thisArg, argumentsList);
2621
+ }),
2622
+ });
2623
+ }
2624
+ let replaceSync;
2625
+ if (win.CSSStyleSheet.prototype.replaceSync) {
2626
+ replaceSync = win.CSSStyleSheet.prototype.replaceSync;
2627
+ win.CSSStyleSheet.prototype.replaceSync = new Proxy(replaceSync, {
2628
+ apply: callbackWrapper((target, thisArg, argumentsList) => {
2629
+ const [text] = argumentsList;
2630
+ const { id, styleId } = getIdAndStyleId(thisArg, mirror, stylesheetManager.styleMirror);
2631
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2632
+ styleSheetRuleCb({
2633
+ id,
2634
+ styleId,
2635
+ replaceSync: text,
2636
+ });
2637
+ }
2638
+ return target.apply(thisArg, argumentsList);
2639
+ }),
2640
+ });
2641
+ }
2174
2642
  const supportedNestedCSSRuleTypes = {};
2175
2643
  if (canMonkeyPatchNestedCSSRule('CSSGroupingRule')) {
2176
2644
  supportedNestedCSSRuleTypes.CSSGroupingRule = win.CSSGroupingRule;
@@ -2195,10 +2663,11 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
2195
2663
  type.prototype.insertRule = new Proxy(unmodifiedFunctions[typeKey].insertRule, {
2196
2664
  apply: callbackWrapper((target, thisArg, argumentsList) => {
2197
2665
  const [rule, index] = argumentsList;
2198
- const id = mirror.getId(thisArg.parentStyleSheet.ownerNode);
2199
- if (id !== -1) {
2666
+ const { id, styleId } = getIdAndStyleId(thisArg.parentStyleSheet, mirror, stylesheetManager.styleMirror);
2667
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2200
2668
  styleSheetRuleCb({
2201
2669
  id,
2670
+ styleId,
2202
2671
  adds: [
2203
2672
  {
2204
2673
  rule,
@@ -2216,10 +2685,11 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
2216
2685
  type.prototype.deleteRule = new Proxy(unmodifiedFunctions[typeKey].deleteRule, {
2217
2686
  apply: callbackWrapper((target, thisArg, argumentsList) => {
2218
2687
  const [index] = argumentsList;
2219
- const id = mirror.getId(thisArg.parentStyleSheet.ownerNode);
2220
- if (id !== -1) {
2688
+ const { id, styleId } = getIdAndStyleId(thisArg.parentStyleSheet, mirror, stylesheetManager.styleMirror);
2689
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2221
2690
  styleSheetRuleCb({
2222
2691
  id,
2692
+ styleId,
2223
2693
  removes: [
2224
2694
  { index: [...getNestedCSSRulePositions(thisArg), index] },
2225
2695
  ],
@@ -2232,22 +2702,76 @@ function initStyleSheetObserver({ styleSheetRuleCb, mirror }, { win }) {
2232
2702
  return callbackWrapper(() => {
2233
2703
  win.CSSStyleSheet.prototype.insertRule = insertRule;
2234
2704
  win.CSSStyleSheet.prototype.deleteRule = deleteRule;
2705
+ replace && (win.CSSStyleSheet.prototype.replace = replace);
2706
+ replaceSync && (win.CSSStyleSheet.prototype.replaceSync = replaceSync);
2235
2707
  Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
2236
2708
  type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
2237
2709
  type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
2238
2710
  });
2239
2711
  });
2240
2712
  }
2241
- function initStyleDeclarationObserver({ styleDeclarationCb, mirror }, { win }) {
2713
+ function initAdoptedStyleSheetObserver({ mirror, stylesheetManager, }, host) {
2714
+ var _a, _b, _c;
2715
+ let hostId = null;
2716
+ if (host.nodeName === '#document')
2717
+ hostId = mirror.getId(host);
2718
+ else
2719
+ hostId = mirror.getId(host.host);
2720
+ const patchTarget = host.nodeName === '#document'
2721
+ ? (_a = host.defaultView) === null || _a === void 0 ? void 0 : _a.Document
2722
+ : (_c = (_b = host.ownerDocument) === null || _b === void 0 ? void 0 : _b.defaultView) === null || _c === void 0 ? void 0 : _c.ShadowRoot;
2723
+ const originalPropertyDescriptor = (patchTarget === null || patchTarget === void 0 ? void 0 : patchTarget.prototype)
2724
+ ? Object.getOwnPropertyDescriptor(patchTarget === null || patchTarget === void 0 ? void 0 : patchTarget.prototype, 'adoptedStyleSheets')
2725
+ : undefined;
2726
+ if (hostId === null ||
2727
+ hostId === -1 ||
2728
+ !patchTarget ||
2729
+ !originalPropertyDescriptor)
2730
+ return () => {
2731
+ };
2732
+ Object.defineProperty(host, 'adoptedStyleSheets', {
2733
+ configurable: originalPropertyDescriptor.configurable,
2734
+ enumerable: originalPropertyDescriptor.enumerable,
2735
+ get() {
2736
+ var _a;
2737
+ return (_a = originalPropertyDescriptor.get) === null || _a === void 0 ? void 0 : _a.call(this);
2738
+ },
2739
+ set(sheets) {
2740
+ var _a;
2741
+ const result = (_a = originalPropertyDescriptor.set) === null || _a === void 0 ? void 0 : _a.call(this, sheets);
2742
+ if (hostId !== null && hostId !== -1) {
2743
+ try {
2744
+ stylesheetManager.adoptStyleSheets(sheets, hostId);
2745
+ }
2746
+ catch (e) {
2747
+ }
2748
+ }
2749
+ return result;
2750
+ },
2751
+ });
2752
+ return callbackWrapper(() => {
2753
+ Object.defineProperty(host, 'adoptedStyleSheets', {
2754
+ configurable: originalPropertyDescriptor.configurable,
2755
+ enumerable: originalPropertyDescriptor.enumerable,
2756
+ get: originalPropertyDescriptor.get,
2757
+ set: originalPropertyDescriptor.set,
2758
+ });
2759
+ });
2760
+ }
2761
+ function initStyleDeclarationObserver({ styleDeclarationCb, mirror, ignoreCSSAttributes, stylesheetManager, }, { win }) {
2242
2762
  const setProperty = win.CSSStyleDeclaration.prototype.setProperty;
2243
2763
  win.CSSStyleDeclaration.prototype.setProperty = new Proxy(setProperty, {
2244
2764
  apply: callbackWrapper((target, thisArg, argumentsList) => {
2245
- var _a, _b;
2765
+ var _a;
2246
2766
  const [property, value, priority] = argumentsList;
2247
- const id = mirror.getId((_b = (_a = thisArg.parentRule) === null || _a === void 0 ? void 0 : _a.parentStyleSheet) === null || _b === void 0 ? void 0 : _b.ownerNode);
2248
- if (id !== -1) {
2767
+ if (ignoreCSSAttributes.has(property)) {
2768
+ return setProperty.apply(thisArg, [property, value, priority]);
2769
+ }
2770
+ const { id, styleId } = getIdAndStyleId((_a = thisArg.parentRule) === null || _a === void 0 ? void 0 : _a.parentStyleSheet, mirror, stylesheetManager.styleMirror);
2771
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2249
2772
  styleDeclarationCb({
2250
2773
  id,
2774
+ styleId,
2251
2775
  set: {
2252
2776
  property,
2253
2777
  value,
@@ -2262,12 +2786,16 @@ function initStyleDeclarationObserver({ styleDeclarationCb, mirror }, { win }) {
2262
2786
  const removeProperty = win.CSSStyleDeclaration.prototype.removeProperty;
2263
2787
  win.CSSStyleDeclaration.prototype.removeProperty = new Proxy(removeProperty, {
2264
2788
  apply: callbackWrapper((target, thisArg, argumentsList) => {
2265
- var _a, _b;
2789
+ var _a;
2266
2790
  const [property] = argumentsList;
2267
- const id = mirror.getId((_b = (_a = thisArg.parentRule) === null || _a === void 0 ? void 0 : _a.parentStyleSheet) === null || _b === void 0 ? void 0 : _b.ownerNode);
2268
- if (id !== -1) {
2791
+ if (ignoreCSSAttributes.has(property)) {
2792
+ return removeProperty.apply(thisArg, [property]);
2793
+ }
2794
+ const { id, styleId } = getIdAndStyleId((_a = thisArg.parentRule) === null || _a === void 0 ? void 0 : _a.parentStyleSheet, mirror, stylesheetManager.styleMirror);
2795
+ if ((id && id !== -1) || (styleId && styleId !== -1)) {
2269
2796
  styleDeclarationCb({
2270
2797
  id,
2798
+ styleId,
2271
2799
  remove: {
2272
2800
  property,
2273
2801
  },
@@ -2282,27 +2810,29 @@ function initStyleDeclarationObserver({ styleDeclarationCb, mirror }, { win }) {
2282
2810
  win.CSSStyleDeclaration.prototype.removeProperty = removeProperty;
2283
2811
  });
2284
2812
  }
2285
- function initMediaInteractionObserver({ mediaInteractionCb, blockClass, blockSelector, unblockSelector, mirror, sampling, }) {
2286
- const handler = (type) => throttle$1(callbackWrapper((event) => {
2813
+ function initMediaInteractionObserver({ mediaInteractionCb, blockClass, blockSelector, unblockSelector, mirror, sampling, doc, }) {
2814
+ const handler = callbackWrapper((type) => throttle$1(callbackWrapper((event) => {
2287
2815
  const target = getEventTarget(event);
2288
2816
  if (!target ||
2289
- isBlocked(target, blockClass, blockSelector, unblockSelector)) {
2817
+ isBlocked(target, blockClass, blockSelector, unblockSelector, true)) {
2290
2818
  return;
2291
2819
  }
2292
- const { currentTime, volume, muted } = target;
2820
+ const { currentTime, volume, muted, playbackRate } = target;
2293
2821
  mediaInteractionCb({
2294
2822
  type,
2295
2823
  id: mirror.getId(target),
2296
2824
  currentTime,
2297
2825
  volume,
2298
2826
  muted,
2827
+ playbackRate,
2299
2828
  });
2300
- }), sampling.media || 500);
2829
+ }), sampling.media || 500));
2301
2830
  const handlers = [
2302
- on('play', handler(0)),
2303
- on('pause', handler(1)),
2304
- on('seeked', handler(2)),
2305
- on('volumechange', handler(3)),
2831
+ on('play', handler(0), doc),
2832
+ on('pause', handler(1), doc),
2833
+ on('seeked', handler(2), doc),
2834
+ on('volumechange', handler(3), doc),
2835
+ on('ratechange', handler(4), doc),
2306
2836
  ];
2307
2837
  return callbackWrapper(() => {
2308
2838
  handlers.forEach((h) => h());
@@ -2311,7 +2841,8 @@ function initMediaInteractionObserver({ mediaInteractionCb, blockClass, blockSel
2311
2841
  function initFontObserver({ fontCb, doc }) {
2312
2842
  const win = doc.defaultView;
2313
2843
  if (!win) {
2314
- return () => { };
2844
+ return () => {
2845
+ };
2315
2846
  }
2316
2847
  const handlers = [];
2317
2848
  const fontMap = new WeakMap();
@@ -2324,20 +2855,19 @@ function initFontObserver({ fontCb, doc }) {
2324
2855
  descriptors,
2325
2856
  fontSource: typeof source === 'string'
2326
2857
  ? source
2327
- :
2328
- JSON.stringify(Array.from(new Uint8Array(source))),
2858
+ : JSON.stringify(Array.from(new Uint8Array(source))),
2329
2859
  });
2330
2860
  return fontFace;
2331
2861
  };
2332
2862
  const restoreHandler = patch(doc.fonts, 'add', function (original) {
2333
2863
  return function (fontFace) {
2334
- setTimeout(() => {
2864
+ setTimeout(callbackWrapper(() => {
2335
2865
  const p = fontMap.get(fontFace);
2336
2866
  if (p) {
2337
2867
  fontCb(p);
2338
2868
  fontMap.delete(fontFace);
2339
2869
  }
2340
- }, 0);
2870
+ }), 0);
2341
2871
  return original.apply(this, [fontFace]);
2342
2872
  };
2343
2873
  });
@@ -2349,8 +2879,59 @@ function initFontObserver({ fontCb, doc }) {
2349
2879
  handlers.forEach((h) => h());
2350
2880
  });
2351
2881
  }
2882
+ function initSelectionObserver(param) {
2883
+ const { doc, mirror, blockClass, blockSelector, unblockSelector, selectionCb, } = param;
2884
+ let collapsed = true;
2885
+ const updateSelection = callbackWrapper(() => {
2886
+ const selection = doc.getSelection();
2887
+ if (!selection || (collapsed && (selection === null || selection === void 0 ? void 0 : selection.isCollapsed)))
2888
+ return;
2889
+ collapsed = selection.isCollapsed || false;
2890
+ const ranges = [];
2891
+ const count = selection.rangeCount || 0;
2892
+ for (let i = 0; i < count; i++) {
2893
+ const range = selection.getRangeAt(i);
2894
+ const { startContainer, startOffset, endContainer, endOffset } = range;
2895
+ const blocked = isBlocked(startContainer, blockClass, blockSelector, unblockSelector, true) ||
2896
+ isBlocked(endContainer, blockClass, blockSelector, unblockSelector, true);
2897
+ if (blocked)
2898
+ continue;
2899
+ ranges.push({
2900
+ start: mirror.getId(startContainer),
2901
+ startOffset,
2902
+ end: mirror.getId(endContainer),
2903
+ endOffset,
2904
+ });
2905
+ }
2906
+ selectionCb({ ranges });
2907
+ });
2908
+ updateSelection();
2909
+ return on('selectionchange', updateSelection);
2910
+ }
2911
+ function initCustomElementObserver({ doc, customElementCb, }) {
2912
+ const win = doc.defaultView;
2913
+ if (!win || !win.customElements) {
2914
+ return () => {
2915
+ };
2916
+ }
2917
+ const restoreHandler = patch(win.customElements, 'define', function (original) {
2918
+ return function (name, constructor, options) {
2919
+ try {
2920
+ customElementCb({
2921
+ define: {
2922
+ name,
2923
+ },
2924
+ });
2925
+ }
2926
+ catch (e) {
2927
+ }
2928
+ return original.apply(this, [name, constructor, options]);
2929
+ };
2930
+ });
2931
+ return restoreHandler;
2932
+ }
2352
2933
  function mergeHooks(o, hooks) {
2353
- const { mutationCb, mousemoveCb, mouseInteractionCb, scrollCb, viewportResizeCb, inputCb, mediaInteractionCb, styleSheetRuleCb, styleDeclarationCb, canvasMutationCb, fontCb, } = o;
2934
+ const { mutationCb, mousemoveCb, mouseInteractionCb, scrollCb, viewportResizeCb, inputCb, mediaInteractionCb, styleSheetRuleCb, styleDeclarationCb, canvasMutationCb, fontCb, selectionCb, customElementCb, } = o;
2354
2935
  o.mutationCb = (...p) => {
2355
2936
  if (hooks.mutation) {
2356
2937
  hooks.mutation(...p);
@@ -2417,25 +2998,46 @@ function mergeHooks(o, hooks) {
2417
2998
  }
2418
2999
  fontCb(...p);
2419
3000
  };
3001
+ o.selectionCb = (...p) => {
3002
+ if (hooks.selection) {
3003
+ hooks.selection(...p);
3004
+ }
3005
+ selectionCb(...p);
3006
+ };
3007
+ o.customElementCb = (...c) => {
3008
+ if (hooks.customElement) {
3009
+ hooks.customElement(...c);
3010
+ }
3011
+ customElementCb(...c);
3012
+ };
2420
3013
  }
2421
3014
  function initObservers(o, hooks = {}) {
2422
3015
  const currentWindow = o.doc.defaultView;
2423
3016
  if (!currentWindow) {
2424
- return () => { };
3017
+ return () => {
3018
+ };
2425
3019
  }
2426
3020
  mergeHooks(o, hooks);
2427
3021
  const mutationObserver = initMutationObserver(o, o.doc);
2428
3022
  const mousemoveHandler = initMoveObserver(o);
2429
3023
  const mouseInteractionHandler = initMouseInteractionObserver(o);
2430
3024
  const scrollHandler = initScrollObserver(o);
2431
- const viewportResizeHandler = initViewportResizeObserver(o);
3025
+ const viewportResizeHandler = initViewportResizeObserver(o, {
3026
+ win: currentWindow,
3027
+ });
2432
3028
  const inputHandler = initInputObserver(o);
2433
3029
  const mediaInteractionHandler = initMediaInteractionObserver(o);
2434
3030
  const styleSheetObserver = initStyleSheetObserver(o, { win: currentWindow });
3031
+ const adoptedStyleSheetObserver = initAdoptedStyleSheetObserver(o, o.doc);
2435
3032
  const styleDeclarationObserver = initStyleDeclarationObserver(o, {
2436
3033
  win: currentWindow,
2437
3034
  });
2438
- const fontObserver = o.collectFonts ? initFontObserver(o) : () => { };
3035
+ const fontObserver = o.collectFonts
3036
+ ? initFontObserver(o)
3037
+ : () => {
3038
+ };
3039
+ const selectionObserver = initSelectionObserver(o);
3040
+ const customElementObserver = initCustomElementObserver(o);
2439
3041
  const pluginHandlers = [];
2440
3042
  for (const plugin of o.plugins) {
2441
3043
  pluginHandlers.push(plugin.observer(plugin.callback, currentWindow, plugin.options));
@@ -2449,13 +3051,12 @@ function initObservers(o, hooks = {}) {
2449
3051
  viewportResizeHandler();
2450
3052
  inputHandler();
2451
3053
  mediaInteractionHandler();
2452
- try {
2453
- styleSheetObserver();
2454
- styleDeclarationObserver();
2455
- }
2456
- catch (e) {
2457
- }
3054
+ styleSheetObserver();
3055
+ adoptedStyleSheetObserver();
3056
+ styleDeclarationObserver();
2458
3057
  fontObserver();
3058
+ selectionObserver();
3059
+ customElementObserver();
2459
3060
  pluginHandlers.forEach((h) => h());
2460
3061
  });
2461
3062
  }
@@ -2469,13 +3070,88 @@ function canMonkeyPatchNestedCSSRule(prop) {
2469
3070
  'deleteRule' in window[prop].prototype);
2470
3071
  }
2471
3072
 
3073
+ class CrossOriginIframeMirror {
3074
+ constructor(generateIdFn) {
3075
+ this.generateIdFn = generateIdFn;
3076
+ this.iframeIdToRemoteIdMap = new WeakMap();
3077
+ this.iframeRemoteIdToIdMap = new WeakMap();
3078
+ }
3079
+ getId(iframe, remoteId, idToRemoteMap, remoteToIdMap) {
3080
+ const idToRemoteIdMap = idToRemoteMap || this.getIdToRemoteIdMap(iframe);
3081
+ const remoteIdToIdMap = remoteToIdMap || this.getRemoteIdToIdMap(iframe);
3082
+ let id = idToRemoteIdMap.get(remoteId);
3083
+ if (!id) {
3084
+ id = this.generateIdFn();
3085
+ idToRemoteIdMap.set(remoteId, id);
3086
+ remoteIdToIdMap.set(id, remoteId);
3087
+ }
3088
+ return id;
3089
+ }
3090
+ getIds(iframe, remoteId) {
3091
+ const idToRemoteIdMap = this.getIdToRemoteIdMap(iframe);
3092
+ const remoteIdToIdMap = this.getRemoteIdToIdMap(iframe);
3093
+ return remoteId.map((id) => this.getId(iframe, id, idToRemoteIdMap, remoteIdToIdMap));
3094
+ }
3095
+ getRemoteId(iframe, id, map) {
3096
+ const remoteIdToIdMap = map || this.getRemoteIdToIdMap(iframe);
3097
+ if (typeof id !== 'number')
3098
+ return id;
3099
+ const remoteId = remoteIdToIdMap.get(id);
3100
+ if (!remoteId)
3101
+ return -1;
3102
+ return remoteId;
3103
+ }
3104
+ getRemoteIds(iframe, ids) {
3105
+ const remoteIdToIdMap = this.getRemoteIdToIdMap(iframe);
3106
+ return ids.map((id) => this.getRemoteId(iframe, id, remoteIdToIdMap));
3107
+ }
3108
+ reset(iframe) {
3109
+ if (!iframe) {
3110
+ this.iframeIdToRemoteIdMap = new WeakMap();
3111
+ this.iframeRemoteIdToIdMap = new WeakMap();
3112
+ return;
3113
+ }
3114
+ this.iframeIdToRemoteIdMap.delete(iframe);
3115
+ this.iframeRemoteIdToIdMap.delete(iframe);
3116
+ }
3117
+ getIdToRemoteIdMap(iframe) {
3118
+ let idToRemoteIdMap = this.iframeIdToRemoteIdMap.get(iframe);
3119
+ if (!idToRemoteIdMap) {
3120
+ idToRemoteIdMap = new Map();
3121
+ this.iframeIdToRemoteIdMap.set(iframe, idToRemoteIdMap);
3122
+ }
3123
+ return idToRemoteIdMap;
3124
+ }
3125
+ getRemoteIdToIdMap(iframe) {
3126
+ let remoteIdToIdMap = this.iframeRemoteIdToIdMap.get(iframe);
3127
+ if (!remoteIdToIdMap) {
3128
+ remoteIdToIdMap = new Map();
3129
+ this.iframeRemoteIdToIdMap.set(iframe, remoteIdToIdMap);
3130
+ }
3131
+ return remoteIdToIdMap;
3132
+ }
3133
+ }
3134
+
2472
3135
  class IframeManager {
2473
3136
  constructor(options) {
2474
3137
  this.iframes = new WeakMap();
3138
+ this.crossOriginIframeMap = new WeakMap();
3139
+ this.crossOriginIframeMirror = new CrossOriginIframeMirror(genId);
3140
+ this.crossOriginIframeRootIdMap = new WeakMap();
2475
3141
  this.mutationCb = options.mutationCb;
3142
+ this.wrappedEmit = options.wrappedEmit;
3143
+ this.stylesheetManager = options.stylesheetManager;
3144
+ this.recordCrossOriginIframes = options.recordCrossOriginIframes;
3145
+ this.crossOriginIframeStyleMirror = new CrossOriginIframeMirror(this.stylesheetManager.styleMirror.generateId.bind(this.stylesheetManager.styleMirror));
3146
+ this.mirror = options.mirror;
3147
+ if (this.recordCrossOriginIframes) {
3148
+ window.addEventListener('message', this.handleMessage.bind(this));
3149
+ }
2476
3150
  }
2477
3151
  addIframe(iframeEl) {
2478
3152
  this.iframes.set(iframeEl, true);
3153
+ if (iframeEl.contentWindow)
3154
+ this.crossOriginIframeMap.set(iframeEl.contentWindow, iframeEl);
2479
3155
  }
2480
3156
  addLoadListener(cb) {
2481
3157
  this.loadListener = cb;
@@ -2485,7 +3161,7 @@ class IframeManager {
2485
3161
  this.mutationCb({
2486
3162
  adds: [
2487
3163
  {
2488
- parentId: iframeEl.__sn.id,
3164
+ parentId: this.mirror.getId(iframeEl),
2489
3165
  nextId: null,
2490
3166
  node: childSn,
2491
3167
  },
@@ -2496,154 +3172,278 @@ class IframeManager {
2496
3172
  isAttachIframe: true,
2497
3173
  });
2498
3174
  (_a = this.loadListener) === null || _a === void 0 ? void 0 : _a.call(this, iframeEl);
3175
+ if (iframeEl.contentDocument &&
3176
+ iframeEl.contentDocument.adoptedStyleSheets &&
3177
+ iframeEl.contentDocument.adoptedStyleSheets.length > 0)
3178
+ this.stylesheetManager.adoptStyleSheets(iframeEl.contentDocument.adoptedStyleSheets, this.mirror.getId(iframeEl.contentDocument));
3179
+ }
3180
+ handleMessage(message) {
3181
+ const crossOriginMessageEvent = message;
3182
+ if (crossOriginMessageEvent.data.type !== 'rrweb' ||
3183
+ crossOriginMessageEvent.origin !== crossOriginMessageEvent.data.origin)
3184
+ return;
3185
+ const iframeSourceWindow = message.source;
3186
+ if (!iframeSourceWindow)
3187
+ return;
3188
+ const iframeEl = this.crossOriginIframeMap.get(message.source);
3189
+ if (!iframeEl)
3190
+ return;
3191
+ const transformedEvent = this.transformCrossOriginEvent(iframeEl, crossOriginMessageEvent.data.event);
3192
+ if (transformedEvent)
3193
+ this.wrappedEmit(transformedEvent, crossOriginMessageEvent.data.isCheckout);
3194
+ }
3195
+ transformCrossOriginEvent(iframeEl, e) {
3196
+ var _a;
3197
+ switch (e.type) {
3198
+ case EventType.FullSnapshot: {
3199
+ this.crossOriginIframeMirror.reset(iframeEl);
3200
+ this.crossOriginIframeStyleMirror.reset(iframeEl);
3201
+ this.replaceIdOnNode(e.data.node, iframeEl);
3202
+ const rootId = e.data.node.id;
3203
+ this.crossOriginIframeRootIdMap.set(iframeEl, rootId);
3204
+ this.patchRootIdOnNode(e.data.node, rootId);
3205
+ return {
3206
+ timestamp: e.timestamp,
3207
+ type: EventType.IncrementalSnapshot,
3208
+ data: {
3209
+ source: IncrementalSource.Mutation,
3210
+ adds: [
3211
+ {
3212
+ parentId: this.mirror.getId(iframeEl),
3213
+ nextId: null,
3214
+ node: e.data.node,
3215
+ },
3216
+ ],
3217
+ removes: [],
3218
+ texts: [],
3219
+ attributes: [],
3220
+ isAttachIframe: true,
3221
+ },
3222
+ };
3223
+ }
3224
+ case EventType.Meta:
3225
+ case EventType.Load:
3226
+ case EventType.DomContentLoaded: {
3227
+ return false;
3228
+ }
3229
+ case EventType.Plugin: {
3230
+ return e;
3231
+ }
3232
+ case EventType.Custom: {
3233
+ this.replaceIds(e.data.payload, iframeEl, ['id', 'parentId', 'previousId', 'nextId']);
3234
+ return e;
3235
+ }
3236
+ case EventType.IncrementalSnapshot: {
3237
+ switch (e.data.source) {
3238
+ case IncrementalSource.Mutation: {
3239
+ e.data.adds.forEach((n) => {
3240
+ this.replaceIds(n, iframeEl, [
3241
+ 'parentId',
3242
+ 'nextId',
3243
+ 'previousId',
3244
+ ]);
3245
+ this.replaceIdOnNode(n.node, iframeEl);
3246
+ const rootId = this.crossOriginIframeRootIdMap.get(iframeEl);
3247
+ rootId && this.patchRootIdOnNode(n.node, rootId);
3248
+ });
3249
+ e.data.removes.forEach((n) => {
3250
+ this.replaceIds(n, iframeEl, ['parentId', 'id']);
3251
+ });
3252
+ e.data.attributes.forEach((n) => {
3253
+ this.replaceIds(n, iframeEl, ['id']);
3254
+ });
3255
+ e.data.texts.forEach((n) => {
3256
+ this.replaceIds(n, iframeEl, ['id']);
3257
+ });
3258
+ return e;
3259
+ }
3260
+ case IncrementalSource.Drag:
3261
+ case IncrementalSource.TouchMove:
3262
+ case IncrementalSource.MouseMove: {
3263
+ e.data.positions.forEach((p) => {
3264
+ this.replaceIds(p, iframeEl, ['id']);
3265
+ });
3266
+ return e;
3267
+ }
3268
+ case IncrementalSource.ViewportResize: {
3269
+ return false;
3270
+ }
3271
+ case IncrementalSource.MediaInteraction:
3272
+ case IncrementalSource.MouseInteraction:
3273
+ case IncrementalSource.Scroll:
3274
+ case IncrementalSource.CanvasMutation:
3275
+ case IncrementalSource.Input: {
3276
+ this.replaceIds(e.data, iframeEl, ['id']);
3277
+ return e;
3278
+ }
3279
+ case IncrementalSource.StyleSheetRule:
3280
+ case IncrementalSource.StyleDeclaration: {
3281
+ this.replaceIds(e.data, iframeEl, ['id']);
3282
+ this.replaceStyleIds(e.data, iframeEl, ['styleId']);
3283
+ return e;
3284
+ }
3285
+ case IncrementalSource.Font: {
3286
+ return e;
3287
+ }
3288
+ case IncrementalSource.Selection: {
3289
+ e.data.ranges.forEach((range) => {
3290
+ this.replaceIds(range, iframeEl, ['start', 'end']);
3291
+ });
3292
+ return e;
3293
+ }
3294
+ case IncrementalSource.AdoptedStyleSheet: {
3295
+ this.replaceIds(e.data, iframeEl, ['id']);
3296
+ this.replaceStyleIds(e.data, iframeEl, ['styleIds']);
3297
+ (_a = e.data.styles) === null || _a === void 0 ? void 0 : _a.forEach((style) => {
3298
+ this.replaceStyleIds(style, iframeEl, ['styleId']);
3299
+ });
3300
+ return e;
3301
+ }
3302
+ }
3303
+ }
3304
+ }
3305
+ return false;
3306
+ }
3307
+ replace(iframeMirror, obj, iframeEl, keys) {
3308
+ for (const key of keys) {
3309
+ if (!Array.isArray(obj[key]) && typeof obj[key] !== 'number')
3310
+ continue;
3311
+ if (Array.isArray(obj[key])) {
3312
+ obj[key] = iframeMirror.getIds(iframeEl, obj[key]);
3313
+ }
3314
+ else {
3315
+ obj[key] = iframeMirror.getId(iframeEl, obj[key]);
3316
+ }
3317
+ }
3318
+ return obj;
3319
+ }
3320
+ replaceIds(obj, iframeEl, keys) {
3321
+ return this.replace(this.crossOriginIframeMirror, obj, iframeEl, keys);
3322
+ }
3323
+ replaceStyleIds(obj, iframeEl, keys) {
3324
+ return this.replace(this.crossOriginIframeStyleMirror, obj, iframeEl, keys);
3325
+ }
3326
+ replaceIdOnNode(node, iframeEl) {
3327
+ this.replaceIds(node, iframeEl, ['id', 'rootId']);
3328
+ if ('childNodes' in node) {
3329
+ node.childNodes.forEach((child) => {
3330
+ this.replaceIdOnNode(child, iframeEl);
3331
+ });
3332
+ }
3333
+ }
3334
+ patchRootIdOnNode(node, rootId) {
3335
+ if (node.type !== NodeType$1.Document && !node.rootId)
3336
+ node.rootId = rootId;
3337
+ if ('childNodes' in node) {
3338
+ node.childNodes.forEach((child) => {
3339
+ this.patchRootIdOnNode(child, rootId);
3340
+ });
3341
+ }
2499
3342
  }
2500
3343
  }
2501
3344
 
2502
3345
  class ShadowDomManager {
2503
3346
  constructor(options) {
2504
- this.restorePatches = [];
3347
+ this.shadowDoms = new WeakSet();
3348
+ this.restoreHandlers = [];
2505
3349
  this.mutationCb = options.mutationCb;
2506
3350
  this.scrollCb = options.scrollCb;
2507
3351
  this.bypassOptions = options.bypassOptions;
2508
3352
  this.mirror = options.mirror;
2509
- const manager = this;
2510
- this.restorePatches.push(patch(HTMLElement.prototype, 'attachShadow', function (original) {
2511
- return function () {
2512
- const shadowRoot = original.apply(this, arguments);
2513
- if (this.shadowRoot)
2514
- manager.addShadowRoot(this.shadowRoot, this.ownerDocument);
2515
- return shadowRoot;
2516
- };
2517
- }));
3353
+ this.init();
3354
+ }
3355
+ init() {
3356
+ this.reset();
3357
+ this.patchAttachShadow(Element, document);
2518
3358
  }
2519
3359
  addShadowRoot(shadowRoot, doc) {
2520
- initMutationObserver(Object.assign(Object.assign({}, this.bypassOptions), { doc, mutationCb: this.mutationCb, mirror: this.mirror, shadowDomManager: this }), shadowRoot);
2521
- initScrollObserver(Object.assign(Object.assign({}, this.bypassOptions), { scrollCb: this.scrollCb, doc: shadowRoot, mirror: this.mirror }));
3360
+ if (!isNativeShadowDom(shadowRoot))
3361
+ return;
3362
+ if (this.shadowDoms.has(shadowRoot))
3363
+ return;
3364
+ this.shadowDoms.add(shadowRoot);
3365
+ const observer = initMutationObserver(Object.assign(Object.assign({}, this.bypassOptions), { doc, mutationCb: this.mutationCb, mirror: this.mirror, shadowDomManager: this }), shadowRoot);
3366
+ this.restoreHandlers.push(() => observer.disconnect());
3367
+ this.restoreHandlers.push(initScrollObserver(Object.assign(Object.assign({}, this.bypassOptions), { scrollCb: this.scrollCb, doc: shadowRoot, mirror: this.mirror })));
3368
+ setTimeout(() => {
3369
+ if (shadowRoot.adoptedStyleSheets &&
3370
+ shadowRoot.adoptedStyleSheets.length > 0)
3371
+ this.bypassOptions.stylesheetManager.adoptStyleSheets(shadowRoot.adoptedStyleSheets, this.mirror.getId(shadowRoot.host));
3372
+ this.restoreHandlers.push(initAdoptedStyleSheetObserver({
3373
+ mirror: this.mirror,
3374
+ stylesheetManager: this.bypassOptions.stylesheetManager,
3375
+ }, shadowRoot));
3376
+ }, 0);
2522
3377
  }
2523
3378
  observeAttachShadow(iframeElement) {
2524
- if (iframeElement.contentWindow) {
2525
- const manager = this;
2526
- this.restorePatches.push(patch(iframeElement.contentWindow.HTMLElement.prototype, 'attachShadow', function (original) {
2527
- return function () {
2528
- const shadowRoot = original.apply(this, arguments);
2529
- if (this.shadowRoot)
2530
- manager.addShadowRoot(this.shadowRoot, iframeElement.contentDocument);
2531
- return shadowRoot;
2532
- };
2533
- }));
2534
- }
3379
+ if (!iframeElement.contentWindow || !iframeElement.contentDocument)
3380
+ return;
3381
+ this.patchAttachShadow(iframeElement.contentWindow.Element, iframeElement.contentDocument);
3382
+ }
3383
+ patchAttachShadow(element, doc) {
3384
+ const manager = this;
3385
+ this.restoreHandlers.push(patch(element.prototype, 'attachShadow', function (original) {
3386
+ return function (option) {
3387
+ const shadowRoot = original.call(this, option);
3388
+ if (this.shadowRoot && inDom(this))
3389
+ manager.addShadowRoot(this.shadowRoot, doc);
3390
+ return shadowRoot;
3391
+ };
3392
+ }));
2535
3393
  }
2536
3394
  reset() {
2537
- this.restorePatches.forEach((restorePatch) => restorePatch());
3395
+ this.restoreHandlers.forEach((handler) => {
3396
+ try {
3397
+ handler();
3398
+ }
3399
+ catch (e) {
3400
+ }
3401
+ });
3402
+ this.restoreHandlers = [];
3403
+ this.shadowDoms = new WeakSet();
2538
3404
  }
2539
3405
  }
2540
3406
 
2541
- /******************************************************************************
3407
+ /*! *****************************************************************************
2542
3408
  Copyright (c) Microsoft Corporation.
2543
3409
 
2544
3410
  Permission to use, copy, modify, and/or distribute this software for any
2545
3411
  purpose with or without fee is hereby granted.
2546
-
2547
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
2548
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
2549
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
2550
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
2551
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
2552
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
2553
- PERFORMANCE OF THIS SOFTWARE.
2554
- ***************************************************************************** */
2555
-
2556
- function __rest(s, e) {
2557
- var t = {};
2558
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
2559
- t[p] = s[p];
2560
- if (s != null && typeof Object.getOwnPropertySymbols === "function")
2561
- for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
2562
- if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
2563
- t[p[i]] = s[p[i]];
2564
- }
2565
- return t;
2566
- }
2567
-
2568
- function initCanvas2DMutationObserver(cb, win, blockClass, unblockSelector, blockSelector, mirror) {
2569
- const handlers = [];
2570
- const props2D = Object.getOwnPropertyNames(win.CanvasRenderingContext2D.prototype);
2571
- for (const prop of props2D) {
2572
- try {
2573
- if (typeof win.CanvasRenderingContext2D.prototype[prop] !== 'function') {
2574
- continue;
2575
- }
2576
- const restoreHandler = patch(win.CanvasRenderingContext2D.prototype, prop, function (original) {
2577
- return function (...args) {
2578
- if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector)) {
2579
- setTimeout(() => {
2580
- const recordArgs = [...args];
2581
- if (prop === 'drawImage') {
2582
- if (recordArgs[0] &&
2583
- recordArgs[0] instanceof HTMLCanvasElement) {
2584
- const canvas = recordArgs[0];
2585
- const ctx = canvas.getContext('2d');
2586
- let imgd = ctx === null || ctx === void 0 ? void 0 : ctx.getImageData(0, 0, canvas.width, canvas.height);
2587
- let pix = imgd === null || imgd === void 0 ? void 0 : imgd.data;
2588
- recordArgs[0] = JSON.stringify(pix);
2589
- }
2590
- }
2591
- cb(this.canvas, {
2592
- type: CanvasContext['2D'],
2593
- property: prop,
2594
- args: recordArgs,
2595
- });
2596
- }, 0);
2597
- }
2598
- return original.apply(this, args);
2599
- };
2600
- });
2601
- handlers.push(restoreHandler);
2602
- }
2603
- catch (_a) {
2604
- const hookHandler = hookSetter(win.CanvasRenderingContext2D.prototype, prop, {
2605
- set(v) {
2606
- cb(this.canvas, {
2607
- type: CanvasContext['2D'],
2608
- property: prop,
2609
- args: [v],
2610
- setter: true,
2611
- });
2612
- },
2613
- });
2614
- handlers.push(hookHandler);
3412
+
3413
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
3414
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
3415
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
3416
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
3417
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
3418
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
3419
+ PERFORMANCE OF THIS SOFTWARE.
3420
+ ***************************************************************************** */
3421
+
3422
+ function __rest(s, e) {
3423
+ var t = {};
3424
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
3425
+ t[p] = s[p];
3426
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
3427
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
3428
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
3429
+ t[p[i]] = s[p[i]];
2615
3430
  }
2616
- }
2617
- return () => {
2618
- handlers.forEach((h) => h());
2619
- };
3431
+ return t;
2620
3432
  }
2621
3433
 
2622
- function initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector) {
2623
- const handlers = [];
2624
- try {
2625
- const restoreHandler = patch(win.HTMLCanvasElement.prototype, 'getContext', function (original) {
2626
- return function (contextType, ...args) {
2627
- if (!isBlocked(this, blockClass, blockSelector, unblockSelector)) {
2628
- if (!('__context' in this))
2629
- this.__context = contextType;
2630
- }
2631
- return original.apply(this, [contextType, ...args]);
2632
- };
2633
- });
2634
- handlers.push(restoreHandler);
2635
- }
2636
- catch (_a) {
2637
- console.error('failed to patch HTMLCanvasElement.prototype.getContext');
2638
- }
2639
- return () => {
2640
- handlers.forEach((h) => h());
2641
- };
3434
+ function __awaiter(thisArg, _arguments, P, generator) {
3435
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3436
+ return new (P || (P = Promise))(function (resolve, reject) {
3437
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
3438
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
3439
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
3440
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
3441
+ });
2642
3442
  }
2643
3443
 
2644
3444
  /*
2645
- * base64-arraybuffer 1.0.2 <https://github.com/niklasvh/base64-arraybuffer>
2646
- * Copyright (c) 2022 Niklas von Hertzen <https://hertzen.com>
3445
+ * base64-arraybuffer 1.0.1 <https://github.com/niklasvh/base64-arraybuffer>
3446
+ * Copyright (c) 2021 Niklas von Hertzen <https://hertzen.com>
2647
3447
  * Released under MIT License
2648
3448
  */
2649
3449
  var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
@@ -2669,12 +3469,12 @@ var encode = function (arraybuffer) {
2669
3469
  return base64;
2670
3470
  };
2671
3471
 
2672
- const webGLVarMap = new Map();
3472
+ const canvasVarMap = new Map();
2673
3473
  function variableListFor(ctx, ctor) {
2674
- let contextMap = webGLVarMap.get(ctx);
3474
+ let contextMap = canvasVarMap.get(ctx);
2675
3475
  if (!contextMap) {
2676
3476
  contextMap = new Map();
2677
- webGLVarMap.set(ctx, contextMap);
3477
+ canvasVarMap.set(ctx, contextMap);
2678
3478
  }
2679
3479
  if (!contextMap.has(ctor)) {
2680
3480
  contextMap.set(ctor, []);
@@ -2743,6 +3543,14 @@ function serializeArg(value, win, ctx) {
2743
3543
  src,
2744
3544
  };
2745
3545
  }
3546
+ else if (value instanceof HTMLCanvasElement) {
3547
+ const name = 'HTMLImageElement';
3548
+ const src = value.toDataURL();
3549
+ return {
3550
+ rr_type: name,
3551
+ src,
3552
+ };
3553
+ }
2746
3554
  else if (value instanceof ImageData) {
2747
3555
  const name = value.constructor.name;
2748
3556
  return {
@@ -2781,10 +3589,102 @@ const isInstanceOfWebGLObject = (value, win) => {
2781
3589
  return Boolean(supportedWebGLConstructorNames.find((name) => value instanceof win[name]));
2782
3590
  };
2783
3591
 
2784
- function patchGLPrototype(prototype, type, cb, blockClass, unblockSelector, blockSelector, mirror, win) {
3592
+ function initCanvas2DMutationObserver(cb, win, blockClass, blockSelector, unblockSelector) {
3593
+ const handlers = [];
3594
+ const props2D = Object.getOwnPropertyNames(win.CanvasRenderingContext2D.prototype);
3595
+ for (const prop of props2D) {
3596
+ try {
3597
+ if (typeof win.CanvasRenderingContext2D.prototype[prop] !== 'function') {
3598
+ continue;
3599
+ }
3600
+ const restoreHandler = patch(win.CanvasRenderingContext2D.prototype, prop, function (original) {
3601
+ return function (...args) {
3602
+ if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector, true)) {
3603
+ setTimeout(() => {
3604
+ const recordArgs = serializeArgs([...args], win, this);
3605
+ cb(this.canvas, {
3606
+ type: CanvasContext['2D'],
3607
+ property: prop,
3608
+ args: recordArgs,
3609
+ });
3610
+ }, 0);
3611
+ }
3612
+ return original.apply(this, args);
3613
+ };
3614
+ });
3615
+ handlers.push(restoreHandler);
3616
+ }
3617
+ catch (_a) {
3618
+ const hookHandler = hookSetter(win.CanvasRenderingContext2D.prototype, prop, {
3619
+ set(v) {
3620
+ cb(this.canvas, {
3621
+ type: CanvasContext['2D'],
3622
+ property: prop,
3623
+ args: [v],
3624
+ setter: true,
3625
+ });
3626
+ },
3627
+ });
3628
+ handlers.push(hookHandler);
3629
+ }
3630
+ }
3631
+ return () => {
3632
+ handlers.forEach((h) => h());
3633
+ };
3634
+ }
3635
+
3636
+ function getNormalizedContextName(contextType) {
3637
+ return contextType === 'experimental-webgl' ? 'webgl' : contextType;
3638
+ }
3639
+ function initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector, setPreserveDrawingBufferToTrue) {
3640
+ const handlers = [];
3641
+ try {
3642
+ const restoreHandler = patch(win.HTMLCanvasElement.prototype, 'getContext', function (original) {
3643
+ return function (contextType, ...args) {
3644
+ if (!isBlocked(this, blockClass, blockSelector, unblockSelector, true)) {
3645
+ const ctxName = getNormalizedContextName(contextType);
3646
+ if (!('__context' in this))
3647
+ this.__context = ctxName;
3648
+ if (setPreserveDrawingBufferToTrue &&
3649
+ ['webgl', 'webgl2'].includes(ctxName)) {
3650
+ if (args[0] && typeof args[0] === 'object') {
3651
+ const contextAttributes = args[0];
3652
+ if (!contextAttributes.preserveDrawingBuffer) {
3653
+ contextAttributes.preserveDrawingBuffer = true;
3654
+ }
3655
+ }
3656
+ else {
3657
+ args.splice(0, 1, {
3658
+ preserveDrawingBuffer: true,
3659
+ });
3660
+ }
3661
+ }
3662
+ }
3663
+ return original.apply(this, [contextType, ...args]);
3664
+ };
3665
+ });
3666
+ handlers.push(restoreHandler);
3667
+ }
3668
+ catch (_a) {
3669
+ console.error('failed to patch HTMLCanvasElement.prototype.getContext');
3670
+ }
3671
+ return () => {
3672
+ handlers.forEach((h) => h());
3673
+ };
3674
+ }
3675
+
3676
+ function patchGLPrototype(prototype, type, cb, blockClass, blockSelector, unblockSelector, mirror, win) {
2785
3677
  const handlers = [];
2786
3678
  const props = Object.getOwnPropertyNames(prototype);
2787
3679
  for (const prop of props) {
3680
+ if ([
3681
+ 'isContextLost',
3682
+ 'canvas',
3683
+ 'drawingBufferWidth',
3684
+ 'drawingBufferHeight',
3685
+ ].includes(prop)) {
3686
+ continue;
3687
+ }
2788
3688
  try {
2789
3689
  if (typeof prototype[prop] !== 'function') {
2790
3690
  continue;
@@ -2792,10 +3692,10 @@ function patchGLPrototype(prototype, type, cb, blockClass, unblockSelector, bloc
2792
3692
  const restoreHandler = patch(prototype, prop, function (original) {
2793
3693
  return function (...args) {
2794
3694
  const result = original.apply(this, args);
2795
- saveWebGLVar(result, win, prototype);
2796
- if (!isBlocked(this.canvas, blockClass, blockSelector, unblockSelector)) {
2797
- const id = mirror.getId(this.canvas);
2798
- const recordArgs = serializeArgs([...args], win, prototype);
3695
+ saveWebGLVar(result, win, this);
3696
+ if ('tagName' in this.canvas &&
3697
+ !isBlocked(this.canvas, blockClass, blockSelector, unblockSelector, true)) {
3698
+ const recordArgs = serializeArgs([...args], win, this);
2799
3699
  const mutation = {
2800
3700
  type,
2801
3701
  property: prop,
@@ -2835,6 +3735,38 @@ function initCanvasWebGLMutationObserver(cb, win, blockClass, blockSelector, unb
2835
3735
  };
2836
3736
  }
2837
3737
 
3738
+ function decodeBase64(base64, enableUnicode) {
3739
+ var binaryString = atob(base64);
3740
+ if (enableUnicode) {
3741
+ var binaryView = new Uint8Array(binaryString.length);
3742
+ for (var i = 0, n = binaryString.length; i < n; ++i) {
3743
+ binaryView[i] = binaryString.charCodeAt(i);
3744
+ }
3745
+ return String.fromCharCode.apply(null, new Uint16Array(binaryView.buffer));
3746
+ }
3747
+ return binaryString;
3748
+ }
3749
+
3750
+ function createURL(base64, sourcemapArg, enableUnicodeArg) {
3751
+ var sourcemap = sourcemapArg === undefined ? null : sourcemapArg;
3752
+ var enableUnicode = enableUnicodeArg === undefined ? false : enableUnicodeArg;
3753
+ var source = decodeBase64(base64, enableUnicode);
3754
+ var start = source.indexOf('\n', 10) + 1;
3755
+ var body = source.substring(start) + (sourcemap ? '\/\/# sourceMappingURL=' + sourcemap : '');
3756
+ var blob = new Blob([body], { type: 'application/javascript' });
3757
+ return URL.createObjectURL(blob);
3758
+ }
3759
+
3760
+ function createBase64WorkerFactory(base64, sourcemapArg, enableUnicodeArg) {
3761
+ var url;
3762
+ return function WorkerFactory(options) {
3763
+ url = url || createURL(base64, sourcemapArg, enableUnicodeArg);
3764
+ return new Worker(url, options);
3765
+ };
3766
+ }
3767
+
3768
+ var WorkerFactory = createBase64WorkerFactory('Lyogcm9sbHVwLXBsdWdpbi13ZWItd29ya2VyLWxvYWRlciAqLwooZnVuY3Rpb24gKCkgewogICAgJ3VzZSBzdHJpY3QnOwoKICAgIC8qISAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKg0KICAgIENvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLg0KDQogICAgUGVybWlzc2lvbiB0byB1c2UsIGNvcHksIG1vZGlmeSwgYW5kL29yIGRpc3RyaWJ1dGUgdGhpcyBzb2Z0d2FyZSBmb3IgYW55DQogICAgcHVycG9zZSB3aXRoIG9yIHdpdGhvdXQgZmVlIGlzIGhlcmVieSBncmFudGVkLg0KDQogICAgVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEICJBUyBJUyIgQU5EIFRIRSBBVVRIT1IgRElTQ0xBSU1TIEFMTCBXQVJSQU5USUVTIFdJVEgNCiAgICBSRUdBUkQgVE8gVEhJUyBTT0ZUV0FSRSBJTkNMVURJTkcgQUxMIElNUExJRUQgV0FSUkFOVElFUyBPRiBNRVJDSEFOVEFCSUxJVFkNCiAgICBBTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsDQogICAgSU5ESVJFQ1QsIE9SIENPTlNFUVVFTlRJQUwgREFNQUdFUyBPUiBBTlkgREFNQUdFUyBXSEFUU09FVkVSIFJFU1VMVElORyBGUk9NDQogICAgTE9TUyBPRiBVU0UsIERBVEEgT1IgUFJPRklUUywgV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIE5FR0xJR0VOQ0UgT1INCiAgICBPVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SDQogICAgUEVSRk9STUFOQ0UgT0YgVEhJUyBTT0ZUV0FSRS4NCiAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiAqLw0KDQogICAgZnVuY3Rpb24gX19hd2FpdGVyKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikgew0KICAgICAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH0NCiAgICAgICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7DQogICAgICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9DQogICAgICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvclsidGhyb3ciXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9DQogICAgICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfQ0KICAgICAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpOw0KICAgICAgICB9KTsNCiAgICB9CgogICAgLyoKICAgICAqIGJhc2U2NC1hcnJheWJ1ZmZlciAxLjAuMSA8aHR0cHM6Ly9naXRodWIuY29tL25pa2xhc3ZoL2Jhc2U2NC1hcnJheWJ1ZmZlcj4KICAgICAqIENvcHlyaWdodCAoYykgMjAyMSBOaWtsYXMgdm9uIEhlcnR6ZW4gPGh0dHBzOi8vaGVydHplbi5jb20+CiAgICAgKiBSZWxlYXNlZCB1bmRlciBNSVQgTGljZW5zZQogICAgICovCiAgICB2YXIgY2hhcnMgPSAnQUJDREVGR0hJSktMTU5PUFFSU1RVVldYWVphYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3h5ejAxMjM0NTY3ODkrLyc7CiAgICAvLyBVc2UgYSBsb29rdXAgdGFibGUgdG8gZmluZCB0aGUgaW5kZXguCiAgICB2YXIgbG9va3VwID0gdHlwZW9mIFVpbnQ4QXJyYXkgPT09ICd1bmRlZmluZWQnID8gW10gOiBuZXcgVWludDhBcnJheSgyNTYpOwogICAgZm9yICh2YXIgaSA9IDA7IGkgPCBjaGFycy5sZW5ndGg7IGkrKykgewogICAgICAgIGxvb2t1cFtjaGFycy5jaGFyQ29kZUF0KGkpXSA9IGk7CiAgICB9CiAgICB2YXIgZW5jb2RlID0gZnVuY3Rpb24gKGFycmF5YnVmZmVyKSB7CiAgICAgICAgdmFyIGJ5dGVzID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlidWZmZXIpLCBpLCBsZW4gPSBieXRlcy5sZW5ndGgsIGJhc2U2NCA9ICcnOwogICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkgKz0gMykgewogICAgICAgICAgICBiYXNlNjQgKz0gY2hhcnNbYnl0ZXNbaV0gPj4gMl07CiAgICAgICAgICAgIGJhc2U2NCArPSBjaGFyc1soKGJ5dGVzW2ldICYgMykgPDwgNCkgfCAoYnl0ZXNbaSArIDFdID4+IDQpXTsKICAgICAgICAgICAgYmFzZTY0ICs9IGNoYXJzWygoYnl0ZXNbaSArIDFdICYgMTUpIDw8IDIpIHwgKGJ5dGVzW2kgKyAyXSA+PiA2KV07CiAgICAgICAgICAgIGJhc2U2NCArPSBjaGFyc1tieXRlc1tpICsgMl0gJiA2M107CiAgICAgICAgfQogICAgICAgIGlmIChsZW4gJSAzID09PSAyKSB7CiAgICAgICAgICAgIGJhc2U2NCA9IGJhc2U2NC5zdWJzdHJpbmcoMCwgYmFzZTY0Lmxlbmd0aCAtIDEpICsgJz0nOwogICAgICAgIH0KICAgICAgICBlbHNlIGlmIChsZW4gJSAzID09PSAxKSB7CiAgICAgICAgICAgIGJhc2U2NCA9IGJhc2U2NC5zdWJzdHJpbmcoMCwgYmFzZTY0Lmxlbmd0aCAtIDIpICsgJz09JzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIGJhc2U2NDsKICAgIH07CgogICAgY29uc3QgbGFzdEJsb2JNYXAgPSBuZXcgTWFwKCk7DQogICAgY29uc3QgdHJhbnNwYXJlbnRCbG9iTWFwID0gbmV3IE1hcCgpOw0KICAgIGZ1bmN0aW9uIGdldFRyYW5zcGFyZW50QmxvYkZvcih3aWR0aCwgaGVpZ2h0LCBkYXRhVVJMT3B0aW9ucykgew0KICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiogKCkgew0KICAgICAgICAgICAgY29uc3QgaWQgPSBgJHt3aWR0aH0tJHtoZWlnaHR9YDsNCiAgICAgICAgICAgIGlmICgnT2Zmc2NyZWVuQ2FudmFzJyBpbiBnbG9iYWxUaGlzKSB7DQogICAgICAgICAgICAgICAgaWYgKHRyYW5zcGFyZW50QmxvYk1hcC5oYXMoaWQpKQ0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJhbnNwYXJlbnRCbG9iTWFwLmdldChpZCk7DQogICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2NyZWVuID0gbmV3IE9mZnNjcmVlbkNhbnZhcyh3aWR0aCwgaGVpZ2h0KTsNCiAgICAgICAgICAgICAgICBvZmZzY3JlZW4uZ2V0Q29udGV4dCgnMmQnKTsNCiAgICAgICAgICAgICAgICBjb25zdCBibG9iID0geWllbGQgb2Zmc2NyZWVuLmNvbnZlcnRUb0Jsb2IoZGF0YVVSTE9wdGlvbnMpOw0KICAgICAgICAgICAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0geWllbGQgYmxvYi5hcnJheUJ1ZmZlcigpOw0KICAgICAgICAgICAgICAgIGNvbnN0IGJhc2U2NCA9IGVuY29kZShhcnJheUJ1ZmZlcik7DQogICAgICAgICAgICAgICAgdHJhbnNwYXJlbnRCbG9iTWFwLnNldChpZCwgYmFzZTY0KTsNCiAgICAgICAgICAgICAgICByZXR1cm4gYmFzZTY0Ow0KICAgICAgICAgICAgfQ0KICAgICAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAgICAgcmV0dXJuICcnOw0KICAgICAgICAgICAgfQ0KICAgICAgICB9KTsNCiAgICB9DQogICAgY29uc3Qgd29ya2VyID0gc2VsZjsNCiAgICB3b3JrZXIub25tZXNzYWdlID0gZnVuY3Rpb24gKGUpIHsNCiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24qICgpIHsNCiAgICAgICAgICAgIGlmICgnT2Zmc2NyZWVuQ2FudmFzJyBpbiBnbG9iYWxUaGlzKSB7DQogICAgICAgICAgICAgICAgY29uc3QgeyBpZCwgYml0bWFwLCB3aWR0aCwgaGVpZ2h0LCBkYXRhVVJMT3B0aW9ucyB9ID0gZS5kYXRhOw0KICAgICAgICAgICAgICAgIGNvbnN0IHRyYW5zcGFyZW50QmFzZTY0ID0gZ2V0VHJhbnNwYXJlbnRCbG9iRm9yKHdpZHRoLCBoZWlnaHQsIGRhdGFVUkxPcHRpb25zKTsNCiAgICAgICAgICAgICAgICBjb25zdCBvZmZzY3JlZW4gPSBuZXcgT2Zmc2NyZWVuQ2FudmFzKHdpZHRoLCBoZWlnaHQpOw0KICAgICAgICAgICAgICAgIGNvbnN0IGN0eCA9IG9mZnNjcmVlbi5nZXRDb250ZXh0KCcyZCcpOw0KICAgICAgICAgICAgICAgIGN0eC5kcmF3SW1hZ2UoYml0bWFwLCAwLCAwKTsNCiAgICAgICAgICAgICAgICBiaXRtYXAuY2xvc2UoKTsNCiAgICAgICAgICAgICAgICBjb25zdCBibG9iID0geWllbGQgb2Zmc2NyZWVuLmNvbnZlcnRUb0Jsb2IoZGF0YVVSTE9wdGlvbnMpOw0KICAgICAgICAgICAgICAgIGNvbnN0IHR5cGUgPSBibG9iLnR5cGU7DQogICAgICAgICAgICAgICAgY29uc3QgYXJyYXlCdWZmZXIgPSB5aWVsZCBibG9iLmFycmF5QnVmZmVyKCk7DQogICAgICAgICAgICAgICAgY29uc3QgYmFzZTY0ID0gZW5jb2RlKGFycmF5QnVmZmVyKTsNCiAgICAgICAgICAgICAgICBpZiAoIWxhc3RCbG9iTWFwLmhhcyhpZCkgJiYgKHlpZWxkIHRyYW5zcGFyZW50QmFzZTY0KSA9PT0gYmFzZTY0KSB7DQogICAgICAgICAgICAgICAgICAgIGxhc3RCbG9iTWFwLnNldChpZCwgYmFzZTY0KTsNCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHdvcmtlci5wb3N0TWVzc2FnZSh7IGlkIH0pOw0KICAgICAgICAgICAgICAgIH0NCiAgICAgICAgICAgICAgICBpZiAobGFzdEJsb2JNYXAuZ2V0KGlkKSA9PT0gYmFzZTY0KQ0KICAgICAgICAgICAgICAgICAgICByZXR1cm4gd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQgfSk7DQogICAgICAgICAgICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKHsNCiAgICAgICAgICAgICAgICAgICAgaWQsDQogICAgICAgICAgICAgICAgICAgIHR5cGUsDQogICAgICAgICAgICAgICAgICAgIGJhc2U2NCwNCiAgICAgICAgICAgICAgICAgICAgd2lkdGgsDQogICAgICAgICAgICAgICAgICAgIGhlaWdodCwNCiAgICAgICAgICAgICAgICB9KTsNCiAgICAgICAgICAgICAgICBsYXN0QmxvYk1hcC5zZXQoaWQsIGJhc2U2NCk7DQogICAgICAgICAgICB9DQogICAgICAgICAgICBlbHNlIHsNCiAgICAgICAgICAgICAgICByZXR1cm4gd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQ6IGUuZGF0YS5pZCB9KTsNCiAgICAgICAgICAgIH0NCiAgICAgICAgfSk7DQogICAgfTsKCn0pKCk7Cgo=', null, false);
3769
+
2838
3770
  class CanvasManager {
2839
3771
  reset() {
2840
3772
  this.pendingCanvasMutations.clear();
@@ -2857,7 +3789,7 @@ class CanvasManager {
2857
3789
  this.rafStamps = { latestId: 0, invokeId: null };
2858
3790
  this.frozen = false;
2859
3791
  this.locked = false;
2860
- this.processMutation = function (target, mutation) {
3792
+ this.processMutation = (target, mutation) => {
2861
3793
  const newFrame = this.rafStamps.invokeId &&
2862
3794
  this.rafStamps.latestId !== this.rafStamps.invokeId;
2863
3795
  if (newFrame || !this.rafStamps.invokeId)
@@ -2867,16 +3799,108 @@ class CanvasManager {
2867
3799
  }
2868
3800
  this.pendingCanvasMutations.get(target).push(mutation);
2869
3801
  };
3802
+ const { sampling = 'all', win, blockClass, blockSelector, unblockSelector, recordCanvas, dataURLOptions, } = options;
2870
3803
  this.mutationCb = options.mutationCb;
2871
3804
  this.mirror = options.mirror;
2872
- if (options.recordCanvas === true)
2873
- this.initCanvasMutationObserver(options.win, options.blockClass, options.blockSelector, options.unblockSelector);
3805
+ if (recordCanvas && sampling === 'all')
3806
+ this.initCanvasMutationObserver(win, blockClass, blockSelector, unblockSelector);
3807
+ if (recordCanvas && typeof sampling === 'number')
3808
+ this.initCanvasFPSObserver(sampling, win, blockClass, blockSelector, unblockSelector, {
3809
+ dataURLOptions,
3810
+ });
3811
+ }
3812
+ initCanvasFPSObserver(fps, win, blockClass, blockSelector, unblockSelector, options) {
3813
+ const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector, true);
3814
+ const snapshotInProgressMap = new Map();
3815
+ const worker = new WorkerFactory();
3816
+ worker.onmessage = (e) => {
3817
+ const { id } = e.data;
3818
+ snapshotInProgressMap.set(id, false);
3819
+ if (!('base64' in e.data))
3820
+ return;
3821
+ const { base64, type, width, height } = e.data;
3822
+ this.mutationCb({
3823
+ id,
3824
+ type: CanvasContext['2D'],
3825
+ commands: [
3826
+ {
3827
+ property: 'clearRect',
3828
+ args: [0, 0, width, height],
3829
+ },
3830
+ {
3831
+ property: 'drawImage',
3832
+ args: [
3833
+ {
3834
+ rr_type: 'ImageBitmap',
3835
+ args: [
3836
+ {
3837
+ rr_type: 'Blob',
3838
+ data: [{ rr_type: 'ArrayBuffer', base64 }],
3839
+ type,
3840
+ },
3841
+ ],
3842
+ },
3843
+ 0,
3844
+ 0,
3845
+ ],
3846
+ },
3847
+ ],
3848
+ });
3849
+ };
3850
+ const timeBetweenSnapshots = 1000 / fps;
3851
+ let lastSnapshotTime = 0;
3852
+ let rafId;
3853
+ const getCanvas = () => {
3854
+ const matchedCanvas = [];
3855
+ win.document.querySelectorAll('canvas').forEach((canvas) => {
3856
+ if (!isBlocked(canvas, blockClass, blockSelector, unblockSelector, true)) {
3857
+ matchedCanvas.push(canvas);
3858
+ }
3859
+ });
3860
+ return matchedCanvas;
3861
+ };
3862
+ const takeCanvasSnapshots = (timestamp) => {
3863
+ if (lastSnapshotTime &&
3864
+ timestamp - lastSnapshotTime < timeBetweenSnapshots) {
3865
+ rafId = requestAnimationFrame(takeCanvasSnapshots);
3866
+ return;
3867
+ }
3868
+ lastSnapshotTime = timestamp;
3869
+ getCanvas()
3870
+ .forEach((canvas) => __awaiter(this, void 0, void 0, function* () {
3871
+ var _a;
3872
+ const id = this.mirror.getId(canvas);
3873
+ if (snapshotInProgressMap.get(id))
3874
+ return;
3875
+ snapshotInProgressMap.set(id, true);
3876
+ if (['webgl', 'webgl2'].includes(canvas.__context)) {
3877
+ const context = canvas.getContext(canvas.__context);
3878
+ if (((_a = context === null || context === void 0 ? void 0 : context.getContextAttributes()) === null || _a === void 0 ? void 0 : _a.preserveDrawingBuffer) === false) {
3879
+ context.clear(context.COLOR_BUFFER_BIT);
3880
+ }
3881
+ }
3882
+ const bitmap = yield createImageBitmap(canvas);
3883
+ worker.postMessage({
3884
+ id,
3885
+ bitmap,
3886
+ width: canvas.width,
3887
+ height: canvas.height,
3888
+ dataURLOptions: options.dataURLOptions,
3889
+ }, [bitmap]);
3890
+ }));
3891
+ rafId = requestAnimationFrame(takeCanvasSnapshots);
3892
+ };
3893
+ rafId = requestAnimationFrame(takeCanvasSnapshots);
3894
+ this.resetObservers = () => {
3895
+ canvasContextReset();
3896
+ cancelAnimationFrame(rafId);
3897
+ };
2874
3898
  }
2875
- initCanvasMutationObserver(win, blockClass, unblockSelector, blockSelector) {
3899
+ initCanvasMutationObserver(win, blockClass, blockSelector, unblockSelector) {
2876
3900
  this.startRAFTimestamping();
2877
3901
  this.startPendingCanvasMutationFlusher();
2878
- const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector);
2879
- const canvas2DReset = initCanvas2DMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector, unblockSelector, this.mirror);
3902
+ const canvasContextReset = initCanvasContextObserver(win, blockClass, blockSelector, unblockSelector, false);
3903
+ const canvas2DReset = initCanvas2DMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector, unblockSelector);
2880
3904
  const canvasWebGL1and2Reset = initCanvasWebGLMutationObserver(this.processMutation.bind(this), win, blockClass, blockSelector, unblockSelector, this.mirror);
2881
3905
  this.resetObservers = () => {
2882
3906
  canvasContextReset();
@@ -2918,20 +3942,133 @@ class CanvasManager {
2918
3942
  }
2919
3943
  }
2920
3944
 
3945
+ class StylesheetManager {
3946
+ constructor(options) {
3947
+ this.trackedLinkElements = new WeakSet();
3948
+ this.styleMirror = new StyleSheetMirror();
3949
+ this.mutationCb = options.mutationCb;
3950
+ this.adoptedStyleSheetCb = options.adoptedStyleSheetCb;
3951
+ }
3952
+ attachLinkElement(linkEl, childSn) {
3953
+ if ('_cssText' in childSn.attributes)
3954
+ this.mutationCb({
3955
+ adds: [],
3956
+ removes: [],
3957
+ texts: [],
3958
+ attributes: [
3959
+ {
3960
+ id: childSn.id,
3961
+ attributes: childSn
3962
+ .attributes,
3963
+ },
3964
+ ],
3965
+ });
3966
+ this.trackLinkElement(linkEl);
3967
+ }
3968
+ trackLinkElement(linkEl) {
3969
+ if (this.trackedLinkElements.has(linkEl))
3970
+ return;
3971
+ this.trackedLinkElements.add(linkEl);
3972
+ this.trackStylesheetInLinkElement(linkEl);
3973
+ }
3974
+ adoptStyleSheets(sheets, hostId) {
3975
+ if (sheets.length === 0)
3976
+ return;
3977
+ const adoptedStyleSheetData = {
3978
+ id: hostId,
3979
+ styleIds: [],
3980
+ };
3981
+ const styles = [];
3982
+ for (const sheet of sheets) {
3983
+ let styleId;
3984
+ if (!this.styleMirror.has(sheet)) {
3985
+ styleId = this.styleMirror.add(sheet);
3986
+ styles.push({
3987
+ styleId,
3988
+ rules: Array.from(sheet.rules || CSSRule, (r, index) => ({
3989
+ rule: stringifyRule(r),
3990
+ index,
3991
+ })),
3992
+ });
3993
+ }
3994
+ else
3995
+ styleId = this.styleMirror.getId(sheet);
3996
+ adoptedStyleSheetData.styleIds.push(styleId);
3997
+ }
3998
+ if (styles.length > 0)
3999
+ adoptedStyleSheetData.styles = styles;
4000
+ this.adoptedStyleSheetCb(adoptedStyleSheetData);
4001
+ }
4002
+ reset() {
4003
+ this.styleMirror.reset();
4004
+ this.trackedLinkElements = new WeakSet();
4005
+ }
4006
+ trackStylesheetInLinkElement(linkEl) {
4007
+ }
4008
+ }
4009
+
4010
+ class ProcessedNodeManager {
4011
+ constructor() {
4012
+ this.nodeMap = new WeakMap();
4013
+ this.loop = true;
4014
+ this.periodicallyClear();
4015
+ }
4016
+ periodicallyClear() {
4017
+ requestAnimationFrame(() => {
4018
+ this.clear();
4019
+ if (this.loop)
4020
+ this.periodicallyClear();
4021
+ });
4022
+ }
4023
+ inOtherBuffer(node, thisBuffer) {
4024
+ const buffers = this.nodeMap.get(node);
4025
+ return (buffers && Array.from(buffers).some((buffer) => buffer !== thisBuffer));
4026
+ }
4027
+ add(node, buffer) {
4028
+ this.nodeMap.set(node, (this.nodeMap.get(node) || new Set()).add(buffer));
4029
+ }
4030
+ clear() {
4031
+ this.nodeMap = new WeakMap();
4032
+ }
4033
+ destroy() {
4034
+ this.loop = false;
4035
+ }
4036
+ }
4037
+
2921
4038
  function wrapEvent(e) {
2922
- return Object.assign(Object.assign({}, e), { timestamp: Date.now() });
4039
+ return Object.assign(Object.assign({}, e), { timestamp: nowTimestamp() });
2923
4040
  }
2924
4041
  let wrappedEmit;
2925
4042
  let takeFullSnapshot;
4043
+ let canvasManager;
4044
+ let recording = false;
2926
4045
  const mirror = createMirror();
2927
4046
  function record(options = {}) {
2928
- const { emit, checkoutEveryNms, checkoutEveryNth, blockClass = 'rr-block', blockSelector = null, unblockSelector = null, ignoreClass = 'rr-ignore', ignoreSelector = null, maskTextClass = 'rr-mask', maskTextSelector = null, maskInputSelector = null, unmaskTextSelector = null, unmaskInputSelector = null, inlineStylesheet = true, maskAllText = false, maskAllInputs, maskInputOptions: _maskInputOptions, slimDOMOptions: _slimDOMOptions, maskInputFn, maskTextFn, hooks, packFn, sampling = {}, mousemoveWait, recordCanvas = false, userTriggeredOnInput = false, collectFonts = false, inlineImages = false, plugins, keepIframeSrcFn = () => false, onMutation, } = options;
2929
- if (!emit) {
4047
+ 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'
4048
+ ? options.recordAfter
4049
+ : 'load', userTriggeredOnInput = false, collectFonts = false, inlineImages = false, plugins, keepIframeSrcFn = () => false, ignoreCSSAttributes = new Set([]), errorHandler, onMutation, } = options;
4050
+ registerErrorHandler(errorHandler);
4051
+ const inEmittingFrame = recordCrossOriginIframes
4052
+ ? window.parent === window
4053
+ : true;
4054
+ let passEmitsToParent = false;
4055
+ if (!inEmittingFrame) {
4056
+ try {
4057
+ if (window.parent.document) {
4058
+ passEmitsToParent = false;
4059
+ }
4060
+ }
4061
+ catch (e) {
4062
+ passEmitsToParent = true;
4063
+ }
4064
+ }
4065
+ if (inEmittingFrame && !emit) {
2930
4066
  throw new Error('emit function is required');
2931
4067
  }
2932
4068
  if (mousemoveWait !== undefined && sampling.mousemove === undefined) {
2933
4069
  sampling.mousemove = mousemoveWait;
2934
4070
  }
4071
+ mirror.reset();
2935
4072
  const maskInputOptions = maskAllInputs === true
2936
4073
  ? {
2937
4074
  color: true,
@@ -2980,7 +4117,8 @@ function record(options = {}) {
2980
4117
  e = plugin.eventProcessor(e);
2981
4118
  }
2982
4119
  }
2983
- if (packFn) {
4120
+ if (packFn &&
4121
+ !passEmitsToParent) {
2984
4122
  e = packFn(e);
2985
4123
  }
2986
4124
  return e;
@@ -2993,7 +4131,18 @@ function record(options = {}) {
2993
4131
  e.data.source === IncrementalSource.Mutation)) {
2994
4132
  mutationBuffers.forEach((buf) => buf.unfreeze());
2995
4133
  }
2996
- emit(eventProcessor(e), isCheckout);
4134
+ if (inEmittingFrame) {
4135
+ emit === null || emit === void 0 ? void 0 : emit(eventProcessor(e), isCheckout);
4136
+ }
4137
+ else if (passEmitsToParent) {
4138
+ const message = {
4139
+ type: 'rrweb',
4140
+ event: eventProcessor(e),
4141
+ origin: window.location.origin,
4142
+ isCheckout,
4143
+ };
4144
+ window.parent.postMessage(message, '*');
4145
+ }
2997
4146
  if (e.type === EventType.FullSnapshot) {
2998
4147
  lastFullSnapshotEvent = e;
2999
4148
  incrementalSnapshotCount = 0;
@@ -3026,10 +4175,31 @@ function record(options = {}) {
3026
4175
  type: EventType.IncrementalSnapshot,
3027
4176
  data: Object.assign({ source: IncrementalSource.CanvasMutation }, p),
3028
4177
  }));
4178
+ const wrappedAdoptedStyleSheetEmit = (a) => wrappedEmit(wrapEvent({
4179
+ type: EventType.IncrementalSnapshot,
4180
+ data: Object.assign({ source: IncrementalSource.AdoptedStyleSheet }, a),
4181
+ }));
4182
+ const stylesheetManager = new StylesheetManager({
4183
+ mutationCb: wrappedMutationEmit,
4184
+ adoptedStyleSheetCb: wrappedAdoptedStyleSheetEmit,
4185
+ });
3029
4186
  const iframeManager = new IframeManager({
4187
+ mirror,
3030
4188
  mutationCb: wrappedMutationEmit,
4189
+ stylesheetManager: stylesheetManager,
4190
+ recordCrossOriginIframes,
4191
+ wrappedEmit,
3031
4192
  });
3032
- const canvasManager = new CanvasManager({
4193
+ for (const plugin of plugins || []) {
4194
+ if (plugin.getMirror)
4195
+ plugin.getMirror({
4196
+ nodeMirror: mirror,
4197
+ crossOriginIframeMirror: iframeManager.crossOriginIframeMirror,
4198
+ crossOriginIframeStyleMirror: iframeManager.crossOriginIframeStyleMirror,
4199
+ });
4200
+ }
4201
+ const processedNodeManager = new ProcessedNodeManager();
4202
+ canvasManager = new CanvasManager({
3033
4203
  recordCanvas,
3034
4204
  mutationCb: wrappedCanvasMutationEmit,
3035
4205
  win: window,
@@ -3037,6 +4207,8 @@ function record(options = {}) {
3037
4207
  blockSelector,
3038
4208
  unblockSelector,
3039
4209
  mirror,
4210
+ sampling: sampling.canvas,
4211
+ dataURLOptions,
3040
4212
  });
3041
4213
  const shadowDomManager = new ShadowDomManager({
3042
4214
  mutationCb: wrappedMutationEmit,
@@ -3046,14 +4218,15 @@ function record(options = {}) {
3046
4218
  blockClass,
3047
4219
  blockSelector,
3048
4220
  unblockSelector,
4221
+ maskAllText,
3049
4222
  maskTextClass,
4223
+ unmaskTextClass,
3050
4224
  maskTextSelector,
3051
4225
  unmaskTextSelector,
3052
- maskInputSelector,
3053
- unmaskInputSelector,
3054
4226
  inlineStylesheet,
3055
- maskAllText,
3056
4227
  maskInputOptions,
4228
+ dataURLOptions,
4229
+ maskAttributeFn,
3057
4230
  maskTextFn,
3058
4231
  maskInputFn,
3059
4232
  recordCanvas,
@@ -3061,12 +4234,14 @@ function record(options = {}) {
3061
4234
  sampling,
3062
4235
  slimDOMOptions,
3063
4236
  iframeManager,
4237
+ stylesheetManager,
3064
4238
  canvasManager,
4239
+ keepIframeSrcFn,
4240
+ processedNodeManager,
3065
4241
  },
3066
4242
  mirror,
3067
4243
  });
3068
4244
  takeFullSnapshot = (isCheckout = false) => {
3069
- var _a, _b, _c, _d;
3070
4245
  wrappedEmit(wrapEvent({
3071
4246
  type: EventType.Meta,
3072
4247
  data: {
@@ -3075,27 +4250,35 @@ function record(options = {}) {
3075
4250
  height: getWindowHeight(),
3076
4251
  },
3077
4252
  }), isCheckout);
4253
+ stylesheetManager.reset();
4254
+ shadowDomManager.init();
3078
4255
  mutationBuffers.forEach((buf) => buf.lock());
3079
- const [node, idNodeMap] = snapshot(document, {
4256
+ const node = snapshot(document, {
4257
+ mirror,
3080
4258
  blockClass,
3081
4259
  blockSelector,
3082
4260
  unblockSelector,
4261
+ maskAllText,
3083
4262
  maskTextClass,
4263
+ unmaskTextClass,
3084
4264
  maskTextSelector,
3085
4265
  unmaskTextSelector,
3086
- maskInputSelector,
3087
- unmaskInputSelector,
3088
4266
  inlineStylesheet,
3089
- maskAllText,
3090
4267
  maskAllInputs: maskInputOptions,
4268
+ maskAttributeFn,
4269
+ maskInputFn,
3091
4270
  maskTextFn,
3092
4271
  slimDOM: slimDOMOptions,
4272
+ dataURLOptions,
3093
4273
  recordCanvas,
3094
4274
  inlineImages,
3095
4275
  onSerialize: (n) => {
3096
- if (isIframeINode(n)) {
4276
+ if (isSerializedIframe(n, mirror)) {
3097
4277
  iframeManager.addIframe(n);
3098
4278
  }
4279
+ if (isSerializedStylesheet(n, mirror)) {
4280
+ stylesheetManager.trackLinkElement(n);
4281
+ }
3099
4282
  if (hasShadowRoot(n)) {
3100
4283
  shadowDomManager.addShadowRoot(n.shadowRoot, document);
3101
4284
  }
@@ -3104,42 +4287,27 @@ function record(options = {}) {
3104
4287
  iframeManager.attachIframe(iframe, childSn);
3105
4288
  shadowDomManager.observeAttachShadow(iframe);
3106
4289
  },
4290
+ onStylesheetLoad: (linkEl, childSn) => {
4291
+ stylesheetManager.attachLinkElement(linkEl, childSn);
4292
+ },
3107
4293
  keepIframeSrcFn,
3108
4294
  });
3109
4295
  if (!node) {
3110
4296
  return console.warn('Failed to snapshot the document');
3111
4297
  }
3112
- mirror.map = idNodeMap;
3113
4298
  wrappedEmit(wrapEvent({
3114
4299
  type: EventType.FullSnapshot,
3115
4300
  data: {
3116
4301
  node,
3117
- initialOffset: {
3118
- left: window.pageXOffset !== undefined
3119
- ? window.pageXOffset
3120
- : (document === null || document === void 0 ? void 0 : document.documentElement.scrollLeft) ||
3121
- ((_b = (_a = document === null || document === void 0 ? void 0 : document.body) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.scrollLeft) ||
3122
- (document === null || document === void 0 ? void 0 : document.body.scrollLeft) ||
3123
- 0,
3124
- top: window.pageYOffset !== undefined
3125
- ? window.pageYOffset
3126
- : (document === null || document === void 0 ? void 0 : document.documentElement.scrollTop) ||
3127
- ((_d = (_c = document === null || document === void 0 ? void 0 : document.body) === null || _c === void 0 ? void 0 : _c.parentElement) === null || _d === void 0 ? void 0 : _d.scrollTop) ||
3128
- (document === null || document === void 0 ? void 0 : document.body.scrollTop) ||
3129
- 0,
3130
- },
4302
+ initialOffset: getWindowScroll(window),
3131
4303
  },
3132
- }));
4304
+ }), isCheckout);
3133
4305
  mutationBuffers.forEach((buf) => buf.unlock());
4306
+ if (document.adoptedStyleSheets && document.adoptedStyleSheets.length > 0)
4307
+ stylesheetManager.adoptStyleSheets(document.adoptedStyleSheets, mirror.getId(document));
3134
4308
  };
3135
4309
  try {
3136
4310
  const handlers = [];
3137
- handlers.push(on('DOMContentLoaded', () => {
3138
- wrappedEmit(wrapEvent({
3139
- type: EventType.DomContentLoaded,
3140
- data: {},
3141
- }));
3142
- }));
3143
4311
  const observe = (doc) => {
3144
4312
  var _a;
3145
4313
  return callbackWrapper(initObservers)({
@@ -3182,14 +4350,26 @@ function record(options = {}) {
3182
4350
  type: EventType.IncrementalSnapshot,
3183
4351
  data: Object.assign({ source: IncrementalSource.Font }, p),
3184
4352
  })),
4353
+ selectionCb: (p) => {
4354
+ wrappedEmit(wrapEvent({
4355
+ type: EventType.IncrementalSnapshot,
4356
+ data: Object.assign({ source: IncrementalSource.Selection }, p),
4357
+ }));
4358
+ },
4359
+ customElementCb: (c) => {
4360
+ wrappedEmit(wrapEvent({
4361
+ type: EventType.IncrementalSnapshot,
4362
+ data: Object.assign({ source: IncrementalSource.CustomElement }, c),
4363
+ }));
4364
+ },
3185
4365
  blockClass,
3186
4366
  ignoreClass,
3187
4367
  ignoreSelector,
4368
+ maskAllText,
3188
4369
  maskTextClass,
4370
+ unmaskTextClass,
3189
4371
  maskTextSelector,
3190
4372
  unmaskTextSelector,
3191
- maskInputSelector,
3192
- unmaskInputSelector,
3193
4373
  maskInputOptions,
3194
4374
  inlineStylesheet,
3195
4375
  sampling,
@@ -3198,16 +4378,21 @@ function record(options = {}) {
3198
4378
  userTriggeredOnInput,
3199
4379
  collectFonts,
3200
4380
  doc,
3201
- maskAllText,
4381
+ maskAttributeFn,
3202
4382
  maskInputFn,
3203
4383
  maskTextFn,
4384
+ keepIframeSrcFn,
3204
4385
  blockSelector,
3205
4386
  unblockSelector,
3206
4387
  slimDOMOptions,
4388
+ dataURLOptions,
3207
4389
  mirror,
3208
4390
  iframeManager,
4391
+ stylesheetManager,
3209
4392
  shadowDomManager,
4393
+ processedNodeManager,
3210
4394
  canvasManager,
4395
+ ignoreCSSAttributes,
3211
4396
  plugins: ((_a = plugins === null || plugins === void 0 ? void 0 : plugins.filter((p) => p.observer)) === null || _a === void 0 ? void 0 : _a.map((p) => ({
3212
4397
  observer: p.observer,
3213
4398
  options: p.options,
@@ -3232,22 +4417,35 @@ function record(options = {}) {
3232
4417
  const init = () => {
3233
4418
  takeFullSnapshot();
3234
4419
  handlers.push(observe(document));
4420
+ recording = true;
3235
4421
  };
3236
4422
  if (document.readyState === 'interactive' ||
3237
4423
  document.readyState === 'complete') {
3238
4424
  init();
3239
4425
  }
3240
4426
  else {
4427
+ handlers.push(on('DOMContentLoaded', () => {
4428
+ wrappedEmit(wrapEvent({
4429
+ type: EventType.DomContentLoaded,
4430
+ data: {},
4431
+ }));
4432
+ if (recordAfter === 'DOMContentLoaded')
4433
+ init();
4434
+ }));
3241
4435
  handlers.push(on('load', () => {
3242
4436
  wrappedEmit(wrapEvent({
3243
4437
  type: EventType.Load,
3244
4438
  data: {},
3245
4439
  }));
3246
- init();
4440
+ if (recordAfter === 'load')
4441
+ init();
3247
4442
  }, window));
3248
4443
  }
3249
4444
  return () => {
3250
4445
  handlers.forEach((h) => h());
4446
+ processedNodeManager.destroy();
4447
+ recording = false;
4448
+ unregisterErrorHandler();
3251
4449
  };
3252
4450
  }
3253
4451
  catch (error) {
@@ -3255,7 +4453,7 @@ function record(options = {}) {
3255
4453
  }
3256
4454
  }
3257
4455
  record.addCustomEvent = (tag, payload) => {
3258
- if (!wrappedEmit) {
4456
+ if (!recording) {
3259
4457
  throw new Error('please add custom event after start recording');
3260
4458
  }
3261
4459
  wrappedEmit(wrapEvent({
@@ -3270,7 +4468,7 @@ record.freezePage = () => {
3270
4468
  mutationBuffers.forEach((buf) => buf.freeze());
3271
4469
  };
3272
4470
  record.takeFullSnapshot = (isCheckout) => {
3273
- if (!takeFullSnapshot) {
4471
+ if (!recording) {
3274
4472
  throw new Error('please take full snapshot after start recording');
3275
4473
  }
3276
4474
  takeFullSnapshot(isCheckout);
@@ -3766,27 +4964,25 @@ const handleDomListener = (
3766
4964
 
3767
4965
  /** Get the base DOM breadcrumb. */
3768
4966
  function getBaseDomBreadcrumb(target, message) {
3769
- // `__sn` property is the serialized node created by rrweb
3770
- const serializedNode = target && isRrwebNode(target) && target.__sn.type === NodeType.Element ? target.__sn : null;
4967
+ const nodeId = record.mirror.getId(target);
4968
+ const node = nodeId && record.mirror.getNode(nodeId);
4969
+ const meta = node && record.mirror.getMeta(node);
4970
+ const element = meta && isElement(meta) ? meta : null;
3771
4971
 
3772
4972
  return {
3773
4973
  message,
3774
- data: serializedNode
4974
+ data: element
3775
4975
  ? {
3776
- nodeId: serializedNode.id,
4976
+ nodeId,
3777
4977
  node: {
3778
- id: serializedNode.id,
3779
- tagName: serializedNode.tagName,
3780
- textContent: target
3781
- ? Array.from(target.childNodes)
3782
- .map(
3783
- (node) => '__sn' in node && node.__sn.type === NodeType.Text && node.__sn.textContent,
3784
- )
3785
- .filter(Boolean) // filter out empty values
3786
- .map(text => (text ).trim())
3787
- .join('')
3788
- : '',
3789
- attributes: getAttributesToRecord(serializedNode.attributes),
4978
+ id: nodeId,
4979
+ tagName: element.tagName,
4980
+ textContent: Array.from(element.childNodes)
4981
+ .map((node) => node.type === NodeType.Text && node.textContent)
4982
+ .filter(Boolean) // filter out empty values
4983
+ .map(text => (text ).trim())
4984
+ .join(''),
4985
+ attributes: getAttributesToRecord(element.attributes),
3790
4986
  },
3791
4987
  }
3792
4988
  : {},
@@ -3823,8 +5019,8 @@ function getDomTarget(handlerData) {
3823
5019
  return { target, message };
3824
5020
  }
3825
5021
 
3826
- function isRrwebNode(node) {
3827
- return '__sn' in node;
5022
+ function isElement(node) {
5023
+ return node.type === NodeType.Element;
3828
5024
  }
3829
5025
 
3830
5026
  /** Handle keyboard events & create breadcrumbs. */
@@ -5139,16 +6335,7 @@ function shouldFilterRequest(replay, url) {
5139
6335
  return false;
5140
6336
  }
5141
6337
 
5142
- return _isSentryRequest(url);
5143
- }
5144
-
5145
- /**
5146
- * Checks wether a given URL belongs to the configured Sentry DSN.
5147
- */
5148
- function _isSentryRequest(url) {
5149
- const client = core.getCurrentHub().getClient();
5150
- const dsn = client && client.getDsn();
5151
- return dsn ? url.includes(dsn.host) : false;
6338
+ return core.isSentryRequestUrl(url, core.getCurrentHub());
5152
6339
  }
5153
6340
 
5154
6341
  /** Add a performance entry breadcrumb */
@@ -6663,9 +7850,7 @@ function createLargestContentfulPaint(
6663
7850
  data: {
6664
7851
  value, // LCP "duration" in ms
6665
7852
  size,
6666
- // Not sure why this errors, Node should be correct (Argument of type 'Node' is not assignable to parameter of type 'INode')
6667
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
6668
- nodeId: record.mirror.getId(entry.element ),
7853
+ nodeId: record.mirror.getId(entry.element),
6669
7854
  },
6670
7855
  };
6671
7856
  }
@@ -8462,8 +9647,6 @@ function getPrivacyOptions({
8462
9647
  // We are making the decision to make text and input selectors the same
8463
9648
  maskTextSelector: maskSelector,
8464
9649
  unmaskTextSelector: unmaskSelector,
8465
- maskInputSelector: maskSelector,
8466
- unmaskInputSelector: unmaskSelector,
8467
9650
 
8468
9651
  blockSelector: getOption(
8469
9652
  block,
@@ -8499,6 +9682,39 @@ function isElectronNodeRenderer() {
8499
9682
  return typeof process !== 'undefined' && (process ).type === 'renderer';
8500
9683
  }
8501
9684
 
9685
+ /**
9686
+ * Masks an attribute if necessary, otherwise return attribute value as-is.
9687
+ */
9688
+ function maskAttribute({
9689
+ el,
9690
+ key,
9691
+ maskAttributes,
9692
+ maskAllText,
9693
+ privacyOptions,
9694
+ value,
9695
+ }) {
9696
+ // We only mask attributes if `maskAllText` is true
9697
+ if (!maskAllText) {
9698
+ return value;
9699
+ }
9700
+
9701
+ // unmaskTextSelector takes precendence
9702
+ if (privacyOptions.unmaskTextSelector && el.matches(privacyOptions.unmaskTextSelector)) {
9703
+ return value;
9704
+ }
9705
+
9706
+ if (
9707
+ maskAttributes.includes(key) ||
9708
+ // Need to mask `value` attribute for `<input>` if it's a button-like
9709
+ // type
9710
+ (key === 'value' && el.tagName === 'INPUT' && ['submit', 'button'].includes(el.getAttribute('type') || ''))
9711
+ ) {
9712
+ return value.replace(/[\S]/g, '*');
9713
+ }
9714
+
9715
+ return value;
9716
+ }
9717
+
8502
9718
  const MEDIA_SELECTORS =
8503
9719
  'img,image,svg,video,object,picture,embed,map,audio,link[rel="icon"],link[rel="apple-touch-icon"]';
8504
9720
 
@@ -8558,6 +9774,7 @@ class Replay {
8558
9774
  networkResponseHeaders = [],
8559
9775
 
8560
9776
  mask = [],
9777
+ maskAttributes = ['title', 'placeholder'],
8561
9778
  unmask = [],
8562
9779
  block = [],
8563
9780
  unblock = [],
@@ -8581,25 +9798,36 @@ class Replay {
8581
9798
  } = {}) {
8582
9799
  this.name = Replay.id;
8583
9800
 
9801
+ const privacyOptions = getPrivacyOptions({
9802
+ mask,
9803
+ unmask,
9804
+ block,
9805
+ unblock,
9806
+ ignore,
9807
+ blockClass,
9808
+ blockSelector,
9809
+ maskTextClass,
9810
+ maskTextSelector,
9811
+ ignoreClass,
9812
+ });
9813
+
8584
9814
  this._recordingOptions = {
8585
9815
  maskAllInputs,
8586
9816
  maskAllText,
8587
9817
  maskInputOptions: { ...(maskInputOptions || {}), password: true },
8588
9818
  maskTextFn: maskFn,
8589
9819
  maskInputFn: maskFn,
9820
+ maskAttributeFn: (key, value, el) =>
9821
+ maskAttribute({
9822
+ maskAttributes,
9823
+ maskAllText,
9824
+ privacyOptions,
9825
+ key,
9826
+ value,
9827
+ el,
9828
+ }),
8590
9829
 
8591
- ...getPrivacyOptions({
8592
- mask,
8593
- unmask,
8594
- block,
8595
- unblock,
8596
- ignore,
8597
- blockClass,
8598
- blockSelector,
8599
- maskTextClass,
8600
- maskTextSelector,
8601
- ignoreClass,
8602
- }),
9830
+ ...privacyOptions,
8603
9831
 
8604
9832
  // Our defaults
8605
9833
  slimDOMOptions: 'all',
@@ -8609,6 +9837,14 @@ class Replay {
8609
9837
  // collect fonts, but be aware that `sentry.io` needs to be an allowed
8610
9838
  // origin for playback
8611
9839
  collectFonts: true,
9840
+ errorHandler: (err) => {
9841
+ try {
9842
+ err.__rrweb__ = true;
9843
+ } catch (error) {
9844
+ // ignore errors here
9845
+ // this can happen if the error is frozen or does not allow mutation for other reasons
9846
+ }
9847
+ },
8612
9848
  };
8613
9849
 
8614
9850
  this._initialOptions = {