Remove restriction on optional nesting
We previously disallowed OptionalMemberExpression inside a normal MemberExpression, eg `(a?.b).c`. The new representation handles this case correctly so we can remove the restriction.
Joe Savona committed
May 3, 2023 at 17:10 UTC
253b05f28d02c2403b3f8210ee2b20182a054253
3 files changed
+10
-37
compiler/forget/src/HIR/BuildHIR.ts
-26
@@ -2113,32 +2113,6 @@ function lowerMemberExpression(
2113
const object =
2114
loweredObject ?? lowerExpressionToTemporary(builder, objectNode);
2115
2116
- if (
2117
- objectNode.isOptionalMemberExpression() &&
2118
- !expr.isOptionalMemberExpression()
2119
- ) {
2120
- // Babel's `isOptionalMemberExpression` indicates whether this property load itself
2121
- // is conditional (i.e. within an "optional chain"). This is different from the
2122
- // `optional` property, which is only true for property loads at the start of an
2123
- // optional chain. e.g. `a.b?.c.d` decomposes into
2124
- // [0] MemberExpr a.b; // not in an optional chain
2125
- // [1] OptionalMemberExpr [0]?.c
2126
- // [2] OptionalMemberExpr [1].c
2127
- // [3] OptionalMemberExpr [2].d
2128
- // We currently do not handle non-conditional loads from an optional memberexpr
2129
- // e.g. `(a?.b).c`
2130
- // See error.nonoptional-load-from-optional-memberexpr test fixture for details
2131
- builder.errors.push({
2132
- reason: `(BuildHIR::lowerMemberExpression) Handle optional chaining for non-optional member expr.`,
2133
- severity: ErrorSeverity.Todo,
2134
- nodePath: propertyNode,
2135
- });
2136
- return {
2137
- object,
2138
- property: propertyNode.toString(),
2139
- value: { kind: "UnsupportedNode", node: exprNode, loc: exprLoc },
2140
- };
2141
- }
2116
if (!expr.node.computed) {
2117
if (!propertyNode.isIdentifier()) {
2118
builder.errors.push({
compiler/forget/src/__tests__/fixtures/compiler/nonoptional-load-from-optional-memberexpr.expect.md
renamed
+10
-11
@@ -13,18 +13,17 @@ function Component(props) {
13
14
```
15
16
+## Code
17
17
-## Error
18
+```javascript
19
+// Note that `a?.b.c` is semantically different from `(a?.b).c`
20
+// Here, 'props?.a` is an optional chain, and `.b` is an unconditional load
21
+// (nullthrows if a is nullish)
22
+
23
+function Component(props) {
24
+ const x = (props?.a).b;
25
+ return x;
26
+}
27
28
```
20
-[ReactForget] TodoError: (BuildHIR::lowerMemberExpression) Handle optional chaining for non-optional member expr.
21
- 4 |
22
- 5 | function Component(props) {
23
-> 6 | let x = (props?.a).b;
24
- | ^
25
- 7 | return x;
26
- 8 | }
27
- 9 |
28
-```
29
-
29
\ No newline at end of file