fix(es/react): Allow spread children (#6505)

**Related issue:**

 - Closes https://github.com/swc-project/swc/issues/2037.
This commit is contained in:
Donny/강동윤 2022-11-25 00:21:51 +09:00 committed by GitHub
parent bc61b0948a
commit 90aa6c8318
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 242 additions and 119 deletions

View File

@ -1,3 +1,6 @@
var A = function() {
return /*#__PURE__*/ React.createElement("div", null);
return /*#__PURE__*/ React.createElement.apply(React, [
"div",
null
]);
};

View File

@ -3,22 +3,106 @@ export { };
//// [renderer2.d.ts]
export { };
//// [component.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 4 | export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;
//! : ^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
//!
//! x Spread children are not supported in React.
//! ,----
//! 12 | {...this.props.children}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
/** @jsx predom */ import _class_call_check from "@swc/helpers/src/_class_call_check.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
var _this = this;
import { predom } from "./renderer2";
export var MySFC = function(props) {
return /*#__PURE__*/ predom.apply(void 0, [
"p",
null,
props.x,
" + ",
props.y,
" = ",
props.x + props.y
].concat(_to_consumable_array(_this.props.children)));
};
export var MyClass = /*#__PURE__*/ function() {
"use strict";
function MyClass(props) {
_class_call_check(this, MyClass);
this.props = props;
}
var _proto = MyClass.prototype;
_proto.render = function render() {
return /*#__PURE__*/ predom.apply(void 0, [
"p",
null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y
].concat(_to_consumable_array(this.props.children)));
};
return MyClass;
}();
export var tree = /*#__PURE__*/ predom(MySFC, {
x: 1,
y: 2
}, /*#__PURE__*/ predom(MyClass, {
x: 3,
y: 4
}), /*#__PURE__*/ predom(MyClass, {
x: 5,
y: 6
}));
export default /*#__PURE__*/ predom("h", null);
//// [index.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 13 | return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;
//! : ^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
/** @jsx dom */ import _class_call_check from "@swc/helpers/src/_class_call_check.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
import { dom } from "./renderer";
import prerendered, { MySFC, MyClass, tree } from "./component";
var elem = prerendered;
elem = /*#__PURE__*/ dom("h", null); // Expect assignability error here
var DOMSFC = function(props) {
return /*#__PURE__*/ dom("p", null, props.x, " + ", props.y, " = ", props.x + props.y, props.children);
};
var DOMClass = /*#__PURE__*/ function() {
"use strict";
function DOMClass(props) {
_class_call_check(this, DOMClass);
this.props = props;
}
var _proto = DOMClass.prototype;
_proto.render = function render() {
return /*#__PURE__*/ dom.apply(void 0, [
"p",
null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y
].concat(_to_consumable_array(this.props.children)));
};
return DOMClass;
}();
// Should work, everything is a DOM element
var _tree = /*#__PURE__*/ dom(DOMSFC, {
x: 1,
y: 2
}, /*#__PURE__*/ dom(DOMClass, {
x: 3,
y: 4
}), /*#__PURE__*/ dom(DOMClass, {
x: 5,
y: 6
}));
// Should fail, no dom elements
var _brokenTree = /*#__PURE__*/ dom(MySFC, {
x: 1,
y: 2
}, /*#__PURE__*/ dom(MyClass, {
x: 3,
y: 4
}), /*#__PURE__*/ dom(MyClass, {
x: 5,
y: 6
}));
// Should fail, nondom isn't allowed as children of dom
var _brokenTree2 = /*#__PURE__*/ dom(DOMSFC, {
x: 1,
y: 2
}, tree, tree);

View File

@ -3,22 +3,51 @@ export { };
//// [renderer2.d.ts]
export { };
//// [component.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 4 | export const MySFC = (props: {x: number, y: number, children?: predom.JSX.Element[]}) => <p>{props.x} + {props.y} = {props.x + props.y}{...this.props.children}</p>;
//! : ^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
//!
//! x Spread children are not supported in React.
//! ,----
//! 12 | {...this.props.children}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
import _class_call_check from "@swc/helpers/src/_class_call_check.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
var _this = this;
import { predom } from "./renderer2";
export var MySFC = function(props) {
return predom.apply(void 0, [
"p",
null,
props.x,
" + ",
props.y,
" = ",
props.x + props.y
].concat(_to_consumable_array(_this.props.children)));
};
export var MyClass = function() {
"use strict";
function MyClass(props) {
_class_call_check(this, MyClass), this.props = props;
}
return MyClass.prototype.render = function() {
return predom.apply(void 0, [
"p",
null,
this.props.x,
" + ",
this.props.y,
" = ",
this.props.x + this.props.y
].concat(_to_consumable_array(this.props.children)));
}, MyClass;
}();
export var tree = predom(MySFC, {
x: 1,
y: 2
}, predom(MyClass, {
x: 3,
y: 4
}), predom(MyClass, {
x: 5,
y: 6
}));
export default predom("h", null);
//// [index.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 13 | return <p>{this.props.x} + {this.props.y} = {this.props.x + this.props.y}{...this.props.children}</p>;
//! : ^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
import _class_call_check from "@swc/helpers/src/_class_call_check.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
import { dom } from "./renderer";
import prerendered, { MySFC, MyClass, tree } from "./component";

View File

@ -1,7 +1,20 @@
//// [tsxSpreadChildren.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 22 | {...todos.map(todo => <Todo key={todo.id} todo={todo.todo}/>)}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
import _extends from "@swc/helpers/src/_extends.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
function Todo(prop) {
return /*#__PURE__*/ React.createElement("div", null, prop.key.toString() + prop.todo);
}
function TodoList(param) {
var todos = param.todos;
return /*#__PURE__*/ React.createElement.apply(React, [
"div",
null
].concat(_to_consumable_array(todos.map(function(todo) {
return /*#__PURE__*/ React.createElement(Todo, {
key: todo.id,
todo: todo.todo
});
}))));
}
var x;
/*#__PURE__*/ React.createElement(TodoList, _extends({}, x));

View File

@ -1,7 +1,5 @@
//// [tsxSpreadChildren.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 22 | {...todos.map(todo => <Todo key={todo.id} todo={todo.todo}/>)}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
var x;
import _extends from "@swc/helpers/src/_extends.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
_extends({}, x);

View File

@ -1,13 +1,20 @@
//// [tsxSpreadChildrenInvalidType.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 21 | {...<Todo key={todos[0].id} todo={todos[0].todo} />}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
//!
//! x Spread children are not supported in React.
//! ,----
//! 27 | {...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
import _extends from "@swc/helpers/src/_extends.mjs";
function Todo(prop) {
return /*#__PURE__*/ React.createElement("div", null, prop.key.toString() + prop.todo);
}
function TodoList({ todos }) {
return /*#__PURE__*/ React.createElement("div", null, .../*#__PURE__*/ React.createElement(Todo, {
key: todos[0].id,
todo: todos[0].todo
}));
}
function TodoListNoError({ todos }) {
// any is not checked
return /*#__PURE__*/ React.createElement("div", null, .../*#__PURE__*/ React.createElement(Todo, {
key: todos[0].id,
todo: todos[0].todo
}));
}
let x;
/*#__PURE__*/ React.createElement(TodoList, _extends({}, x));

View File

@ -1,13 +1,4 @@
//// [tsxSpreadChildrenInvalidType.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 21 | {...<Todo key={todos[0].id} todo={todos[0].todo} />}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
//!
//! x Spread children are not supported in React.
//! ,----
//! 27 | {...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
let x;
import _extends from "@swc/helpers/src/_extends.mjs";
_extends({}, x);

View File

@ -1,13 +1,29 @@
//// [tsxSpreadChildrenInvalidType.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 21 | {...<Todo key={todos[0].id} todo={todos[0].todo} />}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
//!
//! x Spread children are not supported in React.
//! ,----
//! 27 | {...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
import _extends from "@swc/helpers/src/_extends.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
function Todo(prop) {
return /*#__PURE__*/ React.createElement("div", null, prop.key.toString() + prop.todo);
}
function TodoList(param) {
var todos = param.todos;
return /*#__PURE__*/ React.createElement.apply(React, [
"div",
null
].concat(_to_consumable_array(/*#__PURE__*/ React.createElement(Todo, {
key: todos[0].id,
todo: todos[0].todo
}))));
}
function TodoListNoError(param) {
var todos = param.todos;
// any is not checked
return /*#__PURE__*/ React.createElement.apply(React, [
"div",
null
].concat(_to_consumable_array(/*#__PURE__*/ React.createElement(Todo, {
key: todos[0].id,
todo: todos[0].todo
}))));
}
var x;
/*#__PURE__*/ React.createElement(TodoList, _extends({}, x));

View File

@ -1,13 +1,5 @@
//// [tsxSpreadChildrenInvalidType.tsx]
//!
//! x Spread children are not supported in React.
//! ,----
//! 21 | {...<Todo key={todos[0].id} todo={todos[0].todo} />}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
//!
//! x Spread children are not supported in React.
//! ,----
//! 27 | {...(<Todo key={todos[0].id} todo={todos[0].todo} /> as any)}
//! : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//! `----
var x;
import _extends from "@swc/helpers/src/_extends.mjs";
import _to_consumable_array from "@swc/helpers/src/_to_consumable_array.mjs";
_extends({}, x);

View File

@ -769,14 +769,10 @@ where
}) => return None,
JSXElementChild::JSXElement(el) => self.jsx_elem_to_expr(*el).as_arg(),
JSXElementChild::JSXFragment(el) => self.jsx_frag_to_expr(el).as_arg(),
JSXElementChild::JSXSpreadChild(JSXSpreadChild { span, .. }) => {
HANDLER.with(|handler| {
handler
.struct_span_err(span, "Spread children are not supported in React.")
.emit();
});
return None;
}
JSXElementChild::JSXSpreadChild(JSXSpreadChild { span, expr, .. }) => ExprOrSpread {
spread: Some(span),
expr,
},
})
}

View File

@ -0,0 +1,3 @@
const A = () => {
return <div>{...[]}</div>;
};

View File

@ -0,0 +1,3 @@
const A = ()=>{
return /*#__PURE__*/ React.createElement("div", null, ...[]);
};

View File

@ -1 +1 @@
/*#__PURE__*/ React.createElement("div", null);
/*#__PURE__*/ React.createElement("div", null, ...children);

View File

@ -1,6 +0,0 @@
x Spread children are not supported in React.
,-[input.js:1:1]
1 | <div>{...children}</div>;
: ^^^^^^^^^^^^^
`----

View File

@ -1 +1 @@
/*#__PURE__*/ React.createElement("div", null);
/*#__PURE__*/ React.createElement("div", null, ...children);

View File

@ -1,6 +0,0 @@
x Spread children are not supported in React.
,-[input.js:1:1]
1 | <div>{...children}</div>;
: ^^^^^^^^^^^^^
`----