@@ -193,6 +193,10 @@ thread_local! {
193193 /// super() is allowed when this is >0.
194194 static CONSTRUCTOR_CONTEXT : RefCell <usize > = const { RefCell :: new( 0 ) } ;
195195 static CONSTRUCTOR_CONTEXT_STACK : RefCell <Vec <usize >> = const { RefCell :: new( Vec :: new( ) ) } ;
196+ /// Whether the current class being parsed has an extends clause (heritage).
197+ /// Stacked to support nested classes.
198+ static CLASS_HAS_HERITAGE : RefCell <bool > = const { RefCell :: new( false ) } ;
199+ static CLASS_HAS_HERITAGE_STACK : RefCell <Vec <bool >> = const { RefCell :: new( Vec :: new( ) ) } ;
196200}
197201fn forbid_in ( ) -> bool {
198202 FORBID_IN . with ( |c| * c. borrow ( ) > 0 )
@@ -240,6 +244,20 @@ fn push_constructor_context() {
240244fn pop_constructor_context ( ) {
241245 CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
242246}
247+ fn class_has_heritage ( ) -> bool {
248+ CLASS_HAS_HERITAGE . with ( |c| * c. borrow ( ) )
249+ }
250+ fn push_class_heritage ( has : bool ) {
251+ CLASS_HAS_HERITAGE_STACK . with ( |s| {
252+ s. borrow_mut ( ) . push ( CLASS_HAS_HERITAGE . with ( |c| * c. borrow ( ) ) ) ;
253+ } ) ;
254+ CLASS_HAS_HERITAGE . with ( |c| * c. borrow_mut ( ) = has) ;
255+ }
256+ fn pop_class_heritage ( ) {
257+ if let Some ( prev) = CLASS_HAS_HERITAGE_STACK . with ( |s| s. borrow_mut ( ) . pop ( ) ) {
258+ CLASS_HAS_HERITAGE . with ( |c| * c. borrow_mut ( ) = prev) ;
259+ }
260+ }
243261fn in_function_context ( ) -> bool {
244262 FUNCTION_CONTEXT . with ( |c| * c. borrow ( ) > 0 )
245263}
@@ -488,7 +506,9 @@ fn parse_class_declaration(t: &[TokenData], index: &mut usize) -> Result<Stateme
488506 } else {
489507 None
490508 } ;
509+ push_class_heritage ( extends. is_some ( ) ) ;
491510 let members = parse_class_body ( t, index) ?;
511+ pop_class_heritage ( ) ;
492512 let class_def = crate :: core:: ClassDefinition { name, extends, members } ;
493513 Ok ( Statement {
494514 kind : Box :: new ( StatementKind :: Class ( Box :: new ( class_def) ) ) ,
@@ -3822,6 +3842,20 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
38223842 pos += 1 ;
38233843 continue ;
38243844 }
3845+ // Skip computed property brackets — names inside are usages, not declarations
3846+ if matches ! ( t[ pos] . token, Token :: LBracket ) {
3847+ let mut depth = 1usize ;
3848+ pos += 1 ;
3849+ while pos < t. len ( ) && depth > 0 {
3850+ if matches ! ( t[ pos] . token, Token :: LBracket ) {
3851+ depth += 1 ;
3852+ } else if matches ! ( t[ pos] . token, Token :: RBracket ) {
3853+ depth -= 1 ;
3854+ }
3855+ pos += 1 ;
3856+ }
3857+ continue ;
3858+ }
38253859 if matches ! ( t[ pos] . token, Token :: Static ) {
38263860 pos += 1 ;
38273861 if pos < t. len ( ) && matches ! ( t[ pos] . token, Token :: LBrace ) {
@@ -4208,6 +4242,17 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
42084242 }
42094243 * index += 1 ;
42104244 }
4245+ // It is a Syntax Error if PropName of MethodDefinition is "constructor" and SpecialMethod is true.
4246+ if computed_key_expr. is_none ( )
4247+ && !is_static
4248+ && !is_private
4249+ && name_str_opt. as_deref ( ) == Some ( "constructor" )
4250+ && ( is_generator || is_async_member)
4251+ {
4252+ return Err ( raise_parse_error ! (
4253+ "SyntaxError: Class constructor may not be an async method or a generator"
4254+ ) ) ;
4255+ }
42114256 if computed_key_expr. is_none ( )
42124257 && !is_static
42134258 && !is_private
@@ -4340,7 +4385,11 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
43404385 }
43414386 } else if * index < t. len ( ) && matches ! ( t[ * index] . token, Token :: Assign ) {
43424387 * index += 1 ;
4388+ // Field initializers have an implicit [[HomeObject]], so super property
4389+ // access is valid inside arrow functions in field initializers.
4390+ push_method_context ( ) ;
43434391 let value = parse_expression ( t, index) ?;
4392+ pop_method_context ( ) ;
43444393 if * index < t. len ( ) {
43454394 match t[ * index] . token {
43464395 Token :: Semicolon | Token :: LineTerminator => * index += 1 ,
@@ -4549,7 +4598,9 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
45494598 } else {
45504599 None
45514600 } ;
4601+ push_class_heritage ( extends. is_some ( ) ) ;
45524602 let members = parse_class_body ( tokens, index) ?;
4603+ pop_class_heritage ( ) ;
45534604 let class_def = crate :: core:: ClassDefinition { name, extends, members } ;
45544605 Expr :: Class ( Box :: new ( class_def) )
45554606 }
@@ -4798,6 +4849,12 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
47984849 "'super()' is only valid inside a class constructor"
47994850 ) ) ;
48004851 }
4852+ if !class_has_heritage ( ) {
4853+ return Err ( raise_parse_error_with_token ! (
4854+ tokens[ * index - 1 ] ,
4855+ "'super()' is only valid in a derived class constructor"
4856+ ) ) ;
4857+ }
48014858 * index += 1 ;
48024859 let mut args = Vec :: new ( ) ;
48034860 if * index < tokens. len ( ) && !matches ! ( tokens[ * index] . token, Token :: RParen ) {
0 commit comments