Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/rrweb-snapshot/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ There are several things will be done during rebuild:

#### buildNodeWithSN

`buildNodeWithSN` will build DOM from serialized node and store serialized information in `__sn` property.
`buildNodeWithSN` will build DOM from serialized node and store serialized information in the `mirror.getMeta(node)`.
2 changes: 1 addition & 1 deletion packages/rrweb-snapshot/src/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -892,7 +892,7 @@ function addParent(obj: Stylesheet, parent?: Stylesheet) {
addParent(v, childParent);
});
} else if (value && typeof value === 'object') {
addParent((value as unknown) as Stylesheet, childParent);
addParent(value as Stylesheet, childParent);
}
}

Expand Down
69 changes: 38 additions & 31 deletions packages/rrweb-snapshot/src/rebuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,9 @@ import {
NodeType,
tagMap,
elementNode,
idNodeMap,
INode,
BuildCache,
} from './types';
import { isElement } from './utils';
import { isElement, Mirror } from './utils';

const tagMap: tagMap = {
script: 'noscript',
Expand Down Expand Up @@ -215,7 +213,10 @@ function buildNode(
n.attributes.rr_dataURL
) {
// backup original img srcset
node.setAttribute('rrweb-original-srcset', n.attributes.srcset as string);
node.setAttribute(
'rrweb-original-srcset',
n.attributes.srcset as string,
);
} else {
node.setAttribute(name, value);
}
Expand Down Expand Up @@ -307,16 +308,16 @@ export function buildNodeWithSN(
n: serializedNodeWithId,
options: {
doc: Document;
map: idNodeMap;
mirror: Mirror;
skipChild?: boolean;
hackCss: boolean;
afterAppend?: (n: INode) => unknown;
afterAppend?: (n: Node) => unknown;
cache: BuildCache;
},
): INode | null {
): Node | null {
const {
doc,
map,
mirror,
skipChild = false,
hackCss = true,
afterAppend,
Expand All @@ -328,7 +329,7 @@ export function buildNodeWithSN(
}
if (n.rootId) {
console.assert(
((map[n.rootId] as unknown) as Document) === doc,
(mirror.getNode(n.rootId) as Document) === doc,
'Target document should has the same root id.',
);
}
Expand Down Expand Up @@ -362,8 +363,7 @@ export function buildNodeWithSN(
node = doc;
}

(node as INode).__sn = n;
map[n.id] = node as INode;
mirror.add(node, n);

if (
(n.type === NodeType.Document || n.type === NodeType.Element) &&
Expand All @@ -372,7 +372,7 @@ export function buildNodeWithSN(
for (const childN of n.childNodes) {
const childNode = buildNodeWithSN(childN, {
doc,
map,
mirror,
skipChild: false,
hackCss,
afterAppend,
Expand All @@ -394,27 +394,27 @@ export function buildNodeWithSN(
}
}

return node as INode;
return node;
}

function visit(idNodeMap: idNodeMap, onVisit: (node: INode) => void) {
function walk(node: INode) {
function visit(mirror: Mirror, onVisit: (node: Node) => void) {
function walk(node: Node) {
onVisit(node);
}

for (const key in idNodeMap) {
if (idNodeMap[key]) {
walk(idNodeMap[key]);
for (const id of mirror.getIds()) {
if (mirror.has(id)) {
walk(mirror.getNode(id)!);
}
}
}

function handleScroll(node: INode) {
const n = node.__sn;
if (n.type !== NodeType.Element) {
function handleScroll(node: Node, mirror: Mirror) {
const n = mirror.getMeta(node);
if (n?.type !== NodeType.Element) {
return;
}
const el = (node as Node) as HTMLElement;
const el = node as HTMLElement;
for (const name in n.attributes) {
if (!(n.attributes.hasOwnProperty(name) && name.startsWith('rr_'))) {
continue;
Expand All @@ -433,29 +433,36 @@ function rebuild(
n: serializedNodeWithId,
options: {
doc: Document;
onVisit?: (node: INode) => unknown;
onVisit?: (node: Node) => unknown;
hackCss?: boolean;
afterAppend?: (n: INode) => unknown;
afterAppend?: (n: Node) => unknown;
cache: BuildCache;
mirror: Mirror;
},
): [Node | null, idNodeMap] {
const { doc, onVisit, hackCss = true, afterAppend, cache } = options;
const idNodeMap: idNodeMap = {};
): Node | null {
const {
doc,
onVisit,
hackCss = true,
afterAppend,
cache,
mirror = new Mirror(),
} = options;
const node = buildNodeWithSN(n, {
doc,
map: idNodeMap,
mirror,
skipChild: false,
hackCss,
afterAppend,
cache,
});
visit(idNodeMap, (visitedNode) => {
visit(mirror, (visitedNode) => {
if (onVisit) {
onVisit(visitedNode);
}
handleScroll(visitedNode);
handleScroll(visitedNode, mirror);
});
return [node, idNodeMap];
return node;
}

export default rebuild;
Loading