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: 2012 Red Hat, Inc.
4 : :
5 : : #include <config.h>
6 : :
7 : : #include <sstream>
8 : :
9 : : #include <girepository.h>
10 : : #include <glib-object.h>
11 : :
12 : : #include <js/TypeDecls.h>
13 : : #include <mozilla/Maybe.h>
14 : :
15 : : #include "gi/function.h"
16 : : #include "gi/info.h"
17 : : #include "gi/wrapperutils.h"
18 : : #include "gjs/jsapi-util.h"
19 : :
20 : : using mozilla::Maybe;
21 : :
22 : : /* Default spidermonkey toString is worthless. Replace it
23 : : * with something that gives us both the introspection name
24 : : * and a memory address.
25 : : */
26 : 297 : bool gjs_wrapper_to_string_func(JSContext* context, JSObject* this_obj,
27 : : const char* objtype,
28 : : Maybe<const GI::BaseInfo> info, GType gtype,
29 : : const void* native_address,
30 : : JS::MutableHandleValue rval) {
31 : 297 : std::ostringstream out;
32 : 297 : out << '[' << objtype;
33 [ + + ]: 297 : if (!native_address)
34 : 2 : out << " prototype of";
35 : : else
36 : 295 : out << " instance wrapper";
37 : :
38 [ + + ]: 297 : if (info) {
39 : 264 : out << " GIName:" << info->ns() << "." << info->name();
40 : : } else {
41 : 33 : out << " GType:" << g_type_name(gtype);
42 : : }
43 : :
44 : 297 : out << " jsobj@" << this_obj;
45 [ + + ]: 297 : if (native_address)
46 : 295 : out << " native@" << native_address;
47 : :
48 : 297 : out << ']';
49 : :
50 : 297 : return gjs_string_from_utf8(context, out.str().c_str(), rval);
51 : 297 : }
52 : :
53 : 2 : bool gjs_wrapper_throw_nonexistent_field(JSContext* cx, GType gtype,
54 : : const char* field_name) {
55 : 2 : gjs_throw(cx, "No property %s on %s", field_name, g_type_name(gtype));
56 : 2 : return false;
57 : : }
58 : :
59 : 3 : bool gjs_wrapper_throw_readonly_field(JSContext* cx, GType gtype,
60 : : const char* field_name) {
61 : 3 : gjs_throw(cx, "Property %s.%s is not writable", g_type_name(gtype),
62 : : field_name);
63 : 3 : return false;
64 : : }
65 : :
66 : : template <GI::InfoTag TAG>
67 : 1941 : bool gjs_define_static_methods(JSContext* cx, JS::HandleObject constructor,
68 : : GType gtype, const GI::UnownedInfo<TAG> info) {
69 [ + - + + ]: 74803 : for (GI::AutoFunctionInfo meth_info : info.methods()) {
70 : : // Anything that isn't a method we put on the constructor. This
71 : : // includes <constructor> introspection methods, as well as static
72 : : // methods. We may want to change this to use
73 : : // GI_FUNCTION_IS_CONSTRUCTOR and GI_FUNCTION_IS_STATIC or the like
74 : : // in the future.
75 [ + + ]: 36431 : if (!meth_info.is_method()) {
76 [ - + ]: 5590 : if (!gjs_define_function(cx, constructor, gtype, meth_info))
77 : 0 : return false;
78 : : }
79 : : }
80 : :
81 : : // Also define class/interface methods if there is a gtype struct
82 : :
83 : 1941 : Maybe<GI::AutoStructInfo> type_struct;
84 : : if constexpr (TAG == GI::InfoTag::OBJECT)
85 : 614 : type_struct = info.class_struct();
86 : : else if constexpr (TAG == GI::InfoTag::INTERFACE)
87 : 213 : type_struct = info.iface_struct();
88 [ + + ]: 1941 : if (!type_struct)
89 : 1247 : return true;
90 : :
91 [ + - + + ]: 1616 : for (GI::AutoFunctionInfo meth_info : type_struct->methods()) {
92 [ - + ]: 461 : if (!gjs_define_function(cx, constructor, gtype, meth_info))
93 : 0 : return false;
94 : : }
95 : :
96 : 694 : return true;
97 : 1941 : }
98 : :
99 : : // All possible instantiations are needed
100 : : template bool gjs_define_static_methods<GI::InfoTag::ENUM>(
101 : : JSContext*, JS::HandleObject constructor, GType, const GI::EnumInfo);
102 : : template bool gjs_define_static_methods<GI::InfoTag::INTERFACE>(
103 : : JSContext*, JS::HandleObject constructor, GType, const GI::InterfaceInfo);
104 : : template bool gjs_define_static_methods<GI::InfoTag::OBJECT>(
105 : : JSContext*, JS::HandleObject constructor, GType, const GI::ObjectInfo);
106 : : template bool gjs_define_static_methods<GI::InfoTag::STRUCT>(
107 : : JSContext*, JS::HandleObject constructor, GType, const GI::StructInfo);
108 : : template bool gjs_define_static_methods<GI::InfoTag::UNION>(
109 : : JSContext*, JS::HandleObject constructor, GType, const GI::UnionInfo);
|