Skip to content

Commit 67f1d7a

Browse files
committed
reject ( in arrow function binding patterns
1 parent 4b34056 commit 67f1d7a

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

internal/js_parser/js_parser.go

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1561,6 +1561,9 @@ type deferredErrors struct {
15611561
invalidExprDefaultValue logger.Range
15621562
invalidExprAfterQuestion logger.Range
15631563
arraySpreadFeature logger.Range
1564+
1565+
// These errors are for arrow functions
1566+
invalidParens []logger.Range
15641567
}
15651568

15661569
func (from *deferredErrors) mergeInto(to *deferredErrors) {
@@ -1573,6 +1576,13 @@ func (from *deferredErrors) mergeInto(to *deferredErrors) {
15731576
if from.arraySpreadFeature.Len > 0 {
15741577
to.arraySpreadFeature = from.arraySpreadFeature
15751578
}
1579+
if len(from.invalidParens) > 0 {
1580+
if len(to.invalidParens) > 0 {
1581+
to.invalidParens = append(to.invalidParens, from.invalidParens...)
1582+
} else {
1583+
to.invalidParens = from.invalidParens
1584+
}
1585+
}
15761586
}
15771587

15781588
func (p *parser) logExprErrors(errors *deferredErrors) {
@@ -1590,6 +1600,12 @@ func (p *parser) logExprErrors(errors *deferredErrors) {
15901600
}
15911601
}
15921602

1603+
func (p *parser) logDeferredArrowArgErrors(errors *deferredErrors) {
1604+
for _, paren := range errors.invalidParens {
1605+
p.log.Add(logger.Error, &p.tracker, paren, "Invalid binding pattern")
1606+
}
1607+
}
1608+
15931609
// The "await" and "yield" expressions are never allowed in argument lists but
15941610
// may or may not be allowed otherwise depending on the details of the enclosing
15951611
// function or module. This needs to be handled when parsing an arrow function
@@ -1619,13 +1635,11 @@ type deferredArrowArgErrors struct {
16191635

16201636
func (p *parser) logArrowArgErrors(errors *deferredArrowArgErrors) {
16211637
if errors.invalidExprAwait.Len > 0 {
1622-
r := errors.invalidExprAwait
1623-
p.log.Add(logger.Error, &p.tracker, r, "Cannot use an \"await\" expression here:")
1638+
p.log.Add(logger.Error, &p.tracker, errors.invalidExprAwait, "Cannot use an \"await\" expression here:")
16241639
}
16251640

16261641
if errors.invalidExprYield.Len > 0 {
1627-
r := errors.invalidExprYield
1628-
p.log.Add(logger.Error, &p.tracker, r, "Cannot use a \"yield\" expression here:")
1642+
p.log.Add(logger.Error, &p.tracker, errors.invalidExprYield, "Cannot use a \"yield\" expression here:")
16291643
}
16301644
}
16311645

@@ -2630,6 +2644,7 @@ func (p *parser) parseParenExpr(loc logger.Loc, level js_ast.L, opts parenExprOp
26302644
p.log.Add(logger.Error, &p.tracker, logger.Range{Loc: commaAfterSpread, Len: 1}, "Unexpected \",\" after rest pattern")
26312645
}
26322646
p.logArrowArgErrors(&arrowArgErrors)
2647+
p.logDeferredArrowArgErrors(&errors)
26332648

26342649
// Now that we've decided we're an arrow function, report binding pattern
26352650
// conversion errors
@@ -2749,9 +2764,6 @@ func (p *parser) convertExprToBinding(expr js_ast.Expr, invalidLog invalidLog) (
27492764
if e.CommaAfterSpread.Start != 0 {
27502765
invalidLog.invalidTokens = append(invalidLog.invalidTokens, logger.Range{Loc: e.CommaAfterSpread, Len: 1})
27512766
}
2752-
if e.IsParenthesized {
2753-
invalidLog.invalidTokens = append(invalidLog.invalidTokens, p.source.RangeOfOperatorBefore(expr.Loc, "("))
2754-
}
27552767
p.markSyntaxFeature(compat.Destructuring, p.source.RangeOfOperatorAfter(expr.Loc, "["))
27562768
items := []js_ast.ArrayBinding{}
27572769
isSpread := false
@@ -2777,9 +2789,6 @@ func (p *parser) convertExprToBinding(expr js_ast.Expr, invalidLog invalidLog) (
27772789
if e.CommaAfterSpread.Start != 0 {
27782790
invalidLog.invalidTokens = append(invalidLog.invalidTokens, logger.Range{Loc: e.CommaAfterSpread, Len: 1})
27792791
}
2780-
if e.IsParenthesized {
2781-
invalidLog.invalidTokens = append(invalidLog.invalidTokens, p.source.RangeOfOperatorBefore(expr.Loc, "("))
2782-
}
27832792
p.markSyntaxFeature(compat.Destructuring, p.source.RangeOfOperatorAfter(expr.Loc, "{"))
27842793
properties := []js_ast.PropertyBinding{}
27852794
for _, item := range e.Properties {
@@ -2843,6 +2852,10 @@ func (p *parser) parsePrefix(level js_ast.L, errors *deferredErrors, flags exprF
28432852
return js_ast.Expr{Loc: loc, Data: js_ast.ESuperShared}
28442853

28452854
case js_lexer.TOpenParen:
2855+
if errors != nil {
2856+
errors.invalidParens = append(errors.invalidParens, p.lexer.Range())
2857+
}
2858+
28462859
p.lexer.Next()
28472860

28482861
// Arrow functions aren't allowed in the middle of expressions
@@ -3253,7 +3266,7 @@ func (p *parser) parsePrefix(level js_ast.L, errors *deferredErrors, flags exprF
32533266
if p.lexer.Token == js_lexer.TDotDotDot {
32543267
dotLoc := p.lexer.Loc()
32553268
p.lexer.Next()
3256-
value := p.parseExpr(js_ast.LComma)
3269+
value := p.parseExprOrBindings(js_ast.LComma, &selfErrors)
32573270
properties = append(properties, js_ast.Property{
32583271
Kind: js_ast.PropertySpread,
32593272
Loc: dotLoc,

internal/js_parser/js_parser_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1122,6 +1122,12 @@ func TestPattern(t *testing.T) {
11221122

11231123
expectPrinted(t, "let {1_2_3n: x} = y", "let { 123n: x } = y;\n")
11241124
expectPrinted(t, "let {0x1_2_3n: x} = y", "let { 0x123n: x } = y;\n")
1125+
1126+
expectParseError(t, "var [ (x) ] = 0", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
1127+
expectParseError(t, "var [ ...(x) ] = 0", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
1128+
expectParseError(t, "var { (x) } = 0", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
1129+
expectParseError(t, "var { x: (y) } = 0", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
1130+
expectParseError(t, "var { ...(x) } = 0", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
11251131
}
11261132

11271133
func TestAssignTarget(t *testing.T) {
@@ -1136,6 +1142,12 @@ func TestAssignTarget(t *testing.T) {
11361142
expectParseError(t, "({x = 0} = 0)", "")
11371143
expectParseError(t, "({x: y = 0} = 0)", "")
11381144

1145+
expectParseError(t, "[ (y) ] = 0", "")
1146+
expectParseError(t, "[ ...(y) ] = 0", "")
1147+
expectParseError(t, "({ (y) } = 0)", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
1148+
expectParseError(t, "({ y: (z) } = 0)", "")
1149+
expectParseError(t, "({ ...(y) } = 0)", "")
1150+
11391151
expectParseError(t, "[...x = y] = 0", "<stdin>: ERROR: Invalid assignment target\n")
11401152
expectParseError(t, "x() = 0", "<stdin>: ERROR: Invalid assignment target\n")
11411153
expectParseError(t, "x?.y = 0", "<stdin>: ERROR: Invalid assignment target\n")
@@ -1979,6 +1991,17 @@ func TestArrow(t *testing.T) {
19791991
expectParseError(t, "({a: b, get c() {}}) => {}", "<stdin>: ERROR: Invalid binding pattern\n")
19801992
expectParseError(t, "({a: b, set c(x) {}}) => {}", "<stdin>: ERROR: Invalid binding pattern\n")
19811993

1994+
expectParseError(t, "x = ([ (y) ]) => 0", "<stdin>: ERROR: Invalid binding pattern\n")
1995+
expectParseError(t, "x = ([ ...(y) ]) => 0", "<stdin>: ERROR: Invalid binding pattern\n")
1996+
expectParseError(t, "x = ({ (y) }) => 0", "<stdin>: ERROR: Expected identifier but found \"(\"\n")
1997+
expectParseError(t, "x = ({ y: (z) }) => 0", "<stdin>: ERROR: Invalid binding pattern\n")
1998+
expectParseError(t, "x = ({ ...(y) }) => 0", "<stdin>: ERROR: Invalid binding pattern\n")
1999+
2000+
expectPrinted(t, "x = ([ y = [ (z) ] ]) => 0", "x = ([y = [z]]) => 0;\n")
2001+
expectPrinted(t, "x = ([ y = [ ...(z) ] ]) => 0", "x = ([y = [...z]]) => 0;\n")
2002+
expectPrinted(t, "x = ({ y = { y: (z) } }) => 0", "x = ({ y = { y: z } }) => 0;\n")
2003+
expectPrinted(t, "x = ({ y = { ...(y) } }) => 0", "x = ({ y = { ...y } }) => 0;\n")
2004+
19822005
expectPrinted(t, "x => function() {}", "(x) => function() {\n};\n")
19832006
expectPrinted(t, "(x) => function() {}", "(x) => function() {\n};\n")
19842007
expectPrinted(t, "(x => function() {})", "(x) => function() {\n};\n")

0 commit comments

Comments
 (0)