mirror of
https://github.com/LadybirdBrowser/ladybird
synced 2026-04-30 11:37:16 +02:00
LibWeb+LibWasm: Implement and use the "reset the Memory buffer" steps
This implements the memory object cache and its "reset on grow" semantics, as the web depends on the exact behaviour.
This commit is contained in:
committed by
Andreas Kling
parent
14fb6372c3
commit
64da05a96d
Notes:
sideshowbarker
2024-07-17 07:08:37 +09:00
Author: https://github.com/alimpfard Commit: https://github.com/SerenityOS/serenity/commit/64da05a96d Pull-request: https://github.com/SerenityOS/serenity/pull/18079
@@ -25,7 +25,12 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<Memory>> Memory::construct_impl(JS::Realm&
|
||||
if (!address.has_value())
|
||||
return vm.throw_completion<JS::TypeError>("Wasm Memory allocation failed"sv);
|
||||
|
||||
return MUST_OR_THROW_OOM(vm.heap().allocate<Memory>(realm, realm, *address));
|
||||
auto memory_object = MUST_OR_THROW_OOM(vm.heap().allocate<Memory>(realm, realm, *address));
|
||||
Detail::s_abstract_machine.store().get(*address)->successful_grow_hook = [memory_object] {
|
||||
MUST(memory_object->reset_the_memory_buffer());
|
||||
};
|
||||
|
||||
return memory_object;
|
||||
}
|
||||
|
||||
Memory::Memory(JS::Realm& realm, Wasm::MemoryAddress address)
|
||||
@@ -52,26 +57,54 @@ WebIDL::ExceptionOr<u32> Memory::grow(u32 delta)
|
||||
return vm.throw_completion<JS::RangeError>("Could not find the memory instance to grow"sv);
|
||||
|
||||
auto previous_size = memory->size() / Wasm::Constants::page_size;
|
||||
if (!memory->grow(delta * Wasm::Constants::page_size))
|
||||
if (!memory->grow(delta * Wasm::Constants::page_size, Wasm::MemoryInstance::InhibitGrowCallback::Yes))
|
||||
return vm.throw_completion<JS::RangeError>("Memory.grow() grows past the stated limit of the memory instance"sv);
|
||||
|
||||
TRY(reset_the_memory_buffer());
|
||||
|
||||
return previous_size;
|
||||
}
|
||||
|
||||
// https://webassembly.github.io/spec/js-api/#reset-the-memory-buffer
|
||||
WebIDL::ExceptionOr<void> Memory::reset_the_memory_buffer()
|
||||
{
|
||||
if (!m_buffer)
|
||||
return {};
|
||||
|
||||
auto& vm = this->vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
MUST(JS::detach_array_buffer(vm, *m_buffer, MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm, "WebAssembly.Memory"sv))));
|
||||
|
||||
auto buffer = TRY(create_a_memory_buffer(vm, realm, m_address));
|
||||
m_buffer = buffer;
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
// https://webassembly.github.io/spec/js-api/#dom-memory-buffer
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> Memory::buffer() const
|
||||
{
|
||||
auto& vm = this->vm();
|
||||
auto& realm = *vm.current_realm();
|
||||
|
||||
auto* memory = Detail::s_abstract_machine.store().get(address());
|
||||
if (!m_buffer)
|
||||
m_buffer = TRY(create_a_memory_buffer(vm, realm, m_address));
|
||||
|
||||
return JS::NonnullGCPtr(*m_buffer);
|
||||
}
|
||||
|
||||
// https://webassembly.github.io/spec/js-api/#create-a-memory-buffer
|
||||
WebIDL::ExceptionOr<JS::NonnullGCPtr<JS::ArrayBuffer>> Memory::create_a_memory_buffer(JS::VM& vm, JS::Realm& realm, Wasm::MemoryAddress address)
|
||||
{
|
||||
auto* memory = Detail::s_abstract_machine.store().get(address);
|
||||
if (!memory)
|
||||
return vm.throw_completion<JS::RangeError>("Could not find the memory instance"sv);
|
||||
|
||||
auto array_buffer = JS::ArrayBuffer::create(realm, &memory->data());
|
||||
array_buffer->set_detach_key(MUST_OR_THROW_OOM(JS::PrimitiveString::create(vm, "WebAssembly.Memory"sv)));
|
||||
|
||||
return array_buffer;
|
||||
return JS::NonnullGCPtr(*array_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user