mirror of https://github.com/webpack/webpack.git
Allow HMR status handlers to return a Promise
The HMR system will wait until the promise settles before continuing.
This commit is contained in:
parent
e9f90450d5
commit
e852415cd5
|
@ -9,6 +9,7 @@ var $interceptModuleExecution$ = undefined;
|
||||||
var $moduleCache$ = undefined;
|
var $moduleCache$ = undefined;
|
||||||
// eslint-disable-next-line no-unused-vars
|
// eslint-disable-next-line no-unused-vars
|
||||||
var $hmrModuleData$ = undefined;
|
var $hmrModuleData$ = undefined;
|
||||||
|
/** @type {() => Promise} */
|
||||||
var $hmrDownloadManifest$ = undefined;
|
var $hmrDownloadManifest$ = undefined;
|
||||||
var $hmrDownloadUpdateHandlers$ = undefined;
|
var $hmrDownloadUpdateHandlers$ = undefined;
|
||||||
var $hmrInvalidateModuleHandlers$ = undefined;
|
var $hmrInvalidateModuleHandlers$ = undefined;
|
||||||
|
@ -209,8 +210,12 @@ module.exports = function () {
|
||||||
|
|
||||||
function setStatus(newStatus) {
|
function setStatus(newStatus) {
|
||||||
currentStatus = newStatus;
|
currentStatus = newStatus;
|
||||||
|
var results = [];
|
||||||
|
|
||||||
for (var i = 0; i < registeredStatusHandlers.length; i++)
|
for (var i = 0; i < registeredStatusHandlers.length; i++)
|
||||||
registeredStatusHandlers[i].call(null, newStatus);
|
results[i] = registeredStatusHandlers[i].call(null, newStatus);
|
||||||
|
|
||||||
|
return Promise.all(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
function trackBlockingPromise(promise) {
|
function trackBlockingPromise(promise) {
|
||||||
|
@ -219,7 +224,7 @@ module.exports = function () {
|
||||||
setStatus("prepare");
|
setStatus("prepare");
|
||||||
blockingPromises.push(promise);
|
blockingPromises.push(promise);
|
||||||
waitForBlockingPromises(function () {
|
waitForBlockingPromises(function () {
|
||||||
setStatus("ready");
|
return setStatus("ready");
|
||||||
});
|
});
|
||||||
return promise;
|
return promise;
|
||||||
case "prepare":
|
case "prepare":
|
||||||
|
@ -243,15 +248,14 @@ module.exports = function () {
|
||||||
if (currentStatus !== "idle") {
|
if (currentStatus !== "idle") {
|
||||||
throw new Error("check() is only allowed in idle status");
|
throw new Error("check() is only allowed in idle status");
|
||||||
}
|
}
|
||||||
setStatus("check");
|
return setStatus("check")
|
||||||
return $hmrDownloadManifest$().then(function (update) {
|
.then($hmrDownloadManifest$)
|
||||||
|
.then(function (update) {
|
||||||
if (!update) {
|
if (!update) {
|
||||||
setStatus(applyInvalidatedModules() ? "ready" : "idle");
|
return setStatus(applyInvalidatedModules() ? "ready" : "idle");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus("prepare");
|
return setStatus("prepare").then(function () {
|
||||||
|
|
||||||
var updatedModules = [];
|
var updatedModules = [];
|
||||||
blockingPromises = [];
|
blockingPromises = [];
|
||||||
currentUpdateApplyHandlers = [];
|
currentUpdateApplyHandlers = [];
|
||||||
|
@ -277,13 +281,14 @@ module.exports = function () {
|
||||||
if (applyOnUpdate) {
|
if (applyOnUpdate) {
|
||||||
return internalApply(applyOnUpdate);
|
return internalApply(applyOnUpdate);
|
||||||
} else {
|
} else {
|
||||||
setStatus("ready");
|
return setStatus("ready").then(function () {
|
||||||
|
|
||||||
return updatedModules;
|
return updatedModules;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function hotApply(options) {
|
function hotApply(options) {
|
||||||
|
@ -312,22 +317,19 @@ module.exports = function () {
|
||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
setStatus("abort");
|
return setStatus("abort").then(function () {
|
||||||
return Promise.resolve().then(function () {
|
|
||||||
throw errors[0];
|
throw errors[0];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now in "dispose" phase
|
// Now in "dispose" phase
|
||||||
setStatus("dispose");
|
return setStatus("dispose").then(function () {
|
||||||
|
|
||||||
results.forEach(function (result) {
|
results.forEach(function (result) {
|
||||||
if (result.dispose) result.dispose();
|
if (result.dispose) result.dispose();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Now in "apply" phase
|
// Now in "apply" phase
|
||||||
setStatus("apply");
|
return setStatus("apply").then(function () {
|
||||||
|
|
||||||
var error;
|
var error;
|
||||||
var reportError = function (err) {
|
var reportError = function (err) {
|
||||||
if (!error) error = err;
|
if (!error) error = err;
|
||||||
|
@ -347,8 +349,7 @@ module.exports = function () {
|
||||||
|
|
||||||
// handle errors in accept handlers and self accepted module load
|
// handle errors in accept handlers and self accepted module load
|
||||||
if (error) {
|
if (error) {
|
||||||
setStatus("fail");
|
return setStatus("fail").then(function () {
|
||||||
return Promise.resolve().then(function () {
|
|
||||||
throw error;
|
throw error;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -362,8 +363,11 @@ module.exports = function () {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus("idle");
|
return setStatus("idle").then(function () {
|
||||||
return Promise.resolve(outdatedModules);
|
return outdatedModules;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function applyInvalidatedModules() {
|
function applyInvalidatedModules() {
|
||||||
|
|
|
@ -250,7 +250,7 @@ const describeCases = config => {
|
||||||
return JSON.parse(fs.readFileSync(p, "utf-8"));
|
return JSON.parse(fs.readFileSync(p, "utf-8"));
|
||||||
} else {
|
} else {
|
||||||
const fn = vm.runInThisContext(
|
const fn = vm.runInThisContext(
|
||||||
"(function(require, module, exports, __dirname, __filename, it, beforeEach, afterEach, expect, self, window, fetch, document, importScripts, Worker, EventSource, NEXT, STATS) {" +
|
"(function(require, module, exports, __dirname, __filename, it, beforeEach, afterEach, expect, jest, self, window, fetch, document, importScripts, Worker, EventSource, NEXT, STATS) {" +
|
||||||
"global.expect = expect;" +
|
"global.expect = expect;" +
|
||||||
'function nsObj(m) { Object.defineProperty(m, Symbol.toStringTag, { value: "Module" }); return m; }' +
|
'function nsObj(m) { Object.defineProperty(m, Symbol.toStringTag, { value: "Module" }); return m; }' +
|
||||||
fs.readFileSync(p, "utf-8") +
|
fs.readFileSync(p, "utf-8") +
|
||||||
|
@ -271,6 +271,7 @@ const describeCases = config => {
|
||||||
_beforeEach,
|
_beforeEach,
|
||||||
_afterEach,
|
_afterEach,
|
||||||
expect,
|
expect,
|
||||||
|
jest,
|
||||||
window,
|
window,
|
||||||
window,
|
window,
|
||||||
window.fetch,
|
window.fetch,
|
||||||
|
|
|
@ -11,9 +11,10 @@ it("should allow to invalidate and reload a file", () => {
|
||||||
expect(module.hot.status()).toBe("ready");
|
expect(module.hot.status()).toBe("ready");
|
||||||
c.invalidate();
|
c.invalidate();
|
||||||
expect(module.hot.status()).toBe("ready");
|
expect(module.hot.status()).toBe("ready");
|
||||||
module.hot.apply();
|
module.hot.apply().then(function () {
|
||||||
expect(module.hot.status()).toBe("idle");
|
expect(module.hot.status()).toBe("idle");
|
||||||
expect(a.value).not.toBe(oldA);
|
expect(a.value).not.toBe(oldA);
|
||||||
expect(b.value).not.toBe(oldB);
|
expect(b.value).not.toBe(oldB);
|
||||||
expect(c.value).toBe(oldC);
|
expect(c.value).toBe(oldC);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = 1;
|
||||||
|
---
|
||||||
|
module.exports = 2;
|
|
@ -0,0 +1,21 @@
|
||||||
|
var value = require("./file");
|
||||||
|
|
||||||
|
it("should wait until promises returned by status handlers are fulfilled", (done) => {
|
||||||
|
var handler = jest.fn(status => {
|
||||||
|
return Promise.resolve().then(() => {
|
||||||
|
expect(status).toBe(module.hot.status());
|
||||||
|
});
|
||||||
|
});
|
||||||
|
module.hot.addStatusHandler(handler);
|
||||||
|
module.hot.accept("./file", () => {
|
||||||
|
value = require("./file");
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
NEXT(require("../../update")(done, undefined, () => {
|
||||||
|
expect(module.hot.status()).toBe("idle");
|
||||||
|
|
||||||
|
expect(handler.mock.calls).toBe([['check'], ['prepare'], ['dispose'], ['apply'], ['idle']]);
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue