perf: Avoid an extra function call and object clone during event emission (#1441)
performance: remove a nested function call and an object clone during event emission - rename `event` to `eventWithoutTime`, but maintain backwards compatibility - `eventWithTime` (with time) could be renamed to `event` in a future version This is an extension of PR #1339 authored by: mydea <mydea@users.noreply.github.com>
This commit is contained in:
5
.changeset/event-single-wrap.md
Normal file
5
.changeset/event-single-wrap.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'rrweb': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf: Avoid an extra function call and object clone during event emission
|
||||||
@@ -3,7 +3,11 @@ import { genId, NodeType } from 'rrweb-snapshot';
|
|||||||
import type { CrossOriginIframeMessageEvent } from '../types';
|
import type { CrossOriginIframeMessageEvent } from '../types';
|
||||||
import CrossOriginIframeMirror from './cross-origin-iframe-mirror';
|
import CrossOriginIframeMirror from './cross-origin-iframe-mirror';
|
||||||
import { EventType, IncrementalSource } from '@rrweb/types';
|
import { EventType, IncrementalSource } from '@rrweb/types';
|
||||||
import type { eventWithTime, mutationCallBack } from '@rrweb/types';
|
import type {
|
||||||
|
eventWithTime,
|
||||||
|
eventWithoutTime,
|
||||||
|
mutationCallBack,
|
||||||
|
} from '@rrweb/types';
|
||||||
import type { StylesheetManager } from './stylesheet-manager';
|
import type { StylesheetManager } from './stylesheet-manager';
|
||||||
|
|
||||||
export class IframeManager {
|
export class IframeManager {
|
||||||
@@ -16,7 +20,7 @@ export class IframeManager {
|
|||||||
new WeakMap();
|
new WeakMap();
|
||||||
private mirror: Mirror;
|
private mirror: Mirror;
|
||||||
private mutationCb: mutationCallBack;
|
private mutationCb: mutationCallBack;
|
||||||
private wrappedEmit: (e: eventWithTime, isCheckout?: boolean) => void;
|
private wrappedEmit: (e: eventWithoutTime, isCheckout?: boolean) => void;
|
||||||
private loadListener?: (iframeEl: HTMLIFrameElement) => unknown;
|
private loadListener?: (iframeEl: HTMLIFrameElement) => unknown;
|
||||||
private stylesheetManager: StylesheetManager;
|
private stylesheetManager: StylesheetManager;
|
||||||
private recordCrossOriginIframes: boolean;
|
private recordCrossOriginIframes: boolean;
|
||||||
@@ -26,7 +30,7 @@ export class IframeManager {
|
|||||||
mutationCb: mutationCallBack;
|
mutationCb: mutationCallBack;
|
||||||
stylesheetManager: StylesheetManager;
|
stylesheetManager: StylesheetManager;
|
||||||
recordCrossOriginIframes: boolean;
|
recordCrossOriginIframes: boolean;
|
||||||
wrappedEmit: (e: eventWithTime, isCheckout?: boolean) => void;
|
wrappedEmit: (e: eventWithoutTime, isCheckout?: boolean) => void;
|
||||||
}) {
|
}) {
|
||||||
this.mutationCb = options.mutationCb;
|
this.mutationCb = options.mutationCb;
|
||||||
this.wrappedEmit = options.wrappedEmit;
|
this.wrappedEmit = options.wrappedEmit;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import {
|
|||||||
import type { recordOptions } from '../types';
|
import type { recordOptions } from '../types';
|
||||||
import {
|
import {
|
||||||
EventType,
|
EventType,
|
||||||
event,
|
eventWithoutTime,
|
||||||
eventWithTime,
|
eventWithTime,
|
||||||
IncrementalSource,
|
IncrementalSource,
|
||||||
listenerHandler,
|
listenerHandler,
|
||||||
@@ -40,14 +40,7 @@ import {
|
|||||||
unregisterErrorHandler,
|
unregisterErrorHandler,
|
||||||
} from './error-handler';
|
} from './error-handler';
|
||||||
|
|
||||||
function wrapEvent(e: event): eventWithTime {
|
let wrappedEmit!: (e: eventWithoutTime, isCheckout?: boolean) => void;
|
||||||
return {
|
|
||||||
...e,
|
|
||||||
timestamp: nowTimestamp(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
let wrappedEmit!: (e: eventWithTime, isCheckout?: boolean) => void;
|
|
||||||
|
|
||||||
let takeFullSnapshot!: (isCheckout?: boolean) => void;
|
let takeFullSnapshot!: (isCheckout?: boolean) => void;
|
||||||
let canvasManager!: CanvasManager;
|
let canvasManager!: CanvasManager;
|
||||||
@@ -187,7 +180,9 @@ function record<T = eventWithTime>(
|
|||||||
}
|
}
|
||||||
return e as unknown as T;
|
return e as unknown as T;
|
||||||
};
|
};
|
||||||
wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
|
wrappedEmit = (r: eventWithoutTime, isCheckout?: boolean) => {
|
||||||
|
const e = r as eventWithTime;
|
||||||
|
e.timestamp = nowTimestamp();
|
||||||
if (
|
if (
|
||||||
mutationBuffers[0]?.isFrozen() &&
|
mutationBuffers[0]?.isFrozen() &&
|
||||||
e.type !== EventType.FullSnapshot &&
|
e.type !== EventType.FullSnapshot &&
|
||||||
@@ -238,47 +233,39 @@ function record<T = eventWithTime>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const wrappedMutationEmit = (m: mutationCallbackParam) => {
|
const wrappedMutationEmit = (m: mutationCallbackParam) => {
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.Mutation,
|
||||||
source: IncrementalSource.Mutation,
|
...m,
|
||||||
...m,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
const wrappedScrollEmit: scrollCallback = (p) =>
|
const wrappedScrollEmit: scrollCallback = (p) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.Scroll,
|
||||||
source: IncrementalSource.Scroll,
|
...p,
|
||||||
...p,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
const wrappedCanvasMutationEmit = (p: canvasMutationParam) =>
|
const wrappedCanvasMutationEmit = (p: canvasMutationParam) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.CanvasMutation,
|
||||||
source: IncrementalSource.CanvasMutation,
|
...p,
|
||||||
...p,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const wrappedAdoptedStyleSheetEmit = (a: adoptedStyleSheetParam) =>
|
const wrappedAdoptedStyleSheetEmit = (a: adoptedStyleSheetParam) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.AdoptedStyleSheet,
|
||||||
source: IncrementalSource.AdoptedStyleSheet,
|
...a,
|
||||||
...a,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
const stylesheetManager = new StylesheetManager({
|
const stylesheetManager = new StylesheetManager({
|
||||||
mutationCb: wrappedMutationEmit,
|
mutationCb: wrappedMutationEmit,
|
||||||
@@ -350,14 +337,14 @@ function record<T = eventWithTime>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
wrappedEmit(
|
wrappedEmit(
|
||||||
wrapEvent({
|
{
|
||||||
type: EventType.Meta,
|
type: EventType.Meta,
|
||||||
data: {
|
data: {
|
||||||
href: window.location.href,
|
href: window.location.href,
|
||||||
width: getWindowWidth(),
|
width: getWindowWidth(),
|
||||||
height: getWindowHeight(),
|
height: getWindowHeight(),
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
isCheckout,
|
isCheckout,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -406,13 +393,13 @@ function record<T = eventWithTime>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
wrappedEmit(
|
wrappedEmit(
|
||||||
wrapEvent({
|
{
|
||||||
type: EventType.FullSnapshot,
|
type: EventType.FullSnapshot,
|
||||||
data: {
|
data: {
|
||||||
node,
|
node,
|
||||||
initialOffset: getWindowScroll(window),
|
initialOffset: getWindowScroll(window),
|
||||||
},
|
},
|
||||||
}),
|
},
|
||||||
isCheckout,
|
isCheckout,
|
||||||
);
|
);
|
||||||
mutationBuffers.forEach((buf) => buf.unlock()); // generate & emit any mutations that happened during snapshotting, as can now apply against the newly built mirror
|
mutationBuffers.forEach((buf) => buf.unlock()); // generate & emit any mutations that happened during snapshotting, as can now apply against the newly built mirror
|
||||||
@@ -433,108 +420,88 @@ function record<T = eventWithTime>(
|
|||||||
{
|
{
|
||||||
mutationCb: wrappedMutationEmit,
|
mutationCb: wrappedMutationEmit,
|
||||||
mousemoveCb: (positions, source) =>
|
mousemoveCb: (positions, source) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source,
|
||||||
source,
|
positions,
|
||||||
positions,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
mouseInteractionCb: (d) =>
|
mouseInteractionCb: (d) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.MouseInteraction,
|
||||||
source: IncrementalSource.MouseInteraction,
|
...d,
|
||||||
...d,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
scrollCb: wrappedScrollEmit,
|
scrollCb: wrappedScrollEmit,
|
||||||
viewportResizeCb: (d) =>
|
viewportResizeCb: (d) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.ViewportResize,
|
||||||
source: IncrementalSource.ViewportResize,
|
...d,
|
||||||
...d,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
inputCb: (v) =>
|
inputCb: (v) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.Input,
|
||||||
source: IncrementalSource.Input,
|
...v,
|
||||||
...v,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
mediaInteractionCb: (p) =>
|
mediaInteractionCb: (p) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.MediaInteraction,
|
||||||
source: IncrementalSource.MediaInteraction,
|
...p,
|
||||||
...p,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
styleSheetRuleCb: (r) =>
|
styleSheetRuleCb: (r) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.StyleSheetRule,
|
||||||
source: IncrementalSource.StyleSheetRule,
|
...r,
|
||||||
...r,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
styleDeclarationCb: (r) =>
|
styleDeclarationCb: (r) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.StyleDeclaration,
|
||||||
source: IncrementalSource.StyleDeclaration,
|
...r,
|
||||||
...r,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
canvasMutationCb: wrappedCanvasMutationEmit,
|
canvasMutationCb: wrappedCanvasMutationEmit,
|
||||||
fontCb: (p) =>
|
fontCb: (p) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.Font,
|
||||||
source: IncrementalSource.Font,
|
...p,
|
||||||
...p,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
selectionCb: (p) => {
|
selectionCb: (p) => {
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.Selection,
|
||||||
source: IncrementalSource.Selection,
|
...p,
|
||||||
...p,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
customElementCb: (c) => {
|
customElementCb: (c) => {
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.IncrementalSnapshot,
|
||||||
type: EventType.IncrementalSnapshot,
|
data: {
|
||||||
data: {
|
source: IncrementalSource.CustomElement,
|
||||||
source: IncrementalSource.CustomElement,
|
...c,
|
||||||
...c,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
blockClass,
|
blockClass,
|
||||||
ignoreClass,
|
ignoreClass,
|
||||||
@@ -570,15 +537,13 @@ function record<T = eventWithTime>(
|
|||||||
observer: p.observer!,
|
observer: p.observer!,
|
||||||
options: p.options,
|
options: p.options,
|
||||||
callback: (payload: object) =>
|
callback: (payload: object) =>
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.Plugin,
|
||||||
type: EventType.Plugin,
|
data: {
|
||||||
data: {
|
plugin: p.name,
|
||||||
plugin: p.name,
|
payload,
|
||||||
payload,
|
},
|
||||||
},
|
}),
|
||||||
}),
|
|
||||||
),
|
|
||||||
})) || [],
|
})) || [],
|
||||||
},
|
},
|
||||||
hooks,
|
hooks,
|
||||||
@@ -607,12 +572,10 @@ function record<T = eventWithTime>(
|
|||||||
} else {
|
} else {
|
||||||
handlers.push(
|
handlers.push(
|
||||||
on('DOMContentLoaded', () => {
|
on('DOMContentLoaded', () => {
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.DomContentLoaded,
|
||||||
type: EventType.DomContentLoaded,
|
data: {},
|
||||||
data: {},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
if (recordAfter === 'DOMContentLoaded') init();
|
if (recordAfter === 'DOMContentLoaded') init();
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
@@ -620,12 +583,10 @@ function record<T = eventWithTime>(
|
|||||||
on(
|
on(
|
||||||
'load',
|
'load',
|
||||||
() => {
|
() => {
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.Load,
|
||||||
type: EventType.Load,
|
data: {},
|
||||||
data: {},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
if (recordAfter === 'load') init();
|
if (recordAfter === 'load') init();
|
||||||
},
|
},
|
||||||
window,
|
window,
|
||||||
@@ -648,15 +609,13 @@ record.addCustomEvent = <T>(tag: string, payload: T) => {
|
|||||||
if (!recording) {
|
if (!recording) {
|
||||||
throw new Error('please add custom event after start recording');
|
throw new Error('please add custom event after start recording');
|
||||||
}
|
}
|
||||||
wrappedEmit(
|
wrappedEmit({
|
||||||
wrapEvent({
|
type: EventType.Custom,
|
||||||
type: EventType.Custom,
|
data: {
|
||||||
data: {
|
tag,
|
||||||
tag,
|
payload,
|
||||||
payload,
|
},
|
||||||
},
|
});
|
||||||
}),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
record.freezePage = () => {
|
record.freezePage = () => {
|
||||||
|
|||||||
@@ -3,10 +3,10 @@ import {
|
|||||||
EventType,
|
EventType,
|
||||||
IncrementalSource,
|
IncrementalSource,
|
||||||
eventWithTime,
|
eventWithTime,
|
||||||
|
eventWithoutTime,
|
||||||
MouseInteractions,
|
MouseInteractions,
|
||||||
Optional,
|
Optional,
|
||||||
mouseInteractionData,
|
mouseInteractionData,
|
||||||
event,
|
|
||||||
pluginEvent,
|
pluginEvent,
|
||||||
} from '@rrweb/types';
|
} from '@rrweb/types';
|
||||||
import type { recordOptions } from '../src/types';
|
import type { recordOptions } from '../src/types';
|
||||||
@@ -228,7 +228,7 @@ function stringifySnapshots(snapshots: eventWithTime[]): string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
delete (s as Optional<eventWithTime, 'timestamp'>).timestamp;
|
delete (s as Optional<eventWithTime, 'timestamp'>).timestamp;
|
||||||
return s as event;
|
return s as eventWithoutTime;
|
||||||
}),
|
}),
|
||||||
null,
|
null,
|
||||||
2,
|
2,
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ export type incrementalData =
|
|||||||
| adoptedStyleSheetData
|
| adoptedStyleSheetData
|
||||||
| customElementData;
|
| customElementData;
|
||||||
|
|
||||||
export type event =
|
export type eventWithoutTime =
|
||||||
| domContentLoadedEvent
|
| domContentLoadedEvent
|
||||||
| loadedEvent
|
| loadedEvent
|
||||||
| fullSnapshotEvent
|
| fullSnapshotEvent
|
||||||
@@ -172,7 +172,13 @@ export type event =
|
|||||||
| customEvent
|
| customEvent
|
||||||
| pluginEvent;
|
| pluginEvent;
|
||||||
|
|
||||||
export type eventWithTime = event & {
|
/**
|
||||||
|
* @deprecated intended for internal use
|
||||||
|
* a synonym for eventWithoutTime
|
||||||
|
*/
|
||||||
|
export type event = eventWithoutTime;
|
||||||
|
|
||||||
|
export type eventWithTime = eventWithoutTime & {
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
delay?: number;
|
delay?: number;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user