Skip to content

Commit 855b48e

Browse files
authored
Merge branch 'main' into feat/astro
2 parents 20ef187 + 4999cd5 commit 855b48e

85 files changed

Lines changed: 12217 additions & 9139 deletions

File tree

Some content is hidden

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

.github/scripts/clone-parallel.mjs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ import { dirname, join } from "node:path";
1111

1212
// Submodule commit SHAs - updated automatically by .github/workflows/update_submodules.yml
1313
// NOTE: Prettier version is now pinned to `v3.8.0` (not updated by workflow above), Update manually as needed
14-
const TEST262_SHA = "fff41f0522ede859d0880acbff066b09fc9c22a5";
15-
const BABEL_SHA = "6ef16ca449aa76d1f1d689bddc4d63f35e07f574";
16-
const TYPESCRIPT_SHA = "7f6a84673def7665a4c4bc2bdfaf7bcc8549b276";
14+
const TEST262_SHA = "dd6138f9bc1aa2c3ba9cbf54452049b9a92c4e13";
15+
const BABEL_SHA = "92c052dc449eeb7d9562d5852d1ea295d6c86eca";
16+
const TYPESCRIPT_SHA = "95e3aaa90341b516e868bf2300b1da5d07103f1e";
1717
const PRETTIER_SHA = "812a4d0071270f61a7aa549d625b618be7e09d71";
18-
const ESTREE_CONFORMANCE_SHA = "389cb2a71867fb468fc0f090cd493120c9d84993";
18+
const ESTREE_CONFORMANCE_SHA = "32501475c99fc022a93c80bc6ce1a607f21ecc66";
1919
const NODE_COMPAT_TABLE_SHA = "499beb6f1daa36f10c26b85a7f3ec3b3448ded23";
2020

2121
const repoRoot = join(import.meta.dirname, "..", "..");

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ jobs:
268268
runs-on: ubuntu-slim
269269
steps:
270270
- uses: taiki-e/checkout-action@3ab630d442e198ebb0ca30872832406ca01c46eb # v1.4.0
271-
- uses: crate-ci/typos@93cbdb2d23269548cf0db0f74d0bc6a09a3f0d5c # v1.43.0
271+
- uses: crate-ci/typos@3a4d65230db538caabac6e156599c8ba8380ff07 # v1.43.1
272272
with:
273273
files: .
274274

.github/workflows/prepare_release_apps.yml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,30 +80,38 @@ jobs:
8080
- uses: taiki-e/checkout-action@3ab630d442e198ebb0ca30872832406ca01c46eb # v1.4.0
8181

8282
- uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
83-
id: comment
83+
id: comment-oxlint
8484
with:
8585
token: ${{ secrets.GITHUB_TOKEN }}
8686
issue-number: ${{ needs.prepare.outputs.pull-request-number }}
8787
body: |
88-
Triggering Ecosystem CI
89-
oxlint https://github.com/oxc-project/oxc-ecosystem-ci/actions/workflows/oxlint-ci.yml
90-
oxfmt https://github.com/oxc-project/oxc-ecosystem-ci/actions/workflows/oxfmt-ci.yml
88+
Triggering Oxlint Ecosystem CI
89+
https://github.com/oxc-project/oxc-ecosystem-ci/actions/workflows/oxlint-ci.yml
90+
91+
- uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
92+
id: comment-oxfmt
93+
with:
94+
token: ${{ secrets.GITHUB_TOKEN }}
95+
issue-number: ${{ needs.prepare.outputs.pull-request-number }}
96+
body: |
97+
Triggering Oxfmt Ecosystem CI
98+
https://github.com/oxc-project/oxc-ecosystem-ci/actions/workflows/oxfmt-ci.yml
9199
92100
- uses: benc-uk/workflow-dispatch@e2e5e9a103e331dad343f381a29e654aea3cf8fc # v1.2.4
93101
with:
94102
repo: oxc-project/oxc-ecosystem-ci
95103
workflow: oxlint-ci.yml
96104
token: ${{ secrets.OXC_BOT_PAT }}
97105
ref: main
98-
inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment.outputs.comment-id }}" }'
106+
inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment-oxlint.outputs.comment-id }}" }'
99107

100108
- uses: benc-uk/workflow-dispatch@e2e5e9a103e331dad343f381a29e654aea3cf8fc # v1.2.4
101109
with:
102110
repo: oxc-project/oxc-ecosystem-ci
103111
workflow: oxfmt-ci.yml
104112
token: ${{ secrets.OXC_BOT_PAT }}
105113
ref: main
106-
inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment.outputs.comment-id }}" }'
114+
inputs: '{ "issue-number": "${{ needs.prepare.outputs.pull-request-number }}", "comment-id": "${{ steps.comment-oxfmt.outputs.comment-id }}" }'
107115

108116
website:
109117
needs: prepare

apps/oxfmt/src/core/external_formatter.rs

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::{
22
path::Path,
3-
sync::{Arc, Mutex},
3+
sync::{Arc, RwLock},
44
};
55

66
use napi::{
@@ -73,21 +73,24 @@ pub type JsSortTailwindClassesCb = ThreadsafeFunction<
7373
/// Holds raw ThreadsafeFunctions wrapped in Option for cleanup.
7474
/// The TSFNs can be explicitly dropped via `cleanup()` to prevent
7575
/// use-after-free during V8 cleanup on Node.js exit.
76+
///
77+
/// Uses `RwLock` instead of `Mutex` for better performance: the wrapper functions
78+
/// only read from the Option (common path), while only `cleanup()` needs write access.
7679
#[derive(Clone)]
7780
struct TsfnHandles {
78-
init: Arc<Mutex<Option<JsInitExternalFormatterCb>>>,
79-
format_embedded: Arc<Mutex<Option<JsFormatEmbeddedCb>>>,
80-
format_file: Arc<Mutex<Option<JsFormatFileCb>>>,
81-
sort_tailwind: Arc<Mutex<Option<JsSortTailwindClassesCb>>>,
81+
init: Arc<RwLock<Option<JsInitExternalFormatterCb>>>,
82+
format_embedded: Arc<RwLock<Option<JsFormatEmbeddedCb>>>,
83+
format_file: Arc<RwLock<Option<JsFormatFileCb>>>,
84+
sort_tailwind: Arc<RwLock<Option<JsSortTailwindClassesCb>>>,
8285
}
8386

8487
impl TsfnHandles {
8588
/// Drop all ThreadsafeFunctions to prevent use-after-free during V8 cleanup.
8689
fn cleanup(&self) {
87-
let _ = self.init.lock().unwrap().take();
88-
let _ = self.format_embedded.lock().unwrap().take();
89-
let _ = self.format_file.lock().unwrap().take();
90-
let _ = self.sort_tailwind.lock().unwrap().take();
90+
let _ = self.init.write().unwrap().take();
91+
let _ = self.format_embedded.write().unwrap().take();
92+
let _ = self.format_file.write().unwrap().take();
93+
let _ = self.sort_tailwind.write().unwrap().take();
9194
}
9295
}
9396

@@ -145,11 +148,11 @@ impl ExternalFormatter {
145148
format_file_cb: JsFormatFileCb,
146149
sort_tailwindcss_classes_cb: JsSortTailwindClassesCb,
147150
) -> Self {
148-
// Wrap TSFNs in Arc<Mutex<Option<...>>> so they can be explicitly dropped
149-
let init_handle = Arc::new(Mutex::new(Some(init_cb)));
150-
let format_embedded_handle = Arc::new(Mutex::new(Some(format_embedded_cb)));
151-
let format_file_handle = Arc::new(Mutex::new(Some(format_file_cb)));
152-
let sort_tailwind_handle = Arc::new(Mutex::new(Some(sort_tailwindcss_classes_cb)));
151+
// Wrap TSFNs in Arc<RwLock<Option<...>>> so they can be explicitly dropped
152+
let init_handle = Arc::new(RwLock::new(Some(init_cb)));
153+
let format_embedded_handle = Arc::new(RwLock::new(Some(format_embedded_cb)));
154+
let format_file_handle = Arc::new(RwLock::new(Some(format_file_cb)));
155+
let sort_tailwind_handle = Arc::new(RwLock::new(Some(sort_tailwindcss_classes_cb)));
153156

154157
// Create handles struct for cleanup
155158
let handles = TsfnHandles {
@@ -243,10 +246,10 @@ impl ExternalFormatter {
243246
// Therefore, just provides a dummy external formatter that consistently returns errors.
244247
Self {
245248
handles: TsfnHandles {
246-
init: Arc::new(Mutex::new(None)),
247-
format_embedded: Arc::new(Mutex::new(None)),
248-
format_file: Arc::new(Mutex::new(None)),
249-
sort_tailwind: Arc::new(Mutex::new(None)),
249+
init: Arc::new(RwLock::new(None)),
250+
format_embedded: Arc::new(RwLock::new(None)),
251+
format_file: Arc::new(RwLock::new(None)),
252+
sort_tailwind: Arc::new(RwLock::new(None)),
250253
},
251254
init: Arc::new(|_| Err("Dummy init called".to_string())),
252255
format_embedded: Arc::new(|_, _, _| Err("Dummy format_embedded called".to_string())),
@@ -289,11 +292,11 @@ fn language_to_prettier_parser(language: &str) -> Option<&'static str> {
289292

290293
/// Wrap JS `initExternalFormatter` callback as a normal Rust function.
291294
fn wrap_init_external_formatter(
292-
cb_handle: Arc<Mutex<Option<JsInitExternalFormatterCb>>>,
295+
cb_handle: Arc<RwLock<Option<JsInitExternalFormatterCb>>>,
293296
) -> InitExternalFormatterCallback {
294297
Arc::new(move |num_threads: usize| {
295298
debug_span!("oxfmt::external::init", num_threads = num_threads).in_scope(|| {
296-
let guard = cb_handle.lock().unwrap();
299+
let guard = cb_handle.read().unwrap();
297300
let Some(cb) = guard.as_ref() else {
298301
return Err("JS callback unavailable (environment shutting down)".to_string());
299302
};
@@ -320,11 +323,11 @@ fn wrap_init_external_formatter(
320323

321324
/// Wrap JS `formatEmbeddedCode` callback as a normal Rust function.
322325
fn wrap_format_embedded(
323-
cb_handle: Arc<Mutex<Option<JsFormatEmbeddedCb>>>,
326+
cb_handle: Arc<RwLock<Option<JsFormatEmbeddedCb>>>,
324327
) -> FormatEmbeddedWithConfigCallback {
325328
Arc::new(move |options: &Value, parser_name: &str, code: &str| {
326329
debug_span!("oxfmt::external::format_embedded", parser = %parser_name).in_scope(|| {
327-
let guard = cb_handle.lock().unwrap();
330+
let guard = cb_handle.read().unwrap();
328331
let Some(cb) = guard.as_ref() else {
329332
return Err("JS callback unavailable (environment shutting down)".to_string());
330333
};
@@ -360,10 +363,12 @@ fn wrap_format_embedded(
360363
}
361364

362365
/// Wrap JS `formatFile` callback as a normal Rust function.
363-
fn wrap_format_file(cb_handle: Arc<Mutex<Option<JsFormatFileCb>>>) -> FormatFileWithConfigCallback {
366+
fn wrap_format_file(
367+
cb_handle: Arc<RwLock<Option<JsFormatFileCb>>>,
368+
) -> FormatFileWithConfigCallback {
364369
Arc::new(move |options: &Value, parser_name: &str, file_name: &str, code: &str| {
365370
debug_span!("oxfmt::external::format_file", parser = %parser_name, file = %file_name).in_scope(|| {
366-
let guard = cb_handle.lock().unwrap();
371+
let guard = cb_handle.read().unwrap();
367372
let Some(cb) = guard.as_ref() else {
368373
return Err("JS callback unavailable (environment shutting down)".to_string());
369374
};
@@ -396,12 +401,12 @@ fn wrap_format_file(cb_handle: Arc<Mutex<Option<JsFormatFileCb>>>) -> FormatFile
396401

397402
/// Wrap JS `sortTailwindClasses` callback as a normal Rust function.
398403
fn wrap_sort_tailwind_classes(
399-
cb_handle: Arc<Mutex<Option<JsSortTailwindClassesCb>>>,
404+
cb_handle: Arc<RwLock<Option<JsSortTailwindClassesCb>>>,
400405
) -> TailwindWithConfigCallback {
401406
Arc::new(move |filepath: &str, options: &Value, classes: Vec<String>| {
402407
debug_span!("oxfmt::external::sort_tailwind", classes_count = classes.len()).in_scope(
403408
|| {
404-
let guard = cb_handle.lock().unwrap();
409+
let guard = cb_handle.read().unwrap();
405410
let Some(cb) = guard.as_ref() else {
406411
// Return original classes if callback unavailable
407412
return classes;

apps/oxlint/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/node_modules/
22
/dist/
3+
/dist-pkg-plugins/
34
*.node

0 commit comments

Comments
 (0)