fix: Ensure CSS support is checked more robustly (#1106)
* fix: Ensure CSS support is checked more robustly * Apply formatting changes * apply eslint changes * Update packages/rrweb/src/record/observer.ts Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com> * fix: do not use window in module scope --------- Co-authored-by: mydea <mydea@users.noreply.github.com> Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com>
This commit is contained in:
@@ -54,11 +54,6 @@ type WindowWithAngularZone = IWindow & {
|
|||||||
export const mutationBuffers: MutationBuffer[] = [];
|
export const mutationBuffers: MutationBuffer[] = [];
|
||||||
export const processedNodeManager = new ProcessedNodeManager();
|
export const processedNodeManager = new ProcessedNodeManager();
|
||||||
|
|
||||||
const isCSSGroupingRuleSupported = typeof CSSGroupingRule !== 'undefined';
|
|
||||||
const isCSSMediaRuleSupported = typeof CSSMediaRule !== 'undefined';
|
|
||||||
const isCSSSupportsRuleSupported = typeof CSSSupportsRule !== 'undefined';
|
|
||||||
const isCSSConditionRuleSupported = typeof CSSConditionRule !== 'undefined';
|
|
||||||
|
|
||||||
// Event.path is non-standard and used in some older browsers
|
// Event.path is non-standard and used in some older browsers
|
||||||
type NonStandardEvent = Omit<Event, 'composedPath'> & {
|
type NonStandardEvent = Omit<Event, 'composedPath'> & {
|
||||||
path: EventTarget[];
|
path: EventTarget[];
|
||||||
@@ -488,13 +483,13 @@ function getNestedCSSRulePositions(rule: CSSRule): number[] {
|
|||||||
const positions: number[] = [];
|
const positions: number[] = [];
|
||||||
function recurse(childRule: CSSRule, pos: number[]) {
|
function recurse(childRule: CSSRule, pos: number[]) {
|
||||||
if (
|
if (
|
||||||
(isCSSGroupingRuleSupported &&
|
(hasNestedCSSRule('CSSGroupingRule') &&
|
||||||
childRule.parentRule instanceof CSSGroupingRule) ||
|
childRule.parentRule instanceof CSSGroupingRule) ||
|
||||||
(isCSSMediaRuleSupported &&
|
(hasNestedCSSRule('CSSMediaRule') &&
|
||||||
childRule.parentRule instanceof CSSMediaRule) ||
|
childRule.parentRule instanceof CSSMediaRule) ||
|
||||||
(isCSSSupportsRuleSupported &&
|
(hasNestedCSSRule('CSSSupportsRule') &&
|
||||||
childRule.parentRule instanceof CSSSupportsRule) ||
|
childRule.parentRule instanceof CSSSupportsRule) ||
|
||||||
(isCSSConditionRuleSupported &&
|
(hasNestedCSSRule('CSSConditionRule') &&
|
||||||
childRule.parentRule instanceof CSSConditionRule)
|
childRule.parentRule instanceof CSSConditionRule)
|
||||||
) {
|
) {
|
||||||
const rules = Array.from(
|
const rules = Array.from(
|
||||||
@@ -643,20 +638,20 @@ function initStyleSheetObserver(
|
|||||||
const supportedNestedCSSRuleTypes: {
|
const supportedNestedCSSRuleTypes: {
|
||||||
[key: string]: GroupingCSSRuleTypes;
|
[key: string]: GroupingCSSRuleTypes;
|
||||||
} = {};
|
} = {};
|
||||||
if (isCSSGroupingRuleSupported) {
|
if (canMonkeyPatchNestedCSSRule('CSSGroupingRule')) {
|
||||||
supportedNestedCSSRuleTypes.CSSGroupingRule = win.CSSGroupingRule;
|
supportedNestedCSSRuleTypes.CSSGroupingRule = win.CSSGroupingRule;
|
||||||
} else {
|
} else {
|
||||||
// Some browsers (Safari) don't support CSSGroupingRule
|
// Some browsers (Safari) don't support CSSGroupingRule
|
||||||
// https://caniuse.com/?search=cssgroupingrule
|
// https://caniuse.com/?search=cssgroupingrule
|
||||||
// fall back to monkey patching classes that would have inherited from CSSGroupingRule
|
// fall back to monkey patching classes that would have inherited from CSSGroupingRule
|
||||||
|
|
||||||
if (isCSSMediaRuleSupported) {
|
if (canMonkeyPatchNestedCSSRule('CSSMediaRule')) {
|
||||||
supportedNestedCSSRuleTypes.CSSMediaRule = win.CSSMediaRule;
|
supportedNestedCSSRuleTypes.CSSMediaRule = win.CSSMediaRule;
|
||||||
}
|
}
|
||||||
if (isCSSConditionRuleSupported) {
|
if (canMonkeyPatchNestedCSSRule('CSSConditionRule')) {
|
||||||
supportedNestedCSSRuleTypes.CSSConditionRule = win.CSSConditionRule;
|
supportedNestedCSSRuleTypes.CSSConditionRule = win.CSSConditionRule;
|
||||||
}
|
}
|
||||||
if (isCSSSupportsRuleSupported) {
|
if (canMonkeyPatchNestedCSSRule('CSSSupportsRule')) {
|
||||||
supportedNestedCSSRuleTypes.CSSSupportsRule = win.CSSSupportsRule;
|
supportedNestedCSSRuleTypes.CSSSupportsRule = win.CSSSupportsRule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1168,3 +1163,24 @@ export function initObservers(
|
|||||||
pluginHandlers.forEach((h) => h());
|
pluginHandlers.forEach((h) => h());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CSSGroupingProp =
|
||||||
|
| 'CSSGroupingRule'
|
||||||
|
| 'CSSMediaRule'
|
||||||
|
| 'CSSSupportsRule'
|
||||||
|
| 'CSSConditionRule';
|
||||||
|
|
||||||
|
function hasNestedCSSRule(prop: CSSGroupingProp): boolean {
|
||||||
|
return typeof window[prop] !== 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
function canMonkeyPatchNestedCSSRule(prop: CSSGroupingProp): boolean {
|
||||||
|
return Boolean(
|
||||||
|
typeof window[prop] !== 'undefined' &&
|
||||||
|
// Note: Generally, this check _shouldn't_ be necessary
|
||||||
|
// However, in some scenarios (e.g. jsdom) this can sometimes fail, so we check for it here
|
||||||
|
window[prop].prototype &&
|
||||||
|
'insertRule' in window[prop].prototype &&
|
||||||
|
'deleteRule' in window[prop].prototype,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user