LibWeb/WebAssembly: Change behavior of explicit undefined in tables

This commit is contained in:
Diego Frias 2024-08-17 17:02:59 -07:00 committed by Ali Mohammad Pur
commit 80434fa516
Notes: github-actions[bot] 2024-08-18 21:36:03 +00:00
3 changed files with 26 additions and 10 deletions

View file

@ -29,19 +29,14 @@ static Wasm::ValueType table_kind_to_value_type(Bindings::TableKind kind)
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
static JS::ThrowCompletionOr<Wasm::Value> value_to_reference(JS::VM& vm, JS::Value value, Wasm::ValueType const& reference_type)
{
if (value.is_undefined() && reference_type.kind() != Wasm::ValueType::Kind::ExternReference)
return Wasm::Value(reference_type);
return Detail::to_webassembly_value(vm, value, reference_type);
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<Table>> Table::construct_impl(JS::Realm& realm, TableDescriptor& descriptor, JS::Value value) WebIDL::ExceptionOr<JS::NonnullGCPtr<Table>> Table::construct_impl(JS::Realm& realm, TableDescriptor& descriptor, JS::Value value)
{ {
auto& vm = realm.vm(); auto& vm = realm.vm();
auto reference_type = table_kind_to_value_type(descriptor.element); auto reference_type = table_kind_to_value_type(descriptor.element);
auto reference_value = TRY(value_to_reference(vm, value, reference_type)); auto reference_value = vm.argument_count() == 1
? Detail::default_webassembly_value(vm, reference_type)
: TRY(Detail::to_webassembly_value(vm, value, reference_type));
Wasm::Limits limits { descriptor.initial, move(descriptor.maximum) }; Wasm::Limits limits { descriptor.initial, move(descriptor.maximum) };
Wasm::TableType table_type { reference_type, move(limits) }; Wasm::TableType table_type { reference_type, move(limits) };
@ -83,7 +78,9 @@ WebIDL::ExceptionOr<u32> Table::grow(u32 delta, JS::Value value)
auto initial_size = table->elements().size(); auto initial_size = table->elements().size();
auto reference_value = TRY(value_to_reference(vm, value, table->type().element_type())); auto reference_value = vm.argument_count() == 1
? Detail::default_webassembly_value(vm, table->type().element_type())
: TRY(Detail::to_webassembly_value(vm, value, table->type().element_type()));
auto const& reference = reference_value.to<Wasm::Reference>(); auto const& reference = reference_value.to<Wasm::Reference>();
if (!table->grow(delta, reference)) if (!table->grow(delta, reference))
@ -124,7 +121,9 @@ WebIDL::ExceptionOr<void> Table::set(u32 index, JS::Value value)
if (table->elements().size() <= index) if (table->elements().size() <= index)
return vm.throw_completion<JS::RangeError>("Table element index out of range"sv); return vm.throw_completion<JS::RangeError>("Table element index out of range"sv);
auto reference_value = TRY(value_to_reference(vm, value, table->type().element_type())); auto reference_value = vm.argument_count() == 1
? Detail::default_webassembly_value(vm, table->type().element_type())
: TRY(Detail::to_webassembly_value(vm, value, table->type().element_type()));
auto const& reference = reference_value.to<Wasm::Reference>(); auto const& reference = reference_value.to<Wasm::Reference>();
table->elements()[index] = reference; table->elements()[index] = reference;

View file

@ -455,6 +455,22 @@ JS::ThrowCompletionOr<Wasm::Value> to_webassembly_value(JS::VM& vm, JS::Value va
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
Wasm::Value default_webassembly_value(JS::VM& vm, Wasm::ValueType type)
{
switch (type.kind()) {
case Wasm::ValueType::I32:
case Wasm::ValueType::I64:
case Wasm::ValueType::F32:
case Wasm::ValueType::F64:
case Wasm::ValueType::V128:
case Wasm::ValueType::FunctionReference:
return Wasm::Value(type);
case Wasm::ValueType::ExternReference:
return MUST(to_webassembly_value(vm, JS::js_undefined(), type));
}
VERIFY_NOT_REACHED();
}
// https://webassembly.github.io/spec/js-api/#tojsvalue // https://webassembly.github.io/spec/js-api/#tojsvalue
JS::Value to_js_value(JS::VM& vm, Wasm::Value& wasm_value, Wasm::ValueType type) JS::Value to_js_value(JS::VM& vm, Wasm::Value& wasm_value, Wasm::ValueType type)
{ {

View file

@ -66,6 +66,7 @@ JS::ThrowCompletionOr<NonnullOwnPtr<Wasm::ModuleInstance>> instantiate_module(JS
JS::ThrowCompletionOr<NonnullRefPtr<CompiledWebAssemblyModule>> parse_module(JS::VM&, JS::Object* buffer); JS::ThrowCompletionOr<NonnullRefPtr<CompiledWebAssemblyModule>> parse_module(JS::VM&, JS::Object* buffer);
JS::NativeFunction* create_native_function(JS::VM&, Wasm::FunctionAddress address, ByteString const& name, Instance* instance = nullptr); JS::NativeFunction* create_native_function(JS::VM&, Wasm::FunctionAddress address, ByteString const& name, Instance* instance = nullptr);
JS::ThrowCompletionOr<Wasm::Value> to_webassembly_value(JS::VM&, JS::Value value, Wasm::ValueType const& type); JS::ThrowCompletionOr<Wasm::Value> to_webassembly_value(JS::VM&, JS::Value value, Wasm::ValueType const& type);
Wasm::Value default_webassembly_value(JS::VM&, Wasm::ValueType type);
JS::Value to_js_value(JS::VM&, Wasm::Value& wasm_value, Wasm::ValueType type); JS::Value to_js_value(JS::VM&, Wasm::Value& wasm_value, Wasm::ValueType type);
extern HashMap<JS::GCPtr<JS::Object>, WebAssemblyCache> s_caches; extern HashMap<JS::GCPtr<JS::Object>, WebAssemblyCache> s_caches;