Skip to content

Commit 1adb66f

Browse files
committed
fix: respect import.meta.env parser option
1 parent 8e46c0f commit 1adb66f

6 files changed

Lines changed: 98 additions & 43 deletions

File tree

crates/rspack_core/src/options/module.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ macro_rules! define_import_meta_known_properties {
392392

393393
define_import_meta_known_properties! {
394394
const DIRNAME = "dirname";
395+
const ENV = "env";
395396
const FILENAME = "filename";
396397
const GLOB = "glob";
397398
const MAIN = "main";

crates/rspack_plugin_javascript/src/parser_plugin/import_meta_plugin.rs

Lines changed: 61 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -118,43 +118,57 @@ struct ImportMetaBuiltinProperty {
118118
name: &'static str,
119119
property: ImportMetaKnownProperties,
120120
type_of: &'static str,
121+
add_value_dependency: Option<for<'p> fn(&mut JavascriptParser<'p>)>,
121122
}
122123

123124
static IMPORT_META_BUILTIN_PROPERTIES: &[ImportMetaBuiltinProperty] = &[
124125
ImportMetaBuiltinProperty {
125126
name: expr_name::IMPORT_META_URL,
126127
property: ImportMetaKnownProperties::URL,
127128
type_of: "string",
129+
add_value_dependency: None,
128130
},
129131
ImportMetaBuiltinProperty {
130132
name: expr_name::IMPORT_META_RESOLVE,
131133
property: ImportMetaKnownProperties::RESOLVE,
132134
type_of: "function",
135+
add_value_dependency: None,
133136
},
134137
ImportMetaBuiltinProperty {
135138
name: expr_name::IMPORT_META_VERSION,
136139
property: ImportMetaKnownProperties::WEBPACK,
137140
type_of: "number",
141+
add_value_dependency: None,
138142
},
139143
ImportMetaBuiltinProperty {
140144
name: expr_name::IMPORT_META_MAIN,
141145
property: ImportMetaKnownProperties::MAIN,
142146
type_of: "boolean",
147+
add_value_dependency: None,
143148
},
144149
ImportMetaBuiltinProperty {
145150
name: expr_name::IMPORT_META_FILENAME,
146151
property: ImportMetaKnownProperties::FILENAME,
147152
type_of: "string",
153+
add_value_dependency: None,
148154
},
149155
ImportMetaBuiltinProperty {
150156
name: expr_name::IMPORT_META_DIRNAME,
151157
property: ImportMetaKnownProperties::DIRNAME,
152158
type_of: "string",
159+
add_value_dependency: None,
160+
},
161+
ImportMetaBuiltinProperty {
162+
name: expr_name::IMPORT_META_ENV,
163+
property: ImportMetaKnownProperties::ENV,
164+
type_of: "object",
165+
add_value_dependency: Some(add_import_meta_env_value_dependency),
153166
},
154167
ImportMetaBuiltinProperty {
155168
name: expr_name::IMPORT_META_RSPACK_RSC,
156169
property: ImportMetaKnownProperties::RSPACK_RSC,
157170
type_of: "object",
171+
add_value_dependency: None,
158172
},
159173
];
160174

@@ -176,6 +190,12 @@ impl ImportMetaBuiltinProperty {
176190
&self.name[expr_name::IMPORT_META_PREFIX.len()..]
177191
}
178192

193+
fn add_value_dependency(&self, parser: &mut JavascriptParser) {
194+
if let Some(add_value_dependency) = self.add_value_dependency {
195+
add_value_dependency(parser);
196+
}
197+
}
198+
179199
fn enabled(&self, plugin: &ImportMetaPlugin, parser: &JavascriptParser) -> bool {
180200
if !plugin.known_property_enabled(self.property) {
181201
return false;
@@ -185,6 +205,7 @@ impl ImportMetaBuiltinProperty {
185205
ImportMetaKnownProperties::RESOLVE => {
186206
parser.javascript_options.import_meta_resolve == Some(true)
187207
}
208+
ImportMetaKnownProperties::ENV => experiments_env_enabled(parser),
188209
ImportMetaKnownProperties::RSPACK_RSC => is_rsc_layer(parser),
189210
_ => true,
190211
}
@@ -226,6 +247,13 @@ impl ImportMetaBuiltinProperty {
226247
end,
227248
)),
228249
ImportMetaKnownProperties::WEBPACK => Some(eval::evaluate_to_number(5_f64, start, end)),
250+
ImportMetaKnownProperties::ENV => {
251+
self.add_value_dependency(parser);
252+
let mut evaluated = BasicEvaluatedExpression::with_range(start, end);
253+
evaluated.set_truthy();
254+
evaluated.set_side_effects(false);
255+
Some(evaluated)
256+
}
229257
ImportMetaKnownProperties::FILENAME | ImportMetaKnownProperties::DIRNAME => {
230258
get_import_meta_eval_value(parser, self.property)
231259
.map(|value| eval::evaluate_to_string(value, start, end))
@@ -242,6 +270,7 @@ impl ImportMetaBuiltinProperty {
242270
unary_expr: &UnaryExpr,
243271
) -> Option<bool> {
244272
let type_of = self.evaluate_typeof(plugin, parser)?;
273+
self.add_value_dependency(parser);
245274
parser.add_presentational_dependency(Box::new(ConstDependency::new(
246275
unary_expr.span().into(),
247276
concat_string!("'", type_of, "'").into(),
@@ -275,6 +304,14 @@ impl ImportMetaBuiltinProperty {
275304
": ",
276305
plugin.import_meta_main(parser)
277306
)),
307+
ImportMetaKnownProperties::ENV => {
308+
self.add_value_dependency(parser);
309+
Some(concat_string!(
310+
property,
311+
": ",
312+
import_meta_env_definitions_string(parser.compilation_id)
313+
))
314+
}
278315
ImportMetaKnownProperties::FILENAME | ImportMetaKnownProperties::DIRNAME => {
279316
get_import_meta_member_replacement(parser, self.property)
280317
.map(|value| concat_string!(property, ": ", value))
@@ -303,6 +340,10 @@ impl ImportMetaBuiltinProperty {
303340
ImportMetaKnownProperties::URL => concat_string!("'", plugin.import_meta_url(parser), "'"),
304341
ImportMetaKnownProperties::WEBPACK => plugin.import_meta_version(),
305342
ImportMetaKnownProperties::MAIN => plugin.import_meta_main(parser),
343+
ImportMetaKnownProperties::ENV => {
344+
self.add_value_dependency(parser);
345+
import_meta_env_definitions_expression(parser, member_expr.span().real_lo())
346+
}
306347
ImportMetaKnownProperties::FILENAME | ImportMetaKnownProperties::DIRNAME => {
307348
get_import_meta_member_replacement(parser, self.property)?
308349
}
@@ -329,9 +370,9 @@ impl ImportMetaBuiltinProperty {
329370
match self.property {
330371
// dirname/filename may be preserved at runtime based on node options, so don't fold them to undefined.
331372
ImportMetaKnownProperties::FILENAME | ImportMetaKnownProperties::DIRNAME => true,
332-
ImportMetaKnownProperties::MAIN | ImportMetaKnownProperties::RSPACK_RSC => {
333-
self.enabled(plugin, parser)
334-
}
373+
ImportMetaKnownProperties::ENV
374+
| ImportMetaKnownProperties::MAIN
375+
| ImportMetaKnownProperties::RSPACK_RSC => self.enabled(plugin, parser),
335376
_ => false,
336377
}
337378
}
@@ -538,8 +579,6 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
538579
&& self.runtime_api_enabled(api)
539580
{
540581
evaluated = Some(api.type_of.to_string())
541-
} else if experiments_env_enabled(parser) && for_name == expr_name::IMPORT_META_ENV {
542-
evaluated = Some("object".to_string())
543582
} else if let Some(member_expr) = expr.arg.as_member()
544583
&& let Some(meta_expr) = member_expr.obj.as_meta_prop()
545584
&& meta_expr
@@ -578,16 +617,8 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
578617
start: u32,
579618
end: u32,
580619
) -> Option<eval::BasicEvaluatedExpression<'p>> {
581-
if experiments_env_enabled(parser) && for_name == expr_name::IMPORT_META_ENV {
582-
add_import_meta_env_value_dependency(parser);
583-
let mut evaluated = BasicEvaluatedExpression::with_range(start, end);
584-
evaluated.set_truthy();
585-
evaluated.set_side_effects(false);
586-
Some(evaluated)
587-
} else {
588-
let property = ImportMetaBuiltinProperty::from_name(for_name)?;
589-
property.evaluate_identifier(self, parser, start, end)
590-
}
620+
let property = ImportMetaBuiltinProperty::from_name(for_name)?;
621+
property.evaluate_identifier(self, parser, start, end)
591622
}
592623

593624
fn evaluate(
@@ -608,7 +639,6 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
608639
|| import_meta_runtime_api_from_property(ident.sym.as_ref())
609640
.is_some_and(|api| self.runtime_api_enabled(api))
610641
|| self.preserve_property(Some(ident.sym.as_ref()))
611-
|| (experiments_env_enabled(parser) && ident.sym == "env")
612642
{
613643
return None;
614644
}
@@ -626,7 +656,6 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
626656
|| import_meta_runtime_api_from_property(value)
627657
.is_some_and(|api| self.runtime_api_enabled(api))
628658
|| self.preserve_property(Some(value))
629-
|| (experiments_env_enabled(parser) && value == "env")
630659
})
631660
{
632661
return None;
@@ -652,14 +681,6 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
652681
)));
653682
Some(true)
654683
}
655-
expr_name::IMPORT_META_ENV if experiments_env_enabled(parser) => {
656-
add_import_meta_env_value_dependency(parser);
657-
parser.add_presentational_dependency(Box::new(ConstDependency::new(
658-
unary_expr.span().into(),
659-
"'object'".into(),
660-
)));
661-
Some(true)
662-
}
663684
_ => {
664685
if let Some(property) = ImportMetaBuiltinProperty::from_name(for_name) {
665686
return property.add_typeof_dependency(self, parser, unary_expr);
@@ -715,12 +736,7 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
715736
content.push_str(&property);
716737
continue;
717738
}
718-
if experiments_env_enabled(parser) && prop.id == "env" {
719-
add_import_meta_env_value_dependency(parser);
720-
content.push_str("env: ");
721-
content.push_str(&import_meta_env_definitions_string(parser.compilation_id));
722-
} else if let Some(property) = ImportMetaBuiltinProperty::from_property(prop.id.as_ref())
723-
{
739+
if let Some(property) = ImportMetaBuiltinProperty::from_property(prop.id.as_ref()) {
724740
if let Some(rendered) = property.render_destructuring(self, parser, span) {
725741
content.push_str(&rendered);
726742
} else {
@@ -787,16 +803,14 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
787803
member_expr: &MemberExpr,
788804
for_name: &str,
789805
) -> Option<bool> {
790-
if experiments_env_enabled(parser)
791-
&& (is_import_meta_env_member(member_expr) || for_name == expr_name::IMPORT_META_ENV)
792-
{
793-
add_import_meta_env_value_dependency(parser);
794-
parser.add_presentational_dependency(Box::new(ConstDependency::new(
795-
member_expr.span().into(),
796-
import_meta_env_definitions_expression(parser, member_expr.span().real_lo()).into(),
797-
)));
798-
Some(true)
799-
} else if let Some(property) = ImportMetaBuiltinProperty::from_name(for_name)
806+
let property = ImportMetaBuiltinProperty::from_name(for_name).or_else(|| {
807+
if is_import_meta_env_member(member_expr) {
808+
ImportMetaBuiltinProperty::from_name(expr_name::IMPORT_META_ENV)
809+
} else {
810+
None
811+
}
812+
});
813+
if let Some(property) = property
800814
&& let Some(handled) = property.member(self, parser, member_expr)
801815
{
802816
Some(handled)
@@ -818,7 +832,9 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
818832
_members_optionals: &[bool],
819833
_member_ranges: &[Span],
820834
) -> Option<bool> {
821-
if !experiments_env_enabled(parser)
835+
let env_property = ImportMetaBuiltinProperty::from_name(expr_name::IMPORT_META_ENV)
836+
.expect("import.meta.env should be a known property");
837+
if !env_property.enabled(self, parser)
822838
|| for_name != expr_name::IMPORT_META
823839
|| members.first().is_none_or(|member| member != "env")
824840
{
@@ -927,7 +943,9 @@ impl<'p, 'a> JavascriptParserPlugin<'p, 'a> for ImportMetaPlugin {
927943
_ => None,
928944
});
929945

930-
if experiments_env_enabled(parser)
946+
let env_property = ImportMetaBuiltinProperty::from_name(expr_name::IMPORT_META_ENV)
947+
.expect("import.meta.env should be a known property");
948+
if env_property.enabled(self, parser)
931949
&& let Some(members) = &members
932950
&& members
933951
.members

packages/rspack/src/config/types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,11 @@ export type ImportMetaParserOptions = {
11891189
*/
11901190
dirname?: boolean;
11911191

1192+
/**
1193+
* Enable/disable evaluating import.meta.env.
1194+
*/
1195+
env?: boolean;
1196+
11921197
/**
11931198
* Enable/disable evaluating import.meta.filename.
11941199
*/
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
if (typeof import.meta.env === 'undefined') {
2+
import.meta.env = { RUNTIME: 'runtime' };
3+
}
4+
5+
const { env } = import.meta;
6+
7+
export default {
8+
direct: import.meta.env,
9+
destructured: env,
10+
type: typeof import.meta.env,
11+
};

tests/rspack-test/configCases/module/import-meta-env/index.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
1+
import disabled from './disabled';
2+
13
it("should work import.meta.env with EnvironmentPlugin", () => {
24
expect(import.meta.env.AAA).toBe(process.env.AAA);
35
});
46

7+
it("should preserve import.meta.env when its parser property is disabled", () => {
8+
expect(disabled.direct.RUNTIME).toBe('runtime');
9+
expect(disabled.destructured).toBe(disabled.direct);
10+
expect(disabled.type).toBe('object');
11+
});
12+
513
it("import.meta.env behaves like process.env", () => {
614
try {
715
const importMetaEnv = import.meta.env;

tests/rspack-test/configCases/module/import-meta-env/rspack.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,18 @@ const { EnvironmentPlugin } = require('@rspack/core');
55
/** @type {import("@rspack/core").Configuration} */
66
module.exports = {
77
target: 'node',
8+
module: {
9+
rules: [
10+
{
11+
test: /disabled\.js$/,
12+
parser: {
13+
importMeta: {
14+
env: false,
15+
},
16+
},
17+
},
18+
],
19+
},
820
plugins: [
921
new EnvironmentPlugin({
1022
AAA: 'aaa',

0 commit comments

Comments
 (0)