Forráskód Böngészése

LibWeb: Port WebAssembly.Table to IDL

Timothy Flynn 2 éve
szülő
commit
2cfcbccdb5

+ 1 - 0
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,

+ 0 - 17
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"~~~(
 }
 )~~~");

+ 1 - 3
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

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

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

+ 3 - 3
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);
                 }
 

+ 144 - 0
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();
+}
+
+}

+ 50 - 0
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;
+};
+
+}

+ 23 - 0
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;
+};

+ 5 - 5
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 {};
                 },

+ 1 - 2
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;

+ 0 - 94
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.cpp

@@ -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 {};
-}
-
-}

+ 0 - 28
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableConstructor.h

@@ -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; }
-};
-
-}

+ 0 - 19
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.cpp

@@ -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)
-{
-}
-
-}

+ 0 - 29
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTableObject.h

@@ -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;
-};
-
-}

+ 0 - 123
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.cpp

@@ -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());
-}
-
-}

+ 0 - 34
Userland/Libraries/LibWeb/WebAssembly/WebAssemblyTablePrototype.h

@@ -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);
-};
-
-}

+ 1 - 0
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)