perf(css/codegen): Reduce allocations (#6599)

This commit is contained in:
Donny/강동윤 2022-12-08 14:47:35 +09:00 committed by GitHub
parent 6fadb48a52
commit 538d63eb80
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 7 deletions

View File

@ -2,7 +2,7 @@
#![allow(clippy::needless_update)] #![allow(clippy::needless_update)]
pub use std::fmt::Result; pub use std::fmt::Result;
use std::{str, str::from_utf8}; use std::{borrow::Cow, str, str::from_utf8};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use swc_atoms::*; use swc_atoms::*;
@ -1565,9 +1565,9 @@ where
fn emit_ident(&mut self, n: &Ident) -> Result { fn emit_ident(&mut self, n: &Ident) -> Result {
if self.config.minify { if self.config.minify {
let value = if self.ctx.allow_to_lowercase && self.config.minify { let value = if self.ctx.allow_to_lowercase && self.config.minify {
n.value.to_ascii_lowercase().to_string() Cow::Owned(n.value.to_ascii_lowercase())
} else { } else {
n.value.to_string() Cow::Borrowed(&n.value)
}; };
let serialized = serialize_ident(&value, n.raw.as_deref(), true); let serialized = serialize_ident(&value, n.raw.as_deref(), true);

View File

@ -1,6 +1,6 @@
#![deny(clippy::all)] #![deny(clippy::all)]
use std::{char::REPLACEMENT_CHARACTER, str}; use std::{borrow::Cow, char::REPLACEMENT_CHARACTER, str};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@ -153,8 +153,53 @@ pub static NAMED_COLORS: Lazy<AHashMap<JsWord, NamedColor>> = Lazy::new(|| {
named_colors named_colors
}); });
#[inline]
fn is_escape_not_required(value: &str, raw: Option<&str>) -> bool {
if value.is_empty() {
return true;
}
if (b'0'..=b'9').contains(&value.as_bytes()[0]) {
return false;
}
if value.len() == 1 && value.as_bytes()[0] == b'-' {
return false;
}
if value.len() >= 2
&& value.as_bytes()[0] == b'-'
&& (b'0'..=b'9').contains(&value.as_bytes()[1])
{
return false;
}
value.chars().all(|c| {
match c {
REPLACEMENT_CHARACTER if raw.is_some() => false,
'\x00' => false,
'\x01'..='\x1f' | '\x7F' => false,
'-' | '_' => true,
_ if !c.is_ascii()
|| c.is_ascii_digit()
|| c.is_ascii_uppercase()
|| c.is_ascii_lowercase() =>
{
true
}
// Otherwise, the escaped character.
_ => false,
}
})
}
// https://drafts.csswg.org/cssom/#serialize-an-identifier // https://drafts.csswg.org/cssom/#serialize-an-identifier
pub fn serialize_ident(value: &str, raw: Option<&str>, minify: bool) -> String { pub fn serialize_ident<'a>(value: &'a str, raw: Option<&str>, minify: bool) -> Cow<'a, str> {
// Fast-path
if is_escape_not_required(value, raw) {
return Cow::Borrowed(value);
}
let mut result = String::with_capacity(value.len()); let mut result = String::with_capacity(value.len());
// //
@ -175,7 +220,7 @@ pub fn serialize_ident(value: &str, raw: Option<&str>, minify: bool) -> String {
REPLACEMENT_CHARACTER if raw.is_some() => { REPLACEMENT_CHARACTER if raw.is_some() => {
result.push_str(raw.unwrap()); result.push_str(raw.unwrap());
return result; return Cow::Owned(result);
} }
// If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD). // If the character is NULL (U+0000), then the REPLACEMENT CHARACTER (U+FFFD).
'\x00' => { '\x00' => {
@ -225,7 +270,7 @@ pub fn serialize_ident(value: &str, raw: Option<&str>, minify: bool) -> String {
} }
} }
result Cow::Owned(result)
} }
// https://github.com/servo/rust-cssparser/blob/4c5d065798ea1be649412532bde481dbd404f44a/src/serializer.rs#L166 // https://github.com/servo/rust-cssparser/blob/4c5d065798ea1be649412532bde481dbd404f44a/src/serializer.rs#L166