summaryrefslogtreecommitdiff
path: root/vendor/github.com/tetratelabs/wazero/sys/error.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/tetratelabs/wazero/sys/error.go')
-rw-r--r--vendor/github.com/tetratelabs/wazero/sys/error.go83
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
+}