LCOV - code coverage report
Current view: top level - gi - function.h (source / functions) Hit Total Coverage
Test: gjs- Code Coverage Lines: 37 37 100.0 %
Date: 2023-09-17 02:39:54 Functions: 13 13 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 16 20 80.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                 :            : 
       5                 :            : #ifndef GI_FUNCTION_H_
       6                 :            : #define GI_FUNCTION_H_
       7                 :            : 
       8                 :            : #include <config.h>
       9                 :            : 
      10                 :            : #include <stdint.h>
      11                 :            : 
      12                 :            : #include <memory>  // for unique_ptr
      13                 :            : #include <unordered_set>
      14                 :            : #include <vector>
      15                 :            : 
      16                 :            : #include <ffi.h>
      17                 :            : #include <girepository.h>
      18                 :            : #include <girffi.h>  // for g_callable_info_get_closure_native_address
      19                 :            : #include <glib-object.h>
      20                 :            : #include <glib.h>
      21                 :            : 
      22                 :            : #include <js/GCVector.h>
      23                 :            : #include <js/RootingAPI.h>
      24                 :            : #include <js/TypeDecls.h>
      25                 :            : #include <js/Value.h>
      26                 :            : 
      27                 :            : #include "gi/closure.h"
      28                 :            : #include "gjs/jsapi-util.h"
      29                 :            : #include "gjs/macros.h"
      30                 :            : 
      31                 :            : namespace JS {
      32                 :            : class CallArgs;
      33                 :            : }
      34                 :            : 
      35                 :            : typedef enum {
      36                 :            :     PARAM_NORMAL,
      37                 :            :     PARAM_SKIPPED,
      38                 :            :     PARAM_ARRAY,
      39                 :            :     PARAM_CALLBACK,
      40                 :            :     PARAM_UNKNOWN,
      41                 :            : } GjsParamType;
      42                 :            : 
      43                 :            : using GjsAutoGClosure =
      44                 :            :     GjsAutoPointer<GClosure, GClosure, g_closure_unref, g_closure_ref>;
      45                 :            : 
      46                 :            : struct GjsCallbackTrampoline : public Gjs::Closure {
      47                 :            :     GJS_JSAPI_RETURN_CONVENTION static GjsCallbackTrampoline* create(
      48                 :            :         JSContext* cx, JS::HandleObject callable, GICallableInfo* callable_info,
      49                 :            :         GIScopeType scope, bool has_scope_object, bool is_vfunc);
      50                 :            : 
      51                 :            :     ~GjsCallbackTrampoline();
      52                 :            : 
      53                 :        303 :     void* closure() const {
      54                 :            : #if GI_CHECK_VERSION(1, 71, 0)
      55                 :        303 :         return g_callable_info_get_closure_native_address(m_info, m_closure);
      56                 :            : #else
      57                 :            :         return m_closure;
      58                 :            : #endif
      59                 :            :     }
      60                 :            : 
      61                 :        245 :     ffi_closure* get_ffi_closure() const {
      62                 :        245 :         return m_closure;
      63                 :            :     }
      64                 :            : 
      65                 :            :     void mark_forever();
      66                 :            : 
      67                 :            :     static void prepare_shutdown();
      68                 :            : 
      69                 :            :  private:
      70                 :            :     ffi_closure* create_closure();
      71                 :            :     GJS_JSAPI_RETURN_CONVENTION bool initialize();
      72                 :            :     GjsCallbackTrampoline(JSContext* cx, JS::HandleObject callable,
      73                 :            :                           GICallableInfo* callable_info, GIScopeType scope,
      74                 :            :                           bool has_scope_object, bool is_vfunc);
      75                 :            : 
      76                 :            :     void callback_closure(GIArgument** args, void* result);
      77                 :            :     GJS_JSAPI_RETURN_CONVENTION
      78                 :            :     bool callback_closure_inner(JSContext* cx, JS::HandleObject this_object,
      79                 :            :                                 GObject* gobject, JS::MutableHandleValue rval,
      80                 :            :                                 GIArgument** args, GITypeInfo* ret_type,
      81                 :            :                                 int n_args, int c_args_offset, void* result);
      82                 :            :     void warn_about_illegal_js_callback(const char* when, const char* reason,
      83                 :            :                                         bool dump_stack);
      84                 :            : 
      85                 :            :     static std::vector<GjsAutoGClosure> s_forever_closure_list;
      86                 :            : 
      87                 :            :     GjsAutoCallableInfo m_info;
      88                 :            :     ffi_closure* m_closure = nullptr;
      89                 :            :     std::unique_ptr<GjsParamType[]> m_param_types;
      90                 :            :     ffi_cif m_cif;
      91                 :            : 
      92                 :            :     GIScopeType m_scope : 3;
      93                 :            :     bool m_is_vfunc : 1;
      94                 :            : };
      95                 :            : 
      96                 :            : // Stack allocation only!
      97                 :            : class GjsFunctionCallState {
      98                 :            :     GjsAutoCppPointer<GIArgument[]> m_in_cvalues;
      99                 :            :     GjsAutoCppPointer<GIArgument[]> m_out_cvalues;
     100                 :            :     GjsAutoCppPointer<GIArgument[]> m_inout_original_cvalues;
     101                 :            : 
     102                 :            :  public:
     103                 :            :     std::unordered_set<GIArgument*> ignore_release;
     104                 :            :     JS::RootedObject instance_object;
     105                 :            :     JS::RootedVector<JS::Value> return_values;
     106                 :            :     GjsAutoError local_error;
     107                 :            :     GICallableInfo* info;
     108                 :            :     uint8_t gi_argc = 0;
     109                 :            :     uint8_t processed_c_args = 0;
     110                 :            :     bool failed : 1;
     111                 :            :     bool can_throw_gerror : 1;
     112                 :            :     bool is_method : 1;
     113                 :            : 
     114                 :      61405 :     GjsFunctionCallState(JSContext* cx, GICallableInfo* callable)
     115                 :      61405 :         : instance_object(cx),
     116                 :      61405 :           return_values(cx),
     117                 :      61405 :           info(callable),
     118                 :      61405 :           gi_argc(g_callable_info_get_n_args(callable)),
     119                 :      61405 :           failed(false),
     120                 :     122810 :           can_throw_gerror(g_callable_info_can_throw_gerror(callable)),
     121                 :     184215 :           is_method(g_callable_info_is_method(callable)) {
     122                 :      61405 :         int size = gi_argc + first_arg_offset();
     123         [ +  - ]:      61405 :         m_in_cvalues = new GIArgument[size];
     124         [ +  - ]:      61405 :         m_out_cvalues = new GIArgument[size];
     125         [ +  - ]:      61405 :         m_inout_original_cvalues = new GIArgument[size];
     126                 :      61405 :     }
     127                 :            : 
     128                 :            :     GjsFunctionCallState(const GjsFunctionCallState&) = delete;
     129                 :            :     GjsFunctionCallState& operator=(const GjsFunctionCallState&) = delete;
     130                 :            : 
     131         [ +  + ]:     581811 :     constexpr int first_arg_offset() const { return is_method ? 2 : 1; }
     132                 :            : 
     133                 :            :     // The list always contains the return value, and the arguments
     134                 :      67438 :     constexpr GIArgument* instance() {
     135         [ +  - ]:      67438 :         return is_method ? &m_in_cvalues[1] : nullptr;
     136                 :            :     }
     137                 :            : 
     138                 :     156626 :     constexpr GIArgument* return_value() { return &m_out_cvalues[0]; }
     139                 :            : 
     140                 :     137116 :     constexpr GIArgument& in_cvalue(int index) const {
     141                 :     137116 :         return m_in_cvalues[index + first_arg_offset()];
     142                 :            :     }
     143                 :            : 
     144                 :     137575 :     constexpr GIArgument& out_cvalue(int index) const {
     145                 :     137575 :         return m_out_cvalues[index + first_arg_offset()];
     146                 :            :     }
     147                 :            : 
     148                 :        131 :     constexpr GIArgument& inout_original_cvalue(int index) const {
     149                 :        131 :         return m_inout_original_cvalues[index + first_arg_offset()];
     150                 :            :     }
     151                 :            : 
     152                 :     157117 :     constexpr bool did_throw_gerror() const {
     153   [ +  +  +  + ]:     157117 :         return can_throw_gerror && local_error;
     154                 :            :     }
     155                 :            : 
     156   [ +  +  +  + ]:      34491 :     constexpr bool call_completed() { return !failed && !did_throw_gerror(); }
     157                 :            : 
     158                 :     122792 :     constexpr unsigned last_processed_index() {
     159                 :     122792 :         return first_arg_offset() + processed_c_args;
     160                 :            :     }
     161                 :            : 
     162                 :          3 :     [[nodiscard]] GjsAutoChar display_name() {
     163                 :          3 :         GIBaseInfo* container = g_base_info_get_container(info);  // !owned
     164         [ +  + ]:          3 :         if (container) {
     165                 :            :             return g_strdup_printf(
     166                 :            :                 "%s.%s.%s", g_base_info_get_namespace(container),
     167                 :          1 :                 g_base_info_get_name(container), g_base_info_get_name(info));
     168                 :            :         }
     169                 :            :         return g_strdup_printf("%s.%s", g_base_info_get_namespace(info),
     170                 :          2 :                                g_base_info_get_name(info));
     171                 :            :     }
     172                 :            : };
     173                 :            : 
     174                 :            : GJS_JSAPI_RETURN_CONVENTION
     175                 :            : JSObject *gjs_define_function(JSContext       *context,
     176                 :            :                               JS::HandleObject in_object,
     177                 :            :                               GType            gtype,
     178                 :            :                               GICallableInfo  *info);
     179                 :            : 
     180                 :            : GJS_JSAPI_RETURN_CONVENTION
     181                 :            : bool gjs_invoke_constructor_from_c(JSContext* cx, GIFunctionInfo* info,
     182                 :            :                                    JS::HandleObject this_obj,
     183                 :            :                                    const JS::CallArgs& args,
     184                 :            :                                    GIArgument* rvalue);
     185                 :            : 
     186                 :            : #endif  // GI_FUNCTION_H_

Generated by: LCOV version 1.14