Skip to content

Commit 0681ef7

Browse files
authored
Fixed a crash on JSX emit trying to emit unexpectedly recovered BinaryExpression in a JSX attribute (#64470)
1 parent 19dadef commit 0681ef7

8 files changed

Lines changed: 101 additions & 6 deletions

‎tsc/internal/parser/parser.go‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5093,7 +5093,9 @@ func (p *Parser) parseJsxAttributeValue() *ast.Expression {
50935093
return p.parseJsxExpression( /*inExpressionContext*/ true)
50945094
}
50955095
if p.token == ast.KindLessThanToken {
5096-
return p.parseJsxElementOrSelfClosingElementOrFragment(true /*inExpressionContext*/, -1, nil, false)
5096+
// An attribute value must be a single JsxAttributeValue, so don't allow the sibling-element
5097+
// recovery to wrap it in a synthetic binary expression.
5098+
return p.parseJsxElementOrSelfClosingElementOrFragment(true /*inExpressionContext*/, -1 /*topInvalidNodePosition*/, nil /*openingTag*/, true /*mustBeUnary*/)
50975099
}
50985100
p.parseErrorAtCurrentToken(diagnostics.X_or_JSX_element_expected)
50995101
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,11): error TS2657: JSX expressions must have one parent element.
2+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,29): error TS1003: Identifier expected.
3+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,39): error TS1109: Expression expected.
4+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,40): error TS1109: Expression expected.
5+
6+
7+
==== jsxAttributeInitializerMultipleElementsNoCrash.tsx (4 errors) ====
8+
declare namespace JSX { interface IntrinsicElements { [x: string]: any } }
9+
declare const React: any;
10+
11+
const a = <div attr=<span /><span /> />;
12+
~~~~~~~~~~~~~~~~~~~~~~~~~~
13+
!!! error TS2657: JSX expressions must have one parent element.
14+
~
15+
!!! error TS1003: Identifier expected.
16+
~
17+
!!! error TS1109: Expression expected.
18+
~
19+
!!! error TS1109: Expression expected.
20+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [tests/cases/compiler/jsxAttributeInitializerMultipleElementsNoCrash.tsx] ////
2+
3+
//// [jsxAttributeInitializerMultipleElementsNoCrash.tsx]
4+
declare namespace JSX { interface IntrinsicElements { [x: string]: any } }
5+
declare const React: any;
6+
7+
const a = <div attr=<span /><span /> />;
8+
9+
10+
//// [jsxAttributeInitializerMultipleElementsNoCrash.js]
11+
"use strict";
12+
const a = (React.createElement("div", { attr: React.createElement("span", null) }), React.createElement("span", null)) / > ;
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,11): error TS2875: This JSX tag requires the module path 'react/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed.
2+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,11): error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
3+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,11): error TS2657: JSX expressions must have one parent element.
4+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,21): error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
5+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,29): error TS1003: Identifier expected.
6+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,29): error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
7+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,39): error TS1109: Expression expected.
8+
jsxAttributeInitializerMultipleElementsNoCrash.tsx(4,40): error TS1109: Expression expected.
9+
10+
11+
==== jsxAttributeInitializerMultipleElementsNoCrash.tsx (8 errors) ====
12+
declare namespace JSX { interface IntrinsicElements { [x: string]: any } }
13+
declare const React: any;
14+
15+
const a = <div attr=<span /><span /> />;
16+
~~~~~~~~~~~~~~~~~~
17+
!!! error TS2875: This JSX tag requires the module path 'react/jsx-runtime' to exist, but none could be found. Make sure you have types for the appropriate package installed.
18+
~~~~~~~~~~~~~~~~~~
19+
!!! error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
20+
~~~~~~~~~~~~~~~~~~~~~~~~~~
21+
!!! error TS2657: JSX expressions must have one parent element.
22+
~~~~~~~~
23+
!!! error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
24+
~
25+
!!! error TS1003: Identifier expected.
26+
~~~~~~~~
27+
!!! error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
28+
~
29+
!!! error TS1109: Expression expected.
30+
~
31+
!!! error TS1109: Expression expected.
32+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//// [tests/cases/compiler/jsxAttributeInitializerMultipleElementsNoCrash.tsx] ////
2+
3+
//// [jsxAttributeInitializerMultipleElementsNoCrash.tsx]
4+
declare namespace JSX { interface IntrinsicElements { [x: string]: any } }
5+
declare const React: any;
6+
7+
const a = <div attr=<span /><span /> />;
8+
9+
10+
//// [jsxAttributeInitializerMultipleElementsNoCrash.js]
11+
import { jsx as _jsx } from "react/jsx-runtime";
12+
const a = (_jsx("div", { attr: _jsx("span", {}) }), _jsx("span", {})) / > ;
Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
1+
jsxAttributeValueBinaryExpression.tsx(1,1): error TS2657: JSX expressions must have one parent element.
12
jsxAttributeValueBinaryExpression.tsx(1,2): error TS2304: Cannot find name 'X'.
23
jsxAttributeValueBinaryExpression.tsx(1,6): error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
3-
jsxAttributeValueBinaryExpression.tsx(1,6): error TS2657: JSX expressions must have one parent element.
4+
jsxAttributeValueBinaryExpression.tsx(1,10): error TS1003: Identifier expected.
45
jsxAttributeValueBinaryExpression.tsx(1,10): error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
6+
jsxAttributeValueBinaryExpression.tsx(1,16): error TS1109: Expression expected.
7+
jsxAttributeValueBinaryExpression.tsx(1,17): error TS1109: Expression expected.
58

69

7-
==== jsxAttributeValueBinaryExpression.tsx (4 errors) ====
10+
==== jsxAttributeValueBinaryExpression.tsx (7 errors) ====
811
<X a=<b/><c/> />
12+
~~~~~~~~~~~~~
13+
!!! error TS2657: JSX expressions must have one parent element.
914
~
1015
!!! error TS2304: Cannot find name 'X'.
1116
~~~~
1217
!!! error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
13-
~~~~~~~~
14-
!!! error TS2657: JSX expressions must have one parent element.
18+
~
19+
!!! error TS1003: Identifier expected.
1520
~~~~
1621
!!! error TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
22+
~
23+
!!! error TS1109: Expression expected.
24+
25+
!!! error TS1109: Expression expected.
1726

‎tsc/testdata/baselines/reference/compiler/jsxAttributeValueBinaryExpression.js‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66

77
//// [jsxAttributeValueBinaryExpression.jsx]
88
"use strict";
9-
<X a=<b />, <c />/>;
9+
(<X a=<b />/>, <c />) / >
10+
;
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @jsx: react,react-jsx
2+
// @noTypesAndSymbols: true
3+
4+
declare namespace JSX { interface IntrinsicElements { [x: string]: any } }
5+
declare const React: any;
6+
7+
const a = <div attr=<span /><span /> />;

0 commit comments

Comments
 (0)