Add minimal support for WebAssembly #277
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR adds minimal support for compiling LevelDB to WebAssembly. WebAssembly support was added to the Go compiler starting with version 1.11 and you can read the Official Wiki Page for more information about how it works.
Most of the codebase already works in WebAssembly without any changes 😄One thing that doesn't work out of the box is the
leveldb/storage
package. The Go compiler already makes use of thefs
package in Node.js when compiling to WebAssembly. It is easy to open, read, and write to files in a Node.js environment using the Go standard library. The only thing I needed to add in this PR was support for file locks, since the existing implementations (e.g., file_storage_unix.go) rely on OS-specific syscalls.The implementation of file locks that I wrote here is not perfect. Unfortunately Node.js does not support true file locks, so my implementation relies on in-memory maps protected by a mutex. This means it does not prevent other processes from accessing the files. However, I believe it is good enough for most use cases.
You can compile Go tests to WebAssembly and run them in a Node.js environment by running
GOOS=js GOARCH=wasm go test ./...
. Currently, large parts of the test suite fail to build because Ginkgo does not support WebAssembly. It is possible that there are test cases that would fail too if the build were to succeed. However, if you limit the tests to only theleveldb/storage
package, they pass! You can try it yourself withGOOS=js GOARCH=wasm go test ./leveldb/storage -v
.Additionally, with the changes in this PR, I was able to compile this simple program to WebAssembly and run it with
GOOS=js GOARCH=wasm go run main.go
:Working in Node.js is one thing, but browser support is arguably more interesting. I have done some initial testing and it looks like it is possible to get LevelDB working in the browser by using BrowserFS to emulate the Node.js
fs
package. One problem with that right now is that the Go compiler/runtime expects thefs
package to support the special file descriptors 0, 1, and 2 for stdin, stdout, and stderr respectively. I opened this issue to add support for these special file descriptors to BrowserFS.In any case, if you are interested, I can work more on supporting LevelDB in the browser in the future. There are a number of strategies we could use here and not all of them depend on making changes to BrowserFS.