LibWeb: Give IDL exposed PlatformObjects an InterfaceName

By making use of the WEB_PLATFORM_OBJECT macro we can remove
the boilerplate of needing to add this override for every
serializable platform object so that we can check whether they
are exposed or not.
This commit is contained in:
Shannon Booth 2025-07-18 16:04:58 +12:00 committed by Shannon Booth
parent f360f52fef
commit 4d64f21fa5
30 changed files with 40 additions and 28 deletions

View file

@ -9,13 +9,21 @@
#include <AK/Weakable.h>
#include <LibJS/Runtime/Object.h>
#include <LibURL/Origin.h>
#include <LibWeb/Bindings/IntrinsicDefinitions.h>
#include <LibWeb/Export.h>
#include <LibWeb/Forward.h>
namespace Web::Bindings {
#define WEB_NON_IDL_PLATFORM_OBJECT(class_, base_class) \
JS_OBJECT(class_, base_class)
#define WEB_PLATFORM_OBJECT(class_, base_class) \
JS_OBJECT(class_, base_class) \
virtual Bindings::InterfaceName interface_name() const override \
{ \
return Bindings::InterfaceName::class_; \
} \
virtual bool implements_interface(String const& interface) const override \
{ \
if (interface == #class_) \
@ -36,6 +44,9 @@ public:
// This is implemented by overrides that get generated by the WEB_PLATFORM_OBJECT macro.
[[nodiscard]] virtual bool implements_interface(String const&) const { return false; }
// Generated by overrides by the WEB_PLATFORM_OBJECT macro. Only valid on platform objects that are exposed over IDL.
[[nodiscard]] virtual Bindings::InterfaceName interface_name() const { VERIFY_NOT_REACHED(); }
// ^JS::Object
virtual JS::ThrowCompletionOr<Optional<JS::PropertyDescriptor>> internal_get_own_property(JS::PropertyKey const&) const override;
virtual JS::ThrowCompletionOr<bool> internal_set(JS::PropertyKey const&, JS::Value, JS::Value, JS::CacheableSetPropertyMetadata* = nullptr, PropertyLookupPhase = PropertyLookupPhase::OwnProperty) override;

View file

@ -14,7 +14,7 @@ namespace Web::CSS {
// A non-spec base class for descriptor-list classes
class CSSDescriptors : public CSSStyleDeclaration {
WEB_PLATFORM_OBJECT(CSSDescriptors, CSSStyleDeclaration);
WEB_NON_IDL_PLATFORM_OBJECT(CSSDescriptors, CSSStyleDeclaration);
public:
virtual ~CSSDescriptors() override;

View file

@ -17,7 +17,7 @@
namespace Web::DOM {
class WEB_API DocumentObserver final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(DocumentObserver, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(DocumentObserver, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(DocumentObserver);
public:

View file

@ -15,7 +15,7 @@ namespace Web::DOM {
// FIXME: Just like HTMLCollection, LiveNodeList currently does no caching.
class LiveNodeList : public NodeList {
WEB_PLATFORM_OBJECT(LiveNodeList, NodeList);
WEB_NON_IDL_PLATFORM_OBJECT(LiveNodeList, NodeList);
GC_DECLARE_ALLOCATOR(LiveNodeList);
public:

View file

@ -12,7 +12,7 @@
namespace Web::DOM {
class WEB_API ParentNode : public Node {
WEB_PLATFORM_OBJECT(ParentNode, Node);
WEB_NON_IDL_PLATFORM_OBJECT(ParentNode, Node);
GC_DECLARE_ALLOCATOR(ParentNode);
public:

View file

@ -11,7 +11,7 @@
namespace Web::DOM {
class StaticNodeList final : public NodeList {
WEB_PLATFORM_OBJECT(StaticNodeList, NodeList);
WEB_NON_IDL_PLATFORM_OBJECT(StaticNodeList, NodeList);
GC_DECLARE_ALLOCATOR(StaticNodeList);
public:

View file

@ -12,7 +12,7 @@
namespace Web::DOMURL {
class URLSearchParamsIterator : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(URLSearchParamsIterator, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(URLSearchParamsIterator, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(URLSearchParamsIterator);
public:

View file

@ -13,7 +13,7 @@
namespace Web::Fetch {
class HeadersIterator final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(HeadersIterator, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(HeadersIterator, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(HeadersIterator);
public:

View file

@ -13,7 +13,7 @@ namespace Web::HTML {
// https://html.spec.whatwg.org/multipage/interaction.html#close-watcher-manager
class CloseWatcherManager final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(CloseWatcherManager, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(CloseWatcherManager, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(CloseWatcherManager);
public:

View file

@ -12,7 +12,7 @@
namespace Web::HTML {
class HTMLSummaryElement final : public HTMLElement {
WEB_PLATFORM_OBJECT(HTMLSummaryElement, HTMLElement);
WEB_NON_IDL_PLATFORM_OBJECT(HTMLSummaryElement, HTMLElement);
GC_DECLARE_ALLOCATOR(HTMLSummaryElement);
public:

View file

@ -12,7 +12,7 @@
namespace Web::HTML {
class MediaTrackBase : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(MediaTrackBase, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(MediaTrackBase, Bindings::PlatformObject);
public:
virtual ~MediaTrackBase() override;

View file

@ -13,7 +13,7 @@
namespace Web::HTML {
class WEB_API NavigableContainer : public HTMLElement {
WEB_PLATFORM_OBJECT(NavigableContainer, HTMLElement);
WEB_NON_IDL_PLATFORM_OBJECT(NavigableContainer, HTMLElement);
public:
static constexpr bool OVERRIDES_FINALIZE = true;

View file

@ -15,7 +15,7 @@
namespace Web::HTML {
class WEB_API NavigationObserver final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(NavigationObserver, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(NavigationObserver, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(NavigationObserver);
public:

View file

@ -15,7 +15,7 @@
namespace Web::HTML {
class TextTrackObserver final : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(TextTrackObserver, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(TextTrackObserver, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(TextTrackObserver);
public:

View file

@ -17,7 +17,7 @@
namespace Web::HTML {
class WEB_API WindowProxy final : public DOM::EventTarget {
WEB_PLATFORM_OBJECT(WindowProxy, DOM::EventTarget)
WEB_NON_IDL_PLATFORM_OBJECT(WindowProxy, DOM::EventTarget)
GC_DECLARE_ALLOCATOR(WindowProxy);
public:

View file

@ -16,7 +16,7 @@ namespace Web::IndexedDB {
// https://www.w3.org/TR/IndexedDB/#database-construct
class Database : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(Database, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(Database, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(Database);
public:

View file

@ -13,7 +13,7 @@
namespace Web::Internals {
class WEB_API InternalsBase : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(InternalsBase, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(InternalsBase, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(InternalsBase);
public:

View file

@ -11,7 +11,7 @@
namespace Web::MathML {
class MathMLMiElement final : public MathMLElement {
WEB_PLATFORM_OBJECT(MathMLMiElement, MathMLElement);
WEB_NON_IDL_PLATFORM_OBJECT(MathMLMiElement, MathMLElement);
GC_DECLARE_ALLOCATOR(MathMLMiElement);
public:

View file

@ -11,7 +11,7 @@
namespace Web::MathML {
class MathMLMspaceElement final : public MathMLElement {
WEB_PLATFORM_OBJECT(MathMLMspaceElement, MathMLElement);
WEB_NON_IDL_PLATFORM_OBJECT(MathMLMspaceElement, MathMLElement);
GC_DECLARE_ALLOCATOR(MathMLMspaceElement);
public:

View file

@ -18,7 +18,7 @@ struct ReadableStreamIteratorOptions {
};
class ReadableStreamAsyncIterator final : public WebIDL::AsyncIterator {
WEB_PLATFORM_OBJECT(ReadableStreamAsyncIterator, WebIDL::AsyncIterator);
WEB_NON_IDL_PLATFORM_OBJECT(ReadableStreamAsyncIterator, WebIDL::AsyncIterator);
GC_DECLARE_ALLOCATOR(ReadableStreamAsyncIterator);
public:

View file

@ -20,7 +20,7 @@ namespace Web::WebGL {
using namespace Web::HTML;
class WebGL2RenderingContextImpl : public WebGLRenderingContextImpl {
WEB_PLATFORM_OBJECT(WebGL2RenderingContextImpl, WebGLRenderingContextImpl);
WEB_NON_IDL_PLATFORM_OBJECT(WebGL2RenderingContextImpl, WebGLRenderingContextImpl);
public:
WebGL2RenderingContextImpl(JS::Realm&, NonnullOwnPtr<OpenGLContext>);

View file

@ -18,7 +18,7 @@ namespace Web::WebGL {
using namespace Web::HTML;
class WebGL2RenderingContextOverloads : public WebGL2RenderingContextImpl {
WEB_PLATFORM_OBJECT(WebGL2RenderingContextOverloads, WebGL2RenderingContextImpl);
WEB_NON_IDL_PLATFORM_OBJECT(WebGL2RenderingContextOverloads, WebGL2RenderingContextImpl);
public:
WebGL2RenderingContextOverloads(JS::Realm&, NonnullOwnPtr<OpenGLContext>);

View file

@ -37,7 +37,7 @@ static constexpr int MAX_CLIENT_WAIT_TIMEOUT_WEBGL = 0x9247;
using TexImageSource = Variant<GC::Root<HTML::ImageBitmap>, GC::Root<HTML::ImageData>, GC::Root<HTML::HTMLImageElement>, GC::Root<HTML::HTMLCanvasElement>, GC::Root<HTML::OffscreenCanvas>, GC::Root<HTML::HTMLVideoElement>>;
class WebGLRenderingContextBase : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(WebGLRenderingContextBase, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(WebGLRenderingContextBase, Bindings::PlatformObject);
public:
using Float32List = Variant<GC::Root<JS::Float32Array>, Vector<float>>;

View file

@ -21,7 +21,7 @@ namespace Web::WebGL {
using namespace Web::HTML;
class WebGLRenderingContextImpl : public WebGLRenderingContextBase {
WEB_PLATFORM_OBJECT(WebGLRenderingContextImpl, WebGLRenderingContextBase);
WEB_NON_IDL_PLATFORM_OBJECT(WebGLRenderingContextImpl, WebGLRenderingContextBase);
public:
WebGLRenderingContextImpl(JS::Realm&, NonnullOwnPtr<OpenGLContext>);

View file

@ -18,7 +18,7 @@ namespace Web::WebGL {
using namespace Web::HTML;
class WebGLRenderingContextOverloads : public WebGLRenderingContextImpl {
WEB_PLATFORM_OBJECT(WebGLRenderingContextOverloads, WebGLRenderingContextImpl);
WEB_NON_IDL_PLATFORM_OBJECT(WebGLRenderingContextOverloads, WebGLRenderingContextImpl);
public:
WebGLRenderingContextOverloads(JS::Realm&, NonnullOwnPtr<OpenGLContext>);

View file

@ -18,7 +18,7 @@
namespace Web::WebIDL {
class WEB_API AsyncIterator : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(AsyncIterator, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(AsyncIterator, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(AsyncIterator);
public:

View file

@ -12,7 +12,7 @@
namespace Web::XHR {
class FormDataIterator : public Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(FormDataIterator, Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(FormDataIterator, Bindings::PlatformObject);
GC_DECLARE_ALLOCATOR(FormDataIterator);
public:

View file

@ -956,6 +956,7 @@ void LibJSPPCallbacks::MacroExpands(clang::Token const& name_token, clang::Macro
{ "JS_ENVIRONMENT", LibJSCellMacro::Type::JSEnvironment },
{ "JS_PROTOTYPE_OBJECT", LibJSCellMacro::Type::JSPrototypeObject },
{ "WEB_PLATFORM_OBJECT", LibJSCellMacro::Type::WebPlatformObject },
{ "WEB_NON_IDL_PLATFORM_OBJECT", LibJSCellMacro::Type::WebPlatformObject },
};
auto name = ident_info->getName();

View file

@ -28,7 +28,7 @@ class TestEnvironmentClass : JS::Environment {
};
class TestPlatformClass : Web::Bindings::PlatformObject {
WEB_PLATFORM_OBJECT(TestPlatformClass, Web::Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(TestPlatformClass, Web::Bindings::PlatformObject);
};
namespace JS {

View file

@ -34,7 +34,7 @@ class TestEnvironmentClass : JS::Environment {
class TestPlatformClass : Web::Bindings::PlatformObject {
// expected-error@+1 {{Expected first argument of WEB_PLATFORM_OBJECT macro invocation to be TestPlatformClass}}
WEB_PLATFORM_OBJECT(bad, Web::Bindings::PlatformObject);
WEB_NON_IDL_PLATFORM_OBJECT(bad, Web::Bindings::PlatformObject);
};
struct Outer {