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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
var A = function() {
return /*#__PURE__*/ React.createElement("div", null);
return /*#__PURE__*/ React.createElement.apply(React, [
"div",
null
]);
};
Original file line number Diff line number Diff line change
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);
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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));
Original file line number Diff line number Diff line change
@@ -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);
Original file line number Diff line number Diff line change
@@ -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));
Original file line number Diff line number Diff line change
@@ -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);
Original file line number Diff line number Diff line change
@@ -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));
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const A = () => {
return <div>{...[]}</div>;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const A = ()=>{
return /*#__PURE__*/ React.createElement("div", null, ...[]);
};
Original file line number Diff line number Diff line change
@@ -1 +1 @@
/*#__PURE__*/ React.createElement("div", null);
/*#__PURE__*/ React.createElement("div", null, ...children);

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
/*#__PURE__*/ React.createElement("div", null);
/*#__PURE__*/ React.createElement("div", null, ...children);

This file was deleted.