Skip to content

Commit a833d6c

Browse files
committed
Merge branch 'main' into refactor/jsx
2 parents e60ed50 + 5113121 commit a833d6c

File tree

164 files changed

+985
-805
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+985
-805
lines changed

.changeset/long-cars-sing.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
hstr: minor
3+
swc_atoms: major
4+
---
5+
6+
Optimize `atom!` for inlinable strings and adopt it across swc

CHANGELOG-CORE.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
# Changelog
22
## [unreleased]
33

4+
### Bug Fixes
5+
6+
7+
8+
- **(es/codegen)** Fix `.map` path when using `output_path` ([01e5bd1](https://github.com/swc-project/swc/commit/01e5bd1d6560d3b40e98122e09d0f7bd7c73b4c5))
9+
10+
11+
- **(swc)** Fix wrong caching of resolvers regarding file exts ([#10615](https://github.com/swc-project/swc/issues/10615)) ([68aacd1](https://github.com/swc-project/swc/commit/68aacd1dfc2dd97feb5636f1833a6fa1e15407bd))
12+
13+
## [[email protected]] - 2025-06-14
14+
415
### Performance
516

617

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
# Changelog
22
## [unreleased]
33

4+
### Bug Fixes
5+
6+
7+
8+
- **(es/codegen)** Fix `.map` path when using `output_path` ([01e5bd1](https://github.com/swc-project/swc/commit/01e5bd1d6560d3b40e98122e09d0f7bd7c73b4c5))
9+
10+
11+
- **(swc)** Fix wrong caching of resolvers regarding file exts ([#10615](https://github.com/swc-project/swc/issues/10615)) ([68aacd1](https://github.com/swc-project/swc/commit/68aacd1dfc2dd97feb5636f1833a6fa1e15407bd))
12+
413
### Performance
514

615

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bindings/binding_html_node/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ impl MinifyCss for CssMinifier {
402402
span: Default::default(),
403403
name: swc_css_ast::AtRuleName::Ident(swc_css_ast::Ident {
404404
span: Default::default(),
405-
value: "media".into(),
405+
value: atom!("media"),
406406
raw: None,
407407
}),
408408
prelude: Some(
@@ -423,7 +423,7 @@ impl MinifyCss for CssMinifier {
423423
value: vec![swc_css_ast::ComponentValue::Str(
424424
Box::new(swc_css_ast::Str {
425425
span: Default::default(),
426-
value: "placeholder".into(),
426+
value: atom!("placeholder"),
427427
raw: None,
428428
}),
429429
)],

crates/binding_macros/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ binding_wasm = [
3333

3434
[dependencies]
3535
# Common deps for the SWC imports
36-
swc = { optional = true, version = "26.0.0", path = "../swc" }
36+
swc = { optional = true, version = "26.0.1", path = "../swc" }
3737
swc_common = { optional = true, version = "12.0.1", path = "../swc_common" }
3838
swc_ecma_ast = { optional = true, version = "12.0.0", path = "../swc_ecma_ast" }
3939
swc_ecma_transforms = { optional = true, version = "20.0.0", path = "../swc_ecma_transforms" }

crates/hstr/src/dynamic.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::{
44
ffi::c_void,
55
hash::{BuildHasherDefault, Hash, Hasher},
66
mem::{forget, ManuallyDrop},
7+
num::NonZeroU8,
78
ops::Deref,
89
ptr::{self, NonNull},
910
};
@@ -13,7 +14,7 @@ use triomphe::{HeaderWithLength, ThinArc};
1314

1415
use crate::{
1516
tagged_value::{TaggedValue, MAX_INLINE_LEN},
16-
Atom, INLINE_TAG_INIT, LEN_OFFSET, TAG_MASK,
17+
Atom, INLINE_TAG, INLINE_TAG_INIT, LEN_OFFSET, TAG_MASK,
1718
};
1819

1920
#[derive(PartialEq, Eq)]
@@ -146,6 +147,28 @@ where
146147
}
147148
}
148149

150+
/// Attempts to construct an Atom but only if it can be constructed inline.
151+
/// This is primarily useful in constant contexts.
152+
pub(crate) const fn inline_atom(text: &str) -> Option<Atom> {
153+
let len = text.len();
154+
if len < MAX_INLINE_LEN {
155+
// INLINE_TAG ensures this is never zero
156+
let tag = INLINE_TAG | ((len as u8) << LEN_OFFSET);
157+
let mut unsafe_data = TaggedValue::new_tag(NonZeroU8::new(tag).unwrap());
158+
// This odd pattern is needed because we cannot create slices from ranges in
159+
// constant context.
160+
unsafe {
161+
unsafe_data
162+
.data_mut()
163+
.split_at_mut(len)
164+
.0
165+
.copy_from_slice(text.as_bytes());
166+
}
167+
return Some(Atom { unsafe_data });
168+
}
169+
None
170+
}
171+
149172
pub(crate) trait Storage {
150173
fn insert_entry(self, text: &str, hash: u64, is_global: bool) -> Item;
151174
}

crates/hstr/src/lib.rs

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,32 @@ pub struct Atom {
9696
#[doc(hidden)]
9797
pub type CachedAtom = Lazy<Atom>;
9898

99+
#[doc(hidden)]
100+
pub const fn inline_atom(s: &str) -> Option<Atom> {
101+
dynamic::inline_atom(s)
102+
}
103+
99104
/// Create an atom from a string literal. This atom is never dropped.
100105
#[macro_export]
101106
macro_rules! atom {
102-
($s:tt) => {{
103-
#[inline(never)]
104-
fn get_atom() -> $crate::Atom {
105-
static CACHE: $crate::CachedAtom = $crate::CachedAtom::new(|| $crate::Atom::from($s));
107+
($s:expr) => {{
108+
const INLINE: ::core::option::Option<$crate::Atom> = $crate::inline_atom($s);
109+
// This condition can be evaluated at compile time to enable inlining as a
110+
// simple constant
111+
if INLINE.is_some() {
112+
INLINE.unwrap()
113+
} else {
114+
// Otherwise we use a
115+
#[inline(never)]
116+
fn get_atom() -> $crate::Atom {
117+
static CACHE: $crate::CachedAtom =
118+
$crate::CachedAtom::new(|| $crate::Atom::from($s));
106119

107-
(*CACHE).clone()
108-
}
120+
(*CACHE).clone()
121+
}
109122

110-
get_atom()
123+
get_atom()
124+
}
111125
}};
112126
}
113127

@@ -430,3 +444,39 @@ where
430444
Ok(Atom::new(s))
431445
}
432446
}
447+
448+
#[cfg(test)]
449+
mod macro_tests {
450+
451+
use super::*;
452+
#[test]
453+
fn test_atom() {
454+
// Test enough to exceed the small string optimization
455+
assert_eq!(atom!(""), Atom::default());
456+
assert_eq!(atom!(""), Atom::from(""));
457+
assert_eq!(atom!("a"), Atom::from("a"));
458+
assert_eq!(atom!("ab"), Atom::from("ab"));
459+
assert_eq!(atom!("abc"), Atom::from("abc"));
460+
assert_eq!(atom!("abcd"), Atom::from("abcd"));
461+
assert_eq!(atom!("abcde"), Atom::from("abcde"));
462+
assert_eq!(atom!("abcdef"), Atom::from("abcdef"));
463+
assert_eq!(atom!("abcdefg"), Atom::from("abcdefg"));
464+
assert_eq!(atom!("abcdefgh"), Atom::from("abcdefgh"));
465+
assert_eq!(atom!("abcdefghi"), Atom::from("abcdefghi"));
466+
}
467+
468+
#[test]
469+
fn test_inline_atom() {
470+
// This is a silly test, just asserts that rustc can evaluate the pattern from
471+
// our macro in a constant context.
472+
const STR: Atom = {
473+
let inline = inline_atom("hello");
474+
if inline.is_some() {
475+
inline.unwrap()
476+
} else {
477+
unreachable!();
478+
}
479+
};
480+
assert_eq!(STR, Atom::from("hello"));
481+
}
482+
}

crates/hstr/src/tagged_value.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl TaggedValue {
7272
}
7373

7474
#[inline(always)]
75-
pub fn new_tag(value: NonZeroU8) -> Self {
75+
pub const fn new_tag(value: NonZeroU8) -> Self {
7676
let value = value.get() as RawTaggedValue;
7777
Self {
7878
value: unsafe { std::mem::transmute(value) },
@@ -134,7 +134,7 @@ impl TaggedValue {
134134
/// used when setting the untagged slice part of this value. If tag is
135135
/// zero and the slice is zeroed out, using this `TaggedValue` will be
136136
/// UB!
137-
pub unsafe fn data_mut(&mut self) -> &mut [u8] {
137+
pub const unsafe fn data_mut(&mut self) -> &mut [u8] {
138138
let x: *mut _ = &mut self.value;
139139
let mut data = x as *mut u8;
140140
// All except the lowest byte, which is first in little-endian, last in

crates/swc/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ include = ["Cargo.toml", "src/**/*.rs"]
99
license = { workspace = true }
1010
name = "swc"
1111
repository = { workspace = true }
12-
version = "26.0.0"
12+
version = "26.0.1"
1313

1414
[lib]
1515
bench = false
@@ -78,7 +78,7 @@ swc_common = { version = "12.0.1", path = "../swc_common", features = [
7878
"sourcemap",
7979
"parking_lot",
8080
] }
81-
swc_compiler_base = { version = "23.0.1", path = "../swc_compiler_base" }
81+
swc_compiler_base = { version = "23.0.2", path = "../swc_compiler_base" }
8282
swc_config = { version = "3.1.1", path = "../swc_config" }
8383
swc_ecma_ast = { version = "12.0.0", path = "../swc_ecma_ast" }
8484
swc_ecma_codegen = { version = "14.0.0", path = "../swc_ecma_codegen" }

crates/swc/src/config/mod.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1838,8 +1838,9 @@ fn build_resolver(
18381838
resolve_fully: bool,
18391839
file_extension: &str,
18401840
) -> SwcImportResolver {
1841-
static CACHE: Lazy<DashMap<(PathBuf, CompiledPaths, bool), SwcImportResolver, FxBuildHasher>> =
1842-
Lazy::new(Default::default);
1841+
static CACHE: Lazy<
1842+
DashMap<(PathBuf, CompiledPaths, bool, String), SwcImportResolver, FxBuildHasher>,
1843+
> = Lazy::new(Default::default);
18431844

18441845
// On Windows, we need to normalize path as UNC path.
18451846
if cfg!(target_os = "windows") {
@@ -1855,7 +1856,12 @@ fn build_resolver(
18551856
.unwrap();
18561857
}
18571858

1858-
if let Some(cached) = CACHE.get(&(base_url.clone(), paths.clone(), resolve_fully)) {
1859+
if let Some(cached) = CACHE.get(&(
1860+
base_url.clone(),
1861+
paths.clone(),
1862+
resolve_fully,
1863+
file_extension.to_owned(),
1864+
)) {
18591865
return cached.clone();
18601866
}
18611867

@@ -1882,7 +1888,10 @@ fn build_resolver(
18821888
Arc::new(r)
18831889
};
18841890

1885-
CACHE.insert((base_url, paths, resolve_fully), r.clone());
1891+
CACHE.insert(
1892+
(base_url, paths, resolve_fully, file_extension.to_owned()),
1893+
r.clone(),
1894+
);
18861895

18871896
r
18881897
}

crates/swc/tests/fixture/deno/deno-10014/case1/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
"Error"
88
],
99
"sources": [
10-
"../../input/index.ts"
10+
"../input/index.ts"
1111
],
1212
"sourcesContent": [
1313
"import \"./errors.ts\";\n\nfunction a() {\n t();\n}\n\nfunction t(x = false) {\n if (x) {\n throw new Error(\"Hello\");\n }\n t(!0);\n}\n\na();\n"

crates/swc/tests/fixture/issues-10xxx/10346/output/input.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"foo"
55
],
66
"sources": [
7-
"../../input/input.js"
7+
"../input/input.js"
88
],
99
"sourcesContent": [
1010
"\nexport const foo = 1;"

crates/swc/tests/fixture/issues-10xxx/10442-ignoreList/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"log"
99
],
1010
"sources": [
11-
"../../input/index.js"
11+
"../input/index.js"
1212
],
1313
"sourcesContent": [
1414
"console.log('foo');"

crates/swc/tests/fixture/issues-10xxx/10445-glob-filepattern/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"log"
99
],
1010
"sources": [
11-
"../../input/index.js"
11+
"../input/index.js"
1212
],
1313
"sourcesContent": [
1414
"console.log('foo');"

crates/swc/tests/fixture/issues-1xxx/1309/case1/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"foo"
55
],
66
"sources": [
7-
"../../input/index.ts"
7+
"../input/index.ts"
88
],
99
"sourcesContent": [
1010
"export const foo = 1;\n"

crates/swc/tests/fixture/issues-1xxx/1581/case2/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"foo"
55
],
66
"sources": [
7-
"../../input/index.js"
7+
"../input/index.js"
88
],
99
"sourcesContent": [
1010
"export const foo = () => {\n return 2;\n};\n"

crates/swc/tests/fixture/issues-2xxx/2423/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"log"
99
],
1010
"sources": [
11-
"../../input/index.ts"
11+
"../input/index.ts"
1212
],
1313
"sourcesContent": [
1414
"namespace A {\n export const v = 25;\n export function a() {\n console.log(v);\n }\n}\n"

crates/swc/tests/fixture/issues-3xxx/3715/1/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"a"
55
],
66
"sources": [
7-
"../../input/index.js"
7+
"../input/index.js"
88
],
99
"sourcesContent": [
1010
"a() /* IMPORTANT_DO_NOT_REMOVE */;\n"

crates/swc/tests/fixture/issues-3xxx/3715/2/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"a"
55
],
66
"sources": [
7-
"../../input/index.js"
7+
"../input/index.js"
88
],
99
"sourcesContent": [
1010
"a() /* IMPORTANT_DO_NOT_REMOVE */;\n"

crates/swc/tests/fixture/issues-3xxx/3716/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"a"
55
],
66
"sources": [
7-
"../../input/index.js"
7+
"../input/index.js"
88
],
99
"sourcesContent": [
1010
"a(); /*?*/\n\na(); //?\n\na(); /*?*/\n\na(); //?\n"

crates/swc/tests/fixture/issues-3xxx/3782/output/index.map

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"setTimeout"
1010
],
1111
"sources": [
12-
"../../input/index.ts"
12+
"../input/index.ts"
1313
],
1414
"sourcesContent": [
1515
"// index.ts\nexport * as get from \"./get\";\n\n// get/index.ts\n\nexport const byID = (id: string): Promise<string> => {\n // Do some async stuff\n return new Promise((resolve) =>\n setTimeout(() => {\n resolve(\"result\");\n }, 2000)\n );\n};\n"

0 commit comments

Comments
 (0)