diff options
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/sys/error.go')
-rw-r--r-- | vendor/github.com/tetratelabs/wazero/sys/error.go | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/vendor/github.com/tetratelabs/wazero/sys/error.go b/vendor/github.com/tetratelabs/wazero/sys/error.go new file mode 100644 index 000000000..c3efbad96 --- /dev/null +++ b/vendor/github.com/tetratelabs/wazero/sys/error.go @@ -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 +} |