-
Notifications
You must be signed in to change notification settings - Fork 38
Conversation
After this #588, assuming all goes well, the change required will be simply to use |
And this converts to |
Would you rebase on master now that the surface syntax has landed. |
1986d7a
to
23c8915
Compare
Is the idea that clients of the ppx, such as rescript-react, will define their types using |
Frankly, I didn't think that far 😄, but it can be used by clients.
Sure, I'll write down on it. |
I thought this new jsx mode was opt-in, so off by default even on users of V4. |
I think the new mode should have no reference to rescript-react at all. But the references should be the other way round: rescript-react (and others) can use the types defined in this PR (and the corresponding one in the compiler that adds types under Js.React). Btw, instead of |
Made some comments on the compiler PR, but realised it might be simpler to discuss directly on the spec once it is written. |
I've updated the spec in 75f8a28.
I agreed that the new jsx mode is better off by default even for the users of V4. I'm not clear about the direction of the core team regarding the rescript-react. I think it is the only choice to add But, if the core team is wiling to update the rescipt-react and keep it as one of dependencies, then I can make PR for rescript-react for the new jsx mode. I think that releasing the V4 is the best chance to update the rescript-react. |
Definitely rescript-react can, and should be updated. Does it make sense? |
I think we need to explore the gradual upgrade path right now. As that affects the design of the various ppx options. |
About being React-specific: here's a TS page: Notice in particular: "JSX is an embeddable XML-like syntax. It is meant to be transformed into valid JavaScript, though the semantics of that transformation are implementation-specific. JSX rose to popularity with the React framework, but has since seen other implementations as well" I think it makes sense to aim for the same level of generality. Notice it says "TypeScript ships with three JSX modes" and not "TypeScript ships with three React modes". Hence my suggestion to use the |
This! A language should outlast a framework. The community puts some effort trying to use ReScript with SolidJS, Remix, etc. And it will succeed one day I think. Hardcoding the “React” name into the language introduces an unnecessary and incorrect illusion that ReScript is only for React front-end apps. |
Totally, it makes sense. I got your point. It is a good idea to explore the gradual upgrade path first, then fix the spec as the paths. Let me write some of the possible paths with the following specs. |
I can’t agree you more about that the JSX doesn’t mean only for React, and I think it makes sense the namespace But, here is my initial thought. If we use the namespace We can add I hope it conveys my thought correctly. |
Perhaps one way to go is to do 2 of these, the easiest pair being React and React Native. So one could, for example, have the core JSX types in This is just a though. By working out the details one can probably get a good idea. I think one next step is to extent the spec with the types: what types do |
cli/JSXV4UPGRADE.md
Outdated
|
||
The `react.runtime` affects nothing, no matter of `"classic"` or `"automatic"`. | ||
|
||
b. JSX V4 with classic mode |
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 doc looks good.
One aspect to consider more is how to adopt "jsx": 4
gradually. This bsconfig.json
change is sufficient when the entire project is using V4. But we need to also think about what to do when half the project uses V3 and half the project uses V4.
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.
At the very least one needs to specify per-file "jsx": 4
vs "jsx": 3
i.e. override the bsconfig locally.
In fact one might need to be able to do that in the middle of a file.
E.g. What if the file has<A > <B /> </A>
and:
1 initially both A
and B
are in V3, and the current file is using V3
2 make the current file use V4
3 make A.res
use V4
4 make B.res
use V4
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 at point 2, the jsx would cal <A>
the V4 way but it expects to be called the V3 way.
I think this is solved by turning on V4 at the top of the file. And locally turning on V3 where <A > <B /> </A>
is.
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 3, A
uses V4 but B
is still on V3.
We need to be able to turn on V3 inside <A > ... </A>
so that we can call B
with V3.
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 4, we don't need anything anymore. Just turn on V4 at the top of the current file.
When every file has been done like that and the project is converted, then non per-file config is needed anymore.
Does this make sense?
Is it going to work?
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.
Just one minor comment. It's not "they". It is "us".
As long as people are kept in the loop and questions asked in the forum when in doubt, we can just go ahead make new version of rescript-react whenever needed.
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.
It's you or Patrick's call, I can make PR for new Jsx
module if you guys want. Or I'll await the Jsx
module's interface are going to be fixed, once it is fixed, PPX V4 just emits to call that. I guess V4 is almost done now.
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.
Definitely a PR for the new Jsx is useful for testing. Making sure that all works.
Then make a release when the time is 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.
Definitely a PR for the new Jsx is useful for testing. Making sure that all works. Then make a release when the time is right.
Alright! I'm gonna make the Jsx module anyway in my local dev to test the V4. So, I'll make my proposal to rescript-react.
Side comment: Even though there was some confusion, it was a very fun journey for me. I learned a lot from you.
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.
Likewise. It's a pleasure.
I think I got your point. I thought |
cli/JSXV4UPGRADE.md
Outdated
} | ||
``` | ||
|
||
JSX V4 with `Js.React` which needs the peer-dependecy of React v17.\* or higher. It may break the project with dependencies which are using the explicit types of `rescript-react`. |
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.
Js.React
What's the idea of making it a submodule of Js
? How is a user supposed to define this binding?
Also, do we again couple the JSX implementation to React? I thought we wanted to explore more liberate systems that will allow different targets.
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.
It is just a test try to add missing bindings of the new JSX mode which is wrongly bound in rescript-react. #547 (comment)
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 guess what I rather wanted to see is a config model that is similar to TS jsx option, also giving me the flexibility to define the binding module name / jsx factory function names of some sort.
I am sure there are lots of technical concerns that may not allow that, but I still wanted to mention it somewhere.
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.
Oh, that is a good reference. Actually, runtime
is referred to the babel configuration. https://babeljs.io/docs/en/babel-plugin-transform-react-jsx/#with-a-configuration-file-recommended
I have update the upgrade docs based on the discussions. Let me know if it makes sense. |
I've added the proposal |
cli/reactjs_jsx_ppx_v4.ml
Outdated
@@ -1064,7 +1064,8 @@ let transformComponentDefinition nestedModules mapper structure returnStructures | |||
@ | |||
if hasForwardRef then | |||
[ | |||
(Location.mknoloc (Lident "ref"), Pat.var (Location.mknoloc "ref")); | |||
( Location.mknoloc (Lident "ref"), | |||
Pat.var ~attrs:optionalAttr (Location.mknoloc "ref") ); |
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.
Before continuing adding mknoloc
that later need to be changed anyway.
The loc should be corresponding to something in the original source. The only question is whether the loc_ghost
field is set to true or false.
(It would be set to true exactly once for each location used in the code produced by the ppx).
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.
Good catch. I'm gonna look through the whole ppx using loc and polish the loc corresponding to original source code.
8863adf
to
a69d3c4
Compare
Updated the V4 upgrade doc as per rescript-lang/rescript@81029b3 |
c427c11
to
8c62db0
Compare
I made rebase to master. Actually, this PR is ready for another round of review. |
Great. Anything specific the review should focus on? |
Nothing special. I've focused several issues since jsx config update.
I think the forwardRef is less important than others, because it is discouraged usage anyway only for backward compatibility. |
The way to test locations is to hook it up to the compiler, update the vendored parser in the extension, then build an example project with the compiler, turn on V4, and test the extension. |
I'm going to test it on my company project, and let you know. I've noticed one thing hovering information in the sample project I test on. The information from V3 looks more informative than V4 in terms of props type detail. In my guess, it needs to be done in lsp server. Is there way to show the label declarations of props type in V4? |
Hmm. I didn't acknowledge this. I'll try it. |
Yes there's the question of how best to represent the type information. Definitely the type definition would look better if it was expanded? Not sure it matters, but does the type definition generated by the ppx have dummy location or actual location info? |
Side note, and just vaguely related (read: please carry on, don't mind me) - it would be nice to "prettify" component hovers in general. TS also shows that in a very crude format, and it has always bothered me in both TS and ReScript. Maybe we could special case JSX component hovers somehow. The exact format is ofc up for debate, but I'd much rather see something like this on a hover of a JSX component:
|
That would happen for free if that was the way one writes the actual type definition. |
To clarify: what if the syntax parser for types were extended. And the outcome printer. |
In fact, anything that hover shows must be copy-pastable. So it follows that any form of clever hovering needs a syntax extension. |
|
I have a question, because I'm not deeply understanding how the extension and compiler works to show the hover. Is it different to show the type information by extension or maybe compiler between the object and record? I think there is difference between V3 and V4. |
Can we merge and start a new PR for fine tunning? or we still can start a new PR which has base branch to this PR. The thread of this PR gets quite long to show at a glance without unfolding. |
I think we can merge next. We want to be reasonably confident that there are no breaking changes. |
@@ -1,5 +1,6 @@ | |||
type props<'msg> = {key?: string, msg: 'msg} // test React JSX file | |||
|
|||
@react.component |
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.
Something to test here is that this works well e.g. with generating interface files with the vscode extension.
rest ) -> | ||
getPropTypes types rest | ||
| Ptyp_arrow (Nolabel, _type, rest) -> | ||
hasForwardRef := true; |
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.
Not sure I understand this.
How does one know that there is a forwardRef just because there's a function with a non-labelled arg which is not unit?
Is this check applying on the user code, or on code generated by the ppx?
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.
Good catch. And it is quite a tricky part, because of the usage of forwardRef.
Basically, we are not allowing the nolabel arg in @react.component
, right? There is one exception to this rule, forwardRef. So, for the interface, it has no way to know what the label is for the type signature. I think we need some assumptions and restrictions at some point. If there is a nolabel type signature after labeled args, the only ref can go there. It will be considered as forwardRef case.
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.
When operating on a forwardRef, do we know that it's a forwardRef to begin with?
If that code was gated by a check "we are inside a forwardRef" then I would have no objection to it.
As it would be clear it's just a simple heuristic, and we don't care because it only applies to forwardRef.
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 I imagine a reference insideForwardRef
which is set. And checked at this point in the code.
OK made a few additional comments/questions. |
Left a comment on rescript-lang/rescript#5484 to rebase. I'll proceed with testing after that. |
EDIT: Sorry, false report. There are issues with compiler.alpha1 + V4. |
EDIT: I was wrong. It was backward compatibility check with compiler.alpha1 + V3. 😓 There are some errors with compiler.alpha1 + V4. I'm going to leave it as an issue. |
Here is the test bed https://github.com/green-labs/sinsunhi-frontend-mirror/tree/test-v4 |
Want to close this and continue on #614 ? |
So backwards compatibility seems OK right? |
Yes, no diff and same output.
Yes. I'm back now, gonna leave an issue. |
Good! I'm gonna close this PR. |
Js.React
Jsx
inrescript-reactthe compilerforwardRef
interface@@jsxConfig( ... )