mirror of
https://github.com/superseriousbusiness/gotosocial
synced 2025-06-05 21:59:39 +02:00
[experiment] add alternative wasm sqlite3 implementation available via build-tag (#2863)
This allows for building GoToSocial with [SQLite transpiled to WASM](https://github.com/ncruces/go-sqlite3) and accessed through [Wazero](https://wazero.io/).
This commit is contained in:
213
vendor/github.com/tetratelabs/wazero/fsconfig.go
generated
vendored
Normal file
213
vendor/github.com/tetratelabs/wazero/fsconfig.go
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
package wazero
|
||||
|
||||
import (
|
||||
"io/fs"
|
||||
|
||||
experimentalsys "github.com/tetratelabs/wazero/experimental/sys"
|
||||
"github.com/tetratelabs/wazero/internal/sys"
|
||||
"github.com/tetratelabs/wazero/internal/sysfs"
|
||||
)
|
||||
|
||||
// FSConfig configures filesystem paths the embedding host allows the wasm
|
||||
// guest to access. Unconfigured paths are not allowed, so functions like
|
||||
// `path_open` result in unsupported errors (e.g. syscall.ENOSYS).
|
||||
//
|
||||
// # Guest Path
|
||||
//
|
||||
// `guestPath` is the name of the path the guest should use a filesystem for, or
|
||||
// empty for any files.
|
||||
//
|
||||
// All `guestPath` paths are normalized, specifically removing any leading or
|
||||
// trailing slashes. This means "/", "./" or "." all coerce to empty "".
|
||||
//
|
||||
// Multiple `guestPath` values can be configured, but the last longest match
|
||||
// wins. For example, if "tmp", then "" were added, a request to open
|
||||
// "tmp/foo.txt" use the filesystem associated with "tmp" even though a wider
|
||||
// path, "" (all files), was added later.
|
||||
//
|
||||
// A `guestPath` of "." coerces to the empty string "" because the current
|
||||
// directory is handled by the guest. In other words, the guest resolves ites
|
||||
// current directory prior to requesting files.
|
||||
//
|
||||
// More notes on `guestPath`
|
||||
// - Working directories are typically tracked in wasm, though possible some
|
||||
// relative paths are requested. For example, TinyGo may attempt to resolve
|
||||
// a path "../.." in unit tests.
|
||||
// - Zig uses the first path name it sees as the initial working directory of
|
||||
// the process.
|
||||
//
|
||||
// # Scope
|
||||
//
|
||||
// Configuration here is module instance scoped. This means you can use the
|
||||
// same configuration for multiple calls to Runtime.InstantiateModule. Each
|
||||
// module will have a different file descriptor table. Any errors accessing
|
||||
// resources allowed here are deferred to instantiation time of each module.
|
||||
//
|
||||
// Any host resources present at the time of configuration, but deleted before
|
||||
// Runtime.InstantiateModule will trap/panic when the guest wasm initializes or
|
||||
// calls functions like `fd_read`.
|
||||
//
|
||||
// # Windows
|
||||
//
|
||||
// While wazero supports Windows as a platform, all known compilers use POSIX
|
||||
// conventions at runtime. For example, even when running on Windows, paths
|
||||
// used by wasm are separated by forward slash (/), not backslash (\).
|
||||
//
|
||||
// # Notes
|
||||
//
|
||||
// - This is an interface for decoupling, not third-party implementations.
|
||||
// All implementations are in wazero.
|
||||
// - FSConfig is immutable. Each WithXXX function returns a new instance
|
||||
// including the corresponding change.
|
||||
// - RATIONALE.md includes design background and relationship to WebAssembly
|
||||
// System Interfaces (WASI).
|
||||
type FSConfig interface {
|
||||
// WithDirMount assigns a directory at `dir` to any paths beginning at
|
||||
// `guestPath`.
|
||||
//
|
||||
// For example, `dirPath` as / (or c:\ in Windows), makes the entire host
|
||||
// volume writeable to the path on the guest. The `guestPath` is always a
|
||||
// POSIX style path, slash (/) delimited, even if run on Windows.
|
||||
//
|
||||
// If the same `guestPath` was assigned before, this overrides its value,
|
||||
// retaining the original precedence. See the documentation of FSConfig for
|
||||
// more details on `guestPath`.
|
||||
//
|
||||
// # Isolation
|
||||
//
|
||||
// The guest will have full access to this directory including escaping it
|
||||
// via relative path lookups like "../../". Full access includes operations
|
||||
// such as creating or deleting files, limited to any host level access
|
||||
// controls.
|
||||
//
|
||||
// # os.DirFS
|
||||
//
|
||||
// This configuration optimizes for WASI compatibility which is sometimes
|
||||
// at odds with the behavior of os.DirFS. Hence, this will not behave
|
||||
// exactly the same as os.DirFS. See /RATIONALE.md for more.
|
||||
WithDirMount(dir, guestPath string) FSConfig
|
||||
|
||||
// WithReadOnlyDirMount assigns a directory at `dir` to any paths
|
||||
// beginning at `guestPath`.
|
||||
//
|
||||
// This is the same as WithDirMount except only read operations are
|
||||
// permitted. However, escaping the directory via relative path lookups
|
||||
// like "../../" is still allowed.
|
||||
WithReadOnlyDirMount(dir, guestPath string) FSConfig
|
||||
|
||||
// WithFSMount assigns a fs.FS file system for any paths beginning at
|
||||
// `guestPath`.
|
||||
//
|
||||
// If the same `guestPath` was assigned before, this overrides its value,
|
||||
// retaining the original precedence. See the documentation of FSConfig for
|
||||
// more details on `guestPath`.
|
||||
//
|
||||
// # Isolation
|
||||
//
|
||||
// fs.FS does not restrict the ability to overwrite returned files via
|
||||
// io.Writer. Moreover, os.DirFS documentation includes important notes
|
||||
// about isolation, which also applies to fs.Sub. As of Go 1.19, the
|
||||
// built-in file-systems are not jailed (chroot). See
|
||||
// https://github.com/golang/go/issues/42322
|
||||
//
|
||||
// # os.DirFS
|
||||
//
|
||||
// Due to limited control and functionality available in os.DirFS, we
|
||||
// advise using WithDirMount instead. There will be behavior differences
|
||||
// between os.DirFS and WithDirMount, as the latter biases towards what's
|
||||
// expected from WASI implementations.
|
||||
//
|
||||
// # Custom fs.FileInfo
|
||||
//
|
||||
// The underlying implementation supports data not usually in fs.FileInfo
|
||||
// when `info.Sys` returns *sys.Stat_t. For example, a custom fs.FS can use
|
||||
// this approach to generate or mask sys.Inode data. Such a filesystem
|
||||
// needs to decorate any functions that can return fs.FileInfo:
|
||||
//
|
||||
// - `Stat` as defined on `fs.File` (always)
|
||||
// - `Readdir` as defined on `os.File` (if defined)
|
||||
//
|
||||
// See sys.NewStat_t for examples.
|
||||
WithFSMount(fs fs.FS, guestPath string) FSConfig
|
||||
}
|
||||
|
||||
type fsConfig struct {
|
||||
// fs are the currently configured filesystems.
|
||||
fs []experimentalsys.FS
|
||||
// guestPaths are the user-supplied names of the filesystems, retained for
|
||||
// error messages and fmt.Stringer.
|
||||
guestPaths []string
|
||||
// guestPathToFS are the normalized paths to the currently configured
|
||||
// filesystems, used for de-duplicating.
|
||||
guestPathToFS map[string]int
|
||||
}
|
||||
|
||||
// NewFSConfig returns a FSConfig that can be used for configuring module instantiation.
|
||||
func NewFSConfig() FSConfig {
|
||||
return &fsConfig{guestPathToFS: map[string]int{}}
|
||||
}
|
||||
|
||||
// clone makes a deep copy of this module config.
|
||||
func (c *fsConfig) clone() *fsConfig {
|
||||
ret := *c // copy except slice and maps which share a ref
|
||||
ret.fs = make([]experimentalsys.FS, 0, len(c.fs))
|
||||
ret.fs = append(ret.fs, c.fs...)
|
||||
ret.guestPaths = make([]string, 0, len(c.guestPaths))
|
||||
ret.guestPaths = append(ret.guestPaths, c.guestPaths...)
|
||||
ret.guestPathToFS = make(map[string]int, len(c.guestPathToFS))
|
||||
for key, value := range c.guestPathToFS {
|
||||
ret.guestPathToFS[key] = value
|
||||
}
|
||||
return &ret
|
||||
}
|
||||
|
||||
// WithDirMount implements FSConfig.WithDirMount
|
||||
func (c *fsConfig) WithDirMount(dir, guestPath string) FSConfig {
|
||||
return c.WithSysFSMount(sysfs.DirFS(dir), guestPath)
|
||||
}
|
||||
|
||||
// WithReadOnlyDirMount implements FSConfig.WithReadOnlyDirMount
|
||||
func (c *fsConfig) WithReadOnlyDirMount(dir, guestPath string) FSConfig {
|
||||
return c.WithSysFSMount(&sysfs.ReadFS{FS: sysfs.DirFS(dir)}, guestPath)
|
||||
}
|
||||
|
||||
// WithFSMount implements FSConfig.WithFSMount
|
||||
func (c *fsConfig) WithFSMount(fs fs.FS, guestPath string) FSConfig {
|
||||
var adapted experimentalsys.FS
|
||||
if fs != nil {
|
||||
adapted = &sysfs.AdaptFS{FS: fs}
|
||||
}
|
||||
return c.WithSysFSMount(adapted, guestPath)
|
||||
}
|
||||
|
||||
// WithSysFSMount implements sysfs.FSConfig
|
||||
func (c *fsConfig) WithSysFSMount(fs experimentalsys.FS, guestPath string) FSConfig {
|
||||
if _, ok := fs.(experimentalsys.UnimplementedFS); ok {
|
||||
return c // don't add fake paths.
|
||||
}
|
||||
cleaned := sys.StripPrefixesAndTrailingSlash(guestPath)
|
||||
ret := c.clone()
|
||||
if i, ok := ret.guestPathToFS[cleaned]; ok {
|
||||
ret.fs[i] = fs
|
||||
ret.guestPaths[i] = guestPath
|
||||
} else if fs != nil {
|
||||
ret.guestPathToFS[cleaned] = len(ret.fs)
|
||||
ret.fs = append(ret.fs, fs)
|
||||
ret.guestPaths = append(ret.guestPaths, guestPath)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// preopens returns the possible nil index-correlated preopened filesystems
|
||||
// with guest paths.
|
||||
func (c *fsConfig) preopens() ([]experimentalsys.FS, []string) {
|
||||
preopenCount := len(c.fs)
|
||||
if preopenCount == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
fs := make([]experimentalsys.FS, len(c.fs))
|
||||
copy(fs, c.fs)
|
||||
guestPaths := make([]string, len(c.guestPaths))
|
||||
copy(guestPaths, c.guestPaths)
|
||||
return fs, guestPaths
|
||||
}
|
Reference in New Issue
Block a user