Skip to content

Commit 11727a6

Browse files
authored
feat(es/module): Support more import.meta properties (#10179)
**Related issue:** - Closes #10177
1 parent bccdafc commit 11727a6

File tree

7 files changed

+162
-15
lines changed

7 files changed

+162
-15
lines changed

.changeset/fluffy-phones-fetch.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_core: minor
3+
swc_ecma_transforms_module: minor
4+
---
5+
6+
feat(es/module): Support more `import.meta` properties

crates/swc_ecma_transforms_module/src/amd.rs

Lines changed: 74 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use swc_common::{
66
comments::{CommentKind, Comments},
77
source_map::PURE_SP,
88
util::take::Take,
9-
Mark, Span, SyntaxContext, DUMMY_SP,
9+
Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
1010
};
1111
use swc_ecma_ast::*;
1212
use swc_ecma_transforms_base::{feature::FeatureFlag, helper_expr};
@@ -283,17 +283,75 @@ where
283283
);
284284
}
285285
Expr::Member(MemberExpr { span, obj, prop })
286-
if prop.is_ident_with("url")
287-
&& !self.config.preserve_import_meta
286+
if !self.config.preserve_import_meta
288287
&& obj
289288
.as_meta_prop()
290289
.map(|p| p.kind == MetaPropKind::ImportMeta)
291290
.unwrap_or_default() =>
292291
{
293-
obj.visit_mut_with(self);
294-
295-
*n = amd_import_meta_url(*span, self.module());
292+
let p = match prop {
293+
MemberProp::Ident(IdentName { sym, .. }) => &**sym,
294+
MemberProp::Computed(ComputedPropName { expr, .. }) => match &**expr {
295+
Expr::Lit(Lit::Str(s)) => &s.value,
296+
_ => return,
297+
},
298+
MemberProp::PrivateName(..) => return,
299+
};
296300
self.found_import_meta = true;
301+
302+
match p {
303+
// new URL(module.uri, document.baseURI).href
304+
"url" => {
305+
*n = amd_import_meta_url(*span, self.module());
306+
}
307+
// require.toUrl()
308+
"resolve" => {
309+
let mut require = self.require.clone();
310+
require.span = obj.span();
311+
*obj = require.into();
312+
313+
match prop {
314+
MemberProp::Ident(IdentName { sym, .. }) => *sym = "toUrl".into(),
315+
MemberProp::Computed(ComputedPropName { expr, .. }) => {
316+
match &mut **expr {
317+
Expr::Lit(Lit::Str(s)) => {
318+
s.value = "toUrl".into();
319+
s.raw = None;
320+
}
321+
_ => unreachable!(),
322+
}
323+
}
324+
MemberProp::PrivateName(..) => unreachable!(),
325+
}
326+
}
327+
// module.uri.split("/").pop()
328+
"filename" => {
329+
*n = amd_import_meta_filename(*span, self.module());
330+
}
331+
// require.toUrl(".")
332+
"dirname" => {
333+
let mut require = self.require.clone();
334+
require.span = obj.span();
335+
*obj = require.into();
336+
337+
match prop {
338+
MemberProp::Ident(IdentName { sym, .. }) => *sym = "toUrl".into(),
339+
MemberProp::Computed(ComputedPropName { expr, .. }) => {
340+
match &mut **expr {
341+
Expr::Lit(Lit::Str(s)) => {
342+
s.value = "toUrl".into();
343+
s.raw = None;
344+
}
345+
_ => unreachable!(),
346+
}
347+
}
348+
MemberProp::PrivateName(..) => unreachable!(),
349+
}
350+
351+
*n = n.take().as_call(n.span(), vec![quote_str!(".").as_arg()]);
352+
}
353+
_ => {}
354+
}
297355
}
298356
_ => n.visit_mut_children_with(self),
299357
}
@@ -513,3 +571,13 @@ fn amd_import_meta_url(span: Span, module: Ident) -> Expr {
513571
}
514572
.into()
515573
}
574+
575+
// module.uri.split("/").pop()
576+
fn amd_import_meta_filename(span: Span, module: Ident) -> Expr {
577+
module
578+
.make_member(quote_ident!("uri"))
579+
.make_member(quote_ident!("split"))
580+
.as_call(DUMMY_SP, vec![quote_str!("/").as_arg()])
581+
.make_member(quote_ident!("pop"))
582+
.as_call(span, vec![])
583+
}

crates/swc_ecma_transforms_module/src/common_js.rs

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use rustc_hash::FxHashSet;
2-
use swc_common::{source_map::PURE_SP, util::take::Take, Mark, Span, SyntaxContext, DUMMY_SP};
2+
use swc_common::{
3+
source_map::PURE_SP, util::take::Take, Mark, Span, Spanned, SyntaxContext, DUMMY_SP,
4+
};
35
use swc_ecma_ast::*;
46
use swc_ecma_transforms_base::{feature::FeatureFlag, helper_expr};
57
use swc_ecma_utils::{
@@ -200,20 +202,56 @@ impl VisitMut for Cjs {
200202
);
201203
}
202204
Expr::Member(MemberExpr { span, obj, prop })
203-
if prop.is_ident_with("url")
204-
&& !self.config.preserve_import_meta
205+
if !self.config.preserve_import_meta
205206
&& obj
206207
.as_meta_prop()
207208
.map(|p| p.kind == MetaPropKind::ImportMeta)
208209
.unwrap_or_default() =>
209210
{
210-
obj.visit_mut_with(self);
211+
let p = match prop {
212+
MemberProp::Ident(IdentName { sym, .. }) => &**sym,
213+
MemberProp::Computed(ComputedPropName { expr, .. }) => match &**expr {
214+
Expr::Lit(Lit::Str(s)) => &s.value,
215+
_ => return,
216+
},
217+
MemberProp::PrivateName(..) => return,
218+
};
211219

212-
let require = quote_ident!(
213-
SyntaxContext::empty().apply_mark(self.unresolved_mark),
214-
"require"
215-
);
216-
*n = cjs_import_meta_url(*span, require, self.unresolved_mark);
220+
match p {
221+
"url" => {
222+
let require = quote_ident!(
223+
SyntaxContext::empty().apply_mark(self.unresolved_mark),
224+
"require"
225+
);
226+
*n = cjs_import_meta_url(*span, require, self.unresolved_mark);
227+
}
228+
"resolve" => {
229+
let require = quote_ident!(
230+
SyntaxContext::empty().apply_mark(self.unresolved_mark),
231+
obj.span(),
232+
"require"
233+
);
234+
235+
*obj = Box::new(require.into());
236+
}
237+
"filename" => {
238+
*n = quote_ident!(
239+
SyntaxContext::empty().apply_mark(self.unresolved_mark),
240+
*span,
241+
"__filename"
242+
)
243+
.into();
244+
}
245+
"dirname" => {
246+
*n = quote_ident!(
247+
SyntaxContext::empty().apply_mark(self.unresolved_mark),
248+
*span,
249+
"__dirname"
250+
)
251+
.into();
252+
}
253+
_ => {}
254+
}
217255
}
218256
_ => n.visit_mut_children_with(self),
219257
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const react = import.meta.resolve("react");
2+
const url = import.meta.url;
3+
const filename = import.meta.filename;
4+
const dirname = import.meta.dirname;
5+
6+
console.log(react, url, filename, dirname);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
define([
2+
"require",
3+
"module"
4+
], function(require, module) {
5+
"use strict";
6+
const react = require.toUrl("react");
7+
const url = new URL(module.uri, document.baseURI).href;
8+
const filename = module.uri.split("/").pop();
9+
const dirname = require.toUrl(".");
10+
console.log(react, url, filename, dirname);
11+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"use strict";
2+
const react = require.resolve("react");
3+
const url = require("url").pathToFileURL(__filename).toString();
4+
const filename = __filename;
5+
const dirname = __dirname;
6+
console.log(react, url, filename, dirname);
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
(function(global, factory) {
2+
if (typeof module === "object" && typeof module.exports === "object") factory();
3+
else if (typeof define === "function" && define.amd) define([], factory);
4+
else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory();
5+
})(this, function() {
6+
"use strict";
7+
const react = import.meta.resolve("react");
8+
const url = import.meta.url;
9+
const filename = import.meta.filename;
10+
const dirname = import.meta.dirname;
11+
console.log(react, url, filename, dirname);
12+
});

0 commit comments

Comments
 (0)