Skip to content

Commit c75bdde

Browse files
dgozmanpavelfeldman
authored andcommitted
cherry-pick(9731): fix(snapshot): empty adopted stylesheet should not prevent node refs
1 parent 0f38535 commit c75bdde

File tree

2 files changed

+33
-3
lines changed

2 files changed

+33
-3
lines changed

packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,14 +145,15 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
145145
this._staleStyleSheets.add(sheet);
146146
}
147147

148-
private _updateStyleElementStyleSheetTextIfNeeded(sheet: CSSStyleSheet): string | undefined {
148+
private _updateStyleElementStyleSheetTextIfNeeded(sheet: CSSStyleSheet, forceText?: boolean): string | undefined {
149149
const data = ensureCachedData(sheet);
150-
if (this._staleStyleSheets.has(sheet)) {
150+
if (this._staleStyleSheets.has(sheet) || (forceText && data.cssText === undefined)) {
151151
this._staleStyleSheets.delete(sheet);
152152
try {
153153
data.cssText = this._getSheetText(sheet);
154154
} catch (e) {
155155
// Sometimes we cannot access cross-origin stylesheets.
156+
data.cssText = '';
156157
}
157158
}
158159
return data.cssText;
@@ -438,7 +439,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
438439
const visitStyleSheet = (sheet: CSSStyleSheet) => {
439440
const data = ensureCachedData(sheet);
440441
const oldCSSText = data.cssText;
441-
const cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet) || '';
442+
const cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet, true /* forceText */)!;
442443
if (cssText === oldCSSText)
443444
return { equals: true, n: [[ snapshotNumber - data.ref![0], data.ref![1] ]] };
444445
data.ref = [snapshotNumber, nodeCounter++];

tests/snapshotter.spec.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,35 @@ it.describe('snapshots', () => {
180180
expect(distillSnapshot(snapshot)).toBe('<BUTTON data="two">Hello</BUTTON>');
181181
}
182182
});
183+
184+
it('empty adopted style sheets should not prevent node refs', async ({ page, toImpl, snapshotter, browserName }) => {
185+
it.skip(browserName !== 'chromium', 'Constructed stylesheets are only in Chromium.');
186+
187+
await page.setContent('<button>Hello</button>');
188+
await page.evaluate(() => {
189+
const sheet = new CSSStyleSheet();
190+
(document as any).adoptedStyleSheets = [sheet];
191+
192+
const sheet2 = new CSSStyleSheet();
193+
for (const element of [document.createElement('div'), document.createElement('span')]) {
194+
const root = element.attachShadow({
195+
mode: 'open'
196+
});
197+
root.append('foo');
198+
(root as any).adoptedStyleSheets = [sheet2];
199+
document.body.appendChild(element);
200+
}
201+
});
202+
203+
const renderer1 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot1');
204+
// Expect some adopted style sheets.
205+
expect(distillSnapshot(renderer1)).toContain('__playwright_style_sheet_');
206+
207+
const renderer2 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot2');
208+
const snapshot2 = renderer2.snapshot();
209+
// Second snapshot should be just a copy of the first one.
210+
expect(snapshot2.html).toEqual([[1, 13]]);
211+
});
183212
});
184213

185214
function distillSnapshot(snapshot, distillTarget = true) {

0 commit comments

Comments
 (0)