Skip to content
2 changes: 1 addition & 1 deletion examples/consumefuel/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ static void Main(string[] args)
{
expensive();
}
catch (TrapException ex)
catch (WasmtimeException ex)
{
Console.WriteLine("Exception caught with the following message:");
Console.WriteLine(ex.Message);
Expand Down
4 changes: 2 additions & 2 deletions src/Export.cs
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,13 @@ internal Export(IntPtr exportType)
unsafe
{
var name = Native.wasm_exporttype_name(exportType);
if (name->size == UIntPtr.Zero)
if (name->size == 0)
{
Name = String.Empty;
}
else
{
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size);
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
}
}
}
Expand Down
22 changes: 11 additions & 11 deletions src/Function.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2456,14 +2456,14 @@ internal unsafe static IntPtr InvokeCallback(Delegate callback, MethodInfo callb

internal static unsafe IntPtr HandleCallbackException(Exception ex)
{
// Store the exception as trap cause, so that we can use it as the TrapException's
// InnerException when the trap bubbles up to the next host-to-wasm transition.
// If the exception is already a TrapException, we use that one's InnerException,
// Store the exception as error cause, so that we can use it as the WasmtimeException's
// InnerException when the error bubbles up to the next host-to-wasm transition.
// If the exception is already a WasmtimeException, we use that one's InnerException,
// even if it's null.
// Note: This code currently requires that on every host-to-wasm transition where a
// trap can occur, TrapException.FromOwnedTrap() is called when a trap actually occured,
// which will then clear this field.
CallbackTrapCause = ex is TrapException trapException ? trapException.InnerException : ex;
// error can occur, WasmtimeException.FromOwnedError() is called when an error actually
// occured, which will then clear this field.
CallbackErrorCause = ex is WasmtimeException wasmtimeException ? wasmtimeException.InnerException : ex;

var bytes = Encoding.UTF8.GetBytes(ex.Message);

Expand Down Expand Up @@ -2527,17 +2527,17 @@ internal static class Native
internal static readonly Native.Finalizer Finalizer = (p) => GCHandle.FromIntPtr(p).Free();

/// <summary>
/// Contains the cause for a trap returned by invoking a wasm function, in case
/// the trap was caused by the host.
/// Contains the cause for a error returned by invoking a wasm function, in case
/// the error was caused by the host.
/// </summary>
/// <remarks>
/// This thread-local field will be set when catching a .NET exception at the
/// wasm-to-host transition. When the trap bubbles up to the next host-to-wasm
/// wasm-to-host transition. When the error bubbles up to the next host-to-wasm
/// transition, the field needs to be cleared, and its value can be used to set
/// the inner exception of the created <see cref="TrapException"/>.
/// the inner exception of the created <see cref="WasmtimeException"/>.
/// </remarks>
[ThreadStatic]
internal static Exception? CallbackTrapCause;
internal static Exception? CallbackErrorCause;

private static readonly Function _null = new Function();
private static readonly object?[] NullParams = new object?[1];
Expand Down
8 changes: 4 additions & 4 deletions src/Import.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,23 +83,23 @@ internal Import(IntPtr importType)
unsafe
{
var moduleName = Native.wasm_importtype_module(importType);
if (moduleName->size == UIntPtr.Zero)
if (moduleName->size == 0)
{
ModuleName = String.Empty;
}
else
{
ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, (int)moduleName->size);
ModuleName = Marshal.PtrToStringUTF8((IntPtr)moduleName->data, checked((int)moduleName->size));
}

var name = Native.wasm_importtype_name(importType);
if (name is null || name->size == UIntPtr.Zero)
if (name is null || name->size == 0)
{
Name = String.Empty;
}
else
{
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, (int)name->size);
Name = Marshal.PtrToStringUTF8((IntPtr)name->data, checked((int)name->size));
}
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Wasmtime
[StructLayout(LayoutKind.Sequential)]
internal unsafe struct ByteArray : IDisposable
{
public UIntPtr size;
public nuint size;
public byte* data;

public void Dispose()
Expand Down Expand Up @@ -176,7 +176,7 @@ public static Module FromText(Engine engine, string name, string text)
var textBytes = Encoding.UTF8.GetBytes(text);
fixed (byte* ptr = textBytes)
{
var error = Native.wasmtime_wat2wasm(ptr, (UIntPtr)textBytes.Length, out var moduleBytes);
var error = Native.wasmtime_wat2wasm(ptr, (nuint)textBytes.Length, out var moduleBytes);
if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
Expand Down Expand Up @@ -242,7 +242,7 @@ public byte[] Serialize()

using (array)
{
var len = Convert.ToInt32(array.size.ToUInt32());
var len = checked((int)array.size);
var bytes = new byte[len];
unsafe
{
Expand Down Expand Up @@ -335,15 +335,15 @@ public static byte[] ConvertText(string wat)
var textBytes = Encoding.UTF8.GetBytes(wat);
fixed (byte* ptr = textBytes)
{
var error = Native.wasmtime_wat2wasm(ptr, (UIntPtr)textBytes.Length, out var moduleBytes);
var error = Native.wasmtime_wat2wasm(ptr, (nuint)textBytes.Length, out var moduleBytes);
if (error != IntPtr.Zero)
{
throw WasmtimeException.FromOwnedError(error);
}

using (moduleBytes)
{
var arr = new byte[(int)moduleBytes.size];
var arr = new byte[checked((int)moduleBytes.size)];

var src = new Span<byte>(moduleBytes.data, (int)moduleBytes.size);
src.CopyTo(arr);
Expand Down Expand Up @@ -424,7 +424,7 @@ internal static class Native
public static extern void wasmtime_module_exports(IntPtr module, out ExportTypeArray exports);

[DllImport(Engine.LibraryName)]
public static unsafe extern IntPtr wasmtime_wat2wasm(byte* text, UIntPtr len, out ByteArray bytes);
public static unsafe extern IntPtr wasmtime_wat2wasm(byte* text, nuint len, out ByteArray bytes);

[DllImport(Engine.LibraryName)]
public static extern unsafe IntPtr wasmtime_module_validate(Engine.Handle engine, byte* bytes, UIntPtr size);
Expand Down
94 changes: 28 additions & 66 deletions src/TrapException.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ public enum TrapCode
Unreachable = 9,
/// <summary>The trap was the result of interrupting execution.</summary>
Interrupt = 10,
/// <summary>The trap was the result of running out of the configured fuel amount.</summary>
OutOfFuel = 11,
}

/// <summary>
Expand All @@ -53,13 +55,13 @@ unsafe internal TrapFrame(IntPtr frame)
ModuleName = null;

var bytes = Native.wasmtime_frame_func_name(frame);
if (bytes != null && (int)bytes->size > 0)
if (bytes != null && checked((int)bytes->size) > 0)
{
FunctionName = Encoding.UTF8.GetString(bytes->data, (int)bytes->size);
}

bytes = Native.wasmtime_frame_module_name(frame);
if (bytes != null && (int)bytes->size > 0)
if (bytes != null && checked((int)bytes->size) > 0)
{
ModuleName = Encoding.UTF8.GetString(bytes->data, (int)bytes->size);
}
Expand Down Expand Up @@ -88,10 +90,10 @@ unsafe internal TrapFrame(IntPtr frame)
private static class Native
{
[DllImport(Engine.LibraryName)]
public static extern UIntPtr wasm_frame_func_offset(IntPtr frame);
public static extern nuint wasm_frame_func_offset(IntPtr frame);

[DllImport(Engine.LibraryName)]
public static extern UIntPtr wasm_frame_module_offset(IntPtr frame);
public static extern nuint wasm_frame_module_offset(IntPtr frame);

[DllImport(Engine.LibraryName)]
public static extern unsafe ByteArray* wasmtime_frame_func_name(IntPtr frame);
Expand Down Expand Up @@ -127,28 +129,12 @@ public TrapCode TrapCode
{
if (TrapException.Native.wasmtime_trap_code(_trap, out var code))
{
return code;
return (TrapCode)code;
}
return TrapCode.Undefined;
}
}

/// <summary>
/// Attempt to get a WASI exit status code from this trap. May be null if no status code is available.
/// </summary>
public int? ExitStatus
{
get
{
if (TrapException.Native.wasmtime_trap_exit_status(_trap, out var exitStatus))
{
return exitStatus;
}

return null;
}
}

/// <summary>
/// Get the message string
/// </summary>
Expand Down Expand Up @@ -223,16 +209,7 @@ public List<TrapFrame> GetFrames()
TrapException.Native.wasm_trap_trace(_trap, out var frames);
using (frames)
{
var trapFrames = new List<TrapFrame>((int)frames.size);
for (var i = 0; i < (int)frames.size; ++i)
{
unsafe
{
trapFrames.Add(new TrapFrame(frames.data[i]));
}
}

return trapFrames;
return TrapException.GetFrames(frames);
}
}

Expand Down Expand Up @@ -261,18 +238,6 @@ public TrapException(string message) : base(message) { }
/// <inheritdoc/>
public TrapException(string message, Exception? inner) : base(message, inner) { }

/// <summary>
/// Gets the trap's frames.
/// </summary>
public IReadOnlyList<TrapFrame>? Frames { get; protected set; }

/// <summary>
/// The exit code when the trap results from executing the WASI `proc_exit` function.
///
/// The value is null if the trap was not an exit trap.
/// </summary>
public int? ExitCode { get; private set; }

/// <summary>
/// Indentifies which type of trap this is.
/// </summary>
Expand All @@ -290,24 +255,10 @@ internal TrapException(string message, IReadOnlyList<TrapFrame>? frames, TrapCod

internal static TrapException FromOwnedTrap(IntPtr trap, bool delete = true)
{
// Get the cause of the trap if available (in case the trap was caused by a
// .NET exception thrown in a callback).
var callbackTrapCause = Function.CallbackTrapCause;

if (callbackTrapCause is not null)
{
// Clear the field as we consumed the value.
Function.CallbackTrapCause = null;
}

var accessor = new TrapAccessor(trap);
try
{
var trappedException = new TrapException(accessor.Message, accessor.GetFrames(), accessor.TrapCode, callbackTrapCause)
{
ExitCode = accessor.ExitStatus
};

var trappedException = new TrapException(accessor.Message, accessor.GetFrames(), accessor.TrapCode);
return trappedException;
}
finally
Expand All @@ -317,12 +268,27 @@ internal static TrapException FromOwnedTrap(IntPtr trap, bool delete = true)
}
}

internal static class Native
internal static List<TrapFrame> GetFrames(Native.FrameArray frames)
{
int framesSize = checked((int)frames.size);
var trapFrames = new List<TrapFrame>(framesSize);
for (var i = 0; i < framesSize; ++i)
{
unsafe
{
trapFrames.Add(new TrapFrame(frames.data[i]));
}
}

return trapFrames;
}

internal new static class Native
{
[StructLayout(LayoutKind.Sequential)]
public unsafe struct FrameArray : IDisposable
{
public UIntPtr size;
public nuint size;
public IntPtr* data;

public void Dispose()
Expand All @@ -335,7 +301,7 @@ public void Dispose()
public static extern void wasm_trap_message(IntPtr trap, out ByteArray message);

[DllImport(Engine.LibraryName)]
public static extern void wasm_trap_trace(IntPtr trap, out FrameArray message);
public static extern void wasm_trap_trace(IntPtr trap, out FrameArray frames);

[DllImport(Engine.LibraryName)]
public static extern void wasm_trap_delete(IntPtr trap);
Expand All @@ -345,11 +311,7 @@ public void Dispose()

[DllImport(Engine.LibraryName)]
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool wasmtime_trap_exit_status(IntPtr trap, out int exitStatus);

[DllImport(Engine.LibraryName)]
[return: MarshalAs(UnmanagedType.I1)]
internal static extern bool wasmtime_trap_code(IntPtr trap, out TrapCode exitCode);
internal static extern bool wasmtime_trap_code(IntPtr trap, out byte exitCode);
}
}
}
Loading