1 /* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /*
3  * Copyright (c) 2008  litl, LLC
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #ifndef GI_GERROR_H_
25 #define GI_GERROR_H_
26 
27 #include <config.h>
28 
29 #include <girepository.h>
30 #include <glib-object.h>
31 #include <glib.h>
32 
33 #include <js/PropertySpec.h>
34 #include <js/TypeDecls.h>
35 
36 #include "gi/wrapperutils.h"
37 #include "cjs/macros.h"
38 #include "util/log.h"
39 
40 class ErrorPrototype;
41 class ErrorInstance;
42 namespace JS {
43 class CallArgs;
44 }
45 
46 /* To conserve memory, we have two different kinds of private data for GError
47  * JS wrappers: ErrorInstance, and ErrorPrototype. Both inherit from ErrorBase
48  * for their common functionality. For more information, see the notes in
49  * wrapperutils.h.
50  *
51  * ErrorPrototype, unlike the other GIWrapperPrototype subclasses, represents a
52  * single error domain instead of a single GType. All Errors have a GType of
53  * G_TYPE_ERROR.
54  *
55  * Note that in some situations GError structs can show up as BoxedInstance
56  * instead of ErrorInstance. We have some special cases in this code to deal
57  * with that.
58  */
59 
60 class ErrorBase
61     : public GIWrapperBase<ErrorBase, ErrorPrototype, ErrorInstance> {
62     friend class GIWrapperBase<ErrorBase, ErrorPrototype, ErrorInstance>;
63 
64  protected:
65     explicit ErrorBase(ErrorPrototype* proto = nullptr)
GIWrapperBase(proto)66         : GIWrapperBase(proto) {}
~ErrorBase(void)67     ~ErrorBase(void) {}
68 
69     static const GjsDebugTopic debug_topic = GJS_DEBUG_GERROR;
70     static constexpr const char* debug_tag = "gerror";
71 
72     static const struct JSClassOps class_ops;
73     static const struct JSClass klass;
74     static JSPropertySpec proto_properties[];
75     static JSFunctionSpec static_methods[];
76 
77     // Accessors
78 
79  public:
80     [[nodiscard]] GQuark domain(void) const;
81 
82     // Property getters
83 
84  protected:
85     GJS_JSAPI_RETURN_CONVENTION
86     static bool get_domain(JSContext* cx, unsigned argc, JS::Value* vp);
87     GJS_JSAPI_RETURN_CONVENTION
88     static bool get_message(JSContext* cx, unsigned argc, JS::Value* vp);
89     GJS_JSAPI_RETURN_CONVENTION
90     static bool get_code(JSContext* cx, unsigned argc, JS::Value* vp);
91 
92     // JS methods
93 
94     GJS_JSAPI_RETURN_CONVENTION
95     static bool value_of(JSContext* cx, unsigned argc, JS::Value* vp);
96 
97  public:
98     GJS_JSAPI_RETURN_CONVENTION
99     static bool to_string(JSContext* cx, unsigned argc, JS::Value* vp);
100 
101     // Helper methods
102 
103     GJS_JSAPI_RETURN_CONVENTION
104     static GError* to_c_ptr(JSContext* cx, JS::HandleObject obj);
105 
106     GJS_JSAPI_RETURN_CONVENTION
107     static bool transfer_to_gi_argument(JSContext* cx, JS::HandleObject obj,
108                                         GIArgument* arg,
109                                         GIDirection transfer_direction,
110                                         GITransfer transfer_ownership);
111 
112     GJS_JSAPI_RETURN_CONVENTION
113     static bool typecheck(JSContext* cx, JS::HandleObject obj);
114     [[nodiscard]] static bool typecheck(JSContext* cx, JS::HandleObject obj,
115                                         GjsTypecheckNoThrow);
116 };
117 
118 class ErrorPrototype : public GIWrapperPrototype<ErrorBase, ErrorPrototype,
119                                                  ErrorInstance, GIEnumInfo> {
120     friend class GIWrapperPrototype<ErrorBase, ErrorPrototype, ErrorInstance,
121                                     GIEnumInfo>;
122     friend class GIWrapperBase<ErrorBase, ErrorPrototype, ErrorInstance>;
123 
124     GQuark m_domain;
125 
126     static constexpr InfoType::Tag info_type_tag = InfoType::Enum;
127 
128     explicit ErrorPrototype(GIEnumInfo* info, GType gtype);
129     ~ErrorPrototype(void);
130 
131     GJS_JSAPI_RETURN_CONVENTION
132     bool get_parent_proto(JSContext* cx, JS::MutableHandleObject proto) const;
133 
134  public:
domain(void)135     [[nodiscard]] GQuark domain(void) const { return m_domain; }
136 
137     GJS_JSAPI_RETURN_CONVENTION
138     static bool define_class(JSContext* cx, JS::HandleObject in_object,
139                              GIEnumInfo* info);
140 };
141 
142 class ErrorInstance : public GIWrapperInstance<ErrorBase, ErrorPrototype,
143                                                ErrorInstance, GError> {
144     friend class GIWrapperInstance<ErrorBase, ErrorPrototype, ErrorInstance,
145                                    GError>;
146     friend class GIWrapperBase<ErrorBase, ErrorPrototype, ErrorInstance>;
147 
148     explicit ErrorInstance(JSContext* cx, JS::HandleObject obj);
149     ~ErrorInstance(void);
150 
151  public:
copy_gerror(GError * other)152     void copy_gerror(GError* other) { m_ptr = g_error_copy(other); }
153     GJS_JSAPI_RETURN_CONVENTION
copy_ptr(JSContext *,GType,void * ptr)154     static GError* copy_ptr(JSContext*, GType, void* ptr) {
155         return g_error_copy(static_cast<GError*>(ptr));
156     }
157 
158     // Accessors
159 
message(void)160     [[nodiscard]] const char* message(void) const { return m_ptr->message; }
code(void)161     [[nodiscard]] int code(void) const { return m_ptr->code; }
162 
163     // JS constructor
164 
165  private:
166     GJS_JSAPI_RETURN_CONVENTION
167     bool constructor_impl(JSContext* cx, JS::HandleObject obj,
168                           const JS::CallArgs& args);
169 
170     // Public API
171 
172  public:
173     GJS_JSAPI_RETURN_CONVENTION
174     static JSObject* object_for_c_ptr(JSContext* cx, GError* gerror);
175 };
176 
177 GJS_JSAPI_RETURN_CONVENTION
178 GError *gjs_gerror_make_from_error(JSContext       *cx,
179                                    JS::HandleObject obj);
180 
181 GJS_JSAPI_RETURN_CONVENTION
182 bool gjs_define_error_properties(JSContext* cx, JS::HandleObject obj);
183 
184 bool gjs_throw_gerror(JSContext* cx, GError* error);
185 
186 #endif  // GI_GERROR_H_
187