diff options
17 files changed, 230 insertions, 357 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 1873b3dec9..234ec48c08 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -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, diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 7c57df60d6..3b41a0eff7 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -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"~~~( } )~~~"); diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 88c73c4ef3..0d9879b352 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -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 diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 17cb6592aa..d042d9ce7e 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -485,6 +485,7 @@ namespace Web::WebAssembly { class Instance; class Memory; class Module; +class Table; } namespace Web::WebGL { diff --git a/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp b/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp index 065dc08e33..bdc4828b59 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/Instance.cpp @@ -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); } diff --git a/Userland/Libraries/LibWeb/WebAssembly/Table.cpp b/Userland/Libraries/LibWeb/WebAssembly/Table.cpp new file mode 100644 index 0000000000..0a7c3b6c45 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAssembly/Table.cpp @@ -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(); +} + +} diff --git a/Userland/Libraries/LibWeb/WebAssembly/Table.h b/Userland/Libraries/LibWeb/WebAssembly/Table.h new file mode 100644 index 0000000000..2db1a03fe0 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAssembly/Table.h @@ -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; +}; + +} diff --git a/Userland/Libraries/LibWeb/WebAssembly/Table.idl b/Userland/Libraries/LibWeb/WebAssembly/Table.idl new file mode 100644 index 0000000000..8db12e0a7c --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAssembly/Table.idl @@ -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; +}; diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index 2c9a364a86..9ae7b5a66b 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -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 {}; }, diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.h index 1b5b47b7ee..bf465f56bb 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.h +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.h @@ -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; diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp deleted file mode 100644 index af31ce34d2..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp +++ /dev/null @@ -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 {}; -} - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h deleted file mode 100644 index 1d054bc982..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h +++ /dev/null @@ -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; } -}; - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp deleted file mode 100644 index 7569e1f3c7..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp +++ /dev/null @@ -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) -{ -} - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.h deleted file mode 100644 index 2592710c41..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.h +++ /dev/null @@ -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; -}; - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.cpp deleted file mode 100644 index 5301f60dcd..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.cpp +++ /dev/null @@ -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()); -} - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h deleted file mode 100644 index cda4c7fce9..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h +++ /dev/null @@ -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); -}; - -} diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index c02f24d196..1fe22bee79 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -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) |