Serenity Operating System
1/*
2 * Copyright (c) 2021, Ali Mohammad Pur <mpfard@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <AK/ScopeGuard.h>
8#include <LibJS/Runtime/Array.h>
9#include <LibJS/Runtime/ArrayBuffer.h>
10#include <LibJS/Runtime/BigInt.h>
11#include <LibJS/Runtime/TypedArray.h>
12#include <LibWasm/AbstractMachine/Interpreter.h>
13#include <LibWeb/Bindings/Intrinsics.h>
14#include <LibWeb/WebAssembly/WebAssemblyInstanceObject.h>
15#include <LibWeb/WebAssembly/WebAssemblyMemoryPrototype.h>
16#include <LibWeb/WebAssembly/WebAssemblyObject.h>
17#include <LibWeb/WebAssembly/WebAssemblyTableObject.h>
18
19namespace Web::Bindings {
20
21WebAssemblyInstanceObject::WebAssemblyInstanceObject(JS::Realm& realm, size_t index)
22 : Object(ConstructWithPrototypeTag::Tag, Bindings::ensure_web_prototype<WebAssemblyInstancePrototype>(realm, "WebAssembly.Instance"))
23 , m_index(index)
24{
25}
26
27JS::ThrowCompletionOr<void> WebAssemblyInstanceObject::initialize(JS::Realm& realm)
28{
29 MUST_OR_THROW_OOM(Object::initialize(realm));
30
31 auto& vm = this->vm();
32
33 VERIFY(!m_exports_object);
34 m_exports_object = create(realm, nullptr);
35 auto& instance = this->instance();
36 auto& cache = this->cache();
37 for (auto& export_ : instance.exports()) {
38 TRY(export_.value().visit(
39 [&](Wasm::FunctionAddress const& address) -> JS::ThrowCompletionOr<void> {
40 Optional<JS::FunctionObject*> object = cache.function_instances.get(address);
41 if (!object.has_value()) {
42 object = create_native_function(vm, address, export_.name());
43 cache.function_instances.set(address, *object);
44 }
45 m_exports_object->define_direct_property(export_.name(), *object, JS::default_attributes);
46 return {};
47 },
48 [&](Wasm::MemoryAddress const& address) -> JS::ThrowCompletionOr<void> {
49 Optional<WebAssemblyMemoryObject*> object = cache.memory_instances.get(address);
50 if (!object.has_value()) {
51 object = MUST_OR_THROW_OOM(heap().allocate<Web::Bindings::WebAssemblyMemoryObject>(realm, realm, address));
52 cache.memory_instances.set(address, *object);
53 }
54 m_exports_object->define_direct_property(export_.name(), *object, JS::default_attributes);
55 return {};
56 },
57 [&](Wasm::TableAddress const& address) -> JS::ThrowCompletionOr<void> {
58 Optional<WebAssemblyTableObject*> object = cache.table_instances.get(address);
59 if (!object.has_value()) {
60 object = MUST_OR_THROW_OOM(heap().allocate<Web::Bindings::WebAssemblyTableObject>(realm, realm, address));
61 cache.table_instances.set(address, *object);
62 }
63 m_exports_object->define_direct_property(export_.name(), *object, JS::default_attributes);
64 return {};
65 },
66 [&](auto const&) -> JS::ThrowCompletionOr<void> {
67 // FIXME: Implement other exports!
68 return {};
69 }));
70 }
71
72 MUST(m_exports_object->set_integrity_level(IntegrityLevel::Frozen));
73
74 return {};
75}
76
77void WebAssemblyInstanceObject::visit_edges(Visitor& visitor)
78{
79 Base::visit_edges(visitor);
80 visitor.visit(m_exports_object);
81}
82
83}