Skip to content

Commit d0996b9

Browse files
committed
fix: fixes several cases where we access an undefined value (#171)
Fixes several cases where we access an undefined value. In the case of `lastFullSnapshotEvent`, it can be undefined if we receive an incremental event before a full snapshot. This can happen, for example, if a user refreshes while canvas worker is working and on reload it finishes to call the mutation callback and before fullsnapshot occurs. Fixes JAVASCRIPT-2S3R Fixes JAVASCRIPT-2QS1 Fixes JAVASCRIPT-2FQ5 Fixes JAVASCRIPT-2H2H
1 parent 7e60935 commit d0996b9

File tree

2 files changed

+16
-8
lines changed

2 files changed

+16
-8
lines changed

packages/rrweb/src/record/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ function record<T = eventWithTime>(
252252
checkoutEveryNth && incrementalSnapshotCount >= checkoutEveryNth;
253253
const exceedTime =
254254
checkoutEveryNms &&
255+
lastFullSnapshotEvent &&
255256
e.timestamp - lastFullSnapshotEvent.timestamp > checkoutEveryNms;
256257
if (exceedCount || exceedTime) {
257258
takeFullSnapshot(true);

packages/rrweb/src/replay/index.ts

+15-8
Original file line numberDiff line numberDiff line change
@@ -815,9 +815,10 @@ export class Replayer {
815815
const { documentElement, head } = this.iframe.contentDocument;
816816
this.insertStyleRules(documentElement, head);
817817
if (!this.service.state.matches('playing')) {
818-
this.iframe.contentDocument
819-
.getElementsByTagName('html')[0]
820-
.classList.add('rrweb-paused');
818+
const iframeHtmlElement =
819+
this.iframe.contentDocument.getElementsByTagName('html')[0];
820+
821+
iframeHtmlElement && iframeHtmlElement.classList.add('rrweb-paused');
821822
}
822823
this.emitter.emit(ReplayerEvents.FullsnapshotRebuilded, event);
823824
if (!isSync) {
@@ -1960,7 +1961,8 @@ export class Replayer {
19601961
styleSheet.rules,
19611962
data.index,
19621963
) as unknown as CSSStyleRule;
1963-
rule.style &&
1964+
rule &&
1965+
rule.style &&
19641966
rule.style.setProperty(
19651967
data.set.property,
19661968
data.set.value,
@@ -1973,7 +1975,7 @@ export class Replayer {
19731975
styleSheet.rules,
19741976
data.index,
19751977
) as unknown as CSSStyleRule;
1976-
rule.style && rule.style.removeProperty(data.remove.property);
1978+
rule && rule.style && rule.style.removeProperty(data.remove.property);
19771979
}
19781980
}
19791981

@@ -2131,11 +2133,16 @@ export class Replayer {
21312133
}
21322134

21332135
private hoverElements(el: Element) {
2134-
(this.lastHoveredRootNode || this.iframe.contentDocument)
2135-
?.querySelectorAll('.\\:hover')
2136-
.forEach((hoveredEl) => {
2136+
const rootElement = this.lastHoveredRootNode || this.iframe.contentDocument;
2137+
2138+
// Sometimes this throws because `querySelectorAll` is not a function,
2139+
// unsure of value of rootElement when this occurs
2140+
if (rootElement && typeof rootElement.querySelectorAll === 'function') {
2141+
rootElement.querySelectorAll('.\\:hover').forEach((hoveredEl) => {
21372142
hoveredEl.classList.remove(':hover');
21382143
});
2144+
}
2145+
21392146
this.lastHoveredRootNode = el.getRootNode() as Document | ShadowRoot;
21402147
let currentEl: Element | null = el;
21412148
while (currentEl) {

0 commit comments

Comments
 (0)