LCOV - code coverage report
Current view: top level - gi - closure.h (source / functions) Hit Total Coverage
Test: gjs- Code Coverage Lines: 40 40 100.0 %
Date: 2023-09-17 02:39:54 Functions: 18 18 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1 2 50.0 %

           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 <glib-object.h>
      13                 :            : #include <stddef.h>
      14                 :            : 
      15                 :            : #include <js/TypeDecls.h>
      16                 :            : 
      17                 :            : #include "gi/utils-inl.h"
      18                 :            : #include "gjs/jsapi-util-root.h"
      19                 :            : #include "gjs/jsapi-util.h"
      20                 :            : #include "gjs/macros.h"
      21                 :            : 
      22                 :            : class JSTracer;
      23                 :            : namespace JS {
      24                 :            : class HandleValueArray;
      25                 :            : }
      26                 :            : 
      27                 :            : namespace Gjs {
      28                 :            : 
      29                 :            : class Closure : public GClosure {
      30                 :            :  protected:
      31                 :            :     Closure(JSContext*, JSObject* callable, bool root, const char* description);
      32                 :      11569 :     ~Closure() { unset_context(); }
      33                 :            : 
      34                 :            :     // Need to call this if inheriting from Closure to call the dtor
      35                 :            :     template <class C>
      36                 :      11591 :     constexpr void add_finalize_notifier() {
      37                 :            :         static_assert(std::is_base_of_v<Closure, C>);
      38                 :      11591 :         g_closure_add_finalize_notifier(
      39                 :            :             this, nullptr,
      40                 :      11569 :             [](void*, GClosure* closure) { static_cast<C*>(closure)->~C(); });
      41                 :      11591 :     }
      42                 :            : 
      43                 :      11591 :     void* operator new(size_t size) {
      44                 :      11591 :         return g_closure_new_simple(size, nullptr);
      45                 :            :     }
      46                 :            : 
      47                 :            :     void operator delete(void* p) { unref(static_cast<Closure*>(p)); }
      48                 :            : 
      49                 :        599 :     static Closure* ref(Closure* self) {
      50                 :        599 :         return static_cast<Closure*>(g_closure_ref(self));
      51                 :            :     }
      52                 :        708 :     static void unref(Closure* self) { g_closure_unref(self); }
      53                 :            : 
      54                 :            :  public:
      55                 :            :     using Ptr = GjsAutoPointer<Closure, Closure, unref, ref>;
      56                 :            : 
      57                 :       8066 :     [[nodiscard]] constexpr static Closure* for_gclosure(GClosure* gclosure) {
      58                 :            :         // We need to do this in order to ensure this is a constant expression
      59                 :       8066 :         return static_cast<Closure*>(static_cast<void*>(gclosure));
      60                 :            :     }
      61                 :            : 
      62                 :            :     [[nodiscard]] static Closure* create(JSContext* cx, JSObject* callable,
      63                 :            :                                          const char* description, bool root) {
      64                 :            :         auto* self = new Closure(cx, callable, root, description);
      65                 :            :         self->add_finalize_notifier<Closure>();
      66                 :            :         return self;
      67                 :            :     }
      68                 :            : 
      69                 :      11071 :     [[nodiscard]] static Closure* create_marshaled(JSContext* cx,
      70                 :            :                                                    JSObject* callable,
      71                 :            :                                                    const char* description) {
      72                 :      11071 :         auto* self = new Closure(cx, callable, true /* root */, description);
      73                 :      11071 :         self->add_finalize_notifier<Closure>();
      74                 :      11071 :         g_closure_set_marshal(self, marshal_cb);
      75                 :      11071 :         return self;
      76                 :            :     }
      77                 :            : 
      78                 :        216 :     [[nodiscard]] static Closure* create_for_signal(JSContext* cx,
      79                 :            :                                                     JSObject* callable,
      80                 :            :                                                     const char* description,
      81                 :            :                                                     int signal_id) {
      82                 :        216 :         auto* self = new Closure(cx, callable, false /* root */, description);
      83                 :        216 :         self->add_finalize_notifier<Closure>();
      84                 :        216 :         g_closure_set_meta_marshal(self, gjs_int_to_pointer(signal_id),
      85                 :            :                                    marshal_cb);
      86                 :        216 :         return self;
      87                 :            :     }
      88                 :            : 
      89                 :       8427 :     constexpr JSObject* callable() const { return m_callable; }
      90                 :        695 :     [[nodiscard]] constexpr JSContext* context() const { return m_cx; }
      91                 :       8625 :     [[nodiscard]] constexpr bool is_valid() const { return !!m_cx; }
      92                 :            :     GJS_JSAPI_RETURN_CONVENTION bool invoke(JS::HandleObject,
      93                 :            :                                             const JS::HandleValueArray&,
      94                 :            :                                             JS::MutableHandleValue);
      95                 :            : 
      96                 :        110 :     void trace(JSTracer* tracer) {
      97         [ +  - ]:        110 :         if (m_callable)
      98                 :        110 :             m_callable.trace(tracer, "signal connection");
      99                 :        110 :     }
     100                 :            : 
     101                 :            :  private:
     102                 :            :     void unset_context();
     103                 :            : 
     104                 :      11587 :     void reset() {
     105                 :      11587 :         unset_context();
     106                 :      11587 :         m_callable.reset();
     107                 :      11587 :         m_cx = nullptr;
     108                 :      11587 :     }
     109                 :            : 
     110                 :       7849 :     static void marshal_cb(GClosure* closure, GValue* ret, unsigned n_params,
     111                 :            :                            const GValue* params, void* hint, void* data) {
     112                 :       7849 :         for_gclosure(closure)->marshal(ret, n_params, params, hint, data);
     113                 :       7848 :     }
     114                 :            : 
     115                 :        219 :     static void global_context_notifier_cb(JSContext*, void* data) {
     116                 :        219 :         static_cast<Closure*>(data)->global_context_finalized();
     117                 :        219 :     }
     118                 :            : 
     119                 :            :     void closure_invalidated();
     120                 :            :     void closure_set_invalid();
     121                 :            :     void global_context_finalized();
     122                 :            :     void marshal(GValue* ret, unsigned n_parms, const GValue* params,
     123                 :            :                  void* hint, void* data);
     124                 :            : 
     125                 :            :     //  The saved context is used for lifetime management, so that the closure
     126                 :            :     //  will be torn down with the context that created it.
     127                 :            :     //  The context could be attached to the default context of the runtime
     128                 :            :     //  using if we wanted the closure to survive the context that created it.
     129                 :            :     JSContext* m_cx;
     130                 :            :     GjsMaybeOwned<JSObject*> m_callable;
     131                 :            : };
     132                 :            : 
     133                 :            : }  // namespace Gjs
     134                 :            : 
     135                 :            : #endif  // GI_CLOSURE_H_

Generated by: LCOV version 1.14