Skip to content

Commit 1cd6c4e

Browse files
committed
better error messages in HMR
events for ignored updates warnings to console when updates are ignored
1 parent 6748dca commit 1cd6c4e

28 files changed

Lines changed: 291 additions & 42 deletions

File tree

hot/only-dev-server.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,14 @@ if(module.hot) {
1717
}
1818

1919
module.hot.apply({
20-
ignoreUnaccepted: true
20+
ignoreUnaccepted: true,
21+
ignoreDeclined: true,
22+
onUnaccepted: function(data) {
23+
console.warn("Ignored an update to unaccepted module " + data.chain.join(" -> "));
24+
},
25+
onDeclined: function(data) {
26+
console.warn("Ignored an update to declined module " + data.chain.join(" -> "));
27+
}
2128
}).then(function(renewedModules) {
2229
if(!upToDate()) {
2330
check();

lib/HotModuleReplacement.runtime.js

Lines changed: 80 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,11 @@ module.exports = function() {
9999
decline: function(dep) {
100100
if(typeof dep === "undefined")
101101
hot._selfDeclined = true;
102-
else if(typeof dep === "number")
103-
hot._declinedDependencies[dep] = true;
104-
else
102+
else if(typeof dep === "object")
105103
for(var i = 0; i < dep.length; i++)
106104
hot._declinedDependencies[dep[i]] = true;
105+
else
106+
hot._declinedDependencies[dep] = true;
107107
},
108108
dispose: function(callback) {
109109
hot._disposeHandlers.push(callback);
@@ -260,24 +260,44 @@ module.exports = function() {
260260
var outdatedModules = [module];
261261
var outdatedDependencies = {};
262262

263-
var queue = outdatedModules.slice();
263+
var queue = outdatedModules.slice().map(function(id) {
264+
return {
265+
chain: [id],
266+
id: id
267+
}
268+
});
264269
while(queue.length > 0) {
265-
var moduleId = queue.pop();
270+
var queueItem = queue.pop();
271+
var moduleId = queueItem.id;
272+
var chain = queueItem.chain;
266273
module = installedModules[moduleId];
267274
if(!module || module.hot._selfAccepted)
268275
continue;
269276
if(module.hot._selfDeclined) {
270-
return new Error("Aborted because of self decline: " + moduleId);
277+
return {
278+
type: "self-declined",
279+
chain: chain,
280+
moduleId: moduleId
281+
}
271282
}
272283
if(module.hot._main) {
273-
return;
284+
return {
285+
type: "unaccepted",
286+
chain: chain,
287+
moduleId: moduleId
288+
};
274289
}
275290
for(var i = 0; i < module.parents.length; i++) {
276291
var parentId = module.parents[i];
277292
var parent = installedModules[parentId];
278293
if(!parent) continue;
279294
if(parent.hot._declinedDependencies[moduleId]) {
280-
return new Error("Aborted because of declined dependency: " + moduleId + " in " + parentId);
295+
return {
296+
type: "declined",
297+
chain: chain.concat([parentId]),
298+
moduleId: moduleId,
299+
parentId: parentId
300+
}
281301
}
282302
if(outdatedModules.indexOf(parentId) >= 0) continue;
283303
if(parent.hot._acceptedDependencies[moduleId]) {
@@ -288,11 +308,18 @@ module.exports = function() {
288308
}
289309
delete outdatedDependencies[parentId];
290310
outdatedModules.push(parentId);
291-
queue.push(parentId);
311+
queue.push({
312+
chain: chain.concat([parentId]),
313+
id: parentId
314+
});
292315
}
293316
}
294317

295-
return [outdatedModules, outdatedDependencies];
318+
return {
319+
type: "accepted",
320+
outdatedModules: outdatedModules,
321+
outdatedDependencies: outdatedDependencies
322+
};
296323
}
297324

298325
function addAllToSet(a, b) {
@@ -312,37 +339,52 @@ module.exports = function() {
312339
if(Object.prototype.hasOwnProperty.call(hotUpdate, id)) {
313340
moduleId = toModuleId(id);
314341
var result = getAffectedStuff(moduleId);
315-
if(!result) {
316-
if(options.ignoreUnaccepted)
317-
continue;
318-
hotSetStatus("abort");
319-
var unacceptedParents = [];
320-
module = installedModules[moduleId];
321-
if(module) {
322-
for(i = 0; i < module.parents.length; i++) {
323-
var parentId = module.parents[i];
324-
var parent = installedModules[parentId];
325-
if(parent && !parent.hot._acceptedDependencies[moduleId]) {
326-
unacceptedParents.push(parentId);
327-
}
328-
}
329-
}
330-
var message = "Aborted because " + moduleId + " is not accepted";
331-
if(unacceptedParents.length > 0)
332-
message += " (used by " + unacceptedParents.join(", ") + ")";
333-
return Promise.reject(new Error(message));
342+
var abortError = false;
343+
var doApply = false;
344+
var chainInfo = "";
345+
if(result.chain) {
346+
chainInfo = "\nUpdate propagation: " + result.chain.join(" -> ");
334347
}
335-
if(result instanceof Error) {
348+
switch(result.type) {
349+
case "self-declined":
350+
if(options.onDeclined)
351+
options.onDeclined(result);
352+
if(!options.ignoreDeclined)
353+
abortError = new Error("Aborted because of self decline: " + result.moduleId + chainInfo);
354+
break;
355+
case "declined":
356+
if(options.onDeclined)
357+
options.onDeclined(result);
358+
if(!options.ignoreDeclined)
359+
abortError = new Error("Aborted because of declined dependency: " + result.moduleId + " in " + result.parentId + chainInfo);
360+
break;
361+
case "unaccepted":
362+
if(options.onUnaccepted)
363+
options.onUnaccepted(result);
364+
if(!options.ignoreUnaccepted)
365+
abortError = new Error("Aborted because " + moduleId + " is not accepted" + chainInfo);
366+
break;
367+
case "accepted":
368+
if(options.onAccepted)
369+
options.onAccepted(result);
370+
doApply = true;
371+
break;
372+
default:
373+
throw new Error("Unexception type " + result.type);
374+
}
375+
if(abortError) {
336376
hotSetStatus("abort");
337-
return Promise.reject(result);
377+
return Promise.reject(abortError);
338378
}
339-
appliedUpdate[moduleId] = hotUpdate[moduleId];
340-
addAllToSet(outdatedModules, result[0]);
341-
for(moduleId in result[1]) {
342-
if(Object.prototype.hasOwnProperty.call(result[1], moduleId)) {
343-
if(!outdatedDependencies[moduleId])
344-
outdatedDependencies[moduleId] = [];
345-
addAllToSet(outdatedDependencies[moduleId], result[1][moduleId]);
379+
if(doApply) {
380+
appliedUpdate[moduleId] = hotUpdate[moduleId];
381+
addAllToSet(outdatedModules, result.outdatedModules);
382+
for(moduleId in result.outdatedDependencies) {
383+
if(Object.prototype.hasOwnProperty.call(result.outdatedDependencies, moduleId)) {
384+
if(!outdatedDependencies[moduleId])
385+
outdatedDependencies[moduleId] = [];
386+
addAllToSet(outdatedDependencies[moduleId], result.outdatedDependencies[moduleId]);
387+
}
346388
}
347389
}
348390
}

test/HotTestCases.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ describe("HotTestCases", function() {
4747
},
4848
target: "async-node",
4949
plugins: [
50-
new webpack.HotModuleReplacementPlugin()
50+
new webpack.HotModuleReplacementPlugin(),
51+
new webpack.NamedModulesPlugin()
5152
],
5253
recordsPath: recordsPath,
5354
updateIndex: 0

test/hotCases/errors/decline/a.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import b from "./b";
2+
3+
export default b;
4+
5+
if(module.hot) {
6+
module.hot.decline("./b");
7+
module.hot.accept();
8+
}

test/hotCases/errors/decline/b.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { default } from "./c"

test/hotCases/errors/decline/c.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default 1;
2+
---
3+
export default 2;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import a from "./a";
2+
3+
it("should abort when module is declined by parent", function(done) {
4+
a.should.be.eql(1);
5+
NEXT(require("../../update")(function(err) {
6+
try {
7+
err.message.should.match(/Aborted because of declined dependency: \.\/b\.js in \.\/a\.js\nUpdate propagation: \.\/c\.js -> \.\/b\.js -> \.\/a\.js/);
8+
done();
9+
} catch(e) { done(e); }
10+
}));
11+
});

test/hotCases/errors/events/a.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default 1;
2+
---
3+
export default 2;

test/hotCases/errors/events/b.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import c from "./c"
2+
3+
if(module.hot) {
4+
module.hot.accept("./c");
5+
}

test/hotCases/errors/events/c.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export default 1;
2+
---
3+
export default 2;

0 commit comments

Comments
 (0)