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

Playground New ReScript JS API 2020 #4518

Closed
wants to merge 322 commits into from

Conversation

ryyppy
Copy link
Member

@ryyppy ryyppy commented Jul 9, 2020

This PR keeps track of the changes for building our current playground bundle. It introduces following changes in the bundle API:

  • In case of an error, the result will contain an errors attribute with multiple error objects (instead of just a flat error object)
  • Removed the fix where location rows were corrected to row - 1, since 0 based row doesn't make sense for this api
  • For successful compilation, added a type: "success" attribute, to make the return value of each compile function an discriminated union to switch on more easily

For the rest of the changes, follow the comments that were made over the last few months.

@ryyppy ryyppy changed the title Playground napkin support Playground Res support Jul 14, 2020
@ryyppy ryyppy changed the title Playground Res support Playground Res support / New BS JS API 2020 Jul 21, 2020
@ryyppy
Copy link
Member Author

ryyppy commented Jul 21, 2020

I took the chance and also expand the scope of this PR to tackle the new API as discussed in #4450.

The first commit to make the new API possible revolves around following changes:

  • Introduce a bs_platform namespace for all the functionality
  • Reduce the global state of the compiler to allow different settings per instance
  • Add configuration support to be able to manipulate the compiler setup
  • Make super_errors reporting the default

Introduce a bs_platform namespace

Before we were independently adding language support via window.reason, window.ocaml and
window.napkin, etc. This behavior pollutes the global namespace, is harder to discover and
could potentially cause override conflicts.

With one unified bs_platform object, we can now group together all necessary functionality.

Reduce global state / allow different settings

We wanted to introduce different settings for different instances of the
bs_platform bundle API. The way the bundle was designed, the settings state
was fully dependend on the global compiler state, meaning that in case we
are using the bundle for things like multiple independent codesnippets within
a documentation page, everytime we are setting the compilation setting for one
snippet, it would automatically change it for all the snippets as well.

Therefore we needed to introduce a factory function that looks like this:

// load bs bundle globally via <script/> etc...
let bsc = bs_platform.make();

bsc.reason.setModuleType("es6");
bsc.reason.compile("let a = 1");

Internally, the API is still relying on one global compiler state, but we are now
able to locally differentiate between different setting profiles by injecting a
config record to each compile call.

Make super_errors reporting the default

Previously we offered functions like ocaml.compile and ocaml.compile_super_errors to
switch between different reporting engines. Problem was, that once you called compile_super_errors,
it would register the super_error reporters, and any further call with use_super_errors=false would
not take any effect, since the super_error reporters would not be removed (in fact, there are no apis to
clean up the changes of super_main.ml's setup function).

The goal is to make super_errors really solid, and it's probably the best default experience
for our users anyways. So to circumvent this global state issue by managing error reporters, we
just drop support for non super_errors behavior.

@ryyppy ryyppy changed the title Playground Res support / New BS JS API 2020 Playground ReScript syntax support / New ReScript JS API 2020 Aug 12, 2020
@ryyppy ryyppy changed the title Playground ReScript syntax support / New ReScript JS API 2020 Playground New ReScript JS API 2020 Aug 12, 2020
@ryyppy ryyppy requested a review from bobzhang August 12, 2020 13:01
@ryyppy ryyppy marked this pull request as ready for review August 12, 2020 13:01
@ryyppy
Copy link
Member Author

ryyppy commented Aug 12, 2020

@bobzhang Would be great to get some review on this. The main work happened all in jscomp/refmt/jsoo_refmt_main.ml

@bobzhang
Copy link
Member

Note you own the playground module, so I won't block this merge.
Here are some of my thoughts to make it more maintainable in the future:

It seems the new version of playground relies on a much larger surface API from both jsoo and our compiler internal,
can we first reduce such surface API as much as we can, for example, remove such functionality to make it more maintainable?

Reduce global state / allow different settings
We wanted to introduce different settings for different instances of the
bs_platform bundle API. The way the bundle was designed, the settings state
was fully dependend on the global compiler state, meaning that in case we
are using the bundle for things like multiple independent codesnippets within
a documentation page, everytime we are setting the compilation setting for one
snippet, it would automatically change it for all the snippets as well.

I suggest we not play with the idea of changing settings dynamically, it may or may not
work since our compiler was not built with re-entrant in mind.
JSOO relies on some global state too IIRC

After remove unneeded surface API, can you make a module in the jscomp/core directory to list which APIs are
used by the playground, it will be compiled so that we know at least my changes will not break playground in
the compile time

@ryyppy
Copy link
Member Author

ryyppy commented Aug 13, 2020

Thanks for the feedback!

Too many compiler internals

It seems the new version of playground relies on a much larger surface API from both jsoo and our compiler internal,
can we first reduce such surface API as much as we can, for example, remove such functionality to make it more maintainable?

I am happy to reduce them, can you tell me what specific parts are critical in your opinion? @cristianoc once mentioned that it would be a good idea to factor code in a way that js_main and the jsoo bundle use the same functionality to compile code. I had to override super_errors / warning printing since we don't want to print to stdout / stderr anymore and we also need to capture all the warnings as data.

I spent quite some time not overusing internal compiler modules too much, these are the minimal requirements I had basically. I think @chenglou wanted to dedupe the super_error reporting within the compiler and the syntax, so maybe we can reduce the super_error overriding at least?

Dynamic Settings / Global State

I suggest we not play with the idea of changing settings dynamically, it may or may not
work since our compiler was not built with re-entrant in mind.

For a proper playground experience we need a way to manipulate the compiler settings (especially for warning flags / module system). The solution at hand already works as advertised (even handles the precompiled module cache correctly so it doesn't take 2 seconds to build code that uses React).

In the end we are basically doing the same state reset management like the toploop module. In fact, we actually need to reset the compiler state on each run, otherwise the playground will only show warnings once (when compiling similar code twice).

So I am aware of the risk of having bugs, but ultimately, it's not like the playground bundle will break any main workflows of our users when there is a subtle compiler state bug in our web playground / code snippets. The upsides outweigh the downsides and the risk is very low IMO.

I wished the OCaml compiler would allow easier re-entrance, but this is probably something that will never be redesigned I guess.

JSOO relies on some global state too IIRC

The JSOO bundle uses the in memory filesystem to store the build artifacts (as far as I could observe). Other than that, JSOO bundle insertion (for the compiler and dependend libraries) is handled by our React-Hooks api (to make sure the JSOO filesystem creates cmt / cmi files correctly). I don't think that there's any global JSOO state that can otherwise mess with the compiler.

Other

After remove unneeded surface API, can you make a module in the jscomp/core directory to list which APIs are
used by the playground, it will be compiled so that we know at least my changes will not break playground in
the compile time

Yes, will do that after my vacation 👍

@ryyppy
Copy link
Member Author

ryyppy commented Aug 27, 2020

Still need to set forPrinter=false for the ReScript parsing, otherwise escape sequences in the code will be parsed incorrectly.

\cc @IwanKaramazow

@ryyppy
Copy link
Member Author

ryyppy commented Dec 22, 2020

Rebasing onto the 8.4.2 tag today to cut a release

@bobzhang
Copy link
Member

I missed the PR, would you do a rebase against master?

ryyppy added a commit to ryyppy/rescript-compiler that referenced this pull request Feb 11, 2021
@ryyppy ryyppy mentioned this pull request Feb 11, 2021
@ryyppy
Copy link
Member Author

ryyppy commented Feb 11, 2021

Closed in favor of #4947 (for a cleaner diff to review)

@ryyppy ryyppy closed this Feb 11, 2021
ryyppy added a commit to ryyppy/rescript-compiler that referenced this pull request Feb 11, 2021
For reference on the previous work in 2020, refer to rescript-lang#4518
ryyppy added a commit to ryyppy/rescript-compiler that referenced this pull request Apr 18, 2021
For reference on the previous work in 2020, refer to rescript-lang#4518
ryyppy added a commit to ryyppy/rescript-compiler that referenced this pull request Apr 18, 2021
For reference on the previous work in 2020, refer to rescript-lang#4518
ryyppy added a commit to ryyppy/rescript-compiler that referenced this pull request May 7, 2022
For reference on the previous work in 2020, refer to rescript-lang#4518
ryyppy added a commit that referenced this pull request May 31, 2022
For reference on the previous work in 2020, refer to #4518
ryyppy added a commit that referenced this pull request Jun 1, 2022
For reference on the previous work in 2020, refer to #4518
cristianoc pushed a commit that referenced this pull request Jun 1, 2022
* Add all relevant changes from previous 2020 bundle API

For reference on the previous work in 2020, refer to #4518

* Add ninja rule for building jsoo_refmt_main

* Fix formatting edge-cases when formatting ReScript -> ReScript

Configure the parser to pass forPrinter:true when parsing / printing ReScript.
This fixes issues where e.g. Some((1, 2)) get misprinted to Some(1,2) etc.

Relevant bug reports:
- rescript-lang/syntax#274
- rescript-lang/syntax#265

* Introduce initial type hints in playground bundle results

* Adapt playground to newest internal syntax apis

* Make jsoo_refmt_main work again by removing refmt

* Rename jsoo_refmt_main to jsoo_playground_main

* Move jsoo_playground_main to jscomp/main

* Remove irrelevant code

* Remove Refmt_api

* Make repl.js more reliable with missing .mli files

* repl.js: Log target compiler file, set js_playground_main as default

* Update CONTRIBUTING to align with the renamed playground jsoo entrypoint

Co-authored-by: Patrick Stapfer <ryyppy@users.noreply.github.com>
mununki pushed a commit to mununki/rescript-compiler that referenced this pull request Jul 15, 2022
* Add all relevant changes from previous 2020 bundle API

For reference on the previous work in 2020, refer to rescript-lang#4518

* Add ninja rule for building jsoo_refmt_main

* Fix formatting edge-cases when formatting ReScript -> ReScript

Configure the parser to pass forPrinter:true when parsing / printing ReScript.
This fixes issues where e.g. Some((1, 2)) get misprinted to Some(1,2) etc.

Relevant bug reports:
- rescript-lang/syntax#274
- rescript-lang/syntax#265

* Introduce initial type hints in playground bundle results

* Adapt playground to newest internal syntax apis

* Make jsoo_refmt_main work again by removing refmt

* Rename jsoo_refmt_main to jsoo_playground_main

* Move jsoo_playground_main to jscomp/main

* Remove irrelevant code

* Remove Refmt_api

* Make repl.js more reliable with missing .mli files

* repl.js: Log target compiler file, set js_playground_main as default

* Update CONTRIBUTING to align with the renamed playground jsoo entrypoint

Co-authored-by: Patrick Stapfer <ryyppy@users.noreply.github.com>
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.

10 participants