-
-
Notifications
You must be signed in to change notification settings - Fork 636
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
Add JSX support built on the JS backend #21206
Conversation
The motivation for providing a separate target is that plugin authors can distinguish between the sources. |
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.
Thanks so much for continuing to plug away at this work! This is awesome
This PR together with #21176 essentially gives pants "react" support.
🎉
Files that can cross import (post bundling) different transpile formats should use JSRuntimeDependencies and JSRuntimeSourceField. Think typescript, JSX.
More questions to exploring the problem space:
- AIUI, bundlers allow importing other resources too, e.g.
import './example.css'
or even images (https://vitejs.dev/guide/assets), do we have thoughts on how those might be modelled? Maybe as an inferredJSRuntimeDependencies
on afile
orresource
target? Or maybe something else? - How does
pants test path/to/some.test.jsx
work? I see the test project has a test JSX-using test file in it, but it's not obvious to me how this actually executes? I'd be expecting more plumbing to make that work, so I'm surprised it's not here!
required_fields = (JSSourceField,) | ||
required_fields = (JSRuntimeSourceField,) |
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.
On the target discussion, for prettier specifically, it supports things that are very non-JS-shaped, e.g. HTML, GraphQL, Markdown, JSON, Yaml.
Two questions:
- Specifically for prettier: do we currently have any thoughts on how to make Pants able to use Prettier to (optionally!) format non-JS files too?
- Generalising/another clarifying example: are there other tools in the JS ecosystem that might behave similarly and work with more file types? Do we need to think about how to handle them?
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.
- No. I have no use case myself but I suppose a contributor could open up the prettier plugin to more languages later by adding a union-layer? Alternatively prettier seems like the kind of tool one might want to run "target-less" and just glob?
- The typescript compiler can check other files than .ts. It can be run on .js, .jsx and .tsx as well Test runners have the same capability, so the test goal also applies. Those are the usecases I'm primarily intrested in, and I think the "JS-ish source" model works well there.
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 also think it is fun that you implied json is non-js shaped 😏 I get what you're saying though, you do not run a json file.
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.
Alternatively prettier seems like the kind of tool one might want to run "target-less" and just glob?
Hm, maybe, yeah.
The typescript compiler can check other files than .ts. It can be run on .js, .jsx and .tsx as well Test runners have the same capability, so the test goal also applies. Those are the usecases I'm primarily intrested in, and I think the "JS-ish source" model works well there.
👍
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 think I wrote the Prettier plugin a while back, and we did have the discussion about how it could be used target-less, but that (d)evolved into a much larger discussion about the needs for targets and target-less and so on and so forth.
There are a few tools where I think we just want to defer to whatever the tool can handle - and I don't know how we do that in the most pants-esque way
pass | ||
|
||
|
||
class JSSourceField(SingleSourceField): | ||
class JSRuntimeSourceField(SingleSourceField): | ||
"""A source that is javascript at 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.
Feeding into the PR description. Thinking about this framing: AIUI, there's some tools that can run TypeScript natively (e.g. Bun; Node (experimentally) as of nodejs/node#53725), so a .ts
file can be run without being/becoming JS.
Does that play into the broader consideration, or maybe it's not a big-picture issue (e.g. maybe just this doc string is (very slightly) inaccurate)?
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 suppose it is a point of semantics, but bun and node do not run typescript. They strip (node) or compile-down the (bun) types and run the resulting javascript.
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.
Yeah, I think my key point is that there's tools for which the file run is the .ts
one, without a bundling/packaging/compilation step to turn it into real JS first, so it's becomes harder to say that it "is Javascript" at runtime.
Brainstorming: I wonder if we could instead flip this around to be tool-focused using a union somehow (I'm not fully familiar with whether that's possible, though). E.g. register various source types as members of "can be passed to tsc ...
", "can be passed to node ...
", "prettier ...
", "biome ...
", etc.
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.
For specific tools were we can have a field set and union to target the tool, yes.
Not sure how that works out for node_test_script
. The TestFieldSet
is already a union that requires a SourcesField
unique to each union member.
In other words, I think at some point we are required to "boil down" to a unique source field type to "end up" with a JSTestRequest
. If it was generic on e.g SourceField
I think the union is not specialized enough? But idk 🤷♂️
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.
In other words, I think at some point we are required to "boil down" to a unique source field type to "end up" with a JSTestRequest. If it was generic on e.g SourceField I think the union is not specialized enough? But idk 🤷♂️
IDK either 🤷♂️
|
Excited for this 🎉
Just a heads up that it looks like Node will soon run typescript - nodejs/node#53725 |
class JSXTestDependenciesField(JSXDependenciesField): | ||
pass | ||
|
||
|
||
class JSXTestSourceField(JSXSourceField, JSTestRuntimeSourceField): | ||
expected_file_extensions = JSX_FILE_EXTENSIONS | ||
|
||
|
||
class JSXTestTimeoutField(TestTimeoutField): | ||
pass | ||
|
||
|
||
class JSXTestExtraEnvVarsField(TestExtraEnvVarsField): | ||
pass |
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'm honestly not sure why I declare subclasses for each field, but it seems prevalent in all backends. A lot of boilerplate, though.
Co-authored-by: riisi <[email protected]>
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.
Looks good.
Approving to keep us moving forward, because it seems like the best way to explore the best option for how to model these targets is to starting doing something and work out if we like it or not!
pass | ||
|
||
|
||
class JSSourceField(SingleSourceField): | ||
class JSRuntimeSourceField(SingleSourceField): | ||
"""A source that is javascript at 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.
In other words, I think at some point we are required to "boil down" to a unique source field type to "end up" with a JSTestRequest. If it was generic on e.g SourceField I think the union is not specialized enough? But idk 🤷♂️
IDK either 🤷♂️
This is a small change for the JS backend, as the tree-sitter parser already supports JSX.
This is a fairly big decision w.r.t how the js backend will evolve with typescript and other javascript transpile formats. Since many tools that support js also supports other kinds of files, the
JSRuntime...
will be used to refer to the files that can be treated as a source code file for some node-ish runtime who either processes the AST or executes actual programmes.Clarifiying examples:
This PR together with #21176 essentially gives pants "react" support.