From e928dc1b2f1daad61d146ce27ba237323c27e61e Mon Sep 17 00:00:00 2001
From: xusd320 <xusd320@gmail.com>
Date: Thu, 6 Mar 2025 18:06:52 +0800
Subject: [PATCH] feat: add concurrent feature

---
 Cargo.lock                    |  1 +
 Cargo.toml                    |  1 +
 src/source_map.rs             | 13 ++++++-------
 src/transpiling/mod.rs        | 23 ++++++++++++-----------
 src/transpiling/transforms.rs | 10 +++++-----
 5 files changed, 25 insertions(+), 23 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 571243e..1938cf0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1244,6 +1244,7 @@ dependencies = [
  "new_debug_unreachable",
  "num-bigint",
  "once_cell",
+ "parking_lot",
  "rustc-hash 2.1.1",
  "serde",
  "siphasher",
diff --git a/Cargo.toml b/Cargo.toml
index e309035..abc84c3 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -14,6 +14,7 @@ all-features = true
 
 [features]
 bundler = ["swc_bundler", "swc_ecma_transforms_optimization", "swc_graph_analyzer"]
+concurrent = ["swc_common/concurrent"]
 cjs = ["utils", "visit"]
 codegen = ["swc_ecma_codegen", "swc_ecma_codegen_macros", "swc_macros_common"]
 compat = ["transforms", "swc_ecma_transforms_compat", "swc_trace_macro", "swc_config", "swc_config_macro"]
diff --git a/src/source_map.rs b/src/source_map.rs
index 1cd4073..60e8929 100644
--- a/src/source_map.rs
+++ b/src/source_map.rs
@@ -1,7 +1,6 @@
 // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
 
-use std::rc::Rc;
-
+use crate::swc::common::sync::Lrc;
 use crate::swc::common::FileName;
 use crate::swc::common::SourceFile;
 use crate::ModuleSpecifier;
@@ -25,20 +24,20 @@ impl IntoSwcFileName for String {
 
 #[derive(Clone, Default)]
 pub struct SourceMap {
-  inner: Rc<crate::swc::common::SourceMap>,
+  inner: Lrc<crate::swc::common::SourceMap>,
 }
 
 impl SourceMap {
   pub fn single(file_name: impl IntoSwcFileName, source: String) -> Self {
     let map = Self::default();
     map.inner.new_source_file(
-      Rc::new(IntoSwcFileName::into_file_name(file_name)),
+      Lrc::new(IntoSwcFileName::into_file_name(file_name)),
       source,
     );
     map
   }
 
-  pub fn inner(&self) -> &Rc<crate::swc::common::SourceMap> {
+  pub fn inner(&self) -> &Lrc<crate::swc::common::SourceMap> {
     &self.inner
   }
 
@@ -46,9 +45,9 @@ impl SourceMap {
     &self,
     file_name: impl IntoSwcFileName,
     source: String,
-  ) -> Rc<SourceFile> {
+  ) -> Lrc<SourceFile> {
     self.inner.new_source_file(
-      Rc::new(IntoSwcFileName::into_file_name(file_name)),
+      Lrc::new(IntoSwcFileName::into_file_name(file_name)),
       source,
     )
   }
diff --git a/src/transpiling/mod.rs b/src/transpiling/mod.rs
index e968869..3281d92 100644
--- a/src/transpiling/mod.rs
+++ b/src/transpiling/mod.rs
@@ -1,7 +1,6 @@
 // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
 
 use std::borrow::Cow;
-use std::rc::Rc;
 use std::sync::Arc;
 
 use deno_media_type::MediaType;
@@ -14,6 +13,8 @@ use crate::emit;
 use crate::swc::ast::Program;
 use crate::swc::common::comments::SingleThreadedComments;
 use crate::swc::common::errors::Diagnostic as SwcDiagnostic;
+use crate::swc::common::sync::Lock;
+use crate::swc::common::sync::Lrc;
 use crate::swc::ecma_visit::visit_mut_pass;
 use crate::swc::parser::error::SyntaxError;
 use crate::swc::transforms::fixer;
@@ -39,7 +40,6 @@ use crate::ProgramRef;
 use crate::SourceMap;
 
 use deno_error::JsError;
-use std::cell::RefCell;
 
 mod jsx_precompile;
 mod transforms;
@@ -53,7 +53,7 @@ pub enum TranspileResult {
   ///
   /// This is a performance issue and you should strive to get an `Owned` result.
   Cloned(EmittedSourceText),
-  /// The emit occured consuming the `ParsedSource` without cloning.
+  /// The emit occurred consuming the `ParsedSource` without cloning.
   Owned(EmittedSourceText),
 }
 
@@ -174,8 +174,8 @@ impl Default for TranspileOptions {
 impl TranspileOptions {
   fn as_tsx_config(&self) -> typescript::TsxConfig {
     typescript::TsxConfig {
-      pragma: Some(Rc::new(self.jsx_factory.clone())),
-      pragma_frag: Some(Rc::new(self.jsx_fragment_factory.clone())),
+      pragma: Some(Lrc::new(self.jsx_factory.clone())),
+      pragma_frag: Some(Lrc::new(self.jsx_fragment_factory.clone())),
     }
   }
 
@@ -196,7 +196,7 @@ impl TranspileOptions {
       },
       // no need for this to be false because we treat all files as modules
       no_empty_export: true,
-      // we don't suport this, so leave it as-is so it errors in v8
+      // we don't support this, so leave it as-is so it errors in v8
       import_export_assign_config:
         typescript::TsImportExportAssignConfig::Preserve,
       // Do not opt into swc's optimization to inline enum member values
@@ -619,7 +619,7 @@ fn convert_script_module_to_swc_script(
 
 #[derive(Default, Clone)]
 struct DiagnosticCollector {
-  diagnostics_cell: Rc<RefCell<Vec<SwcDiagnostic>>>,
+  diagnostics: Lrc<Lock<Vec<SwcDiagnostic>>>,
 }
 
 impl DiagnosticCollector {
@@ -635,7 +635,8 @@ impl DiagnosticCollector {
 impl crate::swc::common::errors::Emitter for DiagnosticCollector {
   fn emit(&mut self, db: &crate::swc::common::errors::DiagnosticBuilder<'_>) {
     use std::ops::Deref;
-    self.diagnostics_cell.borrow_mut().push(db.deref().clone());
+    let mut diagnostics = self.diagnostics.lock();
+    diagnostics.push(db.deref().clone());
   }
 }
 
@@ -720,8 +721,8 @@ pub fn fold_program<'a>(
         Some(comments),
         #[allow(deprecated)]
         react::Options {
-          pragma: Some(Rc::new(options.jsx_factory.clone())),
-          pragma_frag: Some(Rc::new(options.jsx_fragment_factory.clone())),
+          pragma: Some(Lrc::new(options.jsx_factory.clone())),
+          pragma_frag: Some(Lrc::new(options.jsx_fragment_factory.clone())),
           // This will use `Object.assign()` instead of the `_extends` helper
           // when spreading props (Note: this property is deprecated)
           use_builtins: Some(true),
@@ -755,7 +756,7 @@ pub fn fold_program<'a>(
   );
 
   let emitter = DiagnosticCollector::default();
-  let diagnostics_cell = emitter.diagnostics_cell.clone();
+  let diagnostics_cell = emitter.diagnostics.clone();
   let handler = emitter.into_handler();
   let result = crate::swc::common::errors::HANDLER.set(&handler, || {
     helpers::HELPERS
diff --git a/src/transpiling/transforms.rs b/src/transpiling/transforms.rs
index 23b0b1b..adf3c52 100644
--- a/src/transpiling/transforms.rs
+++ b/src/transpiling/transforms.rs
@@ -288,6 +288,7 @@ mod test {
   use crate::swc::ast::Module;
   use crate::swc::codegen::text_writer::JsWriter;
   use crate::swc::codegen::Node;
+  use crate::swc::common::sync::Lrc;
   use crate::swc::common::FileName;
   use crate::swc::common::SourceMap;
   use crate::swc::ecma_visit::Fold;
@@ -298,7 +299,6 @@ mod test {
   use crate::swc::parser::TsSyntax;
   use crate::ModuleSpecifier;
   use pretty_assertions::assert_eq;
-  use std::rc::Rc;
 
   use super::*;
 
@@ -498,10 +498,10 @@ mod test {
     assert_eq!(output, format!("{}\n", expected_output));
   }
 
-  fn parse(src: &str) -> (Rc<SourceMap>, Module) {
-    let source_map = Rc::new(SourceMap::default());
+  fn parse(src: &str) -> (Lrc<SourceMap>, Module) {
+    let source_map = Lrc::new(SourceMap::default());
     let source_file = source_map.new_source_file(
-      Rc::new(FileName::Url(
+      Lrc::new(FileName::Url(
         ModuleSpecifier::parse("file:///test.ts").unwrap(),
       )),
       src.to_string(),
@@ -514,7 +514,7 @@ mod test {
     (source_map, parser.parse_module().unwrap())
   }
 
-  fn print(source_map: Rc<SourceMap>, module: Module) -> String {
+  fn print(source_map: Lrc<SourceMap>, module: Module) -> String {
     let mut buf = vec![];
     {
       let mut writer =