From ff2baf75b4ea5ce3fc15cdba1a817413d8fedc65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Donny/=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sun, 10 Oct 2021 18:19:47 +0900 Subject: [PATCH] fix(swc): Fix bugs (#2396) swc_ecma_codegen: - Check for comments deeply while emitting a return statement. swc_ecma_transforms_react: - Fix handling of texts in attributes. --- Cargo.lock | 4 +- ecmascript/codegen/Cargo.toml | 2 +- ecmascript/codegen/src/lib.rs | 63 ++++++++++++++++--- ecmascript/transforms/react/Cargo.toml | 2 +- ecmascript/transforms/react/src/jsx/mod.rs | 9 ++- .../react/tests/jsx/fixture/vercel/1/input.js | 6 ++ .../tests/jsx/fixture/vercel/1/output.mjs | 5 ++ .../codegen/comment-1/es5/input/.swcrc | 10 +++ .../codegen/comment-1/es5/input/index.tsx | 16 +++++ .../codegen/comment-1/es5/output/index.tsx | 14 +++++ tests/fixture/codegen/jsx-1/input/.swcrc | 8 +++ tests/fixture/codegen/jsx-1/input/index.js | 6 ++ tests/fixture/codegen/jsx-1/output/index.js | 5 ++ .../fixture/issue-1233/case-1/output/index.js | 2 +- .../fixture/issue-1661/case1/output/index.js | 2 +- 15 files changed, 137 insertions(+), 17 deletions(-) create mode 100644 ecmascript/transforms/react/tests/jsx/fixture/vercel/1/input.js create mode 100644 ecmascript/transforms/react/tests/jsx/fixture/vercel/1/output.mjs create mode 100644 tests/fixture/codegen/comment-1/es5/input/.swcrc create mode 100644 tests/fixture/codegen/comment-1/es5/input/index.tsx create mode 100644 tests/fixture/codegen/comment-1/es5/output/index.tsx create mode 100644 tests/fixture/codegen/jsx-1/input/.swcrc create mode 100644 tests/fixture/codegen/jsx-1/input/index.js create mode 100644 tests/fixture/codegen/jsx-1/output/index.js diff --git a/Cargo.lock b/Cargo.lock index b05244ee0272..f1af33bb9a6f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3370,7 +3370,7 @@ dependencies = [ [[package]] name = "swc_ecma_codegen" -version = "0.74.2" +version = "0.74.3" dependencies = [ "bitflags", "memchr", @@ -3696,7 +3696,7 @@ dependencies = [ [[package]] name = "swc_ecma_transforms_react" -version = "0.48.0" +version = "0.48.1" dependencies = [ "ahash", "base64 0.13.0", diff --git a/ecmascript/codegen/Cargo.toml b/ecmascript/codegen/Cargo.toml index fe775b86682f..e137ecf90191 100644 --- a/ecmascript/codegen/Cargo.toml +++ b/ecmascript/codegen/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = "Apache-2.0/MIT" name = "swc_ecma_codegen" repository = "https://github.com/swc-project/swc.git" -version = "0.74.2" +version = "0.74.3" [dependencies] bitflags = "1" diff --git a/ecmascript/codegen/src/lib.rs b/ecmascript/codegen/src/lib.rs index e332e72f37f1..3a0a18db7bc3 100644 --- a/ecmascript/codegen/src/lib.rs +++ b/ecmascript/codegen/src/lib.rs @@ -2261,6 +2261,57 @@ where emit!(node.body); } + fn has_leading_comment(&self, arg: &Expr) -> bool { + if let Some(cmt) = self.comments { + let lo = arg.span().lo; + + // see #415 + if cmt.has_leading(lo) { + return true; + } + } + + match arg { + Expr::Call(c) => match &c.callee { + ExprOrSuper::Super(callee) => { + if let Some(cmt) = self.comments { + let lo = callee.span.lo; + + if cmt.has_leading(lo) { + return true; + } + } + } + ExprOrSuper::Expr(callee) => { + if self.has_leading_comment(&callee) { + return true; + } + } + }, + + Expr::Member(m) => match &m.obj { + ExprOrSuper::Super(obj) => { + if let Some(cmt) = self.comments { + let lo = obj.span.lo; + + if cmt.has_leading(lo) { + return true; + } + } + } + ExprOrSuper::Expr(obj) => { + if self.has_leading_comment(&obj) { + return true; + } + } + }, + + _ => {} + } + + false + } + #[emitter] fn emit_return_stmt(&mut self, n: &ReturnStmt) -> Result { self.emit_leading_comments_of_span(n.span, false)?; @@ -2276,14 +2327,10 @@ where if let Some(ref arg) = n.arg { let need_paren = !n.arg.span().is_dummy() - && if let Some(cmt) = self.comments { - let lo = n.arg.span().lo(); - - // see #415 - cmt.has_leading(lo) - } else { - false - }; + && n.arg + .as_deref() + .map(|expr| self.has_leading_comment(expr)) + .unwrap_or(false); if need_paren { punct!("("); } else { diff --git a/ecmascript/transforms/react/Cargo.toml b/ecmascript/transforms/react/Cargo.toml index c6e415b434a6..2e285dde3509 100644 --- a/ecmascript/transforms/react/Cargo.toml +++ b/ecmascript/transforms/react/Cargo.toml @@ -7,7 +7,7 @@ include = ["Cargo.toml", "src/**/*.rs"] license = "Apache-2.0/MIT" name = "swc_ecma_transforms_react" repository = "https://github.com/swc-project/swc.git" -version = "0.48.0" +version = "0.48.1" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diff --git a/ecmascript/transforms/react/src/jsx/mod.rs b/ecmascript/transforms/react/src/jsx/mod.rs index cb05c1318952..df5f79d5d258 100644 --- a/ecmascript/transforms/react/src/jsx/mod.rs +++ b/ecmascript/transforms/react/src/jsx/mod.rs @@ -1178,9 +1178,12 @@ fn transform_jsx_attr_str(v: &str) -> String { match c { '\u{0008}' => buf.push_str("\\b"), '\u{000c}' => buf.push_str("\\f"), - '\n' => buf.push_str("\\n"), - '\r' => buf.push_str("\\r"), - '\t' => buf.push_str("\\t"), + ' ' | '\n' | '\r' | '\t' => { + if buf.ends_with(' ') { + } else { + buf.push(' ') + } + } '\u{000b}' => buf.push_str("\\v"), '\0' => buf.push_str("\\x00"), diff --git a/ecmascript/transforms/react/tests/jsx/fixture/vercel/1/input.js b/ecmascript/transforms/react/tests/jsx/fixture/vercel/1/input.js new file mode 100644 index 000000000000..30a56a5a954f --- /dev/null +++ b/ecmascript/transforms/react/tests/jsx/fixture/vercel/1/input.js @@ -0,0 +1,6 @@ +export default \ No newline at end of file diff --git a/ecmascript/transforms/react/tests/jsx/fixture/vercel/1/output.mjs b/ecmascript/transforms/react/tests/jsx/fixture/vercel/1/output.mjs new file mode 100644 index 000000000000..7e6b17883557 --- /dev/null +++ b/ecmascript/transforms/react/tests/jsx/fixture/vercel/1/output.mjs @@ -0,0 +1,5 @@ +export default React.createElement(A, { + className: b, + header: "C", + subheader: "D E" +}); diff --git a/tests/fixture/codegen/comment-1/es5/input/.swcrc b/tests/fixture/codegen/comment-1/es5/input/.swcrc new file mode 100644 index 000000000000..8f96e1fd0e9e --- /dev/null +++ b/tests/fixture/codegen/comment-1/es5/input/.swcrc @@ -0,0 +1,10 @@ +{ + "jsc": { + "target": "es5", + "externalHelpers": true, + "parser": { + "syntax": "typescript", + "tsx": true + } + } +} \ No newline at end of file diff --git a/tests/fixture/codegen/comment-1/es5/input/index.tsx b/tests/fixture/codegen/comment-1/es5/input/index.tsx new file mode 100644 index 000000000000..b062b8774304 --- /dev/null +++ b/tests/fixture/codegen/comment-1/es5/input/index.tsx @@ -0,0 +1,16 @@ +function a({ b = [] }: { b: C[] }) { + const t = useMemo(() => { + return [ + // Cmt1 + ...a.slice(0, 1), + // Cmt2 + ...b, + // Cmt3 + ...c.slice(1), + ]; + }, [frameworks]); + + return 1; +} + +export default a; diff --git a/tests/fixture/codegen/comment-1/es5/output/index.tsx b/tests/fixture/codegen/comment-1/es5/output/index.tsx new file mode 100644 index 000000000000..3274b49e59e0 --- /dev/null +++ b/tests/fixture/codegen/comment-1/es5/output/index.tsx @@ -0,0 +1,14 @@ +import * as swcHelpers from "@swc/helpers"; +function a(param) { + var _b = param.b, b = _b === void 0 ? [] : _b; + var t = useMemo(function() { + return(// Cmt1 + swcHelpers.toConsumableArray(a.slice(0, 1)).concat(// Cmt2 + swcHelpers.toConsumableArray(b), // Cmt3 + swcHelpers.toConsumableArray(c.slice(1)))); + }, [ + frameworks + ]); + return 1; +} +export default a; diff --git a/tests/fixture/codegen/jsx-1/input/.swcrc b/tests/fixture/codegen/jsx-1/input/.swcrc new file mode 100644 index 000000000000..77fb46ac78f2 --- /dev/null +++ b/tests/fixture/codegen/jsx-1/input/.swcrc @@ -0,0 +1,8 @@ +{ + "jsc": { + "parser": { + "syntax": "ecmascript", + "jsx": true + } + } +} \ No newline at end of file diff --git a/tests/fixture/codegen/jsx-1/input/index.js b/tests/fixture/codegen/jsx-1/input/index.js new file mode 100644 index 000000000000..30a56a5a954f --- /dev/null +++ b/tests/fixture/codegen/jsx-1/input/index.js @@ -0,0 +1,6 @@ +export default \ No newline at end of file diff --git a/tests/fixture/codegen/jsx-1/output/index.js b/tests/fixture/codegen/jsx-1/output/index.js new file mode 100644 index 000000000000..6d260ba40c48 --- /dev/null +++ b/tests/fixture/codegen/jsx-1/output/index.js @@ -0,0 +1,5 @@ +export default /*#__PURE__*/ React.createElement(A, { + className: b, + header: "C", + subheader: "D E" +}); diff --git a/tests/fixture/issue-1233/case-1/output/index.js b/tests/fixture/issue-1233/case-1/output/index.js index 18c08969c864..0a97cf1bf7f5 100644 --- a/tests/fixture/issue-1233/case-1/output/index.js +++ b/tests/fixture/issue-1233/case-1/output/index.js @@ -1,5 +1,5 @@ function Component() { return(/*#__PURE__*/ React.createElement("div", { - name: "A\\n\\n B" + name: "A B" })); } diff --git a/tests/fixture/issue-1661/case1/output/index.js b/tests/fixture/issue-1661/case1/output/index.js index 7205b0b7a865..30b335c85b4d 100644 --- a/tests/fixture/issue-1661/case1/output/index.js +++ b/tests/fixture/issue-1661/case1/output/index.js @@ -1,3 +1,3 @@ console.log(/*#__PURE__*/ React.createElement("h1", { - value: "abc\\nas" + value: "abc as" }, "s"));