| ... | ... | @@ -39,7 +39,8 @@ fn parse_stmt_extra<'alloc, 'src: 'alloc>( |
| 39 | 39 | |
| 40 | 40 | let source_type = SourceType::default() |
| 41 | 41 | .with_module(true) |
| 42 | | .with_typescript(true); |
| 42 | .with_typescript(true) |
| 43 | .with_jsx(false); |
| 43 | 44 | |
| 44 | 45 | let mut result = oxc_parser::Parser::new(allocator, source, source_type).parse(); |
| 45 | 46 | if !result.errors.is_empty() && result.program.body.is_empty() { |
| ... | ... | @@ -111,7 +112,8 @@ pub fn parse_expr_extra<'alloc, 'src: 'alloc>( |
| 111 | 112 | |
| 112 | 113 | let source_type = SourceType::default() |
| 113 | 114 | .with_module(true) |
| 114 | | .with_typescript(true); |
| 115 | .with_typescript(true) |
| 116 | .with_jsx(false); |
| 115 | 117 | |
| 116 | 118 | let expr = match oxc_parser::Parser::new(allocator, source, source_type).parse_expression() { |
| 117 | 119 | Ok(expr) => expr, |
| ... | ... | @@ -185,25 +187,30 @@ pub fn parse_expr_without_gt(l: &mut LexState) -> Result<u32, OxcDiagnostic> { |
| 185 | 187 | let rest = l.peek_rest(); |
| 186 | 188 | let mut allocator = Allocator::new(); |
| 187 | 189 | |
| 188 | | // First, try parsing the full source and using AST walking to strip trailing `>`. |
| 190 | // First, try parsing the full source and using AST walking to find the earliest `>`. |
| 189 | 191 | // This handles balanced cases like `arr[a > 0]` and `fn(a > b)` correctly. |
| 192 | // We walk down the left spine of binary expressions, looking for any `>` operator. |
| 193 | // When we find one, we record the span of its left operand. We keep walking to find |
| 194 | // the innermost `>` (which appears earliest in the source). |
| 190 | 195 | if let Ok(expr) = parse_expr_extra(rest, l.offset().cast_signed(), &mut allocator) { |
| 191 | 196 | let mut e = &expr; |
| 197 | let mut result_end = expr.span().end; // default: whole expression |
| 198 | |
| 192 | 199 | while let Expression::BinaryExpression(bin) = e { |
| 193 | 200 | if bin.operator == BinaryOperator::GreaterThan |
| 194 | 201 | || bin.operator == BinaryOperator::GreaterEqualThan |
| 195 | 202 | || bin.operator == BinaryOperator::ShiftRight |
| 196 | 203 | || bin.operator == BinaryOperator::ShiftRightZeroFill |
| 197 | 204 | { |
| 198 | | e = &bin.left; |
| 199 | | } else { |
| 200 | | break; |
| 205 | // Found a `>`, update result to be left side's span |
| 206 | result_end = bin.left.span().end; |
| 201 | 207 | } |
| 208 | // Continue walking left to find any nested `>` operators |
| 209 | e = &bin.left; |
| 202 | 210 | } |
| 203 | 211 | |
| 204 | | let length = e.span().end; |
| 205 | | l.advance(length); |
| 206 | | return Ok(length); |
| 212 | l.advance(result_end); |
| 213 | return Ok(result_end); |
| 207 | 214 | } |
| 208 | 215 | |
| 209 | 216 | // If full parse failed (e.g., due to JSX-like content after the expression), |
| ... | ... | @@ -871,4 +878,53 @@ mod tests { |
| 871 | 878 | let result = scan_first_statement_forbid_trailing(source); |
| 872 | 879 | assert!(result.is_ok()); |
| 873 | 880 | } |
| 881 | |
| 882 | #[test] |
| 883 | fn test_no_gt_with_marko_tags_after() { |
| 884 | assert_eq!(parse_expr_no_gt("'test'>"), Ok(6)); |
| 885 | assert_eq!(parse_expr_no_gt("'a'><b>"), Ok(3)); |
| 886 | assert_eq!(parse_expr_no_gt("'x'><b/>"), Ok(3)); |
| 887 | assert_eq!(parse_expr_no_gt("'x'><b></b>"), Ok(3)); |
| 888 | assert_eq!(parse_expr_no_gt("'x'></>"), Ok(3)); |
| 889 | assert_eq!(parse_expr_no_gt("'x'>text</>"), Ok(3)); |
| 890 | assert_eq!(parse_expr_no_gt("'x'><a/></>"), Ok(3)); |
| 891 | assert_eq!(parse_expr_no_gt("'x'><a></a></>"), Ok(3)); |
| 892 | assert_eq!(parse_expr_no_gt("'x'><a>b</a></>"), Ok(3)); |
| 893 | assert_eq!(parse_expr_no_gt("'x'><a>b</a> c</>"), Ok(3)); |
| 894 | } |
| 895 | |
| 896 | #[test] |
| 897 | fn test_no_gt_double_quoted_string() { |
| 898 | assert_eq!(parse_expr_no_gt("\"hello\">>><stuff>"), Ok(7)); |
| 899 | } |
| 900 | |
| 901 | #[test] |
| 902 | fn test_no_gt_string_followed_by_gt() { |
| 903 | // Simple string then > |
| 904 | assert_eq!(parse_expr_no_gt("'test'>"), Ok(6)); |
| 905 | assert_eq!(parse_expr_no_gt("\"test\">"), Ok(6)); |
| 906 | } |
| 907 | |
| 908 | #[test] |
| 909 | fn test_no_gt_string_then_jsx_like() { |
| 910 | assert_eq!(parse_expr_no_gt("'a'><b>"), Ok(3)); // just 'a' |
| 911 | assert_eq!(parse_expr_no_gt("'a'>b"), Ok(3)); // just 'a' |
| 912 | } |
| 913 | |
| 914 | #[test] |
| 915 | fn test_no_gt_string_then_jsx_variations() { |
| 916 | assert_eq!(parse_expr_no_gt("'x'><b>c</b>"), Ok(3)); |
| 917 | assert_eq!(parse_expr_no_gt("'x'><b/>"), Ok(3)); |
| 918 | assert_eq!(parse_expr_no_gt("'x'><b></b>"), Ok(3)); |
| 919 | assert_eq!(parse_expr_no_gt("'x'><b>c</>"), Ok(3)); |
| 920 | assert_eq!(parse_expr_no_gt("'x'><code>aaa</code>"), Ok(3)); |
| 921 | } |
| 922 | |
| 923 | #[test] |
| 924 | fn test_no_gt_other_ops() { |
| 925 | assert_eq!(parse_expr_no_gt("3 + 4 ___"), Ok(5)); |
| 926 | assert_eq!(parse_expr_no_gt("3 + 4 > 4 ___"), Ok(5)); |
| 927 | assert_eq!(parse_expr_no_gt("3 + 4 < 4 ___"), Ok(9)); |
| 928 | assert_eq!(parse_expr_no_gt("3 < 4 ___"), Ok(5)); |
| 929 | } |
| 874 | 930 | } |