Commit e872907b authored by Dan Abramov's avatar Dan Abramov Committed by GitHub
Browse files

Fix error overlay in Firefox (#749)

parent 2b7a4f14
Showing with 95 additions and 40 deletions
+95 -40
......@@ -39,13 +39,10 @@ var colors = {
};
ansiHTML.setColors(colors);
function showErrorOverlay(message) {
// Use an iframe so that document styles don't mess up the overlay.
var iframeID = 'react-dev-utils-webpack-hot-dev-client-overlay';
var iframe =
document.getElementById(iframeID) ||
document.createElement('iframe');
iframe.id = iframeID;
function createOverlayIframe(onIframeLoad) {
var iframe = document.createElement('iframe');
iframe.id = 'react-dev-utils-webpack-hot-dev-client-overlay';
iframe.src = 'about:blank';
iframe.style.position = 'fixed';
iframe.style.left = 0;
iframe.style.top = 0;
......@@ -55,39 +52,74 @@ function showErrorOverlay(message) {
iframe.style.height = '100vh';
iframe.style.border = 'none';
iframe.style.zIndex = 9999999999;
document.body.appendChild(iframe);
// Inside, make a div.
var overlayID = 'react-dev-utils-webpack-hot-dev-client-overlay-div';
var overlay =
iframe.contentDocument.getElementById(overlayID) ||
iframe.contentDocument.createElement('div');
overlay.id = overlayID;
overlay.style.position = 'fixed';
overlay.style.left = 0;
overlay.style.top = 0;
overlay.style.right = 0;
overlay.style.bottom = 0;
overlay.style.width = '100vw';
overlay.style.height = '100vh';
overlay.style.backgroundColor = 'black';
overlay.style.color = '#E8E8E8';
overlay.style.fontFamily = 'Menlo, Consolas, monospace';
overlay.style.fontSize = 'large';
overlay.style.padding = '2rem';
overlay.style.lineHeight = '1.2';
overlay.style.whiteSpace = 'pre-wrap';
overlay.style.overflow = 'auto';
// Make it look similar to our terminal.
overlay.innerHTML =
'<span style="color: #' +
colors.red +
'">Failed to compile.</span><br><br>' +
ansiHTML(entities.encode(message));
// Render!
iframe.contentDocument.body.appendChild(overlay);
iframe.onload = onIframeLoad;
return iframe;
}
function addOverlayDivTo(iframe) {
var div = iframe.contentDocument.createElement('div');
div.id = 'react-dev-utils-webpack-hot-dev-client-overlay-div';
div.style.position = 'fixed';
div.style.left = 0;
div.style.top = 0;
div.style.right = 0;
div.style.bottom = 0;
div.style.width = '100vw';
div.style.height = '100vh';
div.style.backgroundColor = 'black';
div.style.color = '#E8E8E8';
div.style.fontFamily = 'Menlo, Consolas, monospace';
div.style.fontSize = 'large';
div.style.padding = '2rem';
div.style.lineHeight = '1.2';
div.style.whiteSpace = 'pre-wrap';
div.style.overflow = 'auto';
iframe.contentDocument.body.appendChild(div);
return div;
}
var overlayIframe = null;
var overlayDiv = null;
var lastOnOverlayDivReady = null;
function ensureOverlayDivExists(onOverlayDivReady) {
if (overlayDiv) {
// Everything is ready, call the callback right away.
onOverlayDivReady(overlayDiv);
return;
}
// Creating an iframe may be asynchronous so we'll schedule the callback.
// In case of multiple calls, last callback wins.
lastOnOverlayDivReady = onOverlayDivReady;
if (overlayIframe) {
// We're already creating it.
return;
}
// Create iframe and, when it is ready, a div inside it.
overlayIframe = createOverlayIframe(function onIframeLoad() {
overlayDiv = addOverlayDivTo(overlayIframe);
// Now we can talk!
lastOnOverlayDivReady(overlayDiv);
});
// Zalgo alert: onIframeLoad() will be called either synchronouly
// or asynchronously depending on the browser.
// We delay adding it so `overlayIframe` is set when `onIframeLoad` fires.
document.body.appendChild(overlayIframe);
}
function showErrorOverlay(message) {
ensureOverlayDivExists(function onOverlayDivReady(overlayDiv) {
// Make it look similar to our terminal.
overlayDiv.innerHTML =
'<span style="color: #' +
colors.red +
'">Failed to compile.</span><br><br>' +
ansiHTML(entities.encode(message));
});
}
// Connect to WebpackDevServer via a socket.
......@@ -105,11 +137,22 @@ var connection = new SockJS(url.format({
// Remember some state related to hot module replacement.
var isFirstCompilation = true;
var mostRecentCompilationHash = null;
var hasCompileErrors = false;
function clearOutdatedErrors() {
// Clean up outdated compile errors, if any.
if (hasCompileErrors && typeof console.clear === 'function') {
console.clear();
}
}
// Successful compilation.
function handleSuccess() {
clearOutdatedErrors();
var isHotUpdate = !isFirstCompilation;
isFirstCompilation = false;
hasCompileErrors = false;
// Attempt to apply hot updates or reload.
if (isHotUpdate) {
......@@ -119,8 +162,11 @@ function handleSuccess() {
// Compilation with warnings (e.g. ESLint).
function handleWarnings(warnings) {
clearOutdatedErrors();
var isHotUpdate = !isFirstCompilation;
isFirstCompilation = false;
hasCompileErrors = false;
function printWarnings() {
// Print warnings to the console.
......@@ -144,7 +190,10 @@ function handleWarnings(warnings) {
// Compilation with errors (e.g. syntax error or missing modules).
function handleErrors(errors) {
clearOutdatedErrors();
isFirstCompilation = false;
hasCompileErrors = true;
// "Massage" webpack messages.
var formatted = formatWebpackMessages({
......@@ -154,6 +203,12 @@ function handleErrors(errors) {
// Only show the first error.
showErrorOverlay(formatted.errors[0]);
// Also log them to the console.
for (var i = 0; i < formatted.errors.length; i++) {
console.error(stripAnsi(formatted.errors[i]));
}
// Do not attempt to reload now.
// We will reload on next success instead.
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment