LCOV - code coverage report
Current view: top level - gi - foreign.cpp (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 52.7 % 55 29
Test Date: 2024-04-16 04:37:39 Functions: 85.7 % 7 6
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 34.6 % 26 9

             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 <stddef.h>  // for size_t
       8                 :             : 
       9                 :             : #include <string>
      10                 :             : #include <unordered_map>
      11                 :             : #include <utility>  // for pair
      12                 :             : 
      13                 :             : #include <girepository.h>
      14                 :             : #include <glib.h>
      15                 :             : 
      16                 :             : #include <js/RootingAPI.h>
      17                 :             : #include <js/TypeDecls.h>
      18                 :             : 
      19                 :             : #include "gi/foreign.h"
      20                 :             : #include "gjs/context-private.h"
      21                 :             : #include "gjs/jsapi-util.h"
      22                 :             : #include "gjs/macros.h"
      23                 :             : 
      24                 :             : enum LoadedStatus { NotLoaded, Loaded };
      25                 :             : static std::unordered_map<std::string, LoadedStatus> foreign_modules{
      26                 :             :     {"cairo", NotLoaded}};
      27                 :             : 
      28                 :             : using StructID = std::pair<std::string, std::string>;
      29                 :             : struct StructIDHash {
      30                 :          22 :     [[nodiscard]] size_t operator()(StructID val) const {
      31                 :             :         std::hash<std::string> hasher;
      32                 :          22 :         return hasher(val.first) ^ hasher(val.second);
      33                 :             :     }
      34                 :             : };
      35                 :             : static std::unordered_map<StructID, GjsForeignInfo*, StructIDHash>
      36                 :             :     foreign_structs_table;
      37                 :             : 
      38                 :           0 : [[nodiscard]] static bool gjs_foreign_load_foreign_module(
      39                 :             :     JSContext* cx, const char* gi_namespace) {
      40                 :           0 :     auto entry = foreign_modules.find(gi_namespace);
      41         [ #  # ]:           0 :     if (entry == foreign_modules.end())
      42                 :           0 :         return false;
      43                 :             : 
      44         [ #  # ]:           0 :     if (entry->second == Loaded)
      45                 :           0 :         return true;
      46                 :             : 
      47                 :             :     // FIXME: Find a way to check if a module is imported and only execute this
      48                 :             :     // statement if it isn't
      49                 :           0 :     std::string script = "imports." + entry->first + ';';
      50                 :           0 :     JS::RootedValue retval{cx};
      51                 :           0 :     GjsContextPrivate* gjs = GjsContextPrivate::from_cx(cx);
      52         [ #  # ]:           0 :     if (!gjs->eval_with_scope(nullptr, script.c_str(), script.length(),
      53                 :             :                               "<internal>", &retval)) {
      54                 :           0 :         g_critical("ERROR importing foreign module %s\n", gi_namespace);
      55                 :           0 :         return false;
      56                 :             :     }
      57                 :           0 :     entry->second = Loaded;
      58                 :           0 :     return true;
      59                 :           0 : }
      60                 :             : 
      61                 :           6 : void gjs_struct_foreign_register(const char* gi_namespace,
      62                 :             :                                  const char* type_name, GjsForeignInfo* info) {
      63                 :           6 :     foreign_structs_table.insert({{gi_namespace, type_name}, info});
      64                 :           6 : }
      65                 :             : 
      66                 :             : GJS_JSAPI_RETURN_CONVENTION
      67                 :          16 : static GjsForeignInfo* gjs_struct_foreign_lookup(JSContext* cx,
      68                 :             :                                                  GIStructInfo* info) {
      69                 :          16 :     const char* ns = g_base_info_get_namespace(info);
      70                 :          16 :     StructID key{ns, g_base_info_get_name(info)};
      71                 :          16 :     auto entry = foreign_structs_table.find(key);
      72         [ -  + ]:          16 :     if (entry == foreign_structs_table.end()) {
      73         [ #  # ]:           0 :         if (gjs_foreign_load_foreign_module(cx, ns))
      74                 :           0 :             entry = foreign_structs_table.find(key);
      75                 :             :     }
      76                 :             : 
      77         [ -  + ]:          16 :     if (entry == foreign_structs_table.end()) {
      78                 :           0 :         gjs_throw(cx, "Unable to find module implementing foreign type %s.%s",
      79                 :             :                   key.first.c_str(), key.second.c_str());
      80                 :           0 :         return nullptr;
      81                 :             :     }
      82                 :             : 
      83                 :          16 :     return entry->second;
      84                 :          16 : }
      85                 :             : 
      86                 :           4 : bool gjs_struct_foreign_convert_to_gi_argument(
      87                 :             :     JSContext* context, JS::Value value, GIStructInfo* info,
      88                 :             :     const char* arg_name, GjsArgumentType argument_type, GITransfer transfer,
      89                 :             :     GjsArgumentFlags flags, GIArgument* arg) {
      90                 :             :     GjsForeignInfo *foreign;
      91                 :             : 
      92                 :           4 :     foreign = gjs_struct_foreign_lookup(context, info);
      93         [ -  + ]:           4 :     if (!foreign)
      94                 :           0 :         return false;
      95                 :             : 
      96         [ -  + ]:           4 :     if (!foreign->to_func(context, value, arg_name, argument_type, transfer,
      97                 :             :                           flags, arg))
      98                 :           0 :         return false;
      99                 :             : 
     100                 :           4 :     return true;
     101                 :             : }
     102                 :             : 
     103                 :           6 : bool gjs_struct_foreign_convert_from_gi_argument(JSContext* context,
     104                 :             :                                                  JS::MutableHandleValue value_p,
     105                 :             :                                                  GIStructInfo* info,
     106                 :             :                                                  GIArgument* arg) {
     107                 :           6 :     GjsForeignInfo* foreign = gjs_struct_foreign_lookup(context, info);
     108         [ -  + ]:           6 :     if (!foreign)
     109                 :           0 :         return false;
     110                 :             : 
     111         [ -  + ]:           6 :     if (!foreign->from_func(context, value_p, arg))
     112                 :           0 :         return false;
     113                 :             : 
     114                 :           6 :     return true;
     115                 :             : }
     116                 :             : 
     117                 :           6 : bool gjs_struct_foreign_release_gi_argument(JSContext* context,
     118                 :             :                                             GITransfer transfer,
     119                 :             :                                             GIStructInfo* info,
     120                 :             :                                             GIArgument* arg) {
     121                 :           6 :     GjsForeignInfo* foreign = gjs_struct_foreign_lookup(context, info);
     122         [ -  + ]:           6 :     if (!foreign)
     123                 :           0 :         return false;
     124                 :             : 
     125         [ -  + ]:           6 :     if (!foreign->release_func)
     126                 :           0 :         return true;
     127                 :             : 
     128         [ -  + ]:           6 :     if (!foreign->release_func(context, transfer, arg))
     129                 :           0 :         return false;
     130                 :             : 
     131                 :           6 :     return true;
     132                 :             : }
        

Generated by: LCOV version 2.0-1