Skip to content

Commit

Permalink
Add overlay for build errors when using hmr (#1074)
Browse files Browse the repository at this point in the history
  • Loading branch information
lmontopo authored and devongovett committed Mar 28, 2018
1 parent ba93b87 commit 32c796d
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 16 deletions.
39 changes: 39 additions & 0 deletions src/builtins/hmr-runtime.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
var OVERLAY_ID = '__parcel__error__overlay__';

var global = (1, eval)('this');
var OldModule = module.bundle.Module;

Expand Down Expand Up @@ -49,14 +51,51 @@ if ((!parent || !parent.isParcelRequire) && typeof WebSocket !== 'undefined') {

if (data.type === 'error-resolved') {
console.log('[parcel] ✨ Error resolved');

removeErrorOverlay();
}

if (data.type === 'error') {
console.error('[parcel] 🚨 ' + data.error.message + '\n' + data.error.stack);

removeErrorOverlay();

var overlay = createErrorOverlay(data);
document.body.appendChild(overlay);
}
};
}

function removeErrorOverlay() {
var overlay = document.getElementById(OVERLAY_ID);
if (overlay) {
overlay.remove();
}
}

function createErrorOverlay(data) {
var overlay = document.createElement('div');
overlay.id = OVERLAY_ID;

// html encode message and stack trace
var message = document.createElement('div');
var stackTrace = document.createElement('pre');
message.innerText = data.error.message;
stackTrace.innerText = data.error.stack;

overlay.innerHTML = (
'<div style="background: black; font-size: 16px; color: white; position: fixed; height: 100%; width: 100%; top: 0px; left: 0px; padding: 30px; opacity: 0.85; font-family: Menlo, Consolas, monospace; z-index: 9999;">' +
'<span style="background: red; padding: 2px 4px; border-radius: 2px;">ERROR</span>' +
'<span style="top: 2px; margin-left: 5px; position: relative;">🚨</span>' +
'<div style="font-size: 18px; font-weight: bold; margin-top: 20px;">' + message.innerHTML + '</div>' +
'<pre>' + stackTrace.innerHTML + '</pre>' +
'</div>'
);

return overlay;

}

function getParents(bundle, id) {
var modules = bundle.modules;
if (!modules) {
Expand Down
52 changes: 36 additions & 16 deletions test/hmr.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const promisify = require('../src/utils/promisify');
const ncp = promisify(require('ncp'));
const WebSocket = require('ws');
const json5 = require('json5');
const sinon = require('sinon');

describe('hmr', function() {
let b, ws;
Expand Down Expand Up @@ -299,20 +300,26 @@ describe('hmr', function() {
assert.deepEqual(outputs, [3, 10]);
});

it('should log emitted errors', async function() {
it('should log emitted errors and show an error overlay', async function() {
await ncp(__dirname + '/integration/commonjs', __dirname + '/input');

b = bundler(__dirname + '/input/index.js', {watch: true, hmr: true});
let bundle = await b.bundle();

let logs = [];
run(bundle, {
console: {
error(msg) {
logs.push(msg);
let ctx = run(
bundle,
{
console: {
error(msg) {
logs.push(msg);
}
}
}
});
},
{require: false}
);

let spy = sinon.spy(ctx.document.body, 'appendChild');

fs.writeFileSync(
__dirname + '/input/local.js',
Expand All @@ -323,6 +330,7 @@ describe('hmr', function() {

assert.equal(logs.length, 1);
assert(logs[0].trim().startsWith('[parcel] 🚨'));
assert(spy.calledOnce);
});

it('should log when errors resolve', async function() {
Expand All @@ -332,22 +340,32 @@ describe('hmr', function() {
let bundle = await b.bundle();

let logs = [];
run(bundle, {
console: {
error(msg) {
logs.push(msg);
},
log(msg) {
logs.push(msg);
let ctx = run(
bundle,
{
console: {
error(msg) {
logs.push(msg);
},
log(msg) {
logs.push(msg);
}
}
}
});
},
{require: false}
);

let appendSpy = sinon.spy(ctx.document.body, 'appendChild');
let removeSpy = sinon.spy(ctx.document.getElementById('tmp'), 'remove');

fs.writeFileSync(
__dirname + '/input/local.js',
'require("fs"; exports.a = 5; exports.b = 5;'
);
await nextEvent(b, 'buildEnd');
await sleep(50);

assert(appendSpy.called);

fs.writeFileSync(
__dirname + '/input/local.js',
Expand All @@ -356,6 +374,8 @@ describe('hmr', function() {
await nextEvent(b, 'buildEnd');
await sleep(50);

assert(removeSpy.called);

assert.equal(logs.length, 2);
assert(logs[0].trim().startsWith('[parcel] 🚨'));
assert(logs[1].trim().startsWith('[parcel] ✨'));
Expand Down
14 changes: 14 additions & 0 deletions test/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ function bundle(file, opts) {

function prepareBrowserContext(bundle, globals) {
// for testing dynamic imports
const fakeElement = {
remove() {}
};

const fakeDocument = {
createElement(tag) {
return {tag};
Expand All @@ -68,6 +72,16 @@ function prepareBrowserContext(bundle, globals) {
}
}
];
},

getElementById() {
return fakeElement;
},

body: {
appendChild() {
return null;
}
}
};

Expand Down

0 comments on commit 32c796d

Please sign in to comment.