Serenity Operating System
at master 94 lines 3.6 kB view raw
1/* 2 * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <LibJS/Runtime/GlobalObject.h> 8#include <LibJS/Runtime/TypedArray.h> 9#include <LibWeb/Bindings/Intrinsics.h> 10#include <LibWeb/WebAssembly/WebAssemblyObject.h> 11#include <LibWeb/WebAssembly/WebAssemblyTableConstructor.h> 12#include <LibWeb/WebAssembly/WebAssemblyTableObject.h> 13#include <LibWeb/WebAssembly/WebAssemblyTablePrototype.h> 14 15namespace Web::Bindings { 16 17WebAssemblyTableConstructor::WebAssemblyTableConstructor(JS::Realm& realm) 18 : NativeFunction(*realm.intrinsics().function_prototype()) 19{ 20} 21 22WebAssemblyTableConstructor::~WebAssemblyTableConstructor() = default; 23 24JS::ThrowCompletionOr<JS::Value> WebAssemblyTableConstructor::call() 25{ 26 return vm().throw_completion<JS::TypeError>(JS::ErrorType::ConstructorWithoutNew, "WebAssembly.Table"); 27} 28 29JS::ThrowCompletionOr<JS::NonnullGCPtr<JS::Object>> WebAssemblyTableConstructor::construct(FunctionObject&) 30{ 31 auto& vm = this->vm(); 32 auto& realm = *vm.current_realm(); 33 34 auto descriptor = TRY(vm.argument(0).to_object(vm)); 35 auto element_value = TRY(descriptor->get("element")); 36 if (!element_value.is_string()) 37 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidHint, TRY_OR_THROW_OOM(vm, element_value.to_string_without_side_effects())); 38 auto element = TRY(element_value.as_string().deprecated_string()); 39 40 Optional<Wasm::ValueType> reference_type; 41 if (element == "anyfunc"sv) 42 reference_type = Wasm::ValueType(Wasm::ValueType::FunctionReference); 43 else if (element == "externref"sv) 44 reference_type = Wasm::ValueType(Wasm::ValueType::ExternReference); 45 46 if (!reference_type.has_value()) 47 return vm.throw_completion<JS::TypeError>(JS::ErrorType::InvalidHint, element); 48 49 auto initial_value = TRY(descriptor->get("initial")); 50 auto maximum_value = TRY(descriptor->get("maximum")); 51 52 auto initial = TRY(initial_value.to_u32(vm)); 53 54 Optional<u32> maximum; 55 56 if (!maximum_value.is_undefined()) 57 maximum = TRY(maximum_value.to_u32(vm)); 58 59 if (maximum.has_value() && maximum.value() < initial) 60 return vm.throw_completion<JS::RangeError>("maximum should be larger than or equal to initial"sv); 61 62 auto value_value = TRY(descriptor->get("value")); 63 auto reference_value = TRY([&]() -> JS::ThrowCompletionOr<Wasm::Value> { 64 if (value_value.is_undefined()) 65 return Wasm::Value(*reference_type, 0ull); 66 67 return to_webassembly_value(vm, value_value, *reference_type); 68 }()); 69 70 auto& reference = reference_value.value().get<Wasm::Reference>(); 71 72 auto address = WebAssemblyObject::s_abstract_machine.store().allocate(Wasm::TableType { *reference_type, Wasm::Limits { initial, maximum } }); 73 if (!address.has_value()) 74 return vm.throw_completion<JS::TypeError>("Wasm Table allocation failed"sv); 75 76 auto& table = *WebAssemblyObject::s_abstract_machine.store().get(*address); 77 for (auto& element : table.elements()) 78 element = reference; 79 80 return MUST_OR_THROW_OOM(vm.heap().allocate<WebAssemblyTableObject>(realm, realm, *address)); 81} 82 83JS::ThrowCompletionOr<void> WebAssemblyTableConstructor::initialize(JS::Realm& realm) 84{ 85 auto& vm = this->vm(); 86 87 MUST_OR_THROW_OOM(NativeFunction::initialize(realm)); 88 define_direct_property(vm.names.prototype, &Bindings::ensure_web_prototype<WebAssemblyTablePrototype>(realm, "WebAssembly.Table"), 0); 89 define_direct_property(vm.names.length, JS::Value(1), JS::Attribute::Configurable); 90 91 return {}; 92} 93 94}