Optional Chaining Operator (Stage 1)#5813
Conversation
hzoo
left a comment
There was a problem hiding this comment.
- readme update with example and link to proposal
- does babel-types need changing?
- do we want some simple exec tests? (could be basis for test262 as well)
|
@hzoo: done. Please advise whether I have all the necessary LHS parents we need to guard. |
|
Nice job @jridgewell!
I'm ok with closing my PR. Link to parser PR babel/babylon#545. |
|
Done. Sorry about the duplicate PRs. I usually open one against the original PR (like the parser one), but this implementation was significantly different. |
| const baz = obj?.foo?.bar?.baz(); // 42 | ||
|
|
||
| const safe = obj?.qux?.baz(); // undefined | ||
| const safe2 = obj?.foo.bar.qux?.(); // undefined |
There was a problem hiding this comment.
can we add an example like obj?.foo.bar.bazz() that throws?
|
|
||
| const baz = new obj?.foo?.bar?.baz(); // baz instance | ||
|
|
||
| const safe = new obj?.qux?.baz(); // undefined |
There was a problem hiding this comment.
I don't think this should return undefined (obv that depends on the proposal itself).
I think that if you want the new not to throw when it gets a non-function, either the new or the () must have the conditional operator attached to it.
In other words, new obj?.qux?.baz() should be identical to const foo = obj?.qux?.baz; new foo().
| optionals.push(node); | ||
| } | ||
|
|
||
| objectPath = objectPath.get("object"); |
There was a problem hiding this comment.
for (let objectPath = path.get(key); objectPath.isMemberExpression(); objectPath = objectPath.get("object"))| objectPath = objectPath.get("object"); | ||
| } | ||
|
|
||
| for (let i = optionals.length - 1; i >= 0; i--) { |
There was a problem hiding this comment.
for (const [i, node] of optionals.entries())or
optionals.forEach((node, i) => {})There was a problem hiding this comment.
Can't, I have to reverse iterate.
There was a problem hiding this comment.
Oh, right. .reverse() could do the trick, but the i would have to be subtracted from the length 🤔
| if (atCall && t.isMemberExpression(chain)) { | ||
| if (loose) { | ||
| // To avoid a Function#call, we can instead re-grab the property from the context object. | ||
| // `a.?b.?()` translates roughly to `_a.b != null && _a.b()` |
There was a problem hiding this comment.
That would invoke a getter twice though...
There was a problem hiding this comment.
Yup, that's why it's loose. 😉
packages/babel-plugin-transform-optional-chaining/test/fixtures/execute/new.js
Show resolved
Hide resolved
|
|
||
| defineType("MemberExpression", { | ||
| builder: ["object", "property", "computed"], | ||
| builder: ["object", "property", "computed", "optional"], |
There was a problem hiding this comment.
Does this need to be added to NewExpression / CallExpression as well?
|
This way, it quickly returns from the conditions. The first nil will now exit, instead of checking every nil. This also allows conditionalChaining inside a container to still operate the container.
gisenberg
left a comment
There was a problem hiding this comment.
Looks good to me, thanks so much for the contribution! I'll work towards updating the TC39 proposal to cover some of the comments in this PR.
|
Does this mean that it has been added to the preset-stage-1? |
|
It's in there now. |
| "babel-plugin-syntax-optional-chaining": "7.0.0-alpha.13" | ||
| }, | ||
| "keywords": [ | ||
| "babel-plugin" |
There was a problem hiding this comment.
We can more keyword here:
- optional chaining
- null propagator
- elvis
There was a problem hiding this comment.
|
Great job @jridgewell and @xtuc, thanks for the review @gisenberg!! |
|
This is awesome! Can this be released on NPM please? I was not able to install |
|
@pronebird see #5905 |
|
You want transform not syntax - https://github.com/babel/babel/releases/tag/v7.0.0-alpha.15, it's part of stage-1 too |
|
This is awesome! Can this support destructuring? |
Example: https://babeljs.io/repl/build/master#?babili=false&browsers=&build=&builtIns=false&code_lz=IYfgdARg3AUDqTAYzAE1vcFnnXBA2gOQREC6shEFmYAFAJRRA&debug=false&circleciRepo=&evaluate=false&lineWrap=false&presets=stage-0&prettier=false&targets=&version=7.0.0-beta.2
This is another implementation of Null Propagation Operators, competing with #5786. This one takes a different, top-down approach to the transform that avoids the
WeakSetstate. It also implements optionalCallExpressions andNewExpressions.This has a few todos:
manipulateOptionsstuff)CallExpressions don't have acalleeNewExpressions have acalleethat's aCallExpression. That callee'scalleeandargumentsshould be theNewExpressionscalleeandargumentsbabel-generatorprinter