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

Generated by: LCOV version 2.0-1