close #228 safe access content document, which may be destroyed manually

This commit is contained in:
Yanzhen Yu
2020-07-18 15:29:01 +08:00
parent 0756319b8e
commit c5580f97f4

View File

@@ -364,6 +364,9 @@ export class Replayer {
private rebuildFullSnapshot( private rebuildFullSnapshot(
event: fullSnapshotEvent & { timestamp: number }, event: fullSnapshotEvent & { timestamp: number },
) { ) {
if (!this.iframe.contentDocument) {
return console.warn('Looks like your replayer has been destroyed.');
}
if (Object.keys(this.legacy_missingNodeRetryMap).length) { if (Object.keys(this.legacy_missingNodeRetryMap).length) {
console.warn( console.warn(
'Found unresolved missing node map', 'Found unresolved missing node map',
@@ -371,9 +374,9 @@ export class Replayer {
); );
} }
this.legacy_missingNodeRetryMap = {}; this.legacy_missingNodeRetryMap = {};
mirror.map = rebuild(event.data.node, this.iframe.contentDocument!)[1]; mirror.map = rebuild(event.data.node, this.iframe.contentDocument)[1];
const styleEl = document.createElement('style'); const styleEl = document.createElement('style');
const { documentElement, head } = this.iframe.contentDocument!; const { documentElement, head } = this.iframe.contentDocument;
documentElement!.insertBefore(styleEl, head); documentElement!.insertBefore(styleEl, head);
const injectStylesRules = getInjectStyleRules( const injectStylesRules = getInjectStyleRules(
this.config.blockClass, this.config.blockClass,
@@ -389,7 +392,7 @@ export class Replayer {
* pause when loading style sheet, resume when loaded all timeout exceed * pause when loading style sheet, resume when loaded all timeout exceed
*/ */
private waitForStylesheetLoad() { private waitForStylesheetLoad() {
const { head } = this.iframe.contentDocument!; const head = this.iframe.contentDocument?.head;
if (head) { if (head) {
const unloadSheets: Set<HTMLLinkElement> = new Set(); const unloadSheets: Set<HTMLLinkElement> = new Set();
let timer: number; let timer: number;
@@ -638,12 +641,15 @@ export class Replayer {
const queue: addedNodeMutation[] = []; const queue: addedNodeMutation[] = [];
const appendNode = (mutation: addedNodeMutation) => { const appendNode = (mutation: addedNodeMutation) => {
if (!this.iframe.contentDocument) {
return console.warn('Looks like your replayer has been destroyed.');
}
let parent = mirror.getNode(mutation.parentId); let parent = mirror.getNode(mutation.parentId);
if (!parent) { if (!parent) {
return queue.push(mutation); return queue.push(mutation);
} }
const parentInDocument = this.iframe.contentDocument!.contains(parent); const parentInDocument = this.iframe.contentDocument.contains(parent);
if (useVirtualParent && parentInDocument) { if (useVirtualParent && parentInDocument) {
const virtualParent = (document.createDocumentFragment() as unknown) as INode; const virtualParent = (document.createDocumentFragment() as unknown) as INode;
mirror.map[mutation.parentId] = virtualParent; mirror.map[mutation.parentId] = virtualParent;
@@ -669,7 +675,7 @@ export class Replayer {
const target = buildNodeWithSN( const target = buildNodeWithSN(
mutation.node, mutation.node,
this.iframe.contentDocument!, this.iframe.contentDocument,
mirror.map, mirror.map,
true, true,
) as Node; ) as Node;
@@ -832,8 +838,8 @@ export class Replayer {
} }
private hoverElements(el: Element) { private hoverElements(el: Element) {
this.iframe this.iframe.contentDocument
.contentDocument!.querySelectorAll('.\\:hover') ?.querySelectorAll('.\\:hover')
.forEach((hoveredEl) => { .forEach((hoveredEl) => {
hoveredEl.classList.remove(':hover'); hoveredEl.classList.remove(':hover');
}); });