@@ -3654,3 +3654,202 @@ func hasComment(kind Kind) bool {
36543654 return false
36553655 }
36563656}
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