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 = { ...@@ -39,13 +39,10 @@ var colors = {
}; };
ansiHTML.setColors(colors); ansiHTML.setColors(colors);
function showErrorOverlay(message) { function createOverlayIframe(onIframeLoad) {
// Use an iframe so that document styles don't mess up the overlay. var iframe = document.createElement('iframe');
var iframeID = 'react-dev-utils-webpack-hot-dev-client-overlay'; iframe.id = 'react-dev-utils-webpack-hot-dev-client-overlay';
var iframe = iframe.src = 'about:blank';
document.getElementById(iframeID) ||
document.createElement('iframe');
iframe.id = iframeID;
iframe.style.position = 'fixed'; iframe.style.position = 'fixed';
iframe.style.left = 0; iframe.style.left = 0;
iframe.style.top = 0; iframe.style.top = 0;
...@@ -55,39 +52,74 @@ function showErrorOverlay(message) { ...@@ -55,39 +52,74 @@ function showErrorOverlay(message) {
iframe.style.height = '100vh'; iframe.style.height = '100vh';
iframe.style.border = 'none'; iframe.style.border = 'none';
iframe.style.zIndex = 9999999999; iframe.style.zIndex = 9999999999;
document.body.appendChild(iframe); iframe.onload = onIframeLoad;
return iframe;
// Inside, make a div. }
var overlayID = 'react-dev-utils-webpack-hot-dev-client-overlay-div';
var overlay = function addOverlayDivTo(iframe) {
iframe.contentDocument.getElementById(overlayID) || var div = iframe.contentDocument.createElement('div');
iframe.contentDocument.createElement('div'); div.id = 'react-dev-utils-webpack-hot-dev-client-overlay-div';
overlay.id = overlayID; div.style.position = 'fixed';
overlay.style.position = 'fixed'; div.style.left = 0;
overlay.style.left = 0; div.style.top = 0;
overlay.style.top = 0; div.style.right = 0;
overlay.style.right = 0; div.style.bottom = 0;
overlay.style.bottom = 0; div.style.width = '100vw';
overlay.style.width = '100vw'; div.style.height = '100vh';
overlay.style.height = '100vh'; div.style.backgroundColor = 'black';
overlay.style.backgroundColor = 'black'; div.style.color = '#E8E8E8';
overlay.style.color = '#E8E8E8'; div.style.fontFamily = 'Menlo, Consolas, monospace';
overlay.style.fontFamily = 'Menlo, Consolas, monospace'; div.style.fontSize = 'large';
overlay.style.fontSize = 'large'; div.style.padding = '2rem';
overlay.style.padding = '2rem'; div.style.lineHeight = '1.2';
overlay.style.lineHeight = '1.2'; div.style.whiteSpace = 'pre-wrap';
overlay.style.whiteSpace = 'pre-wrap'; div.style.overflow = 'auto';
overlay.style.overflow = 'auto'; iframe.contentDocument.body.appendChild(div);
return div;
// Make it look similar to our terminal. }
overlay.innerHTML =
'<span style="color: #' + var overlayIframe = null;
colors.red + var overlayDiv = null;
'">Failed to compile.</span><br><br>' + var lastOnOverlayDivReady = null;
ansiHTML(entities.encode(message));
function ensureOverlayDivExists(onOverlayDivReady) {
// Render! if (overlayDiv) {
iframe.contentDocument.body.appendChild(overlay); // 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. // Connect to WebpackDevServer via a socket.
...@@ -105,11 +137,22 @@ var connection = new SockJS(url.format({ ...@@ -105,11 +137,22 @@ var connection = new SockJS(url.format({
// Remember some state related to hot module replacement. // Remember some state related to hot module replacement.
var isFirstCompilation = true; var isFirstCompilation = true;
var mostRecentCompilationHash = null; 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. // Successful compilation.
function handleSuccess() { function handleSuccess() {
clearOutdatedErrors();
var isHotUpdate = !isFirstCompilation; var isHotUpdate = !isFirstCompilation;
isFirstCompilation = false; isFirstCompilation = false;
hasCompileErrors = false;
// Attempt to apply hot updates or reload. // Attempt to apply hot updates or reload.
if (isHotUpdate) { if (isHotUpdate) {
...@@ -119,8 +162,11 @@ function handleSuccess() { ...@@ -119,8 +162,11 @@ function handleSuccess() {
// Compilation with warnings (e.g. ESLint). // Compilation with warnings (e.g. ESLint).
function handleWarnings(warnings) { function handleWarnings(warnings) {
clearOutdatedErrors();
var isHotUpdate = !isFirstCompilation; var isHotUpdate = !isFirstCompilation;
isFirstCompilation = false; isFirstCompilation = false;
hasCompileErrors = false;
function printWarnings() { function printWarnings() {
// Print warnings to the console. // Print warnings to the console.
...@@ -144,7 +190,10 @@ function handleWarnings(warnings) { ...@@ -144,7 +190,10 @@ function handleWarnings(warnings) {
// Compilation with errors (e.g. syntax error or missing modules). // Compilation with errors (e.g. syntax error or missing modules).
function handleErrors(errors) { function handleErrors(errors) {
clearOutdatedErrors();
isFirstCompilation = false; isFirstCompilation = false;
hasCompileErrors = true;
// "Massage" webpack messages. // "Massage" webpack messages.
var formatted = formatWebpackMessages({ var formatted = formatWebpackMessages({
...@@ -154,6 +203,12 @@ function handleErrors(errors) { ...@@ -154,6 +203,12 @@ function handleErrors(errors) {
// Only show the first error. // Only show the first error.
showErrorOverlay(formatted.errors[0]); 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. // Do not attempt to reload now.
// We will reload on next success instead. // 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