///|
pub(all) suberror RuntimeError {
UnsupportedHostCapability(String)
HostExit(Int32)
StackUnderflow
StackOverflow
TypeMismatch
InvalidModule(String)
ForeignStore
InvalidHandle
StoreClosed
MemoryClosed
InvalidMemoryType(String)
InvalidTableType(String)
HeapRepresentationInUse
OutOfBoundsMemoryAccess
OutOfBoundsTableAccess
OutOfBoundsArrayAccess // GC array access out of bounds
UndefinedElement
UninitializedElement
IndirectCallTypeMismatch
DivisionByZero
IntegerOverflow
InvalidConversion
OutOfMemory
InvalidResourceLimit
InvalidExecutionLimit
ExecutionLimitsUnavailable
ExecutionCancelled
ExecutionTimedOut
ExecutionBudgetExceeded
ResourceLimitExceeded(ResourceKind)
TableAllocationOverflow
TableAllocationFailed
MemoryMinimumExceedsLimits(Int64)
AllocationTooLarge
AtomicWaitNonSharedMemory
Unreachable
UncaughtException
CallStackExhausted
UnknownImport(String, String) // Import not found: (module_name, field_name)
LinkError // Import type mismatch during linking
// Link error with extra context (e.g. which import mismatched).
// The `Show` output still begins with "link error" for compatibility.
LinkErrorDetail(String)
CastFailure
NullReference // Null exception reference (null exnref thrown)
UnalignedAtomic
// Used when evaluating init expressions during instantiation; this should
// never be reached for validated modules, but helps diagnose engine gaps.
InvalidConstantExpression(String)
ContinuationAlreadyConsumed
UnhandledSuspension
UnsupportedGcContinuationStorage
AsyncHostRequiresAsyncCall
AsyncHostCallInProgress
AsyncHostCallCancelled
AsyncHostError(String)
} derive(Debug, Eq)
///|
/// Recover a structured runtime error from the language-wide `Error` type.
///
/// This is the single transport boundary used by executors and asynchronous
/// host-call adapters; unrelated errors return `None` instead of being
/// flattened to a string here.
pub fn RuntimeError::from_error(error : Error) -> RuntimeError? {
match error {
ContinuationAlreadyConsumed => Some(ContinuationAlreadyConsumed)
UnhandledSuspension => Some(UnhandledSuspension)
UnsupportedGcContinuationStorage => Some(UnsupportedGcContinuationStorage)
HostExit(_) as error => Some(error)
StackUnderflow => Some(StackUnderflow)
StackOverflow => Some(StackOverflow)
TypeMismatch => Some(TypeMismatch)
InvalidModule(detail) => Some(InvalidModule(detail))
ForeignStore => Some(ForeignStore)
InvalidHandle => Some(InvalidHandle)
StoreClosed => Some(StoreClosed)
MemoryClosed => Some(MemoryClosed)
InvalidMemoryType(_) as error => Some(error)
InvalidTableType(_) as error => Some(error)
HeapRepresentationInUse => Some(HeapRepresentationInUse)
OutOfBoundsMemoryAccess => Some(OutOfBoundsMemoryAccess)
OutOfBoundsTableAccess => Some(OutOfBoundsTableAccess)
OutOfBoundsArrayAccess => Some(OutOfBoundsArrayAccess)
UndefinedElement => Some(UndefinedElement)
UninitializedElement => Some(UninitializedElement)
IndirectCallTypeMismatch => Some(IndirectCallTypeMismatch)
DivisionByZero => Some(DivisionByZero)
IntegerOverflow => Some(IntegerOverflow)
InvalidConversion => Some(InvalidConversion)
MemoryMinimumExceedsLimits(_) as error => Some(error)
TableAllocationOverflow => Some(TableAllocationOverflow)
TableAllocationFailed => Some(TableAllocationFailed)
InvalidExecutionLimit => Some(InvalidExecutionLimit)
ExecutionLimitsUnavailable => Some(ExecutionLimitsUnavailable)
ExecutionCancelled => Some(ExecutionCancelled)
ExecutionTimedOut => Some(ExecutionTimedOut)
ExecutionBudgetExceeded => Some(ExecutionBudgetExceeded)
InvalidResourceLimit => Some(InvalidResourceLimit)
ResourceLimitExceeded(_) as error => Some(error)
OutOfMemory => Some(OutOfMemory)
AllocationTooLarge => Some(AllocationTooLarge)
AtomicWaitNonSharedMemory => Some(AtomicWaitNonSharedMemory)
Unreachable => Some(Unreachable)
UncaughtException => Some(UncaughtException)
CallStackExhausted => Some(CallStackExhausted)
UnknownImport(_, _) as runtime_error => Some(runtime_error)
LinkError => Some(LinkError)
LinkErrorDetail(_) as runtime_error => Some(runtime_error)
CastFailure => Some(CastFailure)
NullReference => Some(NullReference)
UnalignedAtomic => Some(UnalignedAtomic)
InvalidConstantExpression(_) as runtime_error => Some(runtime_error)
AsyncHostRequiresAsyncCall => Some(AsyncHostRequiresAsyncCall)
AsyncHostCallInProgress => Some(AsyncHostCallInProgress)
AsyncHostCallCancelled => Some(AsyncHostCallCancelled)
AsyncHostError(_) as runtime_error => Some(runtime_error)
_ => None
}
}
///|
/// Custom Show implementation for WebAssembly-spec-compliant error messages
pub impl Show for RuntimeError with fn output(self, logger) {
let msg = match self {
UnsupportedHostCapability(detail) =>
"unsupported host capability: \{detail}"
ContinuationAlreadyConsumed => "continuation already consumed"
UnhandledSuspension => "unhandled suspension"
UnsupportedGcContinuationStorage =>
"Stack switching feature not compatible with GC storage"
HostExit(code) => "host requested exit: \{code}"
StackUnderflow => "stack underflow"
StackOverflow => "stack overflow"
TypeMismatch => "type mismatch"
InvalidModule(detail) => "invalid module: \{detail}"
ForeignStore => "instance belongs to another store"
InvalidHandle => "invalid or stale runtime handle"
StoreClosed => "store is closed"
MemoryClosed => "memory is closed"
InvalidMemoryType(detail) => "invalid memory type: \{detail}"
InvalidTableType(detail) => "invalid table type: \{detail}"
HeapRepresentationInUse =>
"cannot enable native GC with live interpreter objects"
OutOfBoundsMemoryAccess => "out of bounds memory access"
OutOfBoundsTableAccess => "undefined element: out of bounds table access"
OutOfBoundsArrayAccess => "out of bounds array access"
UndefinedElement => "undefined element: out of bounds table access"
UninitializedElement => "uninitialized element"
IndirectCallTypeMismatch => "indirect call type mismatch"
DivisionByZero => "integer divide by zero"
IntegerOverflow => "integer overflow"
InvalidConversion => "invalid conversion to integer"
MemoryMinimumExceedsLimits(pages) =>
"memory minimum size of \{pages.reinterpret_as_uint64()} pages exceeds memory limits"
TableAllocationOverflow => "overflow calculating table allocation size"
TableAllocationFailed => "failed to allocate"
InvalidExecutionLimit => "invalid execution limit"
ExecutionLimitsUnavailable => "execution limits require compiled safepoints"
ExecutionCancelled => "execution cancelled"
ExecutionTimedOut => "execution deadline exceeded"
ExecutionBudgetExceeded => "execution safepoint budget exhausted"
InvalidResourceLimit => "invalid resource limit"
ResourceLimitExceeded(kind) => "host resource limit exceeded: \{Repr(kind)}"
OutOfMemory => "out of memory"
AllocationTooLarge => "allocation size too large"
AtomicWaitNonSharedMemory => "atomic wait on non-shared memory"
Unreachable => "unreachable"
UncaughtException => "uncaught exception"
CallStackExhausted => "call stack exhausted"
UnknownImport(mod_name, field_name) =>
"unknown import: \{mod_name}.\{field_name}"
LinkError => "link error"
LinkErrorDetail(detail) =>
if detail == "" {
"link error"
} else {
"link error: \{detail}"
}
CastFailure => "cast failure"
NullReference => "null reference"
UnalignedAtomic => "unaligned atomic"
InvalidConstantExpression(detail) =>
if detail == "" {
"invalid constant expression"
} else {
"invalid constant expression: \{detail}"
}
AsyncHostRequiresAsyncCall =>
"async host function requires an async wasm call"
AsyncHostCallInProgress => "another async host call is already pending"
AsyncHostCallCancelled => "async wasm call was cancelled"
AsyncHostError(message) => "async host function failed: \{message}"
}
logger.write_string(msg)
}
///|
/// A stack frame entry for error reporting
pub(all) struct CallStackEntry {
func_idx : Int32
func_name : String? // Optional function name from debug info
}
///|
fn CallStackEntry::to_string(self : CallStackEntry) -> String {
match self.func_name {
Some(name) => "func[\{self.func_idx}] \{name}"
None => "func[\{self.func_idx}]"
}
}
///|
/// Runtime error with additional context for debugging
pub struct RuntimeErrorContext {
error : RuntimeError
call_stack : Array[CallStackEntry]
instruction : String? // The instruction that caused the error
func_idx : Int32? // The function index where error occurred
}
///|
pub fn RuntimeErrorContext::RuntimeErrorContext(
error : RuntimeError,
) -> RuntimeErrorContext {
{ error, call_stack: [], instruction: None, func_idx: None, }
}
///|
pub fn RuntimeErrorContext::with_call_stack(
self : RuntimeErrorContext,
stack : Array[CallStackEntry],
) -> RuntimeErrorContext {
{ ..self, call_stack: stack, }
}
///|
pub fn RuntimeErrorContext::with_instruction(
self : RuntimeErrorContext,
instr : String,
) -> RuntimeErrorContext {
{ ..self, instruction: Some(instr), }
}
///|
pub fn RuntimeErrorContext::with_func_idx(
self : RuntimeErrorContext,
idx : Int32,
) -> RuntimeErrorContext {
{ ..self, func_idx: Some(idx), }
}
///|
/// Format the runtime error with full context for display
pub fn RuntimeErrorContext::format(self : RuntimeErrorContext) -> String {
let result = StringBuilder::StringBuilder()
result.write_string("runtime error: ")
result.write_string(self.error.to_string())
result.write_string("\n")
// Show instruction if available
if self.instruction is Some(instr) {
result.write_string(" at instruction: ")
result.write_string(instr)
result.write_string("\n")
}
// Show function index if available
if self.func_idx is Some(idx) {
result.write_string(" in function: func[\{idx}]\n")
}
// Show call stack
if self.call_stack.length() > 0 {
result.write_string("\ncall stack (most recent call last):\n")
for i, entry in self.call_stack {
result.write_string(" \{i}: ")
result.write_string(entry.to_string())
result.write_string("\n")
}
}
result.to_string()
}
///|
pub impl Show for RuntimeErrorContext with fn output(self, logger) {
logger.write_string(self.format())
}
///|
/// Format a basic RuntimeError without context
pub fn format_runtime_error(error : RuntimeError) -> String {
RuntimeErrorContext::RuntimeErrorContext(error).format()
}