LibGC+Everywhere: Factor out a LibGC from LibJS

Resulting in a massive rename across almost everywhere! Alongside the
namespace change, we now have the following names:

 * JS::NonnullGCPtr -> GC::Ref
 * JS::GCPtr -> GC::Ptr
 * JS::HeapFunction -> GC::Function
 * JS::CellImpl -> GC::Cell
 * JS::Handle -> GC::Root
This commit is contained in:
Shannon Booth 2024-11-15 04:01:23 +13:00 committed by Andreas Kling
commit f87041bf3a
Notes: github-actions[bot] 2024-11-15 13:50:17 +00:00
1722 changed files with 9939 additions and 9906 deletions

View file

@ -15,10 +15,10 @@
namespace Web::XHR {
JS_DEFINE_ALLOCATOR(FormData);
GC_DEFINE_ALLOCATOR(FormData);
// https://xhr.spec.whatwg.org/#dom-formdata
WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> FormData::construct_impl(JS::Realm& realm, JS::GCPtr<HTML::HTMLFormElement> form)
WebIDL::ExceptionOr<GC::Ref<FormData>> FormData::construct_impl(JS::Realm& realm, GC::Ptr<HTML::HTMLFormElement> form)
{
Vector<FormDataEntry> list;
// 1. If form is given, then:
@ -35,12 +35,12 @@ WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> FormData::construct_impl(JS::Rea
return construct_impl(realm, move(list));
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> FormData::construct_impl(JS::Realm& realm, Vector<FormDataEntry> entry_list)
WebIDL::ExceptionOr<GC::Ref<FormData>> FormData::construct_impl(JS::Realm& realm, Vector<FormDataEntry> entry_list)
{
return realm.create<FormData>(realm, move(entry_list));
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> FormData::create(JS::Realm& realm, Vector<DOMURL::QueryParam> entry_list)
WebIDL::ExceptionOr<GC::Ref<FormData>> FormData::create(JS::Realm& realm, Vector<DOMURL::QueryParam> entry_list)
{
Vector<FormDataEntry> list;
list.ensure_capacity(entry_list.size());
@ -71,7 +71,7 @@ WebIDL::ExceptionOr<void> FormData::append(String const& name, String const& val
}
// https://xhr.spec.whatwg.org/#dom-formdata-append-blob
WebIDL::ExceptionOr<void> FormData::append(String const& name, JS::NonnullGCPtr<FileAPI::Blob> const& blob_value, Optional<String> const& filename)
WebIDL::ExceptionOr<void> FormData::append(String const& name, GC::Ref<FileAPI::Blob> const& blob_value, Optional<String> const& filename)
{
auto inner_filename = filename.has_value() ? filename.value() : Optional<String> {};
return append_impl(name, blob_value, inner_filename);
@ -79,7 +79,7 @@ WebIDL::ExceptionOr<void> FormData::append(String const& name, JS::NonnullGCPtr<
// https://xhr.spec.whatwg.org/#dom-formdata-append
// https://xhr.spec.whatwg.org/#dom-formdata-append-blob
WebIDL::ExceptionOr<void> FormData::append_impl(String const& name, Variant<JS::NonnullGCPtr<FileAPI::Blob>, String> const& value, Optional<String> const& filename)
WebIDL::ExceptionOr<void> FormData::append_impl(String const& name, Variant<GC::Ref<FileAPI::Blob>, String> const& value, Optional<String> const& filename)
{
auto& realm = this->realm();
auto& vm = realm.vm();
@ -103,7 +103,7 @@ void FormData::delete_(String const& name)
}
// https://xhr.spec.whatwg.org/#dom-formdata-get
Variant<JS::Handle<FileAPI::File>, String, Empty> FormData::get(String const& name)
Variant<GC::Root<FileAPI::File>, String, Empty> FormData::get(String const& name)
{
// 1. If there is no entry whose name is name in thiss entry list, then return null.
auto entry_iterator = m_entry_list.find_if([&name](FormDataEntry const& entry) {
@ -145,7 +145,7 @@ WebIDL::ExceptionOr<void> FormData::set(String const& name, String const& value)
}
// https://xhr.spec.whatwg.org/#dom-formdata-set-blob
WebIDL::ExceptionOr<void> FormData::set(String const& name, JS::NonnullGCPtr<FileAPI::Blob> const& blob_value, Optional<String> const& filename)
WebIDL::ExceptionOr<void> FormData::set(String const& name, GC::Ref<FileAPI::Blob> const& blob_value, Optional<String> const& filename)
{
auto inner_filename = filename.has_value() ? filename.value() : Optional<String> {};
return set_impl(name, blob_value, inner_filename);
@ -153,7 +153,7 @@ WebIDL::ExceptionOr<void> FormData::set(String const& name, JS::NonnullGCPtr<Fil
// https://xhr.spec.whatwg.org/#dom-formdata-set
// https://xhr.spec.whatwg.org/#dom-formdata-set-blob
WebIDL::ExceptionOr<void> FormData::set_impl(String const& name, Variant<JS::NonnullGCPtr<FileAPI::Blob>, String> const& value, Optional<String> const& filename)
WebIDL::ExceptionOr<void> FormData::set_impl(String const& name, Variant<GC::Ref<FileAPI::Blob>, String> const& value, Optional<String> const& filename)
{
auto& realm = this->realm();
auto& vm = realm.vm();

View file

@ -19,24 +19,24 @@ namespace Web::XHR {
// https://xhr.spec.whatwg.org/#interface-formdata
class FormData : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(FormData, Bindings::PlatformObject);
JS_DECLARE_ALLOCATOR(FormData);
GC_DECLARE_ALLOCATOR(FormData);
public:
virtual ~FormData() override;
static WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> construct_impl(JS::Realm&, JS::GCPtr<HTML::HTMLFormElement> form = {});
static WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> construct_impl(JS::Realm&, Vector<FormDataEntry> entry_list);
static WebIDL::ExceptionOr<GC::Ref<FormData>> construct_impl(JS::Realm&, GC::Ptr<HTML::HTMLFormElement> form = {});
static WebIDL::ExceptionOr<GC::Ref<FormData>> construct_impl(JS::Realm&, Vector<FormDataEntry> entry_list);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<FormData>> create(JS::Realm&, Vector<DOMURL::QueryParam> entry_list);
static WebIDL::ExceptionOr<GC::Ref<FormData>> create(JS::Realm&, Vector<DOMURL::QueryParam> entry_list);
WebIDL::ExceptionOr<void> append(String const& name, String const& value);
WebIDL::ExceptionOr<void> append(String const& name, JS::NonnullGCPtr<FileAPI::Blob> const& blob_value, Optional<String> const& filename = {});
WebIDL::ExceptionOr<void> append(String const& name, GC::Ref<FileAPI::Blob> const& blob_value, Optional<String> const& filename = {});
void delete_(String const& name);
Variant<JS::Handle<FileAPI::File>, String, Empty> get(String const& name);
Variant<GC::Root<FileAPI::File>, String, Empty> get(String const& name);
WebIDL::ExceptionOr<Vector<FormDataEntryValue>> get_all(String const& name);
bool has(String const& name);
WebIDL::ExceptionOr<void> set(String const& name, String const& value);
WebIDL::ExceptionOr<void> set(String const& name, JS::NonnullGCPtr<FileAPI::Blob> const& blob_value, Optional<String> const& filename = {});
WebIDL::ExceptionOr<void> set(String const& name, GC::Ref<FileAPI::Blob> const& blob_value, Optional<String> const& filename = {});
Vector<FormDataEntry> const& entry_list() const { return m_entry_list; }
@ -50,8 +50,8 @@ private:
virtual void initialize(JS::Realm&) override;
WebIDL::ExceptionOr<void> append_impl(String const& name, Variant<JS::NonnullGCPtr<FileAPI::Blob>, String> const& value, Optional<String> const& filename = {});
WebIDL::ExceptionOr<void> set_impl(String const& name, Variant<JS::NonnullGCPtr<FileAPI::Blob>, String> const& value, Optional<String> const& filename = {});
WebIDL::ExceptionOr<void> append_impl(String const& name, Variant<GC::Ref<FileAPI::Blob>, String> const& value, Optional<String> const& filename = {});
WebIDL::ExceptionOr<void> set_impl(String const& name, Variant<GC::Ref<FileAPI::Blob>, String> const& value, Optional<String> const& filename = {});
Vector<FormDataEntry> m_entry_list;
};

View file

@ -8,13 +8,13 @@
#include <AK/String.h>
#include <AK/Variant.h>
#include <LibJS/Heap/Handle.h>
#include <LibGC/Root.h>
#include <LibWeb/Forward.h>
namespace Web::XHR {
// https://xhr.spec.whatwg.org/#formdataentryvalue
using FormDataEntryValue = Variant<JS::Handle<FileAPI::File>, String>;
using FormDataEntryValue = Variant<GC::Root<FileAPI::File>, String>;
struct FormDataEntry {
String name;

View file

@ -24,9 +24,9 @@ void Intrinsics::create_web_prototype_and_constructor<FormDataIteratorPrototype>
namespace Web::XHR {
JS_DEFINE_ALLOCATOR(FormDataIterator);
GC_DEFINE_ALLOCATOR(FormDataIterator);
JS::NonnullGCPtr<FormDataIterator> FormDataIterator::create(FormData const& form_data, JS::Object::PropertyKind iterator_kind)
GC::Ref<FormDataIterator> FormDataIterator::create(FormData const& form_data, JS::Object::PropertyKind iterator_kind)
{
return form_data.realm().create<FormDataIterator>(form_data, iterator_kind);
}
@ -64,7 +64,7 @@ JS::Object* FormDataIterator::next()
return create_iterator_result_object(vm, JS::PrimitiveString::create(vm, entry.name), false);
auto entry_value = entry.value.visit(
[&](JS::Handle<FileAPI::File> const& file) -> JS::Value {
[&](GC::Root<FileAPI::File> const& file) -> JS::Value {
return file.cell();
},
[&](String const& string) -> JS::Value {

View file

@ -13,10 +13,10 @@ namespace Web::XHR {
class FormDataIterator : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(FormDataIterator, Bindings::PlatformObject);
JS_DECLARE_ALLOCATOR(FormDataIterator);
GC_DECLARE_ALLOCATOR(FormDataIterator);
public:
[[nodiscard]] static JS::NonnullGCPtr<FormDataIterator> create(FormData const&, JS::Object::PropertyKind iterator_kind);
[[nodiscard]] static GC::Ref<FormDataIterator> create(FormData const&, JS::Object::PropertyKind iterator_kind);
virtual ~FormDataIterator() override;
@ -28,7 +28,7 @@ private:
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Cell::Visitor&) override;
JS::NonnullGCPtr<FormData const> m_form_data;
GC::Ref<FormData const> m_form_data;
JS::Object::PropertyKind m_iterator_kind;
size_t m_index { 0 };
};

View file

@ -10,14 +10,14 @@
namespace Web::XHR {
JS_DEFINE_ALLOCATOR(ProgressEvent);
GC_DEFINE_ALLOCATOR(ProgressEvent);
JS::NonnullGCPtr<ProgressEvent> ProgressEvent::create(JS::Realm& realm, FlyString const& event_name, ProgressEventInit const& event_init)
GC::Ref<ProgressEvent> ProgressEvent::create(JS::Realm& realm, FlyString const& event_name, ProgressEventInit const& event_init)
{
return realm.create<ProgressEvent>(realm, event_name, event_init);
}
WebIDL::ExceptionOr<JS::NonnullGCPtr<ProgressEvent>> ProgressEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, ProgressEventInit const& event_init)
WebIDL::ExceptionOr<GC::Ref<ProgressEvent>> ProgressEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, ProgressEventInit const& event_init)
{
return create(realm, event_name, event_init);
}

View file

@ -20,11 +20,11 @@ struct ProgressEventInit : public DOM::EventInit {
class ProgressEvent final : public DOM::Event {
WEB_PLATFORM_OBJECT(ProgressEvent, DOM::Event);
JS_DECLARE_ALLOCATOR(ProgressEvent);
GC_DECLARE_ALLOCATOR(ProgressEvent);
public:
[[nodiscard]] static JS::NonnullGCPtr<ProgressEvent> create(JS::Realm&, FlyString const& event_name, ProgressEventInit const& event_init);
static WebIDL::ExceptionOr<JS::NonnullGCPtr<ProgressEvent>> construct_impl(JS::Realm&, FlyString const& event_name, ProgressEventInit const& event_init);
[[nodiscard]] static GC::Ref<ProgressEvent> create(JS::Realm&, FlyString const& event_name, ProgressEventInit const& event_init);
static WebIDL::ExceptionOr<GC::Ref<ProgressEvent>> construct_impl(JS::Realm&, FlyString const& event_name, ProgressEventInit const& event_init);
virtual ~ProgressEvent() override;

View file

@ -56,9 +56,9 @@
namespace Web::XHR {
JS_DEFINE_ALLOCATOR(XMLHttpRequest);
GC_DEFINE_ALLOCATOR(XMLHttpRequest);
WebIDL::ExceptionOr<JS::NonnullGCPtr<XMLHttpRequest>> XMLHttpRequest::construct_impl(JS::Realm& realm)
WebIDL::ExceptionOr<GC::Ref<XMLHttpRequest>> XMLHttpRequest::construct_impl(JS::Realm& realm)
{
auto upload_object = realm.create<XMLHttpRequestUpload>(realm);
auto author_request_headers = Fetch::Infrastructure::HeaderList::create(realm.vm());
@ -95,7 +95,7 @@ void XMLHttpRequest::visit_edges(Cell::Visitor& visitor)
visitor.visit(m_response);
visitor.visit(m_fetch_controller);
if (auto* value = m_response_object.get_pointer<JS::NonnullGCPtr<JS::Object>>())
if (auto* value = m_response_object.get_pointer<GC::Ref<JS::Object>>())
visitor.visit(*value);
}
@ -129,7 +129,7 @@ WebIDL::ExceptionOr<String> XMLHttpRequest::response_text() const
}
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsexml
WebIDL::ExceptionOr<JS::GCPtr<DOM::Document>> XMLHttpRequest::response_xml()
WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> XMLHttpRequest::response_xml()
{
// 1. If thiss response type is not the empty string or "document", then throw an "InvalidStateError" DOMException.
if (m_response_type != Bindings::XMLHttpRequestResponseType::Empty && m_response_type != Bindings::XMLHttpRequestResponseType::Document)
@ -144,7 +144,7 @@ WebIDL::ExceptionOr<JS::GCPtr<DOM::Document>> XMLHttpRequest::response_xml()
// 4. If thiss response object is non-null, then return it.
if (!m_response_object.has<Empty>())
return &verify_cast<DOM::Document>(*m_response_object.get<JS::NonnullGCPtr<JS::Object>>());
return &verify_cast<DOM::Document>(*m_response_object.get<GC::Ref<JS::Object>>());
// 5. Set a document response for this.
set_document_response();
@ -152,7 +152,7 @@ WebIDL::ExceptionOr<JS::GCPtr<DOM::Document>> XMLHttpRequest::response_xml()
// 6. Return thiss response object.
if (m_response_object.has<Empty>())
return nullptr;
return &verify_cast<DOM::Document>(*m_response_object.get<JS::NonnullGCPtr<JS::Object>>());
return &verify_cast<DOM::Document>(*m_response_object.get<GC::Ref<JS::Object>>());
}
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-responsetype
@ -199,7 +199,7 @@ WebIDL::ExceptionOr<JS::Value> XMLHttpRequest::response()
// 4. If thiss response object is non-null, then return it.
if (!m_response_object.has<Empty>())
return m_response_object.get<JS::NonnullGCPtr<JS::Object>>();
return m_response_object.get<GC::Ref<JS::Object>>();
// 5. If thiss response type is "arraybuffer",
if (m_response_type == Bindings::XMLHttpRequestResponseType::Arraybuffer) {
@ -212,14 +212,14 @@ WebIDL::ExceptionOr<JS::Value> XMLHttpRequest::response()
auto buffer = buffer_result.release_value();
buffer->buffer().overwrite(0, m_received_bytes.data(), m_received_bytes.size());
m_response_object = JS::NonnullGCPtr<JS::Object> { buffer };
m_response_object = GC::Ref<JS::Object> { buffer };
}
// 6. Otherwise, if thiss response type is "blob", set thiss response object to a new Blob object representing thiss received bytes with type set to the result of get a final MIME type for this.
else if (m_response_type == Bindings::XMLHttpRequestResponseType::Blob) {
auto mime_type_as_string = get_final_mime_type().serialized();
auto blob_part = FileAPI::Blob::create(realm(), m_received_bytes, move(mime_type_as_string));
auto blob = FileAPI::Blob::create(realm(), Vector<FileAPI::BlobPart> { JS::make_handle(*blob_part) });
m_response_object = JS::NonnullGCPtr<JS::Object> { blob };
auto blob = FileAPI::Blob::create(realm(), Vector<FileAPI::BlobPart> { GC::make_root(*blob_part) });
m_response_object = GC::Ref<JS::Object> { blob };
}
// 7. Otherwise, if thiss response type is "document", set a document response for this.
else if (m_response_type == Bindings::XMLHttpRequestResponseType::Document) {
@ -241,14 +241,14 @@ WebIDL::ExceptionOr<JS::Value> XMLHttpRequest::response()
// 4. Set thiss response object to jsonObject.
if (json_object_result.value().is_object())
m_response_object = JS::NonnullGCPtr<JS::Object> { json_object_result.release_value().as_object() };
m_response_object = GC::Ref<JS::Object> { json_object_result.release_value().as_object() };
else
m_response_object = Empty {};
}
// 9. Return thiss response object.
return m_response_object.visit(
[](JS::NonnullGCPtr<JS::Object> object) -> JS::Value { return object; },
[](GC::Ref<JS::Object> object) -> JS::Value { return object; },
[](auto const&) -> JS::Value { return JS::js_null(); });
}
@ -300,7 +300,7 @@ void XMLHttpRequest::set_document_response()
// 5. If finalMIME is an HTML MIME type, then:
Optional<String> charset;
JS::GCPtr<DOM::Document> document;
GC::Ptr<DOM::Document> document;
if (final_mime.is_html()) {
// 5.1. Let charset be the result of get a final encoding for xhr.
if (auto final_encoding = get_final_encoding(); final_encoding.has_value())
@ -350,7 +350,7 @@ void XMLHttpRequest::set_document_response()
document->set_origin(HTML::relevant_settings_object(*this).origin());
// 12. Set xhrs response object to document.
m_response_object = JS::NonnullGCPtr<JS::Object> { *document };
m_response_object = GC::Ref<JS::Object> { *document };
}
// https://xhr.spec.whatwg.org/#final-mime-type
@ -572,8 +572,8 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
Optional<ByteBuffer> extracted_content_type;
// 2. If body is a Document, then set thiss request body to body, serialized, converted, and UTF-8 encoded.
if (body->has<JS::Handle<DOM::Document>>()) {
auto string_serialized_document = TRY(body->get<JS::Handle<DOM::Document>>().cell()->serialize_fragment(DOMParsing::RequireWellFormed::No));
if (body->has<GC::Root<DOM::Document>>()) {
auto string_serialized_document = TRY(body->get<GC::Root<DOM::Document>>().cell()->serialize_fragment(DOMParsing::RequireWellFormed::No));
m_request_body = TRY(Fetch::Infrastructure::byte_sequence_as_body(realm, string_serialized_document.bytes()));
}
// 3. Otherwise:
@ -594,7 +594,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// 5. If originalAuthorContentType is non-null, then:
if (original_author_content_type.has_value()) {
// 1. If body is a Document or a USVString, then:
if (body->has<JS::Handle<DOM::Document>>() || body->has<String>()) {
if (body->has<GC::Root<DOM::Document>>() || body->has<String>()) {
// 1. Let contentTypeRecord be the result of parsing originalAuthorContentType.
auto content_type_record = MimeSniff::MimeType::parse(original_author_content_type.value());
@ -617,8 +617,8 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
}
// 6. Otherwise:
else {
if (body->has<JS::Handle<DOM::Document>>()) {
auto document = body->get<JS::Handle<DOM::Document>>();
if (body->has<GC::Root<DOM::Document>>()) {
auto document = body->get<GC::Root<DOM::Document>>();
// NOTE: A document can only be an HTML document or XML document.
// 1. If body is an HTML document, then set (`Content-Type`, `text/html;charset=UTF-8`) in thiss author request headers.
@ -667,7 +667,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// body
// Thiss request body.
if (m_request_body)
request->set_body(JS::NonnullGCPtr { *m_request_body });
request->set_body(GC::Ref { *m_request_body });
// client
// Thiss relevant settings object.
@ -738,7 +738,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// 7. Let processRequestBodyChunkLength, given a bytesLength, be these steps:
// NOTE: request_body_length is captured by copy as to not UAF it when we leave `send()` and the callback gets called.
// NOTE: `this` is kept alive by FetchAlgorithms using JS::HeapFunction.
// NOTE: `this` is kept alive by FetchAlgorithms using GC::HeapFunction.
auto process_request_body_chunk_length = [this, request_body_length](u64 bytes_length) {
// 1. Increase requestBodyTransmitted by bytesLength.
m_request_body_transmitted += bytes_length;
@ -752,7 +752,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// 8. Let processRequestEndOfBody be these steps:
// NOTE: request_body_length is captured by copy as to not UAF it when we leave `send()` and the callback gets called.
// NOTE: `this` is kept alive by FetchAlgorithms using JS::HeapFunction.
// NOTE: `this` is kept alive by FetchAlgorithms using GC::HeapFunction.
auto process_request_end_of_body = [this, request_body_length]() {
// 1. Set thiss upload complete flag.
m_upload_complete = true;
@ -772,8 +772,8 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
};
// 9. Let processResponse, given a response, be these steps:
// NOTE: `this` is kept alive by FetchAlgorithms using JS::HeapFunction.
auto process_response = [this](JS::NonnullGCPtr<Fetch::Infrastructure::Response> response) {
// NOTE: `this` is kept alive by FetchAlgorithms using GC::HeapFunction.
auto process_response = [this](GC::Ref<Fetch::Infrastructure::Response> response) {
// 1. Set thiss response to response.
m_response = response;
@ -816,7 +816,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// FIXME: We can't implement these steps yet, as we don't fully implement the Streams standard.
// 10. Let processBodyChunk given bytes be these steps:
auto process_body_chunks = JS::create_heap_function(heap(), [this, length](ByteBuffer byte_buffer) {
auto process_body_chunks = GC::create_function(heap(), [this, length](ByteBuffer byte_buffer) {
// 1. Append bytes to thiss received bytes.
m_received_bytes.append(byte_buffer);
@ -835,14 +835,14 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
});
// 11. Let processEndOfBody be this step: run handle response end-of-body for this.
auto process_end_of_body = JS::create_heap_function(heap(), [this]() {
auto process_end_of_body = GC::create_function(heap(), [this]() {
// NOTE: This cannot throw, as `handle_response_end_of_body` only throws in a synchronous context.
// FIXME: However, we can receive allocation failures, but we can't propagate them anywhere currently.
handle_response_end_of_body().release_value_but_fixme_should_propagate_errors();
});
// 12. Let processBodyError be these steps:
auto process_body_error = JS::create_heap_function(heap(), [this](JS::Value) {
auto process_body_error = GC::create_function(heap(), [this](JS::Value) {
auto& vm = this->vm();
// 1. Set thiss response to a network error.
m_response = Fetch::Infrastructure::Response::network_error(vm, "A network error occurred processing body."sv);
@ -853,7 +853,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
});
// 13. Incrementally read thiss responses body, given processBodyChunk, processEndOfBody, processBodyError, and thiss relevant global object.
auto global_object = JS::NonnullGCPtr<JS::Object> { HTML::relevant_global_object(*this) };
auto global_object = GC::Ref<JS::Object> { HTML::relevant_global_object(*this) };
response->body()->incrementally_read(process_body_chunks, process_end_of_body, process_body_error, global_object);
};
@ -880,7 +880,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
// NOTE: `timer` is kept alive by capturing into the lambda for the GC to see
// NOTE: `this` and `request` is kept alive by Platform::Timer using a Handle.
timer->on_timeout = JS::create_heap_function(heap(), [this, request, timer = JS::make_handle(timer)]() {
timer->on_timeout = GC::create_function(heap(), [this, request, timer = GC::make_root(timer)]() {
(void)timer;
if (!request->done()) {
m_timed_out = true;
@ -895,7 +895,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
bool processed_response = false;
// 2. Let processResponseConsumeBody, given a response and nullOrFailureOrBytes, be these steps:
auto process_response_consume_body = [this, &processed_response](JS::NonnullGCPtr<Fetch::Infrastructure::Response> response, Variant<Empty, Fetch::Infrastructure::FetchAlgorithms::ConsumeBodyFailureTag, ByteBuffer> null_or_failure_or_bytes) {
auto process_response_consume_body = [this, &processed_response](GC::Ref<Fetch::Infrastructure::Response> response, Variant<Empty, Fetch::Infrastructure::FetchAlgorithms::ConsumeBodyFailureTag, ByteBuffer> null_or_failure_or_bytes) {
// 1. If nullOrFailureOrBytes is not failure, then set thiss response to response.
if (!null_or_failure_or_bytes.has<Fetch::Infrastructure::FetchAlgorithms::ConsumeBodyFailureTag>())
m_response = response;
@ -933,7 +933,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
auto timer = Platform::Timer::create_single_shot(heap(), m_timeout, nullptr);
// NOTE: `timer` is kept alive by capturing into the lambda for the GC to see
timer->on_timeout = JS::create_heap_function(heap(), [timer = JS::make_handle(timer), &did_time_out]() {
timer->on_timeout = GC::create_function(heap(), [timer = GC::make_root(timer), &did_time_out]() {
(void)timer;
did_time_out = true;
});
@ -942,7 +942,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::send(Optional<DocumentOrXMLHttpRequest
}
// FIXME: This is not exactly correct, as it allows the HTML event loop to continue executing tasks.
Platform::EventLoopPlugin::the().spin_until(JS::create_heap_function(heap(), [&]() {
Platform::EventLoopPlugin::the().spin_until(GC::create_function(heap(), [&]() {
return processed_response || did_time_out;
}));
@ -1145,7 +1145,7 @@ void XMLHttpRequest::abort()
}
// https://xhr.spec.whatwg.org/#dom-xmlhttprequest-upload
JS::NonnullGCPtr<XMLHttpRequestUpload> XMLHttpRequest::upload() const
GC::Ref<XMLHttpRequestUpload> XMLHttpRequest::upload() const
{
// The upload getter steps are to return thiss upload object.
return m_upload_object;
@ -1236,7 +1236,7 @@ WebIDL::ExceptionOr<void> XMLHttpRequest::handle_errors()
return {};
}
JS::ThrowCompletionOr<void> XMLHttpRequest::request_error_steps(FlyString const& event_name, JS::GCPtr<WebIDL::DOMException> exception)
JS::ThrowCompletionOr<void> XMLHttpRequest::request_error_steps(FlyString const& event_name, GC::Ptr<WebIDL::DOMException> exception)
{
// 1. Set xhrs state to done.
m_state = State::Done;

View file

@ -26,11 +26,11 @@
namespace Web::XHR {
// https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit
using DocumentOrXMLHttpRequestBodyInit = Variant<JS::Handle<Web::DOM::Document>, JS::Handle<Web::FileAPI::Blob>, JS::Handle<WebIDL::BufferSource>, JS::Handle<XHR::FormData>, JS::Handle<Web::DOMURL::URLSearchParams>, AK::String>;
using DocumentOrXMLHttpRequestBodyInit = Variant<GC::Root<Web::DOM::Document>, GC::Root<Web::FileAPI::Blob>, GC::Root<WebIDL::BufferSource>, GC::Root<XHR::FormData>, GC::Root<Web::DOMURL::URLSearchParams>, AK::String>;
class XMLHttpRequest final : public XMLHttpRequestEventTarget {
WEB_PLATFORM_OBJECT(XMLHttpRequest, XMLHttpRequestEventTarget);
JS_DECLARE_ALLOCATOR(XMLHttpRequest);
GC_DECLARE_ALLOCATOR(XMLHttpRequest);
public:
enum class State : u16 {
@ -41,7 +41,7 @@ public:
Done = 4,
};
static WebIDL::ExceptionOr<JS::NonnullGCPtr<XMLHttpRequest>> construct_impl(JS::Realm&);
static WebIDL::ExceptionOr<GC::Ref<XMLHttpRequest>> construct_impl(JS::Realm&);
virtual ~XMLHttpRequest() override;
@ -49,7 +49,7 @@ public:
Fetch::Infrastructure::Status status() const;
WebIDL::ExceptionOr<String> status_text() const;
WebIDL::ExceptionOr<String> response_text() const;
WebIDL::ExceptionOr<JS::GCPtr<DOM::Document>> response_xml();
WebIDL::ExceptionOr<GC::Ptr<DOM::Document>> response_xml();
WebIDL::ExceptionOr<JS::Value> response();
Bindings::XMLHttpRequestResponseType response_type() const { return m_response_type; }
String response_url();
@ -77,7 +77,7 @@ public:
void abort();
JS::NonnullGCPtr<XMLHttpRequestUpload> upload() const;
GC::Ref<XMLHttpRequestUpload> upload() const;
private:
virtual void initialize(JS::Realm&) override;
@ -93,14 +93,14 @@ private:
WebIDL::ExceptionOr<void> handle_response_end_of_body();
WebIDL::ExceptionOr<void> handle_errors();
JS::ThrowCompletionOr<void> request_error_steps(FlyString const& event_name, JS::GCPtr<WebIDL::DOMException> exception = nullptr);
JS::ThrowCompletionOr<void> request_error_steps(FlyString const& event_name, GC::Ptr<WebIDL::DOMException> exception = nullptr);
XMLHttpRequest(JS::Realm&, XMLHttpRequestUpload&, Fetch::Infrastructure::HeaderList&, Fetch::Infrastructure::Response&, Fetch::Infrastructure::FetchController&);
// https://xhr.spec.whatwg.org/#upload-object
// upload object
// An XMLHttpRequestUpload object.
JS::NonnullGCPtr<XMLHttpRequestUpload> m_upload_object;
GC::Ref<XMLHttpRequestUpload> m_upload_object;
// https://xhr.spec.whatwg.org/#concept-xmlhttprequest-state
// state
@ -135,12 +135,12 @@ private:
// https://xhr.spec.whatwg.org/#author-request-headers
// author request headers
// A header list, initially empty.
JS::NonnullGCPtr<Fetch::Infrastructure::HeaderList> m_author_request_headers;
GC::Ref<Fetch::Infrastructure::HeaderList> m_author_request_headers;
// https://xhr.spec.whatwg.org/#request-body
// request body
// Initially null.
JS::GCPtr<Fetch::Infrastructure::Body> m_request_body;
GC::Ptr<Fetch::Infrastructure::Body> m_request_body;
// https://xhr.spec.whatwg.org/#synchronous-flag
// synchronous flag
@ -165,7 +165,7 @@ private:
// https://xhr.spec.whatwg.org/#response
// response
// A response, initially a network error.
JS::NonnullGCPtr<Fetch::Infrastructure::Response> m_response;
GC::Ref<Fetch::Infrastructure::Response> m_response;
// https://xhr.spec.whatwg.org/#received-bytes
// received bytes
@ -185,13 +185,13 @@ private:
// response object
// An object, failure, or null, initially null.
// NOTE: This needs to be a JS::Value as the JSON response might not actually be an object.
Variant<JS::NonnullGCPtr<JS::Object>, Failure, Empty> m_response_object;
Variant<GC::Ref<JS::Object>, Failure, Empty> m_response_object;
// https://xhr.spec.whatwg.org/#xmlhttprequest-fetch-controller
// fetch controller
// A fetch controller, initially a new fetch controller.
// NOTE: The send() method sets it to a useful fetch controller, but for simplicity it always holds a fetch controller.
JS::NonnullGCPtr<Fetch::Infrastructure::FetchController> m_fetch_controller;
GC::Ref<Fetch::Infrastructure::FetchController> m_fetch_controller;
// https://xhr.spec.whatwg.org/#override-mime-type
// override MIME type

View file

@ -10,7 +10,7 @@
namespace Web::XHR {
JS_DEFINE_ALLOCATOR(XMLHttpRequestUpload);
GC_DEFINE_ALLOCATOR(XMLHttpRequestUpload);
XMLHttpRequestUpload::XMLHttpRequestUpload(JS::Realm& realm)
: XMLHttpRequestEventTarget(realm)

View file

@ -12,7 +12,7 @@ namespace Web::XHR {
class XMLHttpRequestUpload : public XMLHttpRequestEventTarget {
WEB_PLATFORM_OBJECT(XMLHttpRequestUpload, XMLHttpRequestEventTarget);
JS_DECLARE_ALLOCATOR(XMLHttpRequestUpload);
GC_DECLARE_ALLOCATOR(XMLHttpRequestUpload);
public:
virtual ~XMLHttpRequestUpload() override;