diff --git a/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts b/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts
index 66b3a74aed..31c9712992 100644
--- a/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts
+++ b/packages/playwright-core/src/server/trace/recorder/snapshotterInjected.ts
@@ -145,14 +145,15 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
this._staleStyleSheets.add(sheet);
}
- private _updateStyleElementStyleSheetTextIfNeeded(sheet: CSSStyleSheet): string | undefined {
+ private _updateStyleElementStyleSheetTextIfNeeded(sheet: CSSStyleSheet, forceText?: boolean): string | undefined {
const data = ensureCachedData(sheet);
- if (this._staleStyleSheets.has(sheet)) {
+ if (this._staleStyleSheets.has(sheet) || (forceText && data.cssText === undefined)) {
this._staleStyleSheets.delete(sheet);
try {
data.cssText = this._getSheetText(sheet);
} catch (e) {
// Sometimes we cannot access cross-origin stylesheets.
+ data.cssText = '';
}
}
return data.cssText;
@@ -438,7 +439,7 @@ export function frameSnapshotStreamer(snapshotStreamer: string) {
const visitStyleSheet = (sheet: CSSStyleSheet) => {
const data = ensureCachedData(sheet);
const oldCSSText = data.cssText;
- const cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet) || '';
+ const cssText = this._updateStyleElementStyleSheetTextIfNeeded(sheet, true /* forceText */)!;
if (cssText === oldCSSText)
return { equals: true, n: [[ snapshotNumber - data.ref![0], data.ref![1] ]] };
data.ref = [snapshotNumber, nodeCounter++];
diff --git a/tests/snapshotter.spec.ts b/tests/snapshotter.spec.ts
index 89f8094e02..84edbf08f1 100644
--- a/tests/snapshotter.spec.ts
+++ b/tests/snapshotter.spec.ts
@@ -180,6 +180,35 @@ it.describe('snapshots', () => {
expect(distillSnapshot(snapshot)).toBe('');
}
});
+
+ it('empty adopted style sheets should not prevent node refs', async ({ page, toImpl, snapshotter, browserName }) => {
+ it.skip(browserName !== 'chromium', 'Constructed stylesheets are only in Chromium.');
+
+ await page.setContent('');
+ await page.evaluate(() => {
+ const sheet = new CSSStyleSheet();
+ (document as any).adoptedStyleSheets = [sheet];
+
+ const sheet2 = new CSSStyleSheet();
+ for (const element of [document.createElement('div'), document.createElement('span')]) {
+ const root = element.attachShadow({
+ mode: 'open'
+ });
+ root.append('foo');
+ (root as any).adoptedStyleSheets = [sheet2];
+ document.body.appendChild(element);
+ }
+ });
+
+ const renderer1 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot1');
+ // Expect some adopted style sheets.
+ expect(distillSnapshot(renderer1)).toContain('__playwright_style_sheet_');
+
+ const renderer2 = await snapshotter.captureSnapshot(toImpl(page), 'snapshot2');
+ const snapshot2 = renderer2.snapshot();
+ // Second snapshot should be just a copy of the first one.
+ expect(snapshot2.html).toEqual([[1, 13]]);
+ });
});
function distillSnapshot(snapshot, distillTarget = true) {