LCOV - code coverage report
Current view: top level - gi - foreign.cpp (source / functions) Hit Total Coverage
Test: gjs- Code Coverage Lines: 35 61 57.4 %
Date: 2023-09-17 02:39:54 Functions: 6 7 85.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 11 30 36.7 %

           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: 2010 litl, LLC
       4                 :            : 
       5                 :            : #include <config.h>
       6                 :            : 
       7                 :            : #include <string.h>  // for strcmp
       8                 :            : #include <string>
       9                 :            : 
      10                 :            : #include <girepository.h>
      11                 :            : #include <glib.h>
      12                 :            : 
      13                 :            : #include <js/TypeDecls.h>
      14                 :            : 
      15                 :            : #include "gi/foreign.h"
      16                 :            : #include "gjs/context-private.h"
      17                 :            : #include "gjs/jsapi-util.h"
      18                 :            : 
      19                 :            : static struct {
      20                 :            :     const char* gi_namespace;
      21                 :            :     bool loaded;
      22                 :            : } foreign_modules[] = {
      23                 :            :     // clang-format off
      24                 :            :     {"cairo", false},
      25                 :            :     {nullptr}
      26                 :            :     // clang-format on
      27                 :            : };
      28                 :            : 
      29                 :            : static GHashTable* foreign_structs_table = NULL;
      30                 :            : 
      31                 :         22 : [[nodiscard]] static GHashTable* get_foreign_structs() {
      32                 :            :     // FIXME: look into hasing on GITypeInfo instead.
      33         [ +  + ]:         22 :     if (!foreign_structs_table) {
      34                 :          2 :         foreign_structs_table = g_hash_table_new_full(g_str_hash, g_str_equal,
      35                 :            :                                      (GDestroyNotify)g_free,
      36                 :            :                                      NULL);
      37                 :            :     }
      38                 :            : 
      39                 :         22 :     return foreign_structs_table;
      40                 :            : }
      41                 :            : 
      42                 :          0 : [[nodiscard]] static bool gjs_foreign_load_foreign_module(
      43                 :            :     JSContext* context, const char* gi_namespace) {
      44                 :            :     int i;
      45                 :            : 
      46         [ #  # ]:          0 :     for (i = 0; foreign_modules[i].gi_namespace; ++i) {
      47         [ #  # ]:          0 :         if (strcmp(gi_namespace, foreign_modules[i].gi_namespace) != 0)
      48                 :          0 :             continue;
      49                 :            : 
      50         [ #  # ]:          0 :         if (foreign_modules[i].loaded)
      51                 :          0 :             return true;
      52                 :            : 
      53                 :            :         // FIXME: Find a way to check if a module is imported
      54                 :            :         //        and only execute this statement if isn't
      55                 :          0 :         std::string script = "imports." + std::string(gi_namespace) + ';';
      56                 :          0 :         JS::RootedValue retval(context);
      57                 :          0 :         GjsContextPrivate* gjs = GjsContextPrivate::from_cx(context);
      58         [ #  # ]:          0 :         if (!gjs->eval_with_scope(nullptr, script.c_str(), script.length(),
      59                 :            :                                   "<internal>", &retval)) {
      60                 :          0 :             g_critical("ERROR importing foreign module %s\n", gi_namespace);
      61                 :          0 :             return false;
      62                 :            :         }
      63                 :          0 :         foreign_modules[i].loaded = true;
      64                 :          0 :         return true;
      65                 :          0 :     }
      66                 :            : 
      67                 :          0 :     return false;
      68                 :            : }
      69                 :            : 
      70                 :          6 : void gjs_struct_foreign_register(const char* gi_namespace,
      71                 :            :                                  const char* type_name, GjsForeignInfo* info) {
      72                 :            :     char *canonical_name;
      73                 :            : 
      74                 :          6 :     g_return_if_fail(info);
      75                 :          6 :     g_return_if_fail(info->to_func);
      76                 :          6 :     g_return_if_fail(info->from_func);
      77                 :            : 
      78                 :          6 :     canonical_name = g_strdup_printf("%s.%s", gi_namespace, type_name);
      79                 :          6 :     g_hash_table_insert(get_foreign_structs(), canonical_name, info);
      80                 :            : }
      81                 :            : 
      82                 :         16 : [[nodiscard]] static GjsForeignInfo* gjs_struct_foreign_lookup(
      83                 :            :     JSContext* context, GIBaseInfo* interface_info) {
      84                 :            :     GHashTable* hash_table;
      85                 :            : 
      86                 :         32 :     auto key = std::string(g_base_info_get_namespace(interface_info)) + '.' +
      87                 :         32 :                g_base_info_get_name(interface_info);
      88                 :         16 :     hash_table = get_foreign_structs();
      89                 :            :     auto* retval = static_cast<GjsForeignInfo*>(
      90                 :         16 :         g_hash_table_lookup(hash_table, key.c_str()));
      91         [ -  + ]:         16 :     if (!retval) {
      92         [ #  # ]:          0 :         if (gjs_foreign_load_foreign_module(context, g_base_info_get_namespace(interface_info))) {
      93                 :            :             retval = static_cast<GjsForeignInfo*>(
      94                 :          0 :                 g_hash_table_lookup(hash_table, key.c_str()));
      95                 :            :         }
      96                 :            :     }
      97                 :            : 
      98         [ -  + ]:         16 :     if (!retval) {
      99                 :          0 :         gjs_throw(context, "Unable to find module implementing foreign type %s",
     100                 :            :                   key.c_str());
     101                 :            :     }
     102                 :            : 
     103                 :         32 :     return retval;
     104                 :         16 : }
     105                 :            : 
     106                 :          4 : bool gjs_struct_foreign_convert_to_g_argument(
     107                 :            :     JSContext* context, JS::Value value, GIBaseInfo* interface_info,
     108                 :            :     const char* arg_name, GjsArgumentType argument_type, GITransfer transfer,
     109                 :            :     GjsArgumentFlags flags, GArgument* arg) {
     110                 :            :     GjsForeignInfo *foreign;
     111                 :            : 
     112                 :          4 :     foreign = gjs_struct_foreign_lookup(context, interface_info);
     113         [ -  + ]:          4 :     if (!foreign)
     114                 :          0 :         return false;
     115                 :            : 
     116         [ -  + ]:          4 :     if (!foreign->to_func(context, value, arg_name, argument_type, transfer,
     117                 :            :                           flags, arg))
     118                 :          0 :         return false;
     119                 :            : 
     120                 :          4 :     return true;
     121                 :            : }
     122                 :            : 
     123                 :            : bool
     124                 :          6 : gjs_struct_foreign_convert_from_g_argument(JSContext             *context,
     125                 :            :                                            JS::MutableHandleValue value_p,
     126                 :            :                                            GIBaseInfo            *interface_info,
     127                 :            :                                            GIArgument            *arg)
     128                 :            : {
     129                 :            :     GjsForeignInfo *foreign;
     130                 :            : 
     131                 :          6 :     foreign = gjs_struct_foreign_lookup(context, interface_info);
     132         [ -  + ]:          6 :     if (!foreign)
     133                 :          0 :         return false;
     134                 :            : 
     135         [ -  + ]:          6 :     if (!foreign->from_func(context, value_p, arg))
     136                 :          0 :         return false;
     137                 :            : 
     138                 :          6 :     return true;
     139                 :            : }
     140                 :            : 
     141                 :            : bool
     142                 :          6 : gjs_struct_foreign_release_g_argument(JSContext  *context,
     143                 :            :                                       GITransfer  transfer,
     144                 :            :                                       GIBaseInfo *interface_info,
     145                 :            :                                       GArgument  *arg)
     146                 :            : {
     147                 :            :     GjsForeignInfo *foreign;
     148                 :            : 
     149                 :          6 :     foreign = gjs_struct_foreign_lookup(context, interface_info);
     150         [ -  + ]:          6 :     if (!foreign)
     151                 :          0 :         return false;
     152                 :            : 
     153         [ -  + ]:          6 :     if (!foreign->release_func)
     154                 :          0 :         return true;
     155                 :            : 
     156         [ -  + ]:          6 :     if (!foreign->release_func(context, transfer, arg))
     157                 :          0 :         return false;
     158                 :            : 
     159                 :          6 :     return true;
     160                 :            : }
     161                 :            : 

Generated by: LCOV version 1.14