Skip to content

Commit

Permalink
Added support for deprecated addRule & removeRule methods (#1515)
Browse files Browse the repository at this point in the history
* Added support for deprecated addRule & removeRule methods

* Respect addRule default value
  • Loading branch information
okejminja committed Jul 23, 2024
1 parent 40bbc25 commit 8059d96
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 0 deletions.
6 changes: 6 additions & 0 deletions .changeset/great-cows-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@rrweb/record": patch
"rrweb": patch
---

Added support for deprecated addRule & removeRule methods
19 changes: 19 additions & 0 deletions packages/rrweb/src/record/observer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -659,6 +659,17 @@ function initStyleSheetObserver(
),
});

// Support for deprecated addRule method
win.CSSStyleSheet.prototype.addRule = function (
this: CSSStyleSheet,
selector: string,
styleBlock: string,
index: number = this.cssRules.length,
) {
const rule = `${selector} { ${styleBlock} }`;
return win.CSSStyleSheet.prototype.insertRule.apply(this, [rule, index]);
};

// eslint-disable-next-line @typescript-eslint/unbound-method
const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
win.CSSStyleSheet.prototype.deleteRule = new Proxy(deleteRule, {
Expand Down Expand Up @@ -688,6 +699,14 @@ function initStyleSheetObserver(
),
});

// Support for deprecated removeRule method
win.CSSStyleSheet.prototype.removeRule = function (
this: CSSStyleSheet,
index: number,
) {
return win.CSSStyleSheet.prototype.deleteRule.apply(this, [index]);
};

let replace: (text: string) => Promise<CSSStyleSheet>;

if (win.CSSStyleSheet.prototype.replace) {
Expand Down
140 changes: 140 additions & 0 deletions packages/rrweb/test/__snapshots__/record.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2196,6 +2196,146 @@ exports[`record > captures stylesheet rules 1`] = `
]"
`;

exports[`record > captures stylesheet rules with deprecated addRule & removeRule properties 1`] = `
"[
{
\\"type\\": 4,
\\"data\\": {
\\"href\\": \\"about:blank\\",
\\"width\\": 1920,
\\"height\\": 1080
}
},
{
\\"type\\": 2,
\\"data\\": {
\\"node\\": {
\\"type\\": 0,
\\"childNodes\\": [
{
\\"type\\": 1,
\\"name\\": \\"html\\",
\\"publicId\\": \\"\\",
\\"systemId\\": \\"\\",
\\"id\\": 2
},
{
\\"type\\": 2,
\\"tagName\\": \\"html\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 2,
\\"tagName\\": \\"head\\",
\\"attributes\\": {},
\\"childNodes\\": [],
\\"id\\": 4
},
{
\\"type\\": 2,
\\"tagName\\": \\"body\\",
\\"attributes\\": {},
\\"childNodes\\": [
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\",
\\"id\\": 6
},
{
\\"type\\": 2,
\\"tagName\\": \\"input\\",
\\"attributes\\": {
\\"type\\": \\"text\\",
\\"size\\": \\"40\\"
},
\\"childNodes\\": [],
\\"id\\": 7
},
{
\\"type\\": 3,
\\"textContent\\": \\"\\\\n \\\\n \\\\n \\",
\\"id\\": 8
}
],
\\"id\\": 5
}
],
\\"id\\": 3
}
],
\\"id\\": 1
},
\\"initialOffset\\": {
\\"left\\": 0,
\\"top\\": 0
}
}
},
{
\\"type\\": 3,
\\"data\\": {
\\"source\\": 0,
\\"texts\\": [],
\\"attributes\\": [],
\\"removes\\": [],
\\"adds\\": [
{
\\"parentId\\": 4,
\\"nextId\\": null,
\\"node\\": {
\\"type\\": 2,
\\"tagName\\": \\"style\\",
\\"attributes\\": {
\\"_cssText\\": \\"body { background: rgb(0, 0, 0); }\\"
},
\\"childNodes\\": [],
\\"id\\": 9
}
}
]
}
},
{
\\"type\\": 3,
\\"data\\": {
\\"source\\": 8,
\\"id\\": 9,
\\"adds\\": [
{
\\"rule\\": \\"body { color: #fff; }\\",
\\"index\\": 1
}
]
}
},
{
\\"type\\": 3,
\\"data\\": {
\\"source\\": 8,
\\"id\\": 9,
\\"removes\\": [
{
\\"index\\": 0
}
]
}
},
{
\\"type\\": 3,
\\"data\\": {
\\"source\\": 8,
\\"id\\": 9,
\\"adds\\": [
{
\\"rule\\": \\"body { color: #ccc; }\\",
\\"index\\": 1
}
]
}
}
]"
`;

exports[`record > captures stylesheets in iframes with \`blob:\` url 1`] = `
"[
{
Expand Down
64 changes: 64 additions & 0 deletions packages/rrweb/test/record.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ describe('record', function (this: ISuite) {
// begin: pre-serialization
const ruleIdx0 = styleSheet.insertRule('body { background: #000; }');
const ruleIdx1 = styleSheet.insertRule('body { background: #111; }');

styleSheet.deleteRule(ruleIdx1);
// end: pre-serialization
setTimeout(() => {
Expand Down Expand Up @@ -328,6 +329,69 @@ describe('record', function (this: ISuite) {
rule: 'body { color: #fff; }',
},
]);
expect((addRules[1].data as styleSheetRuleData).adds).toEqual([
{
rule: 'body { color: #ccc; }',
},
]);
expect(removeRuleCount).toEqual(1);
await assertSnapshot(ctx.events);
});

it('captures stylesheet rules with deprecated addRule & removeRule properties', async () => {
await ctx.page.evaluate(() => {
const { record } = (window as unknown as IWindow).rrweb;

record({
emit: (window as unknown as IWindow).emit,
});

const styleElement = document.createElement('style');
document.head.appendChild(styleElement);

const styleSheet = <CSSStyleSheet>styleElement.sheet;
// begin: pre-serialization
const ruleIdx0 = styleSheet.addRule('body', 'background: #000;');
const ruleIdx1 = styleSheet.addRule('body', 'background: #111;');

styleSheet.removeRule(ruleIdx1);
// end: pre-serialization
setTimeout(() => {
styleSheet.addRule('body', 'color: #fff;');
}, 0);
setTimeout(() => {
styleSheet.removeRule(ruleIdx0);
}, 5);
setTimeout(() => {
styleSheet.addRule('body', 'color: #ccc;');
}, 10);
});
await ctx.page.waitForTimeout(50);
const styleSheetRuleEvents = ctx.events.filter(
(e) =>
e.type === EventType.IncrementalSnapshot &&
e.data.source === IncrementalSource.StyleSheetRule,
);
const addRules = styleSheetRuleEvents.filter((e) =>
Boolean((e.data as styleSheetRuleData).adds),
);
const removeRuleCount = styleSheetRuleEvents.filter((e) =>
Boolean((e.data as styleSheetRuleData).removes),
).length;
// pre-serialization insert/delete should be ignored
expect(addRules.length).toEqual(2);
expect((addRules[0].data as styleSheetRuleData).adds).toEqual([
{
index: 1,
rule: 'body { color: #fff; }',
},
]);
expect((addRules[1].data as styleSheetRuleData).adds).toEqual([
{
index: 1,
rule: 'body { color: #ccc; }',
},
]);
expect(removeRuleCount).toEqual(1);
await assertSnapshot(ctx.events);
});
Expand Down

0 comments on commit 8059d96

Please sign in to comment.