LCOV - code coverage report
Current view: top level - gjs - jsapi-util.h (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 100.0 % 9 9
Test Date: 2025-02-15 06:20:10 Functions: 100.0 % 2 2
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 100.0 % 4 4

             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: 2008 litl, LLC
       4                 :             : // SPDX-FileCopyrightText: 2018-2020  Canonical, Ltd
       5                 :             : 
       6                 :             : #ifndef GJS_JSAPI_UTIL_H_
       7                 :             : #define GJS_JSAPI_UTIL_H_
       8                 :             : 
       9                 :             : #include <config.h>
      10                 :             : 
      11                 :             : #include <stdint.h>
      12                 :             : #include <stdlib.h>     // for free
      13                 :             : #include <sys/types.h>  // for ssize_t
      14                 :             : 
      15                 :             : #include <limits>
      16                 :             : #include <string>  // for string, u16string
      17                 :             : #include <type_traits>  // for enable_if_t, add_pointer_t, add_const_t
      18                 :             : #include <utility>      // IWYU pragma: keep
      19                 :             : #include <vector>
      20                 :             : 
      21                 :             : #include <glib-object.h>
      22                 :             : #include <glib.h>
      23                 :             : 
      24                 :             : #include <js/BigInt.h>
      25                 :             : #include <js/ErrorReport.h>  // for JSExnType
      26                 :             : #include <js/GCAPI.h>
      27                 :             : #include <js/GCPolicyAPI.h>  // for IgnoreGCPolicy
      28                 :             : #include <js/Id.h>
      29                 :             : #include <js/TypeDecls.h>
      30                 :             : #include <js/Utility.h>  // for UniqueChars
      31                 :             : 
      32                 :             : #include "gjs/auto.h"
      33                 :             : #include "gjs/gerror-result.h"
      34                 :             : #include "gjs/macros.h"
      35                 :             : #include "util/log.h"
      36                 :             : 
      37                 :             : #if GJS_VERBOSE_ENABLE_MARSHAL
      38                 :             : #    include "gi/arg-types-inl.h"  // for static_type_name
      39                 :             : #endif
      40                 :             : 
      41                 :             : namespace JS {
      42                 :             : class CallArgs;
      43                 :             : 
      44                 :             : struct Dummy {};
      45                 :             : using GTypeNotUint64 =
      46                 :             :     std::conditional_t<!std::is_same_v<GType, uint64_t>, GType, Dummy>;
      47                 :             : 
      48                 :             : // The GC sweep method should ignore FundamentalTable and GTypeTable's key types
      49                 :             : // Forward declarations
      50                 :             : template <>
      51                 :             : struct GCPolicy<void*> : public IgnoreGCPolicy<void*> {};
      52                 :             : // We need GCPolicy<GType> for GTypeTable. SpiderMonkey already defines
      53                 :             : // GCPolicy<uint64_t> which is equal to GType on some systems; for others we
      54                 :             : // need to define it. (macOS's uint64_t is unsigned long long, which is a
      55                 :             : // different type from unsigned long, even if they are the same width)
      56                 :             : template <>
      57                 :             : struct GCPolicy<GTypeNotUint64> : public IgnoreGCPolicy<GTypeNotUint64> {};
      58                 :             : }  // namespace JS
      59                 :             : 
      60                 :             : /* Flags that should be set on properties exported from native code modules.
      61                 :             :  * Basically set these on API, but do NOT set them on data.
      62                 :             :  *
      63                 :             :  * PERMANENT: forbid deleting the prop
      64                 :             :  * ENUMERATE: allows copyProperties to work among other reasons to have it
      65                 :             :  */
      66                 :             : #define GJS_MODULE_PROP_FLAGS (JSPROP_PERMANENT | JSPROP_ENUMERATE)
      67                 :             : 
      68                 :             : /*
      69                 :             :  * GJS_GET_THIS:
      70                 :             :  * @cx: JSContext pointer passed into JSNative function
      71                 :             :  * @argc: Number of arguments passed into JSNative function
      72                 :             :  * @vp: Argument value array passed into JSNative function
      73                 :             :  * @args: Name for JS::CallArgs variable defined by this code snippet
      74                 :             :  * @to: Name for JS::RootedObject variable referring to function's this
      75                 :             :  *
      76                 :             :  * A convenience macro for getting the 'this' object a function was called with.
      77                 :             :  * Use in any JSNative function.
      78                 :             :  */
      79                 :             : #define GJS_GET_THIS(cx, argc, vp, args, to)          \
      80                 :             :     JS::CallArgs args = JS::CallArgsFromVp(argc, vp); \
      81                 :             :     JS::RootedObject to(cx);                          \
      82                 :             :     if (!args.computeThis(cx, &to))                   \
      83                 :             :         return false;
      84                 :             : 
      85                 :             : void gjs_throw_constructor_error             (JSContext       *context);
      86                 :             : 
      87                 :             : void gjs_throw_abstract_constructor_error(JSContext* cx,
      88                 :             :                                           const JS::CallArgs& args);
      89                 :             : 
      90                 :             : GJS_JSAPI_RETURN_CONVENTION
      91                 :             : JSObject* gjs_build_string_array(JSContext* cx,
      92                 :             :                                  const std::vector<std::string>& strings);
      93                 :             : 
      94                 :             : GJS_JSAPI_RETURN_CONVENTION
      95                 :             : JSObject* gjs_define_string_array(JSContext* cx, JS::HandleObject obj,
      96                 :             :                                   const char* array_name,
      97                 :             :                                   const std::vector<std::string>& strings,
      98                 :             :                                   unsigned attrs);
      99                 :             : 
     100                 :             : [[gnu::format(printf, 2, 3)]] void gjs_throw(JSContext* cx, const char* format,
     101                 :             :                                              ...);
     102                 :             : [[gnu::format(printf, 4, 5)]] void gjs_throw_custom(JSContext* cx,
     103                 :             :                                                     JSExnType error_kind,
     104                 :             :                                                     const char* error_name,
     105                 :             :                                                     const char* format, ...);
     106                 :             : void        gjs_throw_literal                (JSContext       *context,
     107                 :             :                                               const char      *string);
     108                 :             : bool gjs_throw_gerror_message(JSContext* cx, Gjs::AutoError const&);
     109                 :             : 
     110                 :             : bool        gjs_log_exception                (JSContext       *context);
     111                 :             : 
     112                 :             : bool gjs_log_exception_uncaught(JSContext* cx);
     113                 :             : 
     114                 :             : void gjs_log_exception_full(JSContext* cx, JS::HandleValue exc,
     115                 :             :                             JS::HandleString message, GLogLevelFlags level);
     116                 :             : 
     117                 :             : void gjs_warning_reporter(JSContext*, JSErrorReport* report);
     118                 :             : 
     119                 :             : GJS_JSAPI_RETURN_CONVENTION
     120                 :             : JS::UniqueChars gjs_string_to_utf8(JSContext* cx, const JS::Value string_val);
     121                 :             : GJS_JSAPI_RETURN_CONVENTION
     122                 :             : bool gjs_string_to_utf8_n(JSContext* cx, JS::HandleString str, JS::UniqueChars* output,
     123                 :             :                           size_t* output_len);
     124                 :             : GJS_JSAPI_RETURN_CONVENTION
     125                 :             : JSString* gjs_lossy_string_from_utf8(JSContext* cx, const char* utf8_string);
     126                 :             : GJS_JSAPI_RETURN_CONVENTION
     127                 :             : JSString* gjs_lossy_string_from_utf8_n(JSContext* cx, const char* utf8_string,
     128                 :             :                                        size_t len);
     129                 :             : GJS_JSAPI_RETURN_CONVENTION
     130                 :             : bool gjs_string_from_utf8(JSContext             *context,
     131                 :             :                           const char            *utf8_string,
     132                 :             :                           JS::MutableHandleValue value_p);
     133                 :             : GJS_JSAPI_RETURN_CONVENTION
     134                 :             : bool gjs_string_from_utf8_n(JSContext             *cx,
     135                 :             :                             const char            *utf8_chars,
     136                 :             :                             size_t                 len,
     137                 :             :                             JS::MutableHandleValue out);
     138                 :             : 
     139                 :             : GJS_JSAPI_RETURN_CONVENTION
     140                 :             : bool gjs_string_to_filename(JSContext*, const JS::Value,
     141                 :             :                             Gjs::AutoChar* filename_string);
     142                 :             : 
     143                 :             : GJS_JSAPI_RETURN_CONVENTION
     144                 :             : bool gjs_string_from_filename(JSContext             *context,
     145                 :             :                               const char            *filename_string,
     146                 :             :                               ssize_t                n_bytes,
     147                 :             :                               JS::MutableHandleValue value_p);
     148                 :             : 
     149                 :             : GJS_JSAPI_RETURN_CONVENTION
     150                 :             : bool gjs_string_get_char16_data(JSContext       *cx,
     151                 :             :                                 JS::HandleString str,
     152                 :             :                                 char16_t       **data_p,
     153                 :             :                                 size_t          *len_p);
     154                 :             : 
     155                 :             : GJS_JSAPI_RETURN_CONVENTION
     156                 :             : bool gjs_string_to_ucs4(JSContext       *cx,
     157                 :             :                         JS::HandleString value,
     158                 :             :                         gunichar       **ucs4_string_p,
     159                 :             :                         size_t          *len_p);
     160                 :             : GJS_JSAPI_RETURN_CONVENTION
     161                 :             : bool gjs_string_from_ucs4(JSContext             *cx,
     162                 :             :                           const gunichar        *ucs4_string,
     163                 :             :                           ssize_t                n_chars,
     164                 :             :                           JS::MutableHandleValue value_p);
     165                 :             : 
     166                 :             : GJS_JSAPI_RETURN_CONVENTION
     167                 :             : bool gjs_get_string_id(JSContext* cx, jsid id, JS::UniqueChars* name_p);
     168                 :             : GJS_JSAPI_RETURN_CONVENTION
     169                 :             : jsid        gjs_intern_string_to_id          (JSContext       *context,
     170                 :             :                                               const char      *string);
     171                 :             : 
     172                 :             : GJS_JSAPI_RETURN_CONVENTION
     173                 :             : bool        gjs_unichar_from_string          (JSContext       *context,
     174                 :             :                                               JS::Value        string,
     175                 :             :                                               gunichar        *result);
     176                 :             : 
     177                 :             : /* Functions intended for more "internal" use */
     178                 :             : 
     179                 :             : void gjs_maybe_gc (JSContext *context);
     180                 :             : void gjs_gc_if_needed(JSContext *cx);
     181                 :             : 
     182                 :             : GJS_JSAPI_RETURN_CONVENTION
     183                 :             : JS::UniqueChars format_saved_frame(JSContext* cx, JS::HandleObject saved_frame,
     184                 :             :                                    size_t indent = 0);
     185                 :             : 
     186                 :             : /* Overloaded functions, must be outside G_DECLS. More types are intended to be
     187                 :             :  * added as the opportunity arises. */
     188                 :             : 
     189                 :             : GJS_JSAPI_RETURN_CONVENTION
     190                 :             : bool gjs_object_require_property(JSContext             *context,
     191                 :             :                                  JS::HandleObject       obj,
     192                 :             :                                  const char            *obj_description,
     193                 :             :                                  JS::HandleId           property_name,
     194                 :             :                                  JS::MutableHandleValue value);
     195                 :             : 
     196                 :             : GJS_JSAPI_RETURN_CONVENTION
     197                 :             : bool gjs_object_require_property(JSContext       *cx,
     198                 :             :                                  JS::HandleObject obj,
     199                 :             :                                  const char      *description,
     200                 :             :                                  JS::HandleId     property_name,
     201                 :             :                                  bool            *value);
     202                 :             : 
     203                 :             : GJS_JSAPI_RETURN_CONVENTION
     204                 :             : bool gjs_object_require_property(JSContext       *cx,
     205                 :             :                                  JS::HandleObject obj,
     206                 :             :                                  const char      *description,
     207                 :             :                                  JS::HandleId     property_name,
     208                 :             :                                  int32_t         *value);
     209                 :             : 
     210                 :             : GJS_JSAPI_RETURN_CONVENTION
     211                 :             : bool gjs_object_require_property(JSContext* cx, JS::HandleObject obj,
     212                 :             :                                  const char* description,
     213                 :             :                                  JS::HandleId property_name,
     214                 :             :                                  JS::UniqueChars* value);
     215                 :             : 
     216                 :             : GJS_JSAPI_RETURN_CONVENTION
     217                 :             : bool gjs_object_require_property(JSContext              *cx,
     218                 :             :                                  JS::HandleObject        obj,
     219                 :             :                                  const char             *description,
     220                 :             :                                  JS::HandleId            property_name,
     221                 :             :                                  JS::MutableHandleObject value);
     222                 :             : 
     223                 :             : GJS_JSAPI_RETURN_CONVENTION
     224                 :             : bool gjs_object_require_converted_property(JSContext       *context,
     225                 :             :                                            JS::HandleObject obj,
     226                 :             :                                            const char      *description,
     227                 :             :                                            JS::HandleId     property_name,
     228                 :             :                                            uint32_t        *value);
     229                 :             : 
     230                 :             : [[nodiscard]] std::string gjs_debug_bigint(JS::BigInt* bi);
     231                 :             : [[nodiscard]] std::string gjs_debug_string(JSString* str);
     232                 :             : [[nodiscard]] std::string gjs_debug_symbol(JS::Symbol* const sym);
     233                 :             : [[nodiscard]] std::string gjs_debug_object(JSObject* obj);
     234                 :             : [[nodiscard]] std::string gjs_debug_callable(JSObject* callable);
     235                 :             : [[nodiscard]] std::string gjs_debug_value(JS::Value v);
     236                 :             : [[nodiscard]] std::string gjs_debug_id(jsid id);
     237                 :             : 
     238                 :             : [[nodiscard]] Gjs::AutoChar gjs_hyphen_to_underscore(const char* str);
     239                 :             : [[nodiscard]] Gjs::AutoChar gjs_hyphen_to_camel(const char* str);
     240                 :             : 
     241                 :             : #if defined(G_OS_WIN32) && (defined(_MSC_VER) && (_MSC_VER >= 1900))
     242                 :             : [[nodiscard]] std::wstring gjs_win32_vc140_utf8_to_utf16(const char* str);
     243                 :             : #endif
     244                 :             : 
     245                 :             : // Custom GC reasons; SpiderMonkey includes a bunch of "Firefox reasons" which
     246                 :             : // don't apply when embedding the JS engine, so we repurpose them for our own
     247                 :             : // reasons.
     248                 :             : 
     249                 :             : // clang-format off
     250                 :             : #define FOREACH_GC_REASON(macro)  \
     251                 :             :     macro(LINUX_RSS_TRIGGER, 0)   \
     252                 :             :     macro(GJS_CONTEXT_DISPOSE, 1) \
     253                 :             :     macro(BIG_HAMMER, 2)          \
     254                 :             :     macro(GJS_API_CALL, 3)        \
     255                 :             :     macro(LOW_MEMORY, 4)
     256                 :             : // clang-format on
     257                 :             : 
     258                 :             : namespace Gjs {
     259                 :             : 
     260                 :             : struct GCReason {
     261                 :             : #define DEFINE_GC_REASON(name, ix)                     \
     262                 :             :     static constexpr JS::GCReason name = JS::GCReason( \
     263                 :             :         static_cast<int>(JS::GCReason::FIRST_FIREFOX_REASON) + ix);
     264                 :             : FOREACH_GC_REASON(DEFINE_GC_REASON);
     265                 :             : #undef DEFINE_GC_REASON
     266                 :             : 
     267                 :             : #define COUNT_GC_REASON(name, ix) +1
     268                 :             : static constexpr size_t N_REASONS = 0 FOREACH_GC_REASON(COUNT_GC_REASON);
     269                 :             : #undef COUNT_GC_REASON
     270                 :             : };
     271                 :             : 
     272                 :             : template <typename T>
     273                 :        1663 : [[nodiscard]] bool bigint_is_out_of_range(JS::BigInt* bi, T* clamped) {
     274                 :             :     static_assert(sizeof(T) == 8, "64-bit types only");
     275                 :        1663 :     g_assert(bi && "bigint cannot be null");
     276                 :        1663 :     g_assert(clamped && "forgot out parameter");
     277                 :             : 
     278                 :             :     gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
     279                 :             :                       "Checking if BigInt %s is out of range for type %s",
     280                 :             :                       gjs_debug_bigint(bi).c_str(), Gjs::static_type_name<T>());
     281                 :             : 
     282         [ +  + ]:        1663 :     if (JS::BigIntFits(bi, clamped)) {
     283                 :             :         gjs_debug_marshal(
     284                 :             :             GJS_DEBUG_GFUNCTION, "BigInt %s is in the range of type %s",
     285                 :             :             std::to_string(*clamped).c_str(), Gjs::static_type_name<T>());
     286                 :        1645 :         return false;
     287                 :             :     }
     288                 :             : 
     289         [ +  + ]:          18 :     if (JS::BigIntIsNegative(bi)) {
     290                 :          10 :         *clamped = std::numeric_limits<T>::min();
     291                 :             :     } else {
     292                 :           8 :         *clamped = std::numeric_limits<T>::max();
     293                 :             :     }
     294                 :             : 
     295                 :             :     gjs_debug_marshal(GJS_DEBUG_GFUNCTION,
     296                 :             :                       "BigInt %s is not in the range of type %s, clamped to %s",
     297                 :             :                       gjs_debug_bigint(bi).c_str(), Gjs::static_type_name<T>(),
     298                 :             :                       std::to_string(*clamped).c_str());
     299                 :          18 :     return true;
     300                 :             : }
     301                 :             : 
     302                 :             : }  // namespace Gjs
     303                 :             : 
     304                 :             : [[nodiscard]] const char* gjs_explain_gc_reason(JS::GCReason reason);
     305                 :             : 
     306                 :             : #endif  // GJS_JSAPI_UTIL_H_
        

Generated by: LCOV version 2.0-1