Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
245 changes: 219 additions & 26 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
7 changes: 1 addition & 6 deletions crates/binding/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
15 changes: 3 additions & 12 deletions crates/binding/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![deny(clippy::all)]

extern crate swc_malloc;

use std::sync::{Arc, Once};

use js_hook::{JsHooks, TsFnHooks};
Expand All @@ -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)]
Expand Down Expand Up @@ -168,6 +158,7 @@ pub struct BuildParams {
};
experimental?: {
webpackSyntaxValidate?: string[];
rustPlugins?: Array<[string, any]>;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

建议加强类型定义和文档说明

当前的 rustPlugins 类型定义过于宽松:

  1. 使用 any 类型不利于类型安全
  2. 缺少对插件配置结构的文档说明

建议修改为:

- rustPlugins?: Array<[string, any]>;
+ rustPlugins?: Array<{
+   // 插件的路径
+   path: string;
+   // 插件的配置选项
+   options?: {
+     [key: string]: string | number | boolean;
+   };
+ }>;

同时建议添加相关文档说明插件的配置格式和用法。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
rustPlugins?: Array<[string, any]>;
rustPlugins?: Array<{
// 插件的路径
path: string;
// 插件的配置选项
options?: {
[key: string]: string | number | boolean;
};
}>;

};
watch?: {
ignoredPaths?: string[];
Expand Down
15 changes: 8 additions & 7 deletions crates/mako/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand All @@ -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",
Expand All @@ -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"

Expand All @@ -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"
Expand All @@ -90,15 +94,18 @@ 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"
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"
Expand All @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion crates/mako/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
17 changes: 16 additions & 1 deletion crates/mako/src/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ use std::time::Instant;

use anyhow::{anyhow, Error, Result};
use colored::Colorize;
use libloading::Library;
use regex::Regex;
use serde_json::Value;
use swc_core::common::sync::Lrc;
use swc_core::common::{Globals, SourceMap, DUMMY_SP};
use swc_core::ecma::ast::Ident;
Expand Down Expand Up @@ -238,6 +240,19 @@ impl Compiler {
if let Some(extra_plugins) = extra_plugins {
plugins.extend(extra_plugins);
}

let mut external_plugins: Vec<Arc<dyn Plugin>> = 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: Value) -> Arc<dyn Plugin>,
> = lib.get(b"_plugin_create").unwrap();
let plugin = plugin_create_fn(rust_plugin.options);
external_plugins.push(plugin);
}
}

let builtin_plugins: Vec<Arc<dyn Plugin>> = vec![
// features
Arc::new(plugins::manifest::ManifestPlugin {}),
Expand All @@ -254,6 +269,7 @@ 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;
Expand Down Expand Up @@ -488,7 +504,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;
Expand Down
22 changes: 21 additions & 1 deletion crates/mako/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -75,6 +75,7 @@ pub use umd::{deserialize_umd, Umd};
pub use watch::WatchConfig;

use crate::build::load::JS_EXTENSIONS;
use crate::config::experimental::RustPlugin;
use crate::features::node::Node;

#[derive(Debug, Diagnostic)]
Expand Down Expand Up @@ -236,14 +237,25 @@ impl Config {
) -> Result<Self> {
let abs_config_file = root.join(CONFIG_FILE);
let abs_config_file = abs_config_file.to_str().unwrap();
let mut overrides_json: Option<Value> = 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<Value, serde_json::Error> = serde_json::from_str(default_config);
if let Ok(config) = result {
if let Some(rust_plugins) = config
.get("experimental")
.and_then(|experimental| experimental.get("rustPlugins"))
{
overrides_json = Some(json!({ "rust_plugins": rust_plugins }));
}
};
Comment on lines +250 to +258
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

需要改进配置解析的健壮性

当前实现存在以下问题:

  1. 使用unwrap()直接访问JSON数据,缺少错误处理
  2. 缺少对rust_plugins配置结构的验证
  3. 缺少实验性功能的文档说明

建议修改为:

- if let Ok(config) = result {
-     if let Some(rust_plugins) = config
-         .get("experimental")
-         .and_then(|experimental| experimental.get("rustPlugins"))
-     {
-         overrides_json = Some(json!({ "rust_plugins": rust_plugins }));
-     }
- };

+ if let Ok(config) = result {
+     if let Some(experimental) = config.get("experimental") {
+         if let Some(rust_plugins) = experimental.get("rustPlugins") {
+             // 验证rust_plugins的结构
+             if !rust_plugins.is_array() {
+                 return Err(anyhow!("rustPlugins must be an array"));
+             }
+             
+             // 验证每个插件的配置
+             for plugin in rust_plugins.as_array().unwrap() {
+                 if !plugin.is_object() 
+                     || plugin.get("path").is_none() 
+                     || !plugin.get("path").unwrap().is_string() {
+                     return Err(anyhow!("Invalid plugin configuration"));
+                 }
+             }
+             
+             overrides_json = Some(json!({ "rust_plugins": rust_plugins }));
+         }
+     }
+ };

另外建议添加以下文档:

/// 实验性功能:Rust原生插件支持
/// 
/// # 配置示例
/// ```json
/// {
///   "experimental": {
///     "rustPlugins": [
///       {
///         "path": "./plugins/my-plugin.so",
///         "options": { ... }
///       }
///     ]
///   }
/// }
/// ```

Also applies to: 283-287

c.add_source(config::File::from_str(
default_config,
config::FileFormat::Json5,
Expand All @@ -269,6 +281,14 @@ impl Config {
let mut ret = c.try_deserialize::<Config>();
// normalize & check
if let Ok(config) = &mut ret {
// overrides config

if let Some(overrides) = overrides_json {
let rust_plugins: Vec<RustPlugin> =
serde_json::from_value(overrides.get("rust_plugins").unwrap().clone())?;
config.experimental.rust_plugins = rust_plugins;
}

// normalize output
if config.output.path.is_relative() {
config.output.path = root.join(config.output.path.to_string_lossy().to_string());
Expand Down
8 changes: 8 additions & 0 deletions crates/mako/src/config/experimental.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
use serde::{Deserialize, Serialize};
use serde_json::Value;

use crate::create_deserialize_fn;

#[derive(Deserialize, Serialize, Debug, Clone)]
pub struct RustPlugin {
pub path: String,
pub options: Value,
}

#[derive(Deserialize, Serialize, Debug)]
#[serde(rename_all = "camelCase")]
pub struct ExperimentalConfig {
Expand All @@ -12,6 +19,7 @@ pub struct ExperimentalConfig {
pub magic_comment: bool,
#[serde(deserialize_with = "deserialize_detect_loop")]
pub detect_circular_dependence: Option<DetectCircularDependence>,
pub rust_plugins: Vec<RustPlugin>,
pub central_ensure: bool,
pub imports_checker: bool,
}
Expand Down
1 change: 1 addition & 0 deletions crates/mako/src/config/mako.config.default.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
"rscClient": false,
"experimental": {
"webpackSyntaxValidate": [],
"rustPlugins": [],
"requireContext": true,
"ignoreNonLiteralRequire": false,
"magicComment": true,
Expand Down
4 changes: 3 additions & 1 deletion crates/mako/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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) => {
Expand Down
14 changes: 2 additions & 12 deletions crates/mako/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#![feature(box_patterns)]
#![feature(let_chains)]

extern crate swc_malloc;

use std::sync::Arc;

use anyhow::{anyhow, Result};
Expand All @@ -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 };

Expand Down
14 changes: 14 additions & 0 deletions crates/mako_plugin_macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "mako_plugin_macro"
version = "0.0.1"
edition = "2021"
license = "MIT"

[dependencies]
proc-macro2 = "1"
quote = "1"
serde_json = { workspace = true }
syn = { version = "2", features = ["full"] }

[lib]
proc-macro = true
Loading
Loading