diff --git a/.clippy.toml b/.clippy.toml
index 9da0cf0e84dcc..c76422cd094e8 100644
--- a/.clippy.toml
+++ b/.clippy.toml
@@ -1,4 +1,4 @@
-ignore-interior-mutability = ["oxc_linter::rule::RuleWithSeverity"]
+ignore-interior-mutability = ["oxc_linter::rules::RuleEnum"]
disallowed-methods = [
{ path = "str::to_ascii_lowercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_ascii_lowercase` instead." },
diff --git a/.github/generated/ast_changes_watch_list.yml b/.github/generated/ast_changes_watch_list.yml
index b671c40bc73f7..96738fe0fefb0 100644
--- a/.github/generated/ast_changes_watch_list.yml
+++ b/.github/generated/ast_changes_watch_list.yml
@@ -20,8 +20,14 @@ src:
- 'crates/oxc_ast/src/generated/derive_get_span_mut.rs'
- 'crates/oxc_ast/src/generated/derive_take_in.rs'
- 'crates/oxc_ast/src/generated/get_id.rs'
- - 'crates/oxc_ast/src/serialize.rs'
- - 'crates/oxc_ast_macros/src/generated/mod.rs'
+ - 'crates/oxc_ast/src/serialize/basic.rs'
+ - 'crates/oxc_ast/src/serialize/js.rs'
+ - 'crates/oxc_ast/src/serialize/jsx.rs'
+ - 'crates/oxc_ast/src/serialize/literal.rs'
+ - 'crates/oxc_ast/src/serialize/mod.rs'
+ - 'crates/oxc_ast/src/serialize/ts.rs'
+ - 'crates/oxc_ast_macros/src/generated/derived_traits.rs'
+ - 'crates/oxc_ast_macros/src/generated/structs.rs'
- 'crates/oxc_ast_macros/src/lib.rs'
- 'crates/oxc_ast_visit/src/generated/utf8_to_utf16_converter.rs'
- 'crates/oxc_ast_visit/src/generated/visit.rs'
@@ -35,7 +41,7 @@ src:
- 'crates/oxc_span/src/generated/assert_layouts.rs'
- 'crates/oxc_span/src/generated/derive_dummy.rs'
- 'crates/oxc_span/src/generated/derive_estree.rs'
- - 'crates/oxc_span/src/source_type/mod.rs'
+ - 'crates/oxc_span/src/source_type.rs'
- 'crates/oxc_span/src/span.rs'
- 'crates/oxc_syntax/src/generated/assert_layouts.rs'
- 'crates/oxc_syntax/src/generated/derive_clone_in.rs'
diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
index e742fe4ab2714..7b26216d345a1 100644
--- a/.github/workflows/benchmark.yml
+++ b/.github/workflows/benchmark.yml
@@ -148,7 +148,7 @@ jobs:
chmod +x ./target/codspeed/instrumentation/oxc_benchmark/*
- name: Install codspeed
- uses: taiki-e/install-action@86c23eed46c17b80677df6d8151545ce3e236c61 # v2.50.7
+ uses: taiki-e/install-action@83254c543806f3224380bf1001d6fac8feaf2d0b # v2.50.10
with:
tool: cargo-codspeed
diff --git a/.github/workflows/cargo_llvm_lines.yml b/.github/workflows/cargo_llvm_lines.yml
index d218ea9a05baf..aedb6a28d8c38 100644
--- a/.github/workflows/cargo_llvm_lines.yml
+++ b/.github/workflows/cargo_llvm_lines.yml
@@ -22,7 +22,7 @@ jobs:
- uses: oxc-project/setup-rust@cd82e1efec7fef815e2c23d296756f31c7cdc03d # v1.0.0
- name: Install cargo-llvm-lines
- uses: taiki-e/install-action@86c23eed46c17b80677df6d8151545ce3e236c61 # v2.50.7
+ uses: taiki-e/install-action@83254c543806f3224380bf1001d6fac8feaf2d0b # v2.50.10
with:
tool: cargo-llvm-lines
diff --git a/.github/workflows/ci_security.yml b/.github/workflows/ci_security.yml
index 62077e93462d4..ac69bf785a3c9 100644
--- a/.github/workflows/ci_security.yml
+++ b/.github/workflows/ci_security.yml
@@ -23,7 +23,7 @@ jobs:
steps:
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
- - uses: taiki-e/install-action@86c23eed46c17b80677df6d8151545ce3e236c61 # v2.50.7
+ - uses: taiki-e/install-action@83254c543806f3224380bf1001d6fac8feaf2d0b # v2.50.10
with:
tool: zizmor
diff --git a/.github/workflows/dprint.yml b/.github/workflows/dprint.yml
index d6385b1db16da..0514655e93ebb 100644
--- a/.github/workflows/dprint.yml
+++ b/.github/workflows/dprint.yml
@@ -17,7 +17,7 @@ jobs:
steps:
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
- - uses: taiki-e/install-action@86c23eed46c17b80677df6d8151545ce3e236c61 # v2.50.7
+ - uses: taiki-e/install-action@83254c543806f3224380bf1001d6fac8feaf2d0b # v2.50.10
with:
tool: dprint
diff --git a/.github/workflows/link_check.yml b/.github/workflows/link_check.yml
index 3dd5713df84f9..0e2e21f35a4b2 100644
--- a/.github/workflows/link_check.yml
+++ b/.github/workflows/link_check.yml
@@ -31,7 +31,7 @@ jobs:
uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
- name: Check Links
- uses: lycheeverse/lychee-action@1d97d84f0bc547f7b25f4c2170d87d810dc2fb2c # v2.4.0
+ uses: lycheeverse/lychee-action@82202e5e9c2f4ef1a55a3d02563e1cb6041e5332 # v2.4.1
with:
# For parameter description, see https://github.com/lycheeverse/lychee#commandline-parameters
# Accept 429 for now due to GitHub rate limit.
diff --git a/.github/workflows/release_oxlint.yml b/.github/workflows/release_oxlint.yml
index 77c1ab73416a4..c4164ff2de02b 100644
--- a/.github/workflows/release_oxlint.yml
+++ b/.github/workflows/release_oxlint.yml
@@ -88,7 +88,7 @@ jobs:
- uses: taiki-e/checkout-action@b13d20b7cda4e2f325ef19895128f7ff735c0b3d # v1.3.1
- name: Install cross
- uses: taiki-e/install-action@86c23eed46c17b80677df6d8151545ce3e236c61 # v2.50.7
+ uses: taiki-e/install-action@83254c543806f3224380bf1001d6fac8feaf2d0b # v2.50.10
with:
tool: cross
diff --git a/.github/workflows/release_vscode.yml b/.github/workflows/release_vscode.yml
index 00b1e681b5fba..3ddb3c594b791 100644
--- a/.github/workflows/release_vscode.yml
+++ b/.github/workflows/release_vscode.yml
@@ -81,7 +81,7 @@ jobs:
run: pnpm run compile
- name: Install cross
- uses: taiki-e/install-action@86c23eed46c17b80677df6d8151545ce3e236c61 # v2.50.7
+ uses: taiki-e/install-action@83254c543806f3224380bf1001d6fac8feaf2d0b # v2.50.10
with:
tool: cross
diff --git a/.github/workflows/reusable_release_napi.yml b/.github/workflows/reusable_release_napi.yml
index 960fb0fa12e0f..350411b462251 100644
--- a/.github/workflows/reusable_release_napi.yml
+++ b/.github/workflows/reusable_release_napi.yml
@@ -86,6 +86,11 @@ jobs:
build: |
pnpm build --target armv7-unknown-linux-gnueabihf --use-napi-cross
+ - os: ubuntu-latest
+ target: armv7-unknown-linux-musleabihf
+ build: |
+ pnpm build --target armv7-unknown-linux-musleabihf -x
+
- os: macos-latest
target: x86_64-apple-darwin
build: |
diff --git a/.gitignore b/.gitignore
index 2313c7e481136..e8224a0b34300 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,6 +24,8 @@ target/
/editors/vscode/out/
/editors/vscode/*.vsix
/editors/vscode/test_workspace/
+/editors/vscode/test_workspace_second/
+/editors/vscode/*.test.code-workspace
# Cloned conformance repos
tasks/coverage/babel/
diff --git a/Cargo.lock b/Cargo.lock
index f2068566de9ed..aa57190d0cfff 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -58,9 +58,9 @@ checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "backtrace"
-version = "0.3.74"
+version = "0.3.75"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
+checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
dependencies = [
"addr2line",
"cfg-if",
@@ -68,7 +68,7 @@ dependencies = [
"miniz_oxide",
"object",
"rustc-demangle",
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -176,9 +176,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.21"
+version = "1.2.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8691782945451c1c383942c4874dbe63814f61cb57ef773cda2972682b7bb3c0"
+checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1"
dependencies = [
"shlex",
]
@@ -808,9 +808,9 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.3.2"
+version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
+checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
"libc",
@@ -917,21 +917,22 @@ dependencies = [
[[package]]
name = "icu_collections"
-version = "1.5.0"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526"
+checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
dependencies = [
"displaydoc",
+ "potential_utf",
"yoke",
"zerofrom",
"zerovec",
]
[[package]]
-name = "icu_locid"
-version = "1.5.0"
+name = "icu_locale_core"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
dependencies = [
"displaydoc",
"litemap",
@@ -940,31 +941,11 @@ dependencies = [
"zerovec",
]
-[[package]]
-name = "icu_locid_transform"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_locid_transform_data",
- "icu_provider",
- "tinystr",
- "zerovec",
-]
-
-[[package]]
-name = "icu_locid_transform_data"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
-
[[package]]
name = "icu_normalizer"
-version = "1.5.0"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f"
+checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
dependencies = [
"displaydoc",
"icu_collections",
@@ -972,67 +953,54 @@ dependencies = [
"icu_properties",
"icu_provider",
"smallvec",
- "utf16_iter",
- "utf8_iter",
- "write16",
"zerovec",
]
[[package]]
name = "icu_normalizer_data"
-version = "1.5.1"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7"
+checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
[[package]]
name = "icu_properties"
-version = "1.5.1"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5"
+checksum = "2549ca8c7241c82f59c80ba2a6f415d931c5b58d24fb8412caa1a1f02c49139a"
dependencies = [
"displaydoc",
"icu_collections",
- "icu_locid_transform",
+ "icu_locale_core",
"icu_properties_data",
"icu_provider",
- "tinystr",
+ "potential_utf",
+ "zerotrie",
"zerovec",
]
[[package]]
name = "icu_properties_data"
-version = "1.5.1"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2"
+checksum = "8197e866e47b68f8f7d95249e172903bec06004b18b2937f1095d40a0c57de04"
[[package]]
name = "icu_provider"
-version = "1.5.0"
+version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
+checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
dependencies = [
"displaydoc",
- "icu_locid",
- "icu_provider_macros",
+ "icu_locale_core",
"stable_deref_trait",
"tinystr",
"writeable",
"yoke",
"zerofrom",
+ "zerotrie",
"zerovec",
]
-[[package]]
-name = "icu_provider_macros"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
[[package]]
name = "ident_case"
version = "1.0.1"
@@ -1052,9 +1020,9 @@ dependencies = [
[[package]]
name = "idna_adapter"
-version = "1.2.0"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71"
+checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
dependencies = [
"icu_normalizer",
"icu_properties",
@@ -1124,18 +1092,18 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "javascript-globals"
-version = "1.0.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1801f93e5ec6ff0967c1efb67824146b8c5750c316ef3b5ff9d3754e933dfbfa"
+checksum = "0d354e7ed074ff87cc305457421b6fd6388ea445f5a4e8b300e0f3a2cd96df8b"
dependencies = [
"phf",
]
[[package]]
name = "jiff"
-version = "0.2.12"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d07d8d955d798e7a4d6f9c58cd1f1916e790b42b092758a9ef6e16fef9f1b3fd"
+checksum = "f02000660d30638906021176af16b17498bd0d12813dbfe7b276d8bc7f3c0806"
dependencies = [
"jiff-static",
"log",
@@ -1146,9 +1114,9 @@ dependencies = [
[[package]]
name = "jiff-static"
-version = "0.2.12"
+version = "0.2.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f244cfe006d98d26f859c7abd1318d85327e1882dc9cef80f62daeeb0adcf300"
+checksum = "f3c30758ddd7188629c6713fc45d1188af4f44c90582311d0c8d8c9907f60c48"
dependencies = [
"proc-macro2",
"quote",
@@ -1207,19 +1175,19 @@ checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
[[package]]
name = "libloading"
-version = "0.8.6"
+version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
+checksum = "6a793df0d7afeac54f95b471d3af7f0d4fb975699f972341a4b76988d49cdf0c"
dependencies = [
"cfg-if",
- "windows-targets",
+ "windows-targets 0.53.0",
]
[[package]]
name = "libm"
-version = "0.2.14"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a25169bd5913a4b437588a7e3d127cd6e90127b60e0ffbd834a38f1599e016b8"
+checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libmimalloc-sys2"
@@ -1240,9 +1208,9 @@ checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
[[package]]
name = "litemap"
-version = "0.7.5"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
+checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
[[package]]
name = "litrs"
@@ -1490,7 +1458,7 @@ checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564"
[[package]]
name = "oxc"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1512,9 +1480,9 @@ dependencies = [
[[package]]
name = "oxc-browserslist"
-version = "2.0.1"
+version = "2.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf11cf76199836fa65eb981c7cee15baaaa3812ddec4210e2f38f6b96d413e34"
+checksum = "b847912b3807a563f0e0e122bd4086dfca503662fc16f8558b253bdf83cfa71f"
dependencies = [
"nom",
"rustc-hash",
@@ -1551,7 +1519,7 @@ dependencies = [
[[package]]
name = "oxc_allocator"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"allocator-api2",
"bumpalo",
@@ -1566,7 +1534,7 @@ dependencies = [
[[package]]
name = "oxc_ast"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"bitflags 2.9.0",
"cow-utils",
@@ -1581,8 +1549,9 @@ dependencies = [
[[package]]
name = "oxc_ast_macros"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
+ "phf",
"proc-macro2",
"quote",
"syn",
@@ -1601,6 +1570,7 @@ dependencies = [
"lazy-regex",
"oxc_index",
"phf",
+ "phf_codegen",
"prettyplease",
"proc-macro2",
"quote",
@@ -1612,7 +1582,7 @@ dependencies = [
[[package]]
name = "oxc_ast_visit"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"oxc_allocator",
"oxc_ast",
@@ -1646,7 +1616,7 @@ dependencies = [
[[package]]
name = "oxc_cfg"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"bitflags 2.9.0",
"itertools",
@@ -1659,7 +1629,7 @@ dependencies = [
[[package]]
name = "oxc_codegen"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"base64",
"bitflags 2.9.0",
@@ -1722,14 +1692,14 @@ dependencies = [
[[package]]
name = "oxc_data_structures"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"ropey",
]
[[package]]
name = "oxc_diagnostics"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"cow-utils",
"oxc-miette",
@@ -1737,7 +1707,7 @@ dependencies = [
[[package]]
name = "oxc_ecmascript"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"cow-utils",
"num-bigint",
@@ -1749,7 +1719,7 @@ dependencies = [
[[package]]
name = "oxc_estree"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"itoa",
"oxc_data_structures",
@@ -1783,7 +1753,7 @@ dependencies = [
[[package]]
name = "oxc_isolated_declarations"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"bitflags 2.9.0",
"insta",
@@ -1801,7 +1771,7 @@ dependencies = [
[[package]]
name = "oxc_language_server"
-version = "0.16.10"
+version = "0.16.11"
dependencies = [
"env_logger",
"futures",
@@ -1822,7 +1792,7 @@ dependencies = [
[[package]]
name = "oxc_linter"
-version = "0.16.10"
+version = "0.16.11"
dependencies = [
"bitflags 2.9.0",
"constcat",
@@ -1830,7 +1800,6 @@ dependencies = [
"cow-utils",
"fast-glob",
"globset",
- "ignore",
"indexmap",
"insta",
"itertools",
@@ -1884,7 +1853,7 @@ dependencies = [
[[package]]
name = "oxc_mangler"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"fixedbitset",
"itertools",
@@ -1900,7 +1869,7 @@ dependencies = [
[[package]]
name = "oxc_minifier"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"cow-utils",
"insta",
@@ -1958,7 +1927,7 @@ dependencies = [
[[package]]
name = "oxc_napi"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"napi",
"napi-build",
@@ -1966,12 +1935,13 @@ dependencies = [
"oxc_ast",
"oxc_ast_visit",
"oxc_diagnostics",
+ "oxc_span",
"oxc_syntax",
]
[[package]]
name = "oxc_parser"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"bitflags 2.9.0",
"cow-utils",
@@ -1994,7 +1964,7 @@ dependencies = [
[[package]]
name = "oxc_parser_napi"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"mimalloc-safe",
"napi",
@@ -2044,7 +2014,7 @@ dependencies = [
[[package]]
name = "oxc_regular_expression"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"oxc_allocator",
"oxc_ast_macros",
@@ -2057,9 +2027,9 @@ dependencies = [
[[package]]
name = "oxc_resolver"
-version = "8.0.0"
+version = "9.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe5c7d43ec2c0dcd506adb52f94cc2903e754f413cb548c4733b03c3103eb908"
+checksum = "fa108b1939b68ef316a674ac1d81a3f3a9012e5373d914b9e549ae69b6f2b729"
dependencies = [
"cfg-if",
"indexmap",
@@ -2076,7 +2046,7 @@ dependencies = [
[[package]]
name = "oxc_semantic"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"insta",
"itertools",
@@ -2099,9 +2069,9 @@ dependencies = [
[[package]]
name = "oxc_sourcemap"
-version = "3.0.0"
+version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6665c417b2aa1c426a7b142bcc0d2f47d9fee9e6f88610f054cfa7ce6623001e"
+checksum = "9cd7bb37974a2684a080d05b9c28460e1610c5ac5ef13f481a45179f458239cb"
dependencies = [
"base64-simd",
"cfg-if",
@@ -2117,7 +2087,7 @@ dependencies = [
[[package]]
name = "oxc_span"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"compact_str",
"oxc-miette",
@@ -2130,7 +2100,7 @@ dependencies = [
[[package]]
name = "oxc_syntax"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"bitflags 2.9.0",
"cow-utils",
@@ -2189,7 +2159,7 @@ dependencies = [
[[package]]
name = "oxc_transform_napi"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"mimalloc-safe",
"napi",
@@ -2203,7 +2173,7 @@ dependencies = [
[[package]]
name = "oxc_transformer"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"base64",
"compact_str",
@@ -2211,6 +2181,7 @@ dependencies = [
"indexmap",
"insta",
"itoa",
+ "memchr",
"oxc-browserslist",
"oxc_allocator",
"oxc_ast",
@@ -2234,7 +2205,7 @@ dependencies = [
[[package]]
name = "oxc_transformer_plugins"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"cow-utils",
"insta",
@@ -2260,7 +2231,7 @@ dependencies = [
[[package]]
name = "oxc_traverse"
-version = "0.68.1"
+version = "0.70.0"
dependencies = [
"itoa",
"oxc_allocator",
@@ -2276,7 +2247,7 @@ dependencies = [
[[package]]
name = "oxlint"
-version = "0.16.10"
+version = "0.16.11"
dependencies = [
"bpaf",
"cow-utils",
@@ -2316,7 +2287,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -2392,6 +2363,16 @@ dependencies = [
"phf_shared",
]
+[[package]]
+name = "phf_codegen"
+version = "0.11.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
+dependencies = [
+ "phf_generator",
+ "phf_shared",
+]
+
[[package]]
name = "phf_generator"
version = "0.11.3"
@@ -2457,6 +2438,15 @@ dependencies = [
"portable-atomic",
]
+[[package]]
+name = "potential_utf"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
+dependencies = [
+ "zerovec",
+]
+
[[package]]
name = "powerfmt"
version = "0.2.0"
@@ -2653,9 +2643,9 @@ dependencies = [
[[package]]
name = "rustls"
-version = "0.23.26"
+version = "0.23.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0"
+checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321"
dependencies = [
"log",
"once_cell",
@@ -2677,15 +2667,18 @@ dependencies = [
[[package]]
name = "rustls-pki-types"
-version = "1.11.0"
+version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
+checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
+dependencies = [
+ "zeroize",
+]
[[package]]
name = "rustls-webpki"
-version = "0.103.1"
+version = "0.103.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03"
+checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435"
dependencies = [
"ring",
"rustls-pki-types",
@@ -3015,12 +3008,12 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.19.1"
+version = "3.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf"
+checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
dependencies = [
"fastrand",
- "getrandom 0.3.2",
+ "getrandom 0.3.3",
"once_cell",
"rustix",
"windows-sys 0.59.0",
@@ -3100,9 +3093,9 @@ dependencies = [
[[package]]
name = "tinystr"
-version = "0.7.6"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
+checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
dependencies = [
"displaydoc",
"zerovec",
@@ -3110,9 +3103,9 @@ dependencies = [
[[package]]
name = "tokio"
-version = "1.44.2"
+version = "1.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6b88822cbe49de4185e3a4cbf8321dd487cf5fe0c5c65695fef6346371e9c48"
+checksum = "2513ca694ef9ede0fb23fe71a4ee4107cb102b9dc1930f6d0fd77aae068ae165"
dependencies = [
"backtrace",
"pin-project-lite",
@@ -3317,7 +3310,7 @@ dependencies = [
"serde_json",
"ureq-proto",
"utf-8",
- "webpki-roots",
+ "webpki-roots 0.26.11",
]
[[package]]
@@ -3349,12 +3342,6 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
-[[package]]
-name = "utf16_iter"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246"
-
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -3367,7 +3354,7 @@ version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9"
dependencies = [
- "getrandom 0.3.2",
+ "getrandom 0.3.3",
]
[[package]]
@@ -3415,9 +3402,18 @@ dependencies = [
[[package]]
name = "webpki-roots"
-version = "0.26.10"
+version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37493cadf42a2a939ed404698ded7fb378bf301b5011f973361779a3a74f8c93"
+checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
+dependencies = [
+ "webpki-roots 1.0.0",
+]
+
+[[package]]
+name = "webpki-roots"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb"
dependencies = [
"rustls-pki-types",
]
@@ -3480,7 +3476,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -3489,7 +3485,7 @@ version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
dependencies = [
- "windows-targets",
+ "windows-targets 0.52.6",
]
[[package]]
@@ -3498,14 +3494,30 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.52.6",
+ "windows_aarch64_msvc 0.52.6",
+ "windows_i686_gnu 0.52.6",
+ "windows_i686_gnullvm 0.52.6",
+ "windows_i686_msvc 0.52.6",
+ "windows_x86_64_gnu 0.52.6",
+ "windows_x86_64_gnullvm 0.52.6",
+ "windows_x86_64_msvc 0.52.6",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.53.0",
+ "windows_aarch64_msvc 0.53.0",
+ "windows_i686_gnu 0.53.0",
+ "windows_i686_gnullvm 0.53.0",
+ "windows_i686_msvc 0.53.0",
+ "windows_x86_64_gnu 0.53.0",
+ "windows_x86_64_gnullvm 0.53.0",
+ "windows_x86_64_msvc 0.53.0",
]
[[package]]
@@ -3514,48 +3526,96 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
+
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
+
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
+[[package]]
+name = "windows_i686_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
+
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+[[package]]
+name = "windows_i686_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
+
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+[[package]]
+name = "windows_i686_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
+
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
+
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
+
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.53.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
+
[[package]]
name = "wit-bindgen-rt"
version = "0.39.0"
@@ -3565,23 +3625,17 @@ dependencies = [
"bitflags 2.9.0",
]
-[[package]]
-name = "write16"
-version = "1.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936"
-
[[package]]
name = "writeable"
-version = "0.5.5"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
+checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
[[package]]
name = "yoke"
-version = "0.7.5"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
+checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
dependencies = [
"serde",
"stable_deref_trait",
@@ -3591,9 +3645,9 @@ dependencies = [
[[package]]
name = "yoke-derive"
-version = "0.7.5"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
+checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
dependencies = [
"proc-macro2",
"quote",
@@ -3628,11 +3682,22 @@ version = "1.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+[[package]]
+name = "zerotrie"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
+dependencies = [
+ "displaydoc",
+ "yoke",
+ "zerofrom",
+]
+
[[package]]
name = "zerovec"
-version = "0.10.4"
+version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
+checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
dependencies = [
"yoke",
"zerofrom",
@@ -3641,9 +3706,9 @@ dependencies = [
[[package]]
name = "zerovec-derive"
-version = "0.10.3"
+version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
+checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
dependencies = [
"proc-macro2",
"quote",
diff --git a/Cargo.toml b/Cargo.toml
index 8a43c7ad5ca90..1306a2851b596 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -104,31 +104,31 @@ doc_lazy_continuation = "allow" # FIXME
[workspace.dependencies]
# publish = true
-oxc = { version = "0.68.1", path = "crates/oxc" }
-oxc_allocator = { version = "0.68.1", path = "crates/oxc_allocator" }
-oxc_ast = { version = "0.68.1", path = "crates/oxc_ast" }
-oxc_ast_macros = { version = "0.68.1", path = "crates/oxc_ast_macros" }
-oxc_ast_visit = { version = "0.68.1", path = "crates/oxc_ast_visit" }
-oxc_cfg = { version = "0.68.1", path = "crates/oxc_cfg" }
-oxc_codegen = { version = "0.68.1", path = "crates/oxc_codegen" }
-oxc_data_structures = { version = "0.68.1", path = "crates/oxc_data_structures" }
-oxc_diagnostics = { version = "0.68.1", path = "crates/oxc_diagnostics" }
-oxc_ecmascript = { version = "0.68.1", path = "crates/oxc_ecmascript" }
-oxc_estree = { version = "0.68.1", path = "crates/oxc_estree" }
-oxc_isolated_declarations = { version = "0.68.1", path = "crates/oxc_isolated_declarations" }
-oxc_mangler = { version = "0.68.1", path = "crates/oxc_mangler" }
-oxc_minifier = { version = "0.68.1", path = "crates/oxc_minifier" }
-oxc_napi = { version = "0.68.1", path = "crates/oxc_napi" }
-oxc_parser = { version = "0.68.1", path = "crates/oxc_parser", features = ["regular_expression"] }
-oxc_parser_napi = { version = "0.68.1", path = "napi/parser" }
-oxc_regular_expression = { version = "0.68.1", path = "crates/oxc_regular_expression" }
-oxc_semantic = { version = "0.68.1", path = "crates/oxc_semantic" }
-oxc_span = { version = "0.68.1", path = "crates/oxc_span" }
-oxc_syntax = { version = "0.68.1", path = "crates/oxc_syntax" }
-oxc_transform_napi = { version = "0.68.1", path = "napi/transform" }
-oxc_transformer = { version = "0.68.1", path = "crates/oxc_transformer" }
-oxc_transformer_plugins = { version = "0.68.1", path = "crates/oxc_transformer_plugins" }
-oxc_traverse = { version = "0.68.1", path = "crates/oxc_traverse" }
+oxc = { version = "0.70.0", path = "crates/oxc" }
+oxc_allocator = { version = "0.70.0", path = "crates/oxc_allocator" }
+oxc_ast = { version = "0.70.0", path = "crates/oxc_ast" }
+oxc_ast_macros = { version = "0.70.0", path = "crates/oxc_ast_macros" }
+oxc_ast_visit = { version = "0.70.0", path = "crates/oxc_ast_visit" }
+oxc_cfg = { version = "0.70.0", path = "crates/oxc_cfg" }
+oxc_codegen = { version = "0.70.0", path = "crates/oxc_codegen" }
+oxc_data_structures = { version = "0.70.0", path = "crates/oxc_data_structures" }
+oxc_diagnostics = { version = "0.70.0", path = "crates/oxc_diagnostics" }
+oxc_ecmascript = { version = "0.70.0", path = "crates/oxc_ecmascript" }
+oxc_estree = { version = "0.70.0", path = "crates/oxc_estree" }
+oxc_isolated_declarations = { version = "0.70.0", path = "crates/oxc_isolated_declarations" }
+oxc_mangler = { version = "0.70.0", path = "crates/oxc_mangler" }
+oxc_minifier = { version = "0.70.0", path = "crates/oxc_minifier" }
+oxc_napi = { version = "0.70.0", path = "crates/oxc_napi" }
+oxc_parser = { version = "0.70.0", path = "crates/oxc_parser", features = ["regular_expression"] }
+oxc_parser_napi = { version = "0.70.0", path = "napi/parser" }
+oxc_regular_expression = { version = "0.70.0", path = "crates/oxc_regular_expression" }
+oxc_semantic = { version = "0.70.0", path = "crates/oxc_semantic" }
+oxc_span = { version = "0.70.0", path = "crates/oxc_span" }
+oxc_syntax = { version = "0.70.0", path = "crates/oxc_syntax" }
+oxc_transform_napi = { version = "0.70.0", path = "napi/transform" }
+oxc_transformer = { version = "0.70.0", path = "crates/oxc_transformer" }
+oxc_transformer_plugins = { version = "0.70.0", path = "crates/oxc_transformer_plugins" }
+oxc_traverse = { version = "0.70.0", path = "crates/oxc_traverse" }
# publish = false
oxc_formatter = { path = "crates/oxc_formatter" }
@@ -155,11 +155,11 @@ unicode-id-start = "1"
#
oxc-browserslist = "2"
oxc_index = "3"
-oxc_resolver = "8"
+oxc_resolver = "9"
oxc_sourcemap = "3"
#
-allocator-api2 = "0.2.21"
+allocator-api2 = "=0.2.21"
base64 = "0.22.1"
bitflags = "2.9.0"
bpaf = "0.9.19"
@@ -183,28 +183,29 @@ flate2 = "1.1.1"
futures = "0.3.31"
globset = "0.4.16"
handlebars = "6.3.2"
-hashbrown = { version = "0.15.2", default-features = false }
+hashbrown = { version = "0.15.3", default-features = false }
humansize = "2.1.3"
ignore = "0.4.23"
-insta = "1.42.2"
+insta = "1.43.1"
itertools = "0.14.0"
itoa = "1.0.15"
-javascript-globals = "1.0.0"
+javascript-globals = "1.1.0"
json-strip-comments = "1.0.4"
language-tags = "0.3.2"
lazy-regex = "3.4.1"
lazy_static = "1.5.0"
log = "0.4.27"
-markdown = "1.0.0-alpha.23"
+markdown = "1.0.0"
memchr = "2.7.4"
miette = { package = "oxc-miette", version = "2.2.1", features = ["fancy-no-syscall"] }
-mimalloc-safe = "0.1.50"
+mimalloc-safe = "0.1.52"
nonmax = "0.5.5"
num-bigint = "0.4.6"
num-traits = "0.2.19"
papaya = "0.2.1"
-petgraph = { version = "0.8.0", default-features = false }
+petgraph = { version = "0.8.1", default-features = false }
phf = "0.11.3"
+phf_codegen = "0.11.3"
pico-args = "0.5.0"
prettyplease = "0.2.32"
project-root = "0.2.2"
@@ -214,18 +215,18 @@ rust-lapper = "1.1.0"
ryu-js = "1.0.2"
saphyr = "0.0.4"
schemars = "0.8.22"
-self_cell = "1.1.0"
+self_cell = "1.2.0"
seq-macro = "0.3.6"
sha1 = "0.10.6"
simdutf8 = { version = "0.1.5", features = ["aarch64_neon"] }
similar = "2.7.0"
similar-asserts = "1.7.0"
smallvec = "1.15.0"
-tempfile = "3.19.1"
-tokio = { version = "1.44.2", default-features = false }
+tempfile = "3.20.0"
+tokio = { version = "1.45.0", default-features = false }
tower-lsp-server = "0.21.1"
tracing-subscriber = "0.3.19"
-ureq = { version = "3.0.10", default-features = false }
+ureq = { version = "3.0.11", default-features = false }
walkdir = "2.5.0"
[workspace.metadata.cargo-shear]
diff --git a/apps/oxlint/CHANGELOG.md b/apps/oxlint/CHANGELOG.md
index 788358aefe5fd..a128c3cf52038 100644
--- a/apps/oxlint/CHANGELOG.md
+++ b/apps/oxlint/CHANGELOG.md
@@ -4,6 +4,25 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0.
+## [0.16.11] - 2025-05-16
+
+- 4e5c73b span: [**BREAKING**] `SourceType::from_path(".js")` return js instead of jsx (#11038) (Boshen)
+
+### Features
+
+- 466c24a linter: Add gitlab reporter output format (#10927) (Connor Pearson)
+
+### Bug Fixes
+
+- c52a9ba linter: Fix plugins inside overrides not being applied (#11057) (camc314)
+- b12bd48 linter: Fix rule config not being correctly applied (#11055) (camc314)
+- 0961296 linter: Add `gitlab` to linter `--help` docs (#10932) (camc314)
+- 584d8b9 napi: Enable mimalloc `no_opt_arch` feature on linux aarch64 (#11053) (Boshen)
+
+### Refactor
+
+- bb999a3 language_server: Avoid cloning linter by taking reference in LintService (#10907) (Ulrich Stark)
+
## [0.16.10] - 2025-05-09
### Features
diff --git a/apps/oxlint/Cargo.toml b/apps/oxlint/Cargo.toml
index 91f2a2db9d13e..4870e61bb6c0e 100644
--- a/apps/oxlint/Cargo.toml
+++ b/apps/oxlint/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "oxlint"
-version = "0.16.10"
+version = "0.16.11"
authors.workspace = true
categories.workspace = true
edition.workspace = true
@@ -40,12 +40,15 @@ serde_json = { workspace = true }
tempfile = { workspace = true }
tracing-subscriber = { workspace = true, features = [] } # Omit the `regex` feature
-[target.'cfg(all(not(target_os = "linux"), not(target_os = "freebsd"), not(target_family = "wasm")))'.dependencies]
+[target.'cfg(not(any(target_os = "linux", target_os = "freebsd", target_arch = "arm", target_family = "wasm")))'.dependencies]
mimalloc-safe = { workspace = true, optional = true, features = ["skip_collect_on_exit"] }
-[target.'cfg(any(target_os = "linux", target_os = "freebsd"))'.dependencies]
+[target.'cfg(all(target_os = "linux", not(target_arch = "arm"), not(target_arch = "aarch64")))'.dependencies]
mimalloc-safe = { workspace = true, optional = true, features = ["skip_collect_on_exit", "local_dynamic_tls"] }
+[target.'cfg(all(target_os = "linux", target_arch = "aarch64"))'.dependencies]
+mimalloc-safe = { workspace = true, optional = true, features = ["skip_collect_on_exit", "local_dynamic_tls", "no_opt_arch"] }
+
[dev-dependencies]
insta = { workspace = true }
lazy-regex = { workspace = true }
diff --git a/apps/oxlint/fixtures/issue_11054/.oxlintrc.json b/apps/oxlint/fixtures/issue_11054/.oxlintrc.json
new file mode 100644
index 0000000000000..933355aaa4b99
--- /dev/null
+++ b/apps/oxlint/fixtures/issue_11054/.oxlintrc.json
@@ -0,0 +1,12 @@
+{
+ "rules": {
+ "no-unused-vars": [
+ 2,
+ {
+ "args": "none",
+ "caughtErrors": "none",
+ "varsIgnorePattern": "^h|React|createElement|Fragment$"
+ }
+ ]
+ }
+}
diff --git a/apps/oxlint/fixtures/issue_11054/index.js b/apps/oxlint/fixtures/issue_11054/index.js
new file mode 100644
index 0000000000000..24624c8ef0d1d
--- /dev/null
+++ b/apps/oxlint/fixtures/issue_11054/index.js
@@ -0,0 +1 @@
+import { createElement } from "preact";
diff --git a/apps/oxlint/fixtures/linter/js_as_jsx.js b/apps/oxlint/fixtures/linter/js_as_jsx.js
new file mode 100644
index 0000000000000..e130e46d3f36f
--- /dev/null
+++ b/apps/oxlint/fixtures/linter/js_as_jsx.js
@@ -0,0 +1,2 @@
+debugger;
+
// Should `.js` file pass as `.jsx`.
diff --git a/apps/oxlint/fixtures/overrides_with_plugin/.oxlintrc.json b/apps/oxlint/fixtures/overrides_with_plugin/.oxlintrc.json
new file mode 100644
index 0000000000000..febf7a7f2bbe2
--- /dev/null
+++ b/apps/oxlint/fixtures/overrides_with_plugin/.oxlintrc.json
@@ -0,0 +1,13 @@
+{
+ "overrides": [
+ {
+ "files": ["*.test.ts"],
+ "plugins": ["jest", "vitest"],
+ "rules": {
+ "jest/valid-title": "deny",
+ "no-unused-vars": "off"
+ }
+ }
+ ]
+ }
+
\ No newline at end of file
diff --git a/apps/oxlint/fixtures/overrides_with_plugin/index.test.ts b/apps/oxlint/fixtures/overrides_with_plugin/index.test.ts
new file mode 100644
index 0000000000000..b8a63407093bd
--- /dev/null
+++ b/apps/oxlint/fixtures/overrides_with_plugin/index.test.ts
@@ -0,0 +1,7 @@
+describe("", () => {
+ //
+
+ it("", () => {});
+});
+
+const foo = 123;
diff --git a/apps/oxlint/fixtures/overrides_with_plugin/index.ts b/apps/oxlint/fixtures/overrides_with_plugin/index.ts
new file mode 100644
index 0000000000000..472e4584238a4
--- /dev/null
+++ b/apps/oxlint/fixtures/overrides_with_plugin/index.ts
@@ -0,0 +1 @@
+const foo = 123;
diff --git a/apps/oxlint/src/command/lint.rs b/apps/oxlint/src/command/lint.rs
index fcb9c285fc3c2..180f051a851be 100644
--- a/apps/oxlint/src/command/lint.rs
+++ b/apps/oxlint/src/command/lint.rs
@@ -194,7 +194,7 @@ pub struct WarningOptions {
#[derive(Debug, Clone, Bpaf)]
pub struct OutputOptions {
/// Use a specific output format. Possible values:
- /// `checkstyle`, `default`, `github`, `json`, `junit`, `stylish`, `unix`
+ /// `checkstyle`, `default`, `github`, `gitlab`, `json`, `junit`, `stylish`, `unix`
#[bpaf(long, short, fallback(OutputFormat::Default), hide_usage)]
pub format: OutputFormat,
}
diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs
index 3fea36e452f3e..827b55bfd9709 100644
--- a/apps/oxlint/src/lint.rs
+++ b/apps/oxlint/src/lint.rs
@@ -293,18 +293,16 @@ impl Runner for LintRunner {
}
}
- let mut lint_service = LintService::new(linter, options);
let mut diagnostic_service =
Self::get_diagnostic_service(&output_formatter, &warning_options, &misc_options);
+ let tx_error = diagnostic_service.sender().clone();
- let number_of_rules = lint_service.linter().number_of_rules();
+ let number_of_rules = linter.number_of_rules();
// Spawn linting in another thread so diagnostics can be printed immediately from diagnostic_service.run.
- rayon::spawn({
- let tx_error = diagnostic_service.sender().clone();
- move || {
- lint_service.run(&tx_error);
- }
+ rayon::spawn(move || {
+ let mut lint_service = LintService::new(&linter, options);
+ lint_service.run(&tx_error);
});
let diagnostic_result = diagnostic_service.run(stdout);
@@ -780,6 +778,12 @@ mod test {
Tester::new().test_and_snapshot(args);
}
+ #[test]
+ fn js_and_jsx() {
+ let args = &["fixtures/linter/js_as_jsx.js"];
+ Tester::new().test_and_snapshot(args);
+ }
+
#[test]
fn lint_vue_file() {
let args = &["fixtures/vue/debugger.vue"];
@@ -1155,4 +1159,16 @@ mod test {
let args = &["--import-plugin", "-D", "import/no-cycle"];
Tester::new().with_cwd("fixtures/import-cycle".into()).test_and_snapshot(args);
}
+
+ #[test]
+ fn test_rule_config_being_enabled_correctly() {
+ let args = &["-c", ".oxlintrc.json"];
+ Tester::new().with_cwd("fixtures/issue_11054".into()).test_and_snapshot(args);
+ }
+
+ #[test]
+ fn test_plugins_in_overrides_enabled_correctly() {
+ let args = &["-c", ".oxlintrc.json"];
+ Tester::new().with_cwd("fixtures/overrides_with_plugin".into()).test_and_snapshot(args);
+ }
}
diff --git a/apps/oxlint/src/output_formatter/gitlab.rs b/apps/oxlint/src/output_formatter/gitlab.rs
new file mode 100644
index 0000000000000..aba91dc3783a2
--- /dev/null
+++ b/apps/oxlint/src/output_formatter/gitlab.rs
@@ -0,0 +1,129 @@
+use oxc_diagnostics::{
+ Error, Severity,
+ reporter::{DiagnosticReporter, DiagnosticResult, Info},
+};
+
+use std::hash::{DefaultHasher, Hash, Hasher};
+
+use crate::output_formatter::InternalFormatter;
+
+#[derive(Debug, Default)]
+pub struct GitlabOutputFormatter;
+
+#[derive(Debug, serde::Serialize)]
+struct GitlabErrorLocationLinesJson {
+ begin: usize,
+ end: usize,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct GitlabErrorLocationJson {
+ path: String,
+ lines: GitlabErrorLocationLinesJson,
+}
+
+#[derive(Debug, serde::Serialize)]
+struct GitlabErrorJson {
+ description: String,
+ check_name: String,
+ fingerprint: String,
+ severity: String,
+ location: GitlabErrorLocationJson,
+}
+
+impl InternalFormatter for GitlabOutputFormatter {
+ fn get_diagnostic_reporter(&self) -> Box {
+ Box::new(GitlabReporter::default())
+ }
+}
+
+/// Renders reports as a Gitlab Code Quality Report
+///
+///
+///
+/// Note that, due to syntactic restrictions of JSON arrays, this reporter waits until all
+/// diagnostics have been reported before writing them to the output stream.
+#[derive(Default)]
+struct GitlabReporter {
+ diagnostics: Vec,
+}
+
+impl DiagnosticReporter for GitlabReporter {
+ fn finish(&mut self, _: &DiagnosticResult) -> Option {
+ Some(format_gitlab(&mut self.diagnostics))
+ }
+
+ fn render_error(&mut self, error: Error) -> Option {
+ self.diagnostics.push(error);
+ None
+ }
+}
+
+fn format_gitlab(diagnostics: &mut Vec) -> String {
+ let errors = diagnostics.drain(..).map(|error| {
+ let Info { start, end, filename, message, severity, rule_id } = Info::new(&error);
+ let severity = match severity {
+ Severity::Error => "critical".to_string(),
+ Severity::Warning => "major".to_string(),
+ Severity::Advice => "minor".to_string(),
+ };
+
+ let fingerprint = {
+ let mut hasher = DefaultHasher::new();
+ start.line.hash(&mut hasher);
+ end.line.hash(&mut hasher);
+ filename.hash(&mut hasher);
+ message.hash(&mut hasher);
+ severity.hash(&mut hasher);
+
+ format!("{:x}", hasher.finish())
+ };
+
+ GitlabErrorJson {
+ description: message,
+ check_name: rule_id.unwrap_or_default(),
+ location: GitlabErrorLocationJson {
+ path: filename,
+ lines: GitlabErrorLocationLinesJson { begin: start.line, end: end.line },
+ },
+ fingerprint,
+ severity,
+ }
+ });
+
+ serde_json::to_string_pretty(&errors.collect::>()).expect("Failed to serialize")
+}
+
+#[cfg(test)]
+mod test {
+ use oxc_diagnostics::{
+ NamedSource, OxcDiagnostic,
+ reporter::{DiagnosticReporter, DiagnosticResult},
+ };
+ use oxc_span::Span;
+
+ use super::GitlabReporter;
+
+ #[test]
+ fn reporter() {
+ let mut reporter = GitlabReporter::default();
+
+ let error = OxcDiagnostic::warn("error message")
+ .with_label(Span::new(0, 8))
+ .with_source_code(NamedSource::new("file://test.ts", "debugger;"));
+
+ let first_result = reporter.render_error(error);
+
+ // reporter keeps it in memory
+ assert!(first_result.is_none());
+
+ // reporter gives results when finishing
+ let second_result = reporter.finish(&DiagnosticResult::default());
+
+ assert!(second_result.is_some());
+ assert_eq!(
+ second_result.unwrap(),
+ "[\n {\n \"description\": \"error message\",\n \"check_name\": \"\",\n \"fingerprint\": \"8b23bd85b148d3\",\n \"severity\": \"major\",\n \"location\": {\n \"path\": \"file://test.ts\",\n \"lines\": {\n \"begin\": 1,\n \"end\": 1\n }\n }\n }\n]"
+ );
+ }
+}
diff --git a/apps/oxlint/src/output_formatter/mod.rs b/apps/oxlint/src/output_formatter/mod.rs
index a502f45efac6a..39a922fae62ea 100644
--- a/apps/oxlint/src/output_formatter/mod.rs
+++ b/apps/oxlint/src/output_formatter/mod.rs
@@ -1,6 +1,7 @@
mod checkstyle;
mod default;
mod github;
+mod gitlab;
mod json;
mod junit;
mod stylish;
@@ -12,6 +13,7 @@ use std::time::Duration;
use checkstyle::CheckStyleOutputFormatter;
use github::GithubOutputFormatter;
+use gitlab::GitlabOutputFormatter;
use junit::JUnitOutputFormatter;
use stylish::StylishOutputFormatter;
use unix::UnixOutputFormatter;
@@ -26,6 +28,7 @@ pub enum OutputFormat {
/// GitHub Check Annotation
///
Github,
+ Gitlab,
Json,
Unix,
Checkstyle,
@@ -43,6 +46,7 @@ impl FromStr for OutputFormat {
"unix" => Ok(Self::Unix),
"checkstyle" => Ok(Self::Checkstyle),
"github" => Ok(Self::Github),
+ "gitlab" => Ok(Self::Gitlab),
"stylish" => Ok(Self::Stylish),
"junit" => Ok(Self::JUnit),
_ => Err(format!("'{s}' is not a known format")),
@@ -96,6 +100,7 @@ impl OutputFormatter {
OutputFormat::Json => Box::::default(),
OutputFormat::Checkstyle => Box::::default(),
OutputFormat::Github => Box::new(GithubOutputFormatter),
+ OutputFormat::Gitlab => Box::::default(),
OutputFormat::Unix => Box::::default(),
OutputFormat::Default => Box::new(DefaultOutputFormatter),
OutputFormat::Stylish => Box::::default(),
diff --git a/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap b/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap
index fe6cd3391cc4d..5b9d90b549c4c 100644
--- a/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap
+++ b/apps/oxlint/src/snapshots/_-A all fixtures__linter@oxlint.snap
@@ -6,7 +6,7 @@ arguments: -A all fixtures/linter
working directory:
----------
Found 0 warnings and 0 errors.
-Finished in ms on 3 files with 0 rules using 1 threads.
+Finished in ms on 4 files with 0 rules using 1 threads.
----------
CLI result: LintSucceeded
----------
diff --git a/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap b/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap
index ba8feb6dd0a38..45cae04933d7d 100644
--- a/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap
+++ b/apps/oxlint/src/snapshots/_fixtures__linter@oxlint.snap
@@ -20,6 +20,14 @@ working directory:
`----
help: Remove the debugger statement
+ ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\eslint(no-debugger)]8;;\: `debugger` statement is not allowed
+ ,-[fixtures/linter/js_as_jsx.js:1:1]
+ 1 | debugger;
+ : ^^^^^^^^^
+ 2 | // Should `.js` file pass as `.jsx`.
+ `----
+ help: Remove the debugger statement
+
! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/use-isnan.html\eslint(use-isnan)]8;;\: Requires calls to isNaN() when checking for NaN
,-[fixtures/linter/nan.js:1:8]
1 | 123 == NaN;
@@ -27,8 +35,8 @@ working directory:
`----
help: Use the isNaN function to compare with NaN.
-Found 3 warnings and 0 errors.
-Finished in ms on 3 files with 101 rules using 1 threads.
+Found 4 warnings and 0 errors.
+Finished in ms on 4 files with 101 rules using 1 threads.
----------
CLI result: LintSucceeded
----------
diff --git a/apps/oxlint/src/snapshots/_fixtures__linter__js_and_jsx.js@oxlint.snap b/apps/oxlint/src/snapshots/_fixtures__linter__js_and_jsx.js@oxlint.snap
new file mode 100644
index 0000000000000..dab8f41f46802
--- /dev/null
+++ b/apps/oxlint/src/snapshots/_fixtures__linter__js_and_jsx.js@oxlint.snap
@@ -0,0 +1,12 @@
+---
+source: apps/oxlint/src/tester.rs
+---
+##########
+arguments: fixtures/linter/js_and_jsx.js
+working directory:
+----------
+Found 0 warnings and 0 errors.
+Finished in ms on 0 files with 101 rules using 1 threads.
+----------
+CLI result: LintSucceeded
+----------
diff --git a/apps/oxlint/src/snapshots/_fixtures__linter__js_as_jsx.js@oxlint.snap b/apps/oxlint/src/snapshots/_fixtures__linter__js_as_jsx.js@oxlint.snap
new file mode 100644
index 0000000000000..185506f6ae6da
--- /dev/null
+++ b/apps/oxlint/src/snapshots/_fixtures__linter__js_as_jsx.js@oxlint.snap
@@ -0,0 +1,21 @@
+---
+source: apps/oxlint/src/tester.rs
+---
+##########
+arguments: fixtures/linter/js_as_jsx.js
+working directory:
+----------
+
+ ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-debugger.html\eslint(no-debugger)]8;;\: `debugger` statement is not allowed
+ ,-[fixtures/linter/js_as_jsx.js:1:1]
+ 1 | debugger;
+ : ^^^^^^^^^
+ 2 | // Should `.js` file pass as `.jsx`.
+ `----
+ help: Remove the debugger statement
+
+Found 1 warning and 0 errors.
+Finished in ms on 1 file with 101 rules using 1 threads.
+----------
+CLI result: LintSucceeded
+----------
diff --git a/apps/oxlint/src/snapshots/fixtures__issue_11054_-c .oxlintrc.json@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__issue_11054_-c .oxlintrc.json@oxlint.snap
new file mode 100644
index 0000000000000..3621a4b8c0e1f
--- /dev/null
+++ b/apps/oxlint/src/snapshots/fixtures__issue_11054_-c .oxlintrc.json@oxlint.snap
@@ -0,0 +1,12 @@
+---
+source: apps/oxlint/src/tester.rs
+---
+##########
+arguments: -c .oxlintrc.json
+working directory: fixtures/issue_11054
+----------
+Found 0 warnings and 0 errors.
+Finished in ms on 1 file with 101 rules using 1 threads.
+----------
+CLI result: LintSucceeded
+----------
diff --git a/apps/oxlint/src/snapshots/fixtures__overrides_with_plugin_-c .oxlintrc.json@oxlint.snap b/apps/oxlint/src/snapshots/fixtures__overrides_with_plugin_-c .oxlintrc.json@oxlint.snap
new file mode 100644
index 0000000000000..fb6df87b9015f
--- /dev/null
+++ b/apps/oxlint/src/snapshots/fixtures__overrides_with_plugin_-c .oxlintrc.json@oxlint.snap
@@ -0,0 +1,38 @@
+---
+source: apps/oxlint/src/tester.rs
+---
+##########
+arguments: -c .oxlintrc.json
+working directory: fixtures/overrides_with_plugin
+----------
+
+ x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/jest/valid-title.html\eslint-plugin-jest(valid-title)]8;;\: "Should not have an empty title"
+ ,-[index.test.ts:1:10]
+ 1 | describe("", () => {
+ : ^^
+ 2 | //
+ `----
+ help: "Write a meaningful title for your test"
+
+ ! ]8;;https://oxc.rs/docs/guide/usage/linter/rules/eslint/no-unused-vars.html\eslint(no-unused-vars)]8;;\: Variable 'foo' is declared but never used. Unused variables should start with a '_'.
+ ,-[index.ts:1:7]
+ 1 | const foo = 123;
+ : ^|^
+ : `-- 'foo' is declared here
+ `----
+ help: Consider removing this declaration.
+
+ x ]8;;https://oxc.rs/docs/guide/usage/linter/rules/jest/valid-title.html\eslint-plugin-jest(valid-title)]8;;\: "Should not have an empty title"
+ ,-[index.test.ts:4:6]
+ 3 |
+ 4 | it("", () => {});
+ : ^^
+ 5 | });
+ `----
+ help: "Write a meaningful title for your test"
+
+Found 1 warning and 2 errors.
+Finished in ms on 2 files with 101 rules using 1 threads.
+----------
+CLI result: LintFoundErrors
+----------
diff --git a/crates/oxc/CHANGELOG.md b/crates/oxc/CHANGELOG.md
index 74b77299cb505..1f228a7d00089 100644
--- a/crates/oxc/CHANGELOG.md
+++ b/crates/oxc/CHANGELOG.md
@@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0.
+## [0.70.0] - 2025-05-15
+
+### Testing
+
+- a05361e ast/estree: Check span offsets are converted in ascending order in ESTree conformance tests (#10887) (overlookmotel)
+
## [0.68.0] - 2025-05-03
- 315143a codegen: [**BREAKING**] Remove useless `CodeGenerator` type alias (#10702) (Boshen)
diff --git a/crates/oxc/Cargo.toml b/crates/oxc/Cargo.toml
index 18f2c30cb0d70..699a6c316adef 100644
--- a/crates/oxc/Cargo.toml
+++ b/crates/oxc/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "oxc"
-version = "0.68.1"
+version = "0.70.0"
authors.workspace = true
categories.workspace = true
edition.workspace = true
@@ -77,5 +77,8 @@ serialize = [
"oxc_syntax/serialize",
]
+# Only for conformance tests
+conformance = ["oxc_ast_visit/conformance"]
+
[package.metadata.docs.rs]
all-features = true
diff --git a/crates/oxc_allocator/CHANGELOG.md b/crates/oxc_allocator/CHANGELOG.md
index 2f9e7473bc4b7..57198a89dc74b 100644
--- a/crates/oxc_allocator/CHANGELOG.md
+++ b/crates/oxc_allocator/CHANGELOG.md
@@ -4,6 +4,16 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0.
+## [0.69.0] - 2025-05-09
+
+### Bug Fixes
+
+- 446d9b3 allocator: `Allocator::from_raw_parts` do not use const assertion for endianness test (#10888) (overlookmotel)
+
+### Refactor
+
+- b16331e ast/estree: Generalize concatenating fields with `Concat2` (#10848) (overlookmotel)
+
## [0.68.0] - 2025-05-03
### Features
diff --git a/crates/oxc_allocator/Cargo.toml b/crates/oxc_allocator/Cargo.toml
index b7ad7c65020fc..3da1d6daea3a7 100644
--- a/crates/oxc_allocator/Cargo.toml
+++ b/crates/oxc_allocator/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "oxc_allocator"
-version = "0.68.1"
+version = "0.70.0"
authors.workspace = true
categories.workspace = true
edition.workspace = true
diff --git a/crates/oxc_allocator/src/string.rs b/crates/oxc_allocator/src/string.rs
index 336b3ae62c1b9..e3c728cba8ebf 100644
--- a/crates/oxc_allocator/src/string.rs
+++ b/crates/oxc_allocator/src/string.rs
@@ -63,7 +63,6 @@ impl<'alloc> String<'alloc> {
/// If the given capacity is `0`, no allocation will occur, and this method
/// is identical to the [`new_in`] method.
///
- /// [`capacity`]: String::capacity
/// [`new_in`]: String::new_in
#[inline(always)]
pub fn with_capacity_in(capacity: usize, allocator: &'alloc Allocator) -> String<'alloc> {
diff --git a/crates/oxc_allocator/src/vec.rs b/crates/oxc_allocator/src/vec.rs
index 00d05057dd315..e2a47b3caffa5 100644
--- a/crates/oxc_allocator/src/vec.rs
+++ b/crates/oxc_allocator/src/vec.rs
@@ -78,7 +78,7 @@ impl<'alloc, T> Vec<'alloc, T> {
/// minimum *capacity* specified, the vector will have a zero *length*.
///
/// For `Vec` where `T` is a zero-sized type, there will be no allocation
- /// and the capacity will always be `usize::MAX`.
+ /// and the capacity will always be `u32::MAX`.
///
/// # Panics
///
diff --git a/crates/oxc_allocator/src/vec2/mod.rs b/crates/oxc_allocator/src/vec2/mod.rs
index 254c9291a549a..f8faedbe0fbef 100644
--- a/crates/oxc_allocator/src/vec2/mod.rs
+++ b/crates/oxc_allocator/src/vec2/mod.rs
@@ -94,7 +94,6 @@
clippy::semicolon_if_nothing_returned,
clippy::needless_pass_by_ref_mut,
clippy::needless_for_each,
- clippy::needless_lifetimes,
clippy::cloned_instead_of_copied,
clippy::checked_conversions,
clippy::legacy_numeric_constants,
@@ -541,9 +540,9 @@ macro_rules! vec {
/// [`insert`]: struct.Vec.html#method.insert
/// [`reserve`]: struct.Vec.html#method.reserve
/// [owned slice]: https://doc.rust-lang.org/std/boxed/struct.Box.html
+#[repr(transparent)]
pub struct Vec<'bump, T: 'bump> {
buf: RawVec<'bump, T>,
- len: usize,
}
////////////////////////////////////////////////////////////////////////////////
@@ -566,7 +565,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// ```
#[inline]
pub fn new_in(bump: &'bump Bump) -> Vec<'bump, T> {
- Vec { buf: RawVec::new_in(bump), len: 0 }
+ Vec { buf: RawVec::new_in(bump) }
}
/// Constructs a new, empty `Vec<'bump, T>` with the specified capacity.
@@ -603,7 +602,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// ```
#[inline]
pub fn with_capacity_in(capacity: usize, bump: &'bump Bump) -> Vec<'bump, T> {
- Vec { buf: RawVec::with_capacity_in(capacity, bump), len: 0 }
+ Vec { buf: RawVec::with_capacity_in(capacity, bump) }
}
/// Construct a new `Vec` from the given iterator's items.
@@ -687,7 +686,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
capacity: usize,
bump: &'bump Bump,
) -> Vec<'bump, T> {
- Vec { buf: RawVec::from_raw_parts_in(ptr, capacity, bump), len: length }
+ Vec { buf: RawVec::from_raw_parts_in(ptr, bump, capacity, length) }
}
/// Returns a shared reference to the allocator backing this `Vec`.
@@ -724,7 +723,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// ```
#[inline]
pub fn capacity(&self) -> usize {
- self.buf.cap()
+ self.buf.cap_usize()
}
/// Reserves capacity for at least `additional` more elements to be inserted
@@ -735,7 +734,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Panics
///
- /// Panics if the new capacity overflows `usize`.
+ /// Panics if the new capacity overflows `u32`.
///
/// # Examples
///
@@ -748,7 +747,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert!(vec.capacity() >= 11);
/// ```
pub fn reserve(&mut self, additional: usize) {
- self.buf.reserve(self.len, additional);
+ self.buf.reserve(self.buf.len, additional);
}
/// Reserves the minimum capacity for exactly `additional` more elements to
@@ -762,7 +761,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Panics
///
- /// Panics if the new capacity overflows `usize`.
+ /// Panics if the new capacity overflows `u32`.
///
/// # Examples
///
@@ -775,7 +774,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert!(vec.capacity() >= 11);
/// ```
pub fn reserve_exact(&mut self, additional: usize) {
- self.buf.reserve_exact(self.len, additional);
+ self.buf.reserve_exact(self.buf.len, additional);
}
/// Attempts to reserve capacity for at least `additional` more elements to be inserted
@@ -786,7 +785,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Panics
///
- /// Panics if the new capacity overflows `usize`.
+ /// Panics if the new capacity overflows `u32`.
///
/// # Examples
///
@@ -799,7 +798,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert!(vec.capacity() >= 11);
/// ```
pub fn try_reserve(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
- self.buf.try_reserve(self.len, additional)
+ self.buf.try_reserve(self.buf.len, additional)
}
/// Attempts to reserve the minimum capacity for exactly `additional` more elements to
@@ -813,7 +812,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Panics
///
- /// Panics if the new capacity overflows `usize`.
+ /// Panics if the new capacity overflows `u32`.
///
/// # Examples
///
@@ -826,7 +825,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert!(vec.capacity() >= 11);
/// ```
pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), CollectionAllocErr> {
- self.buf.try_reserve_exact(self.len, additional)
+ self.buf.try_reserve_exact(self.buf.len, additional)
}
/// Shrinks the capacity of the vector as much as possible.
@@ -848,8 +847,8 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert!(vec.capacity() >= 3);
/// ```
pub fn shrink_to_fit(&mut self) {
- if self.capacity() != self.len {
- self.buf.shrink_to_fit(self.len);
+ if self.buf.cap() != self.buf.len {
+ self.buf.shrink_to_fit(self.buf.len);
}
}
@@ -955,14 +954,14 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// [`clear`]: #method.clear
/// [`drain`]: #method.drain
pub fn truncate(&mut self, len: usize) {
- let current_len = self.len;
+ let current_len = self.buf.len_usize();
unsafe {
- let mut ptr = self.as_mut_ptr().add(self.len);
+ let mut ptr = self.as_mut_ptr().add(current_len);
// Set the final length at the end, keeping in mind that
// dropping an element might panic. Works around a missed
// optimization, as seen in the following issue:
// https://github.com/rust-lang/rust/issues/51802
- let mut local_len = SetLenOnDrop::new(&mut self.len);
+ let mut local_len = SetLenOnDrop::new(&mut self.buf.len);
// drop any extra elements
for _ in len..current_len {
@@ -1105,6 +1104,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Safety
///
+ /// - `new_len` must be less than or equal to `u32::MAX`.
/// - `new_len` must be less than or equal to [`capacity()`].
/// - The elements at `old_len..new_len` must be initialized.
///
@@ -1169,8 +1169,12 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert_eq!(b"aaaa", &*vec);
/// ```
#[inline]
+ #[expect(clippy::cast_possible_truncation)]
pub unsafe fn set_len(&mut self, new_len: usize) {
- self.len = new_len;
+ // `new_len as u32` is safe because caller must ensure that
+ // `new_len` is less than or equal to `u32::MAX`, otherwise
+ // it is UB.
+ self.buf.len = new_len as u32;
}
/// Removes an element from the vector and returns it.
@@ -1205,8 +1209,8 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
// bounds check on hole succeeds there must be a last element (which
// can be self[index] itself).
let hole: *mut T = &mut self[index];
- let last = ptr::read(self.get_unchecked(self.len - 1));
- self.len -= 1;
+ let last = ptr::read(self.get_unchecked(self.buf.len_usize() - 1));
+ self.buf.len -= 1;
ptr::replace(hole, last)
}
}
@@ -1232,11 +1236,11 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// assert_eq!(vec, [1, 4, 2, 3, 5]);
/// ```
pub fn insert(&mut self, index: usize, element: T) {
- let len = self.len();
+ let len = self.buf.len_usize();
assert!(index <= len);
// space for the new element
- if len == self.buf.cap() {
+ if self.buf.len == self.buf.cap() {
self.buf.grow_one();
}
@@ -1252,7 +1256,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
// element.
ptr::write(p, element);
}
- self.set_len(len + 1);
+ self.buf.len += 1;
}
}
@@ -1547,7 +1551,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Panics
///
- /// Panics if the number of elements in the vector overflows a `usize`.
+ /// Panics if the number of elements in the vector overflows a `u32`.
///
/// # Examples
///
@@ -1564,13 +1568,13 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
pub fn push(&mut self, value: T) {
// This will panic or abort if we would allocate > isize::MAX bytes
// or if the length increment would overflow for zero-sized types.
- if self.len == self.buf.cap() {
+ if self.buf.len == self.buf.cap() {
self.buf.grow_one();
}
unsafe {
- let end = self.buf.ptr().add(self.len);
+ let end = self.buf.ptr().add(self.buf.len_usize());
ptr::write(end, value);
- self.len += 1;
+ self.buf.len += 1;
}
}
@@ -1592,11 +1596,11 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// ```
#[inline]
pub fn pop(&mut self) -> Option {
- if self.len == 0 {
+ if self.buf.len == 0 {
None
} else {
unsafe {
- self.len -= 1;
+ self.buf.len -= 1;
Some(ptr::read(self.as_ptr().add(self.len())))
}
}
@@ -1606,7 +1610,8 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
///
/// # Panics
///
- /// Panics if the number of elements in the vector overflows a `usize`.
+ /// Panics if the number of elements in the vector overflows a `u32`.
+ /// Panics if the length of `Self` and `other` add up to more than `u32::MAX`.
///
/// # Examples
///
@@ -1630,13 +1635,24 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
}
/// Appends elements to `Self` from other buffer.
+ ///
+ /// # SAFETY
+ ///
+ /// The caller must ensure that the length of buffer passed in is less than or
+ /// equal to `u32::MAX`.
+ /// The length of the `Self` and `other` buffer add up to must be less than or
+ /// equal to `u32::MAX`.
#[inline]
+ #[expect(clippy::cast_possible_truncation)]
unsafe fn append_elements(&mut self, other: *const [T]) {
let count = (*other).len();
self.reserve(count);
let len = self.len();
ptr::copy_nonoverlapping(other as *const T, self.as_mut_ptr().add(len), count);
- self.len += count;
+ // `unwrap_unchecked()` is okay because that caller needs to ensure that
+ // the length of the buffer passed in is less than or equal to `u32::MAX`,
+ // otherwise it is UB.
+ self.buf.len = self.buf.len.checked_add(count as u32).unwrap_unchecked()
}
/// Creates a draining iterator that removes the specified range in the vector
@@ -1753,7 +1769,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// ```
#[inline]
pub fn len(&self) -> usize {
- self.len
+ self.buf.len_usize()
}
/// Returns `true` if the vector contains no elements.
@@ -1802,7 +1818,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
pub fn split_off(&mut self, at: usize) -> Self {
assert!(at <= self.len(), "`at` out of bounds");
- let other_len = self.len - at;
+ let other_len = self.buf.len_usize() - at;
let mut other = Vec::with_capacity_in(other_len, self.buf.bump());
// Unsafely `set_len` and copy items to `other`.
@@ -2069,7 +2085,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
// Use SetLenOnDrop to work around bug where compiler
// may not realize the store through `ptr` through self.set_len()
// don't alias.
- let mut local_len = SetLenOnDrop::new(&mut self.len);
+ let mut local_len = SetLenOnDrop::new(&mut self.buf.len);
// Write all elements except the last one
for _ in 1..n {
@@ -2096,28 +2112,28 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
// that the optimizer will see does not alias with any stores through the Vec's data
// pointer. This is a workaround for alias analysis issue #32155
struct SetLenOnDrop<'a> {
- len: &'a mut usize,
- local_len: usize,
+ len: &'a mut u32,
+ local_len: u32,
}
impl<'a> SetLenOnDrop<'a> {
#[inline]
- fn new(len: &'a mut usize) -> Self {
+ fn new(len: &'a mut u32) -> Self {
SetLenOnDrop { local_len: *len, len }
}
#[inline]
- fn increment_len(&mut self, increment: usize) {
+ fn increment_len(&mut self, increment: u32) {
self.local_len += increment;
}
#[inline]
- fn decrement_len(&mut self, decrement: usize) {
+ fn decrement_len(&mut self, decrement: u32) {
self.local_len -= decrement;
}
}
-impl<'a> Drop for SetLenOnDrop<'a> {
+impl Drop for SetLenOnDrop<'_> {
#[inline]
fn drop(&mut self) {
*self.len = self.local_len;
@@ -2180,7 +2196,7 @@ impl<'bump, T: 'bump + Hash> Hash for Vec<'bump, T> {
}
}
-impl<'bump, T, I> Index for Vec<'bump, T>
+impl Index for Vec<'_, T>
where
I: ::core::slice::SliceIndex<[T]>,
{
@@ -2192,7 +2208,7 @@ where
}
}
-impl<'bump, T, I> IndexMut for Vec<'bump, T>
+impl IndexMut for Vec<'_, T>
where
I: ::core::slice::SliceIndex<[T]>,
{
@@ -2209,7 +2225,7 @@ impl<'bump, T: 'bump> ops::Deref for Vec<'bump, T> {
unsafe {
let p = self.buf.ptr();
// assume(!p.is_null());
- slice::from_raw_parts(p, self.len)
+ slice::from_raw_parts(p, self.buf.len_usize())
}
}
}
@@ -2219,7 +2235,7 @@ impl<'bump, T: 'bump> ops::DerefMut for Vec<'bump, T> {
unsafe {
let ptr = self.buf.ptr();
// assume(!ptr.is_null());
- slice::from_raw_parts_mut(ptr, self.len)
+ slice::from_raw_parts_mut(ptr, self.buf.len_usize())
}
}
}
@@ -2260,7 +2276,7 @@ impl<'bump, T: 'bump> IntoIterator for Vec<'bump, T> {
}
}
-impl<'a, 'bump, T> IntoIterator for &'a Vec<'bump, T> {
+impl<'a, T> IntoIterator for &'a Vec<'_, T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
@@ -2269,7 +2285,7 @@ impl<'a, 'bump, T> IntoIterator for &'a Vec<'bump, T> {
}
}
-impl<'a, 'bump, T> IntoIterator for &'a mut Vec<'bump, T> {
+impl<'a, T> IntoIterator for &'a mut Vec<'_, T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
@@ -2381,7 +2397,7 @@ impl<'bump, T: 'bump> Vec<'bump, T> {
/// append the entire slice at once.
///
/// [`copy_from_slice`]: https://doc.rust-lang.org/std/primitive.slice.html#method.copy_from_slice
-impl<'a, 'bump, T: 'a + Copy> Extend<&'a T> for Vec<'bump, T> {
+impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<'_, T> {
fn extend>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned())
}
@@ -2530,7 +2546,7 @@ pub struct IntoIter<'bump, T> {
end: *const T,
}
-impl<'bump, T: fmt::Debug> fmt::Debug for IntoIter<'bump, T> {
+impl fmt::Debug for IntoIter<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
}
@@ -2578,8 +2594,8 @@ impl<'bump, T: 'bump> IntoIter<'bump, T> {
}
}
-unsafe impl<'bump, T: Send> Send for IntoIter<'bump, T> {}
-unsafe impl<'bump, T: Sync> Sync for IntoIter<'bump, T> {}
+unsafe impl Send for IntoIter<'_, T> {}
+unsafe impl Sync for IntoIter<'_, T> {}
impl<'bump, T: 'bump> Iterator for IntoIter<'bump, T> {
type Item = T;
@@ -2587,7 +2603,7 @@ impl<'bump, T: 'bump> Iterator for IntoIter<'bump, T> {
#[inline]
fn next(&mut self) -> Option {
unsafe {
- if self.ptr as *const _ == self.end {
+ if std::ptr::eq(self.ptr, self.end) {
None
} else if mem::size_of::() == 0 {
// purposefully don't use 'ptr.offset' because for
@@ -2647,7 +2663,7 @@ impl<'bump, T: 'bump> ExactSizeIterator for IntoIter<'bump, T> {}
impl<'bump, T: 'bump> FusedIterator for IntoIter<'bump, T> {}
-impl<'bump, T> Drop for IntoIter<'bump, T> {
+impl Drop for IntoIter<'_, T> {
fn drop(&mut self) {
// drop all remaining elements
self.for_each(drop);
@@ -2673,10 +2689,10 @@ impl<'a, 'bump, T: 'a + 'bump + fmt::Debug> fmt::Debug for Drain<'a, 'bump, T> {
}
}
-unsafe impl<'a, 'bump, T: Sync> Sync for Drain<'a, 'bump, T> {}
-unsafe impl<'a, 'bump, T: Send> Send for Drain<'a, 'bump, T> {}
+unsafe impl Sync for Drain<'_, '_, T> {}
+unsafe impl Send for Drain<'_, '_, T> {}
-impl<'a, 'bump, T> Iterator for Drain<'a, 'bump, T> {
+impl Iterator for Drain<'_, '_, T> {
type Item = T;
#[inline]
@@ -2689,14 +2705,14 @@ impl<'a, 'bump, T> Iterator for Drain<'a, 'bump, T> {
}
}
-impl<'a, 'bump, T> DoubleEndedIterator for Drain<'a, 'bump, T> {
+impl DoubleEndedIterator for Drain<'_, '_, T> {
#[inline]
fn next_back(&mut self) -> Option {
self.iter.next_back().map(|elt| unsafe { ptr::read(elt as *const _) })
}
}
-impl<'a, 'bump, T> Drop for Drain<'a, 'bump, T> {
+impl Drop for Drain<'_, '_, T> {
fn drop(&mut self) {
// exhaust self first
self.for_each(drop);
@@ -2718,9 +2734,9 @@ impl<'a, 'bump, T> Drop for Drain<'a, 'bump, T> {
}
}
-impl<'a, 'bump, T> ExactSizeIterator for Drain<'a, 'bump, T> {}
+impl ExactSizeIterator for Drain<'_, '_, T> {}
-impl<'a, 'bump, T> FusedIterator for Drain<'a, 'bump, T> {}
+impl FusedIterator for Drain<'_, '_, T> {}
/// A splicing iterator for `Vec`.
///
@@ -2732,7 +2748,7 @@ pub struct Splice<'a, 'bump, I: Iterator + 'a + 'bump> {
replace_with: I,
}
-impl<'a, 'bump, I: Iterator> Iterator for Splice<'a, 'bump, I> {
+impl Iterator for Splice<'_, '_, I> {
type Item = I::Item;
fn next(&mut self) -> Option {
@@ -2744,15 +2760,15 @@ impl<'a, 'bump, I: Iterator> Iterator for Splice<'a, 'bump, I> {
}
}
-impl<'a, 'bump, I: Iterator> DoubleEndedIterator for Splice<'a, 'bump, I> {
+impl DoubleEndedIterator for Splice<'_, '_, I> {
fn next_back(&mut self) -> Option {
self.drain.next_back()
}
}
-impl<'a, 'bump, I: Iterator> ExactSizeIterator for Splice<'a, 'bump, I> {}
+impl ExactSizeIterator for Splice<'_, '_, I> {}
-impl<'a, 'bump, I: Iterator> Drop for Splice<'a, 'bump, I> {
+impl Drop for Splice<'_, '_, I> {
fn drop(&mut self) {
self.drain.by_ref().for_each(drop);
@@ -2795,14 +2811,14 @@ impl<'a, 'bump, I: Iterator> Drop for Splice<'a, 'bump, I> {
}
/// Private helper methods for `Splice::drop`
-impl<'a, 'bump, T> Drain<'a, 'bump, T> {
+impl Drain<'_, '_, T> {
/// The range from `self.vec.len` to `self.tail_start` contains elements
/// that have been moved out.
/// Fill that range as much as possible with new elements from the `replace_with` iterator.
/// Return whether we filled the entire range. (`replace_with.next()` didn’t return `None`.)
unsafe fn fill>(&mut self, replace_with: &mut I) -> bool {
let vec = self.vec.as_mut();
- let range_start = vec.len;
+ let range_start = vec.buf.len_usize();
let range_end = self.tail_start;
let range_slice =
slice::from_raw_parts_mut(vec.as_mut_ptr().add(range_start), range_end - range_start);
@@ -2810,7 +2826,7 @@ impl<'a, 'bump, T> Drain<'a, 'bump, T> {
for place in range_slice {
if let Some(new_item) = replace_with.next() {
ptr::write(place, new_item);
- vec.len += 1;
+ vec.buf.len += 1;
} else {
return false;
}
@@ -2819,10 +2835,14 @@ impl<'a, 'bump, T> Drain<'a, 'bump, T> {
}
/// Make room for inserting more elements before the tail.
+ #[expect(clippy::cast_possible_truncation)]
unsafe fn move_tail(&mut self, extra_capacity: usize) {
let vec = self.vec.as_mut();
let used_capacity = self.tail_start + self.tail_len;
- vec.buf.reserve(used_capacity, extra_capacity);
+ // `used_capacity as u32` is safe because the [`Vec::drain`] method has ensured that
+ // `self.tail_start` is less than or equal to `self.len()`, and `self.tail_len` calculated
+ // from `self.len() - self.tail_start`, and `self.len()` is `u32`.
+ vec.buf.reserve(used_capacity as u32, extra_capacity);
let new_tail_start = self.tail_start + extra_capacity;
let src = vec.as_ptr().add(self.tail_start);
@@ -2845,7 +2865,7 @@ where
pred: F,
}
-impl<'a, 'bump, T, F> Iterator for DrainFilter<'a, 'bump, T, F>
+impl Iterator for DrainFilter<'_, '_, T, F>
where
F: FnMut(&mut T) -> bool,
{
@@ -2879,7 +2899,7 @@ where
}
}
-impl<'a, 'bump, T, F> Drop for DrainFilter<'a, 'bump, T, F>
+impl Drop for DrainFilter<'_, '_, T, F>
where
F: FnMut(&mut T) -> bool,
{
diff --git a/crates/oxc_allocator/src/vec2/raw_vec.rs b/crates/oxc_allocator/src/vec2/raw_vec.rs
index 871c8e5bd6660..8bc83dbee416b 100644
--- a/crates/oxc_allocator/src/vec2/raw_vec.rs
+++ b/crates/oxc_allocator/src/vec2/raw_vec.rs
@@ -53,7 +53,7 @@ use bumpalo::collections::CollectionAllocErr::{self, AllocErr, CapacityOverflow}
/// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec
/// to handle the actual things *stored* inside of a RawVec.
///
-/// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types.
+/// Note that a RawVec always forces its capacity to be u32::MAX for zero-sized types.
/// This enables you to use capacity growing logic catch the overflows in your length
/// that might occur with zero-sized types.
///
@@ -63,9 +63,11 @@ use bumpalo::collections::CollectionAllocErr::{self, AllocErr, CapacityOverflow}
/// field. This allows zero-sized types to not be special-cased by consumers of
/// this type.
#[allow(missing_debug_implementations)]
+#[repr(C)]
pub struct RawVec<'a, T> {
ptr: NonNull,
- cap: usize,
+ pub(super) len: u32,
+ cap: u32,
a: &'a Bump,
}
@@ -74,7 +76,7 @@ impl<'a, T> RawVec<'a, T> {
/// the returned RawVec.
pub fn new_in(a: &'a Bump) -> Self {
// `cap: 0` means "unallocated". zero-sized types are ignored.
- RawVec { ptr: NonNull::dangling(), cap: 0, a }
+ RawVec { ptr: NonNull::dangling(), a, cap: 0, len: 0 }
}
/// Like `with_capacity` but parameterized over the choice of
@@ -91,6 +93,7 @@ impl<'a, T> RawVec<'a, T> {
RawVec::allocate_in(cap, true, a)
}
+ #[expect(clippy::cast_possible_truncation)]
fn allocate_in(cap: usize, zeroed: bool, mut a: &'a Bump) -> Self {
unsafe {
let elem_size = mem::size_of::();
@@ -111,7 +114,9 @@ impl<'a, T> RawVec<'a, T> {
}
};
- RawVec { ptr, cap, a }
+ // `cap as u32` is safe because `alloc_guard` ensures that `cap`
+ // cannot exceed `u32::MAX`.
+ RawVec { ptr, a, cap: cap as u32, len: 0 }
}
}
}
@@ -122,10 +127,15 @@ impl<'a, T> RawVec<'a, T> {
/// # Undefined Behavior
///
/// The ptr must be allocated (via the given allocator `a`), and with the given capacity. The
- /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
+ /// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems) and also
+ /// cannot exceed `u32::MAX` as capacity is stored as `u32`.
/// If the ptr and capacity come from a RawVec created via `a`, then this is guaranteed.
- pub unsafe fn from_raw_parts_in(ptr: *mut T, cap: usize, a: &'a Bump) -> Self {
- RawVec { ptr: NonNull::new_unchecked(ptr), cap, a }
+ #[expect(clippy::cast_possible_truncation)]
+ pub unsafe fn from_raw_parts_in(ptr: *mut T, a: &'a Bump, cap: usize, len: usize) -> Self {
+ alloc_guard(cap).unwrap_or_else(|_| capacity_overflow());
+ // `cap as u32` and `len as u32` are safe because `alloc_guard` ensures that
+ // `cap` and `len` cannot exceed `u32::MAX`.
+ RawVec { ptr: NonNull::new_unchecked(ptr), a, cap: cap as u32, len: len as u32 }
}
}
@@ -139,12 +149,29 @@ impl<'a, T> RawVec<'a, T> {
/// Gets the capacity of the allocation.
///
- /// This will always be `usize::MAX` if `T` is zero-sized.
+ /// This will always be `u32::MAX` if `T` is zero-sized.
#[inline(always)]
- pub fn cap(&self) -> usize {
+ pub fn cap(&self) -> u32 {
if mem::size_of::() == 0 { !0 } else { self.cap }
}
+ /// Gets the usize capacity of the allocation.
+ ///
+ /// This will always be `usize::MAX` if `T` is zero-sized.
+ #[inline(always)]
+ pub fn cap_usize(&self) -> usize {
+ // `self.cap as usize` is safe because it's is `u32` so it must be
+ // less than `usize::MAX`.
+ if mem::size_of::() == 0 { !0 } else { self.cap as usize }
+ }
+
+ /// Gets the usize number of elements.
+ pub fn len_usize(&self) -> usize {
+ // `self.len as usize` is safe because it's is `u32` so it must be
+ // less than `usize::MAX`.
+ self.len as usize
+ }
+
/// Returns a shared reference to the allocator backing this RawVec.
pub fn bump(&self) -> &'a Bump {
self.a
@@ -158,7 +185,9 @@ impl<'a, T> RawVec<'a, T> {
// checks to get our current layout.
unsafe {
let align = mem::align_of::();
- let size = mem::size_of::() * self.cap;
+ // `self.cap as usize` is safe because it's is `u32`
+ // so it must be less than `usize::MAX`.
+ let size = mem::size_of::() * self.cap as usize;
Some(Layout::from_size_align_unchecked(size, align))
}
}
@@ -177,7 +206,7 @@ impl<'a, T> RawVec<'a, T> {
/// # Panics
///
/// * Panics if T is zero-sized on the assumption that you managed to exhaust
- /// all `usize::MAX` slots in your imaginary buffer.
+ /// all `u32::MAX` slots in your imaginary buffer.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
@@ -273,7 +302,7 @@ impl<'a, T> RawVec<'a, T> {
/// # Panics
///
/// * Panics if T is zero-sized on the assumption that you managed to exhaust
- /// all `usize::MAX` slots in your imaginary buffer.
+ /// all `u32::MAX` slots in your imaginary buffer.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
#[inline(never)]
@@ -315,7 +344,7 @@ impl<'a, T> RawVec<'a, T> {
/// The same as `reserve_exact`, but returns on errors instead of panicking or aborting.
pub fn try_reserve_exact(
&mut self,
- len: usize,
+ len: u32,
additional: usize,
) -> Result<(), CollectionAllocErr> {
if self.needs_to_grow(len, additional) {
@@ -338,21 +367,22 @@ impl<'a, T> RawVec<'a, T> {
///
/// # Panics
///
- /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
+ /// * Panics if the requested capacity exceeds `u32::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
+ /// * Panics if the new number of elements would overflow `u32`.
///
/// # Aborts
///
/// Aborts on OOM
- pub fn reserve_exact(&mut self, len: usize, additional: usize) {
+ pub fn reserve_exact(&mut self, len: u32, additional: usize) {
if let Err(err) = self.try_reserve_exact(len, additional) {
handle_error(err)
}
}
/// The same as `reserve`, but returns on errors instead of panicking or aborting.
- pub fn try_reserve(&mut self, len: usize, additional: usize) -> Result<(), CollectionAllocErr> {
+ pub fn try_reserve(&mut self, len: u32, additional: usize) -> Result<(), CollectionAllocErr> {
if self.needs_to_grow(len, additional) {
self.grow_amortized(len, additional)?;
}
@@ -374,7 +404,7 @@ impl<'a, T> RawVec<'a, T> {
///
/// # Panics
///
- /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
+ /// * Panics if the requested capacity exceeds `u32::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
@@ -413,13 +443,13 @@ impl<'a, T> RawVec<'a, T> {
/// # }
/// ```
#[inline]
- pub fn reserve(&mut self, len: usize, additional: usize) {
+ pub fn reserve(&mut self, len: u32, additional: usize) {
// Callers expect this function to be very cheap when there is already sufficient capacity.
// Therefore, we move all the resizing and error-handling logic from grow_amortized and
// handle_reserve behind a call, while making sure that this function is likely to be
// inlined as just a comparison and a call if the comparison fails.
#[cold]
- fn do_reserve_and_handle(slf: &mut RawVec, len: usize, additional: usize) {
+ fn do_reserve_and_handle(slf: &mut RawVec, len: u32, additional: usize) {
if let Err(err) = slf.grow_amortized(len, additional) {
handle_error(err);
}
@@ -457,7 +487,7 @@ impl<'a, T> RawVec<'a, T> {
///
/// # Panics
///
- /// * Panics if the requested capacity exceeds `usize::MAX` bytes.
+ /// * Panics if the requested capacity exceeds `u32::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
pub fn reserve_in_place(&mut self, len: usize, additional: usize) -> bool {
@@ -510,7 +540,7 @@ impl<'a, T> RawVec<'a, T> {
/// # Aborts
///
/// Aborts on OOM.
- pub fn shrink_to_fit(&mut self, amount: usize) {
+ pub fn shrink_to_fit(&mut self, amount: u32) {
let elem_size = mem::size_of::();
// Set the `cap` because they might be about to promote to a `Box<[T]>`
@@ -544,8 +574,11 @@ impl<'a, T> RawVec<'a, T> {
// We also know that `self.cap` is greater than `amount`, and
// consequently we don't need runtime checks for creating either
// layout
- let old_size = elem_size * self.cap;
- let new_size = elem_size * amount;
+ //
+ // `self.cap as usize` and `amount as usize` are safe because
+ // they are `u32` so they must be less than `usize::MAX`.
+ let old_size = elem_size * self.cap as usize;
+ let new_size = elem_size * amount as usize;
let align = mem::align_of::();
let old_layout = Layout::from_size_align_unchecked(old_size, align);
let new_layout = Layout::from_size_align_unchecked(new_size, align);
@@ -584,27 +617,35 @@ impl<'a, T> RawVec<'a, T> {
}
*/
-impl<'a, T> RawVec<'a, T> {
+impl RawVec<'_, T> {
#[inline]
- fn needs_to_grow(&self, len: usize, additional: usize) -> bool {
- additional > self.cap().wrapping_sub(len)
+ fn needs_to_grow(&self, len: u32, additional: usize) -> bool {
+ // `self.cap().wrapping_sub(len) as usize` is safe because
+ // `self.cap()` is `u32` and `len` is `u32`, so the result
+ // is guaranteed to be less than `usize::MAX`.
+ additional > self.cap().wrapping_sub(len) as usize
}
/// Helper method to reserve additional space, reallocating the backing memory.
/// The caller is responsible for confirming that there is not already enough space available.
- fn grow_exact(&mut self, len: usize, additional: usize) -> Result<(), CollectionAllocErr> {
+ #[expect(clippy::cast_possible_truncation)]
+ fn grow_exact(&mut self, len: u32, additional: usize) -> Result<(), CollectionAllocErr> {
unsafe {
// NOTE: we don't early branch on ZSTs here because we want this
- // to actually catch "asking for more than usize::MAX" in that case.
+ // to actually catch "asking for more than u32::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
// panic.
- let new_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
+ // `len as usize` is safe because `len` is `u32`, so it must be
+ // less than `usize::MAX`.
+ let new_cap = (len as usize).checked_add(additional).ok_or(CapacityOverflow)?;
let new_layout = Layout::array::(new_cap).map_err(|_| CapacityOverflow)?;
self.ptr = self.finish_grow(new_layout)?.cast();
- self.cap = new_cap;
+ // `cap as u32` is safe because `finish_grow` called `alloc_guard`, and
+ // `alloc_guard` ensures that `cap` cannot exceed `u32::MAX`.
+ self.cap = new_cap as u32;
Ok(())
}
@@ -612,19 +653,22 @@ impl<'a, T> RawVec<'a, T> {
/// Helper method to reserve additional space, reallocating the backing memory.
/// The caller is responsible for confirming that there is not already enough space available.
- fn grow_amortized(&mut self, len: usize, additional: usize) -> Result<(), CollectionAllocErr> {
+ #[expect(clippy::cast_possible_truncation)]
+ fn grow_amortized(&mut self, len: u32, additional: usize) -> Result<(), CollectionAllocErr> {
unsafe {
// NOTE: we don't early branch on ZSTs here because we want this
- // to actually catch "asking for more than usize::MAX" in that case.
+ // to actually catch "asking for more than u32::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
// panic.
// Nothing we can really do about these checks, sadly.
- let required_cap = len.checked_add(additional).ok_or(CapacityOverflow)?;
+ // `len as usize` is safe because `len` is `u32`, so it must be
+ // less than `usize::MAX`.
+ let required_cap = (len as usize).checked_add(additional).ok_or(CapacityOverflow)?;
// This guarantees exponential growth. The doubling cannot overflow
- // because `cap <= isize::MAX` and the type of `cap` is `usize`.
- let cap = cmp::max(self.cap() * 2, required_cap);
+ // because `cap <= isize::MAX` and the type of `cap` is `u32`.
+ let cap = cmp::max((self.cap() as usize) * 2, required_cap);
// The following commented-out code is copied from the standard library.
// We don't use it because this would cause notable performance regression
@@ -658,7 +702,9 @@ impl<'a, T> RawVec<'a, T> {
self.ptr = self.finish_grow(new_layout)?.cast();
- self.cap = cap;
+ // `cap as u32` is safe because `finish_grow` called `alloc_guard`, and
+ // `alloc_guard` ensures that `cap` cannot exceed `u32::MAX`.
+ self.cap = cap as u32;
Ok(())
}
@@ -693,7 +739,7 @@ impl<'a, T> RawVec<'a, T> {
}
}
-impl<'a, T> RawVec<'a, T> {
+impl RawVec<'_, T> {
/// Frees the memory owned by the RawVec *without* trying to Drop its contents.
pub unsafe fn dealloc_buffer(&mut self) {
let elem_size = mem::size_of::();
@@ -707,20 +753,23 @@ impl<'a, T> RawVec<'a, T> {
// We need to guarantee the following:
// * We don't ever allocate `> isize::MAX` byte-size objects
-// * We don't overflow `usize::MAX` and actually allocate too little
+// * We don't overflow `u32::MAX` and actually allocate too little
//
-// On 64-bit we just need to check for overflow since trying to allocate
-// `> isize::MAX` bytes will surely fail. On 32-bit and 16-bit we need to add
-// an extra guard for this in case we're running on a platform which can use
-// all 4GB in user-space. e.g. PAE or x32
+// On 64-bit we need to check for overflow since trying to allocate `> u32::MAX`
+// bytes is overflow because `cap` and `len` are both `u32`s.
+// On 32-bit and 16-bit we need to add an extra guard for this in case we're
+// running on a platform which can use all 4GB in user-space. e.g. PAE or x32
#[inline]
fn alloc_guard(alloc_size: usize) -> Result<(), CollectionAllocErr> {
- if mem::size_of::() < 8 && alloc_size > ::core::isize::MAX as usize {
- Err(CapacityOverflow)
- } else {
- Ok(())
+ if mem::size_of::() < 8 {
+ if alloc_size > ::core::isize::MAX as usize {
+ return Err(CapacityOverflow);
+ }
+ } else if alloc_size > u32::MAX as usize {
+ return Err(CapacityOverflow);
}
+ Ok(())
}
// One central function responsible for reporting capacity overflows. This'll
diff --git a/crates/oxc_ast/CHANGELOG.md b/crates/oxc_ast/CHANGELOG.md
index ee704eb2e0fa6..2f12aa186e0d7 100644
--- a/crates/oxc_ast/CHANGELOG.md
+++ b/crates/oxc_ast/CHANGELOG.md
@@ -4,6 +4,91 @@ All notable changes to this package will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0.
+## [0.70.0] - 2025-05-15
+
+### Features
+
+- 1673ffb codegen: Rework printing normal / legal / annotation comments (#10997) (Boshen)
+
+### Bug Fixes
+
+- 6f3f9d7 ast/estree: Fix `raw_deser` for `TSMappedTypeOptional` serializer (#10971) (overlookmotel)
+- 53329f8 ast/estree: Fix field order for `FormalParameter` (#10962) (overlookmotel)
+- 8b8f78f ast/estree: Fix field order and type def for `RestElement` in `FormalParameters` (#10961) (overlookmotel)
+- 2b76ab5 ast/estree: Fix `TSModuleDeclaration` raw deserializer (#10924) (overlookmotel)
+- d036cf5 estree: Ensure the same key order for `AssignmentPattern` (#10953) (Yuji Sugiura)
+
+### Performance
+
+- a4b5716 ast/estree: Streamline raw deserializer for `WithClause` (#10974) (overlookmotel)
+
+### Documentation
+
+- 206e07d ast: Fix docs for `ExportSpecifier` (#10891) (overlookmotel)
+- b23fef7 ast/estree: Standardize doc comments for ESTree serializers (#10968) (overlookmotel)
+
+### Refactor
+
+- 6cc74ff ast/estree: Add semi-colon (#10973) (overlookmotel)
+- 2958ff7 ast/estree: Rename serializers (#10969) (overlookmotel)
+- b8018b9 ast/estree: Split custom serializers into multiple files (#10967) (overlookmotel)
+- 08f1f3f ast/estree: Remove custom serializer for `Elision` (#10965) (overlookmotel)
+- d01a47b ast/estree: Simplify custom serializers for `FormalParameters` (#10964) (overlookmotel)
+- bfc6b9a ast/estree: Rename custom serializers for fields containing `FormalParameters` (#10963) (overlookmotel)
+
+### Styling
+
+- 6d4936f ast/estree: Reformat `raw_deser` code (#10972) (overlookmotel)
+
+## [0.69.0] - 2025-05-09
+
+- 2b5d826 ast: [**BREAKING**] Fix field order for `TSTypeAssertion` (#10906) (overlookmotel)
+
+- 1f35910 ast: [**BREAKING**] Fix field order for `TSNamedTupleMember` (#10905) (overlookmotel)
+
+- 8a3bba8 ast: [**BREAKING**] Fix field order for `PropertyDefinition` (#10902) (overlookmotel)
+
+- 5746d36 ast: [**BREAKING**] Fix field order for `NewExpression` (#10893) (overlookmotel)
+
+- 0139793 ast: [**BREAKING**] Re-order fields of `TaggedTemplateExpression` (#10889) (overlookmotel)
+
+- 6646b6b ast: [**BREAKING**] Fix field order for `JSXOpeningElement` (#10882) (overlookmotel)
+
+- cc2ed21 ast: [**BREAKING**] Fix field order for `JSXElement` and `JSXFragment` (#10881) (overlookmotel)
+
+- ad4fbf4 ast: [**BREAKING**] Simplify `RegExpPattern` (#10834) (overlookmotel)
+
+### Features
+
+- d066516 ast_tools: Support `#[estree(prepend_to)]` (#10849) (overlookmotel)
+
+### Bug Fixes
+
+- 2c09243 ast: Fix field order for `AccessorProperty` (#10878) (overlookmotel)
+- 581d068 ast/estree: Fix TS type def for `RegExpLiteral` (#10876) (overlookmotel)
+- e7228fa ast/estree: Fix `optional` field of `TSMappedType` in TS-ESTree AST (#10874) (overlookmotel)
+- 6f0638a ast/estree: Remove `TSImportTypeOptions` custom serializer (#10873) (overlookmotel)
+- e6657ae ast/estree: Reorder fields for TS `Identifier` types in TS-ESTree AST (#10864) (overlookmotel)
+
+### Performance
+
+- 49a6f97 napi/parser: Faster fixup of `BigInt`s and `RegExp`s (#10820) (overlookmotel)
+
+### Documentation
+
+- 4863eef ast: Improve docs for `TSImportType` (#10903) (overlookmotel)
+
+### Refactor
+
+- 805735b ast: Remove quotes from `#[estree(append_to)]` attributes (#10863) (overlookmotel)
+- 0f7e755 ast/estree: Use `#[estree(prepend_to)]` (#10862) (overlookmotel)
+- b16331e ast/estree: Generalize concatenating fields with `Concat2` (#10848) (overlookmotel)
+- daba0a7 estree: Remove regular expression types from ESTree AST (#10855) (overlookmotel)
+
+### Styling
+
+- 62c3a4a ast_tools: Add full stop to end of generated comments (#10809) (overlookmotel)
+
## [0.68.1] - 2025-05-04
### Bug Fixes
diff --git a/crates/oxc_ast/Cargo.toml b/crates/oxc_ast/Cargo.toml
index ad9d07f5f99e9..7d1b433ac95b8 100644
--- a/crates/oxc_ast/Cargo.toml
+++ b/crates/oxc_ast/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "oxc_ast"
-version = "0.68.1"
+version = "0.70.0"
authors.workspace = true
categories.workspace = true
edition.workspace = true
diff --git a/crates/oxc_ast/src/ast/comment.rs b/crates/oxc_ast/src/ast/comment.rs
index e142fec8e98ff..8c0ff61971d50 100644
--- a/crates/oxc_ast/src/ast/comment.rs
+++ b/crates/oxc_ast/src/ast/comment.rs
@@ -49,15 +49,14 @@ pub enum CommentAnnotation {
#[default]
None = 0,
- /// `/** jsdoc */`
- ///
- Jsdoc = 1,
-
/// Legal Comment
/// e.g. `/* @license */`, `/* @preserve */`, or starts with `//!` or `/*!`.
- ///
///
- Legal = 2,
+ Legal = 1,
+
+ /// `/** jsdoc */`
+ ///
+ Jsdoc = 2,
/// `/* #__PURE__ */`
///
@@ -82,6 +81,22 @@ pub enum CommentAnnotation {
CoverageIgnore = 7,
}
+/// State of newlines around a comment.
+#[ast]
+#[generate_derive(CloneIn, ContentEq)]
+#[derive(Debug, Default, Clone, Copy, Eq, PartialEq)]
+pub enum CommentNewlines {
+ /// No newlines before or after
+ #[default]
+ None = 0,
+ /// Preceded by a newline
+ Leading = 1,
+ /// Followed by a newline
+ Trailing = 2,
+ /// Preceded and followed by a newline
+ LeadingAndTrailing = 3,
+}
+
/// A comment in source code.
#[ast]
#[generate_derive(CloneIn, ContentEq, ESTree)]
@@ -106,14 +121,10 @@ pub struct Comment {
#[estree(skip)]
pub position: CommentPosition,
- /// Whether this comment has a preceding newline.
+ /// Whether this comment has newlines around it.
/// Used to avoid becoming a trailing comment in codegen.
#[estree(skip)]
- pub preceded_by_newline: bool,
-
- /// Whether this comment has a tailing newline.
- #[estree(skip)]
- pub followed_by_newline: bool,
+ pub newlines: CommentNewlines,
/// Comment Annotation
#[estree(skip)]
@@ -130,8 +141,7 @@ impl Comment {
attached_to: 0,
kind,
position: CommentPosition::Trailing,
- preceded_by_newline: false,
- followed_by_newline: false,
+ newlines: CommentNewlines::None,
annotation: CommentAnnotation::None,
}
}
@@ -220,4 +230,50 @@ impl Comment {
pub fn is_coverage_ignore(self) -> bool {
self.annotation == CommentAnnotation::CoverageIgnore && self.is_leading()
}
+
+ /// Sets the state of `newlines` to include/exclude a newline after the comment.
+ pub fn set_followed_by_newline(&mut self, followed_by_newline: bool) {
+ if followed_by_newline {
+ self.newlines = match self.newlines {
+ CommentNewlines::None => CommentNewlines::Trailing,
+ CommentNewlines::Leading => CommentNewlines::LeadingAndTrailing,
+ _ => self.newlines,
+ }
+ } else {
+ self.newlines = match self.newlines {
+ CommentNewlines::Trailing => CommentNewlines::None,
+ CommentNewlines::LeadingAndTrailing => CommentNewlines::Leading,
+ _ => self.newlines,
+ }
+ }
+ }
+
+ /// Sets the state of `newlines` to include/exclude a newline before the comment.
+ pub fn set_preceded_by_newline(&mut self, preceded_by_newline: bool) {
+ if preceded_by_newline {
+ self.newlines = match self.newlines {
+ CommentNewlines::None => CommentNewlines::Leading,
+ CommentNewlines::Trailing => CommentNewlines::LeadingAndTrailing,
+ _ => self.newlines,
+ }
+ } else {
+ self.newlines = match self.newlines {
+ CommentNewlines::Leading => CommentNewlines::None,
+ CommentNewlines::LeadingAndTrailing => CommentNewlines::Trailing,
+ _ => self.newlines,
+ }
+ }
+ }
+
+ /// Returns `true` if this comment is preceded by a newline.
+ #[inline]
+ pub fn preceded_by_newline(self) -> bool {
+ matches!(self.newlines, CommentNewlines::Leading | CommentNewlines::LeadingAndTrailing)
+ }
+
+ /// Returns `true` if this comment is followed by a newline.
+ #[inline]
+ pub fn followed_by_newline(self) -> bool {
+ matches!(self.newlines, CommentNewlines::Trailing | CommentNewlines::LeadingAndTrailing)
+ }
}
diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs
index 23876a7ae2a29..1ba0166423951 100644
--- a/crates/oxc_ast/src/ast/js.rs
+++ b/crates/oxc_ast/src/ast/js.rs
@@ -334,11 +334,10 @@ pub enum ArrayExpressionElement<'a> {
/// empty slot in `const array = [1, , 2];`
///
/// Array Expression Elision Element
-/// Serialized as `null` in JSON AST. See `serialize.rs`.
#[ast(visit)]
#[derive(Debug, Clone)]
#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
-#[estree(via = ElisionConverter)]
+#[estree(via = Null)]
pub struct Elision {
pub span: Span,
}
@@ -963,7 +962,7 @@ pub struct AssignmentTargetPropertyIdentifier<'a> {
pub span: Span,
#[estree(rename = "key")]
pub binding: IdentifierReference<'a>,
- #[estree(rename = "value", via = AssignmentTargetPropertyIdentifierValue)]
+ #[estree(rename = "value", via = AssignmentTargetPropertyIdentifierInit)]
pub init: Option>,
}
@@ -1727,7 +1726,7 @@ pub struct Function<'a> {
/// Function parameters.
///
/// Does not include `this` parameters used by some TypeScript functions.
- #[estree(via = FunctionFormalParameters)]
+ #[estree(via = FunctionParams)]
pub params: Box<'a, FormalParameters<'a>>,
/// The TypeScript return type annotation.
#[ts]
@@ -1774,8 +1773,10 @@ pub enum FunctionType {
interface FormalParameterRest extends Span {
type: 'RestElement';
argument: BindingPatternKind;
- typeAnnotation: TSTypeAnnotation | null;
- optional: boolean;
+ decorators?: [],
+ optional?: boolean;
+ typeAnnotation?: TSTypeAnnotation | null;
+ value?: null;
}
"
)]
@@ -2490,10 +2491,13 @@ pub struct ImportNamespaceSpecifier<'a> {
#[ast(visit)]
#[derive(Debug)]
#[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree)]
-#[estree(no_ts_def)]
+#[estree(no_type, no_ts_def)]
pub struct WithClause<'a> {
+ #[estree(skip)]
pub span: Span,
+ #[estree(skip)]
pub attributes_keyword: IdentifierName<'a>, // `with` or `assert`
+ #[estree(rename = "attributes")]
pub with_entries: Vec<'a, ImportAttribute<'a>>,
}
@@ -2589,12 +2593,16 @@ pub struct ExportAllDeclaration<'a> {
///
/// Each [`ExportSpecifier`] is one of the named exports in an [`ExportNamedDeclaration`].
///
+/// Note: `export_kind` relates to whether this specific `ExportSpecifier` is preceded by `type` keyword.
+/// If the whole `ExportNamedDeclaration` has a `type` prefix, its `ExportSpecifier`s will still have
+/// `export_kind: ImportOrExportKind::Value`. e.g. in this case: `export type { Foo, Bar }`.
+///
/// ## Example
///
/// ```ts
/// // ____ export_kind
-/// import { type Foo as Bar } from './foo';
-/// // exported ^^^ ^^^ local
+/// export { type Foo as Bar };
+/// // local ^^^ ^^^ exported
/// ```
#[ast(visit)]
#[derive(Debug)]
@@ -2604,7 +2612,7 @@ pub struct ExportSpecifier<'a> {
pub local: ModuleExportName<'a>,
pub exported: ModuleExportName<'a>,
#[ts]
- pub export_kind: ImportOrExportKind, // `export type *`
+ pub export_kind: ImportOrExportKind, // `export { type Foo as Bar };`
}
inherit_variants! {
diff --git a/crates/oxc_ast/src/ast/jsx.rs b/crates/oxc_ast/src/ast/jsx.rs
index 2039ecdf5ff20..b78477dea718e 100644
--- a/crates/oxc_ast/src/ast/jsx.rs
+++ b/crates/oxc_ast/src/ast/jsx.rs
@@ -38,7 +38,7 @@ pub struct JSXElement<'a> {
/// Node location in source code
pub span: Span,
/// Opening tag of the element.
- #[estree(via = JSXElementOpening)]
+ #[estree(via = JSXElementOpeningElement)]
pub opening_element: Box<'a, JSXOpeningElement<'a>>,
/// Children of the element.
/// This can be text, other elements, or expressions.
diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs
index 0df61554d6361..c61c8805c23d2 100644
--- a/crates/oxc_ast/src/ast/ts.rs
+++ b/crates/oxc_ast/src/ast/ts.rs
@@ -1020,7 +1020,7 @@ pub struct TSCallSignatureDeclaration<'a> {
pub type_parameters: Option>>,
#[estree(skip)]
pub this_param: Option>>,
- #[estree(via = TSCallSignatureDeclarationFormalParameters)]
+ #[estree(via = TSCallSignatureDeclarationParams)]
pub params: Box<'a, FormalParameters<'a>>,
pub return_type: Option>>,
}
@@ -1059,7 +1059,7 @@ pub struct TSMethodSignature<'a> {
pub type_parameters: Option>>,
#[estree(skip)]
pub this_param: Option>>,
- #[estree(via = TSMethodSignatureFormalParameters)]
+ #[estree(via = TSMethodSignatureParams)]
pub params: Box<'a, FormalParameters<'a>>,
pub return_type: Option>>,
pub scope_id: Cell