Skip to content

Commit c3ce90b

Browse files
authored
feat: keep unknown import.meta properties
1 parent 255b88a commit c3ce90b

File tree

12 files changed

+156
-27
lines changed

12 files changed

+156
-27
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"webpack": minor
3+
---
4+
5+
Unknown import.meta properties are now determined at runtime instead of being statically analyzed at compile time.

declarations/WebpackOptions.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3317,9 +3317,9 @@ export interface JavascriptParserOptions {
33173317
*/
33183318
importExportsPresence?: "error" | "warn" | "auto" | false;
33193319
/**
3320-
* Enable/disable evaluating import.meta.
3320+
* Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.
33213321
*/
3322-
importMeta?: boolean;
3322+
importMeta?: boolean | "preserve-unknown";
33233323
/**
33243324
* Enable/disable evaluating import.meta.webpackContext.
33253325
*/

lib/config/defaults.js

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,10 @@ const applyWebpackOptionsDefaults = (options, compilerIndex) => {
447447
isNode: targetProperties && targetProperties.node === true,
448448
uniqueName: /** @type {string} */ (options.output.uniqueName),
449449
targetProperties,
450-
mode: options.mode
450+
mode: options.mode,
451+
outputModule:
452+
/** @type {NonNullable<WebpackOptionsNormalized["output"]["module"]>} */
453+
(options.output.module)
451454
});
452455

453456
applyExternalsPresetsDefaults(options.externalsPresets, {
@@ -739,11 +742,12 @@ const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
739742
* @param {boolean} options.futureDefaults is future defaults enabled
740743
* @param {boolean} options.deferImport is defer import enabled
741744
* @param {boolean} options.isNode is node target platform
745+
* @param {boolean} options.outputModule is output.module enabled
742746
* @returns {void}
743747
*/
744748
const applyJavascriptParserOptionsDefaults = (
745749
parserOptions,
746-
{ futureDefaults, deferImport, isNode }
750+
{ futureDefaults, deferImport, isNode, outputModule }
747751
) => {
748752
D(parserOptions, "unknownContextRequest", ".");
749753
D(parserOptions, "unknownContextRegExp", false);
@@ -757,7 +761,7 @@ const applyJavascriptParserOptionsDefaults = (
757761
D(parserOptions, "wrappedContextRecursive", true);
758762
D(parserOptions, "wrappedContextCritical", false);
759763
D(parserOptions, "strictThisContextOnImports", false);
760-
D(parserOptions, "importMeta", true);
764+
D(parserOptions, "importMeta", outputModule ? "preserve-unknown" : true);
761765
D(parserOptions, "dynamicImportMode", "lazy");
762766
D(parserOptions, "dynamicImportPrefetch", false);
763767
D(parserOptions, "dynamicImportPreload", false);
@@ -810,6 +814,7 @@ const applyCssGeneratorOptionsDefaults = (
810814
* @param {HashSalt} options.hashSalt hash salt
811815
* @param {HashDigest} options.hashDigest hash digest
812816
* @param {HashDigestLength} options.hashDigestLength hash digest length
817+
* @param {boolean} options.outputModule is output.module enabled
813818
* @returns {void}
814819
*/
815820
const applyModuleDefaults = (
@@ -827,7 +832,8 @@ const applyModuleDefaults = (
827832
uniqueName,
828833
targetProperties,
829834
mode,
830-
deferImport
835+
deferImport,
836+
outputModule
831837
}
832838
) => {
833839
if (cache) {
@@ -886,7 +892,8 @@ const applyModuleDefaults = (
886892
{
887893
futureDefaults,
888894
deferImport,
889-
isNode
895+
isNode,
896+
outputModule
890897
}
891898
);
892899

lib/dependencies/ImportMetaPlugin.js

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -157,10 +157,15 @@ class ImportMetaPlugin {
157157
* @param {Members} members members
158158
* @returns {string} error message
159159
*/
160-
const importMetaUnknownProperty = (members) =>
161-
`${Template.toNormalComment(
160+
const importMetaUnknownProperty = (members) => {
161+
if (importMeta === "preserve-unknown") {
162+
return `import.meta${propertyAccess(members, 0)}`;
163+
}
164+
return `${Template.toNormalComment(
162165
`unsupported import.meta.${members.join(".")}`
163166
)} undefined${propertyAccess(members, 1)}`;
167+
};
168+
164169
parser.hooks.typeof
165170
.for("import.meta")
166171
.tap(
@@ -386,6 +391,11 @@ class ImportMetaPlugin {
386391
parser.hooks.unhandledExpressionMemberChain
387392
.for("import.meta")
388393
.tap(PLUGIN_NAME, (expr, members) => {
394+
// unknown import.meta properties should be determined at runtime
395+
if (importMeta === "preserve-unknown") {
396+
return true;
397+
}
398+
389399
// keep import.meta.env unknown property
390400
// don't evaluate import.meta.env.UNKNOWN_PROPERTY -> undefined.UNKNOWN_PROPERTY
391401
// `dirname` and `filename` logic in NodeStuffPlugin
@@ -404,6 +414,7 @@ class ImportMetaPlugin {
404414
parser.state.module.addPresentationalDependency(dep);
405415
return true;
406416
});
417+
407418
parser.hooks.evaluate
408419
.for("MemberExpression")
409420
.tap(PLUGIN_NAME, (expression) => {

schemas/WebpackOptions.check.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

schemas/WebpackOptions.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1967,8 +1967,16 @@
19671967
"enum": ["error", "warn", "auto", false]
19681968
},
19691969
"importMeta": {
1970-
"description": "Enable/disable evaluating import.meta.",
1971-
"type": "boolean"
1970+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
1971+
"anyOf": [
1972+
{
1973+
"type": "boolean"
1974+
},
1975+
{
1976+
"type": "string",
1977+
"enum": ["preserve-unknown"]
1978+
}
1979+
]
19721980
},
19731981
"importMetaContext": {
19741982
"description": "Enable/disable evaluating import.meta.webpackContext.",

test/Defaults.unittest.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,9 @@ describe("snapshots", () => {
10141014
- "module": undefined,
10151015
+ "module": true,
10161016
@@ ... @@
1017+
- "importMeta": true,
1018+
+ "importMeta": "preserve-unknown",
1019+
@@ ... @@
10171020
- "chunkFilename": "[name].js",
10181021
- "chunkFormat": "array-push",
10191022
+ "chunkFilename": "[name].mjs",
@@ -1877,6 +1880,9 @@ describe("snapshots", () => {
18771880
- "target": "web",
18781881
+ "target": undefined,
18791882
@@ ... @@
1883+
- "importMeta": true,
1884+
+ "importMeta": "preserve-unknown",
1885+
@@ ... @@
18801886
- "__dirname": "mock",
18811887
- "__filename": "mock",
18821888
+ "__dirname": "eval-only",
@@ -3193,6 +3199,9 @@ describe("snapshots", () => {
31933199
- "createRequire": false,
31943200
+ "createRequire": true,
31953201
@@ ... @@
3202+
- "importMeta": true,
3203+
+ "importMeta": "preserve-unknown",
3204+
@@ ... @@
31963205
- "__dirname": "mock",
31973206
- "__filename": "mock",
31983207
- "global": true,

test/__snapshots__/Cli.basictest.js.snap

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,15 +2811,24 @@ Object {
28112811
"module-parser-javascript-auto-import-meta": Object {
28122812
"configs": Array [
28132813
Object {
2814-
"description": "Enable/disable evaluating import.meta.",
2814+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
28152815
"multiple": false,
28162816
"path": "module.parser.javascript/auto.importMeta",
28172817
"type": "boolean",
28182818
},
2819+
Object {
2820+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
2821+
"multiple": false,
2822+
"path": "module.parser.javascript/auto.importMeta",
2823+
"type": "enum",
2824+
"values": Array [
2825+
"preserve-unknown",
2826+
],
2827+
},
28192828
],
2820-
"description": "Enable/disable evaluating import.meta.",
2829+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
28212830
"multiple": false,
2822-
"simpleType": "boolean",
2831+
"simpleType": "string",
28232832
},
28242833
"module-parser-javascript-auto-import-meta-context": Object {
28252834
"configs": Array [
@@ -3579,15 +3588,24 @@ Object {
35793588
"module-parser-javascript-dynamic-import-meta": Object {
35803589
"configs": Array [
35813590
Object {
3582-
"description": "Enable/disable evaluating import.meta.",
3591+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
35833592
"multiple": false,
35843593
"path": "module.parser.javascript/dynamic.importMeta",
35853594
"type": "boolean",
35863595
},
3596+
Object {
3597+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
3598+
"multiple": false,
3599+
"path": "module.parser.javascript/dynamic.importMeta",
3600+
"type": "enum",
3601+
"values": Array [
3602+
"preserve-unknown",
3603+
],
3604+
},
35873605
],
3588-
"description": "Enable/disable evaluating import.meta.",
3606+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
35893607
"multiple": false,
3590-
"simpleType": "boolean",
3608+
"simpleType": "string",
35913609
},
35923610
"module-parser-javascript-dynamic-import-meta-context": Object {
35933611
"configs": Array [
@@ -4320,15 +4338,24 @@ Object {
43204338
"module-parser-javascript-esm-import-meta": Object {
43214339
"configs": Array [
43224340
Object {
4323-
"description": "Enable/disable evaluating import.meta.",
4341+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
43244342
"multiple": false,
43254343
"path": "module.parser.javascript/esm.importMeta",
43264344
"type": "boolean",
43274345
},
4346+
Object {
4347+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
4348+
"multiple": false,
4349+
"path": "module.parser.javascript/esm.importMeta",
4350+
"type": "enum",
4351+
"values": Array [
4352+
"preserve-unknown",
4353+
],
4354+
},
43284355
],
4329-
"description": "Enable/disable evaluating import.meta.",
4356+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
43304357
"multiple": false,
4331-
"simpleType": "boolean",
4358+
"simpleType": "string",
43324359
},
43334360
"module-parser-javascript-esm-import-meta-context": Object {
43344361
"configs": Array [
@@ -4822,15 +4849,24 @@ Object {
48224849
"module-parser-javascript-import-meta": Object {
48234850
"configs": Array [
48244851
Object {
4825-
"description": "Enable/disable evaluating import.meta.",
4852+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
48264853
"multiple": false,
48274854
"path": "module.parser.javascript.importMeta",
48284855
"type": "boolean",
48294856
},
4857+
Object {
4858+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
4859+
"multiple": false,
4860+
"path": "module.parser.javascript.importMeta",
4861+
"type": "enum",
4862+
"values": Array [
4863+
"preserve-unknown",
4864+
],
4865+
},
48304866
],
4831-
"description": "Enable/disable evaluating import.meta.",
4867+
"description": "Enable/disable evaluating import.meta. Set to 'preserve-unknown' to preserve unknown properties for runtime evaluation.",
48324868
"multiple": false,
4833-
"simpleType": "boolean",
4869+
"simpleType": "string",
48344870
},
48354871
"module-parser-javascript-import-meta-context": Object {
48364872
"configs": Array [

test/cases/parsing/import-meta/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,4 @@ it("should support destructuring assignment", async () => {
6060
expect(version2).toBeTypeOf("number");
6161
expect(url3).toBe(url);
6262
expect(d).toBe(undefined);
63-
});
63+
});
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
if (!import.meta.UNKNOWN_PROPERTY) {
2+
// runtime assignment
3+
import.meta.UNKNOWN_PROPERTY = "HELLO";
4+
}
5+
6+
const { pathToFileURL } = require("url");
7+
const url = pathToFileURL(
8+
require("path").resolve("./test/configCases/module/import-meta/index.js")
9+
).toString();
10+
11+
it("should keep import.meta.UNKNOWN_PROPERTY", () => {
12+
try {
13+
const UNKNOWN_PROPERTY = import.meta.UNKNOWN_PROPERTY;
14+
expect(UNKNOWN_PROPERTY).toBe("HELLO");
15+
expect(typeof import.meta.UNKNOWN_PROPERTY).toBe("string");
16+
17+
expect(typeof import.meta.webpack).toBe("number");
18+
19+
const { UNKNOWN_PROPERTY: UNKNOWN_PROPERTY_2, webpack: WEBPACK_PROPERTY_2 } = import.meta;
20+
expect(UNKNOWN_PROPERTY_2).toBe("HELLO");
21+
expect(typeof WEBPACK_PROPERTY_2).toBe("number");
22+
} catch (_e) {
23+
// ignore
24+
}
25+
});
26+
27+
it("should support destructuring assignment", async () => {
28+
let version, url2, c, unknown;
29+
({ webpack: version } = { url: url2 } = { c } = { UNKNOWN_PROPERTY: unknown } = import.meta);
30+
expect(version).toBeTypeOf("number");
31+
expect(url2).toBe(url);
32+
expect(c).toBe(undefined);
33+
expect(unknown).toBe("HELLO");
34+
35+
let version2, url3, d, unknown2;
36+
({ webpack: version2 } = await ({ url: url3 } = ({ d } = { UNKNOWN_PROPERTY: unknown2 } = await import.meta)));
37+
expect(version2).toBeTypeOf("number");
38+
expect(url3).toBe(url);
39+
expect(d).toBe(undefined);
40+
expect(unknown2).toBe("HELLO");
41+
});

0 commit comments

Comments
 (0)