-
Notifications
You must be signed in to change notification settings - Fork 206
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
Compiling in TS - refactor #3695
Comments
Thank you for the great writeup!
Is this simply referring to compatibility between the compiler + dependency resolver package coming out of this <> NoirJS and BarretenbergBackend? Or is it referring to some general JS workflow? |
I mean with the way JS developers are used to write things, i.e. being aware of the event loop. To give a practical example, on the playground all I wanted is for a message to be displayed when the user hits the // using toast
await toast.promise(compile(code), { pending: "Compiling...", success: "Compiled!" }) or // using native "alert" function
alert("Compiling...")
await compile(code)
alert("Compiled!")
This is what I would define as "standard JS development flow". With the current state of So I had to use some JS fuckery: const compileTO = new Promise((resolve, reject) =>
setTimeout(async () => {
try {
await compile(code);
resolve(code);
} catch (err) {
reject(err);
}
}, 0)
);
await toast.promise(compileTO, {
pending: "Compiling...",
success: "Compiled!",
error: "Error compiling",
}); In this case, I wrapped the synchronous call in a promise so it could be |
…ger` for consistency with native interface (#3891) # Description Merging the work done here: AztecProtocol/aztec-packages#3696 #3781 #3760 Plus some extras to make the API nicer. ## Problem Closes(?) #3695 ## Summary Makes noir_wasm easier to work with, including dependency resolution and bundling. This package can be used from both node and the browser with identical API leveraging a virtual filesystem. Uses webpack for bundling, which is done in two steps: 1) rust -> wasm (cjs/esm) 2) TS + wasm (cjs/esm) -> universal package for web Tests have been migrated to mocha and playwright. ## Additional Context ~~I really want to test it [here](https://github.com/signorecello/noir-playground) before merging, but it's in a state in which it can be reviewed before we commit to an API.~~ Done: signorecello/noir-playground#32 Even though the initial memFS-backed FileManager developed by @alexghr is still here, it is not used for the web version due to import problems. The way it works now, webpack uses `memfs` directly it to alias the node `fs` module (which seems to be its intended use case) and allows us to use the nodejs `fs` API everywhere. ## Documentation Documentation is required for usage, but should basically be: ```typescript // Node.js import { compile, createFileManager } from '@noir-lang/noir_wasm'; // Rename!! const fm = createFileManager(myProjectPath); const myCompiledCode = await compile(fm); ``` ```typescript // Browser import { compile, createFileManager } from '@noir-lang/noir_wasm'; // Rename!! const fm = createFileManager('/'); for (const path of files) { await fm.writeFile(path, await getFileAsStream(path)); } const myCompiledCode = await compile(fm); ``` Check one: - [ ] No documentation needed. - [ ] Documentation included in this PR. - [ ] **[Exceptional Case]** Documentation to be submitted in a separate PR. # PR Checklist - [x] I have tested the changes locally. - [x] I have formatted the changes with [Prettier](https://prettier.io/) and/or `cargo fmt` on default settings. --------- Co-authored-by: sirasistant <[email protected]> Co-authored-by: Tom French <[email protected]> Co-authored-by: Tom French <[email protected]>
@signorecello can we close this? |
Problem
Intro
Currently, the recommended user flow for Noir is:
Nargo is meant to be used as a CLI tool. Using it involves installing Nargo and running commands on an interactive shell. That was enough until a few months ago.
However, production apps need a more programmatic interface. For many reasons, we have concluded that JS is the programmatic support we will be giving, even though significant support is being given to other ways of using Noir (for example with NoirRS).
This comes with a problem: how to make Rust behave with JS? Turns out Rust is a pretty cool language, and tools like
wasm-bindgen
really make this easy. However, because JS is not a pretty cool language, most of the issues arise on this side of the equation. Let's lay them down:Module system
Currently your NoirJS packages are written in TS and transpiled to both
esm
andcjs
withtsc-multi
.As for the packages that use WASM, those are simply Rust that is compiled with
wasm-bindgen
to both targetsnode.js
(cjs
) andweb
(esm
). Then some script runs to modifypackage.json
to deal with the imports.noir_wasm
This is one of the latter. It is
rust
that is compiled to a JS package on bothcjs
andesm
. And more importantly, it needs to be WASM because that's how it interacts with the actual compiler that runs in Rust.However, three big problems exist with WASM:
wasm
can't fetch it.wasm-bindgen
is the--target
flag, which creates a.wasm
file, then a.js
"glue". The problem is that most bundlers likewebpack
orvite
need to be told exactly how to work with non-js files. Even if all goes well, you still need toinstantiate
thewasm
before actually calling functions... If you'recjs
, because foresm
you don't need to. Fucking. Mess.source-resolver
To address this, we have
source-resolver
, a JS package that will resolve dependencies in JS, before callingnoir_wasm
. It fetches them on a filesystem, from the internet, etc. Then you pass the actual text of these files tonoir_wasm
, which does its thing. However, this is not so easy. Two examples:node
don't havefetch
.esm
hasimport.meta.url
but not__dirname
. You can't usefs
orpath
on the browser regardless of which module system you have. And many many many more problems.main
requiresdepA
anddepC
, anddepA
requiresdepB
anddepC
, how should you treatdepC
, as dependency ofmain
, or as dependency ofdepA
?wasm
can't wait, you can't rely on JS powerful event loop. If you need to fetch a dependency from the internet, you literally have to stop and wait for the call to come back, you can't just keep doing other things while you wait, like you usually do in JS. This blocks everything, you can't even scroll a page while it fetches, I shit you not.Here's an example of how messy it quickly becomes:
I hope I have convinced you that this dev experience is probably the worst imaginable. Before even starting to use Noir, the user needs to check:
And then starting to think how exactly will they fit all this into their project. Because if they're bundling it or serving in a browser... Damn, RIP
Happy Case
Happy case is to have a good devex, abstracting away most of the stuff from the user:
esm
andcjs
in a way that user doesn't have to care which version are they usingnoir_wasm
where's the project'sNargo.toml
and forget about itMy naive suggestion would be to:
noir_wasm
resolve dependencies injs
, basically reading theNargo.toml
and recursively resolving dependencies, whether remote or local. Yes, this means eliminatingsource-resolver
.Promises
toFutures
and be 10000% sure there's absolutely no other way to resolve the arising bugswasm
initialization innoir_wasm
, and bundling that as a cross-module packageAlternatives Considered
No response
Additional Context
No response
Would you like to submit a PR for this Issue?
No
Support Needs
No response
The text was updated successfully, but these errors were encountered: