Skip to content

Commit 8ed106d

Browse files
authored
Fix: Add null check for cloneOwnerNode in serializeCSSOM (#2094)
- Adds null check before calling styleSheetFromNode() to prevent 'Cannot read properties of null (reading sheet)' error - Skips stylesheets when cloneOwnerNode is not found in cloned DOM - Adds test case to verify the fix handles missing elements gracefully Fixes: PER-6656
1 parent c16b5a6 commit 8ed106d

File tree

2 files changed

+35
-0
lines changed

2 files changed

+35
-0
lines changed

packages/dom/src/serialize-cssom.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ export function serializeCSSOM(ctx) {
6161
styleId = styleSheet.ownerNode.getAttribute('data-percy-element-id');
6262
if (!styleId && ignoreStyleSheetSerializationErrors) continue;
6363
cloneOwnerNode = clone.querySelector(`[data-percy-element-id="${styleId}"]`);
64+
if (!cloneOwnerNode) continue; // Skip if element not found in clone
6465
if (styleSheetsMatch(styleSheet, styleSheetFromNode(cloneOwnerNode))) continue;
6566
let style = document.createElement('style');
6667

packages/dom/test/serialize-css.test.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,5 +425,39 @@ describe('serializeCSSOM', () => {
425425
document.head.removeChild(linkElement1);
426426
URL.revokeObjectURL(blobUrl1);
427427
});
428+
429+
it('skips stylesheet when cloneOwnerNode is not found in clone', () => {
430+
withExample('<div class="box"></div>');
431+
withCSSOM('.box { height: 500px; }');
432+
433+
const sheet = document.styleSheets[0];
434+
const owner = sheet.ownerNode;
435+
owner.setAttribute('data-percy-element-id', 'test-id');
436+
437+
// Create a clone without the matching element
438+
const clone = document.createDocumentFragment();
439+
const cloneBody = document.createElement('body');
440+
clone.appendChild(cloneBody);
441+
442+
const resources = new Set();
443+
const cache = new Map();
444+
const warnings = new Set();
445+
446+
// Should not throw when element is missing from clone
447+
expect(() => serializeCSSOM({ dom: document, clone, resources, cache, warnings })).not.toThrow();
448+
449+
// Verify no style element was added since the owner wasn't found
450+
let found = false;
451+
for (let node of clone.childNodes) {
452+
if (node.querySelectorAll) {
453+
const serializedStyles = node.querySelectorAll('[data-percy-cssom-serialized]');
454+
if (serializedStyles.length > 0) {
455+
found = true;
456+
break;
457+
}
458+
}
459+
}
460+
expect(found).toBe(false);
461+
});
428462
});
429463
});

0 commit comments

Comments
 (0)