fix: top level await don't leaves imported module wrapped in a Promise on HMR

This commit is contained in:
Natsu 2025-07-28 20:17:04 +08:00 committed by GitHub
parent f6b7a8eef1
commit 92304dfe07
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 116 additions and 62 deletions

View File

@ -116,13 +116,13 @@ HarmonyAcceptDependency.Template = class HarmonyAcceptDependencyTemplate extends
if (runtimeTemplate.supportsArrowFunction()) {
source.insert(
dep.range[0],
`__WEBPACK_OUTDATED_DEPENDENCIES__ => { ${content}(`
`__WEBPACK_OUTDATED_DEPENDENCIES__ => { ${content} return (`
);
source.insert(dep.range[1], ")(__WEBPACK_OUTDATED_DEPENDENCIES__); }");
} else {
source.insert(
dep.range[0],
`function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content}(`
`function(__WEBPACK_OUTDATED_DEPENDENCIES__) { ${content} return (`
);
source.insert(
dep.range[1],

View File

@ -354,38 +354,50 @@ module.exports = function () {
};
var outdatedModules = [];
results.forEach(function (result) {
if (result.apply) {
var modules = result.apply(reportError);
if (modules) {
for (var i = 0; i < modules.length; i++) {
outdatedModules.push(modules[i]);
}
}
}
});
return Promise.all([disposePromise, applyPromise]).then(function () {
// handle errors in accept handlers and self accepted module load
if (error) {
return setStatus("fail").then(function () {
throw error;
});
}
if (queuedInvalidatedModules) {
return internalApply(options).then(function (list) {
outdatedModules.forEach(function (moduleId) {
if (list.indexOf(moduleId) < 0) list.push(moduleId);
var onAccepted = function () {
return Promise.all([disposePromise, applyPromise]).then(function () {
// handle errors in accept handlers and self accepted module load
if (error) {
return setStatus("fail").then(function () {
throw error;
});
return list;
});
}
}
return setStatus("idle").then(function () {
return outdatedModules;
if (queuedInvalidatedModules) {
return internalApply(options).then(function (list) {
outdatedModules.forEach(function (moduleId) {
if (list.indexOf(moduleId) < 0) list.push(moduleId);
});
return list;
});
}
return setStatus("idle").then(function () {
return outdatedModules;
});
});
});
};
return Promise.all(
results
.filter(function (result) {
return result.apply;
})
.map(function (result) {
return result.apply(reportError);
})
)
.then(function (applyResults) {
applyResults.forEach(function (modules) {
if (modules) {
for (var i = 0; i < modules.length; i++) {
outdatedModules.push(modules[i]);
}
}
});
})
.then(onAccepted);
}
function applyInvalidatedModules() {

View File

@ -281,6 +281,7 @@ module.exports = function () {
}
},
apply: function (reportError) {
var acceptPromises = [];
// insert new code
for (var updateModuleId in appliedUpdate) {
if ($hasOwnProperty$(appliedUpdate, updateModuleId)) {
@ -317,8 +318,9 @@ module.exports = function () {
}
}
for (var k = 0; k < callbacks.length; k++) {
var result;
try {
callbacks[k].call(null, moduleOutdatedDependencies);
result = callbacks[k].call(null, moduleOutdatedDependencies);
} catch (err) {
if (typeof errorHandlers[k] === "function") {
try {
@ -355,54 +357,63 @@ module.exports = function () {
}
}
}
if (result && typeof result.then === "function") {
acceptPromises.push(result);
}
}
}
}
}
// Load self accepted modules
for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) {
var item = outdatedSelfAcceptedModules[o];
var moduleId = item.module;
try {
item.require(moduleId);
} catch (err) {
if (typeof item.errorHandler === "function") {
try {
item.errorHandler(err, {
moduleId: moduleId,
module: $moduleCache$[moduleId]
});
} catch (err1) {
var onAccepted = function () {
// Load self accepted modules
for (var o = 0; o < outdatedSelfAcceptedModules.length; o++) {
var item = outdatedSelfAcceptedModules[o];
var moduleId = item.module;
try {
item.require(moduleId);
} catch (err) {
if (typeof item.errorHandler === "function") {
try {
item.errorHandler(err, {
moduleId: moduleId,
module: $moduleCache$[moduleId]
});
} catch (err1) {
if (options.onErrored) {
options.onErrored({
type: "self-accept-error-handler-errored",
moduleId: moduleId,
error: err1,
originalError: err
});
}
if (!options.ignoreErrored) {
reportError(err1);
reportError(err);
}
}
} else {
if (options.onErrored) {
options.onErrored({
type: "self-accept-error-handler-errored",
type: "self-accept-errored",
moduleId: moduleId,
error: err1,
originalError: err
error: err
});
}
if (!options.ignoreErrored) {
reportError(err1);
reportError(err);
}
}
} else {
if (options.onErrored) {
options.onErrored({
type: "self-accept-errored",
moduleId: moduleId,
error: err
});
}
if (!options.ignoreErrored) {
reportError(err);
}
}
}
}
};
return outdatedModules;
return Promise.all(acceptPromises)
.then(onAccepted)
.then(function () {
return outdatedModules;
});
}
};
}

View File

@ -0,0 +1,28 @@
import update from "../../update";
import a from "./module-a";
it("should support async accept", (done) => {
let test = 0;
expect(a).toEqual(1);
import.meta.webpackHot.accept(["./module-a"], () => {
debugger
return new Promise((resolve) => {
setTimeout(() => {
debugger
test = 1;
resolve();
}, 3000);
});
});
NEXT(update(done));
import.meta.webpackHot.addStatusHandler((status) => {
if (status === "idle") {
expect(test).toEqual(1);
expect(a).toEqual(2);
done();
}
});
});

View File

@ -0,0 +1,3 @@
export default 1;
---
export default 2;