From a3b2ecbb209d29cfe79223837b18a0fd8ca07be3 Mon Sep 17 00:00:00 2001 From: Alan Pierce Date: Mon, 4 Mar 2019 07:35:07 -0800 Subject: [PATCH] Fix implementation of JSX spread children Fixes #420 This was actually already handled by the parser carried over from Babel, but there was a bug in the tokenization, since Sucrase always skips the last token so we can get the proper token type for the next one. After fixing that bug, everything seems to work; no transformer changes are needed because argument spread syntax is the same as JSX child spread syntax. As mentioned in #420, Babel disallows this syntax with React and TypeScript seems to give the wrong result, but this change like a good idea regardless since it's just a bug fix. --- src/parser/plugins/jsx/index.ts | 3 ++- test/jsx-test.ts | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/parser/plugins/jsx/index.ts b/src/parser/plugins/jsx/index.ts index 0ee5a3af..9b38c0a9 100644 --- a/src/parser/plugins/jsx/index.ts +++ b/src/parser/plugins/jsx/index.ts @@ -139,11 +139,11 @@ function jsxParseEmptyExpression(): void { } // Parse JSX spread child +// Does not parse the last token. function jsxParseSpreadChild(): void { expect(tt.braceL); expect(tt.ellipsis); parseExpression(); - expect(tt.braceR); } // Parses JSX expression enclosed into curly brackets. @@ -233,6 +233,7 @@ function jsxParseElementAt(): void { case tt.braceL: if (lookaheadType() === tt.ellipsis) { jsxParseSpreadChild(); + nextJSXExprToken(); } else { jsxParseExpressionContainer(); nextJSXExprToken(); diff --git a/test/jsx-test.ts b/test/jsx-test.ts index 8094069b..bb55a067 100644 --- a/test/jsx-test.ts +++ b/test/jsx-test.ts @@ -499,6 +499,17 @@ describe("transform JSX", () => { throws(() => transform("const x = <", {transforms: ["jsx"]})); }); + it("handles spread children", () => { + assertResult( + ` + const e = {...b}; + `, + `${JSX_PREFIX} + const e = React.createElement(A, {${devProps(2)}}, ...b); + `, + ); + }); + describe("with production true", () => { it("handles no props", () => { assertResult(