@@ -803,9 +803,10 @@ export default {
803
803
let maybeID = declaredDependencyNode ;
804
804
while (
805
805
maybeID . type === 'MemberExpression' ||
806
- maybeID . type === 'OptionalMemberExpression'
806
+ maybeID . type === 'OptionalMemberExpression' ||
807
+ maybeID . type === 'ChainExpression'
807
808
) {
808
- maybeID = maybeID . object ;
809
+ maybeID = maybeID . object || maybeID . expression . object ;
809
810
}
810
811
const isDeclaredInComponent = ! componentScope . through . some (
811
812
ref => ref . identifier === maybeID ,
@@ -1599,8 +1600,19 @@ function analyzePropertyChain(node, optionalChains) {
1599
1600
const property = analyzePropertyChain ( node . property , null ) ;
1600
1601
const result = `${ object } .${ property } ` ;
1601
1602
if ( optionalChains ) {
1602
- // Mark as required.
1603
- optionalChains . set ( result , false ) ;
1603
+ // Note: OptionalMemberExpression doesn't necessarily mean this node is optional.
1604
+ // It just means there is an optional member somewhere inside.
1605
+ // This particular node might still represent a required member, so check .optional field.
1606
+ if ( node . optional ) {
1607
+ // We only want to consider it optional if *all* usages were optional.
1608
+ if ( ! optionalChains . has ( result ) ) {
1609
+ // Mark as (maybe) optional. If there's a required usage, this will be overridden.
1610
+ optionalChains . set ( result , true ) ;
1611
+ }
1612
+ } else {
1613
+ // Mark as required.
1614
+ optionalChains . set ( result , false ) ;
1615
+ }
1604
1616
}
1605
1617
return result ;
1606
1618
} else if ( node . type === 'OptionalMemberExpression' && ! node . computed ) {
@@ -1623,6 +1635,27 @@ function analyzePropertyChain(node, optionalChains) {
1623
1635
}
1624
1636
}
1625
1637
return result ;
1638
+ } else if ( node . type === 'ChainExpression' && ! node . computed ) {
1639
+ const expression = node . expression ;
1640
+ const object = analyzePropertyChain ( expression . object , optionalChains ) ;
1641
+ const property = analyzePropertyChain ( expression . property , null ) ;
1642
+ const result = `${ object } .${ property } ` ;
1643
+ if ( optionalChains ) {
1644
+ // Note: OptionalMemberExpression doesn't necessarily mean this node is optional.
1645
+ // It just means there is an optional member somewhere inside.
1646
+ // This particular node might still represent a required member, so check .optional field.
1647
+ if ( expression . optional ) {
1648
+ // We only want to consider it optional if *all* usages were optional.
1649
+ if ( ! optionalChains . has ( result ) ) {
1650
+ // Mark as (maybe) optional. If there's a required usage, this will be overridden.
1651
+ optionalChains . set ( result , true ) ;
1652
+ }
1653
+ } else {
1654
+ // Mark as required.
1655
+ optionalChains . set ( result , false ) ;
1656
+ }
1657
+ }
1658
+ return result ;
1626
1659
} else {
1627
1660
throw new Error ( `Unsupported node type: ${ node . type } ` ) ;
1628
1661
}
0 commit comments