Repository: swc-project/swc (rust)

Issue:
use super where is not a method
### Describe the bug

normally should receive a error `'super' is only allowed in object methods and classes.` or `Uncaught SyntaxError: 'super' keyword unexpected here`
babel has a parser option for this `allowSuperOutsideMethod `

### Input code

```typescript
super.x
class a{
	a = function a(){
      super.x
    }
}
let obj = {
	a: function a(){
    	super.x
    }
}
```


### Config

_No response_

### Playground link

_No response_

### Expected behavior

should throw error

### Actual behavior

_No response_

### Version

1.2.128

### Additional context

_No response_

Pull request:
feat(ecma/parser): add allowSuperOutsideMethod option
**Description:**
throw an error when use `super` outside of class and object methods

**BREAKING CHANGE:**
esConfig:
add `allowSuperOutsideMethod`: By default, super use is not allowed outside of class and object methods. Set this to true to accept such code.

for TS, I found that tsc will output the result and throw an error at the same time, so I make this always true
**Related issue (if exists):**
close #3230

Patch:
diff --git a/crates/swc_ecma_parser/src/lib.rs b/crates/swc_ecma_parser/src/lib.rs
index 8186de4fee..ec19caa94e 100644
--- a/crates/swc_ecma_parser/src/lib.rs
+++ b/crates/swc_ecma_parser/src/lib.rs
@@ -253,6 +253,15 @@ impl Syntax {
             Syntax::Typescript(_) => true,
         }
     }
+    pub fn allow_super_outside_method(self) -> bool {
+        match self {
+            Syntax::Es(EsConfig {
+                allow_super_outside_method,
+                ..
+            }) => allow_super_outside_method,
+            Syntax::Typescript(_) => true,
+        }
+    }
 
     pub(crate) fn early_errors(self) -> bool {
         match self {
@@ -313,6 +322,9 @@ pub struct EsConfig {
 
     #[serde(default, rename = "privateInObject")]
     pub private_in_object: bool,
+
+    #[serde(default, rename = "allowSuperOutsideMethod")]
+    pub allow_super_outside_method: bool,
 }
 
 /// Syntactic context.
@@ -356,6 +368,9 @@ pub struct Context {
 
     /// If true, `:` should not be treated as a type annotation.
     dont_parse_colon_as_type_ann: bool,
+
+    // If true, allow super.x and super[x]
+    allow_direct_super: bool,
 }
 
 #[cfg(test)]
diff --git a/crates/swc_ecma_parser/src/parser/class_and_fn.rs b/crates/swc_ecma_parser/src/parser/class_and_fn.rs
index 5a4f6a0e59..1d5728db0a 100644
--- a/crates/swc_ecma_parser/src/parser/class_and_fn.rs
+++ b/crates/swc_ecma_parser/src/parser/class_and_fn.rs
@@ -287,8 +287,11 @@ impl<'a, I: Tokens> Parser<I> {
                 }));
                 continue;
             }
-
-            elems.push(self.parse_class_member()?);
+            let mut p = self.with_ctx(Context {
+                allow_direct_super: true,
+                ..self.ctx()
+            });
+            elems.push(p.parse_class_member()?);
         }
         Ok(elems)
     }
@@ -992,25 +995,29 @@ impl<'a, I: Tokens> Parser<I> {
             }
         };
 
-        let ctx = Context {
-            in_async: is_async,
-            in_generator: is_generator,
-            ..self.ctx()
-        };
-
         let ident = if T::is_fn_expr() {
             //
             self.with_ctx(Context {
+                in_async: is_async,
                 in_generator: is_generator,
-                ..ctx
+                allow_direct_super: false,
+                ..self.ctx()
             })
             .parse_maybe_opt_binding_ident()?
         } else {
             // function declaration does not change context for `BindingIdentifier`.
-            self.parse_maybe_opt_binding_ident()?
+            self.with_ctx(Context {
+                allow_direct_super: false,
+                ..self.ctx()
+            })
+            .parse_maybe_opt_binding_ident()?
         };
 
-        self.parse_with(|p| {
+        self.with_ctx(Context {
+            allow_direct_super: false,
+            ..self.ctx()
+        })
+        .parse_with(|p| {
             let f = p.parse_fn_args_body(
                 decorators,
                 start,
@@ -1049,7 +1056,6 @@ impl<'a, I: Tokens> Parser<I> {
         F: FnOnce(&mut Self) -> PResult<Vec<Param>>,
     {
         trace_cur!(self, parse_fn_args_body);
-
         // let prev_in_generator = self.ctx().in_generator;
         let ctx = Context {
             in_async: is_async,
@@ -1203,9 +1209,14 @@ impl<'a, I: Tokens> Parser<I> {
         trace_cur!(self, make_method);
 
         let is_static = static_token.is_some();
-        let function = self.parse_with(|p| {
-            p.parse_fn_args_body(decorators, start, parse_args, is_async, is_generator)
-        })?;
+        let function = self
+            .with_ctx(Context {
+                allow_direct_super: true,
+                ..self.ctx()
+            })
+            .parse_with(|p| {
+                p.parse_fn_args_body(decorators, start, parse_args, is_async, is_generator)
+            })?;
 
         match kind {
             MethodKind::Getter | MethodKind::Setter
diff --git a/crates/swc_ecma_parser/src/parser/expr.rs b/crates/swc_ecma_parser/src/parser/expr.rs
index f8aa7e3e2c..00ceddfa3e 100644
--- a/crates/swc_ecma_parser/src/parser/expr.rs
+++ b/crates/swc_ecma_parser/src/parser/expr.rs
@@ -1135,7 +1135,11 @@ impl<'a, I: Tokens> Parser<I> {
                 Box::new(match obj {
                     Callee::Import(..) => unreachable!(),
                     Callee::Super(obj) => {
-                        if question_dot_token.is_some() {
+                        if !self.ctx().allow_direct_super
+                            && !self.input.syntax().allow_super_outside_method()
+                        {
+                            syntax_error!(self, self.input.cur_span(), SyntaxError::InvalidSuper);
+                        } else if question_dot_token.is_some() {
                             if no_call {
                                 syntax_error!(
                                     self,
@@ -1223,7 +1227,11 @@ impl<'a, I: Tokens> Parser<I> {
                         }
                     }
                     Callee::Super(obj) => {
-                        if question_dot_token.is_some() {
+                        if !self.ctx().allow_direct_super
+                            && !self.input.syntax().allow_super_outside_method()
+                        {
+                            syntax_error!(self, self.input.cur_span(), SyntaxError::InvalidSuper);
+                        } else if question_dot_token.is_some() {
                             if no_call {
                                 syntax_error!(
                                     self,
diff --git a/crates/swc_ecma_parser/src/parser/object.rs b/crates/swc_ecma_parser/src/parser/object.rs
index af75d4804c..8c855e0eeb 100644
--- a/crates/swc_ecma_parser/src/parser/object.rs
+++ b/crates/swc_ecma_parser/src/parser/object.rs
@@ -155,6 +155,10 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
         if eat!(self, '*') {
             let name = self.parse_prop_name()?;
             return self
+                .with_ctx(Context {
+                    allow_direct_super: true,
+                    ..self.ctx()
+                })
                 .parse_fn_args_body(
                     // no decorator in an object literal
                     vec![],
@@ -207,6 +211,10 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
         // Handle `a(){}` (and async(){} / get(){} / set(){})
         if (self.input.syntax().typescript() && is!(self, '<')) || is!(self, '(') {
             return self
+                .with_ctx(Context {
+                    allow_direct_super: true,
+                    ..self.ctx()
+                })
                 .parse_fn_args_body(
                     // no decorator in an object literal
                     vec![],
@@ -263,117 +271,128 @@ impl<I: Tokens> ParseObject<Box<Expr>> for Parser<I> {
                 let is_generator = ident.sym == js_word!("async") && eat!(self, '*');
                 let key = self.parse_prop_name()?;
                 let key_span = key.span();
+                self.with_ctx(Context {
+                    allow_direct_super: true,
+                    ..self.ctx()
+                })
+                .parse_with(|parser| {
+                    match ident.sym {
+                        js_word!("get") => parser
+                            .parse_fn_args_body(
+                                // no decorator in an object literal
+                                vec![],
+                                start,
+                                |p| {
+                                    let params = p.parse_formal_params()?;
+
+                                    if params.iter().filter(|p| is_not_this(p)).count() != 0 {
+                                        p.emit_err(key_span, SyntaxError::TS1094);
+                                    }
 
-                match ident.sym {
-                    js_word!("get") => self
-                        .parse_fn_args_body(
-                            // no decorator in an object literal
-                            vec![],
-                            start,
-                            |p| {
-                                let params = p.parse_formal_params()?;
-
-                                if params.iter().filter(|p| is_not_this(p)).count() != 0 {
-                                    p.emit_err(key_span, SyntaxError::TS1094);
-                                }
-
-                                Ok(params)
-                            },
-                            false,
-                            false,
-                        )
-                        .map(
-                            |Function {
-                                 body,
-                                 type_params,
-                                 return_type,
-                                 ..
-                             }| {
-                                if let Some(type_params) = type_params {
-                                    self.emit_err(type_params.span(), SyntaxError::TS1094);
-                                }
-
-                                if self.input.syntax().typescript()
-                                    && self.input.target() == EsVersion::Es3
-                                {
-                                    self.emit_err(key_span, SyntaxError::TS1056);
-                                }
-
-                                PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp {
-                                    span: span!(self, start),
-                                    key,
-                                    type_ann: return_type,
-                                    body,
-                                })))
-                            },
-                        ),
-                    js_word!("set") => self
-                        .parse_fn_args_body(
-                            // no decorator in an object literal
-                            vec![],
-                            start,
-                            |p| {
-                                let params = p.parse_formal_params()?;
-
-                                if params.iter().filter(|p| is_not_this(p)).count() != 1 {
-                                    p.emit_err(key_span, SyntaxError::TS1094);
-                                }
-
-                                if !params.is_empty() {
-                                    if let Pat::Rest(..) = params[0].pat {
-                                        p.emit_err(params[0].span(), SyntaxError::RestPatInSetter);
+                                    Ok(params)
+                                },
+                                false,
+                                false,
+                            )
+                            .map(
+                                |Function {
+                                     body,
+                                     type_params,
+                                     return_type,
+                                     ..
+                                 }| {
+                                    if let Some(type_params) = type_params {
+                                        parser.emit_err(type_params.span(), SyntaxError::TS1094);
+                                    }
+
+                                    if parser.input.syntax().typescript()
+                                        && parser.input.target() == EsVersion::Es3
+                                    {
+                                        parser.emit_err(key_span, SyntaxError::TS1056);
+                                    }
+
+                                    PropOrSpread::Prop(Box::new(Prop::Getter(GetterProp {
+                                        span: span!(parser, start),
+                                        key,
+                                        type_ann: return_type,
+                                        body,
+                                    })))
+                                },
+                            ),
+                        js_word!("set") => parser
+                            .parse_fn_args_body(
+                                // no decorator in an object literal
+                                vec![],
+                                start,
+                                |p| {
+                                    let params = p.parse_formal_params()?;
+
+                                    if params.iter().filter(|p| is_not_this(p)).count() != 1 {
+                                        p.emit_err(key_span, SyntaxError::TS1094);
+                                    }
+
+                                    if !params.is_empty() {
+                                        if let Pat::Rest(..) = params[0].pat {
+                                            p.emit_err(
+                                                params[0].span(),
+                                                SyntaxError::RestPatInSetter,
+                                            );
+                                        }
                                     }
-                                }
-
-                                if p.input.syntax().typescript()
-                                    && p.input.target() == EsVersion::Es3
-                                {
-                                    p.emit_err(key_span, SyntaxError::TS1056);
-                                }
-
-                                Ok(params)
-                            },
-                            false,
-                            false,
-                        )
-                        .map(
-                            |Function {
-                                 params,
-                                 body,
-                                 type_params,
-                                 ..
-                             }| {
-                                if let Some(type_params) = type_params {
-                                    self.emit_err(type_params.span(), SyntaxError::TS1094);
-                                }
-
-                                // debug_assert_eq!(params.len(), 1);
-                                PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp {
-                                    span: span!(self, start),
+
+                                    if p.input.syntax().typescript()
+                                        && p.input.target() == EsVersion::Es3
+                                    {
+                                        p.emit_err(key_span, SyntaxError::TS1056);
+                                    }
+
+                                    Ok(params)
+                                },
+                                false,
+                                false,
+                            )
+                            .map(
+                                |Function {
+                                     params,
+                                     body,
+                                     type_params,
+                                     ..
+                                 }| {
+                                    if let Some(type_params) = type_params {
+                                        parser.emit_err(type_params.span(), SyntaxError::TS1094);
+                                    }
+
+                                    // debug_assert_eq!(params.len(), 1);
+                                    PropOrSpread::Prop(Box::new(Prop::Setter(SetterProp {
+                                        span: span!(parser, start),
+                                        key,
+                                        body,
+                                        param: params
+                                            .into_iter()
+                                            .map(|p| p.pat)
+                                            .next()
+                                            .unwrap_or(Pat::Invalid(Invalid { span: key_span })),
+                                    })))
+                                },
+                            ),
+                        js_word!("async") => parser
+                            .parse_fn_args_body(
+                                // no decorator in an object literal
+                                vec![],
+                                start,
+                                |p| p.parse_unique_formal_params(),
+                                true,
+                                is_generator,
+                            )
+                            .map(|function| {
+                                PropOrSpread::Prop(Box::new(Prop::Method(MethodProp {
                                     key,
-                                    body,
-                                    param: params
-                                        .into_iter()
-                                        .map(|p| p.pat)
-                                        .next()
-                                        .unwrap_or(Pat::Invalid(Invalid { span: key_span })),
+                                    function,
                                 })))
-                            },
-                        ),
-                    js_word!("async") => self
-                        .parse_fn_args_body(
-                            // no decorator in an object literal
-                            vec![],
-                            start,
-                            |p| p.parse_unique_formal_params(),
-                            true,
-                            is_generator,
-                        )
-                        .map(|function| {
-                            PropOrSpread::Prop(Box::new(Prop::Method(MethodProp { key, function })))
-                        }),
-                    _ => unreachable!(),
-                }
+                            }),
+                        _ => unreachable!(),
+                    }
+                })
             }
             _ => {
                 if self.input.syntax().typescript() {
diff --git a/crates/swc_ecma_transforms_compat/src/es2015/object_super.rs b/crates/swc_ecma_transforms_compat/src/es2015/object_super.rs
index b079c2536d..7cb2bd699e 100644
--- a/crates/swc_ecma_transforms_compat/src/es2015/object_super.rs
+++ b/crates/swc_ecma_transforms_compat/src/es2015/object_super.rs
@@ -464,6 +464,7 @@ mod tests {
     use super::*;
     use crate::es2015::{function_name, shorthand_property::shorthand};
     use swc_common::{chain, Mark};
+    use swc_ecma_parser::{EsConfig, Syntax};
     use swc_ecma_transforms_base::resolver::resolver_with_mark;
     use swc_ecma_transforms_testing::test;
     test!(
@@ -575,7 +576,10 @@ mod tests {
     };"#
     );
     test!(
-        ::swc_ecma_parser::Syntax::default(),
+        Syntax::Es(EsConfig {
+            allow_super_outside_method: true,
+            ..Default::default()
+        }),
         |_| {
             let top_level_mark = Mark::fresh(Mark::root());
             chain!(


Test patch:
diff --git a/crates/swc_ecma_parser/src/parser/expr/tests.rs b/crates/swc_ecma_parser/src/parser/expr/tests.rs
index 0c1fcb7a0a..f3518ce5eb 100644
--- a/crates/swc_ecma_parser/src/parser/expr/tests.rs
+++ b/crates/swc_ecma_parser/src/parser/expr/tests.rs
@@ -9,6 +9,7 @@ use test::Bencher;
 
 fn syntax() -> Syntax {
     Syntax::Es(EsConfig {
+        allow_super_outside_method: true,
         ..Default::default()
     })
 }
diff --git a/crates/swc_ecma_parser/tests/span.rs b/crates/swc_ecma_parser/tests/span.rs
index 618e6336d5..9392ab8b5b 100644
--- a/crates/swc_ecma_parser/tests/span.rs
+++ b/crates/swc_ecma_parser/tests/span.rs
@@ -1,7 +1,7 @@
 use std::path::PathBuf;
 use swc_common::{comments::SingleThreadedComments, errors::Handler, Spanned};
 use swc_ecma_ast::*;
-use swc_ecma_parser::{lexer::Lexer, Parser, StringInput, Syntax, TsConfig};
+use swc_ecma_parser::{lexer::Lexer, EsConfig, Parser, StringInput, Syntax, TsConfig};
 use swc_ecma_visit::{Visit, VisitWith};
 
 #[testing::fixture("tests/span/**/*.js")]
@@ -20,12 +20,21 @@ fn span(entry: PathBuf) {
 
         let comments = SingleThreadedComments::default();
         let lexer = Lexer::new(
-            Syntax::Typescript(TsConfig {
-                tsx: true,
-                decorators: true,
-                no_early_errors: true,
-                ..Default::default()
-            }),
+            if file_name.ends_with(".js") {
+                Syntax::Es(EsConfig {
+                    jsx: true,
+                    decorators: true,
+                    static_blocks: true,
+                    ..Default::default()
+                })
+            } else {
+                Syntax::Typescript(TsConfig {
+                    tsx: true,
+                    decorators: true,
+                    no_early_errors: true,
+                    ..Default::default()
+                })
+            },
             Default::default(),
             (&*src).into(),
             Some(&comments),
diff --git a/crates/swc_ecma_parser/tests/span/js/super/expr.js b/crates/swc_ecma_parser/tests/span/js/super/expr.js
new file mode 100644
index 0000000000..341bc51d9b
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/expr.js
@@ -0,0 +1,1 @@
+super.x;
\ No newline at end of file
diff --git a/crates/swc_ecma_parser/tests/span/js/super/expr.js.spans b/crates/swc_ecma_parser/tests/span/js/super/expr.js.spans
new file mode 100644
index 0000000000..367ca0479c
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/expr.js.spans
@@ -0,0 +1,6 @@
+error: Invalid access to super
+ --> $DIR/tests/span/js/super/expr.js:1:7
+  |
+1 | super.x;
+  |       ^
+
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj1.js b/crates/swc_ecma_parser/tests/span/js/super/obj1.js
new file mode 100644
index 0000000000..59f48b307b
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj1.js
@@ -0,0 +1,5 @@
+let o2 = {
+    a: function a() {
+        super.x;
+    },
+};
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj1.js.spans b/crates/swc_ecma_parser/tests/span/js/super/obj1.js.spans
new file mode 100644
index 0000000000..d5f7d0e9c5
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj1.js.spans
@@ -0,0 +1,6 @@
+error: Invalid access to super
+ --> $DIR/tests/span/js/super/obj1.js:3:15
+  |
+3 |         super.x;
+  |               ^
+
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj2.js b/crates/swc_ecma_parser/tests/span/js/super/obj2.js
new file mode 100644
index 0000000000..3dc484f325
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj2.js
@@ -0,0 +1,3 @@
+let o = {
+    a: super.x,
+};
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj2.js.spans b/crates/swc_ecma_parser/tests/span/js/super/obj2.js.spans
new file mode 100644
index 0000000000..b6ae7f5667
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj2.js.spans
@@ -0,0 +1,6 @@
+error: Invalid access to super
+ --> $DIR/tests/span/js/super/obj2.js:2:14
+  |
+2 |     a: super.x,
+  |              ^
+
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj3.js b/crates/swc_ecma_parser/tests/span/js/super/obj3.js
new file mode 100644
index 0000000000..e4c68df3d1
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj3.js
@@ -0,0 +1,5 @@
+let o = {
+    a() {
+        let o1 = { b: super.b };
+    },
+};
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj3.js.spans b/crates/swc_ecma_parser/tests/span/js/super/obj3.js.spans
new file mode 100644
index 0000000000..847115d82e
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj3.js.spans
@@ -0,0 +1,244 @@
+warning: Module
+ --> $DIR/tests/span/js/super/obj3.js:1:1
+  |
+1 | / let o = {
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |__^
+
+warning: ModuleItem
+ --> $DIR/tests/span/js/super/obj3.js:1:1
+  |
+1 | / let o = {
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |__^
+
+warning: Stmt
+ --> $DIR/tests/span/js/super/obj3.js:1:1
+  |
+1 | / let o = {
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |__^
+
+warning: Decl
+ --> $DIR/tests/span/js/super/obj3.js:1:1
+  |
+1 | / let o = {
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |__^
+
+warning: VarDecl
+ --> $DIR/tests/span/js/super/obj3.js:1:1
+  |
+1 | / let o = {
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |__^
+
+warning: VarDeclarator
+ --> $DIR/tests/span/js/super/obj3.js:1:5
+  |
+1 |   let o = {
+  |  _____^
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |_^
+
+warning: Pat
+ --> $DIR/tests/span/js/super/obj3.js:1:5
+  |
+1 | let o = {
+  |     ^
+
+warning: Ident
+ --> $DIR/tests/span/js/super/obj3.js:1:5
+  |
+1 | let o = {
+  |     ^
+
+warning: Expr
+ --> $DIR/tests/span/js/super/obj3.js:1:9
+  |
+1 |   let o = {
+  |  _________^
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |_^
+
+warning: ObjectLit
+ --> $DIR/tests/span/js/super/obj3.js:1:9
+  |
+1 |   let o = {
+  |  _________^
+2 | |     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+5 | | };
+  | |_^
+
+warning: PropOrSpread
+ --> $DIR/tests/span/js/super/obj3.js:2:5
+  |
+2 | /     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+  | |_____^
+
+warning: Prop
+ --> $DIR/tests/span/js/super/obj3.js:2:5
+  |
+2 | /     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+  | |_____^
+
+warning: MethodProp
+ --> $DIR/tests/span/js/super/obj3.js:2:5
+  |
+2 | /     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+  | |_____^
+
+warning: PropName
+ --> $DIR/tests/span/js/super/obj3.js:2:5
+  |
+2 |     a() {
+  |     ^
+
+warning: Ident
+ --> $DIR/tests/span/js/super/obj3.js:2:5
+  |
+2 |     a() {
+  |     ^
+
+warning: Function
+ --> $DIR/tests/span/js/super/obj3.js:2:5
+  |
+2 | /     a() {
+3 | |         let o1 = { b: super.b };
+4 | |     },
+  | |_____^
+
+warning: BlockStmt
+ --> $DIR/tests/span/js/super/obj3.js:2:9
+  |
+2 |       a() {
+  |  _________^
+3 | |         let o1 = { b: super.b };
+4 | |     },
+  | |_____^
+
+warning: Stmt
+ --> $DIR/tests/span/js/super/obj3.js:3:9
+  |
+3 |         let o1 = { b: super.b };
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: Decl
+ --> $DIR/tests/span/js/super/obj3.js:3:9
+  |
+3 |         let o1 = { b: super.b };
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: VarDecl
+ --> $DIR/tests/span/js/super/obj3.js:3:9
+  |
+3 |         let o1 = { b: super.b };
+  |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: VarDeclarator
+ --> $DIR/tests/span/js/super/obj3.js:3:13
+  |
+3 |         let o1 = { b: super.b };
+  |             ^^^^^^^^^^^^^^^^^^^
+
+warning: Pat
+ --> $DIR/tests/span/js/super/obj3.js:3:13
+  |
+3 |         let o1 = { b: super.b };
+  |             ^^
+
+warning: Ident
+ --> $DIR/tests/span/js/super/obj3.js:3:13
+  |
+3 |         let o1 = { b: super.b };
+  |             ^^
+
+warning: Expr
+ --> $DIR/tests/span/js/super/obj3.js:3:18
+  |
+3 |         let o1 = { b: super.b };
+  |                  ^^^^^^^^^^^^^^
+
+warning: ObjectLit
+ --> $DIR/tests/span/js/super/obj3.js:3:18
+  |
+3 |         let o1 = { b: super.b };
+  |                  ^^^^^^^^^^^^^^
+
+warning: PropOrSpread
+ --> $DIR/tests/span/js/super/obj3.js:3:20
+  |
+3 |         let o1 = { b: super.b };
+  |                    ^^^^^^^^^^
+
+warning: Prop
+ --> $DIR/tests/span/js/super/obj3.js:3:20
+  |
+3 |         let o1 = { b: super.b };
+  |                    ^^^^^^^^^^
+
+warning: KeyValueProp
+ --> $DIR/tests/span/js/super/obj3.js:3:20
+  |
+3 |         let o1 = { b: super.b };
+  |                    ^^^^^^^^^^
+
+warning: PropName
+ --> $DIR/tests/span/js/super/obj3.js:3:20
+  |
+3 |         let o1 = { b: super.b };
+  |                    ^
+
+warning: Ident
+ --> $DIR/tests/span/js/super/obj3.js:3:20
+  |
+3 |         let o1 = { b: super.b };
+  |                    ^
+
+warning: Expr
+ --> $DIR/tests/span/js/super/obj3.js:3:23
+  |
+3 |         let o1 = { b: super.b };
+  |                       ^^^^^^^
+
+warning: Super
+ --> $DIR/tests/span/js/super/obj3.js:3:23
+  |
+3 |         let o1 = { b: super.b };
+  |                       ^^^^^
+
+warning: Ident
+ --> $DIR/tests/span/js/super/obj3.js:3:29
+  |
+3 |         let o1 = { b: super.b };
+  |                             ^
+
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj4.js b/crates/swc_ecma_parser/tests/span/js/super/obj4.js
new file mode 100644
index 0000000000..f7ebd21760
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj4.js
@@ -0,0 +1,9 @@
+let o = {
+    a() {
+        let o1 = {
+            b: function b(){
+                super.b
+            }
+        };
+    },
+};
diff --git a/crates/swc_ecma_parser/tests/span/js/super/obj4.js.spans b/crates/swc_ecma_parser/tests/span/js/super/obj4.js.spans
new file mode 100644
index 0000000000..faaa32e864
--- /dev/null
+++ b/crates/swc_ecma_parser/tests/span/js/super/obj4.js.spans
@@ -0,0 +1,6 @@
+error: Invalid access to super
+ --> $DIR/tests/span/js/super/obj4.js:5:23
+  |
+5 |                 super.b
+  |                       ^
+
diff --git a/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs b/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs
index 6524e55820..4a2a389441 100644
--- a/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs
+++ b/crates/swc_ecma_transforms_typescript/tests/strip_correctness.rs
@@ -159,6 +159,7 @@ fn identity(entry: PathBuf) {
                 export_default_from: true,
                 private_in_object: true,
                 import_assertions: true,
+                allow_super_outside_method: true,
                 ..Default::default()
             }),
             (&*js_fm).into(),