feat: handle `import.meta.main` (#20065)

This commit is contained in:
Alexander Akait 2025-10-31 16:51:41 +03:00 committed by GitHub
parent e61595200c
commit 8651ffc23a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 91 additions and 16 deletions

View File

@ -126,15 +126,6 @@ class CommonJsImportsParserPlugin {
});
// #region Unsupported
parser.hooks.expression
.for("require.main")
.tap(
PLUGIN_NAME,
expressionIsUnsupported(
parser,
"require.main is not supported by webpack."
)
);
parser.hooks.call
.for("require.main.require")
.tap(

View File

@ -13,6 +13,7 @@ const {
JAVASCRIPT_MODULE_TYPE_AUTO,
JAVASCRIPT_MODULE_TYPE_ESM
} = require("../ModuleTypeConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const BasicEvaluatedExpression = require("../javascript/BasicEvaluatedExpression");
const {
@ -34,6 +35,7 @@ const ConstDependency = require("./ConstDependency");
/** @typedef {import("../javascript/JavascriptParser").Range} Range */
/** @typedef {import("../javascript/JavascriptParser").Members} Members */
/** @typedef {import("../javascript/JavascriptParser").DestructuringAssignmentProperty} DestructuringAssignmentProperty */
/** @typedef {import("./ConstDependency").RawRuntimeRequirements} RawRuntimeRequirements */
const getCriticalDependencyWarning = memoize(() =>
require("./CriticalDependencyWarning")
@ -168,6 +170,9 @@ class ImportMetaPlugin {
return true;
}
/** @type {RawRuntimeRequirements} */
const runtimeRequirements = [];
let str = "";
for (const prop of referencedPropertiesInDestructuring) {
const value = hooks.propertyInDestructuring.call(prop);
@ -184,6 +189,14 @@ class ImportMetaPlugin {
case "webpack":
str += `webpack: ${importMetaWebpackVersion()},`;
break;
case "main":
str += `main: ${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${RuntimeGlobals.module},`;
runtimeRequirements.push(
RuntimeGlobals.moduleCache,
RuntimeGlobals.entryModuleId,
RuntimeGlobals.module
);
break;
default:
str += `[${JSON.stringify(
prop.id
@ -193,7 +206,8 @@ class ImportMetaPlugin {
}
const dep = new ConstDependency(
`({${str}})`,
/** @type {Range} */ (metaProperty.range)
/** @type {Range} */ (metaProperty.range),
runtimeRequirements
);
dep.loc = /** @type {DependencyLocation} */ (metaProperty.loc);
parser.state.module.addPresentationalDependency(dep);
@ -237,18 +251,18 @@ class ImportMetaPlugin {
);
// import.meta.webpack
parser.hooks.typeof
.for("import.meta.webpack")
.tap(
PLUGIN_NAME,
toConstantDependency(parser, JSON.stringify("number"))
);
parser.hooks.expression
.for("import.meta.webpack")
.tap(
PLUGIN_NAME,
toConstantDependency(parser, importMetaWebpackVersion())
);
parser.hooks.typeof
.for("import.meta.webpack")
.tap(
PLUGIN_NAME,
toConstantDependency(parser, JSON.stringify("number"))
);
parser.hooks.evaluateTypeof
.for("import.meta.webpack")
.tap(PLUGIN_NAME, evaluateToString("number"));
@ -256,6 +270,30 @@ class ImportMetaPlugin {
.for("import.meta.webpack")
.tap(PLUGIN_NAME, evaluateToNumber(webpackVersion));
parser.hooks.expression
.for("import.meta.main")
.tap(
PLUGIN_NAME,
toConstantDependency(
parser,
`${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}] === ${RuntimeGlobals.module}`,
[
RuntimeGlobals.moduleCache,
RuntimeGlobals.entryModuleId,
RuntimeGlobals.module
]
)
);
parser.hooks.typeof
.for("import.meta.main")
.tap(
PLUGIN_NAME,
toConstantDependency(parser, JSON.stringify("boolean"))
);
parser.hooks.evaluateTypeof
.for("import.meta.main")
.tap(PLUGIN_NAME, evaluateToString("boolean"));
// Unknown properties
parser.hooks.unhandledExpressionMemberChain
.for("import.meta")

View File

@ -0,0 +1 @@
export default "1";

View File

@ -0,0 +1,14 @@
import { main } from "./module.js";
it("should handle import.meta.main", async () => {
expect(import.meta.main).toBe(true);
expect(typeof import.meta.main).toBe("boolean");
// Just for test, nobody uses this in real code
await import(`./${typeof import.meta.main}.js`);
const { main: myMain } = import.meta;
expect(myMain).toBe(true);
expect(main).toBe(false);
});

View File

@ -0,0 +1,3 @@
const main = import.meta.main;
export { main };

View File

@ -0,0 +1,9 @@
"use strict";
/** @type {import("../../../../").Configuration} */
module.exports = {
target: "node",
optimization: {
concatenateModules: false
}
};

View File

@ -0,0 +1,7 @@
const { main } = require("./module");
it("should handle require.main", async () => {
expect(require.main === module).toBe(true);
expect(main).toBe(false);
});

View File

@ -0,0 +1,3 @@
const main = require.main === module;
module.exports = { main };

View File

@ -0,0 +1,9 @@
"use strict";
/** @type {import("../../../../").Configuration} */
module.exports = {
target: "node",
optimization: {
concatenateModules: false
}
};