LCOV - code coverage report
Current view: top level - gi - closure.h (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 100.0 % 41 41
Test Date: 2025-05-07 12:25:00 Functions: 100.0 % 18 18
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 50.0 % 2 1

             Branch data     Line data    Source code
       1                 :             : /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
       2                 :             : // SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
       3                 :             : // SPDX-FileCopyrightText: 2008 litl, LLC
       4                 :             : // SPDX-FileCopyrightText: 2021 Canonical Ltd.
       5                 :             : // SPDX-FileContributor: Marco Trevisan <marco.trevisan@canonical.com>
       6                 :             : 
       7                 :             : #ifndef GI_CLOSURE_H_
       8                 :             : #define GI_CLOSURE_H_
       9                 :             : 
      10                 :             : #include <config.h>
      11                 :             : 
      12                 :             : #include <stddef.h>
      13                 :             : 
      14                 :             : #include <glib-object.h>
      15                 :             : 
      16                 :             : #include <js/TypeDecls.h>
      17                 :             : 
      18                 :             : #include "gi/utils-inl.h"
      19                 :             : #include "gjs/auto.h"
      20                 :             : #include "gjs/jsapi-util-root.h"
      21                 :             : #include "gjs/macros.h"
      22                 :             : 
      23                 :             : class JSTracer;
      24                 :             : namespace JS {
      25                 :             : class HandleValueArray;
      26                 :             : }
      27                 :             : 
      28                 :             : namespace Gjs {
      29                 :             : 
      30                 :             : class Closure : public GClosure {
      31                 :             :  protected:
      32                 :             :     Closure(JSContext*, JSObject* callable, bool root, const char* description);
      33                 :       14132 :     ~Closure() { unset_context(); }
      34                 :             : 
      35                 :             :     // Need to call this if inheriting from Closure to call the dtor
      36                 :             :     template <class C>
      37                 :       14154 :     constexpr void add_finalize_notifier() {
      38                 :             :         static_assert(std::is_base_of_v<Closure, C>);
      39                 :       14154 :         g_closure_add_finalize_notifier(
      40                 :             :             this, nullptr,
      41                 :       14132 :             [](void*, GClosure* closure) { static_cast<C*>(closure)->~C(); });
      42                 :       14154 :     }
      43                 :             : 
      44                 :       14154 :     void* operator new(size_t size) {
      45                 :       14154 :         return g_closure_new_simple(size, nullptr);
      46                 :             :     }
      47                 :             : 
      48                 :             :     void operator delete(void* p) { unref(static_cast<Closure*>(p)); }
      49                 :             : 
      50                 :         632 :     static Closure* ref(Closure* self) {
      51                 :         632 :         return static_cast<Closure*>(g_closure_ref(self));
      52                 :             :     }
      53                 :         790 :     static void unref(Closure* self) { g_closure_unref(self); }
      54                 :             : 
      55                 :             :  public:
      56                 :         790 :     using Ptr = Gjs::AutoPointer<Closure, Closure, unref, ref>;
      57                 :             : 
      58                 :       10012 :     [[nodiscard]] constexpr static Closure* for_gclosure(GClosure* gclosure) {
      59                 :             :         // We need to do this in order to ensure this is a constant expression
      60                 :       10012 :         return static_cast<Closure*>(static_cast<void*>(gclosure));
      61                 :             :     }
      62                 :             : 
      63                 :             :     [[nodiscard]] static Closure* create(JSContext* cx, JSObject* callable,
      64                 :             :                                          const char* description, bool root) {
      65                 :             :         auto* self = new Closure(cx, callable, root, description);
      66                 :             :         self->add_finalize_notifier<Closure>();
      67                 :             :         return self;
      68                 :             :     }
      69                 :             : 
      70                 :       13515 :     [[nodiscard]] static Closure* create_marshaled(JSContext* cx,
      71                 :             :                                                    JSObject* callable,
      72                 :             :                                                    const char* description,
      73                 :             :                                                    bool root = true) {
      74                 :       13515 :         auto* self = new Closure(cx, callable, root, description);
      75                 :       13515 :         self->add_finalize_notifier<Closure>();
      76                 :       13515 :         g_closure_set_marshal(self, marshal_cb);
      77                 :       13515 :         return self;
      78                 :             :     }
      79                 :             : 
      80                 :         323 :     [[nodiscard]] static Closure* create_for_signal(JSContext* cx,
      81                 :             :                                                     JSObject* callable,
      82                 :             :                                                     const char* description,
      83                 :             :                                                     int signal_id) {
      84                 :         323 :         auto* self = new Closure(cx, callable, false /* root */, description);
      85                 :         323 :         self->add_finalize_notifier<Closure>();
      86                 :         323 :         g_closure_set_meta_marshal(self, gjs_int_to_pointer(signal_id),
      87                 :             :                                    marshal_cb);
      88                 :         323 :         return self;
      89                 :             :     }
      90                 :             : 
      91                 :             :     // COMPAT: constexpr in C++23
      92                 :       10324 :     JSObject* callable() const { return m_callable.get(); }
      93                 :         736 :     [[nodiscard]] constexpr JSContext* context() const { return m_cx; }
      94                 :       10535 :     [[nodiscard]] constexpr bool is_valid() const { return !!m_cx; }
      95                 :             :     GJS_JSAPI_RETURN_CONVENTION bool invoke(JS::HandleObject,
      96                 :             :                                             const JS::HandleValueArray&,
      97                 :             :                                             JS::MutableHandleValue);
      98                 :             : 
      99                 :         185 :     void trace(JSTracer* tracer) {
     100         [ +  - ]:         185 :         if (m_callable)
     101                 :         185 :             m_callable.trace(tracer, "signal connection");
     102                 :         185 :     }
     103                 :             : 
     104                 :             :  private:
     105                 :             :     void unset_context();
     106                 :             : 
     107                 :       14150 :     void reset() {
     108                 :       14150 :         unset_context();
     109                 :       14150 :         m_callable.reset();
     110                 :       14150 :         m_cx = nullptr;
     111                 :       14150 :     }
     112                 :             : 
     113                 :        9720 :     static void marshal_cb(GClosure* closure, GValue* ret, unsigned n_params,
     114                 :             :                            const GValue* params, void* hint, void* data) {
     115                 :        9720 :         for_gclosure(closure)->marshal(ret, n_params, params, hint, data);
     116                 :        9719 :     }
     117                 :             : 
     118                 :         186 :     static void global_context_notifier_cb(JSContext*, void* data) {
     119                 :         186 :         static_cast<Closure*>(data)->global_context_finalized();
     120                 :         186 :     }
     121                 :             : 
     122                 :             :     void closure_invalidated();
     123                 :             :     void closure_set_invalid();
     124                 :             :     void global_context_finalized();
     125                 :             :     void marshal(GValue* ret, unsigned n_parms, const GValue* params,
     126                 :             :                  void* hint, void* data);
     127                 :             : 
     128                 :             :     //  The saved context is used for lifetime management, so that the closure
     129                 :             :     //  will be torn down with the context that created it.
     130                 :             :     //  The context could be attached to the default context of the runtime
     131                 :             :     //  using if we wanted the closure to survive the context that created it.
     132                 :             :     JSContext* m_cx;
     133                 :             :     GjsMaybeOwned m_callable;
     134                 :             : };
     135                 :             : 
     136                 :             : }  // namespace Gjs
     137                 :             : 
     138                 :             : #endif  // GI_CLOSURE_H_
        

Generated by: LCOV version 2.0-1