diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp index 7881996494..1c5486f940 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/WrapperGenerator/IDLGenerators.cpp @@ -159,6 +159,10 @@ static bool impl_is_wrapper(Type const& type) return true; if (type.name == "Storage"sv) return true; + if (type.name == "File"sv) + return true; + if (type.name == "Blob"sv) + return true; return false; } diff --git a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.h b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.h index 424023b6c1..f487874fa0 100644 --- a/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.h +++ b/Userland/Libraries/LibWeb/Fetch/Infrastructure/HTTP/Bodies.h @@ -18,7 +18,7 @@ namespace Web::Fetch::Infrastructure { // https://fetch.spec.whatwg.org/#concept-body class Body final { public: - using SourceType = Variant>; + using SourceType = Variant>; struct ReadableStreamDummy { }; diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp index 69f912e00f..f839062ef4 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.cpp @@ -7,12 +7,19 @@ #include #include #include +#include #include #include #include +#include namespace Web::FileAPI { +DOM::ExceptionOr> Blob::create(HTML::Window& window, ByteBuffer byte_buffer, String type) +{ + return JS::NonnullGCPtr(*window.heap().allocate(window.realm(), window, move(byte_buffer), move(type))); +} + // https://w3c.github.io/FileAPI/#convert-line-endings-to-native ErrorOr convert_line_endings_to_native(String const& string) { @@ -88,7 +95,7 @@ ErrorOr process_blob_parts(Vector const& blob_parts, Optio return bytes.try_append(data_buffer.bytes()); }, // 3. If element is a Blob, append the bytes it represents to bytes. - [&](NonnullRefPtr const& blob) -> ErrorOr { + [&](JS::Handle const& blob) -> ErrorOr { return bytes.try_append(blob->bytes()); })); } @@ -105,25 +112,35 @@ bool is_basic_latin(StringView view) return true; } -Blob::Blob(ByteBuffer byte_buffer, String type) - : m_byte_buffer(move(byte_buffer)) - , m_type(move(type)) +Blob::Blob(HTML::Window& window) + : PlatformObject(window.realm()) { + set_prototype(&window.cached_web_prototype("Blob")); } -Blob::Blob(ByteBuffer byte_buffer) - : m_byte_buffer(move(byte_buffer)) +Blob::Blob(HTML::Window& window, ByteBuffer byte_buffer, String type) + : PlatformObject(window.realm()) + , m_byte_buffer(move(byte_buffer)) + , m_type(move(type)) { + set_prototype(&window.cached_web_prototype("Blob")); +} + +Blob::Blob(HTML::Window& window, ByteBuffer byte_buffer) + : PlatformObject(window.realm()) + , m_byte_buffer(move(byte_buffer)) +{ + set_prototype(&window.cached_web_prototype("Blob")); } Blob::~Blob() = default; // https://w3c.github.io/FileAPI/#ref-for-dom-blob-blob -DOM::ExceptionOr> Blob::create(Optional> const& blob_parts, Optional const& options) +DOM::ExceptionOr> Blob::create(HTML::Window& window, Optional> const& blob_parts, Optional const& options) { // 1. If invoked with zero parameters, return a new Blob object consisting of 0 bytes, with size set to 0, and with type set to the empty string. if (!blob_parts.has_value() && !options.has_value()) - return adopt_ref(*new Blob()); + return JS::NonnullGCPtr(*window.heap().allocate(window.realm(), window)); ByteBuffer byte_buffer {}; // 2. Let bytes be the result of processing blob parts given blobParts and options. @@ -148,16 +165,16 @@ DOM::ExceptionOr> Blob::create(Optional> co } // 4. Return a Blob object referring to bytes as its associated byte sequence, with its size set to the length of bytes, and its type set to the value of t from the substeps above. - return adopt_ref(*new Blob(move(byte_buffer), move(type))); + return JS::NonnullGCPtr(*window.heap().allocate(window.realm(), window, move(byte_buffer), move(type))); } -DOM::ExceptionOr> Blob::create_with_global_object(HTML::Window&, Optional> const& blob_parts, Optional const& options) +DOM::ExceptionOr> Blob::create_with_global_object(HTML::Window& window, Optional> const& blob_parts, Optional const& options) { - return Blob::create(blob_parts, options); + return Blob::create(window, blob_parts, options); } // https://w3c.github.io/FileAPI/#dfn-slice -DOM::ExceptionOr> Blob::slice(Optional start, Optional end, Optional const& content_type) +DOM::ExceptionOr> Blob::slice(Optional start, Optional end, Optional const& content_type) { // 1. The optional start parameter is a value for the start point of a slice() call, and must be treated as a byte-order position, with the zeroth position representing the first byte. // User agents must process slice() with start normalized according to the following: @@ -217,22 +234,19 @@ DOM::ExceptionOr> Blob::slice(Optional start, Optional< // b. S.size = span. // c. S.type = relativeContentType. auto byte_buffer = TRY_OR_RETURN_OOM(m_byte_buffer.slice(relative_start, span)); - return adopt_ref(*new Blob(move(byte_buffer), move(relative_content_type))); + return JS::NonnullGCPtr(*heap().allocate(realm(), global_object(), move(byte_buffer), move(relative_content_type))); } // https://w3c.github.io/FileAPI/#dom-blob-text JS::Promise* Blob::text() { - auto& vm = wrapper()->vm(); - auto& realm = *vm.current_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(realm); - auto* result = JS::js_string(vm, String { m_byte_buffer.bytes() }); + auto* promise = JS::Promise::create(realm()); + auto* result = JS::js_string(vm(), 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. promise->fulfill(result); @@ -242,16 +256,13 @@ JS::Promise* Blob::text() // https://w3c.github.io/FileAPI/#dom-blob-arraybuffer JS::Promise* Blob::array_buffer() { - auto& vm = wrapper()->vm(); - auto& realm = *vm.current_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(realm); - auto buffer_result = JS::ArrayBuffer::create(realm, 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; diff --git a/Userland/Libraries/LibWeb/FileAPI/Blob.h b/Userland/Libraries/LibWeb/FileAPI/Blob.h index 0513db6eae..2661096b6a 100644 --- a/Userland/Libraries/LibWeb/FileAPI/Blob.h +++ b/Userland/Libraries/LibWeb/FileAPI/Blob.h @@ -7,18 +7,16 @@ #pragma once #include -#include #include #include #include -#include +#include #include #include -#include namespace Web::FileAPI { -using BlobPart = Variant, NonnullRefPtr, String>; +using BlobPart = Variant, JS::Handle, String>; struct BlobPropertyBag { String type = String::empty(); @@ -29,26 +27,22 @@ struct BlobPropertyBag { [[nodiscard]] ErrorOr process_blob_parts(Vector const& blob_parts, Optional const& options = {}); [[nodiscard]] bool is_basic_latin(StringView view); -class Blob - : public RefCounted - , public Weakable - , public Bindings::Wrappable { +class Blob : public Bindings::PlatformObject { + WEB_PLATFORM_OBJECT(Blob, Bindings::PlatformObject); public: - using WrapperType = Bindings::BlobWrapper; - Blob(ByteBuffer byte_buffer, String type); - virtual ~Blob() override; - static DOM::ExceptionOr> create(Optional> const& blob_parts = {}, Optional const& options = {}); - static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Optional> const& blob_parts = {}, Optional const& options = {}); + static DOM::ExceptionOr> create(HTML::Window&, Optional> const& blob_parts = {}, Optional const& options = {}); + static DOM::ExceptionOr> create(HTML::Window&, ByteBuffer, String type); + static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Optional> const& blob_parts = {}, Optional const& options = {}); // https://w3c.github.io/FileAPI/#dfn-size u64 size() const { return m_byte_buffer.size(); } // https://w3c.github.io/FileAPI/#dfn-type String const& type() const { return m_type; } - DOM::ExceptionOr> slice(Optional start = {}, Optional end = {}, Optional const& content_type = {}); + DOM::ExceptionOr> slice(Optional start = {}, Optional end = {}, Optional const& content_type = {}); JS::Promise* text(); JS::Promise* array_buffer(); @@ -56,13 +50,16 @@ public: ReadonlyBytes bytes() const { return m_byte_buffer.bytes(); } protected: - Blob(ByteBuffer byte_buffer); + Blob(HTML::Window&, ByteBuffer, String type); + Blob(HTML::Window&, ByteBuffer); private: - Blob() = default; + explicit Blob(HTML::Window&); ByteBuffer m_byte_buffer {}; String m_type {}; }; } + +WRAPPER_HACK(Blob, Web::FileAPI) diff --git a/Userland/Libraries/LibWeb/FileAPI/File.cpp b/Userland/Libraries/LibWeb/FileAPI/File.cpp index b982869ed2..af004640d9 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.cpp +++ b/Userland/Libraries/LibWeb/FileAPI/File.cpp @@ -5,18 +5,22 @@ */ #include +#include namespace Web::FileAPI { -File::File(ByteBuffer byte_buffer, String file_name, String type, i64 last_modified) - : Blob(move(byte_buffer), move(type)) +File::File(HTML::Window& window, ByteBuffer byte_buffer, String file_name, String type, i64 last_modified) + : Blob(window, move(byte_buffer), move(type)) , m_name(move(file_name)) , m_last_modified(last_modified) { + set_prototype(&window.cached_web_prototype("File")); } +File::~File() = default; + // https://w3c.github.io/FileAPI/#ref-for-dom-file-file -DOM::ExceptionOr> File::create(Vector const& file_bits, String const& file_name, Optional const& options) +DOM::ExceptionOr> File::create(HTML::Window& window, Vector const& file_bits, String const& file_name, Optional const& options) { // 1. Let bytes be the result of processing blob parts given fileBits and options. auto bytes = TRY_OR_RETURN_OOM(process_blob_parts(file_bits, static_cast const&>(*options))); @@ -53,12 +57,12 @@ DOM::ExceptionOr> File::create(Vector const& file_ // 4. F.name is set to n. // 5. F.type is set to t. // 6. F.lastModified is set to d. - return adopt_ref(*new File(move(bytes), move(name), move(type), last_modified)); + return JS::NonnullGCPtr(*window.heap().allocate(window.realm(), window, move(bytes), move(name), move(type), last_modified)); } -DOM::ExceptionOr> File::create_with_global_object(HTML::Window&, Vector const& file_bits, String const& file_name, Optional const& options) +DOM::ExceptionOr> File::create_with_global_object(HTML::Window& window, Vector const& file_bits, String const& file_name, Optional const& options) { - return create(file_bits, file_name, options); + return create(window, file_bits, file_name, options); } } diff --git a/Userland/Libraries/LibWeb/FileAPI/File.h b/Userland/Libraries/LibWeb/FileAPI/File.h index 43a8008055..e348e4d37e 100644 --- a/Userland/Libraries/LibWeb/FileAPI/File.h +++ b/Userland/Libraries/LibWeb/FileAPI/File.h @@ -16,12 +16,13 @@ struct FilePropertyBag : BlobPropertyBag { }; class File : public Blob { + WEB_PLATFORM_OBJECT(File, Blob); public: - using WrapperType = Bindings::FileWrapper; + static DOM::ExceptionOr> create(HTML::Window&, Vector const& file_bits, String const& file_name, Optional const& options = {}); + static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Vector const& file_bits, String const& file_name, Optional const& options = {}); - static DOM::ExceptionOr> create(Vector const& file_bits, String const& file_name, Optional const& options = {}); - static DOM::ExceptionOr> create_with_global_object(HTML::Window&, Vector const& file_bits, String const& file_name, Optional const& options = {}); + virtual ~File() override; // https://w3c.github.io/FileAPI/#dfn-name String const& name() const { return m_name; } @@ -29,10 +30,12 @@ public: i64 last_modified() const { return m_last_modified; } private: - File(ByteBuffer byte_buffer, String file_name, String type, i64 last_modified); + File(HTML::Window&, ByteBuffer, String file_name, String type, i64 last_modified); String m_name; i64 m_last_modified { 0 }; }; } + +WRAPPER_HACK(File, Web::FileAPI) diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 3f125a72d8..e8a627ab33 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -448,10 +448,8 @@ class URLSearchParamsIterator; } namespace Web::Bindings { -class BlobWrapper; class CryptoWrapper; class DOMExceptionWrapper; -class FileWrapper; class HeadersWrapper; class HeadersIteratorWrapper; class IdleDeadlineWrapper; diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp index ef447298c1..56e6a7c764 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include @@ -133,9 +132,9 @@ DOM::ExceptionOr XMLHttpRequest::response() } // 6. Otherwise, if this’s response type is "blob", set this’s response object to a new Blob object representing this’s 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 blob_part = TRY_OR_RETURN_OOM(try_make_ref_counted(m_received_bytes, get_final_mime_type().type())); - auto blob = TRY(FileAPI::Blob::create(Vector { move(blob_part) })); - m_response_object = JS::Value(wrap(realm(), *blob)); + auto blob_part = TRY(FileAPI::Blob::create(global_object(), m_received_bytes, get_final_mime_type().type())); + auto blob = TRY(FileAPI::Blob::create(global_object(), Vector { JS::make_handle(*blob_part) })); + m_response_object = JS::Value(blob.ptr()); } // 7. Otherwise, if this’s response type is "document", set a document response for this. else if (m_response_type == Bindings::XMLHttpRequestResponseType::Document) { @@ -286,7 +285,7 @@ static ErrorOr extract_body(XMLHttpRequestB // 6. Switch on object. // FIXME: Still need to support BufferSource and FormData TRY(body_init.visit( - [&](NonnullRefPtr const& blob) -> ErrorOr { + [&](JS::Handle const& blob) -> ErrorOr { // FIXME: Set action to this step: read object. // Set source to object. source = blob; @@ -493,7 +492,7 @@ DOM::ExceptionOr XMLHttpRequest::send(Optional bod request.set_body(buffer); return {}; }, - [&](NonnullRefPtr const& blob) -> ErrorOr { + [&](JS::Handle const& blob) -> ErrorOr { auto byte_buffer = TRY(ByteBuffer::copy(blob->bytes())); request.set_body(byte_buffer); return {}; diff --git a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h index 7c47eb404f..edea21ab67 100644 --- a/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h +++ b/Userland/Libraries/LibWeb/XHR/XMLHttpRequest.h @@ -24,7 +24,7 @@ namespace Web::XHR { // https://fetch.spec.whatwg.org/#typedefdef-xmlhttprequestbodyinit -using XMLHttpRequestBodyInit = Variant, JS::Handle, NonnullRefPtr, String>; +using XMLHttpRequestBodyInit = Variant, JS::Handle, NonnullRefPtr, String>; class XMLHttpRequest final : public XMLHttpRequestEventTarget { WEB_PLATFORM_OBJECT(XMLHttpRequest, XMLHttpRequestEventTarget); diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 47d5f3476a..0307450c85 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -54,8 +54,8 @@ libweb_js_wrapper(DOMParsing/XMLSerializer NO_INSTANCE) libweb_js_wrapper(Encoding/TextDecoder NO_INSTANCE) libweb_js_wrapper(Encoding/TextEncoder NO_INSTANCE) libweb_js_wrapper(Fetch/Headers ITERABLE) -libweb_js_wrapper(FileAPI/Blob) -libweb_js_wrapper(FileAPI/File) +libweb_js_wrapper(FileAPI/Blob NO_INSTANCE) +libweb_js_wrapper(FileAPI/File NO_INSTANCE) libweb_js_wrapper(Geometry/DOMPoint NO_INSTANCE) libweb_js_wrapper(Geometry/DOMPointReadOnly NO_INSTANCE) libweb_js_wrapper(Geometry/DOMRect NO_INSTANCE)