Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Refactor module scope vars & export mirror & takeFullSnapshot directly #113

Merged
merged 3 commits into from
Oct 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@
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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔

so rrweb1 did have mirror exported directly, but they deprecated that -- I'm not sure the reasoning (it's possible they wanted to keep compatibility and decided to have a different interface to mirror, but maybe worthwhile to dig in and see why they changed public interface to mirror.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah so that mirror was different - it was a shared mirror for recording/replaying, I believe (also that mirror was a noop by now).

This is different in that we just always export the recording mirror from @sentry/rrweb.


const mirror = createMirror();
function record<T = eventWithTime>(
options: recordOptions<T> = {},
): listenerHandler | undefined {
Expand Down Expand Up @@ -211,7 +212,7 @@
}
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 @@ -260,6 +261,7 @@
}
}
};
_wrappedEmit = wrappedEmit;

const wrappedMutationEmit = (m: mutationCallbackParam) => {
wrappedEmit(
Expand Down Expand Up @@ -335,7 +337,7 @@

const processedNodeManager = new ProcessedNodeManager();

canvasManager =
const canvasManager: CanvasManagerInterface =
typeof __RRWEB_EXCLUDE_CANVAS__ === 'boolean' && __RRWEB_EXCLUDE_CANVAS__
? new CanvasManagerNoop()
: new CanvasManager({
Expand Down Expand Up @@ -386,7 +388,7 @@
mirror,
});

takeFullSnapshot = (isCheckout = false) => {
const takeFullSnapshot = (isCheckout = false) => {
wrappedEmit(
wrapEvent({
type: EventType.Meta,
Expand Down Expand Up @@ -468,6 +470,7 @@
mirror.getId(document),
);
};
_takeFullSnapshot = takeFullSnapshot;

try {
const handlers: listenerHandler[] = [];
Expand Down Expand Up @@ -616,7 +619,7 @@
plugins
?.filter((p) => p.observer)
?.map((p) => ({
observer: p.observer!,

Check warning on line 622 in packages/rrweb/src/record/index.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb/src/record/index.ts#L622

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
options: p.options,
callback: (payload: object) =>
wrappedEmit(
Expand All @@ -636,7 +639,7 @@

iframeManager.addLoadListener((iframeEl) => {
try {
handlers.push(observe(iframeEl.contentDocument!));

Check warning on line 642 in packages/rrweb/src/record/index.ts

View workflow job for this annotation

GitHub Actions / ESLint Report Analysis

packages/rrweb/src/record/index.ts#L642

[@typescript-eslint/no-non-null-assertion] Forbidden non-null assertion.
} catch (error) {
// TODO: handle internal error
console.warn(error);
Expand All @@ -646,7 +649,6 @@
const init = () => {
takeFullSnapshot();
handlers.push(observe(document));
recording = true;
};
if (
document.readyState === 'interactive' ||
Expand Down Expand Up @@ -684,7 +686,7 @@
return () => {
handlers.forEach((h) => h());
processedNodeManager.destroy();
recording = false;
_takeFullSnapshot = undefined;
unregisterErrorHandler();
};
} catch (error) {
Expand All @@ -693,11 +695,11 @@
}
}

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 @@ -706,19 +708,24 @@
},
}),
);
};
}

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
Loading