fix(rrdom): Ignore invalid DOM attributes when diffing (#1561)
* fix(rrdom): Ignore invalid DOM attributes when diffing (#213)
We encountered an issue where replays with invalid attributes (e.g.
`@click`) would break rendering the replay after seeking. The exception
bubbles up to
[here](62093d4385/packages/rrweb/src/replay/index.ts (L270-L279)),
which means the replay will continue to play, but the replay mirror will
be incomplete.
Closes https://github.com/getsentry/team-replay/issues/458
* add changeset
This commit is contained in:
5
.changeset/chilled-penguins-sin.md
Normal file
5
.changeset/chilled-penguins-sin.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"rrdom": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Ignore invalid DOM attributes when diffing
|
||||||
@@ -354,7 +354,16 @@ function diffProps(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
} else if (newTree.tagName === 'IFRAME' && name === 'srcdoc') continue;
|
} else if (newTree.tagName === 'IFRAME' && name === 'srcdoc') continue;
|
||||||
else oldTree.setAttribute(name, newValue);
|
else {
|
||||||
|
try {
|
||||||
|
oldTree.setAttribute(name, newValue);
|
||||||
|
} catch (err) {
|
||||||
|
// We want to continue diffing so we quietly catch
|
||||||
|
// this exception. Otherwise, this can throw and bubble up to
|
||||||
|
// the `ReplayerEvents.Flush` listener and break rendering
|
||||||
|
console.warn(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const { name } of Array.from(oldAttributes))
|
for (const { name } of Array.from(oldAttributes))
|
||||||
|
|||||||
@@ -335,6 +335,32 @@ describe('diff algorithm for rrdom', () => {
|
|||||||
expect((node as Node as HTMLElement).className).toBe('node');
|
expect((node as Node as HTMLElement).className).toBe('node');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('ignores invalid attributes', () => {
|
||||||
|
const tagName = 'DIV';
|
||||||
|
const node = document.createElement(tagName);
|
||||||
|
const sn = Object.assign({}, elementSn, {
|
||||||
|
attributes: { '@click': 'foo' },
|
||||||
|
tagName,
|
||||||
|
});
|
||||||
|
mirror.add(node, sn);
|
||||||
|
|
||||||
|
const rrDocument = new RRDocument();
|
||||||
|
const rrNode = rrDocument.createElement(tagName);
|
||||||
|
const sn2 = Object.assign({}, elementSn, {
|
||||||
|
attributes: { '@click': 'foo' },
|
||||||
|
tagName,
|
||||||
|
});
|
||||||
|
rrDocument.mirror.add(rrNode, sn2);
|
||||||
|
|
||||||
|
rrNode.attributes = { id: 'node1', class: 'node', '@click': 'foo' };
|
||||||
|
diff(node, rrNode, replayer);
|
||||||
|
expect((node as Node as HTMLElement).id).toBe('node1');
|
||||||
|
expect((node as Node as HTMLElement).className).toBe('node');
|
||||||
|
expect('@click' in (node as Node as HTMLElement)).toBe(false);
|
||||||
|
expect(warn).toHaveBeenCalledTimes(1);
|
||||||
|
warn.mockClear();
|
||||||
|
});
|
||||||
|
|
||||||
it('can update exist properties', () => {
|
it('can update exist properties', () => {
|
||||||
const tagName = 'DIV';
|
const tagName = 'DIV';
|
||||||
const node = document.createElement(tagName);
|
const node = document.createElement(tagName);
|
||||||
|
|||||||
Reference in New Issue
Block a user