MySQL 9.3.0
Source Code Documentation
polyglot_utils.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2024, 2025, Oracle and/or its affiliates.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2.0,
6 * as published by the Free Software Foundation.
7 *
8 * This program is designed to work with certain software (including
9 * but not limited to OpenSSL) that is licensed under separate terms,
10 * as designated in a particular file or component or in included license
11 * documentation. The authors of MySQL hereby grant you an additional
12 * permission to link the program and your derivative works with the
13 * separately licensed software that they have either included with
14 * the program or referenced in the documentation.
15 *
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
19 * the GNU General Public License, version 2.0, for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24 */
25
26#ifndef MYSQLSHDK_SCRIPTING_POLYGLOT_UTILS_POLYGLOT_UTILS_H_
27#define MYSQLSHDK_SCRIPTING_POLYGLOT_UTILS_POLYGLOT_UTILS_H_
28
29#include <cassert>
30#include <iostream>
31#include <memory>
32#include <optional>
33#include <string>
34#include <string_view>
35#include <unordered_map>
36#include <vector>
37
39
43
44namespace shcore {
45namespace polyglot {
46
47enum class Language { JAVASCRIPT };
48
49inline const char *k_origin_shell{"(shell)"};
50
51inline const char *k_syntax_error{"SyntaxError"};
52inline const char *k_interrupted_error{"InterruptedError"};
53
54/**
55 * Returns the collectable and arguments sent by Polyglot on a call to a C++
56 * function.
57 *
58 * This function is meant to be used by a C++ function that does not require to
59 * validate the argument count.
60 */
61size_t parse_callback_args(poly_thread thread, poly_callback_info args,
62 std::vector<poly_value> *argv, void **data);
63
64/**
65 * Returns the collectable sent by Polyglot on a call to a C++ function.
66 *
67 * This function is meant to be used in C++ functions that have no arguments.
68 *
69 * It also centralizes a validation to ensure no arguments are sent by Polyglot.
70 */
71bool get_data(poly_thread thread, poly_callback_info args,
72 std::string_view name, void **data);
73
74/**
75 * Returns the collectable and arguments sent by Polyglot on a call to a C++
76 * function.
77 *
78 * This function is meant to be used in C++ functions that expect a specific
79 * number of arguments since it centralizes a validation to ensure the expected
80 * arguments were received.
81 */
82bool get_args_and_data(poly_thread thread, poly_callback_info args,
83 std::string_view name, void **data, size_t expected_argc,
84 std::vector<poly_value> *argv);
85
86/**
87 * Identifies if a given poly_value corresponds to a wrapped C++ element.
88 */
89bool is_native_type(poly_thread thread, poly_value value, Collectable_type type,
90 void **native_data = nullptr);
91
92/**
93 * Retrieves the names of the members of the given poly_value.
94 */
95std::vector<std::string> get_member_keys(poly_thread thread,
96 poly_context context,
97 poly_value object);
98
99/**
100 * Converts a string into a polyglot string
101 */
102poly_value poly_string(poly_thread thread, poly_context context,
103 std::string_view data);
104
105/**
106 * Converts a polyglot string into a C++ string
107 */
108std::string to_string(poly_thread thread, poly_value obj);
109
110/**
111 * Converts a polyglot string into a C++ int64_t
112 */
113int64_t to_int(poly_thread thread, poly_value obj);
114
115/**
116 * Converts a polyglot string into a C++ double
117 */
118double to_double(poly_thread thread, poly_value obj);
119
120/**
121 * Converts a polyglot string into a C++ double
122 */
123double to_boolean(poly_thread thread, poly_value obj);
124
125/**
126 * Converts a bool into a polyglot boolean
127 */
128poly_value poly_bool(poly_thread thread, poly_context context, bool value);
129
130/**
131 * Converts a bool into a polyglot boolean
132 */
133poly_value poly_uint(poly_thread thread, poly_context context, uint64_t value);
134
135/**
136 * Converts a bool into a polyglot boolean
137 */
138poly_value poly_int(poly_thread thread, poly_context context, int64_t value);
139
140/**
141 * Converts a double into a polyglot double
142 */
143poly_value poly_double(poly_thread thread, poly_context context, double value);
144
145/**
146 * Returns a polyglot null value
147 */
148poly_value poly_null(poly_thread thread, poly_context context);
149
150/**
151 * Converts an array of poly_values into a polyglot array
152 */
153poly_value poly_array(poly_thread thread, poly_context context,
154 const std::vector<poly_value> &values);
155
156/**
157 * Retrieves a member identified with name from the given object
158 */
159poly_value get_member(poly_thread thread, poly_value object,
160 const std::string &name);
161
162/**
163 * Returns true if the given value is executable
164 */
165bool is_executable(poly_thread thread, poly_value object);
166
167/**
168 * The integration of the PolyglotAPI is mostly centered in the registration of
169 * C++ callbacks to implement the functionality for the different proxy objects.
170 * Whenever an exception is reported from any of these callbacks, a
171 * CallbackException object is created in the PolyglotAPI.
172 *
173 * This function is to report a callback exception from C++.
174 */
175void throw_callback_exception(poly_thread thread, const char *error);
176
177/**
178 * Generic handler to be used with functions that interact with the polyglot
179 * library, this is:
180 *
181 * - Require the language instance for the execution
182 * - Receive a vector of polyglot values as arguments
183 * - Return a polyglot value as result
184 */
185template <typename Target, typename Config>
186static poly_value polyglot_handler_fixed_args(poly_thread thread,
187 poly_callback_info args) {
188 std::vector<poly_value> argv;
189 void *data = nullptr;
190 poly_value value = nullptr;
191 try {
192 if (get_args_and_data(thread, args, Config::name, &data, Config::argc,
193 &argv)) {
194 assert(data);
195 const auto instance = static_cast<Target *>(data);
196 const auto language = instance->language();
197 try {
198 value = (instance->*Config::callback)(argv);
199 } catch (const Polyglot_error &exc) {
200 language->throw_exception_object(exc);
201 }
202 }
203 } catch (const std::exception &e) {
204 throw_callback_exception(thread, e.what());
205 }
206 return value;
207}
208
209/**
210 * Generic handler to be used with pure native functions, no interaction with
211 * the polyglot library is done:
212 *
213 * - Receive a vector of Values as arguments
214 * - Return a Value as result
215 */
216template <typename Target, typename Config>
217static poly_value native_handler_fixed_args(poly_thread thread,
218 poly_callback_info args) {
219 std::vector<poly_value> argv;
220 void *data = nullptr;
221 poly_value value = nullptr;
222 try {
223 if (get_args_and_data(thread, args, Config::name, &data, Config::argc,
224 &argv)) {
225 assert(data);
226 const auto instance = static_cast<Target *>(data);
227 const auto language = instance->language();
228 try {
229 value = language->convert(
230 (instance->*Config::callback)(language->convert_args(argv)));
231 } catch (const Polyglot_error &exc) {
232 language->throw_exception_object(exc);
233 }
234 }
235 } catch (const std::exception &e) {
236 throw_callback_exception(thread, e.what());
237 }
238 return value;
239}
240
241/**
242 * Generic handler to be used with functions that interact with the polyglot
243 * library:
244 *
245 * - Receive no arguments
246 * - Return a poly_value as result
247 */
248template <typename Target, typename Config>
249static poly_value polyglot_handler_no_args(poly_thread thread,
250 poly_callback_info args) {
251 void *data = nullptr;
252 poly_value value = nullptr;
253
254 if (get_data(thread, args, Config::name, &data)) {
255 assert(data);
256 const auto instance = static_cast<Target *>(data);
257 const auto language = instance->language();
258 try {
259 value = (instance->*Config::callback)();
260 } catch (const Polyglot_error &exc) {
261 language->throw_exception_object(exc);
262 } catch (const std::exception &e) {
263 throw_callback_exception(thread, e.what());
264 }
265 }
266
267 return value;
268}
269
270/**
271 * Generic handler to be used with pure native functions, no interaction with
272 * the polyglot library is done:
273 *
274 * - Receive no arguments
275 * - Return a Value as result
276 */
277template <typename Target, typename Config>
278static poly_value native_handler_no_args(poly_thread thread,
279 poly_callback_info args) {
280 void *data = nullptr;
281 poly_value value = nullptr;
282
283 if (get_data(thread, args, Config::name, &data)) {
284 assert(data);
285 const auto instance = static_cast<Target *>(data);
286 const auto language = instance->language();
287 try {
288 value = language->convert((instance->*Config::callback)());
289 } catch (const Polyglot_error &exc) {
290 language->throw_exception_object(exc);
291 } catch (const std::exception &e) {
292 throw_callback_exception(thread, e.what());
293 }
294 }
295
296 return value;
297}
298
299/**
300 * Generic handler to be used with pure native functions, no interaction with
301 * the polyglot library is done:
302 *
303 * - Receive a vector of Values as arguments
304 * - Return a Value as result
305 */
306template <typename Target, typename Config>
307static poly_value native_handler_variable_args(poly_thread thread,
308 poly_callback_info args) {
309 std::vector<poly_value> argv;
310 void *data = nullptr;
311 poly_value value = nullptr;
312
313 try {
314 parse_callback_args(thread, args, &argv, &data);
315 assert(data);
316 const auto instance = static_cast<Target *>(data);
317 const auto language = instance->language();
318
319 try {
320 value = language->convert(
321 (instance->*Config::callback)(language->convert_args(argv)));
322 } catch (const Polyglot_error &exc) {
323 language->throw_exception_object(exc);
324 }
325
326 } catch (const std::exception &e) {
327 throw_callback_exception(thread, e.what());
328 }
329
330 return value;
331}
332
333bool get_member(poly_thread thread, poly_value object, const char *name,
334 poly_value *member);
335bool is_object(poly_thread thread, poly_value object, std::string *class_name);
336
337} // namespace polyglot
338} // namespace shcore
339
340#endif // MYSQLSHDK_SCRIPTING_POLYGLOT_UTILS_POLYGLOT_UTILS_H_
Represents polyglot errors that will be created from information available in the polyglot library st...
Definition: polyglot_error.h:77
ValueType value(const std::optional< ValueType > &v)
Definition: gtid.h:83
const char * k_origin_shell
Definition: polyglot_utils.h:49
static poly_value native_handler_variable_args(poly_thread thread, poly_callback_info args)
Generic handler to be used with pure native functions, no interaction with the polyglot library is do...
Definition: polyglot_utils.h:307
poly_value poly_uint(poly_thread thread, poly_context context, uint64_t value)
Converts a bool into a polyglot boolean.
Definition: polyglot_utils.cc:197
void throw_callback_exception(poly_thread thread, const char *error)
The integration of the PolyglotAPI is mostly centered in the registration of C++ callbacks to impleme...
Definition: polyglot_utils.cc:251
poly_value poly_bool(poly_thread thread, poly_context context, bool value)
Converts a bool into a polyglot boolean.
Definition: polyglot_utils.cc:182
const char * k_syntax_error
Definition: polyglot_utils.h:51
double to_double(poly_thread thread, poly_value obj)
Converts a polyglot string into a C++ double.
Definition: polyglot_utils.cc:163
bool is_executable(poly_thread thread, poly_value object)
Returns true if the given value is executable.
Definition: polyglot_utils.cc:267
poly_value poly_int(poly_thread thread, poly_context context, int64_t value)
Converts a bool into a polyglot boolean.
Definition: polyglot_utils.cc:189
std::vector< std::string > get_member_keys(poly_thread thread, poly_context context, poly_value object)
Retrieves the names of the members of the given poly_value.
Definition: polyglot_utils.cc:232
static poly_value polyglot_handler_fixed_args(poly_thread thread, poly_callback_info args)
Generic handler to be used with functions that interact with the polyglot library,...
Definition: polyglot_utils.h:186
bool is_object(poly_thread thread, poly_value object, std::string *class_name)
Definition: polyglot_utils.cc:287
double to_boolean(poly_thread thread, poly_value obj)
Converts a polyglot string into a C++ double.
Definition: polyglot_utils.cc:170
bool get_args_and_data(poly_thread thread, poly_callback_info args, std::string_view name, void **data, size_t expected_argc, std::vector< poly_value > *argv)
Returns the collectable and arguments sent by Polyglot on a call to a C++ function.
Definition: polyglot_utils.cc:109
int64_t to_int(poly_thread thread, poly_value obj)
Converts a polyglot string into a C++ int64_t.
Definition: polyglot_utils.cc:156
static poly_value native_handler_fixed_args(poly_thread thread, poly_callback_info args)
Generic handler to be used with pure native functions, no interaction with the polyglot library is do...
Definition: polyglot_utils.h:217
Collectable_type
Definition: polyglot_collectable.h:39
const char * k_interrupted_error
Definition: polyglot_utils.h:52
poly_value poly_double(poly_thread thread, poly_context context, double value)
Converts a double into a polyglot double.
Definition: polyglot_utils.cc:209
poly_value poly_array(poly_thread thread, poly_context context, const std::vector< poly_value > &values)
Converts an array of poly_values into a polyglot array.
Definition: polyglot_utils.cc:223
bool is_native_type(poly_thread thread, poly_value value, Collectable_type type, void **native_data)
Identifies if a given poly_value corresponds to a wrapped C++ element.
Definition: polyglot_utils.cc:126
Language
Definition: polyglot_utils.h:47
std::string to_string(poly_thread thread, poly_value obj)
Converts a polyglot string into a C++ string.
Definition: polyglot_utils.cc:145
poly_value poly_null(poly_thread thread, poly_context context)
Returns a polyglot null value.
Definition: polyglot_utils.cc:216
size_t parse_callback_args(poly_thread thread, poly_callback_info args, std::vector< poly_value > *argv, void **data)
Parses the callback information sent by polyglot, returning if requested a vector with the arguments ...
Definition: polyglot_utils.cc:63
poly_value poly_string(poly_thread thread, poly_context context, std::string_view data)
Converts a string into a polyglot string.
Definition: polyglot_utils.cc:177
poly_value get_member(poly_thread thread, poly_value object, const std::string &name)
Retrieves a member identified with name from the given object.
Definition: polyglot_utils.cc:259
static poly_value polyglot_handler_no_args(poly_thread thread, poly_callback_info args)
Generic handler to be used with functions that interact with the polyglot library:
Definition: polyglot_utils.h:249
bool get_data(poly_thread thread, poly_callback_info args, std::string_view name, void **data)
Returns the collectable sent by Polyglot on a call to a C++ function.
Definition: polyglot_utils.cc:92
static poly_value native_handler_no_args(poly_thread thread, poly_callback_info args)
Generic handler to be used with pure native functions, no interaction with the polyglot library is do...
Definition: polyglot_utils.h:278
Definition: file_system_exceptions.h:34
required string type
Definition: replication_group_member_actions.proto:34
case opt name
Definition: sslopt-case.h:29