Skip to content

Commit f45455f

Browse files
committed
fix: Correctly handle computed object assignments
1 parent bf74003 commit f45455f

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

src/swc.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ fn prefix_getters_setters(kind: ast::MethodKind, scope_name: &mut ScopeName) {
338338
/// This is only possible if the expression is an identifier or a member expression.
339339
fn infer_name_from_expr(mut expr: &ast::Expr) -> Option<ScopeName> {
340340
let mut scope_name = ScopeName::new();
341+
341342
loop {
342343
match expr {
343344
ast::Expr::Ident(ident) => {
@@ -354,6 +355,18 @@ fn infer_name_from_expr(mut expr: &ast::Expr) -> Option<ScopeName> {
354355
.push_front(NameComponent::ident(ident.clone()));
355356
scope_name.components.push_front(NameComponent::interp("."));
356357
}
358+
359+
if let Some(computed_prop) = member.prop.as_computed() {
360+
if let Some((computed_name, need_delimiter)) =
361+
computed_prop_name_to_component(computed_prop)
362+
{
363+
scope_name.components.push_front(computed_name);
364+
if need_delimiter {
365+
scope_name.components.push_front(NameComponent::interp("."));
366+
}
367+
}
368+
}
369+
357370
expr = &member.obj;
358371
}
359372

@@ -369,6 +382,24 @@ fn infer_name_from_expr(mut expr: &ast::Expr) -> Option<ScopeName> {
369382
}
370383
}
371384

385+
fn computed_prop_name_to_component(prop: &ast::ComputedPropName) -> Option<(NameComponent, bool)> {
386+
if let Some(lit) = prop.expr.as_lit() {
387+
if let ast::Lit::Str(prop) = lit {
388+
return Some((NameComponent::interp(prop.value.to_string()), true));
389+
}
390+
391+
if let ast::Lit::Num(prop) = lit {
392+
return Some((NameComponent::interp(format!("[{}]", prop.value)), false));
393+
}
394+
}
395+
396+
if let Some(ident) = prop.expr.as_ident() {
397+
return Some((NameComponent::interp(format!("[{}]", ident.sym)), false));
398+
}
399+
400+
None
401+
}
402+
372403
fn prop_name_to_component(prop: &ast::PropName) -> NameComponent {
373404
match prop {
374405
ast::PropName::Ident(ref i) => NameComponent::ident(i.clone()),

tests/fixtures/trace/sync.mjs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,17 @@ let obj = {
8484
throw new Error();
8585
},
8686
};
87+
88+
Klass.prototype[42] = function () {
89+
beepBoop();
90+
};
91+
92+
Klass.prototype["method"] = function () {
93+
beepBoop();
94+
};
95+
96+
const method = "computedMethod";
97+
98+
Klass.prototype[method] = function () {
99+
beepBoop();
100+
};

tests/integration.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ fn resolves_scope_names() {
6969
index.lookup(offset)
7070
};
7171

72+
assert_eq!(lookup(99, 3), NamedScope("Klass.prototype[method]"));
73+
assert_eq!(lookup(93, 3), NamedScope("Klass.prototype.method"));
74+
assert_eq!(lookup(89, 3), NamedScope("Klass.prototype[42]"));
75+
7276
// objectLiteralAnon@http://127.0.0.1:8080/sync.mjs:84:11
7377
// at Object.objectLiteralAnon (http://127.0.0.1:8080/sync.mjs:84:11)
7478
assert_eq!(lookup(84, 11), NamedScope("obj.objectLiteralAnon"));

0 commit comments

Comments
 (0)