-
Notifications
You must be signed in to change notification settings - Fork 138
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
Save the project, by figuring out how to make it usable. #105
Comments
The dist directory now contains unoptimized, unpacked files. These are not designed to be used in any application. They can be useful to understand what the current code looks like, to experiment with it, and possibly find a solution to the above problem. |
I've been planning on submitting a PR for exactly this at some point in the next few months based on the ideas I mentioned in #94. It's been working great in the libraries I listed there; we'd probably just want to wait for emscripten-core/emscripten#5296 to be merged before doing the same thing here. This would solve the issue you noted of requiring an external binary to be loaded at run-time, but doesn't help with the async aspect since wasm compilation still generally needs to be asynchronous. A few ideas come to mind as solutions for that:
|
@buu700 I think changing behavior after a ready function is asking for trouble. I like option 2. |
Option 2 would be fantastic. This is the most conservative one, but being in a state where some functions work and some don't feels indeed a bit weird. Option 2 can also be seamlessly used in legacy environments that don't support promises. |
Also I don't like the performance hit of having to run everything through the Promise system. Promises require that they always resolve or reject of a subsequent turn of the event loop. This means you can get all kinds of race conditions as well as unneeded overhead. |
Awesome, sounds good to me; I'll go with option 2. (That was my preference as well, but I thought 3/4 might've been a potentially interesting compromise if there'd been disagreement.) |
I'm not sure I see why the WASM needs to be loaded asynchronously - there are loaders like this one that can bundle How this can deal with various usecases:
Are you referring to option 1? Promise overhead is negligible, in particular if it only concerns the loading stage, but "unnecessary async for every function call" is a possible concern. I don't see any issues with using Promises for a loading stage, though, since that's going to be asynchronous anyway. |
The issue isn't building; the wasm compilation API is asynchronous. (There is a synchronous compilation API, but it's only supported for use with very small modules and it's bad for performance because it blocks the thread.) As far as promise overhead, it sounded like he was referring to option 1, e.g. the performance of a loop of function calls could be measurably affected by each iteration taking place on a separate event loop tick. |
Your changes have been merged, and I tried to build the unified asmjs+webasm libsodium.js files. The resulting files are now in https://github.com/jedisct1/libsodium.js/tree/master/dist (without optimizations/packing) Trying to load Any idea why? |
Looks like the JS in emscripten.sh is getting broken by emscripten inserting
After that, the three instances of After removing the function check and getting rid of constants entirely, it seems to be working as expected based on a quick test of |
Also, just committed fixes for some edge case issues that I caught while testing this to the emscripten PR, so you should pull the latest there before building this again. |
All these symbols should indeed be defined only after |
Happy to test the changes out with a webpack project. Wish I could help more. |
Seems to be working awesome! Having the initially unusable symbols in the same namespace as the What do you think about having the module return the promise, which resolves to an object with all the symbols? |
The password hashing tests fails because What would be a clean way to set |
Nice! I see that you've just made a bunch of commits; is there anything I can do to help? (The promise thing should be pretty easily doable by changing what's currently As far as |
If you could help with that, and maybe the promise thing, that would be great. But we already have something that works pretty well now. This is fantastic, thanks a ton for your help! Hope your Emscripten PRs will finally be merged soon! |
Ah, do you mean you'd want a way to increase the memory limit at run-time in the password hashing methods? I've run into issues with that before (unrelated to WebAssembly) when trying to test the sensitive mem limit with the default build. Not sure if there's any better way to do that than As far as the promise thing, I'll do that and send a PR right now. Thanks / not a problem, and thanks for crediting me in the authors section of the readme! Also, did you mean to delete the dist folder as part of 4bb6bf4? |
The |
For anyone else who wants to test libsodium.js in its current state (WebAssembly with asm.js fallback):
|
One thing I don't like about this is the fact that Having the promise return the object would make this more natural. |
Well, in my example/test, the |
Alright, time to close this ticket :) Thanks a ton, @buu700 , you're a hero! |
Awesome, not a problem at all, and thanks! |
@jedisct1, the |
Anyone here using libsodium with Jest? The ready event never fires for me in jsdom environment. |
@jedisct1 did you settle on a way to set TOTAL_MEMORY? |
No, did you? |
@jedisct1 no 😅 is there a way currently? I am getting memory errors for anything over 8mb, and I think that’s the reason? |
Yes, I think you still need the This can be solved, but I don't know how :) |
Oh really? Is it possible in the sumo build? How? I thought it just added less frequently used functions
|
Alright worked it out, as above you can up TOTAL_MEMORY via setting it on the window: window.sodium = {totalMemory: 134217728}; |
Does window.sodium work now? Last time I checked it did not. I described my workaround here. This was my preferred approach because I could use the smaller non sumo package but with enough memory for pwhash with MEMLIMIT set to 33554432. |
@bufke seems to, how did it not work? I get an abort error in the console, which there's also an outstanding issue for, but other than that my problem appears to be gone Note: saw your workaround and attempted to follow on Ubuntu but it crashed out at some point 😕 way beyond my understanding anyway |
Is it still possible to load libsodium synchronously? It would be awesome to have a possibility to do it with |
Here's a description of the current state of affairs.
libsodium, the core library, works amazingly well after having been compiled to asm.js and to webassembly, thanks to Emscripten.
All the tests are passing, speed isn't too bad, it's great!
However, using Emscripten-compiled code from regular Javascript code requires additional code before and after every call, in order to play well with its conventions and the way memory is managed.
libsodium-wrappers
solves this, by thinly wrapping the Emscripten-compiled function calls, to provide something easier to use, more idiomatic.libsodium-wrappers
is designed to be a module. Something one should be able to use usingrequire()
, amd, ES6 modules. And, for grey beards, one should include a script in a web page, and get something in the global namespace (currently namedsodium
).That thing naturally depends on
libsodium
, the core library. So, includinglibsodium-wrappers
as a module should includelibsodium
as a module, and everything will work fine.Unfortunately, the addition of webassembly messes things up a little bit.
libsodium
compiled to webassembly works well. It's fast. It's awesome. It's the future.So, we want
libsodium-wrappers
to load either the asmjs version, or the webassembly version oflibsodium
, according to what the runtime supports.libsodium-wrappers
could justrequire('libsodium.js')
orrequire('libsodium-wasm.js')
. That's what was attempted.But
libsodium-wasm.js
is just a loader, generated by emscripten, that loads the actual wasm binary code (libsodium.wasm
). That, obviously, has to happen asynchronously.So, we can't
require('libsodium-wasm.js')
and expect symbols to be usable right away. We need an asynchronous interface. Either by returning a Promise, or by forcing applications to provide a callback.What applications must be able to do in order to use that project, and what they may expect:
require('libsodium-wrappers.js')
or equivalent<script src=libsodium-wrappers.js></script>
require()
returns a promise that resolves to the list of exported symbols once everything is loaded.And that's it.
It's probably straightforward to people who have some good experience with Javascript.
Unfortunately, I haven't been able to achieve this. I spent a significant amount time on this, and miserably failed.
I give up.
I'd be glad to keep maintaining the Javascript/Webassembly version of the core library. But I can't do the plumbing alone.
I can't afford to spend more time making both work together and packaged in a way that applications can easily use.
If you can help, please do. Maybe it's as simple as an option to enable in Emscripten, or some tiny Javascript glue to add somewhere. I don't know.
If no one can help, I will delete this project and refocus on things I am more comfortable with.
The text was updated successfully, but these errors were encountered: