Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
FunctionWrapper.h
Go to the documentation of this file.
1/* Copyright (C) 2024 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDED_FUNCTIONWRAPPER
19#define INCLUDED_FUNCTIONWRAPPER
20
21#include "ScriptConversions.h"
22#include "ScriptExceptions.h"
23#include "ScriptRequest.h"
24
25#include <fmt/format.h>
26#include <tuple>
27#include <type_traits>
28#include <stdexcept>
29#include <utility>
30
31class ScriptInterface;
32
33/**
34 * This class introduces templates to conveniently wrap C++ functions in JSNative functions.
35 * This _is_ rather template heavy, so compilation times beware.
36 * The C++ code can have arbitrary arguments and arbitrary return types, so long
37 * as they can be converted to/from JS using Script::ToJSVal (FromJSVal respectively),
38 * and they are default-constructible (TODO: that can probably changed).
39 * (This could be a namespace, but I like being able to specify public/private).
40 */
42{
43private:
44 ScriptFunction() = delete;
47
48 /**
49 * In JS->C++ calls, types are converted using FromJSVal,
50 * and this requires them to be default-constructible (as that function takes an out parameter)
51 * thus constref needs to be removed when defining the tuple.
52 * Exceptions are:
53 * - const ScriptRequest& (as the first argument only, for implementation simplicity).
54 * - const ScriptInterface& (as the first argument only, for implementation simplicity).
55 * - JS::HandleValue
56 */
57 template<typename T>
58 using type_transform = std::conditional_t<
59 std::is_same_v<const ScriptRequest&, T> || std::is_same_v<const ScriptInterface&, T>,
60 T,
61 std::remove_const_t<typename std::remove_reference_t<T>>
62 >;
63
64 /**
65 * Convenient struct to get info on a [class] [const] function pointer.
66 * TODO VS19: I ran into a really weird bug with an auto specialisation on this taking function pointers.
67 * It'd be good to add it back once we upgrade.
68 */
69 template <class T> struct args_info;
70
71 template<typename R, typename ...Types>
72 struct args_info<R(*)(Types ...)>
73 {
74 static constexpr const size_t nb_args = sizeof...(Types);
75 using return_type = R;
76 using object_type = void;
77 using arg_types = std::tuple<type_transform<Types>...>;
78 };
79
80 template<typename C, typename R, typename ...Types>
81 struct args_info<R(C::*)(Types ...)> : public args_info<R(*)(Types ...)> { using object_type = C; };
82 template<typename C, typename R, typename ...Types>
83 struct args_info<R(C::*)(Types ...) const> : public args_info<R(C::*)(Types ...)> {};
84
85 struct IteratorResultError : std::runtime_error
86 {
87 IteratorResultError(const std::string& property) :
88 IteratorResultError{property.c_str()}
89 {}
90 IteratorResultError(const char* property) :
91 std::runtime_error{fmt::format("Failed to get `{}` from an `IteratorResult`.", property)}
92 {}
93 using std::runtime_error::runtime_error;
94 };
95
96 ///////////////////////////////////////////////////////////////////////////
97 ///////////////////////////////////////////////////////////////////////////
98
99 /**
100 * DoConvertFromJS takes a type, a JS argument, and converts.
101 * The type T must be default constructible (except for HandleValue, which is handled specially).
102 * (possible) TODO: this could probably be changed if FromJSVal had a different signature.
103 * @param wentOk - true if the conversion succeeded and wentOk was true before, false otherwise.
104 */
105 template<size_t idx, typename T>
106 static T DoConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& wentOk)
107 {
108 // No need to convert JS values.
109 if constexpr (std::is_same_v<T, JS::HandleValue>)
110 {
111 // Default-construct values that aren't passed by JS.
112 // TODO: this should perhaps be removed, as it's distinct from C++ default values and kind of tricky.
113 if (idx >= args.length())
114 return JS::UndefinedHandleValue;
115 else
116 {
117 // GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch.
118 UNUSED2(rq); UNUSED2(args); UNUSED2(wentOk);
119 return args[idx]; // This passes the null handle value if idx is beyond the length of args.
120 }
121 }
122 else
123 {
124 // Default-construct values that aren't passed by JS.
125 // TODO: this should perhaps be removed, as it's distinct from C++ default values and kind of tricky.
126 if (idx >= args.length())
127 return {};
128 else
129 {
130 T ret;
131 wentOk &= Script::FromJSVal<T>(rq, args[idx], ret);
132 return ret;
133 }
134 }
135 }
136
137 /**
138 * Wrapper: calls DoConvertFromJS for each element in T.
139 */
140 template<typename... T, size_t... idx>
141 static std::tuple<T...> DoConvertFromJS(std::index_sequence<idx...>, const ScriptRequest& rq,
142 JS::CallArgs& args, bool& wentOk)
143 {
144 return {DoConvertFromJS<idx, T>(rq, args, wentOk)...};
145 }
146
147 /**
148 * ConvertFromJS is a wrapper around DoConvertFromJS, and handles specific cases for the
149 * first argument (ScriptRequest, ...).
150 *
151 * Trick: to unpack the types of the tuple as a parameter pack, we deduce them from the function signature.
152 * To do that, we want the tuple in the arguments, but we don't want to actually have to default-instantiate,
153 * so we'll pass a nullptr that's static_cast to what we want.
154 */
155 template<typename ...Types>
156 static std::tuple<Types...> ConvertFromJS(const ScriptRequest& rq, JS::CallArgs& args, bool& wentOk,
157 std::tuple<Types...>*)
158 {
159 return DoConvertFromJS<Types...>(std::index_sequence_for<Types...>(), rq, args, wentOk);
160 }
161
162 // Overloads for ScriptRequest& first argument.
163 template<typename ...Types>
164 static std::tuple<const ScriptRequest&, Types...> ConvertFromJS(const ScriptRequest& rq,
165 JS::CallArgs& args, bool& wentOk, std::tuple<const ScriptRequest&, Types...>*)
166 {
167 return std::tuple_cat(std::tie(rq), DoConvertFromJS<Types...>(
168 std::index_sequence_for<Types...>(), rq, args, wentOk));
169 }
170
171 // Overloads for ScriptInterface& first argument.
172 template<typename ...Types>
173 static std::tuple<const ScriptInterface&, Types...> ConvertFromJS(const ScriptRequest& rq,
174 JS::CallArgs& args, bool& wentOk, std::tuple<const ScriptInterface&, Types...>*)
175 {
176 return std::tuple_cat(std::tie(rq.GetScriptInterface()),
177 DoConvertFromJS<Types...>(std::index_sequence_for<Types...>(), rq, args, wentOk));
178 }
179
180 ///////////////////////////////////////////////////////////////////////////
181 ///////////////////////////////////////////////////////////////////////////
182
183 /**
184 * Wrap std::apply for the case where we have an object method or a regular function.
185 */
186 template <auto callable, typename T, typename tuple>
187 static typename args_info<decltype(callable)>::return_type call(T* object, tuple& args)
188 {
189 if constexpr(std::is_same_v<T, void>)
190 {
191 // GCC (at least < 9) & VS17 prints warnings if arguments are not used in some constexpr branch.
192 UNUSED2(object);
193 return std::apply(callable, args);
194 }
195 else
196 return std::apply(callable, std::tuple_cat(std::forward_as_tuple(*object), args));
197 }
198
199 ///////////////////////////////////////////////////////////////////////////
200 ///////////////////////////////////////////////////////////////////////////
201
202 struct IgnoreResult_t {};
204
205 /**
206 * Converts any number of arguments to a `JS::MutableHandleValueVector`.
207 * If `idx` is empty this function does nothing. For that case there is a
208 * `[[maybe_unused]]` on `argv`. GCC would issue a
209 * "-Wunused-but-set-parameter" warning.
210 * For references like `rq` this warning isn't issued.
211 */
212 template<typename... Types, size_t... idx>
213 static void ToJSValVector(std::index_sequence<idx...>, const ScriptRequest& rq,
214 [[maybe_unused]] JS::MutableHandleValueVector argv, const Types&... params)
215 {
216 (Script::ToJSVal(rq, argv[idx], params), ...);
217 }
218
219 /**
220 * Wrapper around calling a JS function from C++.
221 * Arguments are const& to avoid lvalue/rvalue issues, and so can't be used as out-parameters.
222 * In particular, the problem is that Rooted are deduced as Rooted, not Handle, and so can't be copied.
223 * This could be worked around with more templates, but it doesn't seem particularly worth doing.
224 */
225 template<typename R, typename ...Args>
226 static bool Call_(const ScriptRequest& rq, JS::HandleValue val, const char* name, R& ret, const Args&... args)
227 {
228 JS::RootedObject obj(rq.cx);
229 if (!JS_ValueToObject(rq.cx, val, &obj) || !obj)
230 return false;
231
232 // Fetch the property explicitly - this avoids converting the arguments if it doesn't exist.
233 JS::RootedValue func(rq.cx);
234 if (!JS_GetProperty(rq.cx, obj, name, &func) || func.isUndefined())
235 return false;
236
237 JS::RootedValueVector argv(rq.cx);
238 ignore_result(argv.resize(sizeof...(Args)));
239 ToJSValVector(std::index_sequence_for<Args...>{}, rq, &argv, args...);
240
241 bool success;
242 if constexpr (std::is_same_v<R, JS::MutableHandleValue>)
243 success = JS_CallFunctionValue(rq.cx, obj, func, argv, ret);
244 else
245 {
246 JS::RootedValue jsRet(rq.cx);
247 success = JS_CallFunctionValue(rq.cx, obj, func, argv, &jsRet);
248 if constexpr (!std::is_same_v<R, IgnoreResult_t>)
249 {
250 if (success)
251 Script::FromJSVal(rq, jsRet, ret);
252 }
253 else
254 UNUSED2(ret); // VS2017 complains.
255 }
256 // Even if everything succeeded, there could be pending exceptions
257 return !ScriptException::CatchPending(rq) && success;
258 }
259
260 ///////////////////////////////////////////////////////////////////////////
261 ///////////////////////////////////////////////////////////////////////////
262public:
263 template <typename T>
264 using ObjectGetter = T*(*)(const ScriptRequest&, JS::CallArgs&);
265
266 // TODO: the fact that this takes class and not auto is to work around an odd VS17 bug.
267 // It can be removed with VS19.
268 template <class callableType>
270
271 /**
272 * The meat of this file. This wraps a C++ function into a JSNative,
273 * so that it can be called from JS and manipulated in Spidermonkey.
274 * Most C++ functions can be directly wrapped, so long as their arguments are
275 * convertible from JS::Value and their return value is convertible to JS::Value (or void)
276 * The C++ function may optionally take const ScriptRequest& or ScriptInterface& as its first argument.
277 * The function may be an object method, in which case you need to pass an appropriate getter
278 *
279 * Optimisation note: the ScriptRequest object is created even without arguments,
280 * as it's necessary for IsExceptionPending.
281 *
282 * @param thisGetter to get the object, if necessary.
283 */
284 template <auto callable, GetterFor<decltype(callable)> thisGetter = nullptr>
285 static bool ToJSNative(JSContext* cx, unsigned argc, JS::Value* vp)
286 {
287 using ObjType = typename args_info<decltype(callable)>::object_type;
288
289 JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
290 ScriptRequest rq(cx);
291
292 // If the callable is an object method, we must specify how to fetch the object.
293 static_assert(std::is_same_v<typename args_info<decltype(callable)>::object_type, void> || thisGetter != nullptr,
294 "ScriptFunction::Register - No getter specified for object method");
295
296// GCC 7 triggers spurious warnings
297#ifdef __GNUC__
298#pragma GCC diagnostic push
299#pragma GCC diagnostic ignored "-Waddress"
300#endif
301 ObjType* obj = nullptr;
302 if constexpr (thisGetter != nullptr)
303 {
304 obj = thisGetter(rq, args);
305 if (!obj)
306 return false;
307 }
308#ifdef __GNUC__
309#pragma GCC diagnostic pop
310#endif
311
312 bool wentOk = true;
313 typename args_info<decltype(callable)>::arg_types outs = ConvertFromJS(rq, args, wentOk,
314 static_cast<typename args_info<decltype(callable)>::arg_types*>(nullptr));
315 if (!wentOk)
316 return false;
317
318 /**
319 * TODO: error handling isn't standard, and since this can call any C++ function,
320 * there's no simple obvious way to deal with it.
321 * For now we check for pending JS exceptions, but it would probably be nicer
322 * to standardise on something, or perhaps provide an "errorHandler" here.
323 */
324 if constexpr (std::is_same_v<void, typename args_info<decltype(callable)>::return_type>)
325 call<callable>(obj, outs);
326 else if constexpr (std::is_same_v<JS::Value, typename args_info<decltype(callable)>::return_type>)
327 args.rval().set(call<callable>(obj, outs));
328 else
329 Script::ToJSVal(rq, args.rval(), call<callable>(obj, outs));
330
331 return !ScriptException::IsPending(rq);
332 }
333
334 /**
335 * Call a JS function @a name, property of object @a val, with the arguments @a args.
336 * @a ret will be updated with the return value, if any.
337 * @return the success (or failure) thereof.
338 */
339 template<typename R, typename ...Args>
340 static bool Call(const ScriptRequest& rq, JS::HandleValue val, const char* name, R& ret, const Args&... args)
341 {
342 return Call_(rq, val, name, ret, std::forward<const Args>(args)...);
343 }
344
345 // Specialisation for MutableHandleValue return.
346 template<typename ...Args>
347 static bool Call(const ScriptRequest& rq, JS::HandleValue val, const char* name, JS::MutableHandleValue ret, const Args&... args)
348 {
349 return Call_(rq, val, name, ret, std::forward<const Args>(args)...);
350 }
351
352 /**
353 * Call a JS function @a name, property of object @a val, with the arguments @a args.
354 * @return the success (or failure) thereof.
355 */
356 template<typename ...Args>
357 static bool CallVoid(const ScriptRequest& rq, JS::HandleValue val, const char* name, const Args&... args)
358 {
359 return Call(rq, val, name, IgnoreResult, std::forward<const Args>(args)...);
360 }
361
362 /**
363 * Call a JS function @a name, property of object @a val, with the argument @a args. Repeatetly
364 * invokes @a yieldCallback with the yielded value.
365 * @return the final value of the generator.
366 */
367 template<typename Callback>
368 static JS::Value RunGenerator(const ScriptRequest& rq, JS::HandleValue val, const char* name,
369 JS::HandleValue arg, Callback yieldCallback)
370 {
371 JS::RootedValue generator{rq.cx};
372 if (!ScriptFunction::Call(rq, val, name, &generator, arg))
373 throw std::runtime_error{fmt::format("Failed to call the generator `{}`.", name)};
374
375 const auto continueGenerator = [&](const char* property, auto... args) -> JS::Value
376 {
377 JS::RootedValue iteratorResult{rq.cx};
378 if (!ScriptFunction::Call(rq, generator, property, &iteratorResult, args...))
379 throw std::runtime_error{fmt::format("Failed to call `{}`.", name)};
380 return iteratorResult;
381 };
382
383 JS::PersistentRootedValue error{rq.cx, JS::UndefinedValue()};
384 while (true)
385 {
386 JS::RootedValue iteratorResult{rq.cx, error.isUndefined() ? continueGenerator("next") :
387 continueGenerator("throw", std::exchange(error, JS::UndefinedValue()))};
388
389 try
390 {
391 JS::RootedObject iteratorResultObject{rq.cx, &iteratorResult.toObject()};
392
393 bool done;
394 if (!Script::FromJSProperty(rq, iteratorResult, "done", done, true))
395 throw IteratorResultError{"done"};
396
397 JS::RootedValue value{rq.cx};
398 if (!JS_GetProperty(rq.cx, iteratorResultObject, "value", &value))
399 throw IteratorResultError{"value"};
400
401 if (done)
402 return value;
403
404 yieldCallback(value);
405 }
406 catch (const std::exception& e)
407 {
408 JS::RootedValue global{rq.cx, rq.globalValue()};
409 if (!ScriptFunction::Call(rq, global, "Error", &error, e.what()))
410 throw std::runtime_error{"Failed to construct `Error`."};
411 }
412 }
413 }
414
415 /**
416 * Return a function spec from a C++ function.
417 */
418 template <auto callable, GetterFor<decltype(callable)> thisGetter = nullptr>
419 static JSFunctionSpec Wrap(const char* name,
420 const u16 flags = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
421 {
422 return JS_FN(name, (&ToJSNative<callable, thisGetter>), args_info<decltype(callable)>::nb_args, flags);
423 }
424
425 /**
426 * Return a JSFunction from a C++ function.
427 */
428 template <auto callable, GetterFor<decltype(callable)> thisGetter = nullptr>
429 static JSFunction* Create(const ScriptRequest& rq, const char* name,
430 const u16 flags = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
431 {
432 return JS_NewFunction(rq.cx, &ToJSNative<callable, thisGetter>, args_info<decltype(callable)>::nb_args, flags, name);
433 }
434
435 /**
436 * Register a function on the native scope (usually 'Engine').
437 */
438 template <auto callable, GetterFor<decltype(callable)> thisGetter = nullptr>
439 static void Register(const ScriptRequest& rq, const char* name,
440 const u16 flags = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
441 {
442 JS_DefineFunction(rq.cx, rq.nativeScope, name, &ToJSNative<callable, thisGetter>, args_info<decltype(callable)>::nb_args, flags);
443 }
444
445 /**
446 * Register a function on @param scope.
447 * Prefer the version taking ScriptRequest unless you have a good reason not to.
448 * @see Register
449 */
450 template <auto callable, GetterFor<decltype(callable)> thisGetter = nullptr>
451 static void Register(JSContext* cx, JS::HandleObject scope, const char* name,
452 const u16 flags = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)
453 {
454 JS_DefineFunction(cx, scope, name, &ToJSNative<callable, thisGetter>, args_info<decltype(callable)>::nb_args, flags);
455 }
456};
457
458#endif // INCLUDED_FUNCTIONWRAPPER
This class introduces templates to conveniently wrap C++ functions in JSNative functions.
Definition: FunctionWrapper.h:42
static bool CallVoid(const ScriptRequest &rq, JS::HandleValue val, const char *name, const Args &... args)
Call a JS function name, property of object val, with the arguments args.
Definition: FunctionWrapper.h:357
static bool Call_(const ScriptRequest &rq, JS::HandleValue val, const char *name, R &ret, const Args &... args)
Wrapper around calling a JS function from C++.
Definition: FunctionWrapper.h:226
ScriptFunction(const ScriptFunction &)=delete
static JSFunctionSpec Wrap(const char *name, const u16 flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
Return a function spec from a C++ function.
Definition: FunctionWrapper.h:419
ScriptFunction()=delete
static bool Call(const ScriptRequest &rq, JS::HandleValue val, const char *name, JS::MutableHandleValue ret, const Args &... args)
Definition: FunctionWrapper.h:347
static JS::Value RunGenerator(const ScriptRequest &rq, JS::HandleValue val, const char *name, JS::HandleValue arg, Callback yieldCallback)
Call a JS function name, property of object val, with the argument args.
Definition: FunctionWrapper.h:368
static void Register(const ScriptRequest &rq, const char *name, const u16 flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
Register a function on the native scope (usually 'Engine').
Definition: FunctionWrapper.h:439
static std::tuple< T... > DoConvertFromJS(std::index_sequence< idx... >, const ScriptRequest &rq, JS::CallArgs &args, bool &wentOk)
Wrapper: calls DoConvertFromJS for each element in T.
Definition: FunctionWrapper.h:141
static JSFunction * Create(const ScriptRequest &rq, const char *name, const u16 flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
Return a JSFunction from a C++ function.
Definition: FunctionWrapper.h:429
static IgnoreResult_t IgnoreResult
Definition: FunctionWrapper.h:203
static void ToJSValVector(std::index_sequence< idx... >, const ScriptRequest &rq, JS::MutableHandleValueVector argv, const Types &... params)
Converts any number of arguments to a JS::MutableHandleValueVector.
Definition: FunctionWrapper.h:213
ObjectGetter< typename args_info< callableType >::object_type > GetterFor
Definition: FunctionWrapper.h:269
static std::tuple< Types... > ConvertFromJS(const ScriptRequest &rq, JS::CallArgs &args, bool &wentOk, std::tuple< Types... > *)
ConvertFromJS is a wrapper around DoConvertFromJS, and handles specific cases for the first argument ...
Definition: FunctionWrapper.h:156
static T DoConvertFromJS(const ScriptRequest &rq, JS::CallArgs &args, bool &wentOk)
DoConvertFromJS takes a type, a JS argument, and converts.
Definition: FunctionWrapper.h:106
static std::tuple< const ScriptInterface &, Types... > ConvertFromJS(const ScriptRequest &rq, JS::CallArgs &args, bool &wentOk, std::tuple< const ScriptInterface &, Types... > *)
Definition: FunctionWrapper.h:173
static bool ToJSNative(JSContext *cx, unsigned argc, JS::Value *vp)
The meat of this file.
Definition: FunctionWrapper.h:285
static void Register(JSContext *cx, JS::HandleObject scope, const char *name, const u16 flags=JSPROP_ENUMERATE|JSPROP_READONLY|JSPROP_PERMANENT)
Register a function on.
Definition: FunctionWrapper.h:451
static args_info< decltype(callable)>::return_type call(T *object, tuple &args)
Wrap std::apply for the case where we have an object method or a regular function.
Definition: FunctionWrapper.h:187
std::conditional_t< std::is_same_v< const ScriptRequest &, T >||std::is_same_v< const ScriptInterface &, T >, T, std::remove_const_t< typename std::remove_reference_t< T > > > type_transform
In JS->C++ calls, types are converted using FromJSVal, and this requires them to be default-construct...
Definition: FunctionWrapper.h:62
ScriptFunction(ScriptFunction &&)=delete
static std::tuple< const ScriptRequest &, Types... > ConvertFromJS(const ScriptRequest &rq, JS::CallArgs &args, bool &wentOk, std::tuple< const ScriptRequest &, Types... > *)
Definition: FunctionWrapper.h:164
T *(*)(const ScriptRequest &, JS::CallArgs &) ObjectGetter
Definition: FunctionWrapper.h:264
static bool Call(const ScriptRequest &rq, JS::HandleValue val, const char *name, R &ret, const Args &... args)
Call a JS function name, property of object val, with the arguments args.
Definition: FunctionWrapper.h:340
Abstraction around a SpiderMonkey JS::Realm.
Definition: ScriptInterface.h:72
Spidermonkey maintains some 'local' state via the JSContext* object.
Definition: ScriptRequest.h:60
const ScriptInterface & GetScriptInterface() const
Return the scriptInterface active when creating this ScriptRequest.
Definition: ScriptInterface.cpp:98
JS::Value globalValue() const
Definition: ScriptInterface.cpp:93
JSContext * cx
Definition: ScriptRequest.h:92
JS::HandleObject nativeScope
Definition: ScriptRequest.h:94
#define UNUSED2(param)
mark a function local variable or parameter as unused and avoid the corresponding compiler warning.
Definition: code_annotation.h:58
void ignore_result(const T &)
Silence the 'unused result' warning.
Definition: code_annotation.h:67
bool IsPending(const ScriptRequest &rq)
Definition: ScriptExceptions.cpp:28
bool CatchPending(const ScriptRequest &rq)
Log and then clear the current pending exception.
Definition: ScriptExceptions.cpp:33
bool FromJSVal(const ScriptRequest &rq, const JS::HandleValue val, T &ret)
Convert a JS::Value to a C++ type.
void ToJSVal(const ScriptRequest &rq, JS::MutableHandleValue ret, T const &val)
Convert a C++ type to a JS::Value.
bool FromJSProperty(const ScriptRequest &rq, const JS::HandleValue val, const char *name, T &ret, bool strict=false)
Convert a named property of an object to a C++ type.
Definition: ScriptConversions.h:71
bool error(JSContext *cx, uint argc, JS::Value *vp)
Definition: ScriptInterface.cpp:173
Definition: ShaderDefines.cpp:31
#define T(string_literal)
Definition: secure_crt.cpp:77
Definition: FunctionWrapper.h:202
Definition: FunctionWrapper.h:86
IteratorResultError(const char *property)
Definition: FunctionWrapper.h:90
IteratorResultError(const std::string &property)
Definition: FunctionWrapper.h:87
std::tuple< type_transform< Types >... > arg_types
Definition: FunctionWrapper.h:77
void object_type
Definition: FunctionWrapper.h:76
R return_type
Definition: FunctionWrapper.h:75
Convenient struct to get info on a [class] [const] function pointer.
Definition: FunctionWrapper.h:69
uint16_t u16
Definition: types.h:38