Fix race condition in mermaid observer (#32599)

This Pull Request addresses a race condition in the updateIframeHeight
function where it is sometimes called when the iframe is not fully
loaded or accessible resulting in an alarming error message for the
user.

To address this we:
1. Add defensive programming within the updateIframeHeight function
2. Delay instantiating the intersection observer until the iframe has
loaded

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
william-allspice 2024-11-26 00:37:24 -06:00 committed by GitHub
parent 9ed768adc4
commit 88f5d33ab2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -58,16 +58,12 @@ export async function renderMermaid(): Promise<void> {
mermaidBlock.append(btn); mermaidBlock.append(btn);
const updateIframeHeight = () => { const updateIframeHeight = () => {
iframe.style.height = `${iframe.contentWindow.document.body.clientHeight}px`; const body = iframe.contentWindow?.document?.body;
if (body) {
iframe.style.height = `${body.clientHeight}px`;
}
}; };
// update height when element's visibility state changes, for example when the diagram is inside
// a <details> + <summary> block and the <details> block becomes visible upon user interaction, it
// would initially set a incorrect height and the correct height is set during this callback.
(new IntersectionObserver(() => {
updateIframeHeight();
}, {root: document.documentElement})).observe(iframe);
iframe.addEventListener('load', () => { iframe.addEventListener('load', () => {
pre.replaceWith(mermaidBlock); pre.replaceWith(mermaidBlock);
mermaidBlock.classList.remove('tw-hidden'); mermaidBlock.classList.remove('tw-hidden');
@ -76,6 +72,13 @@ export async function renderMermaid(): Promise<void> {
mermaidBlock.classList.remove('is-loading'); mermaidBlock.classList.remove('is-loading');
iframe.classList.remove('tw-invisible'); iframe.classList.remove('tw-invisible');
}, 0); }, 0);
// update height when element's visibility state changes, for example when the diagram is inside
// a <details> + <summary> block and the <details> block becomes visible upon user interaction, it
// would initially set a incorrect height and the correct height is set during this callback.
(new IntersectionObserver(() => {
updateIframeHeight();
}, {root: document.documentElement})).observe(iframe);
}); });
document.body.append(mermaidBlock); document.body.append(mermaidBlock);