LibWeb: Port WebAssembly.Table to IDL

This commit is contained in:
Timothy Flynn 2023-03-15 20:16:22 -04:00 committed by Andreas Kling
parent ca96f8e364
commit 2cfcbccdb5
Notes: sideshowbarker 2024-07-17 03:35:16 +09:00
17 changed files with 230 additions and 357 deletions

View File

@ -48,6 +48,7 @@ static bool is_platform_object(Type const& type)
"ReadableStream"sv,
"Request"sv,
"Selection"sv,
"Table"sv,
"Text"sv,
"TextMetrics"sv,
"URLSearchParams"sv,

View File

@ -100,12 +100,6 @@ class @legacy_constructor_class@;)~~~");
add_interface(gen, interface.prototype_class, interface.constructor_class, lookup_legacy_constructor(interface));
}
// FIXME: Special case WebAssembly. We should convert WASM to use IDL.
{
auto gen = generator.fork();
add_interface(gen, "WebAssemblyTablePrototype"sv, "WebAssemblyTableConstructor"sv, {});
}
generator.append(R"~~~(
}
@ -150,11 +144,6 @@ static ErrorOr<void> generate_intrinsic_definitions(StringView output_path, Vect
}
}
// FIXME: Special case WebAssembly. We should convert WASM to use IDL.
generator.append(R"~~~(
#include <LibWeb/WebAssembly/WebAssemblyTableConstructor.h>
#include <LibWeb/WebAssembly/WebAssemblyTablePrototype.h>)~~~");
generator.append(R"~~~(
namespace Web::Bindings {
@ -219,12 +208,6 @@ void Intrinsics::create_web_prototype_and_constructor<@prototype_class@>(JS::Rea
add_interface(gen, interface.namespaced_name, interface.prototype_class, interface.constructor_class, lookup_legacy_constructor(interface));
}
// FIXME: Special case WebAssembly. We should convert WASM to use IDL.
{
auto gen = generator.fork();
add_interface(gen, "WebAssembly.Table"sv, "WebAssemblyTablePrototype"sv, "WebAssemblyTableConstructor"sv, {});
}
generator.append(R"~~~(
}
)~~~");

View File

@ -445,10 +445,8 @@ set(SOURCES
WebAssembly/Instance.cpp
WebAssembly/Memory.cpp
WebAssembly/Module.cpp
WebAssembly/Table.cpp
WebAssembly/WebAssemblyObject.cpp
WebAssembly/WebAssemblyTableConstructor.cpp
WebAssembly/WebAssemblyTableObject.cpp
WebAssembly/WebAssemblyTablePrototype.cpp
WebDriver/Capabilities.cpp
WebDriver/Client.cpp
WebDriver/ElementLocationStrategies.cpp

View File

@ -485,6 +485,7 @@ namespace Web::WebAssembly {
class Instance;
class Memory;
class Module;
class Table;
}
namespace Web::WebGL {

View File

@ -15,8 +15,8 @@
#include <LibWeb/WebAssembly/Instance.h>
#include <LibWeb/WebAssembly/Memory.h>
#include <LibWeb/WebAssembly/Module.h>
#include <LibWeb/WebAssembly/Table.h>
#include <LibWeb/WebAssembly/WebAssemblyObject.h>
#include <LibWeb/WebAssembly/WebAssemblyTableObject.h>
namespace Web::WebAssembly {
@ -71,9 +71,9 @@ JS::ThrowCompletionOr<void> Instance::initialize(JS::Realm& realm)
return {};
},
[&](Wasm::TableAddress const& address) -> JS::ThrowCompletionOr<void> {
Optional<JS::GCPtr<Bindings::WebAssemblyTableObject>> object = cache.table_instances.get(address);
Optional<JS::GCPtr<Table>> object = cache.table_instances.get(address);
if (!object.has_value()) {
object = MUST_OR_THROW_OOM(heap().allocate<Web::Bindings::WebAssemblyTableObject>(realm, realm, address));
object = MUST_OR_THROW_OOM(heap().allocate<Table>(realm, realm, address));
cache.table_instances.set(address, *object);
}

View File

@ -0,0 +1,144 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Realm.h>
#include <LibJS/Runtime/VM.h>
#include <LibWasm/Types.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/WebAssembly/Table.h>
#include <LibWeb/WebAssembly/WebAssemblyObject.h>
namespace Web::WebAssembly {
static Wasm::ValueType table_kind_to_value_type(Bindings::TableKind kind)
{
switch (kind) {
case Bindings::TableKind::Externref:
return Wasm::ValueType { Wasm::ValueType::ExternReference };
case Bindings::TableKind::Anyfunc:
return Wasm::ValueType { Wasm::ValueType::FunctionReference };
}
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())
return Wasm::Value(reference_type, 0ull);
return Bindings::to_webassembly_value(vm, value, reference_type);
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<Table>> Table::construct_impl(JS::Realm& realm, TableDescriptor& descriptor, JS::Value value)
{
auto& vm = realm.vm();
auto reference_type = table_kind_to_value_type(descriptor.element);
auto reference_value = TRY(value_to_reference(vm, value, reference_type));
Wasm::Limits limits { descriptor.initial, move(descriptor.maximum) };
Wasm::TableType table_type { reference_type, move(limits) };
auto address = Bindings::WebAssemblyObject::s_abstract_machine.store().allocate(table_type);
if (!address.has_value())
return vm.throw_completion<JS::TypeError>("Wasm Table allocation failed"sv);
auto const& reference = reference_value.value().get<Wasm::Reference>();
auto& table = *Bindings::WebAssemblyObject::s_abstract_machine.store().get(*address);
for (auto& element : table.elements())
element = reference;
return MUST_OR_THROW_OOM(vm.heap().allocate<Table>(realm, realm, *address));
}
Table::Table(JS::Realm& realm, Wasm::TableAddress address)
: Bindings::PlatformObject(realm)
, m_address(address)
{
}
JS::ThrowCompletionOr<void> Table::initialize(JS::Realm& realm)
{
MUST_OR_THROW_OOM(Base::initialize(realm));
set_prototype(&Bindings::ensure_web_prototype<Bindings::TablePrototype>(realm, "WebAssembly.Table"sv));
return {};
}
// https://webassembly.github.io/spec/js-api/#dom-table-grow
WebIDL::ExceptionOr<u32> Table::grow(u32 delta, JS::Value value)
{
auto& vm = this->vm();
auto* table = Bindings::WebAssemblyObject::s_abstract_machine.store().get(address());
if (!table)
return vm.throw_completion<JS::RangeError>("Could not find the memory table to grow"sv);
auto initial_size = table->elements().size();
auto reference_value = TRY(value_to_reference(vm, value, table->type().element_type()));
auto const& reference = reference_value.value().get<Wasm::Reference>();
if (!table->grow(delta, reference))
return vm.throw_completion<JS::RangeError>("Failed to grow table"sv);
return initial_size;
}
// https://webassembly.github.io/spec/js-api/#dom-table-get
WebIDL::ExceptionOr<JS::Value> Table::get(u32 index) const
{
auto& vm = this->vm();
auto* table = Bindings::WebAssemblyObject::s_abstract_machine.store().get(address());
if (!table)
return vm.throw_completion<JS::RangeError>("Could not find the memory table"sv);
if (table->elements().size() <= index)
return vm.throw_completion<JS::RangeError>("Table element index out of range"sv);
auto& ref = table->elements()[index];
if (!ref.has_value())
return JS::js_undefined();
Wasm::Value wasm_value { ref.value() };
return Bindings::to_js_value(vm, wasm_value);
}
// https://webassembly.github.io/spec/js-api/#dom-table-set
WebIDL::ExceptionOr<void> Table::set(u32 index, JS::Value value)
{
auto& vm = this->vm();
auto* table = Bindings::WebAssemblyObject::s_abstract_machine.store().get(address());
if (!table)
return vm.throw_completion<JS::RangeError>("Could not find the memory table"sv);
if (table->elements().size() <= index)
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 const& reference = reference_value.value().get<Wasm::Reference>();
table->elements()[index] = reference;
return {};
}
// https://webassembly.github.io/spec/js-api/#dom-table-length
WebIDL::ExceptionOr<u32> Table::length() const
{
auto& vm = this->vm();
auto* table = Bindings::WebAssemblyObject::s_abstract_machine.store().get(address());
if (!table)
return vm.throw_completion<JS::RangeError>("Could not find the memory table"sv);
return table->elements().size();
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
* Copyright (c) 2023, Tim Flynn <trflynn89@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/Optional.h>
#include <LibJS/Forward.h>
#include <LibJS/Heap/GCPtr.h>
#include <LibJS/Runtime/Value.h>
#include <LibWasm/AbstractMachine/AbstractMachine.h>
#include <LibWeb/Bindings/ExceptionOrUtils.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/Bindings/TablePrototype.h>
namespace Web::WebAssembly {
struct TableDescriptor {
Bindings::TableKind element;
u32 initial { 0 };
Optional<u32> maximum;
};
class Table : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(Table, Bindings::PlatformObject);
public:
static WebIDL::ExceptionOr<JS::NonnullGCPtr<Table>> construct_impl(JS::Realm&, TableDescriptor& descriptor, JS::Value value);
WebIDL::ExceptionOr<u32> grow(u32 delta, JS::Value value);
WebIDL::ExceptionOr<JS::Value> get(u32 index) const;
WebIDL::ExceptionOr<void> set(u32 index, JS::Value value);
WebIDL::ExceptionOr<u32> length() const;
Wasm::TableAddress address() const { return m_address; }
private:
Table(JS::Realm&, Wasm::TableAddress);
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
Wasm::TableAddress m_address;
};
}

View File

@ -0,0 +1,23 @@
enum TableKind {
"externref",
"anyfunc"
};
dictionary TableDescriptor {
required TableKind element;
required [EnforceRange] unsigned long initial;
[EnforceRange] unsigned long maximum;
};
// https://webassembly.github.io/spec/js-api/#tables
[LegacyNamespace=WebAssembly, Exposed=*]
interface Table {
constructor(TableDescriptor descriptor, optional any value);
unsigned long grow([EnforceRange] unsigned long delta, optional any value);
any get([EnforceRange] unsigned long index);
undefined set([EnforceRange] unsigned long index, optional any value);
readonly attribute unsigned long length;
};

View File

@ -4,8 +4,6 @@
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "WebAssemblyTableObject.h"
#include "WebAssemblyTablePrototype.h"
#include <AK/MemoryStream.h>
#include <AK/ScopeGuard.h>
#include <LibJS/Runtime/Array.h>
@ -21,9 +19,11 @@
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MemoryPrototype.h>
#include <LibWeb/Bindings/ModulePrototype.h>
#include <LibWeb/Bindings/TablePrototype.h>
#include <LibWeb/WebAssembly/Instance.h>
#include <LibWeb/WebAssembly/Memory.h>
#include <LibWeb/WebAssembly/Module.h>
#include <LibWeb/WebAssembly/Table.h>
#include <LibWeb/WebAssembly/WebAssemblyObject.h>
namespace Web::Bindings {
@ -52,7 +52,7 @@ JS::ThrowCompletionOr<void> WebAssemblyObject::initialize(JS::Realm& realm)
auto& module_constructor = Bindings::ensure_web_constructor<ModulePrototype>(realm, "WebAssembly.Module"sv);
define_direct_property("Module", &module_constructor, JS::Attribute::Writable | JS::Attribute::Configurable);
auto& table_constructor = Bindings::ensure_web_constructor<WebAssemblyTablePrototype>(realm, "WebAssembly.Table"sv);
auto& table_constructor = Bindings::ensure_web_constructor<TablePrototype>(realm, "WebAssembly.Table"sv);
define_direct_property("Table", &table_constructor, JS::Attribute::Writable | JS::Attribute::Configurable);
return {};
@ -272,11 +272,11 @@ JS::ThrowCompletionOr<size_t> WebAssemblyObject::instantiate_module(JS::VM& vm,
return {};
},
[&](Wasm::TableType const&) -> JS::ThrowCompletionOr<void> {
if (!import_.is_object() || !is<WebAssemblyTableObject>(import_.as_object())) {
if (!import_.is_object() || !is<WebAssembly::Table>(import_.as_object())) {
// FIXME: Throw a LinkError instead
return vm.throw_completion<JS::TypeError>("LinkError: Expected an instance of WebAssembly.Table for a table import"sv);
}
auto address = static_cast<WebAssemblyTableObject const&>(import_.as_object()).address();
auto address = static_cast<WebAssembly::Table const&>(import_.as_object()).address();
resolved_imports.set(import_name, Wasm::ExternValue { address });
return {};
},

View File

@ -12,7 +12,6 @@
namespace Web::Bindings {
class WebAssemblyTableObject;
JS::ThrowCompletionOr<size_t> parse_module(JS::VM&, JS::Object* buffer);
JS::NativeFunction* create_native_function(JS::VM&, Wasm::FunctionAddress address, DeprecatedString const& name);
JS::Value to_js_value(JS::VM&, Wasm::Value& wasm_value);
@ -46,7 +45,7 @@ public:
struct ModuleCache {
HashMap<Wasm::FunctionAddress, JS::GCPtr<JS::FunctionObject>> function_instances;
HashMap<Wasm::MemoryAddress, JS::GCPtr<WebAssembly::Memory>> memory_instances;
HashMap<Wasm::TableAddress, JS::GCPtr<WebAssemblyTableObject>> table_instances;
HashMap<Wasm::TableAddress, JS::GCPtr<WebAssembly::Table>> table_instances;
};
struct GlobalModuleCache {
HashMap<Wasm::FunctionAddress, JS::GCPtr<JS::NativeFunction>> function_instances;

View File

@ -1,94 +0,0 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/GlobalObject.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/WebAssembly/WebAssemblyObject.h>
#include <LibWeb/WebAssembly/WebAssemblyTableConstructor.h>
#include <LibWeb/WebAssembly/WebAssemblyTableObject.h>
#include <LibWeb/WebAssembly/WebAssemblyTablePrototype.h>
namespace Web::Bindings {
WebAssemblyTableConstructor::WebAssemblyTableConstructor(JS::Realm& realm)
: NativeFunction(*realm.intrinsics().function_prototype())
{
}
WebAssemblyTableConstructor::~WebAssemblyTableConstructor() = default;
JS::ThrowCompletionOr<JS::Value> WebAssemblyTableConstructor::call()
{
return vm().throw_completion<JS::TypeError>(JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table");
}
JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> WebAssemblyTableConstructor::construct(FunctionObject&)
{
auto& vm = this->vm();
auto& realm = *vm.current_realm();
auto descriptor = TRY(vm.argument(0).to_object(vm));
auto element_value = TRY(descriptor->get("element"));
if (!element_value.is_string())
return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidHint, TRY_OR_THROW_OOM(vm, element_value.to_string_without_side_effects()));
auto element = TRY(element_value.as_string().deprecated_string());
Optional<Wasm::ValueType> reference_type;
if (element == "anyfunc"sv)
reference_type = Wasm::ValueType(Wasm::ValueType::FunctionReference);
else if (element == "externref"sv)
reference_type = Wasm::ValueType(Wasm::ValueType::ExternReference);
if (!reference_type.has_value())
return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidHint, element);
auto initial_value = TRY(descriptor->get("initial"));
auto maximum_value = TRY(descriptor->get("maximum"));
auto initial = TRY(initial_value.to_u32(vm));
Optional<u32> maximum;
if (!maximum_value.is_undefined())
maximum = TRY(maximum_value.to_u32(vm));
if (maximum.has_value() && maximum.value() < initial)
return vm.throw_completion<JS::RangeError>("maximum should be larger than or equal to initial"sv);
auto value_value = TRY(descriptor->get("value"));
auto reference_value = TRY([&]() -> JS::ThrowCompletionOr<Wasm::Value> {
if (value_value.is_undefined())
return Wasm::Value(*reference_type, 0ull);
return to_webassembly_value(vm, value_value, *reference_type);
}());
auto& reference = reference_value.value().get<Wasm::Reference>();
auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::TableType { *reference_type, Wasm::Limits { initial, maximum } });
if (!address.has_value())
return vm.throw_completion<JS::TypeError>("Wasm Table allocation failed"sv);
auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address);
for (auto& element : table.elements())
element = reference;
return MUST_OR_THROW_OOM(vm.heap().allocate<WebAssemblyTableObject>(realm, realm, *address));
}
JS::ThrowCompletionOr<void> WebAssemblyTableConstructor::initialize(JS::Realm& realm)
{
auto& vm = this->vm();
MUST_OR_THROW_OOM(NativeFunction::initialize(realm));
define_direct_property(vm.names.prototype, &Bindings::ensure_web_prototype<WebAssemblyTablePrototype>(realm, "WebAssembly.Table"), 0);
define_direct_property(vm.names.length, JS::Value(1), JS::Attribute::Configurable);
return {};
}
}

View File

@ -1,28 +0,0 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/NativeFunction.h>
namespace Web::Bindings {
class WebAssemblyTableConstructor : public JS::NativeFunction {
JS_OBJECT(WebAssemblyTableConstructor, JS::NativeFunction);
public:
explicit WebAssemblyTableConstructor(JS::Realm&);
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
virtual ~WebAssemblyTableConstructor() override;
virtual JS::ThrowCompletionOr<JS::Value> call() override;
virtual JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> construct(JS::FunctionObject& new_target) override;
private:
virtual bool has_constructor() const override { return true; }
};
}

View File

@ -1,19 +0,0 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "WebAssemblyTablePrototype.h"
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/WebAssembly/WebAssemblyTableObject.h>
namespace Web::Bindings {
WebAssemblyTableObject::WebAssemblyTableObject(JS::Realm& realm, Wasm::TableAddress address)
: Object(ConstructWithPrototypeTag::Tag, Bindings::ensure_web_prototype<WebAssemblyTablePrototype>(realm, "WebAssembly.Table"))
, m_address(address)
{
}
}

View File

@ -1,29 +0,0 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibJS/Runtime/Object.h>
#include <LibWasm/AbstractMachine/AbstractMachine.h>
#include <LibWeb/Forward.h>
#include <LibWeb/WebAssembly/WebAssemblyObject.h>
namespace Web::Bindings {
class WebAssemblyTableObject final : public JS::Object {
JS_OBJECT(WebAssemblyTableObject, Object);
public:
WebAssemblyTableObject(JS::Realm&, Wasm::TableAddress);
virtual ~WebAssemblyTableObject() override = default;
Wasm::TableAddress address() const { return m_address; }
private:
Wasm::TableAddress m_address;
};
}

View File

@ -1,123 +0,0 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <AK/TypeCasts.h>
#include <LibJS/Runtime/TypedArray.h>
#include <LibWeb/WebAssembly/WebAssemblyTableObject.h>
#include <LibWeb/WebAssembly/WebAssemblyTablePrototype.h>
namespace Web::Bindings {
JS::ThrowCompletionOr<void> WebAssemblyTablePrototype::initialize(JS::Realm& realm)
{
MUST_OR_THROW_OOM(Object::initialize(realm));
define_native_accessor(realm, "length", length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_function(realm, "grow", grow, 1, JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_function(realm, "get", get, 1, JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable);
define_native_function(realm, "set", set, 1, JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable);
return {};
}
JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::grow)
{
auto delta = TRY(vm.argument(0).to_u32(vm));
auto* this_object = TRY(vm.this_value().to_object(vm));
if (!is<WebAssemblyTableObject>(this_object))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "WebAssembly.Table");
auto* table_object = static_cast<WebAssemblyTableObject*>(this_object);
auto address = table_object->address();
auto* table = WebAssemblyObject::s_abstract_machine.store().get(address);
if (!table)
return JS::js_undefined();
auto initial_size = table->elements().size();
auto value_value = vm.argument(1);
auto reference_value = TRY([&]() -> JS::ThrowCompletionOr<Wasm::Value> {
if (value_value.is_undefined())
return Wasm::Value(table->type().element_type(), 0ull);
return to_webassembly_value(vm, value_value, table->type().element_type());
}());
auto& reference = reference_value.value().get<Wasm::Reference>();
if (!table->grow(delta, reference))
return vm.throw_completion<JS::RangeError>("Failed to grow table"sv);
return JS::Value(static_cast<u32>(initial_size));
}
JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::get)
{
auto index = TRY(vm.argument(0).to_u32(vm));
auto* this_object = TRY(vm.this_value().to_object(vm));
if (!is<WebAssemblyTableObject>(this_object))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "WebAssembly.Table");
auto* table_object = static_cast<WebAssemblyTableObject*>(this_object);
auto address = table_object->address();
auto* table = WebAssemblyObject::s_abstract_machine.store().get(address);
if (!table)
return JS::js_undefined();
if (table->elements().size() <= index)
return vm.throw_completion<JS::RangeError>("Table element index out of range"sv);
auto& ref = table->elements()[index];
if (!ref.has_value())
return JS::js_undefined();
Wasm::Value wasm_value { ref.value() };
return to_js_value(vm, wasm_value);
}
JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::set)
{
auto index = TRY(vm.argument(0).to_u32(vm));
auto* this_object = TRY(vm.this_value().to_object(vm));
if (!is<WebAssemblyTableObject>(this_object))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "WebAssembly.Table");
auto* table_object = static_cast<WebAssemblyTableObject*>(this_object);
auto address = table_object->address();
auto* table = WebAssemblyObject::s_abstract_machine.store().get(address);
if (!table)
return JS::js_undefined();
if (table->elements().size() <= index)
return vm.throw_completion<JS::RangeError>("Table element index out of range"sv);
auto value_value = vm.argument(1);
auto reference_value = TRY([&]() -> JS::ThrowCompletionOr<Wasm::Value> {
if (value_value.is_undefined())
return Wasm::Value(table->type().element_type(), 0ull);
return to_webassembly_value(vm, value_value, table->type().element_type());
}());
auto& reference = reference_value.value().get<Wasm::Reference>();
table->elements()[index] = reference;
return JS::js_undefined();
}
JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::length_getter)
{
auto* this_object = TRY(vm.this_value().to_object(vm));
if (!is<WebAssemblyTableObject>(this_object))
return vm.throw_completion<JS::TypeError>(JS::ErrorType::NotAnObjectOfType, "WebAssembly.Table");
auto* table_object = static_cast<WebAssemblyTableObject*>(this_object);
auto address = table_object->address();
auto* table = WebAssemblyObject::s_abstract_machine.store().get(address);
if (!table)
return JS::js_undefined();
return JS::Value(table->elements().size());
}
}

View File

@ -1,34 +0,0 @@
/*
* Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include "WebAssemblyTableConstructor.h"
#include <LibJS/Runtime/Object.h>
#include <LibJS/Runtime/VM.h>
#include <LibWeb/Forward.h>
namespace Web::Bindings {
class WebAssemblyTablePrototype final : public JS::Object {
JS_OBJECT(WebAssemblyTablePrototype, JS::Object);
public:
explicit WebAssemblyTablePrototype(JS::Realm& realm)
: JS::Object(ConstructWithPrototypeTag::Tag, *realm.intrinsics().object_prototype())
{
}
virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
private:
JS_DECLARE_NATIVE_FUNCTION(grow);
JS_DECLARE_NATIVE_FUNCTION(get);
JS_DECLARE_NATIVE_FUNCTION(set);
JS_DECLARE_NATIVE_FUNCTION(length_getter);
};
}

View File

@ -203,6 +203,7 @@ libweb_js_bindings(URL/URLSearchParams ITERABLE)
libweb_js_bindings(WebAssembly/Instance)
libweb_js_bindings(WebAssembly/Memory)
libweb_js_bindings(WebAssembly/Module)
libweb_js_bindings(WebAssembly/Table)
libweb_js_bindings(WebGL/WebGLContextEvent)
libweb_js_bindings(WebGL/WebGLRenderingContext)
libweb_js_bindings(WebIDL/DOMException)