1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
/**
* \file wasmtime/exn.h
*
* \brief Wasmtime APIs for WebAssembly exception objects.
*
* Exception objects carry a tag and a set of field values. They are
* allocated on the GC heap within a store.
*
* ## Throwing from host functions
*
* To throw an exception from a host function implemented via the C API:
*
* 1. Create an exception object with #wasmtime_exn_new.
* 2. Set it as the pending exception with #wasmtime_context_set_exception.
* 3. Return a trap from the host callback (e.g. via `wasmtime_trap_new`).
*
* The runtime will propagate the exception through WebAssembly
* `try_table`/`catch` blocks.
*
* ## Catching exceptions from Wasm
*
* When a call to a WebAssembly function (e.g. via #wasmtime_func_call)
* returns a trap, check for a pending exception:
*
* 1. Call #wasmtime_context_has_exception or #wasmtime_context_take_exception.
* 2. If present, examine the exception's tag and fields.
*/
#ifndef WASMTIME_EXN_H
#define WASMTIME_EXN_H
#include <wasmtime/conf.h>
#ifdef WASMTIME_FEATURE_GC
#include <wasm.h>
#include <wasmtime/error.h>
#include <wasmtime/store.h>
#include <wasmtime/tag.h>
#include <wasmtime/val.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* \typedef wasmtime_exn_t
* \brief An opaque type representing a WebAssembly exception object.
*
* Exception objects are allocated on the GC heap and referenced through
* this handle. The handle is owned by the caller and must be freed
* with #wasmtime_exn_delete.
*/
typedef struct wasmtime_exn wasmtime_exn_t;
/**
* \brief Deletes a #wasmtime_exn_t.
*/
WASM_API_EXTERN void wasmtime_exn_delete(wasmtime_exn_t *exn);
/**
* \brief Creates a new exception object.
*
* \param store the store context
* \param tag the tag to associate with this exception
* \param fields pointer to an array of field values matching the tag's
* payload signature
* \param nfields the number of elements in `fields`
* \param exn_ret on success, set to the newly allocated exception.
* The caller owns the returned pointer and must free it with
* #wasmtime_exn_delete.
*
* \return NULL on success, or an error on failure.
*/
WASM_API_EXTERN wasmtime_error_t *wasmtime_exn_new(wasmtime_context_t *store,
const wasmtime_tag_t *tag,
const wasmtime_val_t *fields,
size_t nfields,
wasmtime_exn_t **exn_ret);
/**
* \brief Returns the tag associated with this exception.
*
* \param store the store context
* \param exn the exception to query
* \param tag_ret on success, filled with the exception's tag
*
* \return NULL on success, or an error on failure.
*/
WASM_API_EXTERN wasmtime_error_t *wasmtime_exn_tag(wasmtime_context_t *store,
const wasmtime_exn_t *exn,
wasmtime_tag_t *tag_ret);
/**
* \brief Returns the number of fields in this exception.
*
* \param store the store context
* \param exn the exception to query
*/
WASM_API_EXTERN size_t wasmtime_exn_field_count(wasmtime_context_t *store,
const wasmtime_exn_t *exn);
/**
* \brief Reads a field value from this exception by index.
*
* \param store the store context
* \param exn the exception to query
* \param index the field index (0-based)
* \param val_ret on success, filled with the field value
* (caller-owned on return).
*
* \return NULL on success, or an error if the index is out of bounds.
*/
WASM_API_EXTERN wasmtime_error_t *wasmtime_exn_field(wasmtime_context_t *store,
const wasmtime_exn_t *exn,
size_t index,
wasmtime_val_t *val_ret);
/**
* \brief Sets the pending exception on the store and returns a trap.
*
* This transfers ownership of `exn` to the store. After this call,
* the caller must not use or free `exn`.
*
* Returns a `wasm_trap_t` that the host callback MUST return to signal
* to the Wasm runtime that an exception was thrown. The caller owns
* the returned trap.
*
* \param store the store context
* \param exn the exception to throw (ownership transferred)
* \return a trap to return from the host callback (caller-owned)
*/
WASM_API_EXTERN wasm_trap_t *
wasmtime_context_set_exception(wasmtime_context_t *store, wasmtime_exn_t *exn);
/**
* \brief Takes the pending exception from the store, if any.
*
* If there is a pending exception, removes it from the store and
* returns it. The caller owns the returned pointer and must free it
* with #wasmtime_exn_delete.
*
* \param store the store context
* \param exn_ret on success, set to the exception (caller-owned)
*
* \return true if there was a pending exception, false otherwise.
*/
WASM_API_EXTERN bool wasmtime_context_take_exception(wasmtime_context_t *store,
wasmtime_exn_t **exn_ret);
/**
* \brief Tests whether there is a pending exception on the store.
*
* \param store the store context
*
* \return true if a pending exception is set, false otherwise.
*/
WASM_API_EXTERN bool wasmtime_context_has_exception(wasmtime_context_t *store);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // WASMTIME_FEATURE_GC
#endif // WASMTIME_EXN_H