@@ -185,6 +185,14 @@ thread_local! {
185185 static FORBID_IN : RefCell <usize > = const { RefCell :: new( 0 ) } ;
186186 static GENERATOR_CONTEXT : RefCell <usize > = const { RefCell :: new( 0 ) } ;
187187 static GENERATOR_CONTEXT_STACK : RefCell <Vec <usize >> = const { RefCell :: new( Vec :: new( ) ) } ;
188+ /// >0 when parsing inside a method body (class/object method, getter, setter).
189+ /// super.x / super[x] are allowed when this is >0.
190+ static METHOD_CONTEXT : RefCell <usize > = const { RefCell :: new( 0 ) } ;
191+ static METHOD_CONTEXT_STACK : RefCell <Vec <usize >> = const { RefCell :: new( Vec :: new( ) ) } ;
192+ /// >0 when parsing inside a constructor body (derived class).
193+ /// super() is allowed when this is >0.
194+ static CONSTRUCTOR_CONTEXT : RefCell <usize > = const { RefCell :: new( 0 ) } ;
195+ static CONSTRUCTOR_CONTEXT_STACK : RefCell <Vec <usize >> = const { RefCell :: new( Vec :: new( ) ) } ;
188196}
189197fn forbid_in ( ) -> bool {
190198 FORBID_IN . with ( |c| * c. borrow ( ) > 0 )
@@ -214,23 +222,72 @@ fn push_generator_context() {
214222fn pop_generator_context ( ) {
215223 GENERATOR_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
216224}
225+ fn in_method_context ( ) -> bool {
226+ METHOD_CONTEXT . with ( |c| * c. borrow ( ) > 0 )
227+ }
228+ fn in_constructor_context ( ) -> bool {
229+ CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow ( ) > 0 )
230+ }
231+ fn push_method_context ( ) {
232+ METHOD_CONTEXT . with ( |c| * c. borrow_mut ( ) += 1 ) ;
233+ }
234+ fn pop_method_context ( ) {
235+ METHOD_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
236+ }
237+ fn push_constructor_context ( ) {
238+ CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow_mut ( ) += 1 ) ;
239+ }
240+ fn pop_constructor_context ( ) {
241+ CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
242+ }
217243fn in_function_context ( ) -> bool {
218244 FUNCTION_CONTEXT . with ( |c| * c. borrow ( ) > 0 )
219245}
220- /// Every function boundary saves+clears generator context automatically.
246+ /// Every function boundary saves+clears generator/method/constructor context automatically.
221247fn push_function_context ( ) {
222248 FUNCTION_CONTEXT . with ( |c| * c. borrow_mut ( ) += 1 ) ;
223- let saved = GENERATOR_CONTEXT . with ( |c| {
249+ let saved_gen = GENERATOR_CONTEXT . with ( |c| {
250+ let prev = * c. borrow ( ) ;
251+ * c. borrow_mut ( ) = 0 ;
252+ prev
253+ } ) ;
254+ GENERATOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . push ( saved_gen) ) ;
255+ let saved_method = METHOD_CONTEXT . with ( |c| {
256+ let prev = * c. borrow ( ) ;
257+ * c. borrow_mut ( ) = 0 ;
258+ prev
259+ } ) ;
260+ METHOD_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . push ( saved_method) ) ;
261+ let saved_ctor = CONSTRUCTOR_CONTEXT . with ( |c| {
224262 let prev = * c. borrow ( ) ;
225263 * c. borrow_mut ( ) = 0 ;
226264 prev
227265 } ) ;
228- GENERATOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . push ( saved ) ) ;
266+ CONSTRUCTOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . push ( saved_ctor ) ) ;
229267}
230268fn pop_function_context ( ) {
231269 FUNCTION_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
232- let saved = GENERATOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . pop ( ) . unwrap_or ( 0 ) ) ;
233- GENERATOR_CONTEXT . with ( |c| * c. borrow_mut ( ) = saved) ;
270+ let saved_gen = GENERATOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . pop ( ) . unwrap_or ( 0 ) ) ;
271+ GENERATOR_CONTEXT . with ( |c| * c. borrow_mut ( ) = saved_gen) ;
272+ let saved_method = METHOD_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . pop ( ) . unwrap_or ( 0 ) ) ;
273+ METHOD_CONTEXT . with ( |c| * c. borrow_mut ( ) = saved_method) ;
274+ let saved_ctor = CONSTRUCTOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . pop ( ) . unwrap_or ( 0 ) ) ;
275+ CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow_mut ( ) = saved_ctor) ;
276+ }
277+ /// Arrow functions inherit super/method/constructor context but NOT generator context
278+ fn push_arrow_function_context ( ) {
279+ FUNCTION_CONTEXT . with ( |c| * c. borrow_mut ( ) += 1 ) ;
280+ let saved_gen = GENERATOR_CONTEXT . with ( |c| {
281+ let prev = * c. borrow ( ) ;
282+ * c. borrow_mut ( ) = 0 ;
283+ prev
284+ } ) ;
285+ GENERATOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . push ( saved_gen) ) ;
286+ }
287+ fn pop_arrow_function_context ( ) {
288+ FUNCTION_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
289+ let saved_gen = GENERATOR_CONTEXT_STACK . with ( |s| s. borrow_mut ( ) . pop ( ) . unwrap_or ( 0 ) ) ;
290+ GENERATOR_CONTEXT . with ( |c| * c. borrow_mut ( ) = saved_gen) ;
234291}
235292pub ( crate ) fn in_await_context ( ) -> bool {
236293 AWAIT_CONTEXT . with ( |c| * c. borrow ( ) > 0 )
@@ -241,6 +298,18 @@ pub(crate) fn push_await_context() {
241298pub ( crate ) fn pop_await_context ( ) {
242299 AWAIT_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
243300}
301+ pub ( crate ) fn push_method_context_for_eval ( ) {
302+ METHOD_CONTEXT . with ( |c| * c. borrow_mut ( ) += 1 ) ;
303+ }
304+ pub ( crate ) fn pop_method_context_for_eval ( ) {
305+ METHOD_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
306+ }
307+ pub ( crate ) fn push_constructor_context_for_eval ( ) {
308+ CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow_mut ( ) += 1 ) ;
309+ }
310+ pub ( crate ) fn pop_constructor_context_for_eval ( ) {
311+ CONSTRUCTOR_CONTEXT . with ( |c| * c. borrow_mut ( ) -= 1 ) ;
312+ }
244313fn strict_binding_checks ( ) -> bool {
245314 STRICT_BINDING_CHECKS . with ( |c| c. get ( ) )
246315}
@@ -594,6 +663,12 @@ fn parse_for_statement(t: &[TokenData], index: &mut usize) -> Result<Statement,
594663 * index += 1 ;
595664 }
596665 if * index < t. len ( ) && matches ! ( & t[ * index] . token, Token :: Identifier ( n) if n == "of" ) {
666+ if raw_identifier_source_has_escape ( & t[ * index] ) {
667+ return Err ( raise_parse_error_with_token ! (
668+ t[ * index] ,
669+ "'of' keyword must not contain Unicode escape sequences"
670+ ) ) ;
671+ }
597672 * index += 1 ;
598673 let iterable = parse_assignment ( t, index) ?;
599674 while * index < t. len ( ) && matches ! ( t[ * index] . token, Token :: LineTerminator ) {
@@ -774,6 +849,12 @@ fn parse_for_statement(t: &[TokenData], index: &mut usize) -> Result<Statement,
774849 * index += 1 ;
775850 }
776851 if * index < t. len ( ) && matches ! ( t[ * index] . token, Token :: Identifier ( ref s) if s == "of" ) {
852+ if raw_identifier_source_has_escape ( & t[ * index] ) {
853+ return Err ( raise_parse_error_with_token ! (
854+ t[ * index] ,
855+ "'of' keyword must not contain Unicode escape sequences"
856+ ) ) ;
857+ }
777858 * index += 1 ;
778859 let iterable = parse_assignment ( t, index) ?;
779860 if !matches ! ( t[ * index] . token, Token :: RParen ) {
@@ -3624,25 +3705,30 @@ fn parse_multiplicative(tokens: &[TokenData], index: &mut usize) -> Result<Expr,
36243705 } )
36253706}
36263707fn parse_exponentiation ( tokens : & [ TokenData ] , index : & mut usize ) -> Result < Expr , JSError > {
3708+ let start = * index;
36273709 let left = parse_primary ( tokens, index, true ) ?;
36283710 if * index >= tokens. len ( ) {
36293711 return Ok ( left) ;
36303712 }
36313713 if matches ! ( tokens[ * index] . token, Token :: Exponent ) {
36323714 // Unary operators cannot be the base of exponentiation (spec: UpdateExpression ** ExponentiationExpression)
3633- match & left {
3634- Expr :: Delete ( _)
3635- | Expr :: Void ( _)
3636- | Expr :: TypeOf ( _)
3637- | Expr :: UnaryPlus ( _)
3638- | Expr :: UnaryNeg ( _)
3639- | Expr :: BitNot ( _)
3640- | Expr :: LogicalNot ( _) => {
3641- return Err ( crate :: raise_syntax_error!(
3642- "Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence"
3643- ) ) ;
3715+ // But parenthesized unary expressions are fine: (-1n) ** -1n is valid
3716+ let was_parenthesized = matches ! ( tokens[ start] . token, Token :: LParen ) ;
3717+ if !was_parenthesized {
3718+ match & left {
3719+ Expr :: Delete ( _)
3720+ | Expr :: Void ( _)
3721+ | Expr :: TypeOf ( _)
3722+ | Expr :: UnaryPlus ( _)
3723+ | Expr :: UnaryNeg ( _)
3724+ | Expr :: BitNot ( _)
3725+ | Expr :: LogicalNot ( _) => {
3726+ return Err ( crate :: raise_syntax_error!(
3727+ "Unary operator used immediately before exponentiation expression. Parenthesis must be used to disambiguate operator precedence"
3728+ ) ) ;
3729+ }
3730+ _ => { }
36443731 }
3645- _ => { }
36463732 }
36473733 * index += 1 ;
36483734 let right = parse_exponentiation ( tokens, index) ?;
@@ -3983,7 +4069,9 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
39834069 }
39844070 * index += 1 ;
39854071 push_function_context ( ) ;
4072+ push_method_context ( ) ;
39864073 let body = with_cleared_forbidden_await_identifier ( || parse_statement_block ( t, index) ) ?;
4074+ pop_method_context ( ) ;
39874075 pop_function_context ( ) ;
39884076 if is_getter {
39894077 if let Some ( prop_expr) = prop_expr_opt {
@@ -4101,7 +4189,11 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
41014189 }
41024190 * index += 1 ;
41034191 push_function_context ( ) ;
4192+ push_method_context ( ) ;
4193+ push_constructor_context ( ) ;
41044194 let body = with_cleared_forbidden_await_identifier ( || parse_statement_block ( t, index) ) ?;
4195+ pop_constructor_context ( ) ;
4196+ pop_method_context ( ) ;
41054197 pop_function_context ( ) ;
41064198 members. push ( ClassMember :: Constructor ( params, body) ) ;
41074199 continue ;
@@ -4128,6 +4220,7 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
41284220 }
41294221 * index += 1 ;
41304222 push_function_context ( ) ;
4223+ push_method_context ( ) ;
41314224 let body = if is_generator {
41324225 push_generator_context ( ) ;
41334226 let b = with_cleared_forbidden_await_identifier ( || parse_statement_block ( t, index) ) ?;
@@ -4136,6 +4229,7 @@ pub fn parse_class_body(t: &[TokenData], index: &mut usize) -> Result<Vec<ClassM
41364229 } else {
41374230 with_cleared_forbidden_await_identifier ( || parse_statement_block ( t, index) ) ?
41384231 } ;
4232+ pop_method_context ( ) ;
41394233 pop_function_context ( ) ;
41404234 if is_generator {
41414235 if let Some ( expr) = computed_key_expr {
@@ -4666,6 +4760,12 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
46664760 Token :: This => Expr :: This ,
46674761 Token :: Super => {
46684762 if * index < tokens. len ( ) && matches ! ( tokens[ * index] . token, Token :: LParen ) {
4763+ if !in_constructor_context ( ) {
4764+ return Err ( raise_parse_error_with_token ! (
4765+ tokens[ * index - 1 ] ,
4766+ "'super()' is only valid inside a class constructor"
4767+ ) ) ;
4768+ }
46694769 * index += 1 ;
46704770 let mut args = Vec :: new ( ) ;
46714771 if * index < tokens. len ( ) && !matches ! ( tokens[ * index] . token, Token :: RParen ) {
@@ -4690,6 +4790,12 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
46904790 * index += 1 ;
46914791 Expr :: SuperCall ( args)
46924792 } else if * index < tokens. len ( ) && matches ! ( tokens[ * index] . token, Token :: Dot ) {
4793+ if !in_method_context ( ) && !in_constructor_context ( ) {
4794+ return Err ( raise_parse_error_with_token ! (
4795+ tokens[ * index - 1 ] ,
4796+ "'super' property access is only valid inside a method"
4797+ ) ) ;
4798+ }
46934799 * index += 1 ;
46944800 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: Identifier ( _) ) {
46954801 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -4745,6 +4851,12 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
47454851 }
47464852 } else if * index < tokens. len ( ) && matches ! ( tokens[ * index] . token, Token :: LBracket ) {
47474853 // super[expr] — computed super property access
4854+ if !in_method_context ( ) && !in_constructor_context ( ) {
4855+ return Err ( raise_parse_error_with_token ! (
4856+ tokens[ * index - 1 ] ,
4857+ "'super' property access is only valid inside a method"
4858+ ) ) ;
4859+ }
47484860 * index += 1 ;
47494861 let key_expr = parse_assignment ( tokens, index) ?;
47504862 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBracket ) {
@@ -4959,13 +5071,15 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
49595071 }
49605072 * index += 1 ;
49615073 push_function_context ( ) ;
5074+ push_method_context ( ) ;
49625075 if is_generator {
49635076 push_generator_context ( ) ;
49645077 }
49655078 let body = parse_statements ( tokens, index) ?;
49665079 if is_generator {
49675080 pop_generator_context ( ) ;
49685081 }
5082+ pop_method_context ( ) ;
49695083 pop_function_context ( ) ;
49705084 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
49715085 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -5038,13 +5152,15 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
50385152 }
50395153 * index += 1 ;
50405154 push_function_context ( ) ;
5155+ push_method_context ( ) ;
50415156 if is_generator {
50425157 push_generator_context ( ) ;
50435158 }
50445159 let body = parse_statements ( tokens, index) ?;
50455160 if is_generator {
50465161 pop_generator_context ( ) ;
50475162 }
5163+ pop_method_context ( ) ;
50485164 pop_function_context ( ) ;
50495165 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
50505166 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -5140,13 +5256,15 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
51405256 }
51415257 * index += 1 ;
51425258 push_function_context ( ) ;
5259+ push_method_context ( ) ;
51435260 if is_generator {
51445261 push_generator_context ( ) ;
51455262 }
51465263 let body = parse_statements ( tokens, index) ?;
51475264 if is_generator {
51485265 pop_generator_context ( ) ;
51495266 }
5267+ pop_method_context ( ) ;
51505268 pop_function_context ( ) ;
51515269 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
51525270 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -5262,13 +5380,15 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
52625380 }
52635381 * index += 1 ;
52645382 push_function_context ( ) ;
5383+ push_method_context ( ) ;
52655384 if is_generator {
52665385 push_generator_context ( ) ;
52675386 }
52685387 let body = parse_statements ( tokens, index) ?;
52695388 if is_generator {
52705389 pop_generator_context ( ) ;
52715390 }
5391+ pop_method_context ( ) ;
52725392 pop_function_context ( ) ;
52735393 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
52745394 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -5324,7 +5444,9 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
53245444 }
53255445 * index += 1 ;
53265446 push_function_context ( ) ;
5447+ push_method_context ( ) ;
53275448 let body = parse_statements ( tokens, index) ?;
5449+ pop_method_context ( ) ;
53285450 pop_function_context ( ) ;
53295451 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
53305452 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -5355,7 +5477,9 @@ fn parse_primary(tokens: &[TokenData], index: &mut usize, allow_call: bool) -> R
53555477 }
53565478 * index += 1 ;
53575479 push_function_context ( ) ;
5480+ push_method_context ( ) ;
53585481 let body = parse_statements ( tokens, index) ?;
5482+ pop_method_context ( ) ;
53595483 pop_function_context ( ) ;
53605484 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
53615485 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
@@ -6249,7 +6373,7 @@ fn parse_arrow_body_inner(tokens: &[TokenData], index: &mut usize, is_async: boo
62496373 }
62506374 if * index < tokens. len ( ) && matches ! ( tokens[ * index] . token, Token :: LBrace ) {
62516375 * index += 1 ;
6252- push_function_context ( ) ;
6376+ push_arrow_function_context ( ) ;
62536377 let body = if is_async {
62546378 push_await_context ( ) ;
62556379 let r = parse_statements ( tokens, index) ;
@@ -6258,7 +6382,7 @@ fn parse_arrow_body_inner(tokens: &[TokenData], index: &mut usize, is_async: boo
62586382 } else {
62596383 with_cleared_await_context ( || parse_statements ( tokens, index) ) ?
62606384 } ;
6261- pop_function_context ( ) ;
6385+ pop_arrow_function_context ( ) ;
62626386 if * index >= tokens. len ( ) || !matches ! ( tokens[ * index] . token, Token :: RBrace ) {
62636387 return Err ( raise_parse_error_at ! ( tokens. get( * index) ) ) ;
62646388 }
0 commit comments