feat(config): Add a dedicated cached regex (#3832)

This commit is contained in:
Donny/강동윤 2022-03-04 01:35:41 +09:00 committed by GitHub
parent 39e7f11c17
commit efc67417a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 160 additions and 77 deletions

65
Cargo.lock generated
View File

@ -60,9 +60,9 @@ dependencies = [
[[package]]
name = "anyhow"
version = "1.0.53"
version = "1.0.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94a45b455c14666b85fc40a019e8ab9eb75e3a124e05494f5397122bc9eb06e0"
checksum = "159bb86af3a200e19a068f4224eae4c8bb2d0fa054c7e5d1cacd5cef95e684cd"
[[package]]
name = "arbitrary"
@ -643,6 +643,17 @@ dependencies = [
"num_cpus",
]
[[package]]
name = "dashmap"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0834a35a3fce649144119e18da2a4d8ed12ef3862f47183fd46f625d072d96c"
dependencies = [
"cfg-if 1.0.0",
"num_cpus",
"parking_lot 0.12.0",
]
[[package]]
name = "debug_unreachable"
version = "0.1.1"
@ -1139,7 +1150,7 @@ name = "jsdoc"
version = "0.60.0"
dependencies = [
"anyhow",
"dashmap",
"dashmap 4.0.2",
"nom 5.1.2",
"serde",
"swc_atoms",
@ -1917,7 +1928,7 @@ dependencies = [
"ahash",
"anyhow",
"browserslist-rs",
"dashmap",
"dashmap 4.0.2",
"from_variant",
"once_cell",
"semver 1.0.4",
@ -2459,16 +2470,6 @@ dependencies = [
"serde",
]
[[package]]
name = "serde_regex"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8136f1a4ea815d7eac4101cfd0b16dc0cb5e1fe1b8609dfd728058656b7badf"
dependencies = [
"regex",
"serde",
]
[[package]]
name = "serde_urlencoded"
version = "0.7.0"
@ -2702,7 +2703,7 @@ dependencies = [
"ahash",
"anyhow",
"base64 0.13.0",
"dashmap",
"dashmap 4.0.2",
"either",
"indexmap",
"lru",
@ -2717,6 +2718,7 @@ dependencies = [
"serde_json",
"sourcemap",
"swc_atoms",
"swc_cached",
"swc_common",
"swc_ecma_ast",
"swc_ecma_codegen",
@ -2757,7 +2759,7 @@ dependencies = [
"ahash",
"anyhow",
"crc",
"dashmap",
"dashmap 4.0.2",
"hex",
"indexmap",
"is-macro",
@ -2794,6 +2796,19 @@ dependencies = [
"url",
]
[[package]]
name = "swc_cached"
version = "0.1.0"
dependencies = [
"ahash",
"anyhow",
"dashmap 5.1.0",
"once_cell",
"regex",
"serde",
"swc_atoms",
]
[[package]]
name = "swc_cli"
version = "0.13.0"
@ -3040,7 +3055,7 @@ version = "0.19.1"
dependencies = [
"ahash",
"auto_impl",
"dashmap",
"dashmap 4.0.2",
"parking_lot 0.12.0",
"rayon",
"regex",
@ -3062,15 +3077,15 @@ version = "0.28.0"
dependencies = [
"ahash",
"anyhow",
"dashmap",
"dashmap 4.0.2",
"lru",
"normpath",
"once_cell",
"parking_lot 0.12.0",
"path-clean",
"regex",
"serde",
"serde_json",
"swc_cached",
"swc_common",
"tracing",
]
@ -3092,8 +3107,8 @@ dependencies = [
"retain_mut",
"serde",
"serde_json",
"serde_regex",
"swc_atoms",
"swc_cached",
"swc_common",
"swc_ecma_ast",
"swc_ecma_codegen",
@ -3139,7 +3154,7 @@ version = "0.98.0"
dependencies = [
"ahash",
"anyhow",
"dashmap",
"dashmap 4.0.2",
"indexmap",
"once_cell",
"preset_env_base",
@ -3316,7 +3331,7 @@ name = "swc_ecma_transforms_optimization"
version = "0.94.1"
dependencies = [
"ahash",
"dashmap",
"dashmap 4.0.2",
"indexmap",
"once_cell",
"rayon",
@ -3368,7 +3383,7 @@ version = "0.86.2"
dependencies = [
"ahash",
"base64 0.13.0",
"dashmap",
"dashmap 4.0.2",
"indexmap",
"once_cell",
"regex",
@ -3563,7 +3578,7 @@ name = "swc_node_bundler"
version = "0.0.0"
dependencies = [
"anyhow",
"dashmap",
"dashmap 4.0.2",
"is-macro",
"once_cell",
"pretty_assertions",
@ -3592,7 +3607,7 @@ name = "swc_node_comments"
version = "0.4.0"
dependencies = [
"ahash",
"dashmap",
"dashmap 4.0.2",
"swc_common",
]

View File

@ -40,12 +40,14 @@ either = "1"
indexmap = {version = "1", features = ["serde"]}
lru = "0.7.1"
once_cell = "1.9.0"
parking_lot = "0.12.0"
pathdiff = "0.2.0"
regex = "1"
serde = {version = "1", features = ["derive"]}
serde_json = "1"
sourcemap = "6"
swc_atoms = {version = "0.2", path = "../swc_atoms"}
swc_cached = {version = "0.1.0", path = "../swc_cached"}
swc_common = {version = "0.17.0", path = "../swc_common", features = ["sourcemap", "concurrent", "parking_lot"]}
swc_ecma_ast = {version = "0.68.0", path = "../swc_ecma_ast"}
swc_ecma_codegen = {version = "0.93.0", path = "../swc_ecma_codegen"}
@ -73,7 +75,6 @@ swc_node_comments = {version = "0.4.0", path = "../swc_node_comments"}
swc_plugin_runner = {version = "0.38.0", path = "../swc_plugin_runner", optional = true}
swc_visit = {version = "0.3.0", path = "../swc_visit"}
tracing = "0.1.31"
parking_lot = "0.12.0"
[dependencies.napi-derive]
default-features = false

View File

@ -9,17 +9,17 @@ use std::{
usize,
};
use anyhow::{bail, Context, Error};
use anyhow::{bail, Error};
use dashmap::DashMap;
use either::Either;
use indexmap::IndexMap;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{
de::{Unexpected, Visitor},
Deserialize, Deserializer, Serialize, Serializer,
};
use swc_atoms::JsWord;
use swc_cached::regex::CachedRegex;
pub use swc_common::chain;
use swc_common::{
collections::{AHashMap, AHashSet},
@ -891,34 +891,23 @@ impl Config {
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FileMatcher {
Regex(String),
None,
Regex(CachedRegex),
Multi(Vec<FileMatcher>),
}
impl Default for FileMatcher {
fn default() -> Self {
Self::Regex(String::from(""))
Self::None
}
}
impl FileMatcher {
pub fn matches(&self, filename: &Path) -> Result<bool, Error> {
static CACHE: Lazy<DashMap<String, Regex, ahash::RandomState>> =
Lazy::new(Default::default);
match self {
FileMatcher::Regex(ref s) => {
if s.is_empty() {
return Ok(false);
}
if !CACHE.contains_key(&*s) {
let re = Regex::new(s).with_context(|| format!("invalid regex: {}", s))?;
CACHE.insert(s.clone(), re);
}
let re = CACHE.get(&*s).unwrap();
FileMatcher::None => Ok(false),
FileMatcher::Regex(re) => {
let filename = if cfg!(target_os = "windows") {
filename.to_string_lossy().replace('\\', "/")
} else {

View File

@ -0,0 +1,20 @@
[package]
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
description = "Cached types for swc"
documentation = "https://rustdoc.swc.rs/swc_cached/"
edition = "2021"
include = ["Cargo.toml", "src/**/*.rs"]
license = "Apache-2.0"
name = "swc_cached"
repository = "https://github.com/swc-project/swc.git"
version = "0.1.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ahash = "0.7.6"
anyhow = "1.0.55"
dashmap = "5.1.0"
once_cell = "1.9.0"
regex = "1.5.4"
serde = "1.0.136"
swc_atoms = {version = "0.2.9", path = "../swc_atoms"}

View File

@ -0,0 +1,3 @@
#![deny(warnings)]
pub mod regex;

View File

@ -0,0 +1,72 @@
use std::{ops::Deref, sync::Arc};
use anyhow::{Context, Result};
use dashmap::DashMap;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{de::Error, Deserialize, Serialize};
/// A regex which can be used as a configuration.
///
/// While deserializing, this will be converted to a string and cached based on
/// the pattern.
#[derive(Debug, Clone)]
pub struct CachedRegex {
regex: Arc<Regex>,
}
impl Deref for CachedRegex {
type Target = Regex;
fn deref(&self) -> &Self::Target {
&self.regex
}
}
impl CachedRegex {
pub fn new(input: &str) -> Result<Self> {
static CACHE: Lazy<DashMap<String, Arc<Regex>, ahash::RandomState>> =
Lazy::new(Default::default);
if let Some(cache) = CACHE.get(input).as_deref().cloned() {
return Ok(Self { regex: cache });
}
let regex =
Regex::new(input).with_context(|| format!("failed to parse `{}` as regex", input))?;
let regex = Arc::new(regex);
CACHE.insert(input.to_owned(), regex.clone());
Ok(CachedRegex { regex })
}
}
impl<'de> Deserialize<'de> for CachedRegex {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::new(&s).map_err(|err| D::Error::custom(err.to_string()))
}
}
impl Serialize for CachedRegex {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let s = self.regex.as_str();
serializer.serialize_str(s)
}
}
/// This will panic for wrong patterns.
impl From<&'_ str> for CachedRegex {
fn from(s: &'_ str) -> Self {
Self::new(s).unwrap()
}
}

View File

@ -19,7 +19,7 @@ cache = ["lru", "parking_lot"]
# Enable node js resolver
node = ["normpath", "serde_json", "dashmap", "once_cell", "path-clean"]
# Enable support for `paths` of tsconfig.json
tsc = ["dashmap", "once_cell", "regex"]
tsc = ["dashmap", "once_cell", "swc_cached"]
[dependencies]
ahash = "0.7.4"
@ -29,9 +29,9 @@ lru = {version = "0.7.1", optional = true}
once_cell = {version = "1.9.0", optional = true}
parking_lot = {version = "0.12.0", optional = true}
path-clean = {version = "=0.1.0", optional = true}
regex = {version = "1", optional = true}
serde = {version = "1", features = ["derive"]}
serde_json = {version = "1.0.64", optional = true}
swc_cached = {version = "0.1.0", optional = true, path = "../swc_cached"}
swc_common = {version = "0.17.0", path = "../swc_common"}
tracing = "0.1.31"

View File

@ -1,16 +1,14 @@
use std::path::{Component, PathBuf};
use anyhow::{bail, Context, Error};
use dashmap::DashMap;
use once_cell::sync::Lazy;
use regex::Regex;
use swc_cached::regex::CachedRegex;
use swc_common::FileName;
use crate::resolve::Resolve;
#[derive(Debug)]
enum Pattern {
Regex(Regex),
Regex(CachedRegex),
/// No wildcard.
Exact(String),
}
@ -193,19 +191,6 @@ where
}
}
fn compile_regex(src: String) -> Regex {
static CACHE: Lazy<DashMap<String, Regex, ahash::RandomState>> = Lazy::new(Default::default);
if !CACHE.contains_key(&*src) {
// Create capture group
let regex_pat = src.replace('*', "(.*)");
let re = Regex::new(&regex_pat).unwrap_or_else(|err| {
panic!("failed to compile `{}` as a pattern: {:?}", regex_pat, err)
});
CACHE.insert(src.clone(), re);
}
let re = CACHE.get(&*src).unwrap();
(*re).clone()
fn compile_regex(src: String) -> CachedRegex {
CachedRegex::new(&src.replace('*', "(.*)")).unwrap()
}

View File

@ -28,8 +28,8 @@ regex = "1.5.3"
retain_mut = "0.1.2"
serde = {version = "1.0.118", features = ["derive"]}
serde_json = "1.0.61"
serde_regex = "1.1.0"
swc_atoms = {version = "0.2", path = "../swc_atoms"}
swc_cached = {version = "0.1.0", path = "../swc_cached"}
swc_common = {version = "0.17.0", path = "../swc_common"}
swc_ecma_ast = {version = "0.68.0", path = "../swc_ecma_ast"}
swc_ecma_codegen = {version = "0.93.0", path = "../swc_ecma_codegen"}

View File

@ -1,6 +1,6 @@
use regex::Regex;
use serde::{Deserialize, Serialize};
use swc_atoms::JsWord;
use swc_cached::regex::CachedRegex;
use swc_common::{collections::AHashMap, Mark};
use swc_ecma_ast::{EsVersion, Expr};
@ -72,8 +72,8 @@ pub struct ManglePropertiesOptions {
pub reserved: Vec<JsWord>,
#[serde(default, alias = "undeclared")]
pub undeclared: bool,
#[serde(default, with = "serde_regex")]
pub regex: Option<Regex>,
#[serde(default)]
pub regex: Option<CachedRegex>,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]

View File

@ -2,15 +2,13 @@
//!
//! License is MIT, which is original license at the time of copying.
//! Original test authors have copyright for their work.
#![deny(warnings)]
#![allow(clippy::needless_update)]
use std::path::PathBuf;
use swc_common::{FileName, DUMMY_SP};
use swc_css_ast::{
ComponentValue, DeclarationOrAtRule, QualifiedRule, SimpleBlock, Stylesheet, Token,
TokenAndSpan,
};
use swc_css_ast::{ComponentValue, DeclarationOrAtRule, QualifiedRule, SimpleBlock, Stylesheet};
use swc_css_codegen::{
writer::basic::{BasicCssWriter, BasicCssWriterConfig},
CodegenConfig, Emit,
@ -537,10 +535,10 @@ fn t(src: &str, expected: &str) {
wr.push_str(&s);
let need_semi = match p {
ComponentValue::DeclarationOrAtRule(DeclarationOrAtRule::Invalid(_)) => false,
_ => true,
};
let need_semi = !matches!(
p,
ComponentValue::DeclarationOrAtRule(DeclarationOrAtRule::Invalid(_))
);
if need_semi {
wr.push(';');