Skip to content

Commit

Permalink
feat: Refactor module scope vars & export mirror & `takeFullSnapsho…
Browse files Browse the repository at this point in the history
…t` directly (#113)

Currently, we use these from `record.xx`, which is not ideal thinking
about treeshaking and lazy loading.

This moves these to be proper exports so we can use the in Replay
without having to import `record` and everything that comes with it
(=everything).
  • Loading branch information
mydea committed Oct 27, 2023
1 parent 42ffd92 commit ab97f8f
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 37 deletions.
13 changes: 2 additions & 11 deletions packages/rrweb/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import record from './record';
import { Replayer } from './replay';
import { _mirror } from './utils';
import * as utils from './utils';

export {
Expand All @@ -19,14 +18,6 @@ export type {

export type { recordOptions } from './types';

const { addCustomEvent } = record;
const { freezePage } = record;
export { record, Replayer, utils };

export {
record,
addCustomEvent,
freezePage,
Replayer,
_mirror as mirror,
utils,
};
export { takeFullSnapshot, mirror, freezePage, addCustomEvent } from './record';
47 changes: 27 additions & 20 deletions packages/rrweb/src/record/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,14 @@ declare global {
const __RRWEB_EXCLUDE_IFRAME__: boolean;
}

let wrappedEmit!: (e: eventWithTime, isCheckout?: boolean) => void;
// These are stored in module scope because we access them in other exported methods
let _wrappedEmit:
| undefined
| ((e: eventWithTime, isCheckout?: boolean) => void);
let _takeFullSnapshot: undefined | ((isCheckout?: boolean) => void);

let takeFullSnapshot!: (isCheckout?: boolean) => void;
let canvasManager: CanvasManagerInterface;
let recording = false;
export const mirror = createMirror();

const mirror = createMirror();
function record<T = eventWithTime>(
options: recordOptions<T> = {},
): listenerHandler | undefined {
Expand Down Expand Up @@ -206,7 +207,7 @@ function record<T = eventWithTime>(
}
return e as unknown as T;
};
wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
const wrappedEmit = (e: eventWithTime, isCheckout?: boolean) => {
if (
mutationBuffers[0]?.isFrozen() &&
e.type !== EventType.FullSnapshot &&
Expand Down Expand Up @@ -255,6 +256,7 @@ function record<T = eventWithTime>(
}
}
};
_wrappedEmit = wrappedEmit;

const wrappedMutationEmit = (m: mutationCallbackParam) => {
wrappedEmit(
Expand Down Expand Up @@ -322,7 +324,7 @@ function record<T = eventWithTime>(

const processedNodeManager = new ProcessedNodeManager();

canvasManager =
const canvasManager: CanvasManagerInterface =
typeof __RRWEB_EXCLUDE_CANVAS__ === 'boolean' && __RRWEB_EXCLUDE_CANVAS__
? new CanvasManagerNoop()
: new CanvasManager({
Expand Down Expand Up @@ -373,7 +375,7 @@ function record<T = eventWithTime>(
mirror,
});

takeFullSnapshot = (isCheckout = false) => {
const takeFullSnapshot = (isCheckout = false) => {
wrappedEmit(
wrapEvent({
type: EventType.Meta,
Expand Down Expand Up @@ -455,6 +457,7 @@ function record<T = eventWithTime>(
mirror.getId(document),
);
};
_takeFullSnapshot = takeFullSnapshot;

try {
const handlers: listenerHandler[] = [];
Expand Down Expand Up @@ -617,7 +620,6 @@ function record<T = eventWithTime>(
const init = () => {
takeFullSnapshot();
handlers.push(observe(document));
recording = true;
};
if (
document.readyState === 'interactive' ||
Expand Down Expand Up @@ -655,7 +657,7 @@ function record<T = eventWithTime>(
return () => {
handlers.forEach((h) => h());
processedNodeManager.destroy();
recording = false;
_takeFullSnapshot = undefined;
unregisterErrorHandler();
};
} catch (error) {
Expand All @@ -664,11 +666,11 @@ function record<T = eventWithTime>(
}
}

record.addCustomEvent = <T>(tag: string, payload: T) => {
if (!recording) {
export function addCustomEvent<T>(tag: string, payload: T) {
if (!_wrappedEmit) {
throw new Error('please add custom event after start recording');
}
wrappedEmit(
_wrappedEmit(
wrapEvent({
type: EventType.Custom,
data: {
Expand All @@ -677,19 +679,24 @@ record.addCustomEvent = <T>(tag: string, payload: T) => {
},
}),
);
};
}

record.freezePage = () => {
export function freezePage() {
mutationBuffers.forEach((buf) => buf.freeze());
};
}

record.takeFullSnapshot = (isCheckout?: boolean) => {
if (!recording) {
export function takeFullSnapshot(isCheckout?: boolean) {
if (!_takeFullSnapshot) {
throw new Error('please take full snapshot after start recording');
}
takeFullSnapshot(isCheckout);
};
_takeFullSnapshot(isCheckout);
}

// record.addCustomEvent is removed because Sentry Session Replay does not use it
// record.freezePage is removed because Sentry Session Replay does not use it

// For backwards compatibility - we can eventually remove this when we migrated to using the exported `mirror` & `takeFullSnapshot`
record.mirror = mirror;
record.takeFullSnapshot = takeFullSnapshot;

export default record;
10 changes: 4 additions & 6 deletions packages/rrweb/test/record.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@ interface ISuite {

interface IWindow extends Window {
rrweb: {
record: ((
record: (
options: recordOptions<eventWithTime>,
) => listenerHandler | undefined) & {
takeFullSnapshot: (isCheckout?: boolean | undefined) => void;
};

) => listenerHandler | undefined;
takeFullSnapshot: (isCheckout?: boolean | undefined) => void;
freezePage(): void;
addCustomEvent<T>(tag: string, payload: T): void;
};
Expand Down Expand Up @@ -611,7 +609,7 @@ describe('record', function (this: ISuite) {

setTimeout(() => {
// When a full snapshot is checked out manually, all adoptedStylesheets should also be captured.
rrweb.record.takeFullSnapshot(true);
rrweb.takeFullSnapshot(true);
resolve(undefined);
}, 10);
});
Expand Down

0 comments on commit ab97f8f

Please sign in to comment.