Implement transform for nullish-coalescing operator (#6483)
* Implement transform for nullish-coalescing operator * Update example output * Switch from BinaryExpression to LogicalExpression * Address review comments - Use generateUidIdentifierBasedOnNode - Inline "??" - Clone ref node - Move "??" to LogicalExpression in babel-types * Fix reference to @babel/helper-plugin-test-runner * Fix reference to @babel/plugin-syntax-nullish-coalescing-operator * Don't use parent scope * Remove .vscode from .gitignore, change 'lib/index.js' to 'lib' * Ensure `document.all ?? 0 === document.all` * Fix note and copy to an inline comment
This commit is contained in:
parent
5c47929983
commit
99be60b53d
@ -0,0 +1,3 @@
|
|||||||
|
src
|
||||||
|
test
|
||||||
|
*.log
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
# @babel/plugin-syntax-nullish-coalescing-operator
|
||||||
|
|
||||||
|
> Allow parsing of the nullish-coalescing operator.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @babel/plugin-syntax-nullish-coalescing-operator
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Via `.babelrc` (Recommended)
|
||||||
|
|
||||||
|
**.babelrc**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugins": ["syntax-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via CLI
|
||||||
|
|
||||||
|
```sh
|
||||||
|
babel --plugins syntax-nullish-coalescing-operator script.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via Node API
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
require("babel-core").transform("code", {
|
||||||
|
plugins: ["syntax-nullish-coalescing-operator"]
|
||||||
|
});
|
||||||
|
```
|
||||||
@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
"name": "@babel/plugin-syntax-nullish-coalescing-operator",
|
||||||
|
"version": "7.0.0-beta.3",
|
||||||
|
"description": "Allow parsing of the nullish-coalescing operator",
|
||||||
|
"repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-nullish-coalescing-operator",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "lib",
|
||||||
|
"keywords": [
|
||||||
|
"babel-plugin"
|
||||||
|
],
|
||||||
|
"dependencies": {},
|
||||||
|
"devDependencies": {}
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
export default function() {
|
||||||
|
return {
|
||||||
|
manipulateOptions(opts, parserOpts) {
|
||||||
|
parserOpts.plugins.push("nullishCoalescingOperator");
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
src
|
||||||
|
test
|
||||||
|
*.log
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
# @babel/plugin-transform-nullish-coalescing-operator
|
||||||
|
|
||||||
|
> Replace `??` with an inline helper.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
**In**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var foo = object.foo ?? "default";
|
||||||
|
```
|
||||||
|
|
||||||
|
**Out**
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
var _object$foo;
|
||||||
|
|
||||||
|
var foo = (_object$foo = object.foo, _object$foo !== null && _object$foo !== void 0 ? _object$foo : "default");
|
||||||
|
```
|
||||||
|
|
||||||
|
> **NOTE:** We cannot use `!= null` here because `document.all == null` and
|
||||||
|
> `document.all` has been deemed not "nullish".
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```sh
|
||||||
|
npm install --save-dev @babel/plugin-transform-nullish-coalescing-operator
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Via `.babelrc` (Recommended)
|
||||||
|
|
||||||
|
**.babelrc**
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugins": ["transform-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via CLI
|
||||||
|
|
||||||
|
```sh
|
||||||
|
babel --plugins transform-nullish-coalescing-operator script.js
|
||||||
|
```
|
||||||
|
|
||||||
|
### Via Node API
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
require("babel-core").transform("code", {
|
||||||
|
plugins: ["transform-nullish-coalescing-operator"]
|
||||||
|
});
|
||||||
|
```
|
||||||
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "@babel/plugin-transform-nullish-coalescing-operator",
|
||||||
|
"version": "7.0.0-beta.3",
|
||||||
|
"description": "Remove nullish coalescing operator",
|
||||||
|
"repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-nullish-coalescing-opearator",
|
||||||
|
"license": "MIT",
|
||||||
|
"main": "lib",
|
||||||
|
"keywords": [
|
||||||
|
"babel-plugin"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/plugin-syntax-nullish-coalescing-operator": "7.0.0-beta.3"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@babel/helper-plugin-test-runner": "7.0.0-beta.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
import syntaxNullishCoalescingOperator from "@babel/plugin-syntax-nullish-coalescing-operator";
|
||||||
|
|
||||||
|
export default function({ types: t }) {
|
||||||
|
return {
|
||||||
|
inherits: syntaxNullishCoalescingOperator,
|
||||||
|
|
||||||
|
visitor: {
|
||||||
|
LogicalExpression(path) {
|
||||||
|
const { node, scope } = path;
|
||||||
|
if (node.operator !== "??") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const ref = scope.generateUidIdentifierBasedOnNode(node.left);
|
||||||
|
scope.push({ id: ref });
|
||||||
|
|
||||||
|
path.replaceWith(
|
||||||
|
t.sequenceExpression([
|
||||||
|
t.assignmentExpression("=", ref, node.left),
|
||||||
|
t.conditionalExpression(
|
||||||
|
// We cannot use `!= null` here because `document.all == null`
|
||||||
|
// and `document.all` has been deemed not "nullish".
|
||||||
|
t.logicalExpression(
|
||||||
|
"&&",
|
||||||
|
t.binaryExpression("!==", t.clone(ref), t.nullLiteral()),
|
||||||
|
t.binaryExpression(
|
||||||
|
"!==",
|
||||||
|
t.clone(ref),
|
||||||
|
scope.buildUndefinedNode(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
t.clone(ref),
|
||||||
|
node.right,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
assert.equal(null ?? undefined, undefined);
|
||||||
|
assert.equal(undefined ?? null, null);
|
||||||
|
assert.equal(false ?? true, false);
|
||||||
|
assert.equal(0 ?? 1, 0);
|
||||||
|
assert.equal("" ?? "foo", "");
|
||||||
|
|
||||||
|
var obj = { exists: true };
|
||||||
|
assert.equal(obj.exists ?? false, true);
|
||||||
|
assert.equal(obj.doesNotExist ?? "foo", "foo");
|
||||||
|
|
||||||
|
var counter = 0;
|
||||||
|
function sideEffect() { return counter++; }
|
||||||
|
assert.equal(sideEffect() ?? -1, 0);
|
||||||
|
|
||||||
|
var counter2 = 0;
|
||||||
|
var obj2 = {
|
||||||
|
get foo() { return counter2++; }
|
||||||
|
};
|
||||||
|
assert.equal(obj2.foo ?? -1, 0);
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["transform-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
function foo(foo, bar = foo ?? "bar") {}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo(foo, bar = (_foo = foo, _foo !== null && _foo !== void 0 ? _foo : "bar")) {
|
||||||
|
var _foo;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["transform-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
function foo(opts) {
|
||||||
|
var foo = opts.foo ?? "default";
|
||||||
|
}
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
function foo(opts) {
|
||||||
|
var _opts$foo;
|
||||||
|
|
||||||
|
var foo = (_opts$foo = opts.foo, _opts$foo !== null && _opts$foo !== void 0 ? _opts$foo : "default");
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"plugins": ["transform-nullish-coalescing-operator"]
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
import runner from "@babel/helper-plugin-test-runner";
|
||||||
|
|
||||||
|
runner(__dirname);
|
||||||
@ -12,6 +12,7 @@
|
|||||||
"@babel/plugin-transform-export-default": "7.0.0-beta.3",
|
"@babel/plugin-transform-export-default": "7.0.0-beta.3",
|
||||||
"@babel/plugin-transform-optional-chaining": "7.0.0-beta.3",
|
"@babel/plugin-transform-optional-chaining": "7.0.0-beta.3",
|
||||||
"@babel/plugin-transform-pipeline-operator": "7.0.0-beta.3",
|
"@babel/plugin-transform-pipeline-operator": "7.0.0-beta.3",
|
||||||
|
"@babel/plugin-transform-nullish-coalescing-operator": "7.0.0-beta.3",
|
||||||
"@babel/preset-stage-2": "7.0.0-beta.3"
|
"@babel/preset-stage-2": "7.0.0-beta.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import transformDecorators from "@babel/plugin-transform-decorators";
|
|||||||
import transformExportDefault from "@babel/plugin-transform-export-default";
|
import transformExportDefault from "@babel/plugin-transform-export-default";
|
||||||
import transformOptionalChaining from "@babel/plugin-transform-optional-chaining";
|
import transformOptionalChaining from "@babel/plugin-transform-optional-chaining";
|
||||||
import transformPipelineOperator from "@babel/plugin-transform-pipeline-operator";
|
import transformPipelineOperator from "@babel/plugin-transform-pipeline-operator";
|
||||||
|
import transformNullishCoalescingOperator from "@babel/plugin-transform-nullish-coalescing-operator";
|
||||||
|
|
||||||
export default function() {
|
export default function() {
|
||||||
return {
|
return {
|
||||||
@ -13,6 +14,7 @@ export default function() {
|
|||||||
transformExportDefault,
|
transformExportDefault,
|
||||||
transformOptionalChaining,
|
transformOptionalChaining,
|
||||||
transformPipelineOperator,
|
transformPipelineOperator,
|
||||||
|
transformNullishCoalescingOperator,
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,7 +9,7 @@ export const COMMENT_KEYS = [
|
|||||||
"innerComments",
|
"innerComments",
|
||||||
];
|
];
|
||||||
|
|
||||||
export const LOGICAL_OPERATORS = ["||", "&&"];
|
export const LOGICAL_OPERATORS = ["||", "&&", "??"];
|
||||||
export const UPDATE_OPERATORS = ["++", "--"];
|
export const UPDATE_OPERATORS = ["++", "--"];
|
||||||
|
|
||||||
export const BOOLEAN_NUMBER_BINARY_OPERATORS = [">", "<", ">=", "<="];
|
export const BOOLEAN_NUMBER_BINARY_OPERATORS = [">", "<", ">=", "<="];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user