refactor: eliminate eslint errors (#920)

* refactor: eliminate eslint errors as many as I can

* refactor: fix more eslint errors in the record module

* LINT: fix @typescript-eslint/unbound-method

* LINT: fix all eslint errors in source code

* LINT: fix as many eslint warnings as possible

Co-authored-by: Justin Halsall <Juice10@users.noreply.github.com>
This commit is contained in:
Yun Feng
2026-04-01 12:00:00 +08:00
committed by GitHub
parent a4360af11a
commit 79dc0fb46c
44 changed files with 524 additions and 374 deletions

View File

@@ -78,7 +78,7 @@
"@xstate/fsm": "^1.4.0",
"base64-arraybuffer": "^1.0.1",
"fflate": "^0.4.4",
"mitt": "^1.1.3",
"mitt": "^3.0.0",
"rrdom": "^0.1.2",
"rrweb-snapshot": "^1.1.14"
}

View File

@@ -7,7 +7,7 @@ export const unpack: UnpackFn = (raw: string) => {
return raw;
}
try {
const e: eventWithTime = JSON.parse(raw);
const e: eventWithTime = JSON.parse(raw) as eventWithTime;
if (e.timestamp) {
return e;
}
@@ -17,7 +17,7 @@ export const unpack: UnpackFn = (raw: string) => {
try {
const e: eventWithTimeAndPacker = JSON.parse(
strFromU8(unzlibSync(strToU8(raw, true))),
);
) as eventWithTimeAndPacker;
if (e.v === MARK) {
return e;
}

View File

@@ -1,3 +1,8 @@
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-return */
// tslint:disable
/**
* Class StackFrame is a fork of https://github.com/stacktracejs/stackframe/blob/master/stackframe.js
@@ -27,19 +32,9 @@ export class StackFrame {
toString() {
const lineNumber = this.lineNumber || '';
const columnNumber = this.columnNumber || '';
if (this.functionName) {
return (
this.functionName +
' (' +
this.fileName +
':' +
lineNumber +
':' +
columnNumber +
')'
);
}
return this.fileName + ':' + lineNumber + ':' + columnNumber;
if (this.functionName)
return `${this.functionName} (${this.fileName}:${lineNumber}:${columnNumber})`;
return `${this.fileName}:${lineNumber}:${columnNumber}`;
}
}
@@ -55,9 +50,6 @@ const SAFARI_NATIVE_CODE_REGEXP = /^(eval@)?(\[native code])?$/;
export const ErrorStackParser = {
/**
* Given an Error object, extract the most information from it.
*
* @param {Error} error object
* @return {Array} of StackFrames
*/
parse: function (error: Error): StackFrame[] {
// https://github.com/rrweb-io/rrweb/issues/782
@@ -65,8 +57,10 @@ export const ErrorStackParser = {
return [];
}
if (
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
typeof error.stacktrace !== 'undefined' ||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
typeof error['opera#sourceloc'] !== 'undefined'
) {

View File

@@ -59,27 +59,6 @@ export type LogData = {
type logCallback = (p: LogData) => void;
export type LogLevel =
| 'assert'
| 'clear'
| 'count'
| 'countReset'
| 'debug'
| 'dir'
| 'dirxml'
| 'error'
| 'group'
| 'groupCollapsed'
| 'groupEnd'
| 'info'
| 'log'
| 'table'
| 'time'
| 'timeEnd'
| 'timeLog'
| 'trace'
| 'warn';
/* fork from interface Console */
// all kinds of console functions
export type Logger = {
@@ -104,14 +83,26 @@ export type Logger = {
warn?: typeof console.warn;
};
export type LogLevel = keyof Logger;
function initLogObserver(
cb: logCallback,
win: IWindow, // top window or in an iframe
logOptions: LogRecordOptions,
options: LogRecordOptions,
): listenerHandler {
const logOptions = (options
? Object.assign({}, defaultLogOptions, options)
: defaultLogOptions) as {
level: LogLevel[];
lengthThreshold: number;
stringifyOptions?: StringifyOptions;
logger: Logger | 'console';
};
const loggerType = logOptions.logger;
if (!loggerType) {
return () => {};
return () => {
//
};
}
let logger: Logger;
if (typeof loggerType === 'string') {
@@ -122,10 +113,11 @@ function initLogObserver(
let logCount = 0;
const cancelHandlers: listenerHandler[] = [];
// add listener to thrown errors
if (logOptions.level!.includes('error')) {
if (logOptions.level.includes('error')) {
if (window) {
const errorHandler = (event: ErrorEvent) => {
const { message, error } = event;
const message = event.message,
error = event.error as Error;
const trace: string[] = ErrorStackParser.parse(
error,
).map((stackFrame: StackFrame) => stackFrame.toString());
@@ -142,7 +134,7 @@ function initLogObserver(
});
}
}
for (const levelType of logOptions.level!) {
for (const levelType of logOptions.level) {
cancelHandlers.push(replace(logger, levelType));
}
return () => {
@@ -151,46 +143,52 @@ function initLogObserver(
/**
* replace the original console function and record logs
* @param logger the logger object such as Console
* @param level the name of log function to be replaced
* @param logger - the logger object such as Console
* @param level - the name of log function to be replaced
*/
function replace(_logger: Logger, level: LogLevel) {
if (!_logger[level]) {
return () => {};
return () => {
//
};
}
// replace the logger.{level}. return a restore function
return patch(_logger, level, (original) => {
return (...args: Array<unknown>) => {
original.apply(this, args);
try {
const trace = ErrorStackParser.parse(new Error())
.map((stackFrame: StackFrame) => stackFrame.toString())
.splice(1); // splice(1) to omit the hijacked log function
const payload = args.map((s) =>
stringify(s, logOptions.stringifyOptions),
);
logCount++;
if (logCount < logOptions.lengthThreshold!) {
cb({
level,
trace,
payload,
});
} else if (logCount === logOptions.lengthThreshold) {
// notify the user
cb({
level: 'warn',
trace: [],
payload: [
stringify('The number of log records reached the threshold.'),
],
});
return patch(
_logger,
level,
(original: (...args: Array<unknown>) => void) => {
return (...args: Array<unknown>) => {
original.apply(this, args);
try {
const trace = ErrorStackParser.parse(new Error())
.map((stackFrame: StackFrame) => stackFrame.toString())
.splice(1); // splice(1) to omit the hijacked log function
const payload = args.map((s) =>
stringify(s, logOptions.stringifyOptions),
);
logCount++;
if (logCount < logOptions.lengthThreshold) {
cb({
level,
trace,
payload,
});
} else if (logCount === logOptions.lengthThreshold) {
// notify the user
cb({
level: 'warn',
trace: [],
payload: [
stringify('The number of log records reached the threshold.'),
],
});
}
} catch (error) {
original('rrweb logger error:', error, ...args);
}
} catch (error) {
original('rrweb logger error:', error, ...args);
}
};
});
};
},
);
}
}
@@ -201,7 +199,5 @@ export const getRecordConsolePlugin: (
) => RecordPlugin = (options) => ({
name: PLUGIN_NAME,
observer: initLogObserver,
options: options
? Object.assign({}, defaultLogOptions, options)
: defaultLogOptions,
options: options,
});

View File

@@ -8,7 +8,7 @@ import type { StringifyOptions } from './index';
/**
* transfer the node path in Event to string
* @param node the first node in a node path array
* @param node - the first node in a node path array
*/
function pathToSelector(node: HTMLElement): string | '' {
if (!node || !node.outerHTML) {
@@ -39,7 +39,7 @@ function pathToSelector(node: HTMLElement): string | '' {
}
if (domSiblings.length > 1) {
name += ':eq(' + domSiblings.indexOf(node) + ')';
name += `:eq(${domSiblings.indexOf(node)})`;
}
path = name + (path ? '>' + path : '');
node = parent;
@@ -51,21 +51,24 @@ function pathToSelector(node: HTMLElement): string | '' {
/**
* judge is object
*/
function isObject(obj: any): boolean {
function isObject(obj: unknown): boolean {
return Object.prototype.toString.call(obj) === '[object Object]';
}
/**
* judge the object's depth
*/
function isObjTooDeep(obj: any, limit: number): boolean {
function isObjTooDeep(obj: Record<string, unknown>, limit: number): boolean {
if (limit === 0) {
return true;
}
const keys = Object.keys(obj);
for (const key of keys) {
if (isObject(obj[key]) && isObjTooDeep(obj[key], limit - 1)) {
if (
isObject(obj[key]) &&
isObjTooDeep(obj[key] as Record<string, unknown>, limit - 1)
) {
return true;
}
}
@@ -75,10 +78,10 @@ function isObjTooDeep(obj: any, limit: number): boolean {
/**
* stringify any js object
* @param obj the object to stringify
* @param obj - the object to stringify
*/
export function stringify(
obj: any,
obj: unknown,
stringifyOptions?: StringifyOptions,
): string {
const options: StringifyOptions = {
@@ -86,63 +89,68 @@ export function stringify(
depthOfLimit: 4,
};
Object.assign(options, stringifyOptions);
const stack: any[] = [];
const keys: any[] = [];
return JSON.stringify(obj, function (key, value) {
/**
* forked from https://github.com/moll/json-stringify-safe/blob/master/stringify.js
* to deCycle the object
*/
if (stack.length > 0) {
const thisPos = stack.indexOf(this);
~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
if (~stack.indexOf(value)) {
if (stack[0] === value) {
value = '[Circular ~]';
} else {
value =
'[Circular ~.' +
keys.slice(0, stack.indexOf(value)).join('.') +
']';
const stack: unknown[] = [];
const keys: unknown[] = [];
return JSON.stringify(
obj,
function (key, value: string | object | null | undefined) {
/**
* forked from https://github.com/moll/json-stringify-safe/blob/master/stringify.js
* to deCycle the object
*/
if (stack.length > 0) {
const thisPos = stack.indexOf(this);
~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
if (~stack.indexOf(value)) {
if (stack[0] === value) {
value = '[Circular ~]';
} else {
value =
'[Circular ~.' +
keys.slice(0, stack.indexOf(value)).join('.') +
']';
}
}
} else {
stack.push(value);
}
} else {
stack.push(value);
}
/* END of the FORK */
/* END of the FORK */
if (value === null || value === undefined) {
return value;
}
if (shouldIgnore(value)) {
return toString(value);
}
if (value instanceof Event) {
const eventResult: any = {};
for (const eventKey in value) {
const eventValue = (value as any)[eventKey];
if (Array.isArray(eventValue)) {
eventResult[eventKey] = pathToSelector(
eventValue.length ? eventValue[0] : null,
);
} else {
eventResult[eventKey] = eventValue;
if (value === null || value === undefined) {
return value;
}
if (shouldIgnore(value as object)) {
return toString(value as object);
}
if (value instanceof Event) {
const eventResult: Record<string, unknown> = {};
for (const eventKey in value) {
const eventValue = ((value as unknown) as Record<string, unknown>)[
eventKey
];
if (Array.isArray(eventValue)) {
eventResult[eventKey] = pathToSelector(
(eventValue.length ? eventValue[0] : null) as HTMLElement,
);
} else {
eventResult[eventKey] = eventValue;
}
}
return eventResult;
} else if (value instanceof Node) {
if (value instanceof HTMLElement) {
return value ? value.outerHTML : '';
}
return value.nodeName;
} else if (value instanceof Error) {
return value.stack
? value.stack + '\nEnd of stack for Error object'
: value.name + ': ' + value.message;
}
return eventResult;
} else if (value instanceof Node) {
if (value instanceof HTMLElement) {
return value ? value.outerHTML : '';
}
return value.nodeName;
} else if (value instanceof Error) {
return value.stack
? value.stack + '\nEnd of stack for Error object'
: value.name + ': ' + value.message;
}
return value;
});
return value;
},
);
/**
* whether we should ignore obj's info and call toString() function instead
@@ -163,7 +171,10 @@ export function stringify(
*
* issues: https://github.com/rrweb-io/rrweb/issues/653
*/
if (isObject(_obj) && isObjTooDeep(_obj, options.depthOfLimit)) {
if (
isObject(_obj) &&
isObjTooDeep(_obj as Record<string, unknown>, options.depthOfLimit)
) {
return true;
}

View File

@@ -70,7 +70,7 @@ class LogReplayPlugin {
]
: console.log;
logger(
...data.payload.map((s) => JSON.parse(s)),
...data.payload.map((s) => JSON.parse(s) as object),
this.formatMessage(data),
);
};
@@ -84,7 +84,7 @@ class LogReplayPlugin {
]
: console[level];
logger(
...data.payload.map((s) => JSON.parse(s)),
...data.payload.map((s) => JSON.parse(s) as object),
this.formatMessage(data),
);
};
@@ -95,7 +95,7 @@ class LogReplayPlugin {
/**
* format the trace data to a string
* @param data the log data
* @param data - the log data
*/
private formatMessage(data: LogData): string {
if (data.trace.length === 0) {

View File

@@ -129,7 +129,9 @@ function initMoveObserver({
mirror,
}: observerParam): listenerHandler {
if (sampling.mousemove === false) {
return () => {};
return () => {
//
};
}
const threshold =
@@ -209,7 +211,9 @@ function initMouseInteractionObserver({
sampling,
}: observerParam): listenerHandler {
if (sampling.mouseInteraction === false) {
return () => {};
return () => {
//
};
}
const disableMap: Record<string, boolean | undefined> =
sampling.mouseInteraction === true ||
@@ -438,7 +442,7 @@ function initInputObserver({
hookSetter<HTMLElement>(p[0], p[1], {
set() {
// mock to a normal event
eventHandler({ target: this } as Event);
eventHandler({ target: this as EventTarget } as Event);
},
}),
),
@@ -492,31 +496,37 @@ function initStyleSheetObserver(
{ styleSheetRuleCb, mirror }: observerParam,
{ win }: { win: IWindow },
): listenerHandler {
// eslint-disable-next-line @typescript-eslint/unbound-method
const insertRule = win.CSSStyleSheet.prototype.insertRule;
win.CSSStyleSheet.prototype.insertRule = function (
this: CSSStyleSheet,
rule: string,
index?: number,
) {
const id = mirror.getId(this.ownerNode);
const id = mirror.getId(this.ownerNode as Node);
if (id !== -1) {
styleSheetRuleCb({
id,
adds: [{ rule, index }],
});
}
return insertRule.apply(this, arguments);
return insertRule.apply(this, [rule, index]);
};
// eslint-disable-next-line @typescript-eslint/unbound-method
const deleteRule = win.CSSStyleSheet.prototype.deleteRule;
win.CSSStyleSheet.prototype.deleteRule = function (index: number) {
const id = mirror.getId(this.ownerNode);
win.CSSStyleSheet.prototype.deleteRule = function (
this: CSSStyleSheet,
index: number,
) {
const id = mirror.getId(this.ownerNode as Node);
if (id !== -1) {
styleSheetRuleCb({
id,
removes: [{ index }],
});
}
return deleteRule.apply(this, arguments);
return deleteRule.apply(this, [index]);
};
const supportedNestedCSSRuleTypes: {
@@ -549,12 +559,15 @@ function initStyleSheetObserver(
Object.entries(supportedNestedCSSRuleTypes).forEach(([typeKey, type]) => {
unmodifiedFunctions[typeKey] = {
// eslint-disable-next-line @typescript-eslint/unbound-method
insertRule: type.prototype.insertRule,
// eslint-disable-next-line @typescript-eslint/unbound-method
deleteRule: type.prototype.deleteRule,
};
type.prototype.insertRule = function (rule: string, index?: number) {
const id = mirror.getId(this.parentStyleSheet.ownerNode);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const id = mirror.getId(this.parentStyleSheet.ownerNode as Node);
if (id !== -1) {
styleSheetRuleCb({
id,
@@ -562,25 +575,28 @@ function initStyleSheetObserver(
{
rule,
index: [
...getNestedCSSRulePositions(this),
...getNestedCSSRulePositions(this as CSSRule),
index || 0, // defaults to 0
],
},
],
});
}
return unmodifiedFunctions[typeKey].insertRule.apply(this, arguments);
return unmodifiedFunctions[typeKey].insertRule.apply(this, [rule, index]);
};
type.prototype.deleteRule = function (index: number) {
const id = mirror.getId(this.parentStyleSheet.ownerNode);
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const id = mirror.getId(this.parentStyleSheet.ownerNode as Node);
if (id !== -1) {
styleSheetRuleCb({
id,
removes: [{ index: [...getNestedCSSRulePositions(this), index] }],
removes: [
{ index: [...getNestedCSSRulePositions(this as CSSRule), index] },
],
});
}
return unmodifiedFunctions[typeKey].deleteRule.apply(this, arguments);
return unmodifiedFunctions[typeKey].deleteRule.apply(this, [index]);
};
});
@@ -598,6 +614,7 @@ function initStyleDeclarationObserver(
{ styleDeclarationCb, mirror }: observerParam,
{ win }: { win: IWindow },
): listenerHandler {
// eslint-disable-next-line @typescript-eslint/unbound-method
const setProperty = win.CSSStyleDeclaration.prototype.setProperty;
win.CSSStyleDeclaration.prototype.setProperty = function (
this: CSSStyleDeclaration,
@@ -617,9 +634,10 @@ function initStyleDeclarationObserver(
index: getNestedCSSRulePositions(this.parentRule!),
});
}
return setProperty.apply(this, arguments);
return setProperty.apply(this, [property, value, priority]);
};
// eslint-disable-next-line @typescript-eslint/unbound-method
const removeProperty = win.CSSStyleDeclaration.prototype.removeProperty;
win.CSSStyleDeclaration.prototype.removeProperty = function (
this: CSSStyleDeclaration,
@@ -635,7 +653,7 @@ function initStyleDeclarationObserver(
index: getNestedCSSRulePositions(this.parentRule!),
});
}
return removeProperty.apply(this, arguments);
return removeProperty.apply(this, [property]);
};
return () => {
@@ -679,7 +697,9 @@ function initMediaInteractionObserver({
function initFontObserver({ fontCb, doc }: observerParam): listenerHandler {
const win = doc.defaultView as IWindow;
if (!win) {
return () => {};
return () => {
//
};
}
const handlers: listenerHandler[] = [];
@@ -689,7 +709,7 @@ function initFontObserver({ fontCb, doc }: observerParam): listenerHandler {
const originalFontFace = win.FontFace;
win.FontFace = (function FontFace(
family: string,
source: string | ArrayBufferView,
source: string | ArrayBufferLike,
descriptors?: FontFaceDescriptors,
) {
const fontFace = new originalFontFace(family, source, descriptors);
@@ -701,23 +721,27 @@ function initFontObserver({ fontCb, doc }: observerParam): listenerHandler {
typeof source === 'string'
? source
: // tslint:disable-next-line: no-any
JSON.stringify(Array.from(new Uint8Array(source as any))),
JSON.stringify(Array.from(new Uint8Array(source))),
});
return fontFace;
} as unknown) as typeof FontFace;
const restoreHandler = patch(doc.fonts, 'add', function (original) {
return function (this: FontFaceSet, fontFace: FontFace) {
setTimeout(() => {
const p = fontMap.get(fontFace);
if (p) {
fontCb(p);
fontMap.delete(fontFace);
}
}, 0);
return original.apply(this, [fontFace]);
};
});
const restoreHandler = patch(
doc.fonts,
'add',
function (original: (font: FontFace) => void) {
return function (this: FontFaceSet, fontFace: FontFace) {
setTimeout(() => {
const p = fontMap.get(fontFace);
if (p) {
fontCb(p);
fontMap.delete(fontFace);
}
}, 0);
return original.apply(this, [fontFace]);
};
},
);
handlers.push(() => {
win.FontFace = originalFontFace;
@@ -817,7 +841,9 @@ export function initObservers(
): listenerHandler {
const currentWindow = o.doc.defaultView; // basically document.window
if (!currentWindow) {
return () => {};
return () => {
//
};
}
mergeHooks(o, hooks);
@@ -833,7 +859,11 @@ export function initObservers(
const styleDeclarationObserver = initStyleDeclarationObserver(o, {
win: currentWindow,
});
const fontObserver = o.collectFonts ? initFontObserver(o) : () => {};
const fontObserver = o.collectFonts
? initFontObserver(o)
: () => {
//
};
// plugins
const pluginHandlers: listenerHandler[] = [];
for (const plugin of o.plugins) {

View File

@@ -31,7 +31,12 @@ export default function initCanvas2DMutationObserver(
const restoreHandler = patch(
win.CanvasRenderingContext2D.prototype,
prop,
function (original) {
function (
original: (
this: CanvasRenderingContext2D,
...args: unknown[]
) => void,
) {
return function (
this: CanvasRenderingContext2D,
...args: Array<unknown>
@@ -59,6 +64,7 @@ export default function initCanvas2DMutationObserver(
prop,
{
set(v) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
cb(this.canvas, {
type: CanvasContext['2D'],
property: prop,

View File

@@ -72,10 +72,10 @@ export class CanvasManager {
this.initCanvasFPSObserver(sampling, win, blockClass);
}
private processMutation: canvasManagerMutationCallback = function (
private processMutation: canvasManagerMutationCallback = (
target,
mutation,
) {
) => {
const newFrame =
this.rafStamps.invokeId &&
this.rafStamps.latestId !== this.rafStamps.invokeId;
@@ -148,7 +148,8 @@ export class CanvasManager {
lastSnapshotTime = timestamp;
win.document
.querySelectorAll(`canvas:not(.${blockClass} *)`)
.querySelectorAll(`canvas:not(.${blockClass as string} *)`)
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.forEach(async (canvas: HTMLCanvasElement) => {
const id = this.mirror.getId(canvas);
if (snapshotInProgressMap.get(id)) return;

View File

@@ -11,7 +11,13 @@ export default function initCanvasContextObserver(
const restoreHandler = patch(
win.HTMLCanvasElement.prototype,
'getContext',
function (original) {
function (
original: (
this: ICanvas,
contextType: string,
...args: Array<unknown>
) => void,
) {
return function (
this: ICanvas,
contextType: string,

View File

@@ -2,7 +2,7 @@ import { encode } from 'base64-arraybuffer';
import type { IWindow, CanvasArg } from '../../../types';
// TODO: unify with `replay/webgl.ts`
type CanvasVarMap = Map<string, any[]>;
type CanvasVarMap = Map<string, unknown[]>;
const canvasVarMap: Map<RenderingContext, CanvasVarMap> = new Map();
export function variableListFor(ctx: RenderingContext, ctor: string) {
let contextMap = canvasVarMap.get(ctx);
@@ -13,11 +13,11 @@ export function variableListFor(ctx: RenderingContext, ctor: string) {
if (!contextMap.has(ctor)) {
contextMap.set(ctor, []);
}
return contextMap.get(ctor) as any[];
return contextMap.get(ctor) as unknown[];
}
export const saveWebGLVar = (
value: any,
value: unknown,
win: IWindow,
ctx: RenderingContext,
): number | void => {
@@ -40,7 +40,7 @@ export const saveWebGLVar = (
// from webgl-recorder: https://github.com/evanw/webgl-recorder/blob/bef0e65596e981ee382126587e2dcbe0fc7748e2/webgl-recorder.js#L50-L77
export function serializeArg(
value: any,
value: unknown,
win: IWindow,
ctx: RenderingContext,
): CanvasArg {
@@ -125,11 +125,11 @@ export function serializeArg(
};
}
return value;
return value as CanvasArg;
}
export const serializeArgs = (
args: Array<any>,
args: Array<unknown>,
win: IWindow,
ctx: RenderingContext,
) => {
@@ -137,7 +137,7 @@ export const serializeArgs = (
};
export const isInstanceOfWebGLObject = (
value: any,
value: unknown,
win: IWindow,
): value is
| WebGLActiveInfo

View File

@@ -27,30 +27,36 @@ function patchGLPrototype(
if (typeof prototype[prop as keyof typeof prototype] !== 'function') {
continue;
}
const restoreHandler = patch(prototype, prop, function (original) {
return function (this: typeof prototype, ...args: Array<unknown>) {
const result = original.apply(this, args);
saveWebGLVar(result, win, prototype);
if (!isBlocked(this.canvas, blockClass, true)) {
const restoreHandler = patch(
prototype,
prop,
function (
original: (this: typeof prototype, ...args: Array<unknown>) => void,
) {
return function (this: typeof prototype, ...args: Array<unknown>) {
const result = original.apply(this, args);
saveWebGLVar(result, win, prototype);
if (!isBlocked(this.canvas, blockClass, true)) {
const recordArgs = serializeArgs([...args], win, prototype);
const mutation: canvasMutationWithType = {
type,
property: prop,
args: recordArgs,
};
// TODO: this could potentially also be an OffscreenCanvas as well as HTMLCanvasElement
cb(this.canvas, mutation);
}
const recordArgs = serializeArgs([...args], win, prototype);
const mutation: canvasMutationWithType = {
type,
property: prop,
args: recordArgs,
};
// TODO: this could potentially also be an OffscreenCanvas as well as HTMLCanvasElement
cb(this.canvas, mutation);
}
return result;
};
});
return result;
};
},
);
handlers.push(restoreHandler);
} catch {
const hookHandler = hookSetter<typeof prototype>(prototype, prop, {
set(v) {
// TODO: this could potentially also be an OffscreenCanvas as well as HTMLCanvasElement
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
cb(this.canvas as HTMLCanvasElement, {
type,
property: prop,

View File

@@ -34,16 +34,21 @@ export class ShadowDomManager {
this.mirror = options.mirror;
// Patch 'attachShadow' to observe newly added shadow doms.
// eslint-disable-next-line @typescript-eslint/no-this-alias
const manager = this;
this.restorePatches.push(
patch(HTMLElement.prototype, 'attachShadow', function (original) {
return function () {
const shadowRoot = original.apply(this, arguments);
if (this.shadowRoot)
manager.addShadowRoot(this.shadowRoot, this.ownerDocument);
return shadowRoot;
};
}),
patch(
HTMLElement.prototype,
'attachShadow',
function (original: (init: ShadowRootInit) => ShadowRoot) {
return function (this: HTMLElement, option: ShadowRootInit) {
const shadowRoot = original.call(this, option);
if (this.shadowRoot)
manager.addShadowRoot(this.shadowRoot, this.ownerDocument);
return shadowRoot;
};
},
),
);
}
@@ -73,6 +78,7 @@ export class ShadowDomManager {
*/
public observeAttachShadow(iframeElement: HTMLIFrameElement) {
if (iframeElement.contentWindow) {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const manager = this;
this.restorePatches.push(
patch(
@@ -80,9 +86,9 @@ export class ShadowDomManager {
HTMLElement: { prototype: HTMLElement };
}).HTMLElement.prototype,
'attachShadow',
function (original) {
return function () {
const shadowRoot = original.apply(this, arguments);
function (original: (init: ShadowRootInit) => ShadowRoot) {
return function (this: HTMLElement, option: ShadowRootInit) {
const shadowRoot = original.call(this, option);
if (this.shadowRoot)
manager.addShadowRoot(
this.shadowRoot,

View File

@@ -40,6 +40,7 @@ async function getTransparentBlobFor(
// `as any` because: https://github.com/Microsoft/TypeScript/issues/20595
const worker: ImageBitmapDataURLResponseWorker = self;
// eslint-disable-next-line @typescript-eslint/no-misused-promises
worker.onmessage = async function (e) {
if (!('OffscreenCanvas' in globalThis))
return worker.postMessage({ id: e.data.id });

View File

@@ -20,13 +20,13 @@ export default async function canvasMutation({
if (mutation.setter) {
// skip some read-only type checks
// tslint:disable-next-line:no-any
(ctx as any)[mutation.property] = mutation.args[0];
((ctx as unknown) as Record<string, unknown>)[mutation.property] =
mutation.args[0];
return;
}
const original = ctx[
mutation.property as Exclude<keyof typeof ctx, 'canvas'>
] as Function;
] as (ctx: CanvasRenderingContext2D, args: unknown[]) => void;
/**
* We have serialized the image source into base64 string during recording,
@@ -37,7 +37,7 @@ export default async function canvasMutation({
mutation.property === 'drawImage' &&
typeof mutation.args[0] === 'string'
) {
const image = imageMap.get(event);
imageMap.get(event);
original.apply(ctx, mutation.args);
} else {
const args = await Promise.all(

View File

@@ -23,6 +23,7 @@ export function variableListFor(
if (!contextMap.has(ctor)) {
contextMap.set(ctor, []);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return contextMap.get(ctor) as any[];
}
@@ -45,16 +46,21 @@ export function deserializeArg(
if (arg && typeof arg === 'object' && 'rr_type' in arg) {
if (preload) preload.isUnchanged = false;
if (arg.rr_type === 'ImageBitmap' && 'args' in arg) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const args = await deserializeArg(imageMap, ctx, preload)(arg.args);
// eslint-disable-next-line prefer-spread
return await createImageBitmap.apply(null, args);
} else if ('index' in arg) {
if (preload || ctx === null) return arg; // we are preloading, ctx is unknown
const { rr_type: name, index } = arg;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return variableListFor(ctx, name)[index];
} else if ('args' in arg) {
const { rr_type: name, args } = arg;
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const ctor = window[name as keyof Window];
// eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call
return new ctor(
...(await Promise.all(
args.map(deserializeArg(imageMap, ctx, preload)),
@@ -85,6 +91,7 @@ export function deserializeArg(
const result = await Promise.all(
arg.map(deserializeArg(imageMap, ctx, preload)),
);
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return result;
}
return arg;

View File

@@ -11,8 +11,9 @@ function getContext(
// you might have to do `ctx.flush()` before every webgl canvas event
try {
if (type === CanvasContext.WebGL) {
return (target.getContext('webgl')! ||
target.getContext('experimental-webgl'));
return (
target.getContext('webgl')! || target.getContext('experimental-webgl')
);
}
return target.getContext('webgl2')!;
} catch (e) {
@@ -37,11 +38,15 @@ function saveToWebGLVarMap(
ctx: WebGLRenderingContext | WebGL2RenderingContext,
result: any,
) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (!result?.constructor) return; // probably null or undefined
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-member-access
const { name } = result.constructor;
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
if (!WebGLVariableConstructorsNames.includes(name)) return; // not a WebGL variable
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
const variables = variableListFor(ctx, name);
if (!variables.includes(result)) variables.push(result);
}
@@ -69,13 +74,16 @@ export default async function webglMutation({
if (mutation.setter) {
// skip some read-only type checks
// tslint:disable-next-line:no-any
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
(ctx as any)[mutation.property] = mutation.args[0];
return;
}
const original = ctx[
mutation.property as Exclude<keyof typeof ctx, 'canvas'>
] as Function;
] as (
ctx: WebGLRenderingContext | WebGL2RenderingContext,
args: unknown[],
) => void;
const args = await Promise.all(
mutation.args.map(deserializeArg(imageMap, ctx)),
@@ -87,16 +95,21 @@ export default async function webglMutation({
const debugMode = false;
if (debugMode) {
if (mutation.property === 'compileShader') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
if (!ctx.getShaderParameter(args[0], ctx.COMPILE_STATUS))
console.warn(
'something went wrong in replay',
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
ctx.getShaderInfoLog(args[0]),
);
} else if (mutation.property === 'linkProgram') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
ctx.validateProgram(args[0]);
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
if (!ctx.getProgramParameter(args[0], ctx.LINK_STATUS))
console.warn(
'something went wrong in replay',
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
ctx.getProgramInfoLog(args[0]),
);
}
@@ -107,6 +120,7 @@ export default async function webglMutation({
webglError,
'on command:',
mutation.property,
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
...args,
);
}

View File

@@ -42,7 +42,6 @@ import {
viewportResizeDimension,
missingNodeMap,
addedNodeMutation,
missingNode,
incrementalSnapshotEvent,
incrementalData,
ReplayerEvents,
@@ -54,7 +53,6 @@ import {
scrollData,
inputData,
canvasMutationData,
styleAttributeValue,
styleValueWithPriority,
mouseMovePos,
IWindow,
@@ -83,8 +81,7 @@ const SKIP_TIME_THRESHOLD = 10 * 1000;
const SKIP_TIME_INTERVAL = 5 * 1000;
// https://github.com/rollup/rollup/issues/1267#issuecomment-296395734
// tslint:disable-next-line
const mitt = (mittProxy as any).default || mittProxy;
const mitt = mittProxy.default || mittProxy;
const REPLAY_CONSOLE_PREFIX = '[replayer]';
@@ -188,7 +185,7 @@ export class Replayer {
canvasMutationData: canvasMutationData,
target: HTMLCanvasElement,
) => {
canvasMutation({
void canvasMutation({
event: canvasEvent,
mutation: canvasMutationData,
target,
@@ -340,8 +337,10 @@ export class Replayer {
public setConfig(config: Partial<playerConfig>) {
Object.keys(config).forEach((key) => {
// @ts-ignore
this.config[key] = config[key];
const newConfigValue = config[key as keyof playerConfig];
(this.config as Record<keyof playerConfig, typeof newConfigValue>)[
key as keyof playerConfig
] = config[key as keyof playerConfig];
});
if (!this.config.skipInactive) {
this.backToNormal();
@@ -404,7 +403,7 @@ export class Replayer {
* So the implementation of play at any time offset will always iterate
* all of the events, cast event before the offset synchronously
* and cast event after the offset asynchronously with timer.
* @param timeOffset number
* @param timeOffset - number
*/
public play(timeOffset = 0) {
if (this.service.state.matches('paused')) {
@@ -452,7 +451,7 @@ export class Replayer {
if (indicatesTouchDevice(event)) {
this.mouse.classList.add('touch-device');
}
Promise.resolve().then(() =>
void Promise.resolve().then(() =>
this.service.send({ type: 'ADD_EVENT', payload: { event } }),
);
}
@@ -511,7 +510,7 @@ export class Replayer {
}
}
private handleResize(dimension: viewportResizeDimension) {
private handleResize = (dimension: viewportResizeDimension) => {
this.iframe.style.display = 'inherit';
for (const el of [this.mouseTail, this.iframe]) {
if (!el) {
@@ -520,9 +519,9 @@ export class Replayer {
el.setAttribute('width', String(dimension.width));
el.setAttribute('height', String(dimension.height));
}
}
};
private applyEventsSynchronously(events: Array<eventWithTime>) {
private applyEventsSynchronously = (events: Array<eventWithTime>) => {
for (const event of events) {
switch (event.type) {
case EventType.DomContentLoaded:
@@ -546,9 +545,9 @@ export class Replayer {
this.mouse.classList.remove('touch-active');
}
this.touchActive = null;
}
};
private getCastFn(event: eventWithTime, isSync = false) {
private getCastFn = (event: eventWithTime, isSync = false) => {
let castFn: undefined | (() => void);
switch (event.type) {
case EventType.DomContentLoaded:
@@ -671,7 +670,7 @@ export class Replayer {
this.emitter.emit(ReplayerEvents.EventCast, event);
};
return wrappedCastFn;
}
};
private rebuildFullSnapshot(
event: fullSnapshotEvent & { timestamp: number },
@@ -714,7 +713,7 @@ export class Replayer {
this.waitForStylesheetLoad();
}
if (this.config.UNSAFE_replayCanvas) {
this.preloadAllImages();
void this.preloadAllImages();
}
}
@@ -870,37 +869,6 @@ export class Replayer {
}
}
private hasImageArg(args: any[]): boolean {
for (const arg of args) {
if (!arg || typeof arg !== 'object') {
// do nothing
} else if ('rr_type' in arg && 'args' in arg) {
if (this.hasImageArg(arg.args)) return true;
} else if ('rr_type' in arg && arg.rr_type === 'HTMLImageElement') {
return true; // has image!
} else if (arg instanceof Array) {
if (this.hasImageArg(arg)) return true;
}
}
return false;
}
private getImageArgs(args: any[]): string[] {
const images: string[] = [];
for (const arg of args) {
if (!arg || typeof arg !== 'object') {
// do nothing
} else if ('rr_type' in arg && 'args' in arg) {
images.push(...this.getImageArgs(arg.args));
} else if ('rr_type' in arg && arg.rr_type === 'HTMLImageElement') {
images.push(arg.src);
} else if (arg instanceof Array) {
images.push(...this.getImageArgs(arg));
}
}
return images;
}
/**
* pause when there are some canvas drawImage args need to be loaded
*/
@@ -940,7 +908,7 @@ export class Replayer {
const ctx = canvas.getContext('2d');
const imgd = ctx?.createImageData(canvas.width, canvas.height);
let d = imgd?.data;
d = JSON.parse(data.args[0]);
d = JSON.parse(data.args[0]) as Uint8ClampedArray;
ctx?.putImageData(imgd!, 0, 0);
}
}
@@ -983,6 +951,7 @@ export class Replayer {
try {
this.applyMutation(d, isSync);
} catch (error) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
this.warn(`Exception in mutation ${error.message || error}`, d);
}
break;
@@ -1013,7 +982,9 @@ export class Replayer {
});
// add a dummy action to keep timer alive
this.timer.addAction({
doAction() {},
doAction() {
//
},
delay: e.delay! - d.positions[0]?.timeOffset,
});
}
@@ -1174,11 +1145,12 @@ export class Replayer {
// i.e. media will evntualy start to play when data is loaded
// 'canplay' event fires even when currentTime attribute changes which may lead to
// unexpeted behavior
mediaEl.play();
void mediaEl.play();
}
} catch (error) {
if (this.config.showWarning) {
console.warn(
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/restrict-template-expressions
`Failed to replay media interactions: ${error.message || error}`,
);
}
@@ -1322,7 +1294,7 @@ export class Replayer {
if (!target) {
return this.debugNodeNotFound(d, d.id);
}
canvasMutation({
void canvasMutation({
event: e,
mutation: d,
target: target as HTMLCanvasElement,
@@ -1337,7 +1309,9 @@ export class Replayer {
try {
const fontFace = new FontFace(
d.family,
d.buffer ? new Uint8Array(JSON.parse(d.fontSource)) : d.fontSource,
d.buffer
? new Uint8Array(JSON.parse(d.fontSource) as Iterable<number>)
: d.fontSource,
d.descriptors,
);
this.iframe.contentDocument?.fonts.add(fontFace);
@@ -1711,8 +1685,8 @@ export class Replayer {
/**
* Apply the scroll data on real elements.
* If the replayer is in sync mode, smooth scroll behavior should be disabled.
* @param d the scroll data
* @param isSync whether the replayer is in sync mode(fast-forward)
* @param d - the scroll data
* @param isSync - whether the replayer is in sync mode(fast-forward)
*/
private applyScroll(d: scrollData, isSync: boolean) {
const target = this.mirror.getNode(d.id);

View File

@@ -3,8 +3,8 @@
* Add support of customize target window and document
*/
/* eslint-disable */
// @ts-nocheck
// tslint:disable
export function polyfill(w: Window = window, d = document) {
// return if scroll behavior is supported and polyfill is not forced
if (

View File

@@ -19,7 +19,6 @@ export class Timer {
}
/**
* Add an action after the timer starts.
* @param action
*/
public addAction(action: actionWithDelay) {
const index = this.findActionIndex(action);
@@ -27,7 +26,6 @@ export class Timer {
}
/**
* Add all actions before the timer starts
* @param actions
*/
public addActions(actions: actionWithDelay[]) {
this.actions = this.actions.concat(actions);
@@ -37,25 +35,24 @@ export class Timer {
this.timeOffset = 0;
let lastTimestamp = performance.now();
const { actions } = this;
const self = this;
function check() {
const check = () => {
const time = performance.now();
self.timeOffset += (time - lastTimestamp) * self.speed;
this.timeOffset += (time - lastTimestamp) * this.speed;
lastTimestamp = time;
while (actions.length) {
const action = actions[0];
if (self.timeOffset >= action.delay) {
if (this.timeOffset >= action.delay) {
actions.shift();
action.doAction();
} else {
break;
}
}
if (actions.length > 0 || self.liveMode) {
self.raf = requestAnimationFrame(check);
if (actions.length > 0 || this.liveMode) {
this.raf = requestAnimationFrame(check);
}
}
};
this.raf = requestAnimationFrame(check);
}

View File

@@ -46,6 +46,7 @@ export class RRdomTreeNode implements AnyObject {
}
public setCachedIndex(parentNode: AnyObject, index: number) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
this.cachedIndexVersion = parentNode.childrenVersion;
this.cachedIndex = index;
}

View File

@@ -27,12 +27,12 @@ export enum EventType {
export type domContentLoadedEvent = {
type: EventType.DomContentLoaded;
data: {};
data: unknown;
};
export type loadedEvent = {
type: EventType.Load;
data: {};
data: unknown;
};
export type fullSnapshotEvent = {
@@ -76,8 +76,6 @@ export type pluginEvent<T = unknown> = {
};
};
export type styleSheetEvent = {};
export enum IncrementalSource {
Mutation,
MouseMove,
@@ -218,7 +216,11 @@ export type SamplingStrategy = Partial<{
export type RecordPlugin<TOptions = unknown> = {
name: string;
observer?: (cb: Function, win: IWindow, options: TOptions) => listenerHandler;
observer?: (
cb: (...args: Array<unknown>) => void,
win: IWindow,
options: TOptions,
) => listenerHandler;
eventProcessor?: <TExtend>(event: eventWithTime) => eventWithTime & TExtend;
options: TOptions;
};
@@ -285,8 +287,12 @@ export type observerParam = {
shadowDomManager: ShadowDomManager;
canvasManager: CanvasManager;
plugins: Array<{
observer: Function;
callback: Function;
observer: (
cb: (...arg: Array<unknown>) => void,
win: IWindow,
options: unknown,
) => listenerHandler;
callback: (...arg: Array<unknown>) => void;
options: unknown;
}>;
};

View File

@@ -57,6 +57,7 @@ if (typeof window !== 'undefined' && window.Proxy && window.Reflect) {
if (prop === 'map') {
console.error(DEPARTED_MIRROR_ACCESS_WARNING);
}
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Reflect.get(target, prop, receiver);
},
});
@@ -70,14 +71,14 @@ export function throttle<T>(
) {
let timeout: ReturnType<typeof setTimeout> | null = null;
let previous = 0;
return function (arg: T) {
return function (...args: T[]) {
const now = Date.now();
if (!previous && options.leading === false) {
previous = now;
}
const remaining = wait - (now - previous);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-this-alias
const context = this;
const args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
@@ -129,11 +130,13 @@ export function patch(
source: { [key: string]: any },
name: string,
// tslint:disable-next-line:no-any
replacement: (...args: any[]) => any,
replacement: (...args: unknown[]) => unknown,
): () => void {
try {
if (!(name in source)) {
return () => {};
return () => {
//
};
}
const original = source[name] as () => unknown;
@@ -143,6 +146,7 @@ export function patch(
// otherwise it'll throw "TypeError: Object.defineProperties called on non-object"
// tslint:disable-next-line:strict-type-predicates
if (typeof wrapped === 'function') {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
wrapped.prototype = wrapped.prototype || {};
Object.defineProperties(wrapped, {
__rrweb_original__: {
@@ -158,7 +162,9 @@ export function patch(
source[name] = original;
};
} catch {
return () => {};
return () => {
//
};
// This can throw if multiple fill happens on a global object like XMLHttpRequest
// Fixes https://github.com/getsentry/sentry-javascript/issues/2043
}
@@ -249,19 +255,22 @@ export function isTouchEvent(
export function polyfill(win = window) {
if ('NodeList' in win && !win.NodeList.prototype.forEach) {
// eslint-disable-next-line @typescript-eslint/unbound-method
win.NodeList.prototype.forEach = (Array.prototype
.forEach as unknown) as NodeList['forEach'];
}
if ('DOMTokenList' in win && !win.DOMTokenList.prototype.forEach) {
// eslint-disable-next-line @typescript-eslint/unbound-method
win.DOMTokenList.prototype.forEach = (Array.prototype
.forEach as unknown) as DOMTokenList['forEach'];
}
// https://github.com/Financial-Times/polyfill-service/pull/183
if (!Node.prototype.contains) {
Node.prototype.contains = function contains(node) {
if (!(0 in arguments)) {
Node.prototype.contains = (...args: unknown[]) => {
let node = args[0] as Node | null;
if (!(0 in args)) {
throw new TypeError('1 argument is required');
}
@@ -269,7 +278,6 @@ export function polyfill(win = window) {
if (this === node) {
return true;
}
// tslint:disable-next-line: no-conditional-assignment
} while ((node = node && node.parentNode));
return false;
@@ -426,8 +434,8 @@ export function getPositionsAndIndex(nestedIndex: number[]) {
/**
* Returns the latest mutation in the queue for each node.
* @param {textMutation[]} mutations The text mutations to filter.
* @returns {textMutation[]} The filtered text mutations.
* @param mutations - mutations The text mutations to filter.
* @returns The filtered text mutations.
*/
export function uniqueTextMutations(mutations: textMutation[]): textMutation[] {
const idSet = new Set<number>();

View File

@@ -12,7 +12,12 @@ import {
generateRecordSnippet,
ISuite,
} from './utils';
import { recordOptions, eventWithTime, EventType } from '../src/types';
import {
recordOptions,
eventWithTime,
EventType,
RecordPlugin,
} from '../src/types';
import { visitSnapshot, NodeType } from 'rrweb-snapshot';
describe('record integration tests', function (this: ISuite) {
@@ -442,8 +447,8 @@ describe('record integration tests', function (this: ISuite) {
const page: puppeteer.Page = await browser.newPage();
await page.goto('about:blank');
await page.setContent(
getHtml.call(this, 'log.html', {
plugins: '[rrwebConsoleRecord.getRecordConsolePlugin()]',
getHtml('log.html', {
plugins: ('[rrwebConsoleRecord.getRecordConsolePlugin()]' as unknown) as RecordPlugin<unknown>[],
}),
);

View File

@@ -11,7 +11,8 @@
"outDir": "build",
"lib": ["es6", "dom"],
"downlevelIteration": true,
"importsNotUsedAsValues": "error"
"importsNotUsedAsValues": "error",
"strictBindCallApply": true
},
"exclude": ["test"],
"include": [

View File

@@ -15,7 +15,6 @@ export declare type LogData = {
trace: string[];
payload: string[];
};
export declare type LogLevel = 'assert' | 'clear' | 'count' | 'countReset' | 'debug' | 'dir' | 'dirxml' | 'error' | 'group' | 'groupCollapsed' | 'groupEnd' | 'info' | 'log' | 'table' | 'time' | 'timeEnd' | 'timeLog' | 'trace' | 'warn';
export declare type Logger = {
assert?: typeof console.assert;
clear?: typeof console.clear;
@@ -37,6 +36,7 @@ export declare type Logger = {
trace?: typeof console.trace;
warn?: typeof console.warn;
};
export declare type LogLevel = keyof Logger;
export declare const PLUGIN_NAME = "rrweb/console@1";
export declare const getRecordConsolePlugin: (options?: LogRecordOptions) => RecordPlugin;
export {};

View File

@@ -1,2 +1,2 @@
import type { StringifyOptions } from './index';
export declare function stringify(obj: any, stringifyOptions?: StringifyOptions): string;
export declare function stringify(obj: unknown, stringifyOptions?: StringifyOptions): string;

View File

@@ -1,6 +1,6 @@
import type { IWindow, CanvasArg } from '../../../types';
export declare function variableListFor(ctx: RenderingContext, ctor: string): any[];
export declare const saveWebGLVar: (value: any, win: IWindow, ctx: RenderingContext) => number | void;
export declare function serializeArg(value: any, win: IWindow, ctx: RenderingContext): CanvasArg;
export declare const serializeArgs: (args: Array<any>, win: IWindow, ctx: RenderingContext) => CanvasArg[];
export declare const isInstanceOfWebGLObject: (value: any, win: IWindow) => value is WebGLTexture | WebGLShader | WebGLBuffer | WebGLVertexArrayObject | WebGLProgram | WebGLActiveInfo | WebGLUniformLocation | WebGLFramebuffer | WebGLRenderbuffer | WebGLShaderPrecisionFormat;
export declare function variableListFor(ctx: RenderingContext, ctor: string): unknown[];
export declare const saveWebGLVar: (value: unknown, win: IWindow, ctx: RenderingContext) => number | void;
export declare function serializeArg(value: unknown, win: IWindow, ctx: RenderingContext): CanvasArg;
export declare const serializeArgs: (args: Array<unknown>, win: IWindow, ctx: RenderingContext) => CanvasArg[];
export declare const isInstanceOfWebGLObject: (value: unknown, win: IWindow) => value is WebGLTexture | WebGLShader | WebGLBuffer | WebGLVertexArrayObject | WebGLProgram | WebGLActiveInfo | WebGLUniformLocation | WebGLFramebuffer | WebGLRenderbuffer | WebGLShaderPrecisionFormat;

View File

@@ -52,8 +52,6 @@ export declare class Replayer {
private attachDocumentToIframe;
private collectIframeAndAttachDocument;
private waitForStylesheetLoad;
private hasImageArg;
private getImageArgs;
private preloadAllImages;
private preloadImages;
private deserializeAndPreloadCanvasEvents;

View File

@@ -17,11 +17,11 @@ export declare enum EventType {
}
export declare type domContentLoadedEvent = {
type: EventType.DomContentLoaded;
data: {};
data: unknown;
};
export declare type loadedEvent = {
type: EventType.Load;
data: {};
data: unknown;
};
export declare type fullSnapshotEvent = {
type: EventType.FullSnapshot;
@@ -59,7 +59,6 @@ export declare type pluginEvent<T = unknown> = {
payload: T;
};
};
export declare type styleSheetEvent = {};
export declare enum IncrementalSource {
Mutation = 0,
MouseMove = 1,
@@ -134,7 +133,7 @@ export declare type SamplingStrategy = Partial<{
}>;
export declare type RecordPlugin<TOptions = unknown> = {
name: string;
observer?: (cb: Function, win: IWindow, options: TOptions) => listenerHandler;
observer?: (cb: (...args: Array<unknown>) => void, win: IWindow, options: TOptions) => listenerHandler;
eventProcessor?: <TExtend>(event: eventWithTime) => eventWithTime & TExtend;
options: TOptions;
};
@@ -198,8 +197,8 @@ export declare type observerParam = {
shadowDomManager: ShadowDomManager;
canvasManager: CanvasManager;
plugins: Array<{
observer: Function;
callback: Function;
observer: (cb: (...arg: Array<unknown>) => void, win: IWindow, options: unknown) => listenerHandler;
callback: (...arg: Array<unknown>) => void;
options: unknown;
}>;
};

View File

@@ -3,11 +3,11 @@ import type { IMirror, Mirror } from 'rrweb-snapshot';
import type { RRNode, RRIFrameElement } from 'rrdom';
export declare function on(type: string, fn: EventListenerOrEventListenerObject, target?: Document | IWindow): listenerHandler;
export declare let _mirror: DeprecatedMirror;
export declare function throttle<T>(func: (arg: T) => void, wait: number, options?: throttleOptions): (arg: T) => void;
export declare function throttle<T>(func: (arg: T) => void, wait: number, options?: throttleOptions): (...args: T[]) => void;
export declare function hookSetter<T>(target: T, key: string | number | symbol, d: PropertyDescriptor, isRevoked?: boolean, win?: Window & typeof globalThis): hookResetter;
export declare function patch(source: {
[key: string]: any;
}, name: string, replacement: (...args: any[]) => any): () => void;
}, name: string, replacement: (...args: unknown[]) => unknown): () => void;
export declare function getWindowHeight(): number;
export declare function getWindowWidth(): number;
export declare function isBlocked(node: Node | null, blockClass: blockClass, checkAncestors: boolean): boolean;