mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
fix(semantic): clear member write target for computed keys (#22302)
- clear `MemberWriteTarget` before visiting computed member keys - add semantic snapshot coverage for computed keys versus computed objects Fixes #22300
This commit is contained in:
1 parent
6a8852d910
commit
a7c3e22707
3 files changed
+89
No files matched your search
@@ -2073,6 +2073,19 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> {
|
||||
self.current_reference_flags = ReferenceFlags::empty();
|
||||
}
|
||||
|
||||
fn visit_computed_member_expression(&mut self, it: &ComputedMemberExpression<'a>) {
|
||||
let kind = AstKind::ComputedMemberExpression(self.alloc(it));
|
||||
self.enter_node(kind);
|
||||
self.visit_span(&it.span);
|
||||
self.visit_expression(&it.object);
|
||||
// The key expression is a read context, not part of the property write —
|
||||
// strip MemberWriteTarget so it doesn't leak onto identifiers inside the key
|
||||
// (e.g. `key` in `this[key] = 1`, where `this` doesn't consume the flag).
|
||||
self.current_reference_flags -= ReferenceFlags::MemberWriteTarget;
|
||||
self.visit_expression(&it.expression);
|
||||
self.leave_node(kind);
|
||||
}
|
||||
|
||||
fn visit_simple_assignment_target(&mut self, it: &SimpleAssignmentTarget<'a>) {
|
||||
// Except that the read-write flags has been set in visit_assignment_expression
|
||||
// and visit_update_expression, this is always a write-only reference here.
|
||||
|
||||
@@ -16,3 +16,14 @@ let c = {};
|
||||
let d = {};
|
||||
let e = {};
|
||||
(true ? d : e).foo = 1;
|
||||
|
||||
// No MemberWriteTarget: computed property key
|
||||
let key;
|
||||
this[key] = 1;
|
||||
this[key] += 1;
|
||||
delete this[key];
|
||||
|
||||
// MemberWriteTarget: computed object
|
||||
let f = {};
|
||||
f[key] = 1;
|
||||
f[key] += 1;
|
||||
+65
@@ -97,6 +97,71 @@ input_file: crates/oxc_semantic/tests/fixtures/oxc/js/assignments/member-write-t
|
||||
"scope_id": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"flags": "SymbolFlags(BlockScopedVariable)",
|
||||
"id": 5,
|
||||
"name": "key",
|
||||
"node": "VariableDeclarator(key)",
|
||||
"references": [
|
||||
{
|
||||
"flags": "ReferenceFlags(Read)",
|
||||
"id": 7,
|
||||
"name": "key",
|
||||
"node_id": 71,
|
||||
"scope_id": 0
|
||||
},
|
||||
{
|
||||
"flags": "ReferenceFlags(Read)",
|
||||
"id": 8,
|
||||
"name": "key",
|
||||
"node_id": 77,
|
||||
"scope_id": 0
|
||||
},
|
||||
{
|
||||
"flags": "ReferenceFlags(Read)",
|
||||
"id": 9,
|
||||
"name": "key",
|
||||
"node_id": 83,
|
||||
"scope_id": 0
|
||||
},
|
||||
{
|
||||
"flags": "ReferenceFlags(Read)",
|
||||
"id": 11,
|
||||
"name": "key",
|
||||
"node_id": 92,
|
||||
"scope_id": 0
|
||||
},
|
||||
{
|
||||
"flags": "ReferenceFlags(Read)",
|
||||
"id": 13,
|
||||
"name": "key",
|
||||
"node_id": 98,
|
||||
"scope_id": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"flags": "SymbolFlags(BlockScopedVariable)",
|
||||
"id": 6,
|
||||
"name": "f",
|
||||
"node": "VariableDeclarator(f)",
|
||||
"references": [
|
||||
{
|
||||
"flags": "ReferenceFlags(Read | MemberWriteTarget)",
|
||||
"id": 10,
|
||||
"name": "f",
|
||||
"node_id": 91,
|
||||
"scope_id": 0
|
||||
},
|
||||
{
|
||||
"flags": "ReferenceFlags(Read | MemberWriteTarget)",
|
||||
"id": 12,
|
||||
"name": "f",
|
||||
"node_id": 97,
|
||||
"scope_id": 0
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user