Skip to content

Commit

Permalink
feat(snapshots): switch MutationObserver to only observer attributes (#…
Browse files Browse the repository at this point in the history
…5220)

Everything but attributes in the light dom is manually compared during
DOM traversal, for example child nodes or scroll offset.

This way we get a bullet-proof solution that works with input values,
scroll offsets, shadow dom and anything else web comes up with.

We also restore scroll only on the document scrolling element, for
performance reasons. We should figure out the story around scrolling.

Changes stationary snapshots from ~0.5ms to ~2.5ms due to DOM traversal.
  • Loading branch information
dgozman committed Feb 1, 2021
1 parent bf8c30a commit a9de3d8
Show file tree
Hide file tree
Showing 3 changed files with 134 additions and 115 deletions.
13 changes: 10 additions & 3 deletions src/cli/traceViewer/snapshotServer.ts
Expand Up @@ -203,6 +203,13 @@ export class SnapshotServer {
}

const autoClosing = new Set(['AREA', 'BASE', 'BR', 'COL', 'COMMAND', 'EMBED', 'HR', 'IMG', 'INPUT', 'KEYGEN', 'LINK', 'MENUITEM', 'META', 'PARAM', 'SOURCE', 'TRACK', 'WBR']);
const escaped = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', '\'': '&#39;' };
function escapeAttribute(s: string): string {
return s.replace(/[&<>"']/ug, char => (escaped as any)[char]);
}
function escapeText(s: string): string {
return s.replace(/[&<]/ug, char => (escaped as any)[char]);
}

function snapshotNodes(snapshot: trace.FrameSnapshot): NodeSnapshot[] {
if (!(snapshot as any)._nodes) {
Expand All @@ -211,9 +218,9 @@ export class SnapshotServer {
if (typeof n === 'string') {
nodes.push(n);
} else if (typeof n[0] === 'string') {
nodes.push(n);
for (let i = 2; i < n.length; i++)
visit(n[i]);
nodes.push(n);
}
};
visit(snapshot.html);
Expand All @@ -226,7 +233,7 @@ export class SnapshotServer {
const visit = (n: trace.NodeSnapshot, snapshotIndex: number): string => {
// Text node.
if (typeof n === 'string')
return n;
return escapeText(n);

if (!(n as any)._string) {
if (Array.isArray(n[0])) {
Expand All @@ -243,7 +250,7 @@ export class SnapshotServer {
const builder: string[] = [];
builder.push('<', n[0]);
for (const [attr, value] of Object.entries(n[1] || {}))
builder.push(' ', attr, '="', value, '"');
builder.push(' ', attr, '="', escapeAttribute(value), '"');
builder.push('>');
for (let i = 2; i < n.length; i++)
builder.push(visit(n[i], snapshotIndex));
Expand Down
1 change: 1 addition & 0 deletions src/trace/snapshotter.ts
Expand Up @@ -62,6 +62,7 @@ export class Snapshotter {
];
this._context.exposeBinding(kSnapshotBinding, false, (source, data: SnapshotData) => {
const snapshot: FrameSnapshot = {
doctype: data.doctype,
html: data.html,
viewport: data.viewport,
resourceOverrides: [],
Expand Down

0 comments on commit a9de3d8

Please sign in to comment.