diff --git a/Cargo.lock b/Cargo.lock index 0b3a7b6b8..5a05ecad2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -715,6 +715,28 @@ dependencies = [ "allocator-api2", ] +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytemuck" version = "1.18.0" @@ -1178,12 +1200,6 @@ dependencies = [ "syn 2.0.82", ] -[[package]] -name = "cty" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35" - [[package]] name = "darling" version = "0.14.4" @@ -2664,6 +2680,16 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "libmimalloc-sys" +version = "0.1.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "libredox" version = "0.0.2" @@ -2776,11 +2802,11 @@ dependencies = [ "indexmap 2.5.0", "indicatif", "insta", + "libloading 0.8.5", "maplit", "md5", "mdxjs", "miette 5.10.0", - "mimalloc-rust", "mime_guess", "nanoid", "notify", @@ -2792,8 +2818,10 @@ dependencies = [ "pathdiff", "percent-encoding", "petgraph", + "proc-macro2", "puffin", "puffin_egui", + "quote", "rayon", "regex", "sailfish", @@ -2806,9 +2834,10 @@ dependencies = [ "swc_core 0.101.7", "swc_emotion", "swc_error_reporters 0.21.0", + "swc_malloc", "swc_node_comments", + "syn 2.0.82", "thiserror", - "tikv-jemallocator", "tokio", "tokio-tungstenite", "toml 0.7.8", @@ -2826,14 +2855,22 @@ dependencies = [ "anyhow", "cached", "mako", - "mimalloc-rust", "napi", "napi-build", "napi-derive", "oneshot", "serde", "serde_json", - "tikv-jemallocator", + "swc_malloc", +] + +[[package]] +name = "mako_plugin_macro" +version = "0.0.1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", ] [[package]] @@ -2985,23 +3022,12 @@ dependencies = [ ] [[package]] -name = "mimalloc-rust" -version = "0.2.1" +name = "mimalloc" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb726c8298efb4010b2c46d8050e4be36cf807b9d9e98cb112f830914fc9bbe" +checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" dependencies = [ - "cty", - "mimalloc-rust-sys", -] - -[[package]] -name = "mimalloc-rust-sys" -version = "1.7.9-source" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6413e13241a9809f291568133eca6694572cf528c1a6175502d090adce5dd5db" -dependencies = [ - "cc", - "cty", + "libmimalloc-sys", ] [[package]] @@ -4177,6 +4203,44 @@ version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + +[[package]] +name = "rkyv" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "ron" version = "0.7.1" @@ -4336,6 +4400,12 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "semver" version = "0.9.0" @@ -4499,6 +4569,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "similar" version = "2.6.0" @@ -4738,7 +4814,7 @@ dependencies = [ "serde", "swc_core 0.101.7", "swc_xml", - "testing", + "testing 0.38.1", "thiserror", ] @@ -4811,8 +4887,10 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb6567e4e67485b3e7662b486f1565bdae54bd5b9d6b16b2ba1a9babb1e42125" dependencies = [ + "bytecheck", "hstr", "once_cell", + "rkyv", "rustc-hash", "serde", ] @@ -4896,8 +4974,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "12d0a8eaaf1606c9207077d75828008cb2dfb51b095a766bd2b72ef893576e31" dependencies = [ "ahash 0.8.11", + "anyhow", "ast_node", "better_scoped_tls", + "bytecheck", "cfg-if", "either", "from_variant", @@ -4905,6 +4985,7 @@ dependencies = [ "num-bigint", "once_cell", "parking_lot", + "rkyv", "rustc-hash", "serde", "siphasher", @@ -4978,6 +5059,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24fd64b47f1da39ff3c229b7a3f4fb4d9542e21b245ac77220a4b2ad1f455065" dependencies = [ + "once_cell", "swc", "swc_allocator", "swc_atoms", @@ -5005,9 +5087,13 @@ dependencies = [ "swc_ecma_transforms_optimization", "swc_ecma_transforms_proposal", "swc_ecma_transforms_react", + "swc_ecma_transforms_testing", "swc_ecma_transforms_typescript", "swc_ecma_utils", "swc_ecma_visit", + "swc_plugin", + "swc_plugin_macro", + "swc_plugin_proxy", "vergen 8.3.2", ] @@ -5181,9 +5267,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6f866d12e4d519052b92a0a86d1ac7ff17570da1272ca0c89b3d6f802cd79df" dependencies = [ "bitflags 2.6.0", + "bytecheck", "is-macro", "num-bigint", "phf", + "rkyv", "scoped-tls", "serde", "string_enum", @@ -5573,6 +5661,19 @@ dependencies = [ "syn 2.0.82", ] +[[package]] +name = "swc_ecma_testing" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "945faa325af9833b2541d3b0b4e614812677480c2b763c6c6e8c2a42a133b906" +dependencies = [ + "anyhow", + "hex", + "sha2", + "testing 0.39.0", + "tracing", +] + [[package]] name = "swc_ecma_transforms" version = "0.238.0" @@ -5799,6 +5900,32 @@ dependencies = [ "swc_ecma_visit", ] +[[package]] +name = "swc_ecma_transforms_testing" +version = "0.147.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b262ae285569998385b80ba0457a5cacce0208e6e7a3d7ee7dabc939231b0842" +dependencies = [ + "ansi_term", + "anyhow", + "base64 0.21.7", + "hex", + "serde", + "serde_json", + "sha2", + "sourcemap", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_ecma_codegen", + "swc_ecma_parser", + "swc_ecma_testing", + "swc_ecma_transforms_base 0.144.0", + "swc_ecma_utils", + "swc_ecma_visit", + "tempfile", + "testing 0.39.0", +] + [[package]] name = "swc_ecma_transforms_typescript" version = "0.197.4" @@ -5966,6 +6093,16 @@ dependencies = [ "syn 2.0.82", ] +[[package]] +name = "swc_malloc" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d8138c463d4f42313fa157039fbd69329f1432794676271d6f3e34d6833ab4" +dependencies = [ + "mimalloc", + "tikv-jemallocator", +] + [[package]] name = "swc_node_comments" version = "0.24.0" @@ -5977,6 +6114,40 @@ dependencies = [ "swc_common 0.37.5", ] +[[package]] +name = "swc_plugin" +version = "0.90.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b059b8bb5b74cc5fc54559e8de09195fbddd20f4bb363b176b741993ef4894a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "swc_plugin_macro" +version = "0.9.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3232db481484070637b20a155c064096c0ea1ba04fa2247b89b618661b3574f4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "swc_plugin_proxy" +version = "0.47.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07548e19126fbc58b16237e2c8b0075f037774dfdd691fe4c558ba898cfe784b" +dependencies = [ + "better_scoped_tls", + "rkyv", + "swc_common 0.37.5", + "swc_ecma_ast", + "swc_trace_macro", + "tracing", +] + [[package]] name = "swc_timer" version = "0.25.0" @@ -6188,6 +6359,27 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "testing" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3105e9569b7f674d1107d19494c993aafd19ea51f7a558b96b267b49c9b5f2bf" +dependencies = [ + "ansi_term", + "cargo_metadata", + "difference", + "once_cell", + "pretty_assertions", + "regex", + "serde", + "serde_json", + "swc_common 0.37.5", + "swc_error_reporters 0.21.0", + "testing_macros", + "tracing", + "tracing-subscriber", +] + [[package]] name = "testing_macros" version = "0.2.14" diff --git a/Cargo.toml b/Cargo.toml index ca5e68a18..c4cf2a99f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,12 +6,12 @@ resolver = "2" anyhow = "1.0.71" cached = "0.46.1" clap = "4.3.11" -mimalloc-rust = { version = "=0.2.1" } oneshot = "0.1.8" regex = "1.9.3" serde = "1.0.211" serde_json = "1.0.132" swc_core = { version = "0.101.4", default-features = false } +swc_malloc = "1.0.0" tikv-jemallocator = { version = "=0.5.4", features = ["disable_initial_exec_tls"] } [profile.release] diff --git a/crates/binding/Cargo.toml b/crates/binding/Cargo.toml index dfa62c088..824eed516 100644 --- a/crates/binding/Cargo.toml +++ b/crates/binding/Cargo.toml @@ -15,12 +15,7 @@ napi-derive = "2.16.12" oneshot = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } - -[target.'cfg(not(target_os = "linux"))'.dependencies] -mimalloc-rust = { workspace = true } - -[target.'cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86_64", target_arch = "aarch64")))'.dependencies] -tikv-jemallocator = { workspace = true } +swc_malloc = { workspace = true } [build-dependencies] napi-build = "2.0.1" diff --git a/crates/binding/src/lib.rs b/crates/binding/src/lib.rs index 39c039d13..9fc1962ee 100644 --- a/crates/binding/src/lib.rs +++ b/crates/binding/src/lib.rs @@ -1,5 +1,7 @@ #![deny(clippy::all)] +extern crate swc_malloc; + use std::sync::{Arc, Once}; use js_hook::{JsHooks, TsFnHooks}; @@ -18,18 +20,6 @@ mod js_hook; mod js_plugin; mod threadsafe_function; -#[cfg(not(target_os = "linux"))] -#[global_allocator] -static GLOBAL: mimalloc_rust::GlobalMiMalloc = mimalloc_rust::GlobalMiMalloc; - -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any(target_arch = "x86_64", target_arch = "aarch64") -))] -#[global_allocator] -static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; - static LOG_INIT: Once = Once::new(); #[napi(object)] @@ -165,6 +155,7 @@ pub struct BuildParams { }; experimental?: { webpackSyntaxValidate?: string[]; + rustPlugins?: Array<[string, any]>; }; watch?: { ignoredPaths?: string[]; diff --git a/crates/mako/Cargo.toml b/crates/mako/Cargo.toml index 4c0cc4cc2..21361681c 100644 --- a/crates/mako/Cargo.toml +++ b/crates/mako/Cargo.toml @@ -26,6 +26,7 @@ oxc_resolver = { version = "=1.7.0", features = ["package_json_raw_json_api" percent-encoding = { version = "2.3.1" } serde = { workspace = true } serde_json = { workspace = true } +swc_malloc = { workspace = true } url = { version = "2.5.0" } swc_core = { workspace = true, features = [ @@ -47,6 +48,7 @@ swc_core = { workspace = true, features = [ "ecma_minifier", "ecma_minifier_concurrent", "ecma_parser", + "ecma_plugin_transform", "ecma_preset_env", "ecma_quote", "ecma_transforms_compat", @@ -57,10 +59,11 @@ swc_core = { workspace = true, features = [ "ecma_transforms_typescript", "ecma_utils", "ecma_visit_path", + "swc_common", "swc_ecma_quote_macros", ] } -swc_emotion = "0.72.19" +swc_emotion = "=0.72.22" swc_error_reporters = "0.21.0" swc_node_comments = "0.24.0" @@ -81,6 +84,7 @@ hyper-staticfile = "0.9.6" hyper-tungstenite = "0.10.0" indexmap = "2.0.0" indicatif = "0.17.8" +libloading = "0.8" md5 = "0.7.0" mdxjs = "0.2.6" mime_guess = "2.0.4" @@ -90,8 +94,10 @@ parking_lot = { version = "0.12", features = ["nightly"] } path-clean = "1.0.1" pathdiff = "0.2.1" petgraph = "0.6.3" +proc-macro2 = "1" puffin = { version = "0.16.0", optional = true } puffin_egui = { version = "0.22.0", optional = true } +quote = "1" rayon = "1.7.0" regex = { workspace = true } sailfish = "0.8.3" @@ -99,6 +105,7 @@ semver = "1.0.23" serde-xml-rs = "0.6.0" serde_yaml = "0.9.22" svgr-rs = { path = "../svgr-rs" } +syn = { version = "2", features = ["full"] } thiserror = "1.0.43" tokio = { version = "1", features = ["rt-multi-thread", "sync"] } tokio-tungstenite = "0.19.0" @@ -108,12 +115,6 @@ tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } tungstenite = "0.19.0" twox-hash = "1.6.3" -[target.'cfg(not(target_os = "linux"))'.dependencies] -mimalloc-rust = { workspace = true } - -[target.'cfg(all(target_os = "linux", target_env = "gnu", any(target_arch = "x86_64", target_arch = "aarch64")))'.dependencies] -tikv-jemallocator = { workspace = true } - [dev-dependencies] insta = { version = "1.30.0", features = ["yaml"] } maplit = "1.0.2" diff --git a/crates/mako/src/ast.rs b/crates/mako/src/ast.rs index e131721a9..33dbf6918 100644 --- a/crates/mako/src/ast.rs +++ b/crates/mako/src/ast.rs @@ -8,6 +8,6 @@ pub(crate) mod js_ast; pub(crate) mod sourcemap; #[cfg(test)] pub mod tests; -pub(crate) mod utils; +pub mod utils; pub const DUMMY_CTXT: SyntaxContext = SyntaxContext::empty(); diff --git a/crates/mako/src/compiler.rs b/crates/mako/src/compiler.rs index fc124a87e..48a113920 100644 --- a/crates/mako/src/compiler.rs +++ b/crates/mako/src/compiler.rs @@ -6,6 +6,7 @@ use std::time::Instant; use anyhow::{anyhow, Error, Result}; use colored::Colorize; +use libloading::Library; use regex::Regex; use swc_core::common::sync::Lrc; use swc_core::common::{Globals, SourceMap, DUMMY_SP}; @@ -220,7 +221,7 @@ pub struct Compiler { impl Compiler { pub fn new( - config: Config, + mut config: Config, root: PathBuf, args: Args, extra_plugins: Option>>, @@ -238,6 +239,19 @@ impl Compiler { if let Some(extra_plugins) = extra_plugins { plugins.extend(extra_plugins); } + + let mut external_plugins: Vec> = vec![]; + unsafe { + for rust_plugin in config.experimental.rust_plugins.clone() { + let lib = Arc::new(Library::new(rust_plugin.path)?); + let plugin_create_fn: libloading::Symbol< + unsafe extern "C" fn(option: String) -> Arc, + > = lib.get(b"_plugin_create").unwrap(); + let plugin = plugin_create_fn(rust_plugin.options); + external_plugins.push(plugin); + } + } + let builtin_plugins: Vec> = vec![ // features Arc::new(plugins::manifest::ManifestPlugin {}), @@ -254,10 +268,9 @@ impl Compiler { Arc::new(plugins::tree_shaking::FarmTreeShake {}), Arc::new(plugins::detect_circular_dependence::LoopDetector {}), ]; + plugins.extend(external_plugins); plugins.extend(builtin_plugins); - let mut config = config; - if let Some(progress) = &config.progress { plugins.push(Arc::new(plugins::progress::ProgressPlugin::new( plugins::progress::ProgressPluginOptions { @@ -480,7 +493,6 @@ impl Compiler { let mg = self.context.module_graph.read().unwrap(); cg.full_hash(&mg) } - fn clean_dist(&self) -> Result<()> { // compiler 前清除 dist,如果后续 dev 环境不在 output_path 里,需要再补上 dev 的逻辑 let output_path = &self.context.config.output.path; diff --git a/crates/mako/src/config.rs b/crates/mako/src/config.rs index 1dbc8c3ef..5c3727193 100644 --- a/crates/mako/src/config.rs +++ b/crates/mako/src/config.rs @@ -66,7 +66,7 @@ pub use resolve::ResolveConfig; pub use rsc_client::{deserialize_rsc_client, LogServerComponent, RscClientConfig}; pub use rsc_server::{deserialize_rsc_server, RscServerConfig}; use serde::{Deserialize, Serialize}; -use serde_json::Value; +use serde_json::{json, Value}; pub use stats::{deserialize_stats, StatsConfig}; use thiserror::Error; pub use transform_import::{TransformImportConfig, TransformImportStyle}; @@ -232,14 +232,27 @@ impl Config { ) -> Result { let abs_config_file = root.join(CONFIG_FILE); let abs_config_file = abs_config_file.to_str().unwrap(); + let mut overrides_json: Option = None; let c = config::Config::builder(); // default config let c = c.add_source(config::File::from_str( DEFAULT_CONFIG, config::FileFormat::Json5, )); + // default config from args let c = if let Some(default_config) = default_config { + let result: Result = serde_json::from_str(default_config); + if let Ok(config) = result { + if let Some(experimental) = config.get("experimental") { + overrides_json = Some( + serde_json::to_string(&json!({ + "experimental": experimental + })) + .unwrap(), + ); + } + }; c.add_source(config::File::from_str( default_config, config::FileFormat::Json5, @@ -260,6 +273,15 @@ impl Config { } else { c }; + // overrides config + let c = if let Some(overrides) = overrides_json { + c.add_source(config::File::from_str( + overrides.as_str(), + config::FileFormat::Json5, + )) + } else { + c + }; let c = c.build()?; let mut ret = c.try_deserialize::(); diff --git a/crates/mako/src/config/experimental.rs b/crates/mako/src/config/experimental.rs index 1c86ec1cc..3c5763424 100644 --- a/crates/mako/src/config/experimental.rs +++ b/crates/mako/src/config/experimental.rs @@ -2,6 +2,12 @@ use serde::{Deserialize, Serialize}; use crate::create_deserialize_fn; +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct RustPlugin { + pub path: String, + pub options: String, +} + #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct ExperimentalConfig { @@ -12,6 +18,7 @@ pub struct ExperimentalConfig { pub magic_comment: bool, #[serde(deserialize_with = "deserialize_detect_loop")] pub detect_circular_dependence: Option, + pub rust_plugins: Vec, pub central_ensure: bool, } diff --git a/crates/mako/src/config/mako.config.default.json b/crates/mako/src/config/mako.config.default.json index be971fdbb..3af045455 100644 --- a/crates/mako/src/config/mako.config.default.json +++ b/crates/mako/src/config/mako.config.default.json @@ -66,6 +66,7 @@ "rscClient": false, "experimental": { "webpackSyntaxValidate": [], + "rustPlugins": [], "requireContext": true, "ignoreNonLiteralRequire": false, "magicComment": true, diff --git a/crates/mako/src/lib.rs b/crates/mako/src/lib.rs index 5bc0ede9a..3bebd29c7 100644 --- a/crates/mako/src/lib.rs +++ b/crates/mako/src/lib.rs @@ -10,7 +10,7 @@ pub mod config; pub mod dev; mod features; mod generate; -mod module; +pub mod module; mod module_graph; pub mod plugin; mod plugins; @@ -20,6 +20,8 @@ pub mod stats; pub mod utils; mod visitors; +pub use {swc_core, swc_malloc}; + #[macro_export] macro_rules! mako_profile_scope { ($id:expr) => { diff --git a/crates/mako/src/main.rs b/crates/mako/src/main.rs index 5663333e6..cfc740591 100644 --- a/crates/mako/src/main.rs +++ b/crates/mako/src/main.rs @@ -1,6 +1,8 @@ #![feature(box_patterns)] #![feature(let_chains)] +extern crate swc_malloc; + use std::sync::Arc; use anyhow::{anyhow, Result}; @@ -15,18 +17,6 @@ use mako::utils::tokio_runtime; use mako::{cli, config}; use tracing::debug; -#[cfg(not(target_os = "linux"))] -#[global_allocator] -static GLOBAL: mimalloc_rust::GlobalMiMalloc = mimalloc_rust::GlobalMiMalloc; - -#[cfg(all( - target_os = "linux", - target_env = "gnu", - any(target_arch = "x86_64", target_arch = "aarch64") -))] -#[global_allocator] -static GLOBAL: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc; - fn main() -> Result<()> { let fut = async { run().await }; diff --git a/crates/mako_plugin_macro/Cargo.toml b/crates/mako_plugin_macro/Cargo.toml new file mode 100644 index 000000000..f9c07303a --- /dev/null +++ b/crates/mako_plugin_macro/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "mako_plugin_macro" +version = "0.0.1" +edition = "2021" +license = "MIT" + +[dependencies] +proc-macro2 = "1" +quote = "1" +syn = { version = "2", features = ["full"] } + +[lib] +proc-macro = true diff --git a/crates/mako_plugin_macro/src/lib.rs b/crates/mako_plugin_macro/src/lib.rs new file mode 100644 index 000000000..53dd4a414 --- /dev/null +++ b/crates/mako_plugin_macro/src/lib.rs @@ -0,0 +1,68 @@ +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use quote::{quote, ToTokens}; +use syn::{parse2, parse_quote, DeriveInput, FnArg, ImplItem, ImplItemFn, ItemImpl, Pat, PatType}; + +#[proc_macro_derive(mako_plugin)] +pub fn mako_plugin(input: TokenStream) -> TokenStream { + handler_create(input.into()).into() +} + +fn handler_create(input: TokenStream2) -> TokenStream2 { + let ast = parse2::(input).unwrap(); + let struct_name = &ast.ident; + let ts = quote! { + #[no_mangle] + pub fn _plugin_create(option: std::string::String) -> std::sync::Arc { + std::sync::Arc::new(#struct_name::new(option)) + } + }; + ts +} + +#[proc_macro_attribute] +pub fn with_local(_attr: TokenStream, item: TokenStream) -> TokenStream { + handle_local(_attr.into(), item.into()).into() +} + +fn handle_local(_attr: TokenStream2, item: TokenStream2) -> TokenStream2 { + let ast = parse2::(item).unwrap(); + let items = &ast.items; + let mut expand_items: Vec = vec![]; + + items.iter().for_each(|impl_item| { + if let ImplItem::Fn(f) = impl_item { + let body = &f.block; + let mut inputs = f.sig.inputs.clone().into_iter(); + let has_context = inputs.any(|f| { + if let FnArg::Typed(PatType { pat, .. }) = f { + if let Pat::Ident(i) = *pat { + i.ident.to_string().contains("context") + } else { + false + } + } else { + false + } + }); + let block = if has_context { + parse_quote!({ + mako::swc_core::common::GLOBALS.set(&context.meta.script.globals, || + #body + ) + }) + } else { + parse_quote!( + #body + ) + }; + + expand_items.push(ImplItem::Fn(ImplItemFn { block, ..f.clone() })); + } + }); + let a = ItemImpl { + items: expand_items, + ..ast + }; + a.into_token_stream() +} diff --git a/packages/bundler-mako/index.js b/packages/bundler-mako/index.js index 04974f9b7..ec5853080 100644 --- a/packages/bundler-mako/index.js +++ b/packages/bundler-mako/index.js @@ -662,6 +662,7 @@ async function getMakoConfig(opts) { experimental: { webpackSyntaxValidate: [], requireContext: true, + rustPlugins: [], detectCircularDependence: { ignores: ['node_modules', '\\.umi'], graphviz: false, diff --git a/packages/mako/binding.d.ts b/packages/mako/binding.d.ts index fa889880d..eb1884ce8 100644 --- a/packages/mako/binding.d.ts +++ b/packages/mako/binding.d.ts @@ -255,6 +255,7 @@ export interface BuildParams { }; experimental?: { webpackSyntaxValidate?: string[]; + rustPlugins?: Array<[string, any]>; }; watch?: { ignoredPaths?: string[]; diff --git a/packages/mako/src/binding.d.ts b/packages/mako/src/binding.d.ts index b99643f94..5928a01ab 100644 --- a/packages/mako/src/binding.d.ts +++ b/packages/mako/src/binding.d.ts @@ -235,6 +235,7 @@ export interface BuildParams { }; experimental?: { webpackSyntaxValidate?: string[]; + rustPlugins?: Array<[string, any]>; }; watch?: { ignoredPaths?: string[]; diff --git a/packages/mako/src/index.ts b/packages/mako/src/index.ts index 34c770dbe..de9d1e1ae 100644 --- a/packages/mako/src/index.ts +++ b/packages/mako/src/index.ts @@ -6,6 +6,7 @@ import { type Options } from 'sass'; import * as binding from '../binding'; import { ForkTSChecker as ForkTSChecker } from './forkTSChecker'; import { LessLoaderOpts, lessLoader } from './lessLoader'; +import { rustPluginResolver } from './rustPlugins'; import { sassLoader } from './sassLoader'; type Config = binding.BuildParams['config'] & { @@ -43,6 +44,12 @@ export async function build(params: BuildParams) { params.config.plugins = params.config.plugins || []; params.config.resolve = params.config.resolve || {}; + const rustPlugins = params.config.experimental?.rustPlugins; + if (rustPlugins) { + params.config.experimental!.rustPlugins = + await rustPluginResolver(rustPlugins); + } + let makoConfig: any = {}; let makoConfigPath = path.join(params.root, 'mako.config.json'); if (fs.existsSync(makoConfigPath)) { diff --git a/packages/mako/src/rustPlugins/index.ts b/packages/mako/src/rustPlugins/index.ts new file mode 100644 index 000000000..805ee1118 --- /dev/null +++ b/packages/mako/src/rustPlugins/index.ts @@ -0,0 +1,14 @@ +import { pathToFileURL } from 'url'; +export async function rustPluginResolver(plugins: Array<[string, any]>) { + const resolved: Array<[string, any]> = []; + for (const [plugin, options] of plugins) { + let pluginPath = require.resolve(plugin); + if (process.platform === 'win32') { + pluginPath = (await import(pathToFileURL(pluginPath).toString())).default; + } else { + pluginPath = await import(pluginPath).then((m) => m.default); + } + resolved.push([pluginPath, JSON.stringify(options)]); + } + return resolved; +}