Skip to content

Commit f99b00e

Browse files
authored
Ignore firstFullSnapshot once only after initial 'poster' build (#608)
* Encountered a bug where firstFullSnapshot was played twice because timer was immediately started and reached the snapshot before the setTimeout returned * Ignoring a FullSnapshot needs to be a one-time only thing, as otherwise we'll ignore it after scrubbing (restarting play head at a particular time). This is a problem if mutations have altered the player state, and we try to replay those mutations, so we e.g. try to remove an element that has already been removed because we haven't reset the FullSnapshot state * Some `npm run typings` related fixups
1 parent 55f7f4f commit f99b00e

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

src/replay/index.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ export class Replayer {
8989
private imageMap: Map<eventWithTime, HTMLImageElement> = new Map();
9090

9191
private mirror: Mirror = createMirror();
92-
/** The first time the player is playing. */
93-
private firstPlayedEvent: eventWithTime | null = null;
92+
93+
private firstFullSnapshot: eventWithTime | true | null = null;
9494

9595
private newDocumentQueue: addedNodeMutation[] = [];
9696

@@ -145,7 +145,7 @@ export class Replayer {
145145
}
146146
});
147147
this.emitter.on(ReplayerEvents.PlayBack, () => {
148-
this.firstPlayedEvent = null;
148+
this.firstFullSnapshot = null;
149149
this.mirror.reset();
150150
});
151151

@@ -207,10 +207,11 @@ export class Replayer {
207207
if (firstFullsnapshot) {
208208
setTimeout(() => {
209209
// when something has been played, there is no need to rebuild poster
210-
if (this.firstPlayedEvent) {
210+
if (this.firstFullSnapshot) {
211+
// true if any other fullSnapshot has been executed by Timer already
211212
return;
212213
}
213-
this.firstPlayedEvent = firstFullsnapshot;
214+
this.firstFullSnapshot = firstFullsnapshot;
214215
this.rebuildFullSnapshot(
215216
firstFullsnapshot as fullSnapshotEvent & { timestamp: number },
216217
);
@@ -429,9 +430,15 @@ export class Replayer {
429430
break;
430431
case EventType.FullSnapshot:
431432
castFn = () => {
432-
// Don't build a full snapshot during the first play through since we've already built it when the player was mounted.
433-
if (this.firstPlayedEvent && this.firstPlayedEvent === event) {
434-
return;
433+
if (this.firstFullSnapshot) {
434+
if (this.firstFullSnapshot === event) {
435+
// we've already built this exact FullSnapshot when the player was mounted, and haven't built any other FullSnapshot since
436+
this.firstFullSnapshot = true; // forget as we might need to re-execute this FullSnapshot later e.g. to rebuild after scrubbing
437+
return;
438+
}
439+
} else {
440+
// Timer (requestAnimationFrame) can be faster than setTimeout(..., 1)
441+
this.firstFullSnapshot = true;
435442
}
436443
this.rebuildFullSnapshot(event, isSync);
437444
this.iframe.contentWindow!.scrollTo(event.data.initialOffset);

typings/replay/index.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export declare class Replayer {
2020
private elementStateMap;
2121
private imageMap;
2222
private mirror;
23-
private firstPlayedEvent;
23+
private firstFullSnapshot;
2424
private newDocumentQueue;
2525
constructor(events: Array<eventWithTime | string>, config?: Partial<playerConfig>);
2626
on(event: string, handler: Handler): this;

0 commit comments

Comments
 (0)