fix egde case where a HMR chunk is incorrectly downloaded when loading a unchanged chunk during HMR downloading
This commit is contained in:
parent
86a8bd9618
commit
e1179bf9bb
|
@ -28,7 +28,8 @@ module.exports = function () {
|
|||
var currentStatus = "idle";
|
||||
|
||||
// while downloading
|
||||
var blockingPromises;
|
||||
var blockingPromises = 0;
|
||||
var blockingPromisesWaiting = [];
|
||||
|
||||
// The update info
|
||||
var currentUpdateApplyHandlers;
|
||||
|
@ -218,17 +219,28 @@ module.exports = function () {
|
|||
return Promise.all(results);
|
||||
}
|
||||
|
||||
function unblock() {
|
||||
if (--blockingPromises === 0) {
|
||||
setStatus("ready").then(function () {
|
||||
if (blockingPromises === 0) {
|
||||
var list = blockingPromisesWaiting;
|
||||
blockingPromisesWaiting = [];
|
||||
for (var i = 0; i < list.length; i++) {
|
||||
list[i]();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function trackBlockingPromise(promise) {
|
||||
switch (currentStatus) {
|
||||
case "ready":
|
||||
setStatus("prepare");
|
||||
blockingPromises.push(promise);
|
||||
waitForBlockingPromises(function () {
|
||||
return setStatus("ready");
|
||||
});
|
||||
return promise;
|
||||
/* fallthrough */
|
||||
case "prepare":
|
||||
blockingPromises.push(promise);
|
||||
blockingPromises++;
|
||||
promise.then(unblock, unblock);
|
||||
return promise;
|
||||
default:
|
||||
return promise;
|
||||
|
@ -236,11 +248,11 @@ module.exports = function () {
|
|||
}
|
||||
|
||||
function waitForBlockingPromises(fn) {
|
||||
if (blockingPromises.length === 0) return fn();
|
||||
var blocker = blockingPromises;
|
||||
blockingPromises = [];
|
||||
return Promise.all(blocker).then(function () {
|
||||
return waitForBlockingPromises(fn);
|
||||
if (blockingPromises === 0) return fn();
|
||||
return new Promise(function (resolve) {
|
||||
blockingPromisesWaiting.push(function () {
|
||||
resolve(fn());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -261,7 +273,6 @@ module.exports = function () {
|
|||
|
||||
return setStatus("prepare").then(function () {
|
||||
var updatedModules = [];
|
||||
blockingPromises = [];
|
||||
currentUpdateApplyHandlers = [];
|
||||
|
||||
return Promise.all(
|
||||
|
@ -298,7 +309,11 @@ module.exports = function () {
|
|||
function hotApply(options) {
|
||||
if (currentStatus !== "ready") {
|
||||
return Promise.resolve().then(function () {
|
||||
throw new Error("apply() is only allowed in ready status");
|
||||
throw new Error(
|
||||
"apply() is only allowed in ready status (state: " +
|
||||
currentStatus +
|
||||
")"
|
||||
);
|
||||
});
|
||||
}
|
||||
return internalApply(options);
|
||||
|
|
|
@ -443,15 +443,16 @@ module.exports = function () {
|
|||
) {
|
||||
promises.push($loadUpdateChunk$(chunkId, updatedModulesList));
|
||||
currentUpdateChunks[chunkId] = true;
|
||||
} else {
|
||||
currentUpdateChunks[chunkId] = false;
|
||||
}
|
||||
});
|
||||
if ($ensureChunkHandlers$) {
|
||||
$ensureChunkHandlers$.$key$Hmr = function (chunkId, promises) {
|
||||
if (
|
||||
currentUpdateChunks &&
|
||||
!$hasOwnProperty$(currentUpdateChunks, chunkId) &&
|
||||
$hasOwnProperty$($installedChunks$, chunkId) &&
|
||||
$installedChunks$[chunkId] !== undefined
|
||||
$hasOwnProperty$(currentUpdateChunks, chunkId) &&
|
||||
!currentUpdateChunks[chunkId]
|
||||
) {
|
||||
promises.push($loadUpdateChunk$(chunkId));
|
||||
currentUpdateChunks[chunkId] = true;
|
||||
|
|
|
@ -286,8 +286,9 @@ class JsonpChunkLoadingRuntimeModule extends RuntimeModule {
|
|||
? Template.asString([
|
||||
"var currentUpdatedModulesList;",
|
||||
"var waitingUpdateResolves = {};",
|
||||
"function loadUpdateChunk(chunkId) {",
|
||||
"function loadUpdateChunk(chunkId, updatedModulesList) {",
|
||||
Template.indent([
|
||||
"currentUpdatedModulesList = updatedModulesList;",
|
||||
`return new Promise(${runtimeTemplate.basicFunction(
|
||||
"resolve, reject",
|
||||
[
|
||||
|
|
|
@ -5,22 +5,27 @@ module.hot.accept("./file");
|
|||
const asyncNext = () => {
|
||||
return new Promise((resolve, reject) => {
|
||||
NEXT((err, stats) => {
|
||||
if(err) return reject(err);
|
||||
if (err) return reject(err);
|
||||
resolve(stats);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
it("should download the missing update chunk on import", () => {
|
||||
expect(value).toBe(1);
|
||||
return asyncNext().then(() => {
|
||||
return module.hot.check().then(() => {
|
||||
return import("./chunk").then(chunk => {
|
||||
return Promise.all([
|
||||
import("./chunk"),
|
||||
import("./unaffected-chunk")
|
||||
]).then(([chunk, unaffectedChunk]) => {
|
||||
expect(value).toBe(1);
|
||||
expect(chunk.default).toBe(10);
|
||||
expect(unaffectedChunk.default).toBe(10);
|
||||
return module.hot.apply().then(() => {
|
||||
expect(value).toBe(2);
|
||||
expect(chunk.default).toBe(20);
|
||||
expect(unaffectedChunk.default).toBe(10);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import value from "./unaffected-inner";
|
||||
|
||||
module.hot.accept("./unaffected-inner");
|
||||
|
||||
export { value as default };
|
|
@ -0,0 +1 @@
|
|||
export default 10;
|
Loading…
Reference in New Issue