diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index 1c45cfac19753..7d43a48e74aff 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -3,6 +3,7 @@ use std::ptr; use phf::{Set, phf_set}; use rustc_hash::FxHashMap; +use oxc_allocator::GetAddress; use oxc_ast::{AstKind, ModuleDeclarationKind, ast::*}; use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_ecmascript::{BoundNames, IsSimpleParameterList, PropName}; @@ -900,16 +901,24 @@ pub fn check_super(sup: &Super, ctx: &SemanticBuilder<'_>) { // Not in a class. `super` only valid in an object method. for scope_id in ctx.scoping.scope_ancestors(ctx.current_scope_id) { let flags = ctx.scoping.scope_flags(scope_id); - if flags.is_function() - && matches!( - ctx.nodes.parent_kind(ctx.scoping.get_node_id(scope_id)), - AstKind::ObjectProperty(_) - ) - { - if let Some(super_call_span) = super_call_span { - ctx.error(unexpected_super_call(super_call_span)); + if flags.is_function() && !flags.is_arrow() { + let func_node_id = ctx.scoping.get_node_id(scope_id); + if let AstKind::ObjectProperty(prop) = ctx.nodes.parent_kind(func_node_id) { + if prop.method || prop.kind != PropertyKind::Init { + // Function's parent is an `ObjectProperty` representing a method/getter/setter. + // Check the function is the value of the property, not computed key. + // Valid: `obj = { method() { super.foo } }` + // Invalid: `obj = { [ function() { super.foo } ]() {} }` + let func_kind = ctx.nodes.kind(func_node_id); + if func_kind.address() == prop.value.address() { + if let Some(super_call_span) = super_call_span { + ctx.error(unexpected_super_call(super_call_span)); + } + return; + } + } } - return; + break; } } diff --git a/tasks/coverage/misc/fail/oxc-13323.js b/tasks/coverage/misc/fail/oxc-13323.js new file mode 100644 index 0000000000000..7673c3727b99e --- /dev/null +++ b/tasks/coverage/misc/fail/oxc-13323.js @@ -0,0 +1,17 @@ +o = { + foo: function() { + super.foo; + }, + + bar() { + return function() { + super.bar; + }; + }, + + [ function() { super.qux; } ]() {}, + + get [ function() { super.bing; } ]() {}, + + set [ function() { super.bong; } ](v) {}, +}; diff --git a/tasks/coverage/misc/pass/oxc-13323.js b/tasks/coverage/misc/pass/oxc-13323.js new file mode 100644 index 0000000000000..44dd74e31dc9f --- /dev/null +++ b/tasks/coverage/misc/pass/oxc-13323.js @@ -0,0 +1,16 @@ +o = { + foo() { + super.foo(); + return () => super.foo(); + }, + + get bar() { + const f = () => super.bar; + return super.bar; + }, + + set bar(v) { + const f = () => super.bar; + super.bar = v; + }, +}; diff --git a/tasks/coverage/snapshots/codegen_misc.snap b/tasks/coverage/snapshots/codegen_misc.snap index 5360ba78cdc0d..3459728d0bf56 100644 --- a/tasks/coverage/snapshots/codegen_misc.snap +++ b/tasks/coverage/snapshots/codegen_misc.snap @@ -1,3 +1,3 @@ codegen_misc Summary: -AST Parsed : 47/47 (100.00%) -Positive Passed: 47/47 (100.00%) +AST Parsed : 48/48 (100.00%) +Positive Passed: 48/48 (100.00%) diff --git a/tasks/coverage/snapshots/formatter_misc.snap b/tasks/coverage/snapshots/formatter_misc.snap index 2cb3c127d5766..4ccbad6a7c14e 100644 --- a/tasks/coverage/snapshots/formatter_misc.snap +++ b/tasks/coverage/snapshots/formatter_misc.snap @@ -1,6 +1,6 @@ formatter_misc Summary: -AST Parsed : 47/47 (100.00%) -Positive Passed: 44/47 (93.62%) +AST Parsed : 48/48 (100.00%) +Positive Passed: 45/48 (93.75%) Expect to Parse: tasks/coverage/misc/pass/oxc-12612.ts Expect to Parse: tasks/coverage/misc/pass/oxc-2592.ts diff --git a/tasks/coverage/snapshots/parser_babel.snap b/tasks/coverage/snapshots/parser_babel.snap index 38e7eedb11a72..473f6387ac65a 100644 --- a/tasks/coverage/snapshots/parser_babel.snap +++ b/tasks/coverage/snapshots/parser_babel.snap @@ -3,7 +3,7 @@ commit: 41d96516 parser_babel Summary: AST Parsed : 2407/2423 (99.34%) Positive Passed: 2385/2423 (98.43%) -Negative Passed: 1645/1755 (93.73%) +Negative Passed: 1646/1755 (93.79%) Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/invalid-startindex-and-startline-specified-without-startcolumn/input.js Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/categorized/startline-and-startcolumn-specified/input.js @@ -20,8 +20,6 @@ Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/co Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/core/sourcetype-commonjs/invalid-allowReturnOutsideFunction-true/input.js -Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/class-methods/direct-super-in-object-method/input.js - Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/destructuring/error-operator-for-default/input.js Expect Syntax Error: tasks/coverage/babel/packages/babel-parser/test/fixtures/es2015/for-of/invalid-let-as-identifier/input.js @@ -2963,6 +2961,14 @@ Expect to Parse: tasks/coverage/babel/packages/babel-parser/test/fixtures/typesc · ─────────── ╰──── + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[babel/packages/babel-parser/test/fixtures/es2015/class-methods/direct-super-in-object-method/input.js:4:14] + 3 │ get: function(){ + 4 │ return super.foo; + · ───── + 5 │ } + ╰──── + × Super calls are not permitted outside constructors or in nested functions inside constructors. ╭─[babel/packages/babel-parser/test/fixtures/es2015/class-methods/direct-super-outside-constructor/input.js:2:9] 1 │ class A { diff --git a/tasks/coverage/snapshots/parser_misc.snap b/tasks/coverage/snapshots/parser_misc.snap index ef18efffa34ff..3f4579684208f 100644 --- a/tasks/coverage/snapshots/parser_misc.snap +++ b/tasks/coverage/snapshots/parser_misc.snap @@ -1,7 +1,7 @@ parser_misc Summary: -AST Parsed : 47/47 (100.00%) -Positive Passed: 47/47 (100.00%) -Negative Passed: 77/77 (100.00%) +AST Parsed : 48/48 (100.00%) +Positive Passed: 48/48 (100.00%) +Negative Passed: 78/78 (100.00%) × Cannot assign to 'arguments' in strict mode ╭─[misc/fail/arguments-eval.ts:1:10] @@ -445,6 +445,46 @@ Negative Passed: 77/77 (100.00%) 6 │ }, ╰──── + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[misc/fail/oxc-13323.js:3:5] + 2 │ foo: function() { + 3 │ super.foo; + · ───── + 4 │ }, + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[misc/fail/oxc-13323.js:8:7] + 7 │ return function() { + 8 │ super.bar; + · ───── + 9 │ }; + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[misc/fail/oxc-13323.js:12:18] + 11 │ + 12 │ [ function() { super.qux; } ]() {}, + · ───── + 13 │ + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[misc/fail/oxc-13323.js:14:22] + 13 │ + 14 │ get [ function() { super.bing; } ]() {}, + · ───── + 15 │ + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[misc/fail/oxc-13323.js:16:22] + 15 │ + 16 │ set [ function() { super.bong; } ](v) {}, + · ───── + 17 │ }; + ╰──── + × Unexpected token ╭─[misc/fail/oxc-169.js:2:1] 1 │ 1<(V=82< diff --git a/tasks/coverage/snapshots/parser_typescript.snap b/tasks/coverage/snapshots/parser_typescript.snap index 4cfd38eca038c..0f9ef0ad4202a 100644 --- a/tasks/coverage/snapshots/parser_typescript.snap +++ b/tasks/coverage/snapshots/parser_typescript.snap @@ -13201,6 +13201,30 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc ╰──── help: replace with `super()` or `super.prop` or `super[prop]` + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES5.ts:17:9] + 16 │ p1: function () { + 17 │ super.method(); + · ───── + 18 │ }, + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES5.ts:20:9] + 19 │ p2: function f() { + 20 │ super.method(); + · ───── + 21 │ }, + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES5.ts:23:9] + 22 │ p3: () => { + 23 │ super.method(); + · ───── + 24 │ } + ╰──── + × 'super' can only be referenced in members of derived classes or object literal expressions. ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES5.ts:39:17] 38 │ method() { @@ -13241,6 +13265,30 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc 53 │ }, ╰──── + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES6.ts:17:9] + 16 │ p1: function () { + 17 │ super.method(); + · ───── + 18 │ }, + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES6.ts:20:9] + 19 │ p2: function f() { + 20 │ super.method(); + · ───── + 21 │ }, + ╰──── + + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES6.ts:23:9] + 22 │ p3: () => { + 23 │ super.method(); + · ───── + 24 │ } + ╰──── + × 'super' can only be referenced in members of derived classes or object literal expressions. ╭─[typescript/tests/cases/compiler/superInObjectLiterals_ES6.ts:39:17] 38 │ method() { @@ -13308,6 +13356,14 @@ Expect to Parse: tasks/coverage/typescript/tests/cases/conformance/parser/ecmasc ╰──── help: replace with `super()` or `super.prop` or `super[prop]` + × 'super' can only be referenced in members of derived classes or object literal expressions. + ╭─[typescript/tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts:11:20] + 10 │ test: function () { + 11 │ return super._foo; + · ───── + 12 │ } + ╰──── + × 'super' can only be referenced in members of derived classes or object literal expressions. ╭─[typescript/tests/cases/compiler/super_inside-object-literal-getters-and-setters.ts:21:24] 20 │ get F() { diff --git a/tasks/coverage/snapshots/semantic_misc.snap b/tasks/coverage/snapshots/semantic_misc.snap index 16b4f6357725a..cbb212aece12c 100644 --- a/tasks/coverage/snapshots/semantic_misc.snap +++ b/tasks/coverage/snapshots/semantic_misc.snap @@ -1,6 +1,6 @@ semantic_misc Summary: -AST Parsed : 47/47 (100.00%) -Positive Passed: 31/47 (65.96%) +AST Parsed : 48/48 (100.00%) +Positive Passed: 32/48 (66.67%) semantic Error: tasks/coverage/misc/pass/oxc-11593.ts Scope children mismatch: after transform: ScopeId(0): [ScopeId(1)] diff --git a/tasks/coverage/snapshots/transformer_misc.snap b/tasks/coverage/snapshots/transformer_misc.snap index 12d220ab805e9..d64c7c9443577 100644 --- a/tasks/coverage/snapshots/transformer_misc.snap +++ b/tasks/coverage/snapshots/transformer_misc.snap @@ -1,3 +1,3 @@ transformer_misc Summary: -AST Parsed : 47/47 (100.00%) -Positive Passed: 47/47 (100.00%) +AST Parsed : 48/48 (100.00%) +Positive Passed: 48/48 (100.00%)