UNPKG

@xysfe/memento-core

Version:

record and replay the web

482 lines (479 loc) 17.5 kB
import { __values } from '../node_modules/tslib/tslib.es6.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 || !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) { if (!(name in source)) { return function () { }; } var original = source[name]; var wrapped = replacement(original); if (typeof wrapped === 'function') { try { wrapped.prototype = wrapped.prototype || {}; Object.defineProperties(wrapped, { __memento_original__: { enumerable: false, value: original, }, }); } catch (_a) { } } source[name] = wrapped; return function () { source[name] = original; }; } 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, blockElements) { var e_1, _a; 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 if (node.classList && !!(node.classList)) { node.classList.forEach(function (className) { if (blockClass.test(className)) { needBlock_1 = true; } }); } if (!needBlock_1 && node.tagName && blockElements) { try { for (var blockElements_1 = __values(blockElements), blockElements_1_1 = blockElements_1.next(); !blockElements_1_1.done; blockElements_1_1 = blockElements_1.next()) { var blockElement = blockElements_1_1.value; if (blockElement.tagName === node.tagName.toLowerCase()) { needBlock_1 = true; break; } } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (blockElements_1_1 && !blockElements_1_1.done && (_a = blockElements_1.return)) _a.call(blockElements_1); } finally { if (e_1) throw e_1.error; } } } return needBlock_1 || isBlocked(node.parentNode, blockClass, blockElements); } if (node.nodeType === node.TEXT_NODE) { return isBlocked(node.parentNode, blockClass, blockElements); } return isBlocked(node.parentNode, blockClass, blockElements); } 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() { if ('NodeList' in window && !NodeList.prototype.forEach) { NodeList.prototype.forEach = Array.prototype .forEach; } } function dateFormat(date, fmt) { var o = { 'M+': date.getMonth() + 1, 'd+': date.getDate(), 'h+': date.getHours(), 'm+': date.getMinutes(), 's+': date.getSeconds(), 'q+': Math.floor((date.getMonth() + 3) / 3), 'S': date.getMilliseconds(), }; if (/(y+)/.test(fmt)) { fmt = fmt.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length)); } for (var k in o) { if (new RegExp('(' + k + ')').test(fmt)) { fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length))); } } return fmt; } function needCastInSyncMode(event) { switch (event.type) { case EventType.DomContentLoaded: case EventType.Load: case EventType.PageChange: 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) { return 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_2, _a, e_3, _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_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (_e && !_e.done && (_a = _d.return)) _a.call(_d); } finally { if (e_2) throw e_2.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_3_1) { e_3 = { error: e_3_1 }; } finally { try { if (_g && !_g.done && (_b = _f.return)) _b.call(_f); } finally { if (e_3) throw e_3.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 isNumber(value) { return Object.prototype.toString.call(value) == '[object Number]'; } function isString(value) { return Object.prototype.toString.call(value) == '[object String]'; } function isArray(value) { return Object.prototype.toString.call(value) == '[object Array]'; } function isBoolean(value) { return Object.prototype.toString.call(value) == '[object Boolean]'; } function isUndefined(value) { return value === undefined; } function isNull(value) { return value === null; } function isSymbol(value) { return Object.prototype.toString.call(value) == '[object Symbol]'; } function isObject(value) { return (Object.prototype.toString.call(value) == '[object Object]' || (!isNumber(value) && !isString(value) && !isBoolean(value) && !isArray(value) && !isNull(value) && !isFunction(value) && !isUndefined(value) && !isSymbol(value))); } function isFunction(value) { return Object.prototype.toString.call(value) == '[object Function]'; } function isElement(value) { return (typeof HTMLElement === 'object' ? value instanceof HTMLElement : value && typeof value === "object" && value !== null && value.nodeType === 1 && typeof value.nodeName === "string"); } function isWindow(value) { var toString = Object.prototype.toString.call(value); return toString == '[object global]' || toString == '[object Window]' || toString == '[object DOMWindow]'; } function isPlainObject(obj) { var hasOwn = Object.prototype.hasOwnProperty; if (!obj || typeof obj !== 'object' || obj.nodeType || isWindow(obj)) { return false; } try { if (obj.constructor && !hasOwn.call(obj, 'constructor') && !hasOwn.call(obj.constructor.prototype, 'isPrototypeOf')) { return false; } } catch (e) { return false; } var key; for (key in obj) { } return key === undefined || hasOwn.call(obj, key); } function getBaseDimension(node, rootIframe) { var _a, _b; var frameElement = (_b = (_a = node.ownerDocument) === null || _a === void 0 ? void 0 : _a.defaultView) === null || _b === void 0 ? void 0 : _b.frameElement; if (!frameElement || frameElement === rootIframe) { return { x: 0, y: 0, relativeScale: 1, absoluteScale: 1, }; } var frameDimension = frameElement.getBoundingClientRect(); var frameBaseDimension = getBaseDimension(frameElement, rootIframe); var relativeScale = frameDimension.height / frameElement.clientHeight; return { x: frameDimension.x * frameBaseDimension.relativeScale + frameBaseDimension.x, y: frameDimension.y * frameBaseDimension.relativeScale + frameBaseDimension.y, relativeScale: relativeScale, absoluteScale: frameBaseDimension.absoluteScale * relativeScale, }; } export { TreeIndex, dateFormat, getBaseDimension, getWindowHeight, getWindowWidth, hookSetter, isAncestorRemoved, isArray, isBlocked, isBoolean, isElement, isFunction, isNull, isNumber, isObject, isPlainObject, isString, isSymbol, isTouchEvent, isUndefined, isWindow, mirror, needCastInSyncMode, on, patch, polyfill, throttle };