Open
Description
#139580 adds the ability to test whether an externref
is null or not. This can
be used for in-band error signalling, but it can lead to trouble because some
JavaScript functions care about the difference between null and undefined, and
if we use null to signal errors we can't handle a real null value. There are
several possible solutions:
- Change my functions that return an
__externref_t
to__externref_t f(int *status, <other args>);
(This doesn't require any change to clang.) - Somehow let clang deal with functions with multiple return values and give it
a pair of return values anexternref
and a statusi32
- Similarly to 2, make the return value a single wasm-gc struct that's a pair
- Use a struct with no fields as a sentinel
This fourth case could look like:
if (error_condition) {
return __builtin_wasm_ref_sentinel_extern();
}
and then check like:
__externref_t res = some_func();
if (__builtin_wasm_ref_is_sentinel_extern(res)) {
// handle the error
}
// Otherwise it represents an actual JS value.
We would have a type like
(type $sentinel (struct)) ;; 0x5f, 0x00
Then __builtin_wasm_ref_sentinel_extern()
would translate to:
struct.new $sentinel ;; 0xfb, 0x00, <type index of $sentinel>
extern.convert_any ;; 0xfb, 27
and __builtin_wasm_ref_is_sentinel_extern()
would translate to:
any.convert_extern ;; 0xfb, 26
ref.test $sentinel ;; 0xfb, 20, <type index of $sentinel>
If we needed to, we could make a second one-value type with:
(type $sentinel1 (struct (ref null noextern)))
and similarly by adding more (ref null noextern)
fields we could make as many distinct
struct-based singleton "sentinel" types as we want.