fix(client): handle missing document in preview frame (#44833)
This commit is contained in:
committed by
GitHub
parent
5aaf8677d4
commit
f88473f994
@ -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 => {
|
||||||
|
Reference in New Issue
Block a user