[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:
kim
2024-05-27 15:46:15 +00:00
committed by GitHub
parent cce21c11cb
commit 1e7b32490d
398 changed files with 86174 additions and 684 deletions

26
vendor/github.com/tetratelabs/wazero/sys/clock.go generated vendored Normal file
View File

@ -0,0 +1,26 @@
package sys
// ClockResolution is a positive granularity of clock precision in
// nanoseconds. For example, if the resolution is 1us, this returns 1000.
//
// Note: Some implementations return arbitrary resolution because there's
// no perfect alternative. For example, according to the source in time.go,
// windows monotonic resolution can be 15ms. See /RATIONALE.md.
type ClockResolution uint32
// Walltime returns the current unix/epoch time, seconds since midnight UTC
// 1 January 1970, with a nanosecond fraction.
type Walltime func() (sec int64, nsec int32)
// Nanotime returns nanoseconds since an arbitrary start point, used to measure
// elapsed time. This is sometimes referred to as a tick or monotonic time.
//
// Note: There are no constraints on the value return except that it
// increments. For example, -1 is a valid if the next value is >= 0.
type Nanotime func() int64
// Nanosleep puts the current goroutine to sleep for at least ns nanoseconds.
type Nanosleep func(ns int64)
// Osyield yields the processor, typically to implement spin-wait loops.
type Osyield func()

83
vendor/github.com/tetratelabs/wazero/sys/error.go generated vendored Normal file
View File

@ -0,0 +1,83 @@
// Package sys includes constants and types used by both public and internal APIs.
package sys
import (
"context"
"fmt"
)
// These two special exit codes are reserved by wazero for context Cancel and Timeout integrations.
// The assumption here is that well-behaving Wasm programs won't use these two exit codes.
const (
// ExitCodeContextCanceled corresponds to context.Canceled and returned by ExitError.ExitCode in that case.
ExitCodeContextCanceled uint32 = 0xffffffff
// ExitCodeDeadlineExceeded corresponds to context.DeadlineExceeded and returned by ExitError.ExitCode in that case.
ExitCodeDeadlineExceeded uint32 = 0xefffffff
)
// ExitError is returned to a caller of api.Function when api.Module CloseWithExitCode was invoked,
// or context.Context passed to api.Function Call was canceled or reached the Timeout.
//
// ExitCode zero value means success while any other value is an error.
//
// Here's an example of how to get the exit code:
//
// main := module.ExportedFunction("main")
// if err := main(ctx); err != nil {
// if exitErr, ok := err.(*sys.ExitError); ok {
// // This means your module exited with non-zero code!
// }
// --snip--
//
// Note: While possible the reason of this was "proc_exit" from "wasi_snapshot_preview1", it could be from other host
// functions, for example an AssemblyScript's abort handler, or any arbitrary caller of CloseWithExitCode.
//
// See https://github.com/WebAssembly/WASI/blob/main/phases/snapshot/docs.md#proc_exit and
// https://www.assemblyscript.org/concepts.html#special-imports
//
// Note: In the case of context cancellation or timeout, the api.Module from which the api.Function created is closed.
type ExitError struct {
// Note: this is a struct not a uint32 type as it was originally one and
// we don't want to break call-sites that cast into it.
exitCode uint32
}
var exitZero = &ExitError{}
func NewExitError(exitCode uint32) *ExitError {
if exitCode == 0 {
return exitZero
}
return &ExitError{exitCode: exitCode}
}
// ExitCode returns zero on success, and an arbitrary value otherwise.
func (e *ExitError) ExitCode() uint32 {
return e.exitCode
}
// Error implements the error interface.
func (e *ExitError) Error() string {
switch e.exitCode {
case ExitCodeContextCanceled:
return fmt.Sprintf("module closed with %s", context.Canceled)
case ExitCodeDeadlineExceeded:
return fmt.Sprintf("module closed with %s", context.DeadlineExceeded)
default:
return fmt.Sprintf("module closed with exit_code(%d)", e.exitCode)
}
}
// Is allows use via errors.Is
func (e *ExitError) Is(err error) bool {
if target, ok := err.(*ExitError); ok {
return e.exitCode == target.exitCode
}
if e.exitCode == ExitCodeContextCanceled && err == context.Canceled {
return true
}
if e.exitCode == ExitCodeDeadlineExceeded && err == context.DeadlineExceeded {
return true
}
return false
}

107
vendor/github.com/tetratelabs/wazero/sys/stat.go generated vendored Normal file
View File

@ -0,0 +1,107 @@
package sys
import "io/fs"
// Inode is the file serial number, or zero if unknown.
//
// Any constant value will invalidate functions that use this for
// equivalence, such as os.SameFile (Stat_t.Ino).
//
// When zero is returned by a `readdir`, some compilers will attempt to
// get a non-zero value with `lstat`. Those using this for darwin's definition
// of `getdirentries` conflate zero `d_fileno` with a deleted file, so skip the
// entry. See /RATIONALE.md for more on this.
type Inode = uint64
// ^-- Inode is a type alias to consolidate documentation and aid in reference
// searches. While only Stat_t is exposed publicly at the moment, this is used
// internally for Dirent and several function return values.
// EpochNanos is a timestamp in epoch nanoseconds, or zero if unknown.
//
// This defines epoch time the same way as Walltime, except this value is
// packed into an int64. Common conversions are detailed in the examples.
type EpochNanos = int64
// Stat_t is similar to syscall.Stat_t, except available on all operating
// systems, including Windows.
//
// # Notes
//
// - This is used for WebAssembly ABI emulating the POSIX `stat` system call.
// Fields included are required for WebAssembly ABI including wasip1
// (a.k.a. wasix) and wasi-filesystem (a.k.a. wasip2). See
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/stat.html
// - Fields here are required for WebAssembly ABI including wasip1
// (a.k.a. wasix) and wasi-filesystem (a.k.a. wasip2).
// - This isn't the same as syscall.Stat_t because wazero supports Windows,
// which doesn't have that type. runtime.GOOS that has this already also
// have inconsistent field lengths, which complicates wasm binding.
// - Use NewStat_t to create this from an existing fs.FileInfo.
// - For portability, numeric fields are 64-bit when at least one platform
// defines it that large.
type Stat_t struct {
// Dev is the device ID of device containing the file.
Dev uint64
// Ino is the file serial number, or zero if not available. See Inode for
// more details including impact returning a zero value.
Ino Inode
// Mode is the same as Mode on fs.FileInfo containing bits to identify the
// type of the file (fs.ModeType) and its permissions (fs.ModePerm).
Mode fs.FileMode
// Nlink is the number of hard links to the file.
//
// Note: This value is platform-specific and often at least one. Linux will
// return 1+N for a directory, where BSD (like Darwin) return 2+N, which
// includes the dot entry.
Nlink uint64
// Size is the length in bytes for regular files. For symbolic links, this
// is length in bytes of the pathname contained in the symbolic link.
Size int64
// Atim is the last data access timestamp in epoch nanoseconds.
Atim EpochNanos
// Mtim is the last data modification timestamp in epoch nanoseconds.
Mtim EpochNanos
// Ctim is the last file status change timestamp in epoch nanoseconds.
Ctim EpochNanos
}
// NewStat_t fills a new Stat_t from `info`, including any runtime.GOOS-specific
// details from fs.FileInfo `Sys`. When `Sys` is already a *Stat_t, it is
// returned as-is.
//
// # Notes
//
// - When already in fs.FileInfo `Sys`, Stat_t must be a pointer.
// - When runtime.GOOS is "windows" Stat_t.Ino will be zero.
// - When fs.FileInfo `Sys` is nil or unknown, some fields not in fs.FileInfo
// are defaulted: Stat_t.Atim and Stat_t.Ctim are set to `ModTime`, and
// are set to ModTime and Stat_t.Nlink is set to 1.
func NewStat_t(info fs.FileInfo) Stat_t {
// Note: Pointer, not val, for parity with Go, which sets *syscall.Stat_t
if st, ok := info.Sys().(*Stat_t); ok {
return *st
}
return statFromFileInfo(info)
}
func defaultStatFromFileInfo(info fs.FileInfo) Stat_t {
st := Stat_t{}
st.Ino = 0
st.Dev = 0
st.Mode = info.Mode()
st.Nlink = 1
st.Size = info.Size()
mtim := info.ModTime().UnixNano() // Set all times to the mod time
st.Atim = mtim
st.Mtim = mtim
st.Ctim = mtim
return st
}

29
vendor/github.com/tetratelabs/wazero/sys/stat_bsd.go generated vendored Normal file
View File

@ -0,0 +1,29 @@
//go:build (amd64 || arm64) && (darwin || freebsd)
package sys
import (
"io/fs"
"syscall"
)
const sysParseable = true
func statFromFileInfo(info fs.FileInfo) Stat_t {
if d, ok := info.Sys().(*syscall.Stat_t); ok {
st := Stat_t{}
st.Dev = uint64(d.Dev)
st.Ino = d.Ino
st.Mode = info.Mode()
st.Nlink = uint64(d.Nlink)
st.Size = d.Size
atime := d.Atimespec
st.Atim = atime.Sec*1e9 + atime.Nsec
mtime := d.Mtimespec
st.Mtim = mtime.Sec*1e9 + mtime.Nsec
ctime := d.Ctimespec
st.Ctim = ctime.Sec*1e9 + ctime.Nsec
return st
}
return defaultStatFromFileInfo(info)
}

32
vendor/github.com/tetratelabs/wazero/sys/stat_linux.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
//go:build (amd64 || arm64 || riscv64) && linux
// Note: This expression is not the same as compiler support, even if it looks
// similar. Platform functions here are used in interpreter mode as well.
package sys
import (
"io/fs"
"syscall"
)
const sysParseable = true
func statFromFileInfo(info fs.FileInfo) Stat_t {
if d, ok := info.Sys().(*syscall.Stat_t); ok {
st := Stat_t{}
st.Dev = uint64(d.Dev)
st.Ino = uint64(d.Ino)
st.Mode = info.Mode()
st.Nlink = uint64(d.Nlink)
st.Size = d.Size
atime := d.Atim
st.Atim = atime.Sec*1e9 + atime.Nsec
mtime := d.Mtim
st.Mtim = mtime.Sec*1e9 + mtime.Nsec
ctime := d.Ctim
st.Ctim = ctime.Sec*1e9 + ctime.Nsec
return st
}
return defaultStatFromFileInfo(info)
}

View File

@ -0,0 +1,17 @@
//go:build (!((amd64 || arm64 || riscv64) && linux) && !((amd64 || arm64) && (darwin || freebsd)) && !((amd64 || arm64) && windows)) || js
package sys
import "io/fs"
// sysParseable is only used here as we define "supported" as being able to
// parse `info.Sys()`. The above `go:build` constraints exclude 32-bit until
// that's requested.
//
// TODO: When Go 1.21 is out, use the "unix" build constraint (as 1.21 makes
// our floor Go version 1.19.
const sysParseable = false
func statFromFileInfo(info fs.FileInfo) Stat_t {
return defaultStatFromFileInfo(info)
}

View File

@ -0,0 +1,26 @@
//go:build (amd64 || arm64) && windows
package sys
import (
"io/fs"
"syscall"
)
const sysParseable = true
func statFromFileInfo(info fs.FileInfo) Stat_t {
if d, ok := info.Sys().(*syscall.Win32FileAttributeData); ok {
st := Stat_t{}
st.Ino = 0 // not in Win32FileAttributeData
st.Dev = 0 // not in Win32FileAttributeData
st.Mode = info.Mode()
st.Nlink = 1 // not in Win32FileAttributeData
st.Size = info.Size()
st.Atim = d.LastAccessTime.Nanoseconds()
st.Mtim = d.LastWriteTime.Nanoseconds()
st.Ctim = d.CreationTime.Nanoseconds()
return st
}
return defaultStatFromFileInfo(info)
}