@samitouri / QOS-React-2 / commits / 253b05f28d

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
compiler/forget/src/__tests__/fixtures/compiler/nonoptional-load-from-optional-memberexpr.js renamed