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: incorrect transform jsx-runtime in development #2741

Merged

Conversation

Shinyaigeek
Copy link
Contributor

Motivation 🔥

Fix: #2656

Currently, swc does not transform JSX correctly with new JSX Transform in development mode. It is importing jsx from jsx-runtime when it should be importing jsxDEV from jsx-dev-runtime. (The same applies to jsxs).

I fixed this.

@kdy1 kdy1 added this to the v1.2.109 milestone Nov 13, 2021
Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not enough.
You have to handle special attributes like __source, too.

@Shinyaigeek Shinyaigeek force-pushed the fix/incorrect-import-jsx-development-runtime branch from 19065d3 to e0fe330 Compare November 14, 2021 07:30
@Shinyaigeek
Copy link
Contributor Author

Shinyaigeek commented Nov 14, 2021

Oh! Sorry, I overlooked it 🙇

I updated code with passing isStaticValidation, source, self (this) to jsxDEV, and not set __source and __self as props with "runtime": "automatic" config.

Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's are small issues with jsx directives.

@@ -596,13 +600,62 @@ where

self.top_level_node = top_level_node;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this code will error if /* @jsxRuntime automatic */ is used.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of this, the babel plugin detect attributes named __source and __self and change those into arguments.

Copy link
Contributor Author

@Shinyaigeek Shinyaigeek Nov 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’m sorry for that I did not know about jsx directives.

Because of this, the babel plugin detect attributes named __source and __self and change those into arguments.

Is this the process below?

https://github.com/babel/babel/blob/main/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts#L502

I am worried if my understanding is correct, but should I fix the code to set __source and __self props as JSX attribute in development mode as usual?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for late response, I missed the email.

Is this the process below?

Yes.

Should I fix the code to set __source and __self props as JSX attribute in development mode as usual?

I think so, as it's what babel does

Copy link
Contributor Author

@Shinyaigeek Shinyaigeek Nov 20, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your reply and help!

I fixed code like below

  • set __source and __self to props with jsx_src and jsx_self (as usual)
  • As babel plugin does, with runtime: automatic and development: true configuration, swc extract __source and __self from JSX’s attributes and set it as _jsxDEV’s arguments.

it looks like there are not test settings to test react module(= jsx with jsx_src and jsx_self) with a specific configuration, so I added integration testing directory to test react module with a specific configuration.

If there is yet something I missed, I will be happy if you pointed it out.

@kdy1 kdy1 modified the milestones: v1.2.109, v1.2.110, v1.2.111, v1.2.112 Nov 17, 2021
@Shinyaigeek Shinyaigeek force-pushed the fix/incorrect-import-jsx-development-runtime branch 2 times, most recently from fddc954 to 6351e01 Compare November 20, 2021 17:08
@@ -489,6 +495,44 @@ where
continue;
}

if !use_create_element
&& i.sym == String::from("__source")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String::from("__source") is very inefficient.
You can compare JsWord to str like *i.sym === "__source ".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 1ed2c7b

@@ -468,6 +472,8 @@ where
};

let mut key = None;
let mut __source = None;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think variable name should not use _ as a prefix as it has special meaning in rust.

Copy link
Contributor Author

@Shinyaigeek Shinyaigeek Nov 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 7fcafd2

I replaced __source with source_props, and __self with self_props.

Some(key) => key,
None => ExprOrSpread {
spread: None,
expr: Box::new(build_undefined_literal_value()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use undefined(DUMMY_SP) instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not notice undefined util module 🙇

👍 0ac5ded

})
.as_arg(),
))
.chain(Some(__source))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's std::iter::once and it's better than using Some to create an iterator.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 75a12b8

Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@kdy1
Copy link
Member

kdy1 commented Nov 21, 2021

Code changes look fine to me, but can you add some more tests?
Actually this feature was once implemented by #2542, but I reverted it because it broke next.js

@Shinyaigeek
Copy link
Contributor Author

Thank you!

I've added some tests on this, but I am wondering what more tests to add.

Can you share what happened or error logs when Next.js was broken? (I searched for the Next.js issue but couldn't find it)

@kdy1
Copy link
Member

kdy1 commented Nov 23, 2021

@Shinyaigeek vercel/next.js#30302 (comment)
This was the issue, and thank you!

@kdy1 kdy1 removed this from the v1.2.112 milestone Nov 24, 2021
@kdy1 kdy1 added this to the v1.2.116 milestone Dec 1, 2021
Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!
I found some tiny issues.

crates/swc_ecma_transforms_react/src/jsx/mod.rs Outdated Show resolved Hide resolved
crates/swc_ecma_transforms_react/src/jsx/mod.rs Outdated Show resolved Hide resolved
]
},
void 0,
true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I got different output from babel.

var _jsxFileName = "/Users/kdy1/projects/lab/src/input.js";
import { jsxDEV as _jsxDEV } from "react/jsx-dev-runtime";
import { Fragment as _Fragment } from "react/jsx-dev-runtime";

var x = /*#__PURE__*/_jsxDEV(_Fragment, {
  children: [/*#__PURE__*/_jsxDEV("div", {
    children: "hoge"
  }, void 0, false, {
    fileName: _jsxFileName,
    lineNumber: 3,
    columnNumber: 9
  }, this), /*#__PURE__*/_jsxDEV("div", {
    children: "fuga"
  }, void 0, false, {
    fileName: _jsxFileName,
    lineNumber: 4,
    columnNumber: 9
  }, this)]
}, void 0, true);

Seems like children of fragments are not visited?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this works. jsxdev-args-with-gragment test is placed in fixture, not in integration. This means jsx-src and jsx-self does not work while this test run. This output will be the same with babel’s output if we move this test into integration. I think this is a little confusing, so I moved this test case from fixture into integration in fdaaaa2

@kdy1 kdy1 modified the milestones: v1.2.116, v1.2.117, v1.2.118, v1.2.119 Dec 1, 2021
@Shinyaigeek
Copy link
Contributor Author

I’m sorry I did not understand why #2542 broke next.js (vercel/next.js#30302 (comment)). I think there are enough test cases for this change, but I am also worried that this change will break next.js as vercel/next.js#30302 (comment) . Is there any documentation for running Next.js tests with the local version of swc? (I rewrote Cargo.toml of next-swc with {path = "..."}, I get a compile error ...)

@kdy1
Copy link
Member

kdy1 commented Dec 6, 2021

@Shinyaigeek Same here. I don't understand the reason.

I think in this case it will be fine, as you added tests for all input. But if you want to try it, you can patch all swc dependencies in https://github.com/vercel/next.js/tree/c004322d138e1949437efb0b80e0973f3a3775cf/packages/next-swc/crates to use git or path dependency targeting your own branch and create a PR.

@kdy1
Copy link
Member

kdy1 commented Dec 6, 2021

But I really think it will be fine in this case, as we tested all input.

@Shinyaigeek
Copy link
Contributor Author

@kdy1 I see. It seems to be a tough task to test with next-swc, so is it okay to get a review as it is, and send a follow up issue & PR if there is any problem?

@kdy1
Copy link
Member

kdy1 commented Dec 8, 2021

Yeah, I think it is better. Thanks for the pr again and I'll review it soon

Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I found one perf/code style issue.


let args = if self.development {
args.into_iter()
.chain(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think .chain(once(undefined(DUMMY_SP).as_arg())).chain(once(Lit::Bool(Bool { span: DUMMY_SP, value: use_jsxs, }) .as_arg())) would be better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK 👍 Thank you for helping! I fixed in 5be5cf0

Copy link
Member

@kdy1 kdy1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks!

@kdy1 kdy1 enabled auto-merge (squash) December 10, 2021 08:46
@kdy1 kdy1 merged commit ed704c9 into swc-project:main Dec 10, 2021
kodiakhq bot pushed a commit to vercel/next.js that referenced this pull request Dec 13, 2021
## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`


This PR applies

 - swc-project/swc#2741

This fixes `development` mode of jsx.
nicholasxjy pushed a commit to nicholasxjy/swc that referenced this pull request Dec 18, 2021
cdierkens pushed a commit to cdierkens/next.js that referenced this pull request Dec 20, 2021
## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`


This PR applies

 - swc-project/swc#2741

This fixes `development` mode of jsx.
natew pushed a commit to natew/next.js that referenced this pull request Feb 16, 2022
## Bug

- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Errors have helpful link attached, see `contributing.md`

## Feature

- [ ] Implements an existing feature request or RFC. Make sure the feature request has been accepted for implementation before opening a PR.
- [ ] Related issues linked using `fixes #number`
- [ ] Integration tests added
- [ ] Documentation added
- [ ] Telemetry added. In case of a feature if it's used or not.
- [ ] Errors have helpful link attached, see `contributing.md`

## Documentation / Examples

- [ ] Make sure the linting passes by running `yarn lint`


This PR applies

 - swc-project/swc#2741

This fixes `development` mode of jsx.
@swc-project swc-project locked as resolved and limited conversation to collaborators Nov 2, 2022
This pull request was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Development

Successfully merging this pull request may close these issues.

JSX automatic transform development incorrect
2 participants