mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:22:43 +00:00 
			
		
		
		
	LibWeb+LibWasm: Implement the WebAssembly.Table object
This commit is contained in:
		
							parent
							
								
									d52a26de3f
								
							
						
					
					
						commit
						09dd397160
					
				
					 9 changed files with 433 additions and 1 deletions
				
			
		|  | @ -301,6 +301,23 @@ public: | |||
|     auto& elements() { return m_elements; } | ||||
|     auto& type() const { return m_type; } | ||||
| 
 | ||||
|     bool grow(size_t size_to_grow, Reference const& fill_value) | ||||
|     { | ||||
|         if (size_to_grow == 0) | ||||
|             return true; | ||||
|         auto new_size = m_elements.size() + size_to_grow; | ||||
|         if (auto max = m_type.limits().max(); max.has_value()) { | ||||
|             if (max.value() < new_size) | ||||
|                 return false; | ||||
|         } | ||||
|         auto previous_size = m_elements.size(); | ||||
|         if (!m_elements.try_resize(new_size)) | ||||
|             return false; | ||||
|         for (size_t i = previous_size; i < m_elements.size(); ++i) | ||||
|             m_elements[i] = fill_value; | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     Vector<Optional<Reference>> m_elements; | ||||
|     TableType const& m_type; | ||||
|  |  | |||
|  | @ -231,6 +231,9 @@ set(SOURCES | |||
|     WebAssembly/WebAssemblyModuleConstructor.cpp | ||||
|     WebAssembly/WebAssemblyModuleObject.cpp | ||||
|     WebAssembly/WebAssemblyObject.cpp | ||||
|     WebAssembly/WebAssemblyTableConstructor.cpp | ||||
|     WebAssembly/WebAssemblyTableObject.cpp | ||||
|     WebAssembly/WebAssemblyTablePrototype.cpp | ||||
|     WebContentClient.cpp | ||||
|     XHR/EventNames.cpp | ||||
|     XHR/XMLHttpRequest.cpp | ||||
|  |  | |||
|  | @ -9,6 +9,8 @@ | |||
| #include "WebAssemblyModuleConstructor.h" | ||||
| #include "WebAssemblyModuleObject.h" | ||||
| #include "WebAssemblyModulePrototype.h" | ||||
| #include "WebAssemblyTableObject.h" | ||||
| #include "WebAssemblyTablePrototype.h" | ||||
| #include <AK/ScopeGuard.h> | ||||
| #include <LibJS/Runtime/Array.h> | ||||
| #include <LibJS/Runtime/ArrayBuffer.h> | ||||
|  | @ -57,6 +59,12 @@ void WebAssemblyObject::initialize(JS::GlobalObject& global_object) | |||
|     auto& module_prototype = window.ensure_web_prototype<WebAssemblyModulePrototype>("WebAssemblyModulePrototype"); | ||||
|     module_prototype.define_direct_property(vm.names.constructor, &module_constructor, JS::Attribute::Writable | JS::Attribute::Configurable); | ||||
|     define_direct_property("Module", &module_constructor, JS::Attribute::Writable | JS::Attribute::Configurable); | ||||
| 
 | ||||
|     auto& table_constructor = window.ensure_web_constructor<WebAssemblyTableConstructor>("WebAssembly.Table"); | ||||
|     table_constructor.define_direct_property(vm.names.name, js_string(vm, "WebAssembly.Table"), JS::Attribute::Configurable); | ||||
|     auto& table_prototype = window.ensure_web_prototype<WebAssemblyTablePrototype>("WebAssemblyTablePrototype"); | ||||
|     table_prototype.define_direct_property(vm.names.constructor, &table_constructor, JS::Attribute::Writable | JS::Attribute::Configurable); | ||||
|     define_direct_property("Table", &table_constructor, JS::Attribute::Writable | JS::Attribute::Configurable); | ||||
| } | ||||
| 
 | ||||
| NonnullOwnPtrVector<WebAssemblyObject::CompiledWebAssemblyModule> WebAssemblyObject::s_compiled_modules; | ||||
|  | @ -249,6 +257,15 @@ Result<size_t, JS::Value> WebAssemblyObject::instantiate_module(Wasm::Module con | |||
|                     auto address = static_cast<WebAssemblyMemoryObject const&>(import_.as_object()).address(); | ||||
|                     resolved_imports.set(import_name, Wasm::ExternValue { address }); | ||||
|                 }, | ||||
|                 [&](Wasm::TableType const&) { | ||||
|                     if (!import_.is_object() || !is<WebAssemblyTableObject>(import_.as_object())) { | ||||
|                         // FIXME: Throw a LinkError instead
 | ||||
|                         vm.throw_exception<JS::TypeError>(global_object, "LinkError: Expected an instance of WebAssembly.Table for a table import"); | ||||
|                         return; | ||||
|                     } | ||||
|                     auto address = static_cast<WebAssemblyTableObject const&>(import_.as_object()).address(); | ||||
|                     resolved_imports.set(import_name, Wasm::ExternValue { address }); | ||||
|                 }, | ||||
|                 [&](const auto&) { | ||||
|                     // FIXME: Implement these.
 | ||||
|                     dbgln("Unimplemented import of non-function attempted"); | ||||
|  | @ -399,8 +416,22 @@ Optional<Wasm::Value> to_webassembly_value(JS::Value value, const Wasm::ValueTyp | |||
|         return Wasm::Value { static_cast<float>(number) }; | ||||
|     } | ||||
|     case Wasm::ValueType::FunctionReference: | ||||
|     case Wasm::ValueType::NullFunctionReference: { | ||||
|         if (value.is_null()) | ||||
|             return Wasm::Value { Wasm::ValueType(Wasm::ValueType::NullExternReference), 0ull }; | ||||
| 
 | ||||
|         if (value.is_function()) { | ||||
|             auto& function = value.as_function(); | ||||
|             for (auto& entry : WebAssemblyObject::s_global_cache.function_instances) { | ||||
|                 if (entry.value == &function) | ||||
|                     return Wasm::Value { Wasm::Reference { Wasm::Reference::Func { entry.key } } }; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotAn, "Exported function"); | ||||
|         return {}; | ||||
|     } | ||||
|     case Wasm::ValueType::ExternReference: | ||||
|     case Wasm::ValueType::NullFunctionReference: | ||||
|     case Wasm::ValueType::NullExternReference: | ||||
|         TODO(); | ||||
|     } | ||||
|  |  | |||
|  | @ -0,0 +1,124 @@ | |||
| /*
 | ||||
|  * 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/WindowObject.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::GlobalObject& global_object) | ||||
|     : NativeFunction(*global_object.function_prototype()) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| WebAssemblyTableConstructor::~WebAssemblyTableConstructor() | ||||
| { | ||||
| } | ||||
| 
 | ||||
| JS::Value WebAssemblyTableConstructor::call() | ||||
| { | ||||
|     vm().throw_exception<JS::TypeError>(global_object(), JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table"); | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| JS::Value WebAssemblyTableConstructor::construct(FunctionObject&) | ||||
| { | ||||
|     auto& vm = this->vm(); | ||||
|     auto& global_object = this->global_object(); | ||||
| 
 | ||||
|     auto descriptor = vm.argument(0).to_object(global_object); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
| 
 | ||||
|     auto element_value = descriptor->get("element"); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
|     if (!element_value.is_string()) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element_value.to_string_without_side_effects()); | ||||
|         return {}; | ||||
|     } | ||||
|     auto& element = element_value.as_string().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()) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::InvalidHint, element); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     auto initial_value = descriptor->get("initial"); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
|     auto maximum_value = descriptor->get("maximum"); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
| 
 | ||||
|     auto initial = initial_value.to_u32(global_object); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
| 
 | ||||
|     Optional<u32> maximum; | ||||
| 
 | ||||
|     if (!maximum_value.is_undefined()) { | ||||
|         maximum = maximum_value.to_u32(global_object); | ||||
|         if (vm.exception()) | ||||
|             return {}; | ||||
|     } | ||||
| 
 | ||||
|     if (maximum.has_value() && maximum.value() < initial) { | ||||
|         vm.throw_exception<JS::RangeError>(global_object, "maximum should be larger than or equal to initial"); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     auto value_value = descriptor->get("value"); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
| 
 | ||||
|     auto reference_value = [&]() -> Optional<Wasm::Value> { | ||||
|         if (value_value.is_empty() || value_value.is_undefined()) | ||||
|             return Wasm::Value(*reference_type, 0ull); | ||||
| 
 | ||||
|         return to_webassembly_value(value_value, *reference_type, global_object); | ||||
|     }(); | ||||
| 
 | ||||
|     if (!reference_value.has_value()) | ||||
|         return {}; | ||||
| 
 | ||||
|     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()) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, "Wasm Table allocation failed"); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address); | ||||
|     for (auto& element : table.elements()) | ||||
|         element = reference; | ||||
| 
 | ||||
|     return vm.heap().allocate<WebAssemblyTableObject>(global_object, global_object, *address); | ||||
| } | ||||
| 
 | ||||
| void WebAssemblyTableConstructor::initialize(JS::GlobalObject& global_object) | ||||
| { | ||||
|     auto& vm = this->vm(); | ||||
|     auto& window = static_cast<WindowObject&>(global_object); | ||||
| 
 | ||||
|     NativeFunction::initialize(global_object); | ||||
|     define_direct_property(vm.names.prototype, &window.ensure_web_prototype<WebAssemblyTablePrototype>("WebAssemblyTablePrototype"), 0); | ||||
|     define_direct_property(vm.names.length, JS::Value(1), JS::Attribute::Configurable); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,28 @@ | |||
| /*
 | ||||
|  * 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::GlobalObject&); | ||||
|     virtual void initialize(JS::GlobalObject&) override; | ||||
|     virtual ~WebAssemblyTableConstructor() override; | ||||
| 
 | ||||
|     virtual JS::Value call() override; | ||||
|     virtual JS::Value construct(JS::FunctionObject& new_target) override; | ||||
| 
 | ||||
| private: | ||||
|     virtual bool has_constructor() const override { return true; } | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,18 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include "WebAssemblyTablePrototype.h" | ||||
| #include <LibWeb/WebAssembly/WebAssemblyTableObject.h> | ||||
| 
 | ||||
| namespace Web::Bindings { | ||||
| 
 | ||||
| WebAssemblyTableObject::WebAssemblyTableObject(JS::GlobalObject& global_object, Wasm::TableAddress address) | ||||
|     : Object(static_cast<WindowObject&>(global_object).ensure_web_prototype<WebAssemblyTablePrototype>("WebAssemblyTablePrototype")) | ||||
|     , m_address(address) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,30 @@ | |||
| /*
 | ||||
|  * 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/WebAssemblyInstanceObjectPrototype.h> | ||||
| #include <LibWeb/WebAssembly/WebAssemblyObject.h> | ||||
| 
 | ||||
| namespace Web::Bindings { | ||||
| 
 | ||||
| class WebAssemblyTableObject final : public JS::Object { | ||||
|     JS_OBJECT(WebAssemblyTableObject, Object); | ||||
| 
 | ||||
| public: | ||||
|     explicit WebAssemblyTableObject(JS::GlobalObject&, Wasm::TableAddress); | ||||
|     virtual ~WebAssemblyTableObject() override = default; | ||||
| 
 | ||||
|     Wasm::TableAddress address() const { return m_address; } | ||||
| 
 | ||||
| private: | ||||
|     Wasm::TableAddress m_address; | ||||
| }; | ||||
| 
 | ||||
| } | ||||
|  | @ -0,0 +1,145 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #include <LibJS/Runtime/TypedArray.h> | ||||
| #include <LibWeb/WebAssembly/WebAssemblyTableObject.h> | ||||
| #include <LibWeb/WebAssembly/WebAssemblyTablePrototype.h> | ||||
| 
 | ||||
| namespace Web::Bindings { | ||||
| 
 | ||||
| void WebAssemblyTablePrototype::initialize(JS::GlobalObject& global_object) | ||||
| { | ||||
|     Object::initialize(global_object); | ||||
|     define_native_accessor("length", length_getter, {}, JS::Attribute::Enumerable | JS::Attribute::Configurable); | ||||
|     define_native_function("grow", grow, 1, JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable); | ||||
|     define_native_function("get", get, 1, JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable); | ||||
|     define_native_function("set", set, 1, JS::Attribute::Writable | JS::Attribute::Enumerable | JS::Attribute::Configurable); | ||||
| } | ||||
| 
 | ||||
| JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::grow) | ||||
| { | ||||
|     auto delta = vm.argument(0).to_u32(global_object); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
|     auto* this_object = vm.this_value(global_object).to_object(global_object); | ||||
|     if (!this_object || !is<WebAssemblyTableObject>(this_object)) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WebAssembly.Table"); | ||||
|         return {}; | ||||
|     } | ||||
|     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 = [&]() -> Optional<Wasm::Value> { | ||||
|         if (value_value.is_empty() || value_value.is_undefined()) | ||||
|             return Wasm::Value(table->type().element_type(), 0ull); | ||||
| 
 | ||||
|         return to_webassembly_value(value_value, table->type().element_type(), global_object); | ||||
|     }(); | ||||
| 
 | ||||
|     if (!reference_value.has_value()) | ||||
|         return {}; | ||||
| 
 | ||||
|     auto& reference = reference_value->value().get<Wasm::Reference>(); | ||||
| 
 | ||||
|     if (!table->grow(delta, reference)) { | ||||
|         vm.throw_exception<JS::RangeError>(global_object, "Failed to grow table"); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     return JS::Value(static_cast<u32>(initial_size)); | ||||
| } | ||||
| 
 | ||||
| JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::get) | ||||
| { | ||||
|     auto index = vm.argument(0).to_u32(global_object); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
| 
 | ||||
|     auto* this_object = vm.this_value(global_object).to_object(global_object); | ||||
|     if (!this_object || !is<WebAssemblyTableObject>(this_object)) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WebAssembly.Table"); | ||||
|         return {}; | ||||
|     } | ||||
|     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) { | ||||
|         vm.throw_exception<JS::RangeError>(global_object, "Table element index out of range"); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     auto& ref = table->elements()[index]; | ||||
|     if (!ref.has_value()) | ||||
|         return JS::js_undefined(); | ||||
| 
 | ||||
|     Wasm::Value wasm_value { ref.value() }; | ||||
|     return to_js_value(wasm_value, global_object); | ||||
| } | ||||
| 
 | ||||
| JS_DEFINE_NATIVE_FUNCTION(WebAssemblyTablePrototype::set) | ||||
| { | ||||
|     auto index = vm.argument(0).to_u32(global_object); | ||||
|     if (vm.exception()) | ||||
|         return {}; | ||||
| 
 | ||||
|     auto* this_object = vm.this_value(global_object).to_object(global_object); | ||||
|     if (!this_object || !is<WebAssemblyTableObject>(this_object)) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WebAssembly.Table"); | ||||
|         return {}; | ||||
|     } | ||||
|     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) { | ||||
|         vm.throw_exception<JS::RangeError>(global_object, "Table element index out of range"); | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     auto value_value = vm.argument(1); | ||||
|     auto reference_value = [&]() -> Optional<Wasm::Value> { | ||||
|         if (value_value.is_empty() || value_value.is_undefined()) | ||||
|             return Wasm::Value(table->type().element_type(), 0ull); | ||||
| 
 | ||||
|         return to_webassembly_value(value_value, table->type().element_type(), global_object); | ||||
|     }(); | ||||
| 
 | ||||
|     if (!reference_value.has_value()) | ||||
|         return {}; | ||||
| 
 | ||||
|     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 = vm.this_value(global_object).to_object(global_object); | ||||
|     if (!this_object || !is<WebAssemblyTableObject>(this_object)) { | ||||
|         vm.throw_exception<JS::TypeError>(global_object, JS::ErrorType::NotA, "WebAssembly.Table"); | ||||
|         return {}; | ||||
|     } | ||||
|     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,0 +1,36 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> | ||||
|  * | ||||
|  * SPDX-License-Identifier: BSD-2-Clause | ||||
|  */ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "WebAssemblyTableConstructor.h" | ||||
| #include <LibJS/Runtime/GlobalObject.h> | ||||
| #include <LibJS/Runtime/Object.h> | ||||
| #include <LibJS/Runtime/VM.h> | ||||
| #include <LibWeb/Bindings/WindowObject.h> | ||||
| #include <LibWeb/Forward.h> | ||||
| 
 | ||||
| namespace Web::Bindings { | ||||
| 
 | ||||
| class WebAssemblyTablePrototype final : public JS::Object { | ||||
|     JS_OBJECT(WebAssemblyTablePrototype, JS::Object); | ||||
| 
 | ||||
| public: | ||||
|     explicit WebAssemblyTablePrototype(JS::GlobalObject& global_object) | ||||
|         : JS::Object(global_object) | ||||
|     { | ||||
|     } | ||||
| 
 | ||||
|     virtual void initialize(JS::GlobalObject& global_object) override; | ||||
| 
 | ||||
| private: | ||||
|     JS_DECLARE_NATIVE_FUNCTION(grow); | ||||
|     JS_DECLARE_NATIVE_FUNCTION(get); | ||||
|     JS_DECLARE_NATIVE_FUNCTION(set); | ||||
|     JS_DECLARE_NATIVE_FUNCTION(length_getter); | ||||
| }; | ||||
| 
 | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Ali Mohammad Pur
						Ali Mohammad Pur