Ensure all JSX spread properties get visited in ES2018+ (#55859)

This commit is contained in:
Mateusz Burzyński 2023-10-27 20:36:21 +02:00 committed by GitHub
parent 85c2577285
commit a25321afce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 228 additions and 2 deletions

View File

@ -36,6 +36,7 @@ import {
isJsxSelfClosingElement,
isJsxSpreadAttribute,
isLineBreak,
isObjectLiteralElementLike,
isObjectLiteralExpression,
isPropertyAssignment,
isSourceFile,
@ -63,6 +64,7 @@ import {
ObjectLiteralElementLike,
ObjectLiteralExpression,
PropertyAssignment,
sameMap,
ScriptTarget,
setIdentifierGeneratedImportReference,
setParentRecursive,
@ -444,7 +446,7 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B
function transformJsxSpreadAttributeToProps(node: JsxSpreadAttribute) {
if (isObjectLiteralExpression(node.expression) && !hasProto(node.expression)) {
return node.expression.properties;
return sameMap(node.expression.properties, p => Debug.checkDefined(visitNode(p, visitor, isObjectLiteralElementLike)));
}
return factory.createSpreadAssignment(Debug.checkDefined(visitNode(node.expression, visitor, isExpression)));
}

View File

@ -0,0 +1,36 @@
/a.tsx(5,13): error TS2304: Cannot find name 'Comp'.
/a.tsx(9,13): error TS2304: Cannot find name 'Comp'.
/a.tsx(13,13): error TS2304: Cannot find name 'Comp'.
/a.tsx(17,13): error TS2304: Cannot find name 'Comp'.
==== /a.tsx (4 errors) ====
declare const React: any;
const t1 = <div {...<span />} />;
const t2 = <div {...<span className="foo" />} />;
const t3 = <Comp
~~~~
!!! error TS2304: Cannot find name 'Comp'.
right={<div>x</div>}
{...{ wrong: <div>x</div>}}
/>;
const t4 = <Comp
~~~~
!!! error TS2304: Cannot find name 'Comp'.
right={<div>x</div>}
{...{ wrong() { return <div>x</div>; }}}
/>;
const t5 = <Comp
~~~~
!!! error TS2304: Cannot find name 'Comp'.
right={<div>x</div>}
{...{ get wrong() { return <div>x</div>; }}}
/>;
const t6 = <Comp
~~~~
!!! error TS2304: Cannot find name 'Comp'.
right={<div>x</div>}
{...{ set wrong(s) { let a = <div>x</div>; }}}
/>;

View File

@ -0,0 +1,32 @@
//// [tests/cases/compiler/jsxSpreadTag.ts] ////
//// [a.tsx]
declare const React: any;
const t1 = <div {...<span />} />;
const t2 = <div {...<span className="foo" />} />;
const t3 = <Comp
right={<div>x</div>}
{...{ wrong: <div>x</div>}}
/>;
const t4 = <Comp
right={<div>x</div>}
{...{ wrong() { return <div>x</div>; }}}
/>;
const t5 = <Comp
right={<div>x</div>}
{...{ get wrong() { return <div>x</div>; }}}
/>;
const t6 = <Comp
right={<div>x</div>}
{...{ set wrong(s) { let a = <div>x</div>; }}}
/>;
//// [a.js]
const t1 = React.createElement("div", { ...React.createElement("span", null) });
const t2 = React.createElement("div", { ...React.createElement("span", { className: "foo" }) });
const t3 = React.createElement(Comp, { right: React.createElement("div", null, "x"), wrong: React.createElement("div", null, "x") });
const t4 = React.createElement(Comp, { right: React.createElement("div", null, "x"), wrong() { return React.createElement("div", null, "x"); } });
const t5 = React.createElement(Comp, { right: React.createElement("div", null, "x"), get wrong() { return React.createElement("div", null, "x"); } });
const t6 = React.createElement(Comp, { right: React.createElement("div", null, "x"), set wrong(s) { let a = React.createElement("div", null, "x"); } });

View File

@ -0,0 +1,56 @@
//// [tests/cases/compiler/jsxSpreadTag.ts] ////
=== /a.tsx ===
declare const React: any;
>React : Symbol(React, Decl(a.tsx, 0, 13))
const t1 = <div {...<span />} />;
>t1 : Symbol(t1, Decl(a.tsx, 2, 5))
const t2 = <div {...<span className="foo" />} />;
>t2 : Symbol(t2, Decl(a.tsx, 3, 5))
>className : Symbol(className, Decl(a.tsx, 3, 25))
const t3 = <Comp
>t3 : Symbol(t3, Decl(a.tsx, 4, 5))
right={<div>x</div>}
>right : Symbol(right, Decl(a.tsx, 4, 16))
{...{ wrong: <div>x</div>}}
>wrong : Symbol(wrong, Decl(a.tsx, 6, 9))
/>;
const t4 = <Comp
>t4 : Symbol(t4, Decl(a.tsx, 8, 5))
right={<div>x</div>}
>right : Symbol(right, Decl(a.tsx, 8, 16))
{...{ wrong() { return <div>x</div>; }}}
>wrong : Symbol(wrong, Decl(a.tsx, 10, 9))
/>;
const t5 = <Comp
>t5 : Symbol(t5, Decl(a.tsx, 12, 5))
right={<div>x</div>}
>right : Symbol(right, Decl(a.tsx, 12, 16))
{...{ get wrong() { return <div>x</div>; }}}
>wrong : Symbol(wrong, Decl(a.tsx, 14, 9))
/>;
const t6 = <Comp
>t6 : Symbol(t6, Decl(a.tsx, 16, 5))
right={<div>x</div>}
>right : Symbol(right, Decl(a.tsx, 16, 16))
{...{ set wrong(s) { let a = <div>x</div>; }}}
>wrong : Symbol(wrong, Decl(a.tsx, 18, 9))
>s : Symbol(s, Decl(a.tsx, 18, 20))
>a : Symbol(a, Decl(a.tsx, 18, 28))
/>;

View File

@ -0,0 +1,100 @@
//// [tests/cases/compiler/jsxSpreadTag.ts] ////
=== /a.tsx ===
declare const React: any;
>React : any
const t1 = <div {...<span />} />;
>t1 : any
><div {...<span />} /> : any
>div : any
><span /> : any
>span : any
const t2 = <div {...<span className="foo" />} />;
>t2 : any
><div {...<span className="foo" />} /> : any
>div : any
><span className="foo" /> : any
>span : any
>className : string
const t3 = <Comp
>t3 : any
><Comp right={<div>x</div>} {...{ wrong: <div>x</div>}}/> : any
>Comp : any
right={<div>x</div>}
>right : any
><div>x</div> : any
>div : any
>div : any
{...{ wrong: <div>x</div>}}
>{ wrong: <div>x</div>} : { wrong: any; }
>wrong : any
><div>x</div> : any
>div : any
>div : any
/>;
const t4 = <Comp
>t4 : any
><Comp right={<div>x</div>} {...{ wrong() { return <div>x</div>; }}}/> : any
>Comp : any
right={<div>x</div>}
>right : any
><div>x</div> : any
>div : any
>div : any
{...{ wrong() { return <div>x</div>; }}}
>{ wrong() { return <div>x</div>; }} : { wrong(): any; }
>wrong : () => any
><div>x</div> : any
>div : any
>div : any
/>;
const t5 = <Comp
>t5 : any
><Comp right={<div>x</div>} {...{ get wrong() { return <div>x</div>; }}}/> : any
>Comp : any
right={<div>x</div>}
>right : any
><div>x</div> : any
>div : any
>div : any
{...{ get wrong() { return <div>x</div>; }}}
>{ get wrong() { return <div>x</div>; }} : { readonly wrong: any; }
>wrong : any
><div>x</div> : any
>div : any
>div : any
/>;
const t6 = <Comp
>t6 : any
><Comp right={<div>x</div>} {...{ set wrong(s) { let a = <div>x</div>; }}}/> : any
>Comp : any
right={<div>x</div>}
>right : any
><div>x</div> : any
>div : any
>div : any
{...{ set wrong(s) { let a = <div>x</div>; }}}
>{ set wrong(s) { let a = <div>x</div>; }} : { wrong: any; }
>wrong : any
>s : any
>a : any
><div>x</div> : any
>div : any
>div : any
/>;

View File

@ -1,5 +1,5 @@
// @jsx: react
// @target: es2015
// @target: es2015,esnext
// @filename: /a.tsx
declare const React: any;