From 8e55c455ff2987a3b5f367f23f48c1f2de74ce45 Mon Sep 17 00:00:00 2001 From: Billy Vong Date: Fri, 13 Sep 2024 05:50:46 -0230 Subject: [PATCH] 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](https://github.com/rrweb-io/rrweb/blob/62093d4385a09eb0980c2ac02d97eea5ce2882be/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 --- .changeset/chilled-penguins-sin.md | 5 +++++ packages/rrdom/src/diff.ts | 11 ++++++++++- packages/rrdom/test/diff.test.ts | 26 ++++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 .changeset/chilled-penguins-sin.md diff --git a/.changeset/chilled-penguins-sin.md b/.changeset/chilled-penguins-sin.md new file mode 100644 index 0000000000..060744a07b --- /dev/null +++ b/.changeset/chilled-penguins-sin.md @@ -0,0 +1,5 @@ +--- +"rrdom": patch +--- + +Ignore invalid DOM attributes when diffing diff --git a/packages/rrdom/src/diff.ts b/packages/rrdom/src/diff.ts index 10acb4f419..5cff5dc724 100644 --- a/packages/rrdom/src/diff.ts +++ b/packages/rrdom/src/diff.ts @@ -354,7 +354,16 @@ function diffProps( } }; } 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)) diff --git a/packages/rrdom/test/diff.test.ts b/packages/rrdom/test/diff.test.ts index ff817a1627..e250ef8f06 100644 --- a/packages/rrdom/test/diff.test.ts +++ b/packages/rrdom/test/diff.test.ts @@ -335,6 +335,32 @@ describe('diff algorithm for rrdom', () => { 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', () => { const tagName = 'DIV'; const node = document.createElement(tagName);