diff --git a/__generated/rr/rrweb/rr.js b/__generated/rr/rrweb/rr.js index 22660631b89..097c75d3a43 100644 --- a/__generated/rr/rrweb/rr.js +++ b/__generated/rr/rrweb/rr.js @@ -63,10 +63,12 @@ function getUntaintedPrototype$1(key) { const iframeEl = document.createElement("iframe"); document.body.appendChild(iframeEl); const win = iframeEl.contentWindow; - if (!win) return defaultObj.prototype; + if (!win) + return defaultObj.prototype; const untaintedObject = win[key].prototype; document.body.removeChild(iframeEl); - if (!untaintedObject) return defaultPrototype; + if (!untaintedObject) + return defaultPrototype; return untaintedBasePrototype$1[key] = untaintedObject; } catch { return defaultPrototype; @@ -85,7 +87,8 @@ function getUntaintedAccessor$1(key, instance, accessor) { untaintedPrototype, accessor )) == null ? void 0 : _a2.get; - if (!untaintedAccessor) return instance[accessor]; + if (!untaintedAccessor) + return instance[accessor]; untaintedAccessorCache$1[cacheKey] = untaintedAccessor; return untaintedAccessor.call(instance); } @@ -98,7 +101,8 @@ function getUntaintedMethod$1(key, instance, method) { ); const untaintedPrototype = getUntaintedPrototype$1(key); const untaintedMethod = untaintedPrototype[method]; - if (typeof untaintedMethod !== "function") return instance[method]; + if (typeof untaintedMethod !== "function") + return instance[method]; untaintedMethodCache$1[cacheKey] = untaintedMethod; return untaintedMethod.bind(instance); } @@ -121,14 +125,16 @@ function getRootNode$1(n2) { return getUntaintedMethod$1("Node", n2, "getRootNode")(); } function host$1(n2) { - if (!n2 || !("host" in n2)) return null; + if (!n2 || !("host" in n2)) + return null; return getUntaintedAccessor$1("ShadowRoot", n2, "host"); } function styleSheets$1(n2) { return n2.styleSheets; } function shadowRoot$1(n2) { - if (!n2 || !("shadowRoot" in n2)) return null; + if (!n2 || !("shadowRoot" in n2)) + return null; return getUntaintedAccessor$1("Element", n2, "shadowRoot"); } function querySelector$1(n2, selectors) { @@ -202,13 +208,9 @@ function stringifyStylesheet(s2) { if (!rules2) { return null; } - let sheetHref = s2.href; - if (!sheetHref && s2.ownerNode && s2.ownerNode.ownerDocument) { - sheetHref = s2.ownerNode.ownerDocument.location.href; - } const stringifiedRules = Array.from( rules2, - (rule2) => stringifyRule(rule2, sheetHref) + (rule2) => stringifyRule(rule2, s2.href) ).join(""); return fixBrowserCompatibilityIssuesInCSS(stringifiedRules); } catch (error) { @@ -438,40 +440,6 @@ function absolutifyURLs(cssText, href) { } ); } -function normalizeCssString(cssText) { - return cssText.replace(/(\/\*[^*]*\*\/)|[\s;]/g, ""); -} -function splitCssText(cssText, style) { - const childNodes2 = Array.from(style.childNodes); - const splits = []; - if (childNodes2.length > 1 && cssText && typeof cssText === "string") { - const cssTextNorm = normalizeCssString(cssText); - for (let i2 = 1; i2 < childNodes2.length; i2++) { - if (childNodes2[i2].textContent && typeof childNodes2[i2].textContent === "string") { - const textContentNorm = normalizeCssString(childNodes2[i2].textContent); - for (let j = 3; j < textContentNorm.length; j++) { - const bit = textContentNorm.substring(0, j); - if (cssTextNorm.split(bit).length === 2) { - const splitNorm = cssTextNorm.indexOf(bit); - for (let k = splitNorm; k < cssText.length; k++) { - if (normalizeCssString(cssText.substring(0, k)).length === splitNorm) { - splits.push(cssText.substring(0, k)); - cssText = cssText.substring(k); - break; - } - } - break; - } - } - } - } - } - splits.push(cssText); - return splits; -} -function markCssSplits(cssText, style) { - return splitCssText(cssText, style).join("/* rr_split */"); -} function obfuscateText(text) { text = text.replace(/[^ -~]+/g, ""); text = (text == null ? void 0 : text.split(" ").map((word) => Math.random().toString(20).substring(2, word.length)).join(" ")) || ""; @@ -775,7 +743,6 @@ function serializeNode(n2, options) { recordCanvas, keepIframeSrcFn, newlyAddedElement = false, - cssCaptured = false, privacySetting } = options; const rootId = getRootId(doc, mirror2); @@ -825,8 +792,7 @@ function serializeNode(n2, options) { needsMask, maskTextFn, privacySetting, - rootId, - cssCaptured + rootId }); case n2.CDATA_SECTION_NODE: return { @@ -850,27 +816,36 @@ function getRootId(doc, mirror2) { return docId === 1 ? void 0 : docId; } function serializeTextNode(n2, options) { - var _a2; - const { needsMask, maskTextFn, privacySetting, rootId, cssCaptured } = options; + var _a2, _b; + const { needsMask, maskTextFn, privacySetting, rootId } = options; const parent = index$1.parentNode(n2); const parentTagName = parent && parent.tagName; - let textContent2 = ""; + let text = index$1.textContent(n2); const isStyle = parentTagName === "STYLE" ? true : void 0; const isScript = parentTagName === "SCRIPT" ? true : void 0; - if (isScript) { - textContent2 = "SCRIPT_PLACEHOLDER"; - } else if (!cssCaptured) { - textContent2 = index$1.textContent(n2); - if (isStyle && textContent2) { - textContent2 = absolutifyURLs(textContent2, getHref(options.doc)); + if (isStyle && text) { + try { + if (n2.nextSibling || n2.previousSibling) { + } else if ((_a2 = parent.sheet) == null ? void 0 : _a2.cssRules) { + text = stringifyStylesheet(parent.sheet); + } + } catch (err) { + console.warn( + `Cannot get CSS styles from text's parentNode. Error: ${err}`, + n2 + ); } + text = absolutifyURLs(text, getHref(options.doc)); + } + if (isScript) { + text = "SCRIPT_PLACEHOLDER"; } - if (!isStyle && !isScript && textContent2 && needsMask) { - textContent2 = maskTextFn ? maskTextFn(textContent2, index$1.parentElement(n2)) : textContent2.replace(/[\S]/g, "*"); + if (!isStyle && !isScript && text && needsMask) { + text = maskTextFn ? maskTextFn(text, index$1.parentElement(n2)) : text.replace(/[\S]/g, "*"); } const enableStrictPrivacy = privacySetting === "strict"; - const highlightOverwriteRecord = (_a2 = n2.parentElement) == null ? void 0 : _a2.getAttribute("data-hl-record"); - const obfuscateDefaultPrivacy = privacySetting === "default" && shouldObfuscateTextByDefault(textContent2); + const highlightOverwriteRecord = (_b = n2.parentElement) == null ? void 0 : _b.getAttribute("data-hl-record"); + const obfuscateDefaultPrivacy = privacySetting === "default" && shouldObfuscateTextByDefault(text); if ((enableStrictPrivacy || obfuscateDefaultPrivacy) && !highlightOverwriteRecord && parentTagName) { const IGNORE_TAG_NAMES = /* @__PURE__ */ new Set([ "HEAD", @@ -881,13 +856,14 @@ function serializeTextNode(n2, options) { "BODY", "NOSCRIPT" ]); - if (!IGNORE_TAG_NAMES.has(parentTagName) && textContent2) { - textContent2 = obfuscateText(textContent2); + if (!IGNORE_TAG_NAMES.has(parentTagName) && text) { + text = obfuscateText(text); } } return { type: NodeType$2.Text, - textContent: textContent2 || "", + textContent: text || "", + isStyle, rootId }; } @@ -939,14 +915,12 @@ function serializeElementNode(n2, options) { attributes._cssText = cssText; } } - if (tagName === "style" && n2.sheet) { - let cssText = stringifyStylesheet( + if (tagName === "style" && n2.sheet && // TODO: Currently we only try to get dynamic stylesheet when it is an empty style element + !(n2.innerText || index$1.textContent(n2) || "").trim().length) { + const cssText = stringifyStylesheet( n2.sheet ); if (cssText) { - if (n2.childNodes.length > 1) { - cssText = markCssSplits(cssText, n2); - } attributes._cssText = cssText; } } @@ -1172,7 +1146,6 @@ function serializeNodeWithId(n2, options) { stylesheetLoadTimeout = 5e3, keepIframeSrcFn = () => false, newlyAddedElement = false, - cssCaptured = false, privacySetting } = options; let { needsMask } = options; @@ -1202,7 +1175,6 @@ function serializeNodeWithId(n2, options) { recordCanvas, keepIframeSrcFn, newlyAddedElement, - cssCaptured, privacySetting }); if (!_serializedNode) { @@ -1212,7 +1184,7 @@ function serializeNodeWithId(n2, options) { let id; if (mirror2.hasNode(n2)) { id = mirror2.getId(n2); - } else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || !preserveWhiteSpace && _serializedNode.type === NodeType$2.Text && !_serializedNode.textContent.replace(/^\s+|\s+$/gm, "").length) { + } else if (slimDOMExcluded(_serializedNode, slimDOMOptions) || !preserveWhiteSpace && _serializedNode.type === NodeType$2.Text && !_serializedNode.isStyle && !_serializedNode.textContent.replace(/^\s+|\s+$/gm, "").length) { id = IGNORED_NODE; } else { id = genId(); @@ -1271,14 +1243,10 @@ function serializeNodeWithId(n2, options) { onStylesheetLoad, stylesheetLoadTimeout, keepIframeSrcFn, - cssCaptured: false, privacySetting: overwrittenPrivacySetting }; if (serializedNode.type === NodeType$2.Element && serializedNode.tagName === "textarea" && serializedNode.attributes.value !== void 0) ; else { - if (serializedNode.type === NodeType$2.Element && serializedNode.attributes._cssText !== void 0 && typeof serializedNode.attributes._cssText === "string") { - bypassOptions.cssCaptured = true; - } for (const childN of Array.from(index$1.childNodes(n2))) { const serializedChildNode = serializeNodeWithId(childN, bypassOptions); if (serializedChildNode) { @@ -5157,40 +5125,6 @@ function createCache() { stylesWithHoverClass }; } -function applyCssSplits(n2, cssText, hackCss, cache) { - const childTextNodes = []; - for (const scn of n2.childNodes) { - if (scn.type === NodeType$2.Text) { - childTextNodes.push(scn); - } - } - const cssTextSplits = cssText.split("/* rr_split */"); - while (cssTextSplits.length > 1 && cssTextSplits.length > childTextNodes.length) { - cssTextSplits.splice(-2, 2, cssTextSplits.slice(-2).join("")); - } - for (let i2 = 0; i2 < childTextNodes.length; i2++) { - const childTextNode = childTextNodes[i2]; - const cssTextSection = cssTextSplits[i2]; - if (childTextNode && cssTextSection) { - try { - childTextNode.textContent = hackCss ? adaptCssForReplay(cssTextSection, cache) : cssTextSection; - } catch (err) { - console.warn(`Highlight failed to set rrweb css ${err}`); - } - } - } -} -function buildStyleNode(n2, styleEl, cssText, options) { - const { doc, hackCss, cache } = options; - if (n2.childNodes.length) { - applyCssSplits(n2, cssText, hackCss, cache); - } else { - if (hackCss) { - cssText = adaptCssForReplay(cssText, cache); - } - styleEl.appendChild(doc.createTextNode(cssText)); - } -} function buildNode(n2, options) { var _a2; const { doc, hackCss, cache } = options; @@ -5239,11 +5173,12 @@ function buildNode(n2, options) { specialAttributes[name] = value; continue; } - if (typeof value !== "string") ; - else if (tagName === "style" && name === "_cssText") { - buildStyleNode(n2, node2, value, options); - continue; - } else if (tagName === "textarea" && name === "value") { + const isTextarea = tagName === "textarea" && name === "value"; + const isRemoteOrDynamicCss = tagName === "style" && name === "_cssText"; + if (isRemoteOrDynamicCss && hackCss && typeof value === "string") { + value = adaptCssForReplay(value, cache); + } + if ((isTextarea || isRemoteOrDynamicCss) && typeof value === "string") { node2.appendChild(doc.createTextNode(value)); try { n2.childNodes = []; @@ -5342,10 +5277,9 @@ function buildNode(n2, options) { return node2; } case NodeType$2.Text: - if (n2.isStyle && hackCss) { - return doc.createTextNode(adaptCssForReplay(n2.textContent, cache)); - } - return doc.createTextNode(n2.textContent); + return doc.createTextNode( + n2.isStyle && hackCss ? adaptCssForReplay(n2.textContent, cache) : n2.textContent + ); case NodeType$2.CDATA: return doc.createCDATASection(n2.textContent); case NodeType$2.Comment: @@ -10449,10 +10383,12 @@ function getUntaintedPrototype(key) { const iframeEl = document.createElement("iframe"); document.body.appendChild(iframeEl); const win = iframeEl.contentWindow; - if (!win) return defaultObj.prototype; + if (!win) + return defaultObj.prototype; const untaintedObject = win[key].prototype; document.body.removeChild(iframeEl); - if (!untaintedObject) return defaultPrototype; + if (!untaintedObject) + return defaultPrototype; return untaintedBasePrototype[key] = untaintedObject; } catch { return defaultPrototype; @@ -10471,7 +10407,8 @@ function getUntaintedAccessor(key, instance, accessor) { untaintedPrototype, accessor )) == null ? void 0 : _a2.get; - if (!untaintedAccessor) return instance[accessor]; + if (!untaintedAccessor) + return instance[accessor]; untaintedAccessorCache[cacheKey] = untaintedAccessor; return untaintedAccessor.call(instance); } @@ -10484,7 +10421,8 @@ function getUntaintedMethod(key, instance, method) { ); const untaintedPrototype = getUntaintedPrototype(key); const untaintedMethod = untaintedPrototype[method]; - if (typeof untaintedMethod !== "function") return instance[method]; + if (typeof untaintedMethod !== "function") + return instance[method]; untaintedMethodCache[cacheKey] = untaintedMethod; return untaintedMethod.bind(instance); } @@ -10507,14 +10445,16 @@ function getRootNode(n2) { return getUntaintedMethod("Node", n2, "getRootNode")(); } function host(n2) { - if (!n2 || !("host" in n2)) return null; + if (!n2 || !("host" in n2)) + return null; return getUntaintedAccessor("ShadowRoot", n2, "host"); } function styleSheets(n2) { return n2.styleSheets; } function shadowRoot(n2) { - if (!n2 || !("shadowRoot" in n2)) return null; + if (!n2 || !("shadowRoot" in n2)) + return null; return getUntaintedAccessor("Element", n2, "shadowRoot"); } function querySelector(n2, selectors) { @@ -11174,18 +11114,9 @@ var MutationBuffer = class { }; const pushAdd = (n2) => { const parent = index.parentNode(n2); - if (!parent || !inDom(n2)) { + if (!parent || !inDom(n2) || parent.tagName === "TEXTAREA") { return; } - let cssCaptured = false; - if (n2.nodeType === Node.TEXT_NODE) { - const parentTag = parent.tagName; - if (parentTag === "TEXTAREA") { - return; - } else if (parentTag === "STYLE" && this.addedSet.has(parent)) { - cssCaptured = true; - } - } const parentId = isShadowRoot(parent) ? this.mirror.getId(getShadowHost(n2)) : this.mirror.getId(parent); const nextId = getNextId(n2); if (parentId === -1 || nextId === -1) { @@ -11228,8 +11159,7 @@ var MutationBuffer = class { }, onStylesheetLoad: (link, childSn) => { this.stylesheetManager.attachLinkElement(link, childSn); - }, - cssCaptured + } }); if (sn) { adds.push({ @@ -16425,9 +16355,6 @@ var Replayer = class { "html.rrweb-paused *, html.rrweb-paused *:before, html.rrweb-paused *:after { animation-play-state: paused !important; }" ); } - if (!injectStylesRules.length) { - return; - } if (this.usingVirtualDom) { const styleEl = this.virtualDom.createElement("style"); this.virtualDom.mirror.add( @@ -17102,12 +17029,7 @@ var Replayer = class { } return this.warnNodeNotFound(d, mutation.id); } - const parentEl = target.parentElement; - if (mutation.value && parentEl && parentEl.tagName === "STYLE") { - target.textContent = adaptCssForReplay(mutation.value, this.cache); - } else { - target.textContent = mutation.value; - } + target.textContent = mutation.value; if (this.usingVirtualDom) { const parent = target.parentNode; if (((_a2 = parent == null ? void 0 : parent.rules) == null ? void 0 : _a2.length) > 0) parent.rules = []; diff --git a/rrweb b/rrweb index cb01260d6e0..2701b9ddd75 160000 --- a/rrweb +++ b/rrweb @@ -1 +1 @@ -Subproject commit cb01260d6e05a1107dbb8c7613e7462d0d1b041f +Subproject commit 2701b9ddd75b1e70106c247526c9ab051e2394f9 diff --git a/sdk/firstload/CHANGELOG.md b/sdk/firstload/CHANGELOG.md index b9c7281c067..3fe3e85dd97 100644 --- a/sdk/firstload/CHANGELOG.md +++ b/sdk/firstload/CHANGELOG.md @@ -1,5 +1,11 @@ # highlight.run +## 9.7.1 + +### Patch Changes + +- 847fdc0: revert single style sheet serialization due to performance regression + ## 9.7.0 ### Minor Changes diff --git a/sdk/firstload/package.json b/sdk/firstload/package.json index b7daaef55cc..972ad1a7508 100644 --- a/sdk/firstload/package.json +++ b/sdk/firstload/package.json @@ -1,6 +1,6 @@ { "name": "highlight.run", - "version": "9.7.0", + "version": "9.7.1", "description": "Open source, fullstack monitoring. Capture frontend errors, record server side logs, and visualize what broke with session replay.", "keywords": [ "highlight", diff --git a/sdk/firstload/src/__generated/version.ts b/sdk/firstload/src/__generated/version.ts index 3ec120f12a1..822e6850930 100644 --- a/sdk/firstload/src/__generated/version.ts +++ b/sdk/firstload/src/__generated/version.ts @@ -1 +1 @@ -export default "9.7.0" \ No newline at end of file +export default "9.7.1" \ No newline at end of file diff --git a/sdk/highlight-next/CHANGELOG.md b/sdk/highlight-next/CHANGELOG.md index 7596aede8e7..eea174853a3 100644 --- a/sdk/highlight-next/CHANGELOG.md +++ b/sdk/highlight-next/CHANGELOG.md @@ -1,5 +1,14 @@ # @highlight-run/next +## 7.6.10 + +### Patch Changes + +- Updated dependencies [847fdc0] + - highlight.run@9.7.1 + - @highlight-run/node@3.10.1 + - @highlight-run/react@8.0.1 + ## 7.6.9 ### Patch Changes diff --git a/sdk/highlight-next/package.json b/sdk/highlight-next/package.json index 83d1384a56e..ef786418949 100644 --- a/sdk/highlight-next/package.json +++ b/sdk/highlight-next/package.json @@ -1,6 +1,6 @@ { "name": "@highlight-run/next", - "version": "7.6.9", + "version": "7.6.10", "description": "Client for interfacing with Highlight in next.js", "files": [ "dist", diff --git a/sdk/highlight-react/CHANGELOG.md b/sdk/highlight-react/CHANGELOG.md index 146bdf1641f..883e4d8d1d9 100644 --- a/sdk/highlight-react/CHANGELOG.md +++ b/sdk/highlight-react/CHANGELOG.md @@ -1,5 +1,12 @@ # @highlight-run/react +## 8.0.1 + +### Patch Changes + +- Updated dependencies [847fdc0] + - highlight.run@9.7.1 + ## 8.0.0 ### Patch Changes diff --git a/sdk/highlight-react/package.json b/sdk/highlight-react/package.json index 6c67f0672b3..a27ea5f71b4 100644 --- a/sdk/highlight-react/package.json +++ b/sdk/highlight-react/package.json @@ -1,6 +1,6 @@ { "name": "@highlight-run/react", - "version": "8.0.0", + "version": "8.0.1", "description": "The official Highlight SDK for React", "license": "Apache-2.0", "peerDependencies": { diff --git a/sdk/highlight-remix/CHANGELOG.md b/sdk/highlight-remix/CHANGELOG.md index 96899d1aed0..4fcfd4ee363 100644 --- a/sdk/highlight-remix/CHANGELOG.md +++ b/sdk/highlight-remix/CHANGELOG.md @@ -1,5 +1,14 @@ # @highlight-run/remix +## 2.0.73 + +### Patch Changes + +- Updated dependencies [847fdc0] + - highlight.run@9.7.1 + - @highlight-run/node@3.10.1 + - @highlight-run/react@8.0.1 + ## 2.0.72 ### Patch Changes diff --git a/sdk/highlight-remix/package.json b/sdk/highlight-remix/package.json index 5e95a4226b7..e6bec625845 100644 --- a/sdk/highlight-remix/package.json +++ b/sdk/highlight-remix/package.json @@ -1,6 +1,6 @@ { "name": "@highlight-run/remix", - "version": "2.0.72", + "version": "2.0.73", "description": "Client for interfacing with Highlight in Remix", "packageManager": "yarn@4.0.2", "author": "", diff --git a/yarn.lock b/yarn.lock index 75ff041598b..49089e820d1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -16878,7 +16878,6 @@ __metadata: eslint-plugin-compat: "npm:^5.0.0" eslint-plugin-jest: "npm:^27.6.0" eslint-plugin-tsdoc: "npm:^0.2.17" - happy-dom: "npm:^14.12.0" markdownlint: "npm:^0.25.1" markdownlint-cli: "npm:^0.31.1" prettier: "npm:2.8.4" @@ -52695,6 +52694,7 @@ __metadata: "@typescript-eslint/eslint-plugin": "npm:^5.23.0" "@typescript-eslint/parser": "npm:^5.23.0" eslint: "npm:^8.15.0" + happy-dom: "npm:^14.12.0" puppeteer: "npm:^17.1.3" rrweb-snapshot: "workspace:*" turbo: "npm:^2.0.5"