add missing runtime requirement for async module header

active async modules when top level await is used
This commit is contained in:
Tobias Koppers 2019-11-19 12:10:45 +01:00
parent e82b870007
commit cda629eaac
4 changed files with 40 additions and 9 deletions

View File

@ -308,10 +308,18 @@ class WebpackOptionsApply extends OptionsApply {
new RuntimePlugin().apply(compiler);
if (options.experiments.importAwait || options.experiments.importAsync) {
if (
options.experiments.importAwait ||
options.experiments.importAsync ||
options.experiments.topLevelAwait
) {
const InferAsyncModulesPlugin = require("./async-modules/InferAsyncModulesPlugin");
new InferAsyncModulesPlugin({
errorOnMissingAwait: !options.experiments.importAsync
errorOnImport: options.experiments.importAsync
? false
: options.experiments.importAwait
? "await"
: true
}).apply(compiler);
}

View File

@ -13,9 +13,12 @@ const HarmonyImportSideEffectDependency = require("../dependencies/HarmonyImport
/** @typedef {import("../Module")} Module */
class InferAsyncModulesPlugin {
constructor(options) {
const { errorOnMissingAwait = false } = options || {};
this.errorOnMissingAwait = errorOnMissingAwait;
/**
* @param {Object} options options object
* @param {boolean | "await"=} options.errorOnImport false: no error, true: error when importing async module, "await": error when import async module without import await
*/
constructor({ errorOnImport = false } = {}) {
this.errorOnImport = errorOnImport;
}
/**
* @param {Compiler} compiler webpack compiler
@ -41,12 +44,14 @@ class InferAsyncModulesPlugin {
const dep = connection.dependency;
if (dep instanceof HarmonyImportDependency && connection.active) {
if (
this.errorOnMissingAwait &&
this.errorOnImport &&
dep instanceof HarmonyImportSideEffectDependency &&
!dep.await
(this.errorOnImport === true || !dep.await)
) {
const error = new WebpackError(
"Tried to import async module with normal import/export (must use 'import await'/'export await' instead)"
this.errorOnImport === true
? "Tried to import async module with import/export (must enable experiments.importAsync to allow this)"
: "Tried to import async module with normal import/export (must use 'import await'/'export await' instead)"
);
error.module = module;
error.loc = dep.loc;

View File

@ -56,13 +56,17 @@ HarmonyCompatibilityDependency.Template = class HarmonyExportDependencyTemplate
}
if (moduleGraph.isAsync(module)) {
runtimeRequirements.add(RuntimeGlobals.module);
if (usedExports !== false)
runtimeRequirements.add(RuntimeGlobals.exports);
initFragments.push(
new InitFragment(
`${module.moduleArgument}.exports = (async () => {\n`,
InitFragment.STAGE_ASYNC_BOUNDARY,
0,
undefined,
`\nreturn ${module.exportsArgument};\n})();`
usedExports !== false
? `\nreturn ${module.exportsArgument};\n})();`
: "\n})();"
)
);
}

View File

@ -0,0 +1,14 @@
let value = 0;
it("should not crash when top level await is used without export", () => {
// wait for itself
return require.cache[module.id].exports.then(() => {
expect(value).toBe(42);
});
});
await new Promise(r => setTimeout(r, 100));
value = 42;
export {};