Skip to content

Commit d07a762

Browse files
author
Cameron McHenry
committed
fix(linter): remove false positives for no-extend-native
1 parent 189fc00 commit d07a762

File tree

2 files changed

+35
-12
lines changed

2 files changed

+35
-12
lines changed

crates/oxc_linter/src/rules/eslint/no_extend_native.rs

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -180,19 +180,29 @@ fn get_property_assignment<'a>(
180180
ctx: &'a LintContext,
181181
node: &AstNode<'a>,
182182
) -> Option<&'a AstNode<'a>> {
183-
// Ignore computed member expressions like `obj[Object.prototype] = 0` (i.e., the
184-
// given node is the `expression` of the computed member expression)
185-
if let Some(AstKind::ComputedMemberExpression(parent_mem_expr)) =
186-
ctx.nodes().parent_kind(node.id())
187-
{
188-
if parent_mem_expr.expression.span().contains_inclusive(node.span()) {
189-
return None;
190-
}
191-
}
192-
193183
for parent in ctx.nodes().ancestors(node.id()).skip(1) {
194-
if let AstKind::AssignmentExpression(_) = parent.kind() {
195-
return Some(parent);
184+
match parent.kind() {
185+
AstKind::AssignmentExpression(assignment_expr)
186+
if assignment_expr.left.span().contains_inclusive(node.span()) =>
187+
{
188+
return Some(parent);
189+
}
190+
AstKind::ArrayAssignmentTarget(assign_target)
191+
if assign_target.elements.iter().any(|e| {
192+
e.as_ref().is_some_and(|e| e.span().contains_inclusive(node.span()))
193+
}) =>
194+
{
195+
return Some(parent);
196+
}
197+
AstKind::ComputedMemberExpression(computed_expr)
198+
if computed_expr.object.span().contains_inclusive(node.span()) =>
199+
{
200+
continue;
201+
}
202+
AstKind::StaticMemberExpression(_)
203+
| AstKind::SimpleAssignmentTarget(_)
204+
| AstKind::AssignmentTarget(_) => continue,
205+
_ => return None,
196206
}
197207
}
198208
None
@@ -257,6 +267,12 @@ fn test() {
257267
("Object.defineProperties()", None),
258268
("function foo() { var Object = function() {}; Object.prototype.p = 0 }", None),
259269
("{ let Object = function() {}; Object.prototype.p = 0 }", None), // { "ecmaVersion": 6 }
270+
("x = Object.prototype.p", None),
271+
("x = Array.prototype.p", None),
272+
("Array.#prototype.p = 0", None),
273+
("foo(Number.prototype.xyz).x = 1", None),
274+
("let { z = Array.prototype.p } = {} ", None),
275+
("Object.x.defineProperty(Array.prototype, 'p', {value: 0})", None),
260276
];
261277

262278
let fail = vec![
@@ -285,6 +301,7 @@ fn test() {
285301
("Array.prototype.p &&= 0", None), // { "ecmaVersion": 2021 },
286302
("Array.prototype.p ||= 0", None), // { "ecmaVersion": 2021 },
287303
("Array.prototype.p ??= 0", None), // { "ecmaVersion": 2021 }
304+
("[Array.prototype.p] = [() => {}]", None),
288305
];
289306

290307
Tester::new(NoExtendNative::NAME, NoExtendNative::PLUGIN, pass, fail).test_and_snapshot();

crates/oxc_linter/src/snapshots/eslint_no_extend_native.snap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,9 @@ source: crates/oxc_linter/src/tester.rs
156156
1Array.prototype.p ??= 0
157157
· ───────────────────────
158158
╰────
159+
160+
eslint(no-extend-native): Array prototype is read-only, properties should not be added.
161+
╭─[no_extend_native.tsx:1:1]
162+
1 │ [Array.prototype.p] = [() => {}]
163+
· ───────────────────
164+
╰────

0 commit comments

Comments
 (0)