diff --git a/.gitignore b/.gitignore index 4dfb35cc7a..8fed22464f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ coverage lib node_modules npm-debug.log +.vscode diff --git a/ast/spec.md b/ast/spec.md index 4a13d6d697..644f4af81b 100644 --- a/ast/spec.md +++ b/ast/spec.md @@ -791,7 +791,6 @@ enum BinaryOperator { | "|" | "^" | "&" | "in" | "instanceof" | "|>" - | "??" } ``` @@ -839,7 +838,7 @@ A logical operator expression. ```js enum LogicalOperator { - "||" | "&&" + "||" | "&&" | "??" } ``` diff --git a/src/parser/expression.js b/src/parser/expression.js index b44122514c..bc192cb491 100644 --- a/src/parser/expression.js +++ b/src/parser/expression.js @@ -311,7 +311,9 @@ export default class ExpressionParser extends LValParser { this.finishNode( node, - op === tt.logicalOR || op === tt.logicalAND + op === tt.logicalOR || + op === tt.logicalAND || + op === tt.nullishCoalescing ? "LogicalExpression" : "BinaryExpression", ); diff --git a/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/actual.js new file mode 100644 index 0000000000..2b0c8c8ff8 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/actual.js @@ -0,0 +1 @@ +a && b ?? c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/expected.json new file mode 100644 index 0000000000..57882d871e --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "LogicalExpression", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "&&", + "right": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + } + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/options.json b/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/options.json new file mode 100644 index 0000000000..e70662682b --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/and-nullish/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator"] +} + \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/associativity/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/associativity/actual.js new file mode 100644 index 0000000000..1b247875fc --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/associativity/actual.js @@ -0,0 +1 @@ +a ?? b ?? c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/associativity/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/associativity/expected.json new file mode 100644 index 0000000000..ccd1317f1a --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/associativity/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "LogicalExpression", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + } + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/associativity/options.json b/test/fixtures/experimental/nullish-coalescing-operator/associativity/options.json new file mode 100644 index 0000000000..e70662682b --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/associativity/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator"] +} + \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/expression/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/expression/expected.json index 9e85e6f302..7a2f321c7c 100644 --- a/test/fixtures/experimental/nullish-coalescing-operator/expression/expected.json +++ b/test/fixtures/experimental/nullish-coalescing-operator/expression/expected.json @@ -43,7 +43,7 @@ } }, "expression": { - "type": "BinaryExpression", + "type": "LogicalExpression", "start": 0, "end": 8, "loc": { diff --git a/test/fixtures/experimental/nullish-coalescing-operator/multiline/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/multiline/actual.js new file mode 100644 index 0000000000..fc603903ff --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/multiline/actual.js @@ -0,0 +1,3 @@ +a + ?? b + ?? c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/multiline/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/multiline/expected.json new file mode 100644 index 0000000000..3043dfb4b7 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/multiline/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 17, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 7 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 0, + "end": 16, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 3, + "column": 6 + } + }, + "left": { + "type": "LogicalExpression", + "start": 0, + "end": 9, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 2, + "column": 6 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 8, + "end": 9, + "loc": { + "start": { + "line": 2, + "column": 5 + }, + "end": { + "line": 2, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + } + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 15, + "end": 16, + "loc": { + "start": { + "line": 3, + "column": 5 + }, + "end": { + "line": 3, + "column": 6 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/multiline/options.json b/test/fixtures/experimental/nullish-coalescing-operator/multiline/options.json new file mode 100644 index 0000000000..e70662682b --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/multiline/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator"] +} + \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/actual.js new file mode 100644 index 0000000000..b8805af495 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/actual.js @@ -0,0 +1 @@ +a ?? b && c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/expected.json new file mode 100644 index 0000000000..44583bc17a --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "??", + "right": { + "type": "LogicalExpression", + "start": 5, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + }, + "operator": "&&", + "right": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/options.json b/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/options.json new file mode 100644 index 0000000000..e70662682b --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/nullish-and/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator"] +} + \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/actual.js new file mode 100644 index 0000000000..40ec9c39d1 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/actual.js @@ -0,0 +1 @@ +a ?? b || c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/expected.json new file mode 100644 index 0000000000..c769e52a6a --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "LogicalExpression", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + } + }, + "operator": "||", + "right": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/options.json b/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/options.json new file mode 100644 index 0000000000..e70662682b --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/nullish-or/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator"] +} + \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/actual.js new file mode 100644 index 0000000000..b74eae4c99 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/actual.js @@ -0,0 +1 @@ +a || b ?? c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/expected.json new file mode 100644 index 0000000000..96f679d412 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "expression": { + "type": "LogicalExpression", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "LogicalExpression", + "start": 0, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 6 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "||", + "right": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + } + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/options.json b/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/options.json new file mode 100644 index 0000000000..e70662682b --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/or-nullish/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator"] +} + \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/actual.js b/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/actual.js new file mode 100644 index 0000000000..4809548d80 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/actual.js @@ -0,0 +1 @@ +a |> b ?? c; diff --git a/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/expected.json b/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/expected.json new file mode 100644 index 0000000000..57817930c4 --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/expected.json @@ -0,0 +1,132 @@ +{ + "type": "File", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "program": { + "type": "Program", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "sourceType": "script", + "body": [ + { + "type": "ExpressionStatement", + "start": 0, + "end": 12, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 12 + } + }, + "expression": { + "type": "BinaryExpression", + "start": 0, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "Identifier", + "start": 0, + "end": 1, + "loc": { + "start": { + "line": 1, + "column": 0 + }, + "end": { + "line": 1, + "column": 1 + }, + "identifierName": "a" + }, + "name": "a" + }, + "operator": "|>", + "right": { + "type": "LogicalExpression", + "start": 5, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 11 + } + }, + "left": { + "type": "Identifier", + "start": 5, + "end": 6, + "loc": { + "start": { + "line": 1, + "column": 5 + }, + "end": { + "line": 1, + "column": 6 + }, + "identifierName": "b" + }, + "name": "b" + }, + "operator": "??", + "right": { + "type": "Identifier", + "start": 10, + "end": 11, + "loc": { + "start": { + "line": 1, + "column": 10 + }, + "end": { + "line": 1, + "column": 11 + }, + "identifierName": "c" + }, + "name": "c" + } + } + } + } + ], + "directives": [] + } +} \ No newline at end of file diff --git a/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/options.json b/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/options.json new file mode 100644 index 0000000000..37fbfac05f --- /dev/null +++ b/test/fixtures/experimental/nullish-coalescing-operator/with-pipeline/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["nullishCoalescingOperator", "pipelineOperator"] +} + \ No newline at end of file