1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-28 09:37:44 +00:00

LibJS+LibWeb: Replace GlobalObject with Realm in create() functions

This is a continuation of the previous two commits.

As allocating a JS cell already primarily involves a realm instead of a
global object, and we'll need to pass one to the allocate() function
itself eventually (it's bridged via the global object right now), the
create() functions need to receive a realm as well.
The plan is for this to be the highest-level function that actually
receives a realm and passes it around, AOs on an even higher level will
use the "current realm" concept via VM::current_realm() as that's what
the spec assumes; passing around realms (or global objects, for that
matter) on higher AO levels is pointless and unlike for allocating
individual objects, which may happen outside of regular JS execution, we
don't need control over the specific realm that is being used there.
This commit is contained in:
Linus Groh 2022-08-16 00:20:49 +01:00
parent 5dd5896588
commit b99cc7d050
178 changed files with 883 additions and 609 deletions

View file

@ -16,6 +16,7 @@
#include <LibWeb/Bindings/CrossOriginAbstractOperations.h>
#include <LibWeb/Bindings/DOMExceptionWrapper.h>
#include <LibWeb/Bindings/LocationObject.h>
#include <LibWeb/Bindings/MainThreadVM.h>
#include <LibWeb/Bindings/WindowObject.h>
#include <LibWeb/DOM/DOMException.h>
#include <LibWeb/HTML/Scripting/Environments.h>
@ -93,6 +94,7 @@ bool is_platform_object_same_origin(JS::Object const& object)
// 7.2.3.4 CrossOriginGetOwnPropertyHelper ( O, P ), https://html.spec.whatwg.org/multipage/browsers.html#crossorigingetownpropertyhelper-(-o,-p-)
Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<LocationObject*, WindowObject*> const& object, JS::PropertyKey const& property_key)
{
auto& realm = *main_thread_vm().current_realm();
auto const* object_ptr = object.visit([](auto* o) { return static_cast<JS::Object const*>(o); });
auto const object_const_variant = object.visit([](auto* o) { return Variant<LocationObject const*, WindowObject const*> { o }; });
@ -126,7 +128,7 @@ Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<Lo
// 2. If IsCallable(value) is true, then set value to an anonymous built-in function, created in the current Realm Record, that performs the same steps as the IDL operation P on object O.
if (value->is_function()) {
value = JS::NativeFunction::create(
HTML::current_global_object(), [function = JS::make_handle(*value)](auto&, auto& global_object) {
realm, [function = JS::make_handle(*value)](auto&, auto& global_object) {
return JS::call(global_object, function.value(), JS::js_undefined());
},
0, "");
@ -143,7 +145,7 @@ Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<Lo
// 2. If e.[[NeedsGet]] is true, then set crossOriginGet to an anonymous built-in function, created in the current Realm Record, that performs the same steps as the getter of the IDL attribute P on object O.
if (*entry.needs_get) {
cross_origin_get = JS::NativeFunction::create(
HTML::current_global_object(), [object_ptr, getter = JS::make_handle(*original_descriptor->get)](auto&, auto& global_object) {
realm, [object_ptr, getter = JS::make_handle(*original_descriptor->get)](auto&, auto& global_object) {
return JS::call(global_object, getter.cell(), object_ptr);
},
0, "");
@ -155,7 +157,7 @@ Optional<JS::PropertyDescriptor> cross_origin_get_own_property_helper(Variant<Lo
// If e.[[NeedsSet]] is true, then set crossOriginSet to an anonymous built-in function, created in the current Realm Record, that performs the same steps as the setter of the IDL attribute P on object O.
if (*entry.needs_set) {
cross_origin_set = JS::NativeFunction::create(
HTML::current_global_object(), [object_ptr, setter = JS::make_handle(*original_descriptor->set)](auto&, auto& global_object) {
realm, [object_ptr, setter = JS::make_handle(*original_descriptor->set)](auto&, auto& global_object) {
return JS::call(global_object, setter.cell(), object_ptr);
},
0, "");

View file

@ -299,7 +299,6 @@ JS::VM& main_thread_vm()
// https://dom.spec.whatwg.org/#queue-a-mutation-observer-compound-microtask
void queue_mutation_observer_microtask(DOM::Document& document)
{
// FIXME: Is this the correct VM?
auto& vm = main_thread_vm();
auto& custom_data = verify_cast<WebEngineCustomData>(*vm.custom_data());
@ -345,8 +344,9 @@ void queue_mutation_observer_microtask(DOM::Document& document)
if (!records.is_empty()) {
auto& callback = mutation_observer.callback();
auto& global_object = callback.callback_context.global_object();
auto& realm = callback.callback_context.realm();
auto* wrapped_records = MUST(JS::Array::create(global_object, 0));
auto* wrapped_records = MUST(JS::Array::create(realm, 0));
for (size_t i = 0; i < records.size(); ++i) {
auto& record = records.at(i);
auto* wrapped_record = Bindings::wrap(global_object, record);

View file

@ -21,7 +21,7 @@ NavigatorObject::NavigatorObject(JS::Realm& realm)
void NavigatorObject::initialize(JS::Realm& realm)
{
auto& heap = this->heap();
auto* languages = MUST(JS::Array::create(realm.global_object(), 0));
auto* languages = MUST(JS::Array::create(realm, 0));
languages->indexed_properties().append(js_string(heap, "en-US"));
// FIXME: All of these should be in Navigator's prototype and be native accessors

View file

@ -618,6 +618,8 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll)
// https://www.w3.org/TR/cssom-view/#dom-window-scrollby
JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by)
{
auto& realm = *global_object.associated_realm();
auto* impl = TRY(impl_from(vm, global_object));
if (!impl->page())
return JS::js_undefined();
@ -626,12 +628,12 @@ JS_DEFINE_NATIVE_FUNCTION(WindowObject::scroll_by)
JS::Object* options = nullptr;
if (vm.argument_count() == 0) {
options = JS::Object::create(global_object, nullptr);
options = JS::Object::create(realm, nullptr);
} else if (vm.argument_count() == 1) {
options = TRY(vm.argument(0).to_object(global_object));
} else if (vm.argument_count() >= 2) {
// We ignore arguments 2+ in line with behavior of Chrome and Firefox
options = JS::Object::create(global_object, nullptr);
options = JS::Object::create(realm, nullptr);
MUST(options->set("left", vm.argument(0), ShouldThrowExceptions::No));
MUST(options->set("top", vm.argument(1), ShouldThrowExceptions::No));
MUST(options->set("behavior", JS::js_string(vm, "auto"), ShouldThrowExceptions::No));

View file

@ -30,7 +30,7 @@ inline Wrapper* wrap_impl(JS::GlobalObject& global_object, NativeObject& native_
{
auto& realm = *global_object.associated_realm();
if (!native_object.wrapper()) {
native_object.set_wrapper(*global_object.heap().allocate<typename NativeObject::WrapperType>(global_object, realm, native_object));
native_object.set_wrapper(*realm.heap().allocate<typename NativeObject::WrapperType>(realm.global_object(), realm, native_object));
}
return native_object.wrapper();
}

View file

@ -18,6 +18,7 @@ namespace Web::Crypto {
JS::Promise* SubtleCrypto::digest(String const& algorithm, JS::Handle<JS::Object> const& data)
{
auto& global_object = wrapper()->global_object();
auto& realm = *global_object.associated_realm();
// 1. Let algorithm be the algorithm parameter passed to the digest() method.
@ -25,7 +26,7 @@ JS::Promise* SubtleCrypto::digest(String const& algorithm, JS::Handle<JS::Object
auto data_buffer_or_error = Bindings::IDL::get_buffer_source_copy(*data.cell());
if (data_buffer_or_error.is_error()) {
auto* error = wrap(wrapper()->global_object(), DOM::OperationError::create("Failed to copy bytes from ArrayBuffer"));
auto* promise = JS::Promise::create(global_object);
auto* promise = JS::Promise::create(realm);
promise->reject(error);
return promise;
}
@ -46,13 +47,13 @@ JS::Promise* SubtleCrypto::digest(String const& algorithm, JS::Handle<JS::Object
// 4. If an error occurred, return a Promise rejected with normalizedAlgorithm.
else {
auto* error = wrap(wrapper()->global_object(), DOM::NotSupportedError::create(String::formatted("Invalid hash function '{}'", algorithm)));
auto* promise = JS::Promise::create(global_object);
auto* promise = JS::Promise::create(realm);
promise->reject(error);
return promise;
}
// 5. Let promise be a new Promise.
auto* promise = JS::Promise::create(global_object);
auto* promise = JS::Promise::create(realm);
// 6. Return promise and perform the remaining steps in parallel.
// FIXME: We don't have a good abstraction for this yet, so we do it in sync.
@ -71,7 +72,7 @@ JS::Promise* SubtleCrypto::digest(String const& algorithm, JS::Handle<JS::Object
return promise;
}
auto* result = JS::ArrayBuffer::create(global_object, result_buffer.release_value());
auto* result = JS::ArrayBuffer::create(realm, result_buffer.release_value());
// 9. Resolve promise with result.
promise->fulfill(result);

View file

@ -437,7 +437,7 @@ Bindings::CallbackType* EventTarget::get_current_value_of_event_handler(FlyStrin
// 6. Return scope. (NOTE: Not necessary)
auto* function = JS::ECMAScriptFunctionObject::create(global_object, name, builder.to_string(), program->body(), program->parameters(), program->function_length(), scope, nullptr, JS::FunctionKind::Normal, program->is_strict_mode(), program->might_need_arguments_object(), is_arrow_function);
auto* function = JS::ECMAScriptFunctionObject::create(realm, name, builder.to_string(), program->body(), program->parameters(), program->function_length(), scope, nullptr, JS::FunctionKind::Normal, program->is_strict_mode(), program->might_need_arguments_object(), is_arrow_function);
VERIFY(function);
// 10. Remove settings object's realm execution context from the JavaScript execution context stack.
@ -488,7 +488,7 @@ void EventTarget::set_event_handler_attribute(FlyString const& name, Optional<Bi
// Optimization: We pass in the event handler here instead of having activate_event_handler do another hash map lookup just to get the same object.
// This handles a new event handler while the other path handles an existing event handler. As such, both paths must have their own
// unique call to activate_event_handler.
event_target->activate_event_handler(name, new_event_handler, IsAttribute::No);
event_target->activate_event_handler(name, new_event_handler);
handler_map.set(name, move(new_event_handler));
return;
@ -500,12 +500,14 @@ void EventTarget::set_event_handler_attribute(FlyString const& name, Optional<Bi
// 4. Activate an event handler given eventTarget and name.
// NOTE: See the optimization comment above.
event_target->activate_event_handler(name, event_handler, IsAttribute::No);
event_target->activate_event_handler(name, event_handler);
}
// https://html.spec.whatwg.org/multipage/webappapis.html#activate-an-event-handler
void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandler& event_handler, IsAttribute is_attribute)
void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandler& event_handler)
{
auto& realm = *Bindings::main_thread_vm().current_realm();
// 1. Let handlerMap be eventTarget's event handler map.
// 2. Let eventHandler be handlerMap[name].
// NOTE: These are achieved by using the passed in event handler.
@ -517,36 +519,12 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl
// 4. Let callback be the result of creating a Web IDL EventListener instance representing a reference to a function of one argument that executes the steps of the event handler processing algorithm, given eventTarget, name, and its argument.
// The EventListener's callback context can be arbitrary; it does not impact the steps of the event handler processing algorithm. [DOM]
// FIXME: This is guess work on what global object the NativeFunction should be allocated on.
// For <body> or <frameset> elements who just had an element attribute set, it will be this's wrapper, as `this` is the result of determine_target_of_event_handler
// returning the element's document's global object, which is the HTML::Window object.
// For any other HTMLElement who just had an element attribute set, `this` will be that HTMLElement, so the global object is this's document's realm's global object.
// For anything else, it came from JavaScript, so use the global object of the provided callback function.
JS::GlobalObject* global_object = nullptr;
if (is_attribute == IsAttribute::Yes) {
if (is<HTML::Window>(this)) {
auto& window = verify_cast<HTML::Window>(*this);
// If an element attribute is set on a <body> element before any script is run, Window::wrapper() will be null.
// Force creation of the global object via the Document::interpreter() lazy initialization mechanism.
if (window.wrapper() == nullptr)
window.associated_document().interpreter();
global_object = static_cast<JS::GlobalObject*>(window.wrapper());
} else {
auto& html_element = verify_cast<HTML::HTMLElement>(*this);
global_object = &html_element.document().realm().global_object();
}
} else {
global_object = &event_handler.value.get<Bindings::CallbackType>().callback.cell()->global_object();
}
VERIFY(global_object);
// NOTE: The callback must keep `this` alive. For example:
// document.body.onunload = () => { console.log("onunload called!"); }
// document.body.remove();
// location.reload();
// The body element is no longer in the DOM and there is no variable holding onto it. However, the onunload handler is still called, meaning the callback keeps the body element alive.
auto callback_function = JS::NativeFunction::create(*global_object, "", [event_target = NonnullRefPtr(*this), name](JS::VM& vm, auto&) mutable -> JS::ThrowCompletionOr<JS::Value> {
auto callback_function = JS::NativeFunction::create(realm, "", [event_target = NonnullRefPtr(*this), name](JS::VM& vm, auto&) mutable -> JS::ThrowCompletionOr<JS::Value> {
// The event dispatcher should only call this with one argument.
VERIFY(vm.argument_count() == 1);
@ -561,7 +539,7 @@ void EventTarget::activate_event_handler(FlyString const& name, HTML::EventHandl
});
// NOTE: As per the spec, the callback context is arbitrary.
Bindings::CallbackType callback { JS::make_handle(static_cast<JS::Object*>(callback_function)), verify_cast<HTML::EnvironmentSettingsObject>(*global_object->associated_realm()->host_defined()) };
Bindings::CallbackType callback { JS::make_handle(static_cast<JS::Object*>(callback_function)), verify_cast<HTML::EnvironmentSettingsObject>(*realm.host_defined()) };
// 5. Let listener be a new event listener whose type is the event handler event type corresponding to eventHandler and callback is callback.
auto listener = adopt_ref(*new DOMEventListener);
@ -725,7 +703,7 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local
HTML::EventHandler new_event_handler { value };
// 6. Activate an event handler given eventTarget and name.
event_target->activate_event_handler(local_name, new_event_handler, IsAttribute::Yes);
event_target->activate_event_handler(local_name, new_event_handler);
handler_map.set(local_name, move(new_event_handler));
return;
@ -735,7 +713,7 @@ void EventTarget::element_event_handler_attribute_changed(FlyString const& local
// 6. Activate an event handler given eventTarget and name.
event_handler.value = value;
event_target->activate_event_handler(local_name, event_handler, IsAttribute::Yes);
event_target->activate_event_handler(local_name, event_handler);
}
bool EventTarget::dispatch_event(NonnullRefPtr<Event> event)

View file

@ -75,13 +75,8 @@ private:
// Spec Note: The order of the entries of event handler map could be arbitrary. It is not observable through any algorithms that operate on the map.
HashMap<FlyString, HTML::EventHandler> m_event_handler_map;
enum class IsAttribute {
No,
Yes,
};
Bindings::CallbackType* get_current_value_of_event_handler(FlyString const& name);
void activate_event_handler(FlyString const& name, HTML::EventHandler& event_handler, IsAttribute is_attribute);
void activate_event_handler(FlyString const& name, HTML::EventHandler& event_handler);
void deactivate_event_handler(FlyString const& name);
JS::ThrowCompletionOr<void> process_event_handler_for_event(FlyString const& name, Event& event);
};

View file

@ -15,6 +15,7 @@ namespace Web::Encoding {
JS::Uint8Array* TextEncoder::encode(String const& input) const
{
auto& global_object = wrapper()->global_object();
auto& realm = *global_object.associated_realm();
// NOTE: The AK::String returned from PrimitiveString::string() is always UTF-8, regardless of the internal string type, so most of these steps are no-ops.
@ -28,8 +29,8 @@ JS::Uint8Array* TextEncoder::encode(String const& input) const
auto byte_buffer = input.to_byte_buffer();
auto array_length = byte_buffer.size();
auto* array_buffer = JS::ArrayBuffer::create(global_object, move(byte_buffer));
return JS::Uint8Array::create(global_object, array_length, *array_buffer);
auto* array_buffer = JS::ArrayBuffer::create(realm, move(byte_buffer));
return JS::Uint8Array::create(realm, array_length, *array_buffer);
}
// https://encoding.spec.whatwg.org/#dom-textencoder-encoding

View file

@ -17,6 +17,7 @@ JS::ThrowCompletionOr<JS::Object*> HeadersIterator::next()
{
auto& global_object = wrapper()->global_object();
auto& vm = global_object.vm();
auto& realm = *global_object.associated_realm();
// The value pairs to iterate over are the return value of running sort and combine with thiss header list.
auto value_pairs_to_iterate_over = [&]() -> JS::ThrowCompletionOr<Vector<Fetch::Infrastructure::Header>> {
@ -39,7 +40,7 @@ JS::ThrowCompletionOr<JS::Object*> HeadersIterator::next()
case JS::Object::PropertyKind::Value:
return create_iterator_result_object(global_object, JS::js_string(vm, StringView { pair.value }), false);
case JS::Object::PropertyKind::KeyAndValue: {
auto* array = JS::Array::create_from(global_object, { JS::js_string(vm, StringView { pair.name }), JS::js_string(vm, StringView { pair.value }) });
auto* array = JS::Array::create_from(realm, { JS::js_string(vm, StringView { pair.name }), JS::js_string(vm, StringView { pair.value }) });
return create_iterator_result_object(global_object, array, false);
}
default:

View file

@ -222,13 +222,14 @@ DOM::ExceptionOr<NonnullRefPtr<Blob>> Blob::slice(Optional<i64> start, Optional<
JS::Promise* Blob::text()
{
auto& global_object = wrapper()->global_object();
auto& realm = *global_object.associated_realm();
// FIXME: 1. Let stream be the result of calling get stream on this.
// FIXME: 2. Let reader be the result of getting a reader from stream. If that threw an exception, return a new promise rejected with that exception.
// FIXME: We still need to implement ReadableStream for this step to be fully valid.
// 3. Let promise be the result of reading all bytes from stream with reader
auto* promise = JS::Promise::create(global_object);
auto* promise = JS::Promise::create(realm);
auto* result = JS::js_string(global_object.heap(), String { m_byte_buffer.bytes() });
// 4. Return the result of transforming promise by a fulfillment handler that returns the result of running UTF-8 decode on its first argument.
@ -240,14 +241,15 @@ JS::Promise* Blob::text()
JS::Promise* Blob::array_buffer()
{
auto& global_object = wrapper()->global_object();
auto& realm = *global_object.associated_realm();
// FIXME: 1. Let stream be the result of calling get stream on this.
// FIXME: 2. Let reader be the result of getting a reader from stream. If that threw an exception, return a new promise rejected with that exception.
// FIXME: We still need to implement ReadableStream for this step to be fully valid.
// 3. Let promise be the result of reading all bytes from stream with reader.
auto* promise = JS::Promise::create(global_object);
auto buffer_result = JS::ArrayBuffer::create(global_object, m_byte_buffer.size());
auto* promise = JS::Promise::create(realm);
auto buffer_result = JS::ArrayBuffer::create(realm, m_byte_buffer.size());
if (buffer_result.is_error()) {
promise->reject(buffer_result.release_error().value().release_value());
return promise;

View file

@ -12,13 +12,15 @@ namespace Web::HTML {
RefPtr<ImageData> ImageData::create_with_size(JS::GlobalObject& global_object, int width, int height)
{
auto& realm = *global_object.associated_realm();
if (width <= 0 || height <= 0)
return nullptr;
if (width > 16384 || height > 16384)
return nullptr;
auto data_or_error = JS::Uint8ClampedArray::create(global_object, width * height * 4);
auto data_or_error = JS::Uint8ClampedArray::create(realm, width * height * 4);
if (data_or_error.is_error())
return nullptr;
auto* data = data_or_error.release_value();

View file

@ -16,6 +16,7 @@ JS::Object* URLSearchParamsIterator::next()
{
auto& global_object = wrapper()->global_object();
auto& vm = global_object.vm();
auto& realm = *global_object.associated_realm();
if (m_index >= m_url_search_params.m_list.size())
return create_iterator_result_object(global_object, JS::js_undefined(), true);
@ -26,7 +27,7 @@ JS::Object* URLSearchParamsIterator::next()
else if (m_iteration_kind == JS::Object::PropertyKind::Value)
return create_iterator_result_object(global_object, JS::js_string(vm, entry.value), false);
return create_iterator_result_object(global_object, JS::Array::create_from(global_object, { JS::js_string(vm, entry.name), JS::js_string(vm, entry.value) }), false);
return create_iterator_result_object(global_object, JS::Array::create_from(realm, { JS::js_string(vm, entry.name), JS::js_string(vm, entry.value) }), false);
}
void URLSearchParamsIterator::visit_edges(JS::Cell::Visitor& visitor)

View file

@ -28,7 +28,7 @@ void WebAssemblyInstanceObject::initialize(JS::Realm& realm)
Object::initialize(realm);
VERIFY(!m_exports_object);
m_exports_object = create(realm.global_object(), nullptr);
m_exports_object = create(realm, nullptr);
auto& instance = this->instance();
auto& cache = this->cache();
for (auto& export_ : instance.exports()) {

View file

@ -38,6 +38,8 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyMemoryPrototype::grow)
JS_DEFINE_NATIVE_FUNCTION(WebAssemblyMemoryPrototype::buffer_getter)
{
auto& realm = *global_object.associated_realm();
auto* this_object = TRY(vm.this_value(global_object).to_object(global_object));
if (!is<WebAssemblyMemoryObject>(this_object))
return vm.throw_completion<JS::TypeError>(global_object, JS::ErrorType::NotAnObjectOfType, "WebAssembly.Memory");
@ -47,7 +49,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyMemoryPrototype::buffer_getter)
if (!memory)
return JS::js_undefined();
auto* array_buffer = JS::ArrayBuffer::create(global_object, &memory->data());
auto* array_buffer = JS::ArrayBuffer::create(realm, &memory->data());
array_buffer->set_detach_key(JS::js_string(vm, "WebAssembly.Memory"));
return array_buffer;
}

View file

@ -164,7 +164,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::compile)
if (buffer_or_error.is_error())
rejection_value = *buffer_or_error.throw_completion().value();
auto promise = JS::Promise::create(global_object);
auto promise = JS::Promise::create(realm);
if (!rejection_value.is_empty()) {
promise->reject(rejection_value);
return promise;
@ -323,7 +323,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::instantiate)
// FIXME: This shouldn't block!
auto buffer_or_error = vm.argument(0).to_object(global_object);
auto promise = JS::Promise::create(global_object);
auto promise = JS::Promise::create(realm);
bool should_return_module = false;
if (buffer_or_error.is_error()) {
auto rejection_value = *buffer_or_error.throw_completion().value();
@ -344,7 +344,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::instantiate)
} else if (is<WebAssemblyModuleObject>(buffer)) {
module = &static_cast<WebAssemblyModuleObject*>(buffer)->module();
} else {
auto error = JS::TypeError::create(global_object, String::formatted("{} is not an ArrayBuffer or a Module", buffer->class_name()));
auto error = JS::TypeError::create(realm, String::formatted("{} is not an ArrayBuffer or a Module", buffer->class_name()));
promise->reject(error);
return promise;
}
@ -356,7 +356,7 @@ JS_DEFINE_NATIVE_FUNCTION(WebAssemblyObject::instantiate)
} else {
auto instance_object = vm.heap().allocate<WebAssemblyInstanceObject>(global_object, realm, result.release_value());
if (should_return_module) {
auto object = JS::Object::create(global_object, nullptr);
auto object = JS::Object::create(realm, nullptr);
object->define_direct_property("module", vm.heap().allocate<WebAssemblyModuleObject>(global_object, realm, s_compiled_modules.size() - 1), JS::default_attributes);
object->define_direct_property("instance", instance_object, JS::default_attributes);
promise->fulfill(object);
@ -442,15 +442,17 @@ JS::ThrowCompletionOr<Wasm::Value> to_webassembly_value(JS::GlobalObject& global
JS::NativeFunction* create_native_function(JS::GlobalObject& global_object, Wasm::FunctionAddress address, String const& name)
{
auto& realm = *global_object.associated_realm();
Optional<Wasm::FunctionType> type;
WebAssemblyObject::s_abstract_machine.store().get(address)->visit([&](auto const& value) { type = value.type(); });
if (auto entry = WebAssemblyObject::s_global_cache.function_instances.get(address); entry.has_value())
return *entry;
auto function = JS::NativeFunction::create(
global_object,
realm,
name,
[address, type = type.release_value()](JS::VM& vm, JS::GlobalObject& global_object) -> JS::ThrowCompletionOr<JS::Value> {
auto& realm = *global_object.associated_realm();
Vector<Wasm::Value> values;
values.ensure_capacity(type.parameters().size());
@ -474,7 +476,7 @@ JS::NativeFunction* create_native_function(JS::GlobalObject& global_object, Wasm
for (auto& entry : result.values())
result_values.append(to_js_value(global_object, entry));
return JS::Value(JS::Array::create_from(global_object, result_values));
return JS::Value(JS::Array::create_from(realm, result_values));
});
WebAssemblyObject::s_global_cache.function_instances.set(address, function);

View file

@ -214,8 +214,9 @@ void WebSocket::on_message(ByteBuffer message, bool is_text)
} else if (m_binary_type == "arraybuffer") {
// type indicates that the data is Binary and binaryType is "arraybuffer"
auto& global_object = wrapper()->global_object();
auto& realm = *global_object.associated_realm();
HTML::MessageEventInit event_init;
event_init.data = JS::ArrayBuffer::create(global_object, message);
event_init.data = JS::ArrayBuffer::create(realm, message);
event_init.origin = url();
dispatch_event(HTML::MessageEvent::create(HTML::EventNames::message, event_init));
return;

View file

@ -83,6 +83,7 @@ DOM::ExceptionOr<String> XMLHttpRequest::response_text() const
DOM::ExceptionOr<JS::Value> XMLHttpRequest::response()
{
auto& global_object = wrapper()->global_object();
auto& realm = *global_object.associated_realm();
// 1. If thiss response type is the empty string or "text", then:
if (m_response_type == Bindings::XMLHttpRequestResponseType::Empty || m_response_type == Bindings::XMLHttpRequestResponseType::Text) {
@ -108,7 +109,7 @@ DOM::ExceptionOr<JS::Value> XMLHttpRequest::response()
// 5. If thiss response type is "arraybuffer",
if (m_response_type == Bindings::XMLHttpRequestResponseType::Arraybuffer) {
// then set thiss response object to a new ArrayBuffer object representing thiss received bytes. If this throws an exception, then set thiss response object to failure and return null.
auto buffer_result = JS::ArrayBuffer::create(global_object, m_received_bytes.size());
auto buffer_result = JS::ArrayBuffer::create(realm, m_received_bytes.size());
if (buffer_result.is_error()) {
m_response_object = Failure();
return JS::js_null();