rrweb
Version:
record and replay the web
425 lines (422 loc) • 14.7 kB
JavaScript
import { __values } from '../node_modules/tslib/tslib.es6.js';
import { IGNORED_NODE } from '../node_modules/rrweb-snapshot/es/rrweb-snapshot.js';
import { EventType, IncrementalSource } from './types.js';
function on(type, fn, target) {
if (target === void 0) { target = document; }
var options = { capture: true, passive: true };
target.addEventListener(type, fn, options);
return function () { return target.removeEventListener(type, fn, options); };
}
var mirror = {
map: {},
getId: function (n) {
if (!n.__sn) {
return -1;
}
return n.__sn.id;
},
getNode: function (id) {
return mirror.map[id] || null;
},
removeNodeFromMap: function (n) {
var id = n.__sn && n.__sn.id;
delete mirror.map[id];
if (n.childNodes) {
n.childNodes.forEach(function (child) {
return mirror.removeNodeFromMap(child);
});
}
},
has: function (id) {
return mirror.map.hasOwnProperty(id);
},
};
function throttle(func, wait, options) {
if (options === void 0) { options = {}; }
var timeout = null;
var previous = 0;
return function (arg) {
var now = Date.now();
if (!previous && options.leading === false) {
previous = now;
}
var remaining = wait - (now - previous);
var context = this;
var args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
window.clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
}
else if (!timeout && options.trailing !== false) {
timeout = window.setTimeout(function () {
previous = options.leading === false ? 0 : Date.now();
timeout = null;
func.apply(context, args);
}, remaining);
}
};
}
function hookSetter(target, key, d, isRevoked, win) {
if (win === void 0) { win = window; }
var original = win.Object.getOwnPropertyDescriptor(target, key);
win.Object.defineProperty(target, key, isRevoked
? d
: {
set: function (value) {
var _this = this;
setTimeout(function () {
d.set.call(_this, value);
}, 0);
if (original && original.set) {
original.set.call(this, value);
}
},
});
return function () { return hookSetter(target, key, original || {}, true); };
}
function patch(source, name, replacement) {
try {
if (!(name in source)) {
return function () { };
}
var original_1 = source[name];
var wrapped = replacement(original_1);
if (typeof wrapped === 'function') {
wrapped.prototype = wrapped.prototype || {};
Object.defineProperties(wrapped, {
__rrweb_original__: {
enumerable: false,
value: original_1,
},
});
}
source[name] = wrapped;
return function () {
source[name] = original_1;
};
}
catch (_a) {
return function () { };
}
}
function getWindowHeight() {
return (window.innerHeight ||
(document.documentElement && document.documentElement.clientHeight) ||
(document.body && document.body.clientHeight));
}
function getWindowWidth() {
return (window.innerWidth ||
(document.documentElement && document.documentElement.clientWidth) ||
(document.body && document.body.clientWidth));
}
function isBlocked(node, blockClass) {
if (!node) {
return false;
}
if (node.nodeType === node.ELEMENT_NODE) {
var needBlock_1 = false;
if (typeof blockClass === 'string') {
needBlock_1 = node.classList.contains(blockClass);
}
else {
node.classList.forEach(function (className) {
if (blockClass.test(className)) {
needBlock_1 = true;
}
});
}
return needBlock_1 || isBlocked(node.parentNode, blockClass);
}
if (node.nodeType === node.TEXT_NODE) {
return isBlocked(node.parentNode, blockClass);
}
return isBlocked(node.parentNode, blockClass);
}
function isIgnored(n) {
if ('__sn' in n) {
return n.__sn.id === IGNORED_NODE;
}
return false;
}
function isAncestorRemoved(target) {
var id = mirror.getId(target);
if (!mirror.has(id)) {
return true;
}
if (target.parentNode &&
target.parentNode.nodeType === target.DOCUMENT_NODE) {
return false;
}
if (!target.parentNode) {
return true;
}
return isAncestorRemoved(target.parentNode);
}
function isTouchEvent(event) {
return Boolean(event.changedTouches);
}
function polyfill(win) {
if (win === void 0) { win = window; }
if ('NodeList' in win && !win.NodeList.prototype.forEach) {
win.NodeList.prototype.forEach = Array.prototype
.forEach;
}
if ('DOMTokenList' in win && !win.DOMTokenList.prototype.forEach) {
win.DOMTokenList.prototype.forEach = Array.prototype
.forEach;
}
}
function needCastInSyncMode(event) {
switch (event.type) {
case EventType.DomContentLoaded:
case EventType.Load:
case EventType.Custom:
return false;
case EventType.FullSnapshot:
case EventType.Meta:
return true;
}
switch (event.data.source) {
case IncrementalSource.MouseMove:
case IncrementalSource.MouseInteraction:
case IncrementalSource.TouchMove:
case IncrementalSource.MediaInteraction:
return false;
case IncrementalSource.ViewportResize:
case IncrementalSource.StyleSheetRule:
case IncrementalSource.Scroll:
case IncrementalSource.Input:
return true;
}
return true;
}
var TreeIndex = (function () {
function TreeIndex() {
this.reset();
}
TreeIndex.prototype.add = function (mutation) {
var parentTreeNode = this.indexes.get(mutation.parentId);
var treeNode = {
id: mutation.node.id,
mutation: mutation,
children: [],
texts: [],
attributes: [],
};
if (!parentTreeNode) {
this.tree[treeNode.id] = treeNode;
}
else {
treeNode.parent = parentTreeNode;
parentTreeNode.children[treeNode.id] = treeNode;
}
this.indexes.set(treeNode.id, treeNode);
};
TreeIndex.prototype.remove = function (mutation) {
var _this = this;
var parentTreeNode = this.indexes.get(mutation.parentId);
var treeNode = this.indexes.get(mutation.id);
var deepRemoveFromMirror = function (id) {
_this.removeIdSet.add(id);
var node = mirror.getNode(id);
node === null || node === void 0 ? void 0 : node.childNodes.forEach(function (childNode) {
if ('__sn' in childNode) {
deepRemoveFromMirror(childNode.__sn.id);
}
});
};
var deepRemoveFromTreeIndex = function (node) {
_this.removeIdSet.add(node.id);
Object.values(node.children).forEach(function (n) { return deepRemoveFromTreeIndex(n); });
var _treeNode = _this.indexes.get(node.id);
if (_treeNode) {
var _parentTreeNode = _treeNode.parent;
if (_parentTreeNode) {
delete _treeNode.parent;
delete _parentTreeNode.children[_treeNode.id];
_this.indexes.delete(mutation.id);
}
}
};
if (!treeNode) {
this.removeNodeMutations.push(mutation);
deepRemoveFromMirror(mutation.id);
}
else if (!parentTreeNode) {
delete this.tree[treeNode.id];
this.indexes.delete(treeNode.id);
deepRemoveFromTreeIndex(treeNode);
}
else {
delete treeNode.parent;
delete parentTreeNode.children[treeNode.id];
this.indexes.delete(mutation.id);
deepRemoveFromTreeIndex(treeNode);
}
};
TreeIndex.prototype.text = function (mutation) {
var treeNode = this.indexes.get(mutation.id);
if (treeNode) {
treeNode.texts.push(mutation);
}
else {
this.textMutations.push(mutation);
}
};
TreeIndex.prototype.attribute = function (mutation) {
var treeNode = this.indexes.get(mutation.id);
if (treeNode) {
treeNode.attributes.push(mutation);
}
else {
this.attributeMutations.push(mutation);
}
};
TreeIndex.prototype.scroll = function (d) {
this.scrollMap.set(d.id, d);
};
TreeIndex.prototype.input = function (d) {
this.inputMap.set(d.id, d);
};
TreeIndex.prototype.flush = function () {
var e_1, _a, e_2, _b;
var _this = this;
var _c = this, tree = _c.tree, removeNodeMutations = _c.removeNodeMutations, textMutations = _c.textMutations, attributeMutations = _c.attributeMutations;
var batchMutationData = {
source: IncrementalSource.Mutation,
removes: removeNodeMutations,
texts: textMutations,
attributes: attributeMutations,
adds: [],
};
var walk = function (treeNode, removed) {
if (removed) {
_this.removeIdSet.add(treeNode.id);
}
batchMutationData.texts = batchMutationData.texts
.concat(removed ? [] : treeNode.texts)
.filter(function (m) { return !_this.removeIdSet.has(m.id); });
batchMutationData.attributes = batchMutationData.attributes
.concat(removed ? [] : treeNode.attributes)
.filter(function (m) { return !_this.removeIdSet.has(m.id); });
if (!_this.removeIdSet.has(treeNode.id) &&
!_this.removeIdSet.has(treeNode.mutation.parentId) &&
!removed) {
batchMutationData.adds.push(treeNode.mutation);
if (treeNode.children) {
Object.values(treeNode.children).forEach(function (n) { return walk(n, false); });
}
}
else {
Object.values(treeNode.children).forEach(function (n) { return walk(n, true); });
}
};
Object.values(tree).forEach(function (n) { return walk(n, false); });
try {
for (var _d = __values(this.scrollMap.keys()), _e = _d.next(); !_e.done; _e = _d.next()) {
var id = _e.value;
if (this.removeIdSet.has(id)) {
this.scrollMap.delete(id);
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
}
finally { if (e_1) throw e_1.error; }
}
try {
for (var _f = __values(this.inputMap.keys()), _g = _f.next(); !_g.done; _g = _f.next()) {
var id = _g.value;
if (this.removeIdSet.has(id)) {
this.inputMap.delete(id);
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (_g && !_g.done && (_b = _f.return)) _b.call(_f);
}
finally { if (e_2) throw e_2.error; }
}
var scrollMap = new Map(this.scrollMap);
var inputMap = new Map(this.inputMap);
this.reset();
return {
mutationData: batchMutationData,
scrollMap: scrollMap,
inputMap: inputMap,
};
};
TreeIndex.prototype.reset = function () {
this.tree = [];
this.indexes = new Map();
this.removeNodeMutations = [];
this.textMutations = [];
this.attributeMutations = [];
this.removeIdSet = new Set();
this.scrollMap = new Map();
this.inputMap = new Map();
};
return TreeIndex;
}());
function queueToResolveTrees(queue) {
var e_3, _a;
var queueNodeMap = {};
var putIntoMap = function (m, parent) {
var nodeInTree = {
value: m,
parent: parent,
children: [],
};
queueNodeMap[m.node.id] = nodeInTree;
return nodeInTree;
};
var queueNodeTrees = [];
try {
for (var queue_1 = __values(queue), queue_1_1 = queue_1.next(); !queue_1_1.done; queue_1_1 = queue_1.next()) {
var mutation = queue_1_1.value;
var nextId = mutation.nextId, parentId = mutation.parentId;
if (nextId && nextId in queueNodeMap) {
var nextInTree = queueNodeMap[nextId];
if (nextInTree.parent) {
var idx = nextInTree.parent.children.indexOf(nextInTree);
nextInTree.parent.children.splice(idx, 0, putIntoMap(mutation, nextInTree.parent));
}
else {
var idx = queueNodeTrees.indexOf(nextInTree);
queueNodeTrees.splice(idx, 0, putIntoMap(mutation, null));
}
continue;
}
if (parentId in queueNodeMap) {
var parentInTree = queueNodeMap[parentId];
parentInTree.children.push(putIntoMap(mutation, parentInTree));
continue;
}
queueNodeTrees.push(putIntoMap(mutation, null));
}
}
catch (e_3_1) { e_3 = { error: e_3_1 }; }
finally {
try {
if (queue_1_1 && !queue_1_1.done && (_a = queue_1.return)) _a.call(queue_1);
}
finally { if (e_3) throw e_3.error; }
}
return queueNodeTrees;
}
function iterateResolveTree(tree, cb) {
cb(tree.value);
for (var i = tree.children.length - 1; i >= 0; i--) {
iterateResolveTree(tree.children[i], cb);
}
}
export { TreeIndex, getWindowHeight, getWindowWidth, hookSetter, isAncestorRemoved, isBlocked, isIgnored, isTouchEvent, iterateResolveTree, mirror, needCastInSyncMode, on, patch, polyfill, queueToResolveTrees, throttle };