improve type assertion, from #716
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { listenerHandler, RecordPlugin } from '../../../types';
|
import { listenerHandler, RecordPlugin, IWindow } from '../../../types';
|
||||||
import { patch } from '../../../utils';
|
import { patch } from '../../../utils';
|
||||||
import { ErrorStackParser, StackFrame } from './error-stack-parser';
|
import { ErrorStackParser, StackFrame } from './error-stack-parser';
|
||||||
import { stringify } from './stringify';
|
import { stringify } from './stringify';
|
||||||
@@ -22,7 +22,7 @@ type LogRecordOptions = {
|
|||||||
level?: LogLevel[];
|
level?: LogLevel[];
|
||||||
lengthThreshold?: number;
|
lengthThreshold?: number;
|
||||||
stringifyOptions?: StringifyOptions;
|
stringifyOptions?: StringifyOptions;
|
||||||
logger?: Logger | string;
|
logger?: Logger | 'console';
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultLogOptions: LogRecordOptions = {
|
const defaultLogOptions: LogRecordOptions = {
|
||||||
@@ -106,7 +106,7 @@ export type Logger = {
|
|||||||
|
|
||||||
function initLogObserver(
|
function initLogObserver(
|
||||||
cb: logCallback,
|
cb: logCallback,
|
||||||
win: Window, // top window or in an iframe
|
win: IWindow, // top window or in an iframe
|
||||||
logOptions: LogRecordOptions,
|
logOptions: LogRecordOptions,
|
||||||
): listenerHandler {
|
): listenerHandler {
|
||||||
const loggerType = logOptions.logger;
|
const loggerType = logOptions.logger;
|
||||||
@@ -115,7 +115,7 @@ function initLogObserver(
|
|||||||
}
|
}
|
||||||
let logger: Logger;
|
let logger: Logger;
|
||||||
if (typeof loggerType === 'string') {
|
if (typeof loggerType === 'string') {
|
||||||
logger = (win as any)[loggerType];
|
logger = win[loggerType];
|
||||||
} else {
|
} else {
|
||||||
logger = loggerType;
|
logger = loggerType;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,15 +44,16 @@ import {
|
|||||||
fontParam,
|
fontParam,
|
||||||
Mirror,
|
Mirror,
|
||||||
styleDeclarationCallback,
|
styleDeclarationCallback,
|
||||||
|
IWindow,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import MutationBuffer from './mutation';
|
import MutationBuffer from './mutation';
|
||||||
import { IframeManager } from './iframe-manager';
|
import { IframeManager } from './iframe-manager';
|
||||||
import { ShadowDomManager } from './shadow-dom-manager';
|
import { ShadowDomManager } from './shadow-dom-manager';
|
||||||
|
|
||||||
type WindowWithStoredMutationObserver = Window & {
|
type WindowWithStoredMutationObserver = IWindow & {
|
||||||
__rrMutationObserver?: MutationObserver;
|
__rrMutationObserver?: MutationObserver;
|
||||||
};
|
};
|
||||||
type WindowWithAngularZone = Window & {
|
type WindowWithAngularZone = IWindow & {
|
||||||
Zone?: {
|
Zone?: {
|
||||||
__symbol__?: (key: string) => string;
|
__symbol__?: (key: string) => string;
|
||||||
};
|
};
|
||||||
@@ -519,11 +520,14 @@ function getNestedCSSRulePositions(rule: CSSRule): number[] {
|
|||||||
|
|
||||||
function initStyleSheetObserver(
|
function initStyleSheetObserver(
|
||||||
cb: styleSheetRuleCallback,
|
cb: styleSheetRuleCallback,
|
||||||
win: Window,
|
win: IWindow,
|
||||||
mirror: Mirror,
|
mirror: Mirror,
|
||||||
): listenerHandler {
|
): listenerHandler {
|
||||||
const insertRule = (win as any).CSSStyleSheet.prototype.insertRule;
|
const insertRule = win.CSSStyleSheet.prototype.insertRule;
|
||||||
(win as any).CSSStyleSheet.prototype.insertRule = function (rule: string, index?: number) {
|
win.CSSStyleSheet.prototype.insertRule = function (
|
||||||
|
rule: string,
|
||||||
|
index?: number,
|
||||||
|
) {
|
||||||
const id = mirror.getId(this.ownerNode as INode);
|
const id = mirror.getId(this.ownerNode as INode);
|
||||||
if (id !== -1) {
|
if (id !== -1) {
|
||||||
cb({
|
cb({
|
||||||
@@ -534,8 +538,8 @@ function initStyleSheetObserver(
|
|||||||
return insertRule.apply(this, arguments);
|
return insertRule.apply(this, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteRule = (win as any).CSSStyleSheet.prototype.deleteRule;
|
const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
|
||||||
(win as any).CSSStyleSheet.prototype.deleteRule = function (index: number) {
|
win.CSSStyleSheet.prototype.deleteRule = function (index: number) {
|
||||||
const id = mirror.getId(this.ownerNode as INode);
|
const id = mirror.getId(this.ownerNode as INode);
|
||||||
if (id !== -1) {
|
if (id !== -1) {
|
||||||
cb({
|
cb({
|
||||||
@@ -550,20 +554,20 @@ function initStyleSheetObserver(
|
|||||||
[key: string]: GroupingCSSRuleTypes;
|
[key: string]: GroupingCSSRuleTypes;
|
||||||
} = {};
|
} = {};
|
||||||
if (isCSSGroupingRuleSupported) {
|
if (isCSSGroupingRuleSupported) {
|
||||||
supportedNestedCSSRuleTypes['CSSGroupingRule'] = (win as any).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 (isCSSMediaRuleSupported) {
|
||||||
supportedNestedCSSRuleTypes['CSSMediaRule'] = (win as any).CSSMediaRule;
|
supportedNestedCSSRuleTypes.CSSMediaRule = win.CSSMediaRule;
|
||||||
}
|
}
|
||||||
if (isCSSConditionRuleSupported) {
|
if (isCSSConditionRuleSupported) {
|
||||||
supportedNestedCSSRuleTypes['CSSConditionRule'] = (win as any).CSSConditionRule;
|
supportedNestedCSSRuleTypes.CSSConditionRule = win.CSSConditionRule;
|
||||||
}
|
}
|
||||||
if (isCSSSupportsRuleSupported) {
|
if (isCSSSupportsRuleSupported) {
|
||||||
supportedNestedCSSRuleTypes['CSSSupportsRule'] = (win as any).CSSSupportsRule;
|
supportedNestedCSSRuleTypes.CSSSupportsRule = win.CSSSupportsRule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,8 +616,8 @@ function initStyleSheetObserver(
|
|||||||
});
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
(win as any).CSSStyleSheet.prototype.insertRule = insertRule;
|
win.CSSStyleSheet.prototype.insertRule = insertRule;
|
||||||
(win as any).CSSStyleSheet.prototype.deleteRule = deleteRule;
|
win.CSSStyleSheet.prototype.deleteRule = deleteRule;
|
||||||
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
|
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
|
||||||
type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
|
type.prototype.insertRule = unmodifiedFunctions[typeKey].insertRule;
|
||||||
type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
|
type.prototype.deleteRule = unmodifiedFunctions[typeKey].deleteRule;
|
||||||
@@ -623,11 +627,11 @@ function initStyleSheetObserver(
|
|||||||
|
|
||||||
function initStyleDeclarationObserver(
|
function initStyleDeclarationObserver(
|
||||||
cb: styleDeclarationCallback,
|
cb: styleDeclarationCallback,
|
||||||
win: Window,
|
win: IWindow,
|
||||||
mirror: Mirror,
|
mirror: Mirror,
|
||||||
): listenerHandler {
|
): listenerHandler {
|
||||||
const setProperty = (win as any).CSSStyleDeclaration.prototype.setProperty;
|
const setProperty = win.CSSStyleDeclaration.prototype.setProperty;
|
||||||
(win as any).CSSStyleDeclaration.prototype.setProperty = function (
|
win.CSSStyleDeclaration.prototype.setProperty = function (
|
||||||
this: CSSStyleDeclaration,
|
this: CSSStyleDeclaration,
|
||||||
property: string,
|
property: string,
|
||||||
value: string,
|
value: string,
|
||||||
@@ -650,8 +654,8 @@ function initStyleDeclarationObserver(
|
|||||||
return setProperty.apply(this, arguments);
|
return setProperty.apply(this, arguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeProperty = (win as any).CSSStyleDeclaration.prototype.removeProperty;
|
const removeProperty = win.CSSStyleDeclaration.prototype.removeProperty;
|
||||||
(win as any).CSSStyleDeclaration.prototype.removeProperty = function (
|
win.CSSStyleDeclaration.prototype.removeProperty = function (
|
||||||
this: CSSStyleDeclaration,
|
this: CSSStyleDeclaration,
|
||||||
property: string,
|
property: string,
|
||||||
) {
|
) {
|
||||||
@@ -671,8 +675,8 @@ function initStyleDeclarationObserver(
|
|||||||
};
|
};
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
(win as any).CSSStyleDeclaration.prototype.setProperty = setProperty;
|
win.CSSStyleDeclaration.prototype.setProperty = setProperty;
|
||||||
(win as any).CSSStyleDeclaration.prototype.removeProperty = removeProperty;
|
win.CSSStyleDeclaration.prototype.removeProperty = removeProperty;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -704,23 +708,25 @@ function initMediaInteractionObserver(
|
|||||||
|
|
||||||
function initCanvasMutationObserver(
|
function initCanvasMutationObserver(
|
||||||
cb: canvasMutationCallback,
|
cb: canvasMutationCallback,
|
||||||
win: Window,
|
win: IWindow,
|
||||||
blockClass: blockClass,
|
blockClass: blockClass,
|
||||||
mirror: Mirror,
|
mirror: Mirror,
|
||||||
): listenerHandler {
|
): listenerHandler {
|
||||||
const props = Object.getOwnPropertyNames((win as any).CanvasRenderingContext2D.prototype);
|
const props = Object.getOwnPropertyNames(
|
||||||
|
win.CanvasRenderingContext2D.prototype,
|
||||||
|
);
|
||||||
const handlers: listenerHandler[] = [];
|
const handlers: listenerHandler[] = [];
|
||||||
for (const prop of props) {
|
for (const prop of props) {
|
||||||
try {
|
try {
|
||||||
if (
|
if (
|
||||||
typeof (win as any).CanvasRenderingContext2D.prototype[
|
typeof win.CanvasRenderingContext2D.prototype[
|
||||||
prop as keyof CanvasRenderingContext2D
|
prop as keyof CanvasRenderingContext2D
|
||||||
] !== 'function'
|
] !== 'function'
|
||||||
) {
|
) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const restoreHandler = patch(
|
const restoreHandler = patch(
|
||||||
(win as any).CanvasRenderingContext2D.prototype,
|
win.CanvasRenderingContext2D.prototype,
|
||||||
prop,
|
prop,
|
||||||
function (original) {
|
function (original) {
|
||||||
return function (
|
return function (
|
||||||
@@ -761,7 +767,7 @@ function initCanvasMutationObserver(
|
|||||||
handlers.push(restoreHandler);
|
handlers.push(restoreHandler);
|
||||||
} catch {
|
} catch {
|
||||||
const hookHandler = hookSetter<CanvasRenderingContext2D>(
|
const hookHandler = hookSetter<CanvasRenderingContext2D>(
|
||||||
(win as any).CanvasRenderingContext2D.prototype,
|
win.CanvasRenderingContext2D.prototype,
|
||||||
prop,
|
prop,
|
||||||
{
|
{
|
||||||
set(v) {
|
set(v) {
|
||||||
@@ -782,19 +788,18 @@ function initCanvasMutationObserver(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function initFontObserver(
|
function initFontObserver(cb: fontCallback, doc: Document): listenerHandler {
|
||||||
cb: fontCallback,
|
const win = doc.defaultView as IWindow;
|
||||||
doc: Document,
|
if (!win) {
|
||||||
): listenerHandler {
|
return () => {};
|
||||||
const win = doc.defaultView;
|
}
|
||||||
|
|
||||||
const handlers: listenerHandler[] = [];
|
const handlers: listenerHandler[] = [];
|
||||||
|
|
||||||
const fontMap = new WeakMap<FontFace, fontParam>();
|
const fontMap = new WeakMap<FontFace, fontParam>();
|
||||||
|
|
||||||
const originalFontFace = (win as any).FontFace;
|
const originalFontFace = win.FontFace;
|
||||||
// tslint:disable-next-line: no-any
|
win.FontFace = (function FontFace(
|
||||||
(win as any).FontFace = function FontFace(
|
|
||||||
family: string,
|
family: string,
|
||||||
source: string | ArrayBufferView,
|
source: string | ArrayBufferView,
|
||||||
descriptors?: FontFaceDescriptors,
|
descriptors?: FontFaceDescriptors,
|
||||||
@@ -811,7 +816,7 @@ function initFontObserver(
|
|||||||
JSON.stringify(Array.from(new Uint8Array(source as any))),
|
JSON.stringify(Array.from(new Uint8Array(source as any))),
|
||||||
});
|
});
|
||||||
return fontFace;
|
return fontFace;
|
||||||
};
|
} as unknown) as typeof FontFace;
|
||||||
|
|
||||||
const restoreHandler = patch(doc.fonts, 'add', function (original) {
|
const restoreHandler = patch(doc.fonts, 'add', function (original) {
|
||||||
return function (this: FontFaceSet, fontFace: FontFace) {
|
return function (this: FontFaceSet, fontFace: FontFace) {
|
||||||
@@ -827,8 +832,7 @@ function initFontObserver(
|
|||||||
});
|
});
|
||||||
|
|
||||||
handlers.push(() => {
|
handlers.push(() => {
|
||||||
// tslint:disable-next-line: no-any
|
win.FontFace = originalFontFace;
|
||||||
(win as any).FontFace = originalFontFace;
|
|
||||||
});
|
});
|
||||||
handlers.push(restoreHandler);
|
handlers.push(restoreHandler);
|
||||||
|
|
||||||
@@ -923,6 +927,11 @@ export function initObservers(
|
|||||||
o: observerParam,
|
o: observerParam,
|
||||||
hooks: hooksParam = {},
|
hooks: hooksParam = {},
|
||||||
): listenerHandler {
|
): listenerHandler {
|
||||||
|
const currentWindow = o.doc.defaultView; // basically document.window
|
||||||
|
if (!currentWindow) {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
|
||||||
mergeHooks(o, hooks);
|
mergeHooks(o, hooks);
|
||||||
const mutationObserver = initMutationObserver(
|
const mutationObserver = initMutationObserver(
|
||||||
o.mutationCb,
|
o.mutationCb,
|
||||||
@@ -980,8 +989,6 @@ export function initObservers(
|
|||||||
o.mirror,
|
o.mirror,
|
||||||
);
|
);
|
||||||
|
|
||||||
const currentWindow = o.doc.defaultView as Window; // basically document.window
|
|
||||||
|
|
||||||
const styleSheetObserver = initStyleSheetObserver(
|
const styleSheetObserver = initStyleSheetObserver(
|
||||||
o.styleSheetRuleCb,
|
o.styleSheetRuleCb,
|
||||||
currentWindow,
|
currentWindow,
|
||||||
@@ -994,20 +1001,21 @@ export function initObservers(
|
|||||||
);
|
);
|
||||||
const canvasMutationObserver = o.recordCanvas
|
const canvasMutationObserver = o.recordCanvas
|
||||||
? initCanvasMutationObserver(
|
? initCanvasMutationObserver(
|
||||||
o.canvasMutationCb,
|
o.canvasMutationCb,
|
||||||
currentWindow,
|
currentWindow,
|
||||||
o.blockClass,
|
o.blockClass,
|
||||||
o.mirror,
|
o.mirror,
|
||||||
) : () => {};
|
)
|
||||||
const fontObserver = o.collectFonts ? initFontObserver(o.fontCb, o.doc) : () => {};
|
: () => {};
|
||||||
|
const fontObserver = o.collectFonts
|
||||||
|
? initFontObserver(o.fontCb, o.doc)
|
||||||
|
: () => {};
|
||||||
// plugins
|
// plugins
|
||||||
const pluginHandlers: listenerHandler[] = [];
|
const pluginHandlers: listenerHandler[] = [];
|
||||||
for (const plugin of o.plugins) {
|
for (const plugin of o.plugins) {
|
||||||
pluginHandlers.push(plugin.observer(
|
pluginHandlers.push(
|
||||||
plugin.callback,
|
plugin.observer(plugin.callback, currentWindow, plugin.options),
|
||||||
currentWindow,
|
);
|
||||||
plugin.options,
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import {
|
|||||||
styleAttributeValue,
|
styleAttributeValue,
|
||||||
styleValueWithPriority,
|
styleValueWithPriority,
|
||||||
mouseMovePos,
|
mouseMovePos,
|
||||||
|
IWindow,
|
||||||
} from '../types';
|
} from '../types';
|
||||||
import {
|
import {
|
||||||
createMirror,
|
createMirror,
|
||||||
@@ -449,7 +450,7 @@ export class Replayer {
|
|||||||
this.iframe.contentDocument,
|
this.iframe.contentDocument,
|
||||||
);
|
);
|
||||||
|
|
||||||
polyfill(this.iframe.contentWindow as Window & typeof globalThis);
|
polyfill(this.iframe.contentWindow as IWindow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ export type SamplingStrategy = Partial<{
|
|||||||
|
|
||||||
export type RecordPlugin<TOptions = unknown> = {
|
export type RecordPlugin<TOptions = unknown> = {
|
||||||
name: string;
|
name: string;
|
||||||
observer: (cb: Function, win: Window, options: TOptions) => listenerHandler;
|
observer: (cb: Function, win: IWindow, options: TOptions) => listenerHandler;
|
||||||
options: TOptions;
|
options: TOptions;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -598,3 +598,11 @@ export type ElementState = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type KeepIframeSrcFn = (src: string) => boolean;
|
export type KeepIframeSrcFn = (src: string) => boolean;
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
FontFace: typeof FontFace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export type IWindow = Window & typeof globalThis;
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import {
|
|||||||
listenerHandler,
|
listenerHandler,
|
||||||
hookResetter,
|
hookResetter,
|
||||||
blockClass,
|
blockClass,
|
||||||
eventWithTime,
|
|
||||||
EventType,
|
|
||||||
IncrementalSource,
|
IncrementalSource,
|
||||||
addedNodeMutation,
|
addedNodeMutation,
|
||||||
removedNodeMutation,
|
removedNodeMutation,
|
||||||
@@ -15,6 +13,7 @@ import {
|
|||||||
scrollData,
|
scrollData,
|
||||||
inputData,
|
inputData,
|
||||||
DocumentDimension,
|
DocumentDimension,
|
||||||
|
IWindow,
|
||||||
} from './types';
|
} from './types';
|
||||||
import {
|
import {
|
||||||
INode,
|
INode,
|
||||||
@@ -27,7 +26,7 @@ import {
|
|||||||
export function on(
|
export function on(
|
||||||
type: string,
|
type: string,
|
||||||
fn: EventListenerOrEventListenerObject,
|
fn: EventListenerOrEventListenerObject,
|
||||||
target: Document | Window = document,
|
target: Document | IWindow = document,
|
||||||
): listenerHandler {
|
): listenerHandler {
|
||||||
const options = { capture: true, passive: true };
|
const options = { capture: true, passive: true };
|
||||||
target.addEventListener(type, fn, options);
|
target.addEventListener(type, fn, options);
|
||||||
|
|||||||
Reference in New Issue
Block a user