Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 7 commits into from Nov 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -1,3 +1,6 @@
var A = function() {
return /*#__PURE__*/ React.createElement("div", null);
return /*#__PURE__*/ React.createElement.apply(React, [
"div",
null
]);
};
Expand Up @@ -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);
Expand Up @@ -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";
25 changes: 19 additions & 6 deletions crates/swc/tests/tsc-references/tsxSpreadChildren.1.normal.js
@@ -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));
@@ -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);
@@ -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));
@@ -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);
@@ -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));
@@ -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);
12 changes: 4 additions & 8 deletions crates/swc_ecma_transforms_react/src/jsx/mod.rs
Expand Up @@ -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,
},
})
}

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

This file was deleted.

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

This file was deleted.