Serenity Operating System
at master 110 lines 3.9 kB view raw
1/* 2 * Copyright (c) 2022, Luke Wilde <lukew@serenityos.org> 3 * Copyright (c) 2022, Andreas Kling <kling@serenityos.org> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <AK/RefCounted.h> 11#include <LibJS/Heap/Handle.h> 12#include <LibWeb/DOM/MutationRecord.h> 13#include <LibWeb/WebIDL/CallbackType.h> 14#include <LibWeb/WebIDL/ExceptionOr.h> 15 16namespace Web::DOM { 17 18// https://dom.spec.whatwg.org/#dictdef-mutationobserverinit 19struct MutationObserverInit { 20 bool child_list { false }; 21 Optional<bool> attributes; 22 Optional<bool> character_data; 23 bool subtree { false }; 24 Optional<bool> attribute_old_value; 25 Optional<bool> character_data_old_value; 26 Optional<Vector<DeprecatedString>> attribute_filter; 27}; 28 29// https://dom.spec.whatwg.org/#mutationobserver 30class MutationObserver final : public Bindings::PlatformObject { 31 WEB_PLATFORM_OBJECT(MutationObserver, Bindings::PlatformObject); 32 33public: 34 static WebIDL::ExceptionOr<JS::NonnullGCPtr<MutationObserver>> construct_impl(JS::Realm&, JS::GCPtr<WebIDL::CallbackType>); 35 virtual ~MutationObserver() override; 36 37 WebIDL::ExceptionOr<void> observe(Node& target, MutationObserverInit options = {}); 38 void disconnect(); 39 Vector<JS::Handle<MutationRecord>> take_records(); 40 41 Vector<WeakPtr<Node>>& node_list() { return m_node_list; } 42 Vector<WeakPtr<Node>> const& node_list() const { return m_node_list; } 43 44 WebIDL::CallbackType& callback() { return *m_callback; } 45 46 void enqueue_record(Badge<Node>, JS::NonnullGCPtr<MutationRecord> mutation_record) 47 { 48 m_record_queue.append(*mutation_record); 49 } 50 51private: 52 MutationObserver(JS::Realm&, JS::GCPtr<WebIDL::CallbackType>); 53 54 virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; 55 virtual void visit_edges(Cell::Visitor&) override; 56 57 // https://dom.spec.whatwg.org/#concept-mo-callback 58 JS::GCPtr<WebIDL::CallbackType> m_callback; 59 60 // https://dom.spec.whatwg.org/#mutationobserver-node-list 61 // NOTE: These are weak, per https://dom.spec.whatwg.org/#garbage-collection 62 // Registered observers in a node’s registered observer list have a weak reference to the node. 63 Vector<WeakPtr<Node>> m_node_list; 64 65 // https://dom.spec.whatwg.org/#concept-mo-queue 66 Vector<JS::NonnullGCPtr<MutationRecord>> m_record_queue; 67}; 68 69// https://dom.spec.whatwg.org/#registered-observer 70class RegisteredObserver : public JS::Cell { 71 JS_CELL(RegisteredObserver, JS::Cell); 72 73public: 74 static JS::NonnullGCPtr<RegisteredObserver> create(MutationObserver&, MutationObserverInit const&); 75 virtual ~RegisteredObserver() override; 76 77 JS::NonnullGCPtr<MutationObserver> observer() const { return m_observer; } 78 79 MutationObserverInit const& options() const { return m_options; } 80 void set_options(MutationObserverInit options) { m_options = move(options); } 81 82protected: 83 RegisteredObserver(MutationObserver& observer, MutationObserverInit const& options); 84 85 virtual void visit_edges(Cell::Visitor&) override; 86 87private: 88 JS::NonnullGCPtr<MutationObserver> m_observer; 89 MutationObserverInit m_options; 90}; 91 92// https://dom.spec.whatwg.org/#transient-registered-observer 93class TransientRegisteredObserver final : public RegisteredObserver { 94 JS_CELL(TransientRegisteredObserver, RegisteredObserver); 95 96public: 97 static JS::NonnullGCPtr<TransientRegisteredObserver> create(MutationObserver&, MutationObserverInit const&, RegisteredObserver& source); 98 virtual ~TransientRegisteredObserver() override; 99 100 JS::NonnullGCPtr<RegisteredObserver> source() const { return m_source; } 101 102private: 103 TransientRegisteredObserver(MutationObserver& observer, MutationObserverInit const& options, RegisteredObserver& source); 104 105 virtual void visit_edges(Cell::Visitor&) override; 106 107 JS::NonnullGCPtr<RegisteredObserver> m_source; 108}; 109 110}