gnolang / gno

Gno: An interpreted, stack-based Go virtual machine to build succinct and composable apps + Gno.land: a blockchain for timeless code and fair open-source
https://gno.land/
Other
844 stars 344 forks source link

Add support for WASM in goleveldb dependency #1008

Closed ilgooz closed 11 months ago

ilgooz commented 11 months ago

Currently, syndtr/goleveldb used as the storage. As this dependency doesn't have support for WASM it prevents compiling gnovm to WASM.

We should either (1) fork it and apply the following change to bring compatibility or (2) switch to another storage with builtin support. I prefer option (1) because it's the fastest and safest for overall code stability. How should we proceed with this?

The following code introduces js+wasm built target with;

diff --git a/leveldb/storage/file_storage_js.go b/leveldb/storage/file_storage_js.go
new file mode 100644
index 0000000..36b4bf8
--- /dev/null
+++ b/leveldb/storage/file_storage_js.go
@@ -0,0 +1,63 @@
+// Copyright (c) 2012, Suryandaru Triandana <syndtr@gmail.com>
+// All rights reserved.
+//
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+//go:build js && wasm
+// +build js,wasm
+
+package storage
+
+import (
+   "os"
+   "syscall"
+)
+
+type jsFileLock struct{}
+
+func (fl *jsFileLock) release() error {
+   return nil
+}
+
+func newFileLock(path string, readOnly bool) (fl fileLock, err error) {
+   return &jsFileLock{}, nil
+}
+
+func rename(oldpath, newpath string) error {
+   return os.Rename(oldpath, newpath)
+}
+
+func isErrInvalid(err error) bool {
+   if err == os.ErrInvalid {
+       return true
+   }
+   // Go < 1.8
+   if syserr, ok := err.(*os.SyscallError); ok && syserr.Err == syscall.EINVAL {
+       return true
+   }
+   // Go >= 1.8 returns *os.PathError instead
+   if patherr, ok := err.(*os.PathError); ok && patherr.Err == syscall.EINVAL {
+       return true
+   }
+   return false
+}
+
+func syncDir(name string) error {
+   // As per fsync manpage, Linux seems to expect fsync on directory, however
+   // some system don't support this, so we will ignore syscall.EINVAL.
+   //
+   // From fsync(2):
+   //   Calling fsync() does not necessarily ensure that the entry in the
+   //   directory containing the file has also reached disk. For that an
+   //   explicit fsync() on a file descriptor for the directory is also needed.
+   f, err := os.Open(name)
+   if err != nil {
+       return err
+   }
+   defer f.Close()
+   if err := f.Sync(); err != nil && !isErrInvalid(err) {
+       return err
+   }
+   return nil
+}
moul commented 11 months ago

Addresses https://github.com/gnolang/gno/issues/1013

ilgooz commented 11 months ago

Should be solved in https://github.com/gnolang/gno/pull/1012.