@@ -3654,3 +3654,202 @@ func hasComment(kind Kind) bool {
3654
3654
return false
3655
3655
}
3656
3656
}
3657
+
3658
+ func IsAssignmentPattern (node * Node ) bool {
3659
+ return node .Kind == KindArrayLiteralExpression || node .Kind == KindObjectLiteralExpression
3660
+ }
3661
+
3662
+ func GetElementsOfBindingOrAssignmentPattern (name * Node ) []* Node {
3663
+ switch name .Kind {
3664
+ case KindObjectBindingPattern , KindArrayBindingPattern :
3665
+ // `a` in `{a}`
3666
+ // `a` in `[a]`
3667
+ return name .AsBindingPattern ().Elements .Nodes
3668
+ case KindArrayLiteralExpression :
3669
+ // `a` in `[a]`
3670
+ return name .AsArrayLiteralExpression ().Elements .Nodes
3671
+ case KindObjectLiteralExpression :
3672
+ // `a` in `{a}`
3673
+ return name .AsObjectLiteralExpression ().Properties .Nodes
3674
+ }
3675
+ return nil
3676
+ }
3677
+
3678
+ func IsDeclarationBindingElement (bindingElement * Node ) bool {
3679
+ switch bindingElement .Kind {
3680
+ case KindVariableDeclaration , KindParameter , KindBindingElement :
3681
+ return true
3682
+ default :
3683
+ return false
3684
+ }
3685
+ }
3686
+
3687
+ /**
3688
+ * Gets the name of an BindingOrAssignmentElement.
3689
+ */
3690
+ func GetTargetOfBindingOrAssignmentElement (bindingElement * Node ) * Node {
3691
+ if IsDeclarationBindingElement (bindingElement ) {
3692
+ // `a` in `let { a } = ...`
3693
+ // `a` in `let { a = 1 } = ...`
3694
+ // `b` in `let { a: b } = ...`
3695
+ // `b` in `let { a: b = 1 } = ...`
3696
+ // `a` in `let { ...a } = ...`
3697
+ // `{b}` in `let { a: {b} } = ...`
3698
+ // `{b}` in `let { a: {b} = 1 } = ...`
3699
+ // `[b]` in `let { a: [b] } = ...`
3700
+ // `[b]` in `let { a: [b] = 1 } = ...`
3701
+ // `a` in `let [a] = ...`
3702
+ // `a` in `let [a = 1] = ...`
3703
+ // `a` in `let [...a] = ...`
3704
+ // `{a}` in `let [{a}] = ...`
3705
+ // `{a}` in `let [{a} = 1] = ...`
3706
+ // `[a]` in `let [[a]] = ...`
3707
+ // `[a]` in `let [[a] = 1] = ...`
3708
+ return bindingElement .Name ()
3709
+ }
3710
+
3711
+ if IsObjectLiteralElement (bindingElement ) {
3712
+ switch bindingElement .Kind {
3713
+ case KindPropertyAssignment :
3714
+ // `b` in `({ a: b } = ...)`
3715
+ // `b` in `({ a: b = 1 } = ...)`
3716
+ // `{b}` in `({ a: {b} } = ...)`
3717
+ // `{b}` in `({ a: {b} = 1 } = ...)`
3718
+ // `[b]` in `({ a: [b] } = ...)`
3719
+ // `[b]` in `({ a: [b] = 1 } = ...)`
3720
+ // `b.c` in `({ a: b.c } = ...)`
3721
+ // `b.c` in `({ a: b.c = 1 } = ...)`
3722
+ // `b[0]` in `({ a: b[0] } = ...)`
3723
+ // `b[0]` in `({ a: b[0] = 1 } = ...)`
3724
+ return GetTargetOfBindingOrAssignmentElement (bindingElement .Initializer ())
3725
+ case KindShorthandPropertyAssignment :
3726
+ // `a` in `({ a } = ...)`
3727
+ // `a` in `({ a = 1 } = ...)`
3728
+ return bindingElement .Name ()
3729
+ case KindSpreadAssignment :
3730
+ // `a` in `({ ...a } = ...)`
3731
+ return GetTargetOfBindingOrAssignmentElement (bindingElement .AsSpreadAssignment ().Expression )
3732
+ }
3733
+
3734
+ // no target
3735
+ return nil
3736
+ }
3737
+
3738
+ if IsAssignmentExpression (bindingElement /*excludeCompoundAssignment*/ , true ) {
3739
+ // `a` in `[a = 1] = ...`
3740
+ // `{a}` in `[{a} = 1] = ...`
3741
+ // `[a]` in `[[a] = 1] = ...`
3742
+ // `a.b` in `[a.b = 1] = ...`
3743
+ // `a[0]` in `[a[0] = 1] = ...`
3744
+ return GetTargetOfBindingOrAssignmentElement (bindingElement .AsBinaryExpression ().Left )
3745
+ }
3746
+
3747
+ if IsSpreadElement (bindingElement ) {
3748
+ // `a` in `[...a] = ...`
3749
+ return GetTargetOfBindingOrAssignmentElement (bindingElement .AsSpreadElement ().Expression )
3750
+ }
3751
+
3752
+ // `a` in `[a] = ...`
3753
+ // `{a}` in `[{a}] = ...`
3754
+ // `[a]` in `[[a]] = ...`
3755
+ // `a.b` in `[a.b] = ...`
3756
+ // `a[0]` in `[a[0]] = ...`
3757
+ return bindingElement
3758
+ }
3759
+
3760
+ func TryGetPropertyNameOfBindingOrAssignmentElement (bindingElement * Node ) * Node {
3761
+ switch bindingElement .Kind {
3762
+ case KindBindingElement :
3763
+ // `a` in `let { a: b } = ...`
3764
+ // `[a]` in `let { [a]: b } = ...`
3765
+ // `"a"` in `let { "a": b } = ...`
3766
+ // `1` in `let { 1: b } = ...`
3767
+ if bindingElement .AsBindingElement ().PropertyName != nil {
3768
+ propertyName := bindingElement .AsBindingElement ().PropertyName
3769
+ // if ast.IsPrivateIdentifier(propertyName) {
3770
+ // return Debug.failBadSyntaxKind(propertyName) // !!!
3771
+ // }
3772
+ if IsComputedPropertyName (propertyName ) && IsStringOrNumericLiteralLike (propertyName .AsComputedPropertyName ().Expression ) {
3773
+ return propertyName .AsComputedPropertyName ().Expression
3774
+ }
3775
+ return propertyName
3776
+ }
3777
+ case KindPropertyAssignment :
3778
+ // `a` in `({ a: b } = ...)`
3779
+ // `[a]` in `({ [a]: b } = ...)`
3780
+ // `"a"` in `({ "a": b } = ...)`
3781
+ // `1` in `({ 1: b } = ...)`
3782
+ if bindingElement .Name () != nil {
3783
+ propertyName := bindingElement .Name ()
3784
+ // if ast.IsPrivateIdentifier(propertyName) {
3785
+ // return Debug.failBadSyntaxKind(propertyName) // !!!
3786
+ // }
3787
+ if IsComputedPropertyName (propertyName ) && IsStringOrNumericLiteralLike (propertyName .AsComputedPropertyName ().Expression ) {
3788
+ return propertyName .AsComputedPropertyName ().Expression
3789
+ }
3790
+ return propertyName
3791
+ }
3792
+ case KindSpreadAssignment :
3793
+ // `a` in `({ ...a } = ...)`
3794
+ // if ast.IsPrivateIdentifier(bindingElement.Name()) {
3795
+ // return Debug.failBadSyntaxKind(bindingElement.Name()) // !!!
3796
+ // }
3797
+ return bindingElement .Name ()
3798
+ }
3799
+
3800
+ target := GetTargetOfBindingOrAssignmentElement (bindingElement )
3801
+ if target != nil && IsPropertyName (target ) {
3802
+ return target
3803
+ }
3804
+ return nil
3805
+ }
3806
+
3807
+ /**
3808
+ * Walk an AssignmentPattern to determine if it contains object rest (`...`) syntax. We cannot rely on
3809
+ * propagation of `TransformFlags.ContainsObjectRestOrSpread` since it isn't propagated by default in
3810
+ * ObjectLiteralExpression and ArrayLiteralExpression since we do not know whether they belong to an
3811
+ * AssignmentPattern at the time the nodes are parsed.
3812
+ */
3813
+ func ContainsObjectRestOrSpread (node * Node ) bool {
3814
+ if node .SubtreeFacts ()& SubtreeContainsObjectRestOrSpread != 0 {
3815
+ return true
3816
+ }
3817
+ if node .SubtreeFacts ()& SubtreeContainsESObjectRestOrSpread != 0 {
3818
+ // check for nested spread assignments, otherwise '{ x: { a, ...b } = foo } = c'
3819
+ // will not be correctly interpreted by the rest/spread transformer
3820
+ for _ , element := range GetElementsOfBindingOrAssignmentPattern (node ) {
3821
+ target := GetTargetOfBindingOrAssignmentElement (element )
3822
+ if target != nil && IsAssignmentPattern (target ) {
3823
+ if target .SubtreeFacts ()& SubtreeContainsObjectRestOrSpread != 0 {
3824
+ return true
3825
+ }
3826
+ if target .SubtreeFacts ()& SubtreeContainsESObjectRestOrSpread != 0 {
3827
+ if ContainsObjectRestOrSpread (target ) {
3828
+ return true
3829
+ }
3830
+ }
3831
+ }
3832
+ }
3833
+ }
3834
+ return false
3835
+ }
3836
+
3837
+ func IsEmptyObjectLiteral (expression * Node ) bool {
3838
+ return expression .Kind == KindObjectLiteralExpression && len (expression .AsObjectLiteralExpression ().Properties .Nodes ) == 0
3839
+ }
3840
+
3841
+ func IsEmptyArrayLiteral (expression * Node ) bool {
3842
+ return expression .Kind == KindArrayLiteralExpression && len (expression .AsArrayLiteralExpression ().Elements .Nodes ) == 0
3843
+ }
3844
+
3845
+ func GetRestIndicatorOfBindingOrAssignmentElement (bindingElement * Node ) * Node {
3846
+ switch bindingElement .Kind {
3847
+ case KindParameter :
3848
+ return bindingElement .AsParameterDeclaration ().DotDotDotToken
3849
+ case KindBindingElement :
3850
+ return bindingElement .AsBindingElement ().DotDotDotToken
3851
+ case KindSpreadElement , KindSpreadAssignment :
3852
+ return bindingElement
3853
+ }
3854
+ return nil
3855
+ }
0 commit comments