diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 218d2b9af1..67e9274178 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -37,6 +37,7 @@ static bool is_platform_object(Type const& type) "FileList"sv, "FormData"sv, "ImageData"sv, + "Module"sv, "MutationRecord"sv, "NamedNodeMap"sv, "Node"sv, diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp index 0b9b6fa7a4..b4743a5629 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateWindowOrWorkerInterfaces.cpp @@ -105,7 +105,6 @@ class @legacy_constructor_class@;)~~~"); auto gen = generator.fork(); add_interface(gen, "WebAssemblyMemoryPrototype"sv, "WebAssemblyMemoryConstructor"sv, {}); add_interface(gen, "WebAssemblyInstancePrototype"sv, "WebAssemblyInstanceConstructor"sv, {}); - add_interface(gen, "WebAssemblyModulePrototype"sv, "WebAssemblyModuleConstructor"sv, {}); add_interface(gen, "WebAssemblyTablePrototype"sv, "WebAssemblyTableConstructor"sv, {}); } @@ -159,8 +158,6 @@ static ErrorOr generate_intrinsic_definitions(StringView output_path, Vect #include #include #include -#include -#include #include #include )~~~"); @@ -233,7 +230,6 @@ void Intrinsics::create_web_prototype_and_constructor<@prototype_class@>(JS::Rea auto gen = generator.fork(); add_interface(gen, "WebAssembly.Memory"sv, "WebAssemblyMemoryPrototype"sv, "WebAssemblyMemoryConstructor"sv, {}); add_interface(gen, "WebAssembly.Instance"sv, "WebAssemblyInstancePrototype"sv, "WebAssemblyInstanceConstructor"sv, {}); - add_interface(gen, "WebAssembly.Module"sv, "WebAssemblyModulePrototype"sv, "WebAssemblyModuleConstructor"sv, {}); add_interface(gen, "WebAssembly.Table"sv, "WebAssemblyTablePrototype"sv, "WebAssemblyTableConstructor"sv, {}); } diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index cdf5bcd2b8..8a0064252f 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -442,13 +442,12 @@ set(SOURCES URL/URL.cpp URL/URLSearchParams.cpp URL/URLSearchParamsIterator.cpp + WebAssembly/Module.cpp WebAssembly/WebAssemblyInstanceConstructor.cpp WebAssembly/WebAssemblyInstanceObject.cpp WebAssembly/WebAssemblyInstanceObjectPrototype.cpp WebAssembly/WebAssemblyMemoryConstructor.cpp WebAssembly/WebAssemblyMemoryPrototype.cpp - WebAssembly/WebAssemblyModuleConstructor.cpp - WebAssembly/WebAssemblyModuleObject.cpp WebAssembly/WebAssemblyObject.cpp WebAssembly/WebAssemblyTableConstructor.cpp WebAssembly/WebAssemblyTableObject.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 912c8a08e2..e19c5c0fc3 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -482,6 +482,7 @@ class ResourceLoader; } namespace Web::WebAssembly { +class Module; } namespace Web::WebGL { diff --git a/Userland/Libraries/LibWeb/WebAssembly/Module.cpp b/Userland/Libraries/LibWeb/WebAssembly/Module.cpp new file mode 100644 index 0000000000..efbafa5961 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAssembly/Module.cpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2021, Ali Mohammad Pur + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include +#include +#include +#include +#include +#include + +namespace Web::WebAssembly { + +WebIDL::ExceptionOr> Module::construct_impl(JS::Realm& realm, JS::Handle& bytes) +{ + auto& vm = realm.vm(); + + auto index = TRY(Bindings::parse_module(vm, bytes.cell())); + return MUST_OR_THROW_OOM(vm.heap().allocate(realm, realm, index)); +} + +Module::Module(JS::Realm& realm, size_t index) + : Bindings::PlatformObject(realm) + , m_index(index) +{ +} + +JS::ThrowCompletionOr Module::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype(realm, "WebAssembly.Module"sv)); + + return {}; +} + +Wasm::Module const& Module::module() const +{ + return Bindings::WebAssemblyObject::s_compiled_modules.at(index())->module; +} + +} diff --git a/Userland/Libraries/LibWeb/WebAssembly/Module.h b/Userland/Libraries/LibWeb/WebAssembly/Module.h new file mode 100644 index 0000000000..701ecab4eb --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAssembly/Module.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Ali Mohammad Pur + * Copyright (c) 2023, Tim Flynn + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Web::WebAssembly { + +class Module : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(Module, Bindings::PlatformObject); + +public: + static WebIDL::ExceptionOr> construct_impl(JS::Realm&, JS::Handle& bytes); + + size_t index() const { return m_index; } + Wasm::Module const& module() const; + +private: + Module(JS::Realm&, size_t index); + + virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; + + size_t m_index { 0 }; +}; + +} diff --git a/Userland/Libraries/LibWeb/WebAssembly/Module.idl b/Userland/Libraries/LibWeb/WebAssembly/Module.idl new file mode 100644 index 0000000000..eb03880b86 --- /dev/null +++ b/Userland/Libraries/LibWeb/WebAssembly/Module.idl @@ -0,0 +1,27 @@ +enum ImportExportKind { + "function", + "table", + "memory", + "global" +}; + +dictionary ModuleExportDescriptor { + required USVString name; + required ImportExportKind kind; +}; + +dictionary ModuleImportDescriptor { + required USVString module; + required USVString name; + required ImportExportKind kind; +}; + +// https://webassembly.github.io/spec/js-api/#modules +[LegacyNamespace=WebAssembly, Exposed=*] +interface Module { + constructor(BufferSource bytes); + + // FIXME: static sequence exports(Module moduleObject); + // FIXME: static sequence imports(Module moduleObject); + // FIXME: static sequence customSections(Module moduleObject, DOMString sectionName); +}; diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp index a733b94fa8..f7b5091d4d 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyInstanceConstructor.cpp @@ -6,10 +6,10 @@ #include #include +#include #include #include #include -#include #include namespace Web::Bindings { @@ -32,9 +32,9 @@ JS::ThrowCompletionOr> WebAssemblyInstanceConstruct auto& realm = *vm.current_realm(); auto* module_argument = TRY(vm.argument(0).to_object(vm)); - if (!is(module_argument)) + if (!is(module_argument)) return vm.throw_completion(JS::ErrorType::NotAnObjectOfType, "WebAssembly.Module"); - auto& module_object = static_cast(*module_argument); + auto& module_object = static_cast(*module_argument); auto result = TRY(WebAssemblyObject::instantiate_module(vm, module_object.module())); return MUST_OR_THROW_OOM(heap().allocate(realm, realm, result)); } diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp deleted file mode 100644 index c8563f6ccf..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2021, Ali Mohammad Pur - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include -#include -#include -#include -#include -#include - -namespace Web::Bindings { - -WebAssemblyModuleConstructor::WebAssemblyModuleConstructor(JS::Realm& realm) - : NativeFunction(*realm.intrinsics().function_prototype()) -{ -} - -WebAssemblyModuleConstructor::~WebAssemblyModuleConstructor() = default; - -JS::ThrowCompletionOr WebAssemblyModuleConstructor::call() -{ - return vm().throw_completion(JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Module"); -} - -JS::ThrowCompletionOr> WebAssemblyModuleConstructor::construct(FunctionObject&) -{ - auto& vm = this->vm(); - auto& realm = *vm.current_realm(); - - auto* buffer_object = TRY(vm.argument(0).to_object(vm)); - auto result = TRY(parse_module(vm, buffer_object)); - - return MUST_OR_THROW_OOM(heap().allocate(realm, realm, result)); -} - -JS::ThrowCompletionOr WebAssemblyModuleConstructor::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(realm, "WebAssembly.Module"), 0); - define_direct_property(vm.names.length, JS::Value(1), JS::Attribute::Configurable); - - return {}; -} - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h deleted file mode 100644 index cfdfe0412f..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleConstructor.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2021, Ali Mohammad Pur - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include - -namespace Web::Bindings { - -class WebAssemblyModuleConstructor : public JS::NativeFunction { - JS_OBJECT(WebAssemblyModuleConstructor, JS::NativeFunction); - -public: - explicit WebAssemblyModuleConstructor(JS::Realm&); - virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; - virtual ~WebAssemblyModuleConstructor() override; - - virtual JS::ThrowCompletionOr call() override; - virtual JS::ThrowCompletionOr> construct(JS::FunctionObject& new_target) override; - -private: - virtual bool has_constructor() const override { return true; } -}; - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp deleted file mode 100644 index a73b50d5ee..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2021, Ali Mohammad Pur - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include "WebAssemblyModulePrototype.h" -#include -#include - -namespace Web::Bindings { - -WebAssemblyModuleObject::WebAssemblyModuleObject(JS::Realm& realm, size_t index) - : Object(ConstructWithPrototypeTag::Tag, Bindings::ensure_web_prototype(realm, "WebAssembly.Module")) - , m_index(index) -{ -} - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.h deleted file mode 100644 index 5ed6c3c130..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModuleObject.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2021, Ali Mohammad Pur - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include -#include -#include -#include -#include - -namespace Web::Bindings { - -class WebAssemblyModuleObject final : public JS::Object { - JS_OBJECT(WebAssemblyModuleObject, Object); - -public: - explicit WebAssemblyModuleObject(JS::Realm&, size_t index); - virtual ~WebAssemblyModuleObject() override = default; - - size_t index() const { return m_index; } - Wasm::Module const& module() const { return WebAssemblyObject::s_compiled_modules.at(m_index)->module; } - -private: - size_t m_index { 0 }; -}; - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h deleted file mode 100644 index 63155ae0d1..0000000000 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyModulePrototype.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2021, Ali Mohammad Pur - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include "WebAssemblyModuleConstructor.h" -#include -#include -#include - -namespace Web::Bindings { - -class WebAssemblyModulePrototype final : public JS::Object { - JS_OBJECT(WebAssemblyModulePrototype, JS::Object); - -public: - explicit WebAssemblyModulePrototype(JS::Realm& realm) - : JS::Object(ConstructWithPrototypeTag::Tag, *realm.intrinsics().object_prototype()) - { - } -}; - -} diff --git a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp index e2800c8624..55c717a66b 100644 --- a/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp +++ b/Userland/Libraries/LibWeb/WebAssembly/WebAssemblyObject.cpp @@ -6,9 +6,6 @@ #include "WebAssemblyInstanceObject.h" #include "WebAssemblyMemoryPrototype.h" -#include "WebAssemblyModuleConstructor.h" -#include "WebAssemblyModuleObject.h" -#include "WebAssemblyModulePrototype.h" #include "WebAssemblyTableObject.h" #include "WebAssemblyTablePrototype.h" #include @@ -23,6 +20,8 @@ #include #include #include +#include +#include #include #include @@ -49,7 +48,7 @@ JS::ThrowCompletionOr WebAssemblyObject::initialize(JS::Realm& realm) auto& instance_constructor = Bindings::ensure_web_constructor(realm, "WebAssembly.Instance"sv); define_direct_property("Instance", &instance_constructor, JS::Attribute::Writable | JS::Attribute::Configurable); - auto& module_constructor = Bindings::ensure_web_constructor(realm, "WebAssembly.Module"sv); + auto& module_constructor = Bindings::ensure_web_constructor(realm, "WebAssembly.Module"sv); define_direct_property("Module", &module_constructor, JS::Attribute::Writable | JS::Attribute::Configurable); auto& table_constructor = Bindings::ensure_web_constructor(realm, "WebAssembly.Table"sv); @@ -159,7 +158,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::compile) if (result.is_error()) promise->reject(*result.release_error().value()); else - promise->fulfill(MUST_OR_THROW_OOM(vm.heap().allocate(realm, realm, result.release_value()))); + promise->fulfill(MUST_OR_THROW_OOM(vm.heap().allocate(realm, realm, result.release_value()))); return promise; } @@ -333,8 +332,8 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::instantiate) } module = &WebAssemblyObject::s_compiled_modules.at(result.release_value())->module; should_return_module = true; - } else if (is(buffer)) { - module = &static_cast(buffer)->module(); + } else if (is(buffer)) { + module = &static_cast(buffer)->module(); } else { auto error = JS::TypeError::create(realm, TRY_OR_THROW_OOM(vm, String::formatted("{} is not an ArrayBuffer or a Module", buffer->class_name()))); promise->reject(error); @@ -349,7 +348,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::instantiate) auto instance_object = MUST_OR_THROW_OOM(vm.heap().allocate(realm, realm, result.release_value())); if (should_return_module) { auto object = JS::Object::create(realm, nullptr); - object->define_direct_property("module", MUST_OR_THROW_OOM(vm.heap().allocate(realm, realm, s_compiled_modules.size() - 1)), JS::default_attributes); + object->define_direct_property("module", MUST_OR_THROW_OOM(vm.heap().allocate(realm, realm, s_compiled_modules.size() - 1)), JS::default_attributes); object->define_direct_property("instance", instance_object, JS::default_attributes); promise->fulfill(object); } else { diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index bbb10269a9..45e70a2276 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -200,6 +200,7 @@ libweb_js_bindings(UIEvents/UIEvent) libweb_js_bindings(UIEvents/WheelEvent) libweb_js_bindings(URL/URL) libweb_js_bindings(URL/URLSearchParams ITERABLE) +libweb_js_bindings(WebAssembly/Module) libweb_js_bindings(WebGL/WebGLContextEvent) libweb_js_bindings(WebGL/WebGLRenderingContext) libweb_js_bindings(WebIDL/DOMException)