LCOV - code coverage report
Current view: top level - gi - fundamental.cpp (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 24.4 % 213 52
Test Date: 2024-11-29 04:16:41 Functions: 50.0 % 20 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 9.7 % 124 12

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

Generated by: LCOV version 2.0-1