From 5697c689d9835147dc06061c7c1b350d55548e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Tue, 21 May 2019 11:55:43 +0200 Subject: [PATCH] reuse serialized nodes ids (#12) * reuse serialized nodes ids With this patch, each DOM node keeps its id during its existence. This allows to apply RRWeb events to previous snapshots if needed. `resetId` has been removed because it loses its meaning: calling it would not reset the existing nodes ids anymore, only the new ones. Since we don't reset the id anymore, we may exhaust the available ids quicker, but Number.MAX_SAFE_INTEGER (2 ** 53 - 1) is pretty large, so I doubt this'll cause any problem. * improv TS typing The `nAsINode` variable was not very elegant. Simplify this by removing the cast, and make the INode interface compatible with Node. * update typings --- src/index.ts | 4 ++-- src/snapshot.ts | 20 ++++++++++---------- typings/index.d.ts | 4 ++-- typings/snapshot.d.ts | 5 ++--- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index f3238ea2..5b2b0b9f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ -import snapshot, { serializeNodeWithId, resetId } from './snapshot'; +import snapshot, { serializeNodeWithId } from './snapshot'; import rebuild, { buildNodeWithSN } from './rebuild'; export * from './types'; -export { snapshot, serializeNodeWithId, resetId, rebuild, buildNodeWithSN }; +export { snapshot, serializeNodeWithId, rebuild, buildNodeWithSN }; diff --git a/src/snapshot.ts b/src/snapshot.ts index dd2a5447..2c0e170e 100644 --- a/src/snapshot.ts +++ b/src/snapshot.ts @@ -13,10 +13,6 @@ function genId(): number { return _id++; } -export function resetId() { - _id = 1; -} - function getCssRulesString(s: CSSStyleSheet): string | null { try { const rules = s.rules || s.cssRules; @@ -239,7 +235,7 @@ function serializeNode( } export function serializeNodeWithId( - n: Node, + n: Node | INode, doc: Document, map: idNodeMap, blockClass: string | RegExp, @@ -252,11 +248,16 @@ export function serializeNodeWithId( console.warn(n, 'not serialized'); return null; } - const serializedNode = Object.assign(_serializedNode, { - id: genId(), - }); + let id + // Try to reuse the previous id + if ('__sn' in n) { + id = n.__sn.id + } else { + id = genId() + } + const serializedNode = Object.assign(_serializedNode, { id }); (n as INode).__sn = serializedNode; - map[serializedNode.id] = n as INode; + map[id] = (n as INode); let recordChild = !skipChild; if (serializedNode.type === NodeType.Element) { recordChild = recordChild && !serializedNode.needBlock; @@ -290,7 +291,6 @@ function snapshot( blockClass: string | RegExp = 'rr-block', inlineStylesheet = true, ): [serializedNodeWithId | null, idNodeMap] { - resetId(); const idNodeMap: idNodeMap = {}; return [ serializeNodeWithId(n, n, idNodeMap, blockClass, false, inlineStylesheet), diff --git a/typings/index.d.ts b/typings/index.d.ts index 60e49702..87f610a3 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1,4 +1,4 @@ -import snapshot, { serializeNodeWithId, resetId } from './snapshot'; +import snapshot, { serializeNodeWithId } from './snapshot'; import rebuild, { buildNodeWithSN } from './rebuild'; export * from './types'; -export { snapshot, serializeNodeWithId, resetId, rebuild, buildNodeWithSN }; +export { snapshot, serializeNodeWithId, rebuild, buildNodeWithSN }; diff --git a/typings/snapshot.d.ts b/typings/snapshot.d.ts index 61ed5163..e8605417 100644 --- a/typings/snapshot.d.ts +++ b/typings/snapshot.d.ts @@ -1,6 +1,5 @@ -import { serializedNodeWithId, idNodeMap } from './types'; -export declare function resetId(): void; +import { serializedNodeWithId, INode, idNodeMap } from './types'; export declare function absoluteToStylesheet(cssText: string, href: string): string; -export declare function serializeNodeWithId(n: Node, doc: Document, map: idNodeMap, blockClass: string | RegExp, skipChild?: boolean, inlineStylesheet?: boolean): serializedNodeWithId | null; +export declare function serializeNodeWithId(n: Node | INode, doc: Document, map: idNodeMap, blockClass: string | RegExp, skipChild?: boolean, inlineStylesheet?: boolean): serializedNodeWithId | null; declare function snapshot(n: Document, blockClass?: string | RegExp, inlineStylesheet?: boolean): [serializedNodeWithId | null, idNodeMap]; export default snapshot;