mirror of
https://github.com/RGBCube/serenity
synced 2025-05-14 08:54:58 +00:00
LibWeb: Port WebAssembly.Table to IDL
This commit is contained in:
parent
ca96f8e364
commit
2cfcbccdb5
17 changed files with 230 additions and 357 deletions
|
@ -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,
|
||||
|
|
|
@ -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"~~~(
|
||||
}
|
||||
)~~~");
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -485,6 +485,7 @@ namespace Web::WebAssembly {
|
|||
class Instance;
|
||||
class Memory;
|
||||
class Module;
|
||||
class Table;
|
||||
}
|
||||
|
||||
namespace Web::WebGL {
|
||||
|
|
|
@ -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
Userland/Libraries/LibWeb/WebAssembly/Table.cpp
Normal file
144
Userland/Libraries/LibWeb/WebAssembly/Table.cpp
Normal 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();
|
||||
}
|
||||
|
||||
}
|
50
Userland/Libraries/LibWeb/WebAssembly/Table.h
Normal file
50
Userland/Libraries/LibWeb/WebAssembly/Table.h
Normal 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;
|
||||
};
|
||||
|
||||
}
|
23
Userland/Libraries/LibWeb/WebAssembly/Table.idl
Normal file
23
Userland/Libraries/LibWeb/WebAssembly/Table.idl
Normal 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;
|
||||
};
|
|
@ -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 {};
|
||||
},
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {};
|
||||
}
|
||||
|
||||
}
|
|
@ -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; }
|
||||
};
|
||||
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue