From 233aaca60291a106665995a65e31e9abe6d97c95 Mon Sep 17 00:00:00 2001 From: Alex Kaminskii Date: Tue, 4 Oct 2022 15:37:16 +0200 Subject: [PATCH] fix(tracker):4.1.5: fix adoptedCss id + hide css cors error --- tracker/tracker/package.json | 2 +- .../main/modules/constructedStyleSheets.ts | 82 ++++++++++--------- tracker/tracker/src/main/modules/cssrules.ts | 12 +-- tracker/tracker/src/main/modules/exception.ts | 2 +- 4 files changed, 53 insertions(+), 45 deletions(-) diff --git a/tracker/tracker/package.json b/tracker/tracker/package.json index 8d60a0cee..e748cc15a 100644 --- a/tracker/tracker/package.json +++ b/tracker/tracker/package.json @@ -1,7 +1,7 @@ { "name": "@openreplay/tracker", "description": "The OpenReplay tracker main package", - "version": "4.1.4", + "version": "4.1.5", "keywords": [ "logging", "replay" diff --git a/tracker/tracker/src/main/modules/constructedStyleSheets.ts b/tracker/tracker/src/main/modules/constructedStyleSheets.ts index 5a25352de..64eb8d659 100644 --- a/tracker/tracker/src/main/modules/constructedStyleSheets.ts +++ b/tracker/tracker/src/main/modules/constructedStyleSheets.ts @@ -41,44 +41,52 @@ export default function (app: App | null) { const styleSheetIDMap: Map = new Map() const adoptedStyleSheetsOwnings: Map = new Map() - const sendAdoptedStyleSheetsUpdate = (root: StyleSheetOwner) => { - let nodeID = app.nodes.getID(root) - if (root === document) { - nodeID = 0 // main document doesn't have nodeID. ID count starts from the documentElement - } - if (!nodeID) { - return - } - let pastOwning = adoptedStyleSheetsOwnings.get(nodeID) - if (!pastOwning) { - pastOwning = [] - } - const nowOwning: number[] = [] - const styleSheets = root.adoptedStyleSheets - for (const s of styleSheets) { - let sheetID = styleSheetIDMap.get(s) - const init = !sheetID - if (!sheetID) { - sheetID = nextID() + const sendAdoptedStyleSheetsUpdate = (root: StyleSheetOwner) => + setTimeout(() => { + let nodeID = app.nodes.getID(root) + if (root === document) { + nodeID = 0 // main document doesn't have nodeID. ID count starts from the documentElement } - nowOwning.push(sheetID) - if (!pastOwning.includes(sheetID)) { - app.send(AdoptedSSAddOwner(sheetID, nodeID)) + if (nodeID === undefined) { + return } - if (init) { - const rules = s.cssRules - for (let i = 0; i < rules.length; i++) { - app.send(AdoptedSSInsertRuleURLBased(sheetID, rules[i].cssText, i, app.getBaseHref())) + let pastOwning = adoptedStyleSheetsOwnings.get(nodeID) + if (!pastOwning) { + pastOwning = [] + } + const nowOwning: number[] = [] + const styleSheets = root.adoptedStyleSheets + for (const s of styleSheets) { + let sheetID = styleSheetIDMap.get(s) + const init = !sheetID + if (!sheetID) { + sheetID = nextID() + styleSheetIDMap.set(s, sheetID) + } + if (!pastOwning.includes(sheetID)) { + app.send(AdoptedSSAddOwner(sheetID, nodeID)) + } + if (init) { + const rules = s.cssRules + for (let i = 0; i < rules.length; i++) { + app.send(AdoptedSSInsertRuleURLBased(sheetID, rules[i].cssText, i, app.getBaseHref())) + } + } + nowOwning.push(sheetID) + } + for (const sheetID of pastOwning) { + if (!nowOwning.includes(sheetID)) { + app.send(AdoptedSSRemoveOwner(sheetID, nodeID)) } } - } - for (const sheetID of pastOwning) { - if (!nowOwning.includes(sheetID)) { - app.send(AdoptedSSRemoveOwner(sheetID, nodeID)) - } - } - adoptedStyleSheetsOwnings.set(nodeID, nowOwning) - } + adoptedStyleSheetsOwnings.set(nodeID, nowOwning) + }, 20) // Misterious bug: + /* On the page https://explore.fast.design/components/fast-accordion + the only rule inside the only adoptedStyleSheet of the iframe-s document + gets changed during first milliseconds after the load. + Howerer, none of the documented methods (replace, insertRule) is triggered. + The rule is not substituted (remains the same object), however the text gets changed. + */ function patchAdoptedStyleSheets( prototype: typeof Document.prototype | typeof ShadowRoot.prototype, @@ -111,8 +119,8 @@ export default function (app: App | null) { patchAdoptedStyleSheets(context.Document.prototype) patchAdoptedStyleSheets(context.ShadowRoot.prototype) - //@ts-ignore TODO: configure ts (use necessary lib) - const { insertRule, deleteRule, replace, replaceSync } = context.CSSStyleSheet.prototype + //@ts-ignore TODO: upgrade ts to 4.8+ + const { replace, replaceSync } = context.CSSStyleSheet.prototype //@ts-ignore context.CSSStyleSheet.prototype.replace = function (text: string) { @@ -135,7 +143,7 @@ export default function (app: App | null) { } patchContext(window) - app.observer.attachContextCallback(patchContext) + app.observer.attachContextCallback(app.safe(patchContext)) app.attachStopCallback(() => { styleSheetIDMap.clear() diff --git a/tracker/tracker/src/main/modules/cssrules.ts b/tracker/tracker/src/main/modules/cssrules.ts index c4fce0fb7..08db23af8 100644 --- a/tracker/tracker/src/main/modules/cssrules.ts +++ b/tracker/tracker/src/main/modules/cssrules.ts @@ -17,7 +17,7 @@ export default function (app: App | null) { return } - const sendInserDeleteRule = app.safe((sheet: CSSStyleSheet, index: number, rule?: string) => { + const sendInsertDeleteRule = app.safe((sheet: CSSStyleSheet, index: number, rule?: string) => { const sheetID = styleSheetIDMap.get(sheet) if (!sheetID) { // OK-case. Sheet haven't been registered yet. Rules will be sent on registration. @@ -57,17 +57,17 @@ export default function (app: App | null) { } }) - const patchContext = (context: typeof globalThis) => { + const patchContext = app.safe((context: typeof globalThis) => { const { insertRule, deleteRule } = context.CSSStyleSheet.prototype const { insertRule: groupInsertRule, deleteRule: groupDeleteRule } = context.CSSGroupingRule.prototype context.CSSStyleSheet.prototype.insertRule = function (rule: string, index = 0): number { - sendInserDeleteRule(this, index, rule) + sendInsertDeleteRule(this, index, rule) return insertRule.call(this, rule, index) } context.CSSStyleSheet.prototype.deleteRule = function (index: number): void { - sendInserDeleteRule(this, index) + sendInsertDeleteRule(this, index) return deleteRule.call(this, index) } @@ -81,7 +81,7 @@ export default function (app: App | null) { sendReplaceGroupingRule(this) return result } - } + }) patchContext(window) app.observer.attachContextCallback(patchContext) @@ -105,7 +105,7 @@ export default function (app: App | null) { const rules = sheet.cssRules for (let i = 0; i < rules.length; i++) { - sendInserDeleteRule(sheet, i, rules[i].cssText) + sendInsertDeleteRule(sheet, i, rules[i].cssText) } }) } diff --git a/tracker/tracker/src/main/modules/exception.ts b/tracker/tracker/src/main/modules/exception.ts index 8d286349f..7462226d3 100644 --- a/tracker/tracker/src/main/modules/exception.ts +++ b/tracker/tracker/src/main/modules/exception.ts @@ -84,7 +84,7 @@ export default function (app: App, opts: Partial): void { app.attachEventListener(context, 'error', handler) } if (options.captureExceptions) { - app.observer.attachContextCallback(patchContext) + app.observer.attachContextCallback(patchContext) // TODO: attach once-per-iframe (?) patchContext(window) } }