fix(client): handle missing document in preview frame (#44833)

This commit is contained in:
Oliver Eyton-Williams
2022-01-20 14:22:25 +01:00
committed by GitHub
parent 5aaf8677d4
commit f88473f994

View File

@ -9,6 +9,8 @@ const testId = 'fcc-test-frame';
// the project preview frame demos the finished project // the project preview frame demos the finished project
export const projectPreviewId = 'fcc-project-preview-frame'; export const projectPreviewId = 'fcc-project-preview-frame';
const DOCUMENT_NOT_FOUND_ERROR = 'document not found';
// base tag here will force relative links // base tag here will force relative links
// within iframe to point to '' instead of // within iframe to point to '' instead of
// append to the current challenge url // append to the current challenge url
@ -103,48 +105,60 @@ const buildProxyConsole = proxyLogger => ctx => {
}; };
const initTestFrame = frameReady => ctx => { const initTestFrame = frameReady => ctx => {
waitForFrame(ctx).then(async () => { waitForFrame(ctx)
const { sources, loadEnzyme } = ctx; .then(async () => {
// default for classic challenges const { sources, loadEnzyme } = ctx;
// should not be used for modern // default for classic challenges
const code = { // should not be used for modern
contents: sources.index, const code = {
editableContents: sources.editableContents contents: sources.index,
}; editableContents: sources.editableContents
// provide the file name and get the original source };
const getUserInput = fileName => toString(sources[fileName]); // provide the file name and get the original source
await ctx.document.__initTestFrame({ code, getUserInput, loadEnzyme }); const getUserInput = fileName => toString(sources[fileName]);
frameReady(); await ctx.document.__initTestFrame({ code, getUserInput, loadEnzyme });
}); frameReady();
})
.catch(handleDocumentNotFound);
return ctx; return ctx;
}; };
const initMainFrame = (_, proxyLogger) => ctx => { const initMainFrame = (_, proxyLogger) => ctx => {
waitForFrame(ctx).then(() => { waitForFrame(ctx)
// Overwriting the onerror added by createHeader to catch any errors thrown .then(() => {
// after the frame is ready. It has to be overwritten, as proxyLogger cannot // Overwriting the onerror added by createHeader to catch any errors thrown
// be added as part of createHeader. // after the frame is ready. It has to be overwritten, as proxyLogger cannot
ctx.window.onerror = function (msg) { // be added as part of createHeader.
var string = msg.toLowerCase(); ctx.window.onerror = function (msg) {
if (string.includes('script error')) { var string = msg.toLowerCase();
msg = 'Error, open your browser console to learn more.'; if (string.includes('script error')) {
} msg = 'Error, open your browser console to learn more.';
if (proxyLogger) { }
proxyLogger(msg); if (proxyLogger) {
} proxyLogger(msg);
// let the error propagate so it appears in the browser console, otherwise }
// an error from a cross origin script just appears as 'Script error.' // let the error propagate so it appears in the browser console, otherwise
return false; // an error from a cross origin script just appears as 'Script error.'
}; return false;
}); };
})
.catch(handleDocumentNotFound);
return ctx; return ctx;
}; };
function handleDocumentNotFound(err) {
if (err !== DOCUMENT_NOT_FOUND_ERROR) {
console.log(err);
}
}
const initPreviewFrame = () => ctx => ctx; const initPreviewFrame = () => ctx => ctx;
const waitForFrame = ctx => { const waitForFrame = ctx => {
return new Promise(resolve => { return new Promise((resolve, reject) => {
if (ctx.document.readyState === 'loading') { if (!ctx.document) {
reject(DOCUMENT_NOT_FOUND_ERROR);
} else if (ctx.document.readyState === 'loading') {
ctx.document.addEventListener('DOMContentLoaded', resolve); ctx.document.addEventListener('DOMContentLoaded', resolve);
} else { } else {
resolve(); resolve();
@ -153,10 +167,13 @@ const waitForFrame = ctx => {
}; };
function writeToFrame(content, frame) { function writeToFrame(content, frame) {
frame.open(); // it's possible, if the preview is rapidly opened and closed, for the frame
frame.write(content); // to be null at this point.
frame.close(); if (frame) {
return frame; frame.open();
frame.write(content);
frame.close();
}
} }
const writeContentToFrame = ctx => { const writeContentToFrame = ctx => {