Skip to content

Commit 4f9dd98

Browse files
authored
feat(span): remove From<String> and From<Cow> API because they create memory leak (#2628)
closes #2621
1 parent 240ff19 commit 4f9dd98

File tree

17 files changed

+141
-152
lines changed

17 files changed

+141
-152
lines changed

crates/oxc_ast/src/ast/js.rs

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{cell::Cell, fmt, hash::Hash};
22

33
use oxc_allocator::{Box, Vec};
4-
use oxc_span::{Atom, SourceType, Span};
4+
use oxc_span::{Atom, CompactStr, SourceType, Span};
55
use oxc_syntax::{
66
operator::{
77
AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator,
@@ -212,7 +212,7 @@ impl<'a> Expression<'a> {
212212
}
213213
}
214214

215-
pub fn is_specific_member_access(&'a self, object: &str, property: &str) -> bool {
215+
pub fn is_specific_member_access(&self, object: &str, property: &str) -> bool {
216216
match self.get_inner_expression() {
217217
Expression::MemberExpression(expr) => expr.is_specific_member_access(object, property),
218218
Expression::ChainExpression(chain) => {
@@ -466,19 +466,22 @@ pub enum PropertyKey<'a> {
466466
}
467467

468468
impl<'a> PropertyKey<'a> {
469-
pub fn static_name(&self) -> Option<Atom<'a>> {
469+
pub fn static_name(&self) -> Option<CompactStr> {
470470
match self {
471-
Self::Identifier(ident) => Some(ident.name.clone()),
471+
Self::Identifier(ident) => Some(ident.name.to_compact_str()),
472472
Self::PrivateIdentifier(_) => None,
473473
Self::Expression(expr) => match expr {
474-
Expression::StringLiteral(lit) => Some(lit.value.clone()),
475-
Expression::RegExpLiteral(lit) => Some(Atom::from(lit.regex.to_string())),
476-
Expression::NumericLiteral(lit) => Some(Atom::from(lit.value.to_string())),
477-
Expression::BigintLiteral(lit) => Some(lit.raw.clone()),
474+
Expression::StringLiteral(lit) => Some(lit.value.to_compact_str()),
475+
Expression::RegExpLiteral(lit) => Some(lit.regex.to_string().into()),
476+
Expression::NumericLiteral(lit) => Some(lit.value.to_string().into()),
477+
Expression::BigintLiteral(lit) => Some(lit.raw.to_compact_str()),
478478
Expression::NullLiteral(_) => Some("null".into()),
479-
Expression::TemplateLiteral(lit) => {
480-
lit.expressions.is_empty().then(|| lit.quasi()).flatten().cloned()
481-
}
479+
Expression::TemplateLiteral(lit) => lit
480+
.expressions
481+
.is_empty()
482+
.then(|| lit.quasi())
483+
.flatten()
484+
.map(Atom::to_compact_str),
482485
_ => None,
483486
},
484487
}
@@ -496,16 +499,16 @@ impl<'a> PropertyKey<'a> {
496499
matches!(self, Self::PrivateIdentifier(_))
497500
}
498501

499-
pub fn private_name(&self) -> Option<Atom<'a>> {
502+
pub fn private_name(&self) -> Option<&Atom<'a>> {
500503
match self {
501-
Self::PrivateIdentifier(ident) => Some(ident.name.clone()),
504+
Self::PrivateIdentifier(ident) => Some(&ident.name),
502505
_ => None,
503506
}
504507
}
505508

506-
pub fn name(&self) -> Option<Atom<'a>> {
509+
pub fn name(&self) -> Option<CompactStr> {
507510
if self.is_private_identifier() {
508-
self.private_name()
511+
self.private_name().map(Atom::to_compact_str)
509512
} else {
510513
self.static_name()
511514
}
@@ -758,7 +761,7 @@ impl<'a> CallExpression<'a> {
758761
}
759762
}
760763

761-
pub fn is_symbol_or_symbol_for_call(&'a self) -> bool {
764+
pub fn is_symbol_or_symbol_for_call(&self) -> bool {
762765
// TODO: is 'Symbol' reference to global object
763766
match &self.callee {
764767
Expression::Identifier(id) => id.name == "Symbol",
@@ -2017,7 +2020,7 @@ impl<'a> ClassElement<'a> {
20172020
}
20182021
}
20192022

2020-
pub fn static_name(&self) -> Option<Atom> {
2023+
pub fn static_name(&self) -> Option<CompactStr> {
20212024
match self {
20222025
Self::TSIndexSignature(_) | Self::StaticBlock(_) => None,
20232026
Self::MethodDefinition(def) => def.key.static_name(),

crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ impl GetMethod for ClassElement<'_> {
130130
fn get_method(&self) -> Option<Method> {
131131
match self {
132132
ClassElement::MethodDefinition(def) => def.key.static_name().map(|name| Method {
133-
name: name.to_compact_str(),
133+
name,
134134
r#static: def.r#static,
135135
call_signature: false,
136136
kind: get_kind_from_key(&def.key),
@@ -145,7 +145,7 @@ impl GetMethod for TSSignature<'_> {
145145
fn get_method(&self) -> Option<Method> {
146146
match self {
147147
TSSignature::TSMethodSignature(sig) => sig.key.static_name().map(|name| Method {
148-
name: name.to_compact_str(),
148+
name,
149149
r#static: false,
150150
call_signature: false,
151151
kind: get_kind_from_key(&sig.key),

crates/oxc_minifier/src/compressor/fold.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,7 +264,7 @@ impl<'a> Compressor<'a> {
264264
let right_string = get_string_value(right)?;
265265
// let value = left_string.to_owned().
266266
let value = left_string + right_string;
267-
let string_literal = StringLiteral::new(span, Atom::from(value));
267+
let string_literal = StringLiteral::new(span, self.ast.new_atom(&value));
268268
Some(self.ast.literal_string_expression(string_literal))
269269
},
270270

crates/oxc_semantic/src/binder.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
//! Declare symbol for `BindingIdentifier`s
22
3+
use std::borrow::Cow;
4+
35
#[allow(clippy::wildcard_imports)]
46
use oxc_ast::ast::*;
57
use oxc_ast::{
68
syntax_directed_operations::{BoundNames, IsSimpleParameterList},
79
AstKind,
810
};
9-
use oxc_span::{Atom, SourceType};
11+
use oxc_span::SourceType;
1012

1113
use crate::{scope::ScopeFlags, symbol::SymbolFlags, SemanticBuilder};
1214

@@ -343,9 +345,9 @@ impl<'a> Binder for TSEnumMember<'a> {
343345
return;
344346
}
345347
let name = match &self.id {
346-
TSEnumMemberName::Identifier(id) => id.name.clone(),
347-
TSEnumMemberName::StringLiteral(s) => s.value.clone(),
348-
TSEnumMemberName::NumericLiteral(n) => Atom::from(n.value.to_string()),
348+
TSEnumMemberName::Identifier(id) => Cow::Borrowed(id.name.as_str()),
349+
TSEnumMemberName::StringLiteral(s) => Cow::Borrowed(s.value.as_str()),
350+
TSEnumMemberName::NumericLiteral(n) => Cow::Owned(n.value.to_string()),
349351
TSEnumMemberName::ComputedPropertyName(_) => panic!("TODO: implement"),
350352
};
351353
builder.declare_symbol(

crates/oxc_semantic/src/builder.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc};
55
#[allow(clippy::wildcard_imports)]
66
use oxc_ast::{ast::*, AstKind, Trivias, TriviasMap, Visit};
77
use oxc_diagnostics::Error;
8-
use oxc_span::{Atom, SourceType, Span};
8+
use oxc_span::{CompactStr, SourceType, Span};
99
use oxc_syntax::{
1010
module_record::{ExportLocalName, ModuleRecord},
1111
operator::AssignmentOperator,
@@ -231,7 +231,7 @@ impl<'a> SemanticBuilder<'a> {
231231
pub fn declare_symbol_on_scope(
232232
&mut self,
233233
span: Span,
234-
name: &Atom,
234+
name: &str,
235235
scope_id: ScopeId,
236236
includes: SymbolFlags,
237237
excludes: SymbolFlags,
@@ -243,16 +243,16 @@ impl<'a> SemanticBuilder<'a> {
243243
}
244244

245245
let includes = includes | self.current_symbol_flags;
246-
let symbol_id = self.symbols.create_symbol(span, name.clone(), includes, scope_id);
246+
let symbol_id = self.symbols.create_symbol(span, name, includes, scope_id);
247247
self.symbols.add_declaration(self.current_node_id);
248-
self.scope.add_binding(scope_id, name.to_compact_str(), symbol_id);
248+
self.scope.add_binding(scope_id, CompactStr::from(name), symbol_id);
249249
symbol_id
250250
}
251251

252252
pub fn declare_symbol(
253253
&mut self,
254254
span: Span,
255-
name: &Atom,
255+
name: &str,
256256
includes: SymbolFlags,
257257
excludes: SymbolFlags,
258258
) -> SymbolId {
@@ -263,14 +263,14 @@ impl<'a> SemanticBuilder<'a> {
263263
&mut self,
264264
scope_id: ScopeId,
265265
span: Span,
266-
name: &Atom,
266+
name: &str,
267267
excludes: SymbolFlags,
268268
report_error: bool,
269269
) -> Option<SymbolId> {
270270
let symbol_id = self.scope.get_binding(scope_id, name)?;
271271
if report_error && self.symbols.get_flag(symbol_id).intersects(excludes) {
272272
let symbol_span = self.symbols.get_span(symbol_id);
273-
self.error(Redeclaration(name.to_compact_str(), symbol_span, span));
273+
self.error(Redeclaration(CompactStr::from(name), symbol_span, span));
274274
}
275275
Some(symbol_id)
276276
}
@@ -285,16 +285,15 @@ impl<'a> SemanticBuilder<'a> {
285285
/// Declares a `Symbol` for the node, shadowing previous declarations in the same scope.
286286
pub fn declare_shadow_symbol(
287287
&mut self,
288-
name: &Atom,
288+
name: &str,
289289
span: Span,
290290
scope_id: ScopeId,
291291
includes: SymbolFlags,
292292
) -> SymbolId {
293293
let includes = includes | self.current_symbol_flags;
294-
let symbol_id =
295-
self.symbols.create_symbol(span, name.clone(), includes, self.current_scope_id);
294+
let symbol_id = self.symbols.create_symbol(span, name, includes, self.current_scope_id);
296295
self.symbols.add_declaration(self.current_node_id);
297-
self.scope.get_bindings_mut(scope_id).insert(name.to_compact_str(), symbol_id);
296+
self.scope.get_bindings_mut(scope_id).insert(CompactStr::from(name), symbol_id);
298297
symbol_id
299298
}
300299

crates/oxc_semantic/src/class/builder.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use oxc_ast::{
55
},
66
AstKind,
77
};
8-
use oxc_span::GetSpan;
8+
use oxc_span::{Atom, GetSpan};
99
use oxc_syntax::class::{ClassId, ElementKind};
1010

1111
use crate::{AstNodeId, AstNodes};
@@ -57,15 +57,14 @@ impl ClassTableBuilder {
5757

5858
pub fn declare_class_accessor(&mut self, property: &AccessorProperty) {
5959
let is_private = property.key.is_private_identifier();
60-
let name =
61-
if is_private { property.key.private_name() } else { property.key.static_name() };
60+
let name = property.key.name();
6261

6362
if let Some(name) = name {
6463
if let Some(class_id) = self.current_class_id {
6564
self.classes.add_element(
6665
class_id,
6766
Element::new(
68-
name.to_compact_str(),
67+
name,
6968
property.key.span(),
7069
property.r#static,
7170
is_private,
@@ -78,15 +77,14 @@ impl ClassTableBuilder {
7877

7978
pub fn declare_class_property(&mut self, property: &PropertyDefinition) {
8079
let is_private = property.key.is_private_identifier();
81-
let name =
82-
if is_private { property.key.private_name() } else { property.key.static_name() };
80+
let name = property.key.name();
8381

8482
if let Some(name) = name {
8583
if let Some(class_id) = self.current_class_id {
8684
self.classes.add_element(
8785
class_id,
8886
Element::new(
89-
name.to_compact_str(),
87+
name,
9088
property.key.span(),
9189
property.r#static,
9290
is_private,
@@ -127,14 +125,18 @@ impl ClassTableBuilder {
127125
return;
128126
}
129127
let is_private = method.key.is_private_identifier();
130-
let name = if is_private { method.key.private_name() } else { method.key.static_name() };
128+
let name = if is_private {
129+
method.key.private_name().map(Atom::to_compact_str)
130+
} else {
131+
method.key.static_name()
132+
};
131133

132134
if let Some(name) = name {
133135
if let Some(class_id) = self.current_class_id {
134136
self.classes.add_element(
135137
class_id,
136138
Element::new(
137-
name.to_compact_str(),
139+
name,
138140
method.key.span(),
139141
method.r#static,
140142
is_private,

crates/oxc_semantic/src/symbol.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,12 +117,12 @@ impl SymbolTable {
117117
pub fn create_symbol(
118118
&mut self,
119119
span: Span,
120-
name: Atom,
120+
name: &str,
121121
flag: SymbolFlags,
122122
scope_id: ScopeId,
123123
) -> SymbolId {
124124
_ = self.spans.push(span);
125-
_ = self.names.push(name.into_compact_str());
125+
_ = self.names.push(CompactStr::from(name));
126126
_ = self.flags.push(flag);
127127
_ = self.scope_ids.push(scope_id);
128128
_ = self.resolved_references.push(vec![]);

crates/oxc_semantic/tests/util/symbol_tester.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ impl<'a> SymbolTester<'a> {
141141
pub fn is_exported(mut self) -> Self {
142142
self.test_result = match self.test_result {
143143
Ok(symbol_id) => {
144-
let binding = Atom::from(self.target_symbol_name.clone());
144+
let binding = self.target_symbol_name.clone();
145145
if self.semantic.module_record().exported_bindings.contains_key(binding.as_str())
146146
&& self.semantic.scopes().get_root_binding(&binding) == Some(symbol_id)
147147
{

crates/oxc_span/src/atom.rs

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
use std::{
2-
borrow::{Borrow, Cow},
3-
fmt, hash,
4-
ops::Deref,
5-
};
1+
use std::{borrow::Borrow, fmt, hash, ops::Deref};
62

73
#[cfg(feature = "serde")]
84
use serde::{Serialize, Serializer};
@@ -82,18 +78,6 @@ impl<'a> From<&'a str> for Atom<'a> {
8278
}
8379
}
8480

85-
impl<'a> From<String> for Atom<'a> {
86-
fn from(s: String) -> Self {
87-
Self::Compact(CompactString::from(s))
88-
}
89-
}
90-
91-
impl<'a> From<Cow<'_, str>> for Atom<'a> {
92-
fn from(s: Cow<'_, str>) -> Self {
93-
Self::Compact(CompactString::from(s))
94-
}
95-
}
96-
9781
impl<'a> Deref for Atom<'a> {
9882
type Target = str;
9983

crates/oxc_transformer/src/es2015/duplicate_keys.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use std::{collections::HashSet, rc::Rc};
44

55
use oxc_ast::{ast::*, AstBuilder};
6-
use oxc_span::{Atom, SPAN};
6+
use oxc_span::{CompactStr, SPAN};
77

88
use crate::options::{TransformOptions, TransformTarget};
99

@@ -22,9 +22,9 @@ impl<'a> DuplicateKeys<'a> {
2222
}
2323

2424
pub fn transform_object_expression<'b>(&mut self, obj_expr: &'b mut ObjectExpression<'a>) {
25-
let mut visited_data: HashSet<Atom> = HashSet::new();
26-
let mut visited_getters: HashSet<Atom> = HashSet::new();
27-
let mut visited_setters: HashSet<Atom> = HashSet::new();
25+
let mut visited_data: HashSet<CompactStr> = HashSet::new();
26+
let mut visited_getters: HashSet<CompactStr> = HashSet::new();
27+
let mut visited_setters: HashSet<CompactStr> = HashSet::new();
2828

2929
for property in obj_expr.properties.iter_mut() {
3030
let ObjectPropertyKind::ObjectProperty(obj_property) = property else {
@@ -64,7 +64,7 @@ impl<'a> DuplicateKeys<'a> {
6464

6565
if is_duplicate {
6666
obj_property.computed = true;
67-
let string_literal = StringLiteral::new(SPAN, name.clone());
67+
let string_literal = StringLiteral::new(SPAN, self.ast.new_atom(name));
6868
let expr = self.ast.literal_string_expression(string_literal);
6969
obj_property.key = PropertyKey::Expression(expr);
7070
}

0 commit comments

Comments
 (0)