/* * Copyright (c) 2022, Luke Wilde * Copyright (c) 2022, Andreas Kling * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once #include #include #include #include #include namespace Web::DOM { // https://dom.spec.whatwg.org/#dictdef-mutationobserverinit struct MutationObserverInit { bool child_list { false }; Optional attributes; Optional character_data; bool subtree { false }; Optional attribute_old_value; Optional character_data_old_value; Optional> attribute_filter; }; // https://dom.spec.whatwg.org/#mutationobserver class MutationObserver final : public Bindings::PlatformObject { WEB_PLATFORM_OBJECT(MutationObserver, Bindings::PlatformObject); GC_DECLARE_ALLOCATOR(MutationObserver); public: static WebIDL::ExceptionOr> construct_impl(JS::Realm&, GC::Ptr); virtual ~MutationObserver() override; WebIDL::ExceptionOr observe(Node& target, MutationObserverInit options = {}); void disconnect(); Vector> take_records(); Vector>& node_list() { return m_node_list; } Vector> const& node_list() const { return m_node_list; } WebIDL::CallbackType& callback() { return *m_callback; } void enqueue_record(Badge, GC::Ref mutation_record) { m_record_queue.append(*mutation_record); } private: MutationObserver(JS::Realm&, GC::Ptr); virtual void initialize(JS::Realm&) override; virtual void visit_edges(Cell::Visitor&) override; // https://dom.spec.whatwg.org/#concept-mo-callback GC::Ptr m_callback; // https://dom.spec.whatwg.org/#mutationobserver-node-list // NOTE: These are weak, per https://dom.spec.whatwg.org/#garbage-collection // Registered observers in a node’s registered observer list have a weak reference to the node. Vector> m_node_list; // https://dom.spec.whatwg.org/#concept-mo-queue Vector> m_record_queue; }; // https://dom.spec.whatwg.org/#registered-observer class RegisteredObserver : public JS::Cell { GC_CELL(RegisteredObserver, JS::Cell); public: static GC::Ref create(MutationObserver&, MutationObserverInit const&); virtual ~RegisteredObserver() override; GC::Ref observer() const { return m_observer; } MutationObserverInit const& options() const { return m_options; } void set_options(MutationObserverInit options) { m_options = move(options); } protected: RegisteredObserver(MutationObserver& observer, MutationObserverInit const& options); virtual void visit_edges(Cell::Visitor&) override; private: GC::Ref m_observer; MutationObserverInit m_options; }; // https://dom.spec.whatwg.org/#transient-registered-observer class TransientRegisteredObserver final : public RegisteredObserver { GC_CELL(TransientRegisteredObserver, RegisteredObserver); GC_DECLARE_ALLOCATOR(TransientRegisteredObserver); public: static GC::Ref create(MutationObserver&, MutationObserverInit const&, RegisteredObserver& source); virtual ~TransientRegisteredObserver() override; GC::Ref source() const { return m_source; } private: TransientRegisteredObserver(MutationObserver& observer, MutationObserverInit const& options, RegisteredObserver& source); virtual void visit_edges(Cell::Visitor&) override; GC::Ref m_source; }; }