Skip to content

Commit 0fe2d19

Browse files
committed
refactor: simplify literals
1 parent 78a63fa commit 0fe2d19

File tree

2 files changed

+20
-87
lines changed

2 files changed

+20
-87
lines changed

crates/jsshaker/src/value/literal/mod.rs

Lines changed: 18 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use oxc::{
88
semantic::SymbolId,
99
span::{Atom, SPAN, Span},
1010
};
11-
use oxc_ecmascript::{StringCharAt, StringCharAtResult, StringToNumber};
11+
use oxc_ecmascript::StringToNumber;
1212
use oxc_syntax::number::ToJsString;
1313

1414
use super::{
@@ -62,30 +62,22 @@ impl<'a> ValueTrait<'a> for LiteralValue<'a> {
6262
dep: Dep<'a>,
6363
key: Entity<'a>,
6464
) -> Entity<'a> {
65-
if matches!(self, LiteralValue::Null | LiteralValue::Undefined) {
66-
analyzer.throw_builtin_error("Cannot get property of null or undefined");
67-
if analyzer.config.preserve_exceptions {
68-
consumed_object::get_property(self, analyzer, dep, key)
69-
} else {
70-
analyzer.factory.never
71-
}
72-
} else {
73-
let prototype = self.get_prototype(analyzer);
74-
let dep = analyzer.dep((self, dep, key));
75-
if let Some(key_literals) = key.get_to_literals(analyzer) {
76-
let mut values = analyzer.factory.vec();
77-
for &key_literal in &key_literals {
78-
if let Some(property) = self.get_known_instance_property(analyzer, key_literal) {
79-
values.push(property);
80-
} else if let Some(property) = prototype.get_literal_keyed(key_literal) {
81-
values.push(property);
82-
} else {
83-
values.push(analyzer.factory.unmatched_prototype_property);
84-
}
65+
match self {
66+
LiteralValue::Null | LiteralValue::Undefined => {
67+
analyzer.throw_builtin_error("Cannot get property of null or undefined");
68+
if analyzer.config.preserve_exceptions {
69+
consumed_object::get_property(self, analyzer, dep, key)
70+
} else {
71+
analyzer.factory.never
8572
}
86-
analyzer.factory.computed_union(values, dep)
87-
} else {
88-
analyzer.factory.computed_unknown(dep)
73+
}
74+
LiteralValue::String(str, atom) => {
75+
let dep = analyzer.dep((dep, *atom));
76+
str.get_property(analyzer, dep, key)
77+
}
78+
_ => {
79+
let prototype = self.get_prototype(analyzer);
80+
prototype.get_property(analyzer, self.into(), key, dep)
8981
}
9082
}
9183
}
@@ -113,30 +105,7 @@ impl<'a> ValueTrait<'a> for LiteralValue<'a> {
113105
dep: Dep<'a>,
114106
) -> EnumeratedProperties<'a> {
115107
if let LiteralValue::String(value, atom) = self {
116-
let dep = analyzer.dep((dep, *atom));
117-
if value.len() <= analyzer.config.max_simple_string_length {
118-
EnumeratedProperties {
119-
known: value
120-
.char_indices()
121-
.map(|(i, c)| {
122-
let i_str = i.to_string().to_atom_ref(analyzer.allocator);
123-
let c_str = c.to_string().to_atom_ref(analyzer.allocator);
124-
(
125-
PropertyKeyValue::String(i_str),
126-
(
127-
true,
128-
analyzer.factory.unmangable_string(i_str),
129-
analyzer.factory.unmangable_string(c_str),
130-
),
131-
)
132-
})
133-
.collect(),
134-
unknown: None,
135-
dep,
136-
}
137-
} else {
138-
analyzer.factory.computed_unknown_string(self).enumerate_properties(analyzer, dep)
139-
}
108+
value.enumerate_properties(analyzer, analyzer.dep((dep, *atom)))
140109
} else {
141110
// No effect
142111
EnumeratedProperties { known: Default::default(), unknown: None, dep }
@@ -234,11 +203,7 @@ impl<'a> ValueTrait<'a> for LiteralValue<'a> {
234203
}
235204
}
236205
LiteralValue::String(str, atom) => {
237-
let val = str.trim().string_to_number();
238-
analyzer.factory.computed(
239-
if val.is_nan() { analyzer.factory.nan } else { analyzer.factory.number(val, None) },
240-
*atom,
241-
)
206+
analyzer.factory.computed(str.get_to_numeric(analyzer), *atom)
242207
}
243208
LiteralValue::Null => analyzer.factory.number(0.0, Some(builtin_atom!("0"))),
244209
LiteralValue::Symbol(_, _) => {
@@ -460,34 +425,6 @@ impl<'a> LiteralValue<'a> {
460425
}
461426
}
462427

463-
fn get_known_instance_property(
464-
&self,
465-
analyzer: &Analyzer<'a>,
466-
key: LiteralValue<'a>,
467-
) -> Option<Entity<'a>> {
468-
match self {
469-
LiteralValue::String(value, atom_self) => {
470-
let LiteralValue::String(key, atom_key) = key else { return None };
471-
if key == "length" {
472-
Some(analyzer.factory.number(value.len() as f64, None))
473-
} else {
474-
let index = key.as_str().string_to_number();
475-
if index.is_finite() {
476-
Some(match value.as_str().char_at(Some(index)) {
477-
StringCharAtResult::InvalidChar(_) => analyzer.factory.unknown,
478-
StringCharAtResult::OutOfRange => analyzer.factory.undefined,
479-
StringCharAtResult::Value(c) => analyzer.factory.unmangable_string(c.to_string()),
480-
})
481-
} else {
482-
None
483-
}
484-
}
485-
.map(|val| analyzer.factory.computed(val, (*atom_self, atom_key)))
486-
}
487-
_ => None,
488-
}
489-
}
490-
491428
pub fn strict_eq(self, other: LiteralValue, object_is: bool) -> (bool, Option<MangleConstraint>) {
492429
// 0.0 === -0.0
493430
if !object_is && let (LiteralValue::Number(l, _), LiteralValue::Number(r, _)) = (self, other) {

crates/jsshaker/src/value/literal/string.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl<'a> ValueTrait<'a> for Atom<'a> {
4747
key: Entity<'a>,
4848
) -> Entity<'a> {
4949
let prototype = &analyzer.builtins.prototypes.string;
50-
let dep = analyzer.dep((self, dep, key));
50+
let dep = analyzer.dep((dep, key));
5151
if let Some(key_literals) = key.get_to_literals(analyzer) {
5252
let mut values = analyzer.factory.vec();
5353
for &key_literal in &key_literals {
@@ -149,11 +149,7 @@ impl<'a> ValueTrait<'a> for Atom<'a> {
149149

150150
fn iterate(&'a self, analyzer: &mut Analyzer<'a>, dep: Dep<'a>) -> IteratedElements<'a> {
151151
let value = self.as_str();
152-
(
153-
vec![],
154-
(!value.is_empty()).then_some(analyzer.factory.unknown_string),
155-
analyzer.dep((self, dep)),
156-
)
152+
(vec![], (!value.is_empty()).then_some(analyzer.factory.unknown_string), dep)
157153
}
158154

159155
fn get_to_string(&'a self, _analyzer: &Analyzer<'a>) -> Entity<'a> {

0 commit comments

Comments
 (0)