Skip to content

Explore to rewrite Jsx in res, add helper functions in the compiler #5757

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

Merged
merged 9 commits into from
Oct 28, 2022

Conversation

mununki
Copy link
Member

@mununki mununki commented Oct 27, 2022

This PR is to explore how it works about rewriting Jsx module in res and adding helper functions in res module.
I'll relocate helper functions to the separate res module.

@mununki
Copy link
Member Author

mununki commented Oct 27, 2022

Related discussion rescript-lang/rescript-react#76

@mununki mununki changed the title Explore to ewrite Jsx in res, add helper functions in the compiler Explore to rewrite Jsx in res, add helper functions in the compiler Oct 27, 2022
@cristianoc cristianoc requested a review from cknitt October 27, 2022 11:17
@cknitt
Copy link
Member

cknitt commented Oct 27, 2022

Sorry, I don't think the functions belong into the Jsx module, as that module is meant to be framework-independent, but the helper functions are specific to the React PPX.

I think they should go into a new module named ReactPPX4Support or something like that.

@mununki
Copy link
Member Author

mununki commented Oct 27, 2022

Sorry, I don't think the functions belong into the Jsx module, as that module is meant to be framework-independent, but the helper functions are specific to the React PPX.

I think they should go into a new module named ReactPPX4Support or something like that.

Totally agree with you. Let me relocate helper functions to ReactPPX4Support module.

@mununki
Copy link
Member Author

mununki commented Oct 27, 2022

I've tested the newly built compiler on the example project. It works fine.
I'll let you know the test result of the large project.

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

I've tested in a fairly large project which is my company. It works fine.

Pros:

  • rescript-react zero-cost binding
// as-is
import * as React from "@rescript/react/src/React.bs.js";
import * as React$1 from "react";

// to-be: `@rescript/react/...` is not imported anymore
import * as React from "react";
import * as ReactPPX4Support from "rescript/lib/es6/reactPPX4Support.js";

Cons:

  • Little unreadable js output in passing React.createElement fun
// as-is
React.createElementWithKey("k1", RemovedKeyProp$Foo, {
                  x: "x",
                  y: "y"
                })

// to-be
ReactPPX4Support.createElementWithKey("k1", (function (prim0, prim1) { // <- here
                    return React.createElement(prim0, prim1);
                  }), RemovedKeyProp$Foo, {
                  x: "x",
                  y: "y"
                })

As we had discussed before, it comes to my head to add rescript-react into the compiler. The unreadable output in passing fun would be changed if we change ReactPPX4Support:

// as-is
let createElementWithKey = (~key=?, createElement, component, props) =>
  createElement(component, addKeyProp(~key?, props))

// to-be
let createElementWithKey = (~key=?, component, props) =>
  React.createElement(component, addKeyProp(~key?, props))

I think there are tradeoffs about adding rescript-react into the compiler, but not sure what the tradeoffs are clearly now.

@cristianoc
Copy link
Collaborator

cristianoc commented Oct 28, 2022

Why is it passing React.createElement? That makes things worse (strong coupling via passing a function as argument) than before in my view. Is there a way to avoid it?

Basically wondering why createElement is not also defined here? It's just an external.

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

Basically wondering why createElement is not also defined here? It's just an external.

rescript-lang/rescript-react#76 (comment)

So my suggestion would be to move addKeyProp, createElementWithKey and createElementVariadicWithKey out of @rescript/react and into a new "PPX support module" in the compiler repo. Which means that we'd also need to duplicate the corresponding React.createElement bindings there. But that should be fine.

I missed the last part. I'll add it createElement binding into ReactPPX4Support

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

6345bdf
I've added the React binding for helper functions, and see that no passing function. And I've also see that it works fine in my large project.

@cknitt
Copy link
Member

cknitt commented Oct 28, 2022

Looks great! Now the PPX and its helper functions are completely decoupled from the React bindings in @rescript/react. 👍🎉

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Looks great!

@@ -159,4 +159,5 @@ o others/node_module.cmi others/node_module.cmj : cc others/node_module.ml | oth
o others/node_path.cmi others/node_path.cmj : cc others/node_path.ml | others/belt_internals.cmi others/js.cmi $bsc
o others/node_process.cmj : cc_cmi others/node_process.ml | others/belt_internals.cmi others/js.cmi others/js_dict.cmj others/node.cmi others/node_process.cmi $bsc js_pkg
o others/node_process.cmi : cc others/node_process.mli | others/belt_internals.cmi others/js.cmi others/js_dict.cmi others/node.cmi $bsc js_pkg
o others : phony others/belt_Array.cmi others/belt_Array.cmj others/belt_Float.cmi others/belt_Float.cmj others/belt_HashMap.cmi others/belt_HashMap.cmj others/belt_HashMapInt.cmi others/belt_HashMapInt.cmj others/belt_HashMapString.cmi others/belt_HashMapString.cmj others/belt_HashSet.cmi others/belt_HashSet.cmj others/belt_HashSetInt.cmi others/belt_HashSetInt.cmj others/belt_HashSetString.cmi others/belt_HashSetString.cmj others/belt_Id.cmi others/belt_Id.cmj others/belt_Int.cmi others/belt_Int.cmj others/belt_List.cmi others/belt_List.cmj others/belt_Map.cmi others/belt_Map.cmj others/belt_MapDict.cmi others/belt_MapDict.cmj others/belt_MapInt.cmi others/belt_MapInt.cmj others/belt_MapString.cmi others/belt_MapString.cmj others/belt_MutableMap.cmi others/belt_MutableMap.cmj others/belt_MutableMapInt.cmi others/belt_MutableMapInt.cmj others/belt_MutableMapString.cmi others/belt_MutableMapString.cmj others/belt_MutableQueue.cmi others/belt_MutableQueue.cmj others/belt_MutableSet.cmi others/belt_MutableSet.cmj others/belt_MutableSetInt.cmi others/belt_MutableSetInt.cmj others/belt_MutableSetString.cmi others/belt_MutableSetString.cmj others/belt_MutableStack.cmi others/belt_MutableStack.cmj others/belt_Option.cmi others/belt_Option.cmj others/belt_Range.cmi others/belt_Range.cmj others/belt_Result.cmi others/belt_Result.cmj others/belt_Set.cmi others/belt_Set.cmj others/belt_SetDict.cmi others/belt_SetDict.cmj others/belt_SetInt.cmi others/belt_SetInt.cmj others/belt_SetString.cmi others/belt_SetString.cmj others/belt_SortArray.cmi others/belt_SortArray.cmj others/belt_SortArrayInt.cmi others/belt_SortArrayInt.cmj others/belt_SortArrayString.cmi others/belt_SortArrayString.cmj others/belt_internalAVLset.cmi others/belt_internalAVLset.cmj others/belt_internalAVLtree.cmi others/belt_internalAVLtree.cmj others/belt_internalBuckets.cmi others/belt_internalBuckets.cmj others/belt_internalBucketsType.cmi others/belt_internalBucketsType.cmj others/belt_internalMapInt.cmi others/belt_internalMapInt.cmj others/belt_internalMapString.cmi others/belt_internalMapString.cmj others/belt_internalSetBuckets.cmi others/belt_internalSetBuckets.cmj others/belt_internalSetInt.cmi others/belt_internalSetInt.cmj others/belt_internalSetString.cmi others/belt_internalSetString.cmj others/dom.cmi others/dom.cmj others/dom_storage.cmi others/dom_storage.cmj others/dom_storage2.cmi others/dom_storage2.cmj others/node_buffer.cmi others/node_buffer.cmj others/node_child_process.cmi others/node_child_process.cmj others/node_fs.cmi others/node_fs.cmj others/node_module.cmi others/node_module.cmj others/node_path.cmi others/node_path.cmj others/node_process.cmi others/node_process.cmj
o others/reactPPX4Support.cmi others/reactPPX4Support.cmj : cc others/reactPPX4Support.res | others/belt_internals.cmi others/js.cmi $bsc
Copy link
Member Author

Choose a reason for hiding this comment

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

I guess it shows ReactPPX4Support doesn't have dependency to Jsx. I think this causes the CI error.
Not sure how to fix it.

Copy link
Member Author

Choose a reason for hiding this comment

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

I'm gonna try fix this part in ninja.js

  var jsPrefixSourceFiles = othersDirFiles.filter(
    x =>
      x.startsWith("js") && // maybe? (x.startsWith("js") || x.startsWith("reactPPX4Support"))
      (x.endsWith(".ml") ||
        x.endsWith(".mli") ||
        x.endsWith(".res") ||
        x.endsWith(".resi")) &&
      !x.includes(".cppo") &&
      !x.includes(".pp") &&
      !x.includes("#") &&
      x !== "js.ml"
  );

Copy link
Member Author

Choose a reason for hiding this comment

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

Still wondering why the ci on mac-arm fails only.

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Indeed the CI failure needs addressing.
It could be: that there can't be dependencies between things called js... and others.
Doing more sequential less parallel build would probably always fail.
Or something like that.

@cristianoc
Copy link
Collaborator

cristianoc commented Oct 28, 2022

Sorry let me clarify: sequential vs parallel is just an explanation. It's not a suggestion to change the build.

The js... vs other names is a hypothesis. A possible reason why things don't work.

@cristianoc
Copy link
Collaborator

Indeed it looks like the 2 groups of others/ files, those starting with js, and those not starting with js, are built in parallel.

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

Indeed. I tried to fix with 5368e95 It seems not.

How about rewriting the ReactPPX4Support in ml? Would it be a temporary fix?

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

I guess that jsx.ml, jsxDOM.ml, etc. those were okay because their name starts with js.

@cristianoc
Copy link
Collaborator

That's not related to ml vs res

It's js... vs other names

@cristianoc
Copy link
Collaborator

I guess that jsx.ml, jsxDOM.ml, etc. those were okay because their name starts with js.

Yes that's the reason

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

How about this? Renaming reactPPX4Support to jsxPPX4Support to avoid the build issue. We can revisit to fix it after release 10.1 I think zero cost binding is more benefit we can get.

Copy link
Collaborator

@cristianoc cristianoc left a comment

Choose a reason for hiding this comment

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

Looks good to me!

@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

I've ran a test on the company project, it works nice!

@mununki mununki force-pushed the add-react-helper-functions branch from 369514e to c90aea9 Compare October 28, 2022 16:31
@mununki
Copy link
Member Author

mununki commented Oct 28, 2022

Rebased to 10.1_release

@mununki mununki merged commit 0774d35 into 10.1_release Oct 28, 2022
@mununki mununki deleted the add-react-helper-functions branch October 28, 2022 17:21
@mununki
Copy link
Member Author

mununki commented Aug 29, 2023

Good question. There was a discussion about adding this helper function rescript-lang/syntax#693 (comment)
The TL;DR is that we don't want to expose the key to the user returned element, but at runtime we need to use it with the react api.
You can check the actual implementation of it. https://github.com/rescript-lang/rescript-compiler/blob/8de6c09fd1b0a4c6dcc667c3a4b6cbcebffe30c4/jscomp/others/jsxPPXReactSupportU.res#L4

@cknitt
Copy link
Member

cknitt commented Aug 29, 2023

This is not an issue when using the new JSX runtime ("mode": "automatic") though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants