mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-11-22 23:50:19 +00:00
3709d11212
Instead of passing the continuously merged initial forbidden token set (with the new additional forbidden tokens from each parsed secondary expression) to the next call of parse_secondary_expression(), keep a copy of the original set and use it as the base for parsing the next secondary expression. This bug prevented us from properly parsing the following expression: ```js 0 ?? 0 ? 0 : 0 || 0 ``` ...due to LogicalExpression with LogicalOp::NullishCoalescing returning both DoubleAmpersand and DoublePipe in its forbidden token set. The following correct AST is now generated: Program (Children) ExpressionStatement ConditionalExpression (Test) LogicalExpression NumericLiteral 0 ?? NumericLiteral 0 (Consequent) NumericLiteral 0 (Alternate) LogicalExpression NumericLiteral 0 || NumericLiteral 0 An alternate solution I explored was only merging the original forbidden token set with the one of the last parsed secondary expression which is then passed to match_secondary_expression(); however that led to an incorrect AST (note the alternate expression): Program (Children) ExpressionStatement LogicalExpression ConditionalExpression (Test) LogicalExpression NumericLiteral 0 ?? NumericLiteral 0 (Consequent) NumericLiteral 0 (Alternate) NumericLiteral 0 || NumericLiteral 0 Truth be told, I don't know enough about the inner workings of the parser to fully explain the difference. AFAICT this patch has no unintended side effects in its current form though. Fixes #18087.
41 lines
1.8 KiB
JavaScript
41 lines
1.8 KiB
JavaScript
test("mixing coalescing and logical operators isn't allowed", () => {
|
|
expect("if (0) a ?? b || c").not.toEval();
|
|
expect("if (0) a ?? b && c").not.toEval();
|
|
expect("if (0) a ?? b * c || d").not.toEval();
|
|
expect("if (0) a ?? b * c && d").not.toEval();
|
|
expect("if (0) a && b ?? c").not.toEval();
|
|
expect("if (0) a || b ?? c").not.toEval();
|
|
expect("if (0) a && b * c ?? d").not.toEval();
|
|
expect("if (0) a || b * c ?? d").not.toEval();
|
|
});
|
|
|
|
test("mixing coalescing and logical operators with parens", () => {
|
|
expect("if (0) a ?? (b || c)").toEval();
|
|
expect("if (0) (a ?? b) && c").toEval();
|
|
expect("if (0) a ?? (b * c || d)").toEval();
|
|
expect("if (0) (a ?? b * c) && d").toEval();
|
|
expect("if (0) a && (b ?? c)").toEval();
|
|
expect("if (0) (a || b) ?? c").toEval();
|
|
expect("if (0) a && (b * c) ?? d").not.toEval();
|
|
expect("if (0) a || (b * c) ?? d").not.toEval();
|
|
});
|
|
|
|
test("mixing coalescing and logical operators in ternary expressions", () => {
|
|
expect("0 || 0 ? 0 : 0 ?? 0").toEval();
|
|
expect("0 ?? 0 ? 0 : 0 || 0").toEval();
|
|
expect("0 ? 0 || 0 : 0 ?? 0").toEval();
|
|
expect("0 ? 0 ?? 0 : 0 || 0").toEval();
|
|
expect("0 && 0 ? 0 ?? 0 : 0 || 0").toEval();
|
|
expect("0 ?? 0 ? 0 && 0 : 0 || 0").toEval();
|
|
expect("0 ?? 0 ? 0 || 0 : 0 && 0").toEval();
|
|
expect("0 || 0 ? 0 ?? 0 : 0 && 0").toEval();
|
|
expect("0 && 0 ? 0 || 0 : 0 ?? 0").toEval();
|
|
expect("0 || 0 ? 0 && 0 : 0 ?? 0").toEval();
|
|
});
|
|
|
|
test("mixing coalescing and logical operators when 'in' isn't allowed", () => {
|
|
expect("for (a ?? b || c in a; false;);").not.toEval();
|
|
expect("for (a ?? b && c in a; false;);").not.toEval();
|
|
expect("for (a || b ?? c in a; false;);").not.toEval();
|
|
expect("for (a && b ?? c in a; false;);").not.toEval();
|
|
});
|