Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/dom/src/clone-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,13 @@ export function getOuterHTML(docElement, { shadowRootElements, forceShadowAsLigh
if (forceShadowAsLightDOM) {
return docElement.outerHTML;
}
// With no shadow roots to embed, the getHTML()+textContent=''+outerHTML
// .replace() reassembly below just reproduces `docElement.outerHTML` while
// allocating a full-size intermediate string + replace copy. Skip it to cut
// this step's transient footprint (GC pressure) on heavy pages.
if (!shadowRootElements || shadowRootElements.length === 0) {
return docElement.outerHTML;
}
/* istanbul ignore else if: Only triggered in chrome <= 128 and tests runs on latest */
if (docElement.getHTML) {
// All major browsers in latest versions supports getHTML API to get serialized DOM
Expand Down
14 changes: 10 additions & 4 deletions packages/dom/src/serialize-dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ function doctype(dom) {
return `<!DOCTYPE ${name}${deprecated}>`;
}

// Un-mangle both serialization markers in one pass instead of two:
// <data-percy-custom-element-x> -> <x>
// ` data-percy-serialized-attribute-y=` -> ` y=`
// Serialized HTML can reach tens of MB and each .replace() copies the whole
// string, so folding two passes into one halves the large-string churn (GC
// pressure) per snapshot. Groups: g1 = `<`/`</` (tag); g2/g3 = space + attr.
const PERCY_MARKER_RE = /(<\/?)data-percy-custom-element-|( )data-percy-serialized-attribute-(\w+?)=/gi;

// Serializes and returns the cloned DOM as an HTML string
function serializeHTML(ctx) {
let html = getOuterHTML(ctx.clone.documentElement, { shadowRootElements: ctx.shadowRootElements, forceShadowAsLightDOM: ctx.forceShadowAsLightDOM });
// this is replacing serialized data tag with real tag
html = html.replace(/(<\/?)data-percy-custom-element-/g, '$1');
// replace serialized data attributes with real attributes
html = html.replace(/ data-percy-serialized-attribute-(\w+?)=/ig, ' $1=');
html = html.replace(PERCY_MARKER_RE, (_match, tagPrefix, attrSpace, attrName) =>
tagPrefix !== undefined ? tagPrefix : `${attrSpace}${attrName}=`);
// include the doctype with the html string
return doctype(ctx.dom) + html;
}
Expand Down
Loading