LCOV - code coverage report
Current view: top level - gi - fundamental.cpp (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 78.9 % 213 168
Test Date: 2024-04-29 05:18:28 Functions: 95.0 % 20 19
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 58.9 % 124 73

             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: 2013 Intel Corporation
       4                 :             : // SPDX-FileCopyrightText: 2008-2010 litl, LLC
       5                 :             : 
       6                 :             : #include <config.h>
       7                 :             : 
       8                 :             : #include <girepository.h>
       9                 :             : #include <glib.h>
      10                 :             : 
      11                 :             : #include <js/AllocPolicy.h>  // for SystemAllocPolicy
      12                 :             : #include <js/Class.h>
      13                 :             : #include <js/ErrorReport.h>  // for JS_ReportOutOfMemory
      14                 :             : #include <js/GCHashTable.h>  // for WeakCache
      15                 :             : #include <js/HashTable.h>    // for DefaultHasher via WeakCache
      16                 :             : #include <js/Object.h>       // for GetClass
      17                 :             : #include <js/PropertyAndElement.h>
      18                 :             : #include <js/RootingAPI.h>
      19                 :             : #include <js/TypeDecls.h>
      20                 :             : #include <js/Utility.h>  // for UniqueChars
      21                 :             : #include <js/Value.h>
      22                 :             : #include <jsapi.h>       // for InformalValueTypeName, JS_NewObjectWithGivenP...
      23                 :             : #include <mozilla/HashTable.h>
      24                 :             : 
      25                 :             : #include "gi/arg-inl.h"
      26                 :             : #include "gi/arg.h"
      27                 :             : #include "gi/function.h"
      28                 :             : #include "gi/fundamental.h"
      29                 :             : #include "gi/repo.h"
      30                 :             : #include "gi/value.h"
      31                 :             : #include "gi/wrapperutils.h"
      32                 :             : #include "gjs/atoms.h"
      33                 :             : #include "gjs/context-private.h"
      34                 :             : #include "gjs/jsapi-util.h"
      35                 :             : #include "gjs/macros.h"
      36                 :             : #include "gjs/mem-private.h"
      37                 :             : #include "util/log.h"
      38                 :             : 
      39                 :             : namespace JS {
      40                 :             : class CallArgs;
      41                 :             : }
      42                 :             : 
      43                 :          18 : FundamentalInstance::FundamentalInstance(FundamentalPrototype* prototype,
      44                 :          18 :                                          JS::HandleObject obj)
      45                 :          18 :     : GIWrapperInstance(prototype, obj) {
      46                 :          18 :     GJS_INC_COUNTER(fundamental_instance);
      47                 :          18 : }
      48                 :             : 
      49                 :             : /*
      50                 :             :  * FundamentalInstance::associate_js_instance:
      51                 :             :  *
      52                 :             :  * Associates @gfundamental with @object so that @object can be retrieved in the
      53                 :             :  * future if you have a pointer to @gfundamental. (Assuming @object has not been
      54                 :             :  * garbage collected in the meantime.)
      55                 :             :  */
      56                 :          17 : bool FundamentalInstance::associate_js_instance(JSContext* cx, JSObject* object,
      57                 :             :                                                 void* gfundamental) {
      58                 :          17 :     m_ptr = gfundamental;
      59                 :             : 
      60                 :          17 :     GjsContextPrivate* gjs = GjsContextPrivate::from_cx(cx);
      61         [ -  + ]:          17 :     if (!gjs->fundamental_table().putNew(gfundamental, object)) {
      62                 :           0 :         JS_ReportOutOfMemory(cx);
      63                 :           0 :         return false;
      64                 :             :     }
      65                 :             : 
      66                 :          17 :     debug_lifecycle(object, "associated JSObject with fundamental");
      67                 :             : 
      68                 :          17 :     ref();
      69                 :          17 :     return true;
      70                 :             : }
      71                 :             : 
      72                 :             : /**/
      73                 :             : 
      74                 :             : /* Find the first constructor */
      75                 :           9 : [[nodiscard]] static GIFunctionInfo* find_fundamental_constructor(
      76                 :             :     GIObjectInfo* info) {
      77                 :             :     int i, n_methods;
      78                 :             : 
      79                 :           9 :     n_methods = g_object_info_get_n_methods(info);
      80                 :             : 
      81         [ +  + ]:          35 :     for (i = 0; i < n_methods; ++i) {
      82                 :          31 :         GjsAutoFunctionInfo func_info;
      83                 :             :         GIFunctionInfoFlags flags;
      84                 :             : 
      85                 :          31 :         func_info = g_object_info_get_method(info, i);
      86                 :             : 
      87                 :          31 :         flags = g_function_info_get_flags(func_info);
      88         [ +  + ]:          31 :         if ((flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0)
      89                 :           5 :             return func_info.release();
      90         [ +  + ]:          31 :     }
      91                 :             : 
      92                 :           4 :     return nullptr;
      93                 :             : }
      94                 :             : 
      95                 :             : /**/
      96                 :             : 
      97                 :          58 : bool FundamentalPrototype::resolve_interface(JSContext* cx,
      98                 :             :                                              JS::HandleObject obj,
      99                 :             :                                              bool* resolved, const char* name) {
     100                 :             :     bool ret;
     101                 :             :     GType *interfaces;
     102                 :             :     guint n_interfaces;
     103                 :             :     guint i;
     104                 :             : 
     105                 :          58 :     ret = true;
     106                 :          58 :     interfaces = g_type_interfaces(gtype(), &n_interfaces);
     107         [ -  + ]:          58 :     for (i = 0; i < n_interfaces; i++) {
     108                 :             :         GjsAutoInterfaceInfo iface_info =
     109                 :           0 :             g_irepository_find_by_gtype(nullptr, interfaces[i]);
     110                 :             : 
     111         [ #  # ]:           0 :         if (!iface_info)
     112                 :           0 :             continue;
     113                 :             : 
     114                 :             :         GjsAutoFunctionInfo method_info =
     115                 :           0 :             g_interface_info_find_method(iface_info, name);
     116                 :             : 
     117   [ #  #  #  # ]:           0 :         if (method_info &&
     118         [ #  # ]:           0 :             g_function_info_get_flags(method_info) & GI_FUNCTION_IS_METHOD) {
     119         [ #  # ]:           0 :             if (gjs_define_function(cx, obj, gtype(), method_info)) {
     120                 :           0 :                 *resolved = true;
     121                 :             :             } else {
     122                 :           0 :                 ret = false;
     123                 :             :             }
     124                 :             :         }
     125         [ #  # ]:           0 :     }
     126                 :             : 
     127                 :          58 :     g_free(interfaces);
     128                 :          58 :     return ret;
     129                 :             : }
     130                 :             : 
     131                 :             : // See GIWrapperBase::resolve().
     132                 :          58 : bool FundamentalPrototype::resolve_impl(JSContext* cx, JS::HandleObject obj,
     133                 :             :                                         JS::HandleId id, bool* resolved) {
     134                 :          58 :     JS::UniqueChars prop_name;
     135         [ -  + ]:          58 :     if (!gjs_get_string_id(cx, id, &prop_name))
     136                 :           0 :         return false;
     137         [ -  + ]:          58 :     if (!prop_name) {
     138                 :           0 :         *resolved = false;
     139                 :           0 :         return true;  // not resolved, but no error
     140                 :             :     }
     141                 :             : 
     142                 :             :     /* We are the prototype, so look for methods and other class properties */
     143                 :             :     GjsAutoFunctionInfo method_info =
     144                 :          58 :         g_object_info_find_method(info(), prop_name.get());
     145                 :             : 
     146         [ +  + ]:          58 :     if (method_info) {
     147                 :             : #if GJS_VERBOSE_ENABLE_GI_USAGE
     148                 :             :         _gjs_log_info_usage(method_info);
     149                 :             : #endif
     150         [ +  - ]:           1 :         if (g_function_info_get_flags (method_info) & GI_FUNCTION_IS_METHOD) {
     151                 :             :             /* we do not define deprecated methods in the prototype */
     152         [ -  + ]:           1 :             if (g_base_info_is_deprecated(method_info)) {
     153                 :           0 :                 gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
     154                 :             :                           "Ignoring definition of deprecated method %s in "
     155                 :             :                           "prototype %s.%s",
     156                 :             :                           method_info.name(), ns(), name());
     157                 :           0 :                 *resolved = false;
     158                 :           0 :                 return true;
     159                 :             :             }
     160                 :             : 
     161                 :           1 :             gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
     162                 :             :                       "Defining method %s in prototype for %s.%s",
     163                 :             :                       method_info.name(), ns(), name());
     164                 :             : 
     165         [ -  + ]:           1 :             if (!gjs_define_function(cx, obj, gtype(), method_info))
     166                 :           0 :                 return false;
     167                 :             : 
     168                 :           1 :             *resolved = true;
     169                 :             :         }
     170                 :             :     } else {
     171                 :          57 :         *resolved = false;
     172                 :             :     }
     173                 :             : 
     174                 :          58 :     return resolve_interface(cx, obj, resolved, prop_name.get());
     175                 :          58 : }
     176                 :             : 
     177                 :             : /*
     178                 :             :  * FundamentalInstance::invoke_constructor:
     179                 :             :  *
     180                 :             :  * Finds the type's static constructor method (the static method given by
     181                 :             :  * FundamentalPrototype::constructor_info()) and invokes it with the given
     182                 :             :  * arguments.
     183                 :             :  */
     184                 :          16 : bool FundamentalInstance::invoke_constructor(JSContext* context,
     185                 :             :                                              JS::HandleObject obj,
     186                 :             :                                              const JS::CallArgs& args,
     187                 :             :                                              GIArgument* rvalue) {
     188                 :          16 :     GIFunctionInfo* constructor_info = get_prototype()->constructor_info();
     189         [ +  + ]:          16 :     if (!constructor_info) {
     190                 :           1 :         gjs_throw(context, "Couldn't find a constructor for type %s.%s", ns(),
     191                 :             :                   name());
     192                 :           1 :         return false;
     193                 :             :     }
     194                 :             : 
     195                 :          15 :     return gjs_invoke_constructor_from_c(context, constructor_info, obj, args,
     196                 :          15 :                                          rvalue);
     197                 :             : }
     198                 :             : 
     199                 :             : // See GIWrapperBase::constructor().
     200                 :          16 : bool FundamentalInstance::constructor_impl(JSContext* cx,
     201                 :             :                                            JS::HandleObject object,
     202                 :             :                                            const JS::CallArgs& argv) {
     203                 :             :     GIArgument ret_value;
     204                 :             :     GITypeInfo return_info;
     205                 :             : 
     206   [ +  +  +  + ]:          31 :     if (!invoke_constructor(cx, object, argv, &ret_value) ||
     207         [ -  + ]:          15 :         !associate_js_instance(cx, object, gjs_arg_get<void*>(&ret_value)))
     208                 :           1 :         return false;
     209                 :             : 
     210                 :          15 :     GICallableInfo* constructor_info = get_prototype()->constructor_info();
     211                 :          15 :     g_callable_info_load_return_type(constructor_info, &return_info);
     212                 :             : 
     213                 :          15 :     return gjs_gi_argument_release(
     214                 :             :         cx, g_callable_info_get_caller_owns(constructor_info), &return_info,
     215                 :          15 :         &ret_value);
     216                 :             : }
     217                 :             : 
     218                 :          18 : FundamentalInstance::~FundamentalInstance(void) {
     219         [ +  + ]:          18 :     if (m_ptr) {
     220                 :          17 :         unref();
     221                 :          17 :         m_ptr = nullptr;
     222                 :             :     }
     223                 :          18 :     GJS_DEC_COUNTER(fundamental_instance);
     224                 :          18 : }
     225                 :             : 
     226                 :           9 : FundamentalPrototype::FundamentalPrototype(GIObjectInfo* info, GType gtype)
     227                 :             :     : GIWrapperPrototype(info, gtype),
     228                 :           9 :       m_ref_function(g_object_info_get_ref_function_pointer(info)),
     229                 :           9 :       m_unref_function(g_object_info_get_unref_function_pointer(info)),
     230                 :           9 :       m_get_value_function(g_object_info_get_get_value_function_pointer(info)),
     231                 :           9 :       m_set_value_function(g_object_info_get_set_value_function_pointer(info)),
     232                 :          18 :       m_constructor_info(find_fundamental_constructor(info)) {
     233                 :           9 :     GJS_INC_COUNTER(fundamental_prototype);
     234                 :           9 : }
     235                 :             : 
     236                 :           9 : FundamentalPrototype::~FundamentalPrototype(void) {
     237                 :           9 :     GJS_DEC_COUNTER(fundamental_prototype);
     238                 :           9 : }
     239                 :             : 
     240                 :             : // clang-format off
     241                 :             : const struct JSClassOps FundamentalBase::class_ops = {
     242                 :             :     nullptr,  // addProperty
     243                 :             :     nullptr,  // deleteProperty
     244                 :             :     nullptr,  // enumerate
     245                 :             :     nullptr,  // newEnumerate
     246                 :             :     &FundamentalBase::resolve,
     247                 :             :     nullptr,  // mayResolve
     248                 :             :     &FundamentalBase::finalize,
     249                 :             :     nullptr,  // call
     250                 :             :     nullptr,  // construct
     251                 :             :     &FundamentalBase::trace
     252                 :             : };
     253                 :             : 
     254                 :             : const struct JSClass FundamentalBase::klass = {
     255                 :             :     "GFundamental_Object",
     256                 :             :     JSCLASS_HAS_RESERVED_SLOTS(1) | JSCLASS_FOREGROUND_FINALIZE,
     257                 :             :     &FundamentalBase::class_ops
     258                 :             : };
     259                 :             : // clang-format on
     260                 :             : 
     261                 :             : GJS_JSAPI_RETURN_CONVENTION
     262                 :             : static JSObject *
     263                 :          34 : gjs_lookup_fundamental_prototype(JSContext    *context,
     264                 :             :                                  GIObjectInfo *info,
     265                 :             :                                  GType         gtype)
     266                 :             : {
     267                 :          34 :     JS::RootedObject in_object(context);
     268                 :             :     const char *constructor_name;
     269                 :             : 
     270         [ +  - ]:          34 :     if (info) {
     271                 :          34 :         in_object = gjs_lookup_namespace_object(context, (GIBaseInfo*) info);
     272                 :          34 :         constructor_name = g_base_info_get_name((GIBaseInfo*) info);
     273                 :             :     } else {
     274                 :           0 :         in_object = gjs_lookup_private_namespace(context);
     275                 :           0 :         constructor_name = g_type_name(gtype);
     276                 :             :     }
     277                 :             : 
     278         [ -  + ]:          34 :     if (G_UNLIKELY (!in_object))
     279                 :           0 :         return nullptr;
     280                 :             : 
     281                 :             :     bool found;
     282         [ -  + ]:          34 :     if (!JS_HasProperty(context, in_object, constructor_name, &found))
     283                 :           0 :         return nullptr;
     284                 :             : 
     285                 :          34 :     JS::RootedValue value(context);
     286   [ +  -  -  +  :          34 :     if (found && !JS_GetProperty(context, in_object, constructor_name, &value))
                   -  + ]
     287                 :           0 :         return nullptr;
     288                 :             : 
     289                 :          34 :     JS::RootedObject constructor(context);
     290         [ -  + ]:          34 :     if (value.isUndefined()) {
     291                 :             :         /* In case we're looking for a private type, and we don't find it,
     292                 :             :            we need to define it first.
     293                 :             :         */
     294         [ #  # ]:           0 :         if (!FundamentalPrototype::define_class(context, in_object, info,
     295                 :             :                                                 &constructor))
     296                 :           0 :             return nullptr;
     297                 :             :     } else {
     298         [ -  + ]:          34 :         if (G_UNLIKELY(!value.isObject())) {
     299                 :           0 :             gjs_throw(context,
     300                 :             :                       "Fundamental constructor was not an object, it was a %s",
     301                 :             :                       JS::InformalValueTypeName(value));
     302                 :           0 :             return nullptr;
     303                 :             :         }
     304                 :             : 
     305                 :          34 :         constructor = &value.toObject();
     306                 :             :     }
     307                 :             : 
     308                 :          34 :     g_assert(constructor);
     309                 :             : 
     310                 :          34 :     const GjsAtoms& atoms = GjsContextPrivate::atoms(context);
     311                 :          34 :     JS::RootedObject prototype(context);
     312         [ -  + ]:          34 :     if (!gjs_object_require_property(context, constructor, "constructor object",
     313                 :             :                                      atoms.prototype(), &prototype))
     314                 :           0 :         return nullptr;
     315                 :             : 
     316                 :          34 :     return prototype;
     317                 :          34 : }
     318                 :             : 
     319                 :             : GJS_JSAPI_RETURN_CONVENTION
     320                 :             : static JSObject*
     321                 :          34 : gjs_lookup_fundamental_prototype_from_gtype(JSContext *context,
     322                 :             :                                             GType      gtype)
     323                 :             : {
     324                 :          34 :     GjsAutoObjectInfo info;
     325                 :             : 
     326                 :             :     /* A given gtype might not have any definition in the introspection
     327                 :             :      * data. If that's the case, try to look for a definition of any of the
     328                 :             :      * parent type. */
     329   [ +  -  +  + ]:          72 :     while (gtype != G_TYPE_INVALID &&
     330   [ +  -  +  + ]:          72 :            !(info = g_irepository_find_by_gtype(nullptr, gtype)))
     331                 :           2 :         gtype = g_type_parent(gtype);
     332                 :             : 
     333                 :          34 :     return gjs_lookup_fundamental_prototype(context, info, gtype);
     334                 :          34 : }
     335                 :             : 
     336                 :             : // Overrides GIWrapperPrototype::get_parent_proto().
     337                 :           9 : bool FundamentalPrototype::get_parent_proto(
     338                 :             :     JSContext* cx, JS::MutableHandleObject proto) const {
     339                 :           9 :     GType parent_gtype = g_type_parent(gtype());
     340         [ +  + ]:           9 :     if (parent_gtype != G_TYPE_INVALID) {
     341                 :           4 :         proto.set(
     342                 :           4 :             gjs_lookup_fundamental_prototype_from_gtype(cx, parent_gtype));
     343         [ -  + ]:           4 :         if (!proto)
     344                 :           0 :             return false;
     345                 :             :     }
     346                 :           9 :     return true;
     347                 :             : }
     348                 :             : 
     349                 :             : // Overrides GIWrapperPrototype::constructor_nargs().
     350                 :           9 : unsigned FundamentalPrototype::constructor_nargs(void) const {
     351         [ +  + ]:           9 :     if (m_constructor_info)
     352                 :           5 :         return g_callable_info_get_n_args(m_constructor_info);
     353                 :           4 :     return 0;
     354                 :             : }
     355                 :             : 
     356                 :             : /*
     357                 :             :  * FundamentalPrototype::define_class:
     358                 :             :  * @in_object: Object where the constructor is stored, typically a repo object.
     359                 :             :  * @info: Introspection info for the fundamental class.
     360                 :             :  * @constructor: Return location for the constructor object.
     361                 :             :  *
     362                 :             :  * Define a fundamental class constructor and prototype, including all the
     363                 :             :  * necessary methods and properties. Provides the constructor object as an out
     364                 :             :  * parameter, for convenience elsewhere.
     365                 :             :  */
     366                 :           9 : bool FundamentalPrototype::define_class(JSContext* cx,
     367                 :             :                                         JS::HandleObject in_object,
     368                 :             :                                         GIObjectInfo* info,
     369                 :             :                                         JS::MutableHandleObject constructor) {
     370                 :             :     GType gtype;
     371                 :             : 
     372                 :           9 :     gtype = g_registered_type_info_get_g_type (info);
     373                 :             : 
     374                 :           9 :     JS::RootedObject prototype(cx);
     375                 :           9 :     FundamentalPrototype* priv = FundamentalPrototype::create_class(
     376                 :             :         cx, in_object, info, gtype, constructor, &prototype);
     377         [ -  + ]:           9 :     if (!priv)
     378                 :           0 :         return false;
     379                 :             : 
     380         [ +  + ]:           9 :     if (g_object_info_get_n_fields(info) > 0) {
     381                 :           8 :         gjs_debug(GJS_DEBUG_GFUNDAMENTAL,
     382                 :             :                   "Fundamental type '%s.%s' apparently has accessible fields. "
     383                 :             :                   "Gjs has no support for this yet, ignoring these.",
     384                 :             :                   priv->ns(), priv->name());
     385                 :             :     }
     386                 :             : 
     387                 :           9 :     return true;
     388                 :           9 : }
     389                 :             : 
     390                 :             : /*
     391                 :             :  * FundamentalInstance::object_for_c_ptr:
     392                 :             :  *
     393                 :             :  * Given a pointer to a C fundamental object, returns a JS object. This JS
     394                 :             :  * object may have been cached, or it may be newly created.
     395                 :             :  */
     396                 :          13 : JSObject* FundamentalInstance::object_for_c_ptr(JSContext* context,
     397                 :             :                                                 void* gfundamental) {
     398         [ -  + ]:          13 :     if (!gfundamental) {
     399                 :           0 :         gjs_throw(context, "Cannot get JSObject for null fundamental pointer");
     400                 :           0 :         return nullptr;
     401                 :             :     }
     402                 :             : 
     403                 :          13 :     GjsContextPrivate* gjs = GjsContextPrivate::from_cx(context);
     404                 :          13 :     auto p = gjs->fundamental_table().lookup(gfundamental);
     405         [ +  + ]:          13 :     if (p)
     406                 :          11 :         return p->value();
     407                 :             : 
     408                 :             :     gjs_debug_marshal(GJS_DEBUG_GFUNDAMENTAL,
     409                 :             :                       "Wrapping fundamental %p with JSObject", gfundamental);
     410                 :             : 
     411                 :             :     JS::RootedObject proto(context,
     412                 :           6 :         gjs_lookup_fundamental_prototype_from_gtype(context,
     413                 :           2 :                                                     G_TYPE_FROM_INSTANCE(gfundamental)));
     414         [ -  + ]:           2 :     if (!proto)
     415                 :           0 :         return nullptr;
     416                 :             : 
     417                 :           4 :     JS::RootedObject object(context, JS_NewObjectWithGivenProto(
     418                 :           4 :                                          context, JS::GetClass(proto), proto));
     419                 :             : 
     420         [ -  + ]:           2 :     if (!object)
     421                 :           0 :         return nullptr;
     422                 :             : 
     423                 :           2 :     auto* priv = FundamentalInstance::new_for_js_object(context, object);
     424                 :             : 
     425         [ -  + ]:           2 :     if (!priv->associate_js_instance(context, object, gfundamental))
     426                 :           0 :         return nullptr;
     427                 :             : 
     428                 :           2 :     return object;
     429                 :           2 : }
     430                 :             : 
     431                 :             : /*
     432                 :             :  * FundamentalPrototype::for_gtype:
     433                 :             :  *
     434                 :             :  * Returns the FundamentalPrototype instance associated with the given GType.
     435                 :             :  * Use this if you don't have the prototype object.
     436                 :             :  */
     437                 :          28 : FundamentalPrototype* FundamentalPrototype::for_gtype(JSContext* cx,
     438                 :             :                                                       GType gtype) {
     439                 :             :     JS::RootedObject proto(
     440                 :          28 :         cx, gjs_lookup_fundamental_prototype_from_gtype(cx, gtype));
     441         [ -  + ]:          28 :     if (!proto)
     442                 :           0 :         return nullptr;
     443                 :             : 
     444                 :          28 :     return FundamentalPrototype::for_js(cx, proto);
     445                 :          28 : }
     446                 :             : 
     447                 :          12 : bool FundamentalInstance::object_for_gvalue(
     448                 :             :     JSContext* cx, const GValue* value, GType gtype,
     449                 :             :     JS::MutableHandleObject object_out) {
     450                 :          12 :     auto* proto_priv = FundamentalPrototype::for_gtype(cx, gtype);
     451                 :          12 :     void* fobj = nullptr;
     452                 :             : 
     453         [ +  + ]:          12 :     if (!proto_priv->call_get_value_function(value, &fobj)) {
     454   [ -  +  +  -  :           6 :         if (!G_VALUE_HOLDS(value, gtype) || !g_value_fits_pointer(value)) {
          +  -  -  +  -  
                      + ]
     455                 :           0 :             gjs_throw(cx,
     456                 :             :                       "Failed to convert GValue of type %s to a fundamental %s "
     457                 :             :                       "instance",
     458                 :             :                       G_VALUE_TYPE_NAME(value), g_type_name(gtype));
     459                 :           0 :             return false;
     460                 :             :         }
     461                 :             : 
     462                 :           6 :         fobj = g_value_peek_pointer(value);
     463                 :             :     }
     464                 :             : 
     465         [ -  + ]:          12 :     if (!fobj) {
     466                 :           0 :         object_out.set(nullptr);
     467                 :           0 :         return true;
     468                 :             :     }
     469                 :             : 
     470                 :          12 :     object_out.set(FundamentalInstance::object_for_c_ptr(cx, fobj));
     471                 :          12 :     return object_out.get() != nullptr;
     472                 :             : }
     473                 :             : 
     474                 :          11 : bool FundamentalBase::to_gvalue(JSContext* cx, JS::HandleObject obj,
     475                 :             :                                 GValue* gvalue) {
     476                 :             :     FundamentalBase* priv;
     477   [ +  -  -  + ]:          22 :     if (!for_js_typecheck(cx, obj, &priv) ||
     478         [ -  + ]:          11 :         !priv->check_is_instance(cx, "convert to GValue"))
     479                 :           0 :         return false;
     480                 :             : 
     481                 :          11 :     auto* instance = priv->to_instance();
     482         [ +  + ]:          11 :     if (!instance->set_value(gvalue)) {
     483         [ +  + ]:           7 :         if (g_value_type_compatible(instance->gtype(), G_VALUE_TYPE(gvalue))) {
     484                 :           4 :             g_value_set_instance(gvalue, instance->m_ptr);
     485                 :           4 :             return true;
     486         [ +  + ]:           3 :         } else if (g_value_type_transformable(instance->gtype(),
     487                 :             :                                               G_VALUE_TYPE(gvalue))) {
     488                 :           1 :             Gjs::AutoGValue instance_value;
     489                 :           1 :             g_value_init(&instance_value, instance->gtype());
     490                 :           1 :             g_value_set_instance(&instance_value, instance->m_ptr);
     491         [ +  - ]:           1 :             if (g_value_transform(&instance_value, gvalue))
     492                 :           1 :                 return true;
     493         [ -  + ]:           1 :         }
     494                 :             : 
     495                 :           2 :         gjs_throw(cx,
     496                 :             :                   "Fundamental object of type %s does not support conversion "
     497                 :             :                   "to a GValue of type %s",
     498                 :             :                   instance->type_name(), G_VALUE_TYPE_NAME(gvalue));
     499                 :           2 :         return false;
     500                 :             :     }
     501                 :             : 
     502                 :           4 :     return true;
     503                 :             : }
     504                 :             : 
     505                 :           0 : void* FundamentalInstance::copy_ptr(JSContext* cx, GType gtype,
     506                 :             :                                     void* gfundamental) {
     507                 :           0 :     auto* priv = FundamentalPrototype::for_gtype(cx, gtype);
     508                 :           0 :     return priv->call_ref_function(gfundamental);
     509                 :             : }
        

Generated by: LCOV version 2.0-1