-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
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
Stop using old JSX transform #12253
Stop using old JSX transform #12253
Conversation
@@ -10,6 +10,29 @@ const DEFAULT = { | |||
}; | |||
|
|||
export function helper(babel, options) { | |||
const { useSpread = true, useBuiltIns = false } = options; | |||
|
|||
if (typeof useSpread !== "boolean") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is an opposite check to what had to be introduced at an upper level (jsx transform) because from the perspective of this builder the useSpread: true
is default but we need to keep the compat for public packages which had useSpread: false
as default
state.get("@babel/plugin-react-jsx/usedFragment") && | ||
!state.get("@babel/plugin-react-jsx/pragmaFragSet") | ||
) { | ||
throw new Error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this makes much sense - it's overly restrictive. The old transform had no such validation and TS also has never thrown for this situation:
https://www.typescriptlang.org/play?ts=4.1.0-beta#code/PQKhAIAECsGcA9x0SYAoNBuAPAEwJYBuAfNsASRjqcMUA
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just comment out this code for now?
I'm not 100% sure that we should remove this check (well, we should now for backward compat, but we might re-introduce it in Babel 8). The question is: should we prioritize for React libraries (e.g. Emotion) or for other "frameworks" (e.g. Preact)?
In the first case it's better not to throw because it should "work by default", while in the second case it's better to "prevent a mistake by default".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The question is: should we prioritize for React libraries (e.g. Emotion) or for other "frameworks" (e.g. Preact)?
Yeah, definitely a concern and I don't have a perfect answer for that. My main motivation factors here are that not throwing in this case is:
- backward-compatible
- matching how TS behaves
Using pragmas is not a very common use case so I would be inclined to favor backward compatibility, usually, people should really have those things configured globally per project in a config file. Pragmas are mostly useful in configuration-constrained tools.
@@ -804,8 +814,9 @@ You can set \`throwIfNamespace: false\` to bypass this warning.`, | |||
* breaking on spreads, we then push a new object containing | |||
* all prior attributes to an array for later processing. | |||
*/ | |||
function buildCreateElementOpeningElementAttributes(path, attribs) { | |||
const props = []; | |||
function buildCreateElementOpeningElementAttributes(file, path, attribs) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
changes here are based on the old transform
} | ||
|
||
const visitor = helper(api, { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is basically just "./transform-automatic"
inlined here
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 4b3c31a:
|
d016154
to
48b4ab7
Compare
Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/33065/ |
I'm not sure if this is strongly related or a new issue should be opened, but the ecosystem might not be ready for such a big change yet. Please see airbnb/babel-plugin-inline-react-svg#91 for further details. |
@kripod We have two transforms: one that only supports the |
state.get("@babel/plugin-react-jsx/usedFragment") && | ||
!state.get("@babel/plugin-react-jsx/pragmaFragSet") | ||
) { | ||
throw new Error( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you just comment out this code for now?
I'm not 100% sure that we should remove this check (well, we should now for backward compat, but we might re-introduce it in Babel 8). The question is: should we prioritize for React libraries (e.g. Emotion) or for other "frameworks" (e.g. Preact)?
In the first case it's better not to throw because it should "work by default", while in the second case it's better to "prevent a mistake by default".
development: false, | ||
runtime, | ||
useSpread: | ||
"useSpread" in options ? options.useSpread : runtime !== "classic", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we throw if useSpread is set with the automatic runtime?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is somewhat tricky because the runtime
option doesn't match the actual runtime that will be used when transforming.
What should happen for:
// config
const options = { runtime: 'classic', useSpread: false }
// ...
/** @jsxRuntime automatic */
<div {...props} key="foo" />
If we want to keep using extends helper etc here (which seems rather logical) then this would also imply that we should implement extends helper support for jsx
, jsxs
and jsxDEV
outputs, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want to keep using extends helper etc here (which seems rather logical)
No, this should also throw.
I think that we can throw if:
runtime: "automatic"
anduseSpread: false
are set in the options (when instantiating the plugin)useSpread: false
is explicitly set in the options and there is a/** @jsxRuntime automatic */
comment (when traversing) <-- In this case it's maybe also ok to just warn and ignoreuseSpread: false
, depending on what would be a breaking change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
runtime: "automatic" and useSpread: false are set in the options (when instantiating the plugin)
Technically this was previously allowed, even if useSpread
has been silently ignored in such a case. I'm OK with adding an error in a situation like this - I just want to ensure myself that you are as well.
useSpread: false is explicitly set in the options and there is a /** @jsxRuntime automatic */ comment (when traversing) <-- In this case it's maybe also ok to just warn and ignore useSpread: false, depending on what would be a breaking change.
Previously the /** @jsxRuntime automatic */
was completely ignored if the runtime was set to "classic"
at the plugin level. Technically one could have it in a file but it would have no effect.
So what you are proposing is that whenever we use the automatic runtime we should ignore options like useSpread
regardless of if the runtime has been chosen at the plugin or a file level? So to make those options only applicable when one uses the classic runtime through options (or by just using the default which is still the classic) and not changing the runtime at the file level (so when it stays to be classic). Did I get the intention right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So what you are proposing is that whenever we use the automatic runtime we should ignore options like useSpread regardless of if the runtime has been chosen at the plugin or a file level? So to make those options only applicable when one uses the classic runtime through options (or by just using the default which is still the classic) and not changing the runtime at the file level (so when it stays to be classic). Did I get the intention right?
Yes, that's exactly what I'd like to see.
@nicolo-ribaudo friendly 🏓 |
3abc2c0
to
8618ad5
Compare
// TODO (Babel 8): Remove `useBuiltIns` & `useSpread` | ||
useBuiltIns: !!opts.useBuiltIns, | ||
useSpread: | ||
"useSpread" in opts ? opts.useSpread : runtime !== "classic", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can simply be opts.useSpread
, unless I'm missing something: it defaults to undefined
, which is falsy with the classic
runtime and ignored with the automatic
one.
b5478e4
to
6483ba2
Compare
6483ba2
to
4b3c31a
Compare
I'm now seeing this in my build logs... I'm not using those transforms directly. I'm just using the react preset.
|
That is probably a regression caused by accidentally mixing some logic for the classic and automatic transforms. Could you open a new issue, with your full config and an example of input code that generates that message? |
This triggers it... ['@babel/preset-react', { development: true }] if i set it false, its fine. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@jsg2021 could you paste in your whole Babel config? I expect that you have either loading |
my config was being included twice... I think this change made it obvious... I had been using |
@Andarist I'm not sure how to dump my config... its spread across a few parts. 😅 I'm not seeing those errors anymore and I'm still getting the __self and __source props added... so I'm pretty confident I fixed my config. My config is reused across multiple projects in a react-scripts style package. So it took inspiration for over-specifying the config... dropping that and letting babel figure it out on its own fixed it. |
You can do something like Anyway, it you found that the problem was exactly that your config was loaded twice it's the error @Andarist is fixing in the PR 👍 |
This is an exciting change! 🥳 Unfortunately, it has at least some observable/undesirable side effects: emotion-js/emotion#2173. |
Just a note - I'm looking already into this but not sure how long this one will take me |
As the new JSX transform has been shipped and is already used in production by many I think we can safely just switch to it - the new transform has been called "automatic" at some places but it actually is capable of handling the classic transform as well and I believe the plan was to just replace the old code with the new one. It just got implemented this way as at first it was, in fact, experimental.
To make this actually happen in Babel 7 I had to introduce
useSpread
anduseBuiltIns
options to the new transform but the plan is to remove them in Babel 8. I've focused right now on making tests pass so those options are only used bycreateElement
- to avoid confusing people I would like to actually use them for new factories as well. I also need to split the code a little bit to make it easier to just remove the compatibility code created for those options later (without having to refactor stuff too much to make it happen).I think we should just move the
-experimental
code to the old "builder" package and just remove the-experimental
directory. Is this approach OK with you?I will also put some additional "inline" comments near some code lines to explain a few things with a better context.