Browse Source

LibWeb: Implement HTML::ImageBitmap

And the two methods of `WindowOrWorkerGlobalScope` that are used as
constructors for it.
Lucas CHOLLET 1 year ago
parent
commit
676fc5e8c6

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -354,6 +354,7 @@ set(SOURCES
     HTML/HTMLUListElement.cpp
     HTML/HTMLUListElement.cpp
     HTML/HTMLUnknownElement.cpp
     HTML/HTMLUnknownElement.cpp
     HTML/HTMLVideoElement.cpp
     HTML/HTMLVideoElement.cpp
+    HTML/ImageBitmap.cpp
     HTML/ImageData.cpp
     HTML/ImageData.cpp
     HTML/ImageRequest.cpp
     HTML/ImageRequest.cpp
     HTML/ListOfAvailableImages.cpp
     HTML/ListOfAvailableImages.cpp

+ 1 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -423,6 +423,7 @@ class HTMLTrackElement;
 class HTMLUListElement;
 class HTMLUListElement;
 class HTMLUnknownElement;
 class HTMLUnknownElement;
 class HTMLVideoElement;
 class HTMLVideoElement;
+class ImageBitmap;
 class ImageData;
 class ImageData;
 class ImageRequest;
 class ImageRequest;
 class ListOfAvailableImages;
 class ListOfAvailableImages;

+ 107 - 0
Userland/Libraries/LibWeb/HTML/ImageBitmap.cpp

@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2024, Lucas Chollet <lucas.chollet@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibGfx/Bitmap.h>
+#include <LibWeb/HTML/ImageBitmap.h>
+
+namespace Web::HTML {
+
+JS_DEFINE_ALLOCATOR(ImageBitmap);
+
+JS::NonnullGCPtr<ImageBitmap> ImageBitmap::create(JS::Realm& realm)
+{
+    return realm.heap().allocate<ImageBitmap>(realm, realm);
+}
+
+ImageBitmap::ImageBitmap(JS::Realm& realm)
+    : Bindings::PlatformObject(realm)
+{
+}
+
+void ImageBitmap::initialize(JS::Realm& realm)
+{
+    Base::initialize(realm);
+    WEB_SET_PROTOTYPE_FOR_INTERFACE(ImageBitmap);
+}
+
+void ImageBitmap::visit_edges(Cell::Visitor& visitor)
+{
+    Base::visit_edges(visitor);
+}
+
+WebIDL::ExceptionOr<void> ImageBitmap::serialization_steps(HTML::SerializationRecord&, bool, HTML::SerializationMemory&)
+{
+    // FIXME: Implement this
+    dbgln("(STUBBED) ImageBitmap::serialization_steps(HTML::SerializationRecord&, bool, HTML::SerializationMemory&)");
+    return {};
+}
+
+WebIDL::ExceptionOr<void> ImageBitmap::deserialization_steps(ReadonlySpan<u32> const&, size_t&, HTML::DeserializationMemory&)
+{
+    // FIXME: Implement this
+    dbgln("(STUBBED) ImageBitmap::deserialization_steps(ReadonlySpan<u32> const&, size_t&, HTML::DeserializationMemory&)");
+    return {};
+}
+
+WebIDL::ExceptionOr<void> ImageBitmap::transfer_steps(HTML::TransferDataHolder&)
+{
+    // FIXME: Implement this
+    dbgln("(STUBBED) ImageBitmap::transfer_steps(HTML::TransferDataHolder&)");
+    return {};
+}
+
+WebIDL::ExceptionOr<void> ImageBitmap::transfer_receiving_steps(HTML::TransferDataHolder&)
+{
+    // FIXME: Implement this
+    dbgln("(STUBBED) ImageBitmap::transfer_receiving_steps(HTML::TransferDataHolder&)");
+    return {};
+}
+
+HTML::TransferType ImageBitmap::primary_interface() const
+{
+    // FIXME: Implement this
+    dbgln("(STUBBED) ImageBitmap::primary_interface()");
+    return {};
+}
+
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-imagebitmap-width
+WebIDL::UnsignedLong ImageBitmap::width() const
+{
+    // 1. If this's [[Detached]] internal slot's value is true, then return 0.
+    if (is_detached())
+        return 0;
+    // 2. Return this's width, in CSS pixels.
+    return m_width;
+}
+
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-imagebitmap-height
+WebIDL::UnsignedLong ImageBitmap::height() const
+{
+    // 1. If this's [[Detached]] internal slot's value is true, then return 0.
+    if (is_detached())
+        return 0;
+    // 2. Return this's height, in CSS pixels.
+    return m_height;
+}
+
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-imagebitmap-close
+void ImageBitmap::close()
+{
+    // 1. Set this's [[Detached]] internal slot value to true.
+    set_detached(true);
+
+    // 2. Unset this's bitmap data.
+    m_bitmap = nullptr;
+}
+
+void ImageBitmap::set_bitmap(RefPtr<Gfx::Bitmap> bitmap)
+{
+    m_bitmap = move(bitmap);
+    m_width = m_bitmap->width();
+    m_height = m_bitmap->height();
+}
+
+}

+ 71 - 0
Userland/Libraries/LibWeb/HTML/ImageBitmap.h

@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2024, Lucas Chollet <lucas.chollet@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/OwnPtr.h>
+#include <LibGfx/Bitmap.h>
+#include <LibWeb/Bindings/PlatformObject.h>
+#include <LibWeb/Bindings/Serializable.h>
+#include <LibWeb/Bindings/Transferable.h>
+#include <LibWeb/Forward.h>
+#include <LibWeb/HTML/Canvas/CanvasDrawImage.h>
+
+namespace Web::HTML {
+
+using ImageBitmapSource = Variant<CanvasImageSource, JS::Handle<FileAPI::Blob>, JS::Handle<ImageData>>;
+
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#imagebitmapoptions
+struct ImageBitmapOptions {
+    // FIXME: Implement these fields
+};
+
+class ImageBitmap final : public Bindings::PlatformObject
+    , public Web::Bindings::Serializable
+    , public Web::Bindings::Transferable {
+    WEB_PLATFORM_OBJECT(ImageBitmap, Bindings::PlatformObject);
+    JS_DECLARE_ALLOCATOR(ImageBitmap);
+
+public:
+    static JS::NonnullGCPtr<ImageBitmap> create(JS::Realm&);
+    virtual ~ImageBitmap() override = default;
+
+    // ^Web::Bindings::Serializable
+    virtual StringView interface_name() const override { return "ImageBitmap"sv; }
+    virtual WebIDL::ExceptionOr<void> serialization_steps(HTML::SerializationRecord&, bool for_storage, HTML::SerializationMemory&) override;
+    virtual WebIDL::ExceptionOr<void> deserialization_steps(ReadonlySpan<u32> const&, size_t& position, HTML::DeserializationMemory&) override;
+
+    // ^Web::Bindings::Transferable
+    virtual WebIDL::ExceptionOr<void> transfer_steps(HTML::TransferDataHolder&) override;
+    virtual WebIDL::ExceptionOr<void> transfer_receiving_steps(HTML::TransferDataHolder&) override;
+    virtual HTML::TransferType primary_interface() const override;
+
+    WebIDL::UnsignedLong width() const;
+    WebIDL::UnsignedLong height() const;
+
+    void close();
+
+    // Implementation specific:
+    void set_bitmap(RefPtr<Gfx::Bitmap>);
+
+private:
+    explicit ImageBitmap(JS::Realm&);
+
+    // FIXME: We don't implement this flag yet:
+    // An ImageBitmap object's bitmap has an origin-clean flag, which indicates whether the bitmap is tainted by content
+    // from a different origin. The flag is initially set to true and may be changed to false by the steps of
+    // createImageBitmap().
+
+    virtual void initialize(JS::Realm&) override;
+    virtual void visit_edges(Cell::Visitor&) override;
+
+    WebIDL::UnsignedLong m_width = 0;
+    WebIDL::UnsignedLong m_height = 0;
+
+    RefPtr<Gfx::Bitmap> m_bitmap { nullptr };
+};
+
+}

+ 28 - 0
Userland/Libraries/LibWeb/HTML/ImageBitmap.idl

@@ -0,0 +1,28 @@
+#import <FileAPI/Blob.idl>
+#import <HTML/ImageData.idl>
+
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#images-2
+[Exposed=(Window,Worker), Serializable, Transferable]
+interface ImageBitmap {
+    readonly attribute unsigned long width;
+    readonly attribute unsigned long height;
+    undefined close();
+};
+
+// FIXME: This should also includes CanvasImageSource
+typedef (Blob or
+         ImageData) ImageBitmapSource;
+
+enum ImageOrientation { "from-image", "flipY" };
+enum PremultiplyAlpha { "none", "premultiply", "default" };
+enum ColorSpaceConversion { "none", "default" };
+enum ResizeQuality { "pixelated", "low", "medium", "high" };
+
+dictionary ImageBitmapOptions {
+    // FIXME: ImageOrientation imageOrientation = "from-image";
+    // FIXME: PremultiplyAlpha premultiplyAlpha = "default";
+    // FIXME: ColorSpaceConversion colorSpaceConversion = "default";
+    // FIXME: [EnforceRange] unsigned long resizeWidth;
+    // FIXME: [EnforceRange] unsigned long resizeHeight;
+    // FIXME: ResizeQuality resizeQuality = "low";
+};

+ 1 - 0
Userland/Libraries/LibWeb/HTML/Window.h

@@ -61,6 +61,7 @@ public:
     using WindowOrWorkerGlobalScopeMixin::btoa;
     using WindowOrWorkerGlobalScopeMixin::btoa;
     using WindowOrWorkerGlobalScopeMixin::clear_interval;
     using WindowOrWorkerGlobalScopeMixin::clear_interval;
     using WindowOrWorkerGlobalScopeMixin::clear_timeout;
     using WindowOrWorkerGlobalScopeMixin::clear_timeout;
+    using WindowOrWorkerGlobalScopeMixin::create_image_bitmap;
     using WindowOrWorkerGlobalScopeMixin::fetch;
     using WindowOrWorkerGlobalScopeMixin::fetch;
     using WindowOrWorkerGlobalScopeMixin::queue_microtask;
     using WindowOrWorkerGlobalScopeMixin::queue_microtask;
     using WindowOrWorkerGlobalScopeMixin::set_interval;
     using WindowOrWorkerGlobalScopeMixin::set_interval;

+ 90 - 0
Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp

@@ -17,7 +17,9 @@
 #include <LibWeb/Bindings/MainThreadVM.h>
 #include <LibWeb/Bindings/MainThreadVM.h>
 #include <LibWeb/Fetch/FetchMethod.h>
 #include <LibWeb/Fetch/FetchMethod.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/Forward.h>
+#include <LibWeb/HTML/CanvasRenderingContext2D.h>
 #include <LibWeb/HTML/EventLoop/EventLoop.h>
 #include <LibWeb/HTML/EventLoop/EventLoop.h>
+#include <LibWeb/HTML/ImageBitmap.h>
 #include <LibWeb/HTML/Scripting/ClassicScript.h>
 #include <LibWeb/HTML/Scripting/ClassicScript.h>
 #include <LibWeb/HTML/Scripting/Environments.h>
 #include <LibWeb/HTML/Scripting/Environments.h>
 #include <LibWeb/HTML/Scripting/ExceptionReporter.h>
 #include <LibWeb/HTML/Scripting/ExceptionReporter.h>
@@ -32,6 +34,8 @@
 #include <LibWeb/PerformanceTimeline/EntryTypes.h>
 #include <LibWeb/PerformanceTimeline/EntryTypes.h>
 #include <LibWeb/PerformanceTimeline/PerformanceObserver.h>
 #include <LibWeb/PerformanceTimeline/PerformanceObserver.h>
 #include <LibWeb/PerformanceTimeline/PerformanceObserverEntryList.h>
 #include <LibWeb/PerformanceTimeline/PerformanceObserverEntryList.h>
+#include <LibWeb/Platform/EventLoopPlugin.h>
+#include <LibWeb/Platform/ImageCodecPlugin.h>
 #include <LibWeb/UserTiming/PerformanceMark.h>
 #include <LibWeb/UserTiming/PerformanceMark.h>
 #include <LibWeb/UserTiming/PerformanceMeasure.h>
 #include <LibWeb/UserTiming/PerformanceMeasure.h>
 #include <LibWeb/WebIDL/AbstractOperations.h>
 #include <LibWeb/WebIDL/AbstractOperations.h>
@@ -155,6 +159,92 @@ void WindowOrWorkerGlobalScopeMixin::queue_microtask(WebIDL::CallbackType& callb
     });
     });
 }
 }
 
 
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-createimagebitmap
+JS::NonnullGCPtr<JS::Promise> WindowOrWorkerGlobalScopeMixin::create_image_bitmap(ImageBitmapSource image, Optional<ImageBitmapOptions> options) const
+{
+    return create_image_bitmap_impl(image, {}, {}, {}, {}, options);
+}
+
+// https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#dom-createimagebitmap
+JS::NonnullGCPtr<JS::Promise> WindowOrWorkerGlobalScopeMixin::create_image_bitmap(ImageBitmapSource image, WebIDL::Long sx, WebIDL::Long sy, WebIDL::Long sw, WebIDL::Long sh, Optional<ImageBitmapOptions> options) const
+{
+    return create_image_bitmap_impl(image, sx, sy, sw, sh, options);
+}
+
+JS::NonnullGCPtr<JS::Promise> WindowOrWorkerGlobalScopeMixin::create_image_bitmap_impl(ImageBitmapSource& image, Optional<WebIDL::Long> sx, Optional<WebIDL::Long> sy, Optional<WebIDL::Long> sw, Optional<WebIDL::Long> sh, Optional<ImageBitmapOptions>& options) const
+{
+    // 1. If either sw or sh is given and is 0, then return a promise rejected with a RangeError.
+    if (sw == 0 || sh == 0) {
+        auto promise = JS::Promise::create(this_impl().realm());
+        auto error_message = MUST(String::formatted("{} is an invalid value for {}", sw == 0 ? *sw : *sh, sw == 0 ? "sw"sv : "sh"sv));
+        promise->reject(JS::RangeError::create(this_impl().realm(), move(error_message)));
+        return promise;
+    }
+
+    // FIXME:
+    // 2. If either options's resizeWidth or options's resizeHeight is present and is 0, then return a promise rejected with an "InvalidStateError" DOMException.
+    (void)options;
+
+    // 3. Check the usability of the image argument. If this throws an exception or returns bad, then return a promise rejected with an "InvalidStateError" DOMException.
+    // FIXME: "Check the usability of the image argument" is only defined for CanvasImageSource, let's skip it for other types
+    if (image.has<CanvasImageSource>()) {
+        if (auto usability = check_usability_of_image(image.get<CanvasImageSource>()); usability.is_error() or usability.value() == CanvasImageSourceUsability::Bad) {
+            auto promise = JS::Promise::create(this_impl().realm());
+            promise->reject(WebIDL::InvalidStateError::create(this_impl().realm(), "image argument is not usable"_string));
+            return promise;
+        }
+    }
+
+    // 4. Let p be a new promise.
+    auto p = JS::Promise::create(this_impl().realm());
+
+    // 5. Let imageBitmap be a new ImageBitmap object.
+    auto image_bitmap = ImageBitmap::create(this_impl().realm());
+
+    // 6. Switch on image:
+    image.visit(
+        [&](JS::Handle<FileAPI::Blob>& blob) {
+            // Run these step in parallel:
+            Platform::EventLoopPlugin::the().deferred_invoke([=, this]() {
+                // 1. Let imageData be the result of reading image's data. If an error occurs during reading of the
+                // object, then reject p with an "InvalidStateError" DOMException and abort these steps.
+                // FIXME: I guess this is always fine for us as the data is already read.
+                auto const image_data = blob->bytes();
+
+                // FIXME:
+                // 2. Apply the image sniffing rules to determine the file format of imageData, with MIME type of
+                // image (as given by image's type attribute) giving the official type.
+
+                // 3. If imageData is not in a supported image file format (e.g., it's not an image at all), or if
+                // imageData is corrupted in some fatal way such that the image dimensions cannot be obtained
+                // (e.g., a vector graphic with no natural size), then reject p with an "InvalidStateError" DOMException
+                // and abort these steps.
+                auto result = Web::Platform::ImageCodecPlugin::the().decode_image(image_data);
+                if (!result.has_value()) {
+                    p->reject(WebIDL::InvalidStateError::create(this_impl().realm(), "image does not contain a supported image format"_string));
+                    return;
+                }
+
+                // 4. Set imageBitmap's bitmap data to imageData, cropped to the source rectangle with formatting.
+                // If this is an animated image, imageBitmap's bitmap data must only be taken from the default image
+                // of the animation (the one that the format defines is to be used when animation is not supported
+                // or is disabled), or, if there is no such image, the first frame of the animation.
+                image_bitmap->set_bitmap(result.value().frames.take_first().bitmap);
+
+                // 5. Resolve p with imageBitmap.
+                p->fulfill(image_bitmap);
+            });
+        },
+        [&](auto&) {
+            dbgln("(STUBBED) createImageBitmap() for non-blob types");
+            (void)sx;
+            (void)sy;
+        });
+
+    // 7. Return p.
+    return p;
+}
+
 // https://html.spec.whatwg.org/multipage/structured-data.html#dom-structuredclone
 // https://html.spec.whatwg.org/multipage/structured-data.html#dom-structuredclone
 WebIDL::ExceptionOr<JS::Value> WindowOrWorkerGlobalScopeMixin::structured_clone(JS::Value value, StructuredSerializeOptions const& options) const
 WebIDL::ExceptionOr<JS::Value> WindowOrWorkerGlobalScopeMixin::structured_clone(JS::Value value, StructuredSerializeOptions const& options) const
 {
 {

+ 5 - 0
Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h

@@ -15,6 +15,7 @@
 #include <LibWeb/Bindings/PlatformObject.h>
 #include <LibWeb/Bindings/PlatformObject.h>
 #include <LibWeb/Fetch/Request.h>
 #include <LibWeb/Fetch/Request.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/Forward.h>
+#include <LibWeb/HTML/ImageBitmap.h>
 #include <LibWeb/HTML/MessagePort.h>
 #include <LibWeb/HTML/MessagePort.h>
 #include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
 #include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
 #include <LibWeb/PerformanceTimeline/PerformanceEntryTuple.h>
 #include <LibWeb/PerformanceTimeline/PerformanceEntryTuple.h>
@@ -39,6 +40,8 @@ public:
     WebIDL::ExceptionOr<String> btoa(String const& data) const;
     WebIDL::ExceptionOr<String> btoa(String const& data) const;
     WebIDL::ExceptionOr<String> atob(String const& data) const;
     WebIDL::ExceptionOr<String> atob(String const& data) const;
     void queue_microtask(WebIDL::CallbackType&);
     void queue_microtask(WebIDL::CallbackType&);
+    JS::NonnullGCPtr<JS::Promise> create_image_bitmap(ImageBitmapSource image, Optional<ImageBitmapOptions> options = {}) const;
+    JS::NonnullGCPtr<JS::Promise> create_image_bitmap(ImageBitmapSource image, WebIDL::Long sx, WebIDL::Long sy, WebIDL::Long sw, WebIDL::Long sh, Optional<ImageBitmapOptions> options = {}) const;
     WebIDL::ExceptionOr<JS::Value> structured_clone(JS::Value, StructuredSerializeOptions const&) const;
     WebIDL::ExceptionOr<JS::Value> structured_clone(JS::Value, StructuredSerializeOptions const&) const;
     JS::NonnullGCPtr<JS::Promise> fetch(Fetch::RequestInfo const&, Fetch::RequestInit const&) const;
     JS::NonnullGCPtr<JS::Promise> fetch(Fetch::RequestInfo const&, Fetch::RequestInit const&) const;
 
 
@@ -80,6 +83,8 @@ private:
     i32 run_timer_initialization_steps(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id = {});
     i32 run_timer_initialization_steps(TimerHandler handler, i32 timeout, JS::MarkedVector<JS::Value> arguments, Repeat repeat, Optional<i32> previous_id = {});
     void run_steps_after_a_timeout_impl(i32 timeout, Function<void()> completion_step, Optional<i32> timer_key = {});
     void run_steps_after_a_timeout_impl(i32 timeout, Function<void()> completion_step, Optional<i32> timer_key = {});
 
 
+    JS::NonnullGCPtr<JS::Promise> create_image_bitmap_impl(ImageBitmapSource& image, Optional<WebIDL::Long> sx, Optional<WebIDL::Long> sy, Optional<WebIDL::Long> sw, Optional<WebIDL::Long> sh, Optional<ImageBitmapOptions>& options) const;
+
     IDAllocator m_timer_id_allocator;
     IDAllocator m_timer_id_allocator;
     HashMap<int, JS::NonnullGCPtr<Timer>> m_timers;
     HashMap<int, JS::NonnullGCPtr<Timer>> m_timers;
 
 

+ 3 - 2
Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.idl

@@ -1,6 +1,7 @@
 #import <Fetch/Request.idl>
 #import <Fetch/Request.idl>
 #import <Fetch/Response.idl>
 #import <Fetch/Response.idl>
 #import <HighResolutionTime/Performance.idl>
 #import <HighResolutionTime/Performance.idl>
+#import <HTML/ImageBitmap.idl>
 #import <HTML/MessagePort.idl>
 #import <HTML/MessagePort.idl>
 
 
 // FIXME: Support VoidFunction in the IDL parser
 // FIXME: Support VoidFunction in the IDL parser
@@ -31,8 +32,8 @@ interface mixin WindowOrWorkerGlobalScope {
     undefined queueMicrotask(VoidFunction callback);
     undefined queueMicrotask(VoidFunction callback);
 
 
     // ImageBitmap
     // ImageBitmap
-    // FIXME: Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options = {});
-    // FIXME: Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options = {});
+    Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, optional ImageBitmapOptions options = {});
+    Promise<ImageBitmap> createImageBitmap(ImageBitmapSource image, long sx, long sy, long sw, long sh, optional ImageBitmapOptions options = {});
 
 
     // structured cloning
     // structured cloning
     any structuredClone(any value, optional StructuredSerializeOptions options = {});
     any structuredClone(any value, optional StructuredSerializeOptions options = {});

+ 1 - 0
Userland/Libraries/LibWeb/HTML/WorkerGlobalScope.h

@@ -50,6 +50,7 @@ public:
     using WindowOrWorkerGlobalScopeMixin::btoa;
     using WindowOrWorkerGlobalScopeMixin::btoa;
     using WindowOrWorkerGlobalScopeMixin::clear_interval;
     using WindowOrWorkerGlobalScopeMixin::clear_interval;
     using WindowOrWorkerGlobalScopeMixin::clear_timeout;
     using WindowOrWorkerGlobalScopeMixin::clear_timeout;
+    using WindowOrWorkerGlobalScopeMixin::create_image_bitmap;
     using WindowOrWorkerGlobalScopeMixin::fetch;
     using WindowOrWorkerGlobalScopeMixin::fetch;
     using WindowOrWorkerGlobalScopeMixin::performance;
     using WindowOrWorkerGlobalScopeMixin::performance;
     using WindowOrWorkerGlobalScopeMixin::queue_microtask;
     using WindowOrWorkerGlobalScopeMixin::queue_microtask;

+ 1 - 0
Userland/Libraries/LibWeb/idl_files.cmake

@@ -177,6 +177,7 @@ libweb_js_bindings(HTML/HTMLTrackElement)
 libweb_js_bindings(HTML/HTMLUListElement)
 libweb_js_bindings(HTML/HTMLUListElement)
 libweb_js_bindings(HTML/HTMLUnknownElement)
 libweb_js_bindings(HTML/HTMLUnknownElement)
 libweb_js_bindings(HTML/HTMLVideoElement)
 libweb_js_bindings(HTML/HTMLVideoElement)
+libweb_js_bindings(HTML/ImageBitmap)
 libweb_js_bindings(HTML/ImageData)
 libweb_js_bindings(HTML/ImageData)
 libweb_js_bindings(HTML/Location)
 libweb_js_bindings(HTML/Location)
 libweb_js_bindings(HTML/MediaError)
 libweb_js_bindings(HTML/MediaError)