Skip to content

Commit

Permalink
chore: 🤖 clean
Browse files Browse the repository at this point in the history
  • Loading branch information
IWANABETHATGUY committed Aug 20, 2024
1 parent 20cbd76 commit abefa77
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 64 deletions.
195 changes: 139 additions & 56 deletions crates/oxc_minifier/src/plugins/replace_global_defines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub struct ReplaceGlobalDefinesConfig(Arc<ReplaceGlobalDefinesConfigImpl>);
struct ReplaceGlobalDefinesConfigImpl {
identifier_defines: Vec<(/* key */ CompactStr, /* value */ CompactStr)>,
dot_defines: Vec<DotDefine>,
meta_proeperty_defines: Vec<MetaPropertyDefine>,
}

#[derive(Debug)]
Expand All @@ -31,6 +32,20 @@ pub struct DotDefine {
pub postfix_wildcard: bool,
}

#[derive(Debug)]
pub struct MetaPropertyDefine {
/// only store parts after `import.meta`
pub parts: Vec<CompactStr>,
pub value: CompactStr,
pub postfix_wildcard: bool,
}

impl MetaPropertyDefine {
pub fn new(parts: Vec<CompactStr>, value: CompactStr, postfix_wildcard: bool) -> Self {
Self { parts, value, postfix_wildcard }
}
}

impl DotDefine {
fn new(parts: Vec<CompactStr>, value: CompactStr, postfix_wildcard: bool) -> Self {
Self { parts, value, postfix_wildcard }
Expand All @@ -39,7 +54,9 @@ impl DotDefine {

enum IdentifierType {
Identifier,
DotDefines { parts: Vec<CompactStr>, postfix_wildcard: bool },
DotDefines { parts: Vec<CompactStr> },
// import.meta.a
ImportMeta { parts: Vec<CompactStr>, postfix_wildcard: bool },
}

impl ReplaceGlobalDefinesConfig {
Expand All @@ -51,6 +68,7 @@ impl ReplaceGlobalDefinesConfig {
let allocator = Allocator::default();
let mut identifier_defines = vec![];
let mut dot_defines = vec![];
let mut meta_proeperty_defines = vec![];
for (key, value) in defines {
let key = key.as_ref();

Expand All @@ -61,19 +79,22 @@ impl ReplaceGlobalDefinesConfig {
IdentifierType::Identifier => {
identifier_defines.push((CompactStr::new(key), CompactStr::new(value)));
}
IdentifierType::DotDefines { parts, postfix_wildcard } => {
dot_defines.push(DotDefine::new(
IdentifierType::DotDefines { parts } => {
dot_defines.push(DotDefine::new(parts, CompactStr::new(value), false));
}
IdentifierType::ImportMeta { parts, postfix_wildcard } => {
meta_proeperty_defines.push(MetaPropertyDefine::new(
parts,
CompactStr::new(value),
postfix_wildcard,
));
}
}
}
// Always move specific dot define before wildcard dot define
// Always move specific meta define before wildcard dot define
// Keep other order unchanged
// see test case replace_global_definitions_dot_with_postfix_mixed as an example
dot_defines.sort_by(|a, b| {
meta_proeperty_defines.sort_by(|a, b| {
if !a.postfix_wildcard && b.postfix_wildcard {
Ordering::Less
} else if a.postfix_wildcard && b.postfix_wildcard {
Expand All @@ -82,8 +103,11 @@ impl ReplaceGlobalDefinesConfig {
Ordering::Equal
}
});

Ok(Self(Arc::new(ReplaceGlobalDefinesConfigImpl { identifier_defines, dot_defines })))
Ok(Self(Arc::new(ReplaceGlobalDefinesConfigImpl {
identifier_defines,
dot_defines,
meta_proeperty_defines,
})))
}

fn check_key(key: &str) -> Result<IdentifierType, Vec<OxcDiagnostic>> {
Expand All @@ -99,17 +123,38 @@ impl ReplaceGlobalDefinesConfig {
}
let normalized_parts_len =
if parts[parts.len() - 1] == "*" { parts.len() - 1 } else { parts.len() };
// We can ensure now the parts.len() >= 2
let is_import_meta = parts[0] == "import" && parts[1] == "meta";

for part in &parts[0..normalized_parts_len] {
if !is_identifier_name(part) {
return Err(vec![OxcDiagnostic::error(format!("`{key}` is not an identifier."))]);
}
}

Ok(IdentifierType::DotDefines {
parts: parts.iter().take(normalized_parts_len).map(|s| CompactStr::new(s)).collect(),
postfix_wildcard: parts.len() != normalized_parts_len,
})
if is_import_meta {
Ok(IdentifierType::ImportMeta {
parts: parts
.iter()
.skip(2)
.take(normalized_parts_len - 2)
.map(|s| CompactStr::new(s))
.collect(),
postfix_wildcard: normalized_parts_len != parts.len(),
})
// StaticMemberExpression with postfix wildcard
} else if normalized_parts_len != parts.len() {
Err(vec![OxcDiagnostic::error(format!(
"postfix wildcard is only allowed for `import.meta`."
))])
} else {
Ok(IdentifierType::DotDefines {
parts: parts
.iter()
.take(normalized_parts_len)
.map(|s| CompactStr::new(s))
.collect(),
})
}
}

fn check_value(allocator: &Allocator, source_text: &str) -> Result<(), Vec<OxcDiagnostic>> {
Expand Down Expand Up @@ -170,27 +215,42 @@ impl<'a> ReplaceGlobalDefines<'a> {
}

fn replace_dot_defines(&mut self, expr: &mut Expression<'a>) {
if let Expression::StaticMemberExpression(member) = expr {
for dot_define in &self.config.0.dot_defines {
if Self::is_dot_define(dot_define, member) {
let value = self.parse_value(&dot_define.value);
*expr = value;
break;
}
let Expression::StaticMemberExpression(member) = expr else {
return;
};
for dot_define in &self.config.0.dot_defines {
if Self::is_dot_define(dot_define, member) {
let value = self.parse_value(&dot_define.value);
*expr = value;
return;
}
}
// dbg!(&member);
for meta_proeperty_define in &self.config.0.meta_proeperty_defines {
let ret = Self::is_meta_property_define(meta_proeperty_define, member);
dbg!(&ret);
if ret {
let value = self.parse_value(&meta_proeperty_define.value);
*expr = value;
break;
}
}
}
pub fn is_dot_define(dot_define: &DotDefine, member: &StaticMemberExpression<'a>) -> bool {
debug_assert!(dot_define.parts.len() > 1);

let mut current_part_member_expression =
Some(StaticMemberExpressionOrMeta::StaticMemberExpression(member));
pub fn is_meta_property_define(
meta_define: &MetaPropertyDefine,
member: &StaticMemberExpression<'a>,
) -> bool {
debug_assert!(meta_define.parts.len() >= 1);

let mut current_part_member_expression = Some(member);
let mut cur_part_name = &member.property.name;
let mut has_matched_part = false;
let mut i = dot_define.parts.len() - 1;
let mut i = meta_define.parts.len() - 1;
loop {
let part = &dot_define.parts[i];
let part = &meta_define.parts[i];
let matched = cur_part_name.as_str() == part;
dbg!(&part, cur_part_name);
if !matched {
// Considering import.meta.env.*
// ```js
Expand All @@ -199,54 +259,77 @@ impl<'a> ReplaceGlobalDefines<'a> {
// ```
// So we use has_matched_part to track if any part has matched.

if !dot_define.postfix_wildcard || has_matched_part {
dbg!(&meta_define.postfix_wildcard, has_matched_part);
if !meta_define.postfix_wildcard || has_matched_part {
return false;
}
}

if i == 0 {
break;
} else {
has_matched_part = true;
}

current_part_member_expression = if let Some(member) = current_part_member_expression {
match member {
StaticMemberExpressionOrMeta::StaticMemberExpression(member) => {
match &member.object {
Expression::StaticMemberExpression(member) => {
cur_part_name = &member.property.name;
Some(StaticMemberExpressionOrMeta::StaticMemberExpression(member))
}
Expression::MetaProperty(member) => {
cur_part_name = &member.property.name;
Some(StaticMemberExpressionOrMeta::MetaProperty(member))
}
Expression::Identifier(ident) => {
cur_part_name = &ident.name;
None
}
_ => None,
}
match &member.object {
Expression::StaticMemberExpression(member) => {
cur_part_name = &member.property.name;
Some(member)
}
StaticMemberExpressionOrMeta::MetaProperty(meta) => {
cur_part_name = &meta.meta.name;
None
Expression::MetaProperty(_) => {
return has_matched_part;
}
Expression::Identifier(_) => {
return false;
}
_ => None,
}
} else {
return false;
};
dbg!(&i, matched);

if i == 0 && matched {
break;
}

if matched {
i -= 1;
has_matched_part = true;
}
}

has_matched_part
false
}
}

enum StaticMemberExpressionOrMeta<'a> {
StaticMemberExpression(&'a StaticMemberExpression<'a>),
MetaProperty(&'a MetaProperty<'a>),
pub fn is_dot_define(dot_define: &DotDefine, member: &StaticMemberExpression<'a>) -> bool {
debug_assert!(dot_define.parts.len() > 1);

let mut current_part_member_expression = Some(member);
let mut cur_part_name = &member.property.name;

for (i, part) in dot_define.parts.iter().enumerate().rev() {
if cur_part_name.as_str() != part {
return false;
}

if i == 0 {
break;
}

current_part_member_expression = if let Some(member) = current_part_member_expression {
match &member.object {
Expression::StaticMemberExpression(member) => {
cur_part_name = &member.property.name;
Some(member)
}
Expression::Identifier(ident) => {
cur_part_name = &ident.name;
None
}
_ => None,
}
} else {
return false;
};
}

true
}
}
10 changes: 2 additions & 8 deletions crates/oxc_minifier/tests/plugins/replace_global_defines.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,8 @@ fn replace_global_definitions_dot() {
#[test]
fn replace_global_definitions_dot_with_postfix_wildcard() {
{
let config = ReplaceGlobalDefinesConfig::new(&[
("process.env.NODE_ENV.*", "production"),
("import.meta.env.*", "undefined"),
])
.unwrap();
test("process.env.NODE_ENV.test", "production", config.clone());
let config =
ReplaceGlobalDefinesConfig::new(&[("import.meta.env.*", "undefined")]).unwrap();
test("import.meta.env.result", "undefined", config.clone());
test("import.meta.env", "undefined", config);
}
Expand All @@ -61,12 +57,10 @@ fn replace_global_definitions_dot_with_postfix_wildcard() {
fn replace_global_definitions_dot_with_postfix_mixed() {
{
let config = ReplaceGlobalDefinesConfig::new(&[
("process.env.NODE_ENV.*", "production"),
("import.meta.env.*", "undefined"),
("import.meta.env", "env"),
])
.unwrap();
test("process.env.NODE_ENV.test", "production", config.clone());
test("import.meta.env.result", "undefined", config.clone());
test("import.meta.env", "env", config);
}
Expand Down

0 comments on commit abefa77

Please sign in to comment.