Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qnapi_p.h
Go to the documentation of this file.
1// Copyright (C) 2025 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QNAPI_P_H
5#define QNAPI_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtCore/private/qohoslogger_p.h>
19#include <algorithm>
20#include <functional>
21#include <initializer_list>
22#include <iterator>
23#include <memory>
24#include <napi.h>
25#include <optional>
26#include <string>
27#include <tuple>
28#include <type_traits>
29#include <utility>
30#include <vector>
31
32QT_BEGIN_NAMESPACE
33
34namespace QNapi {
35
36template<typename... ExtraArgs>
38{
39public:
40 template<typename Func>
41 ExtendedCallbackFuncWrapper(Func &&callbackFunc, std::enable_if_t<std::is_void<std::invoke_result_t<Func, const Napi::CallbackInfo &, ExtraArgs...>>::value, char *> = nullptr);
42
43 template<typename Func>
44 ExtendedCallbackFuncWrapper(Func &&callbackFunc, std::enable_if_t<std::is_base_of<Napi::Value, std::invoke_result_t<Func, const Napi::CallbackInfo &, ExtraArgs...>>::value, short *> = nullptr);
45
46 template<typename Func>
47 ExtendedCallbackFuncWrapper(Func &&callbackFunc, std::enable_if_t<std::is_void<std::invoke_result_t<Func, ExtraArgs...>>::value, int *> = nullptr);
48
49 template<typename Func>
51
53
54private:
55 std::function<Napi::Value(const Napi::CallbackInfo &, ExtraArgs...)> m_callbackFunc;
56};
57
59
60using Value = Napi::Value;
61
63
65
67
68using Date = Napi::Date;
69
71
73
75
77
79
81
82template<typename BufferT>
84
85template<typename ExternalT>
87
88template<typename T>
90
91class Promise;
92
94{
95public:
96 template<typename T, std::enable_if_t<!std::is_same<std::decay_t<T>, ValueWrapper>::value, int> = 0>
97 ValueWrapper(T &&inputValue);
98
99 Napi::Value mapToValue(napi_env env) const;
100
101private:
102 std::function<Napi::Value(napi_env)> m_valueFactory;
103};
104
105class Array : public Napi::Array
106{
107public:
108 using Napi::Array::Array;
109
110 static Array New(napi_env env, std::size_t length = 0);
111
112 Array(const Napi::Array &other);
113 Array &operator=(const Napi::Array &other);
114
115 void fill(const ValueWrapper &value);
116};
117
118class Object : public Napi::Object
119{
120public:
121 using Napi::Object::Object;
122
123 static Object New(napi_env env);
124
125 Object(const Napi::Object &other);
126 Object &operator=(const Napi::Object &other);
127
128 template<typename T = Value>
129 T get(const std::string &expr) const;
130
131 template<typename T = Value>
132 T get(const Napi::Name &name) const;
133
134 template<typename T = Value>
135 T eval(const std::string &expr, const std::vector<ValueWrapper> &exprArgs = {}) const;
136
137 QNapi::Promise evalToPromiseOrRejectOnThrow(const std::string &expr, const std::vector<ValueWrapper> &exprArgs = {}) const;
138
139 void set(const std::string &name, const ValueWrapper &value);
140
141 void set(const Napi::Name &name, const ValueWrapper &value);
142
143 void set(const std::vector<std::pair<std::string, ValueWrapper>> &namedValues);
144
145 template<typename Result = Value>
146 Q_DECL_DEPRECATED_X("Use eval() with a methodName() or methodName(*) expression instead.")
147 Result call(const std::string &methodName, const std::vector<ValueWrapper> &args = {}) const;
148
149 // Returns the string keys selected by keyMode and keyFilter, numeric keys as strings; symbol
150 // keys are skipped. Use it instead of GetPropertyNames() or iterating over the object, as both
151 // rely on napi_get_property_names(), which has been seen to return non-enumerable and symbol
152 // keys as well on HarmonyOS devices.
153 std::vector<std::string> getFilteredStringKeys(napi_key_collection_mode keyMode, napi_key_filter keyFilter) const;
154};
155
156template<typename Context>
158
159class Promise : public Napi::Promise
160{
161public:
162 using Napi::Promise::Promise;
163
164 Promise();
165 Promise(const Napi::Promise &other);
166 Promise &operator=(const Napi::Promise &other);
167
168 Promise onThen(CallbackFuncWrapper &&onFulfilledFunc);
169 Promise onThen(CallbackFuncWrapper &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc);
170 Promise onCatch(CallbackFuncWrapper &&onRejectedFunc);
171 Promise onFinally(CallbackFuncWrapper &&onFinallyFunc);
173 CallbackFuncWrapper &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc,
174 CallbackFuncWrapper &&onFinallyFunc);
175
176 template<typename Context>
177 PromiseWithContext<Context> withContext(Context &&context);
178};
179
180template<typename Context>
182{
183public:
184 PromiseWithContext(const Promise &promise, std::shared_ptr<Context> context);
185
188 ExtendedCallbackFuncWrapper<Context &> &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc);
191
192private:
193 std::shared_ptr<Context> m_context;
194};
195
196template<typename T = void>
197class Reference : public Napi::Reference<T>
198{
199public:
200 using Napi::Reference<T>::Reference;
201
202 Reference(Reference<T> &&other);
203 Reference<T> &operator=(Reference<T> &&other);
204
205 Reference(const Reference<T> &other) = delete;
206 Reference<T> &operator=(const Reference<T> &other) = delete;
207
208 Reference(Napi::Reference<T> &&other);
209 Reference<T> &operator=(Napi::Reference<T> &&other);
210
211 static Reference<T> makePersistentFrom(const T &value);
212
213 static Reference<T> makeEmpty();
214};
215
216template<>
218{
219public:
221
222 Reference(Reference<Object> &&other);
224
225 Reference(const Reference<Object> &other) = delete;
226 Reference<Object> &operator=(const Reference<Object> &other) = delete;
227
228 Reference(Napi::Reference<Object> &&other);
229 Reference<Object> &operator=(Napi::Reference<Object> &&other);
230
231 template<typename T = ::QNapi::Value>
232 T eval(const std::string &expr, const std::vector<ValueWrapper> &exprArgs = {}) const;
233
234 QNapi::Promise evalToPromiseOrRejectOnThrow(const std::string &expr, const std::vector<ValueWrapper> &exprArgs = {}) const;
235
236 void set(const std::string &name, const ValueWrapper &value);
237
238 void set(const std::vector<std::pair<std::string, ValueWrapper>> &namedValues);
239
240 template<typename Result = ::QNapi::Value>
241 Q_DECL_DEPRECATED_X("Use eval() with a methodName() or methodName(*) expression instead.")
242 Result call(const std::string &methodName, const std::vector<ValueWrapper> &args = {}) const;
243
244 static Reference<Object> makePersistentFrom(const Object &value);
245
246 static Reference<Object> makeEmpty();
247};
248
249template<>
250class Reference<void>
251{
252public:
253 Reference() = delete;
254
255 template<typename T>
257
258 template<typename T = Value>
259 static Reference<T> makeEmpty();
260};
261
263{
264public:
265 CallbackInfo(const Napi::CallbackInfo &cbInfo);
266
267 CallbackInfo(const CallbackInfo &other) = delete;
268 CallbackInfo &operator=(const CallbackInfo &other) = delete;
269
270 Napi::Env Env() const;
271 std::size_t Length() const;
272
273 template<typename... Args>
274 void getLeadingArgs(const std::string &funcName, Args &...args) const;
275
276 template<typename Arg>
277 Arg getFirstArg(const std::string &funcName) const;
278
279 operator const Napi::CallbackInfo &() const;
280
281private:
282 const Napi::CallbackInfo &m_cbInfo;
283};
284
285std::vector<napi_value> unwrapValues(napi_env env, const std::vector<ValueWrapper> &wrappedValues);
286
287Napi::Error makeLoggedException(napi_env env, const std::string &msg);
288
289template<typename T>
290bool valueTypeMatches(const Napi::Value &value);
291
292template<typename Element>
293bool arrayElementTypesMatch(const Napi::Value &value);
294
295std::string getValueTypeString(const Napi::Value &value);
296
297template<typename T, typename ValueDescriptionSupplier>
298T checkedCast(const Napi::Value &value, ValueDescriptionSupplier &&valueDescSupplier);
299
300template<typename T>
301T checkedCast(const Napi::Value &value);
302
303template<typename OutputContainer, typename Element, typename TransFunc>
304OutputContainer getArrayElements(const Napi::Array &inputArray, TransFunc &&transFunc);
305
306template<typename OutputContainer, typename Element>
307OutputContainer getArrayElements(const Napi::Array &inputArray);
308
309template<typename OutputContainer, typename Element, typename TransFilterFunc>
310OutputContainer getFilteredArrayElements(const Napi::Array &inputArray, TransFilterFunc &&transFilterFunc);
311
312Object makeNewInstance(const Napi::Function &type, const std::vector<ValueWrapper> &args = {});
313
314Object makeNewInstance(const Napi::Object &baseObj, const std::string &typePath, const std::vector<ValueWrapper> &args = {});
315
316Napi::Value getPropOrUndefined(const Napi::Value &obj, const std::string &propName);
317
318template<typename T>
319Napi::Value getPropOrUndefined(const Napi::Reference<T> &objRef, const std::string &propName);
320
321template<typename T>
323getOptionalPropOrEmpty(const Napi::Object &optObj, const std::string &propName, const std::string &objDesc = {});
324
325template<typename T>
327getOptionalPropOrEmpty(const Napi::Object &optObj, const Napi::Name &propName, const std::string &objDesc = {});
328
329Object makeObject(napi_env env, const std::vector<std::pair<std::string, ValueWrapper>> &namedValues = {});
330
331Array makeArray(napi_env env, std::initializer_list<ValueWrapper> values = {});
332
333template<typename InputContainer, typename TransFunc>
334Array makeArray(napi_env env, InputContainer &&inputContainer, TransFunc &&transFunc);
335
336template<typename InputContainer>
337Array makeArray(napi_env env, InputContainer &&inputContainer);
338
339template<typename Result = Napi::Value, typename F>
340Result runEscapingHandleScope(napi_env env, F &&func);
341
342std::string toJsonString(const Napi::Value &value);
343
345
346template<typename T>
348{
349};
350
351template<>
353{
354 static constexpr auto typeCheckMemFun = &Napi::Value::IsBoolean;
355 static constexpr const char *typeName = "Boolean";
356};
357
358template<>
360{
361 static constexpr auto typeCheckMemFun = &Napi::Value::IsNumber;
362 static constexpr const char *typeName = "Number";
363};
364
365template<>
367{
368 static constexpr auto typeCheckMemFun = &Napi::Value::IsBigInt;
369 static constexpr const char *typeName = "BigInt";
370};
371
372template<>
374{
375 static constexpr auto typeCheckMemFun = &Napi::Value::IsDate;
376 static constexpr const char *typeName = "Date";
377};
378
379template<>
381{
382 static constexpr auto typeCheckMemFun = &Napi::Value::IsString;
383 static constexpr const char *typeName = "String";
384};
385
386template<>
388{
389 static constexpr auto typeCheckMemFun = &Napi::Value::IsSymbol;
390 static constexpr const char *typeName = "Symbol";
391};
392
393template<>
395{
396 static constexpr auto typeCheckMemFun = &Napi::Value::IsArray;
397 static constexpr const char *typeName = "Array";
398};
399
400template<>
402{
403};
404
405template<>
407{
408 static constexpr auto typeCheckMemFun = &Napi::Value::IsArrayBuffer;
409 static constexpr const char *typeName = "ArrayBuffer";
410};
411
412template<>
414{
415 static constexpr auto typeCheckMemFun = &Napi::Value::IsTypedArray;
416 static constexpr const char *typeName = "TypedArray";
417};
418
419template<>
421{
422 static constexpr auto typeCheckMemFun = &Napi::Value::IsObject;
423 static constexpr const char *typeName = "Object";
424};
425
426template<>
428{
429};
430
431template<>
433{
434 static constexpr auto typeCheckMemFun = &Napi::Value::IsFunction;
435 static constexpr const char *typeName = "Function";
436};
437
438template<>
440{
441 static constexpr auto typeCheckMemFun = &Napi::Value::IsPromise;
442 static constexpr const char *typeName = "Promise";
443};
444
445template<>
447{
448};
449
450template<>
452{
453 static constexpr auto typeCheckMemFun = &Napi::Value::IsDataView;
454 static constexpr const char *typeName = "DataView";
455};
456
457template<typename BufferT>
459{
460 static constexpr auto typeCheckMemFun = &Napi::Value::IsBuffer;
461 static constexpr const char *typeName = "Buffer";
462};
463
464template<typename ExternalT>
466{
467 static constexpr auto typeCheckMemFun = &Napi::Value::IsExternal;
468 static constexpr const char *typeName = "External";
469};
470
471template<typename T>
473{
474 static constexpr auto typeCheckMemFun = &Napi::Value::IsTypedArray;
475 static constexpr const char *typeName = "TypedArray";
476};
477
478template<typename T>
479constexpr bool isCallbackFuncType()
480{
481 return std::is_constructible<CallbackFuncWrapper, T>::value;
482}
483
484template<typename T>
486{
487 return [callbackFunc = std::move(CallbackFuncWrapper(std::forward<T>(inputValue)).callbackFunc())](napi_env env) {
488 return Napi::Function::New(env, callbackFunc);
489 };
490}
491
492template<typename T>
494{
495 return [inputValue = std::forward<T>(inputValue)](napi_env env) {
496 return Napi::Value::From(env, inputValue);
497 };
498}
499
500inline Napi::Error makeLoggedExceptionImpl(napi_env env, const std::string &msg)
501{
502 qOhosPrintfError("QNapi: exception: %s", msg.c_str());
503 return Napi::Error::New(env, msg);
504}
505
506template<typename T>
507std::enable_if_t<std::is_same<T, Napi::Value>::value, bool> valueTypeMatchesImpl(const Napi::Value &)
508{
509 return true;
510}
511
512template<typename T>
513std::enable_if_t<!std::is_same<T, Napi::Value>::value, bool> valueTypeMatchesImpl(const Napi::Value &value)
514{
515 return (value.*ValueTypeTraits<T>::typeCheckMemFun)();
516}
517
518std::string getArrayElementValueTypeString(const Napi::Array &arrayValue);
519
520inline std::string getValueTypeStringImpl(const Napi::Value &value)
521{
522 using namespace std::string_literals;
523
524 if (value.IsArray()) {
525 auto arrayElemTypeString = getArrayElementValueTypeString(value.As<Napi::Array>());
526 return "Array<"s + arrayElemTypeString + ">"s;
527 }
528
529 // put subtypes of the Napi::Object at the beginning, so that we find most specific type name
530 const std::pair<bool (Napi::Value::*)() const, const char *> typesChecksAndNames[] = {
531 {&Napi::Value::IsEmpty, "<empty>"},
532 {&Napi::Value::IsNull, "Null"},
533 {&Napi::Value::IsUndefined, "Undefined"},
534 {&Napi::Value::IsArray, "Array"},
535 {&Napi::Value::IsArrayBuffer, "ArrayBuffer"},
536 {&Napi::Value::IsBuffer, "Buffer"},
537 {&Napi::Value::IsTypedArray, "TypedArray"},
538 {&Napi::Value::IsDataView, "DataView"},
539 {&Napi::Value::IsFunction, "Function"},
540 {&Napi::Value::IsPromise, "Promise"},
541 {&Napi::Value::IsBigInt, "BigInt"},
542 {&Napi::Value::IsBoolean, "Boolean"},
543 {&Napi::Value::IsDate, "Date"},
544 {&Napi::Value::IsExternal, "External"},
545 {&Napi::Value::IsNumber, "Number"},
546 {&Napi::Value::IsObject, "Object"},
547 {&Napi::Value::IsString, "String"},
548 {&Napi::Value::IsSymbol, "Symbol"},
549 };
550
551 const char *foundTypeName = nullptr;
552 for (const auto &typeCheckEntry : typesChecksAndNames) {
553 if ((value.*(typeCheckEntry.first))()) {
554 foundTypeName = typeCheckEntry.second;
555 break;
556 }
557 }
558
559 return foundTypeName != nullptr ? foundTypeName : "?";
560}
561
562inline std::string getArrayElementValueTypeString(const Napi::Array &arrayValue)
563{
564 constexpr std::size_t maxArrayElementsForTypeCheck = 10;
565
566 std::size_t arrayLength = arrayValue.Length();
567 auto checkRangeSize = std::min(arrayLength, maxArrayElementsForTypeCheck);
568
569 std::string commonElemTypeString;
570 for (std::size_t i = 0; i < checkRangeSize; ++i) {
571 auto elemTypeString = getValueTypeStringImpl(arrayValue.Get(i));
572 if (commonElemTypeString.empty()) {
573 commonElemTypeString = elemTypeString;
574 } else if (commonElemTypeString != elemTypeString) {
575 commonElemTypeString = "";
576 break;
577 }
578 }
579
580 return !commonElemTypeString.empty()
581 ? checkRangeSize == arrayLength
582 ? commonElemTypeString
583 : commonElemTypeString + "?"
584 : "?";
585}
586
587template<typename T, typename ValueDescriptionSupplier>
589 const Napi::Value &value, ValueDescriptionSupplier &&)
590{
591 return value;
592}
593
594template<typename T, typename ValueDescriptionSupplier>
596 const Napi::Value &value, ValueDescriptionSupplier &&valueDescSupplier)
597{
598 using namespace std::string_literals;
599
600 if (!valueTypeMatchesImpl<T>(value)) {
601 constexpr const char *expectedTypeName = ValueTypeTraits<T>::typeName;
602 auto valueTypeStr = getValueTypeStringImpl(value);
603 std::string valueDesc = valueDescSupplier();
604 auto baseErrorMsg =
605 "wrong type (expected '"s + expectedTypeName + "', got '"s + valueTypeStr + "') of Napi value"s;
606 throw makeLoggedExceptionImpl(
607 value.Env(), valueDesc.empty() ? baseErrorMsg : baseErrorMsg + ": "s + valueDesc);
608 }
609
610 return T(value.Env(), value);
611}
612
613template<typename Result, typename F>
614Result runEscapingHandleScopeImpl(napi_env env, F &&func)
615{
616 Napi::EscapableHandleScope scope(env);
617 Result result = std::forward<F>(func)();
618 return checkedCastImpl<Result>(
619 scope.Escape(result),
620 [&]() {
621 return "value escaping from HandleScope";
622 });
623}
624
626 napi_env env, const std::string &callArgsSubExpr, const std::vector<napi_value> &exprArgs)
627{
628 using namespace std::string_literals;
629
630 if (callArgsSubExpr.empty()) {
631 return {};
632 } else if (callArgsSubExpr == "*") {
633 return exprArgs;
634 } else {
635 throw makeLoggedException(
636 env, "illegal call arguments in expression: '"s + callArgsSubExpr + "'"s);
637 }
638}
639
640template<typename T>
642 Napi::Object obj, const std::string &expr, const std::vector<napi_value> &exprArgs = {})
643{
644 using namespace details_qnapi_p_h;
645 using namespace std::string_literals;
646
647 static const std::string newCallTag = "<new>";
648
649 std::pair<Napi::Object, Napi::Value> result;
650
651 auto lastDotPos = expr.rfind('.');
652
653 if (!expr.empty() && expr.back() == ')') {
654 auto openingBracketPos = expr.rfind('(');
655 if (openingBracketPos == std::string::npos)
656 throw makeLoggedExceptionImpl(obj.Env(), "missing opening bracket in '"s + expr + "'"s);
657 bool newInstanceCall =
658 openingBracketPos > newCallTag.size()
659 && expr.compare(openingBracketPos - newCallTag.size(), newCallTag.size(), newCallTag) == 0;
660 auto subFuncArgsExpr = expr.substr(
661 openingBracketPos + 1, expr.size() - 1 - (openingBracketPos + 1));
662 auto subFuncArgs = expandEvalCallArgs(obj.Env(), subFuncArgsExpr, exprArgs);
663 auto subFuncExpr = expr.substr(
664 0, newInstanceCall ? openingBracketPos - newCallTag.size() : openingBracketPos);
665 auto subFuncWithCtx = evalWithContextImpl<Napi::Function>(obj, subFuncExpr, exprArgs);
666 Napi::Value funcCallResult;
667 try {
668 funcCallResult =
669 newInstanceCall
670 ? subFuncWithCtx.second.New(subFuncArgs)
671 : !subFuncWithCtx.first.IsEmpty()
672 ? subFuncWithCtx.second.Call(subFuncWithCtx.first, subFuncArgs)
673 : subFuncWithCtx.second.Call(subFuncArgs);
674 } catch (const Napi::Error &error) {
675 auto message = "QNapi: got exception from call '"s + expr + "': "s + error.what();
676 qOhosPrintfError("%s", message.c_str());
677 throw;
678 }
679
680 result = std::make_pair(Napi::Object(), funcCallResult);
681 } else if (lastDotPos != std::string::npos) {
682 auto subObjExpr = expr.substr(0, lastDotPos);
683 auto propName = expr.substr(lastDotPos + 1);
684
685 auto subObj = evalWithContextImpl<Napi::Object>(obj, subObjExpr, exprArgs).second;
686 if (!subObj.Has(propName)) {
687 throw makeLoggedExceptionImpl(
688 obj.Env(), "object '"s + subObjExpr + "' has no property named '"s + propName + "'"s);
689 }
690
691 result = std::make_pair(subObj, subObj.Get(propName));
692 } else {
693 if (!obj.Has(expr)) {
694 throw makeLoggedExceptionImpl(
695 obj.Env(), "object has no property named '"s + expr + "'"s);
696 }
697
698 result = std::make_pair(obj, obj.Get(expr));
699 }
700
701 return std::make_pair(result.first, checkedCastImpl<T>(result.second, [&]() { return expr; }));
702}
703
705 const Napi::Object &obj, const std::string &methodName, const std::vector<napi_value> &args)
706{
707 using namespace std::string_literals;
708 return runEscapingHandleScopeImpl<Napi::Value>(
709 obj.Env(),
710 [&]() {
711 auto funcWithCtx = evalWithContextImpl<Napi::Function>(obj, methodName);
712 Napi::Value funcResult;
713 try {
714 funcResult = funcWithCtx.second.Call(funcWithCtx.first, args);
715 } catch (const Napi::Error &error) {
716 auto message = "QNapi: got exception from method call '"s + methodName + "': "s + error.what();
717 qOhosPrintfError("%s", message.c_str());
718 throw;
719 }
720
721 return funcResult;
722 });
723}
724
725template<typename Result>
726Result callMethodImpl(const Napi::Object &obj, const std::string &methodName, const std::vector<napi_value> &args)
727{
728 using namespace std::string_literals;
729
730 return checkedCastImpl<Result>(
731 callMethodWithValueResultImpl(obj, methodName, args),
732 [&]() {
733 return "result of '"s + methodName + "' method call"s;
734 });
735}
736
737template<typename Result = Value>
738Result callMethod(const Napi::Object &obj, const std::string &methodName, const std::vector<ValueWrapper> &args)
739{
740 return runEscapingHandleScopeImpl<Result>(
741 obj.Env(),
742 [&]() {
743 return callMethodImpl<Result>(obj, methodName, unwrapValues(obj.Env(), args));
744 });
745}
746
747template<typename Arg>
748void getArgImpl(const std::string &funcName, const Napi::CallbackInfo &cbInfo, Arg &arg, std::size_t argIndex)
749{
750 using namespace std::string_literals;
751
752 arg = checkedCastImpl<Arg>(
753 cbInfo[argIndex],
754 [&]() {
755 return "arg #"s + std::to_string(argIndex) + " of '"s + funcName + "' func call"s;
756 });
757}
758
759template<typename... Args, std::size_t... Is>
761 const std::string &funcName, const Napi::CallbackInfo &cbInfo, std::tuple<Args...> args, std::index_sequence<Is...>)
762{
763 using namespace std::string_literals;
764
765 if (cbInfo.Length() < sizeof...(Args)) {
766 throw makeLoggedExceptionImpl(
767 cbInfo.Env(),
768 "getArgs: func '"s + funcName + "' received less args than expected minimum: "s
769 + std::to_string(cbInfo.Length()) + " vs "s + std::to_string(sizeof...(Args)));
770 }
771
772 auto unused = {(getArgImpl(funcName, cbInfo, std::get<Is>(args), Is), 0)..., 0};
773 (void) unused;
774}
775
776template<typename T>
778getOptionalPropOrEmptyImpl(const Napi::Object &optObj, const Napi::Name &propName, const std::string &objDesc)
779{
780 using namespace std::string_literals;
781
782 if (optObj.IsEmpty() || !optObj.Has(propName))
783 return T();
784
785 auto propValue = optObj.Get(propName);
786
787 return !propValue.IsUndefined()
788 ? QNapi::checkedCast<T>(
789 propValue,
790 [&]() {
791 auto baseDesc = "property '"s + propName.ToString().Utf8Value() + "' of object"s;
792 return !objDesc.empty()
793 ? baseDesc + ": "s + objDesc
794 : baseDesc;
795 })
796 : T();
797}
798
799template<typename Container, typename Element>
800constexpr decltype(auto) forwardContainerElement(Element &element) noexcept
801{
802 using Result = std::conditional_t<std::is_lvalue_reference<Container>::value, Element &, Element &&>;
803 return static_cast<Result>(element);
804}
805
806}
807
808template<typename T, std::enable_if_t<!std::is_same<std::decay_t<T>, ValueWrapper>::value, int>>
813
814inline Napi::Value ValueWrapper::mapToValue(napi_env env) const
815{
816 return m_valueFactory(env);
817}
818
819template<typename... ExtraArgs>
820template<typename Func>
822 Func &&callbackFunc, std::enable_if_t<std::is_void<std::invoke_result_t<Func, const Napi::CallbackInfo &, ExtraArgs...>>::value, char *>)
826 return Napi::Value();
827 })
828{
829 static_assert(!std::is_lvalue_reference<Func>::value, "callback functor must be passed as an rvalue");
830}
831
832template<typename... ExtraArgs>
833template<typename Func>
835 Func &&callbackFunc, std::enable_if_t<std::is_base_of<Napi::Value, std::invoke_result_t<Func, const Napi::CallbackInfo &, ExtraArgs...>>::value, short *>)
838 return (*callbackFunc)(cbInfo, extraArgs...);
839 })
840{
841 static_assert(!std::is_lvalue_reference<Func>::value, "callback functor must be passed as an rvalue");
842}
843
844template<typename... ExtraArgs>
845template<typename Func>
849 (*callbackFunc)(extraArgs...);
850 return Napi::Value();
851 })
852{
853 static_assert(!std::is_lvalue_reference<Func>::value, "callback functor must be passed as an rvalue");
854}
855
856template<typename... ExtraArgs>
857template<typename Func>
859 Func &&callbackFunc, std::enable_if_t<std::is_base_of<Napi::Value, std::invoke_result_t<Func, ExtraArgs...>>::value, long *>)
862 return (*callbackFunc)(extraArgs...);
863 })
864{
865 static_assert(!std::is_lvalue_reference<Func>::value, "callback functor must be passed as an rvalue");
866}
867
868template<typename... ExtraArgs>
870{
871 return m_callbackFunc;
872}
873
874inline Object Object::New(napi_env env)
875{
876 return Napi::Object::New(env);
877}
878
879inline Array Array::New(napi_env env, std::size_t length)
880{
881 return length != 0
882 ? Napi::Array::New(env, length)
883 : Napi::Array::New(env);
884}
885
886inline Array::Array(const Napi::Array &other)
887 : Napi::Array(other)
888{
889}
890
891inline Array &Array::operator=(const Napi::Array &other)
892{
893 Napi::Array::operator=(other);
894 return *this;
895}
896
897inline void Array::fill(const ValueWrapper &value)
898{
899 details_qnapi_p_h::callMethod(*this, "fill", {value});
900}
901
902inline Object::Object(const Napi::Object &other)
903 : Napi::Object(other)
904{
905}
906
907inline Object &Object::operator=(const Napi::Object &other)
908{
909 Napi::Object::operator=(other);
910 return *this;
911}
912
913template<typename T>
914T Object::get(const std::string &expr) const
915{
916 return details_qnapi_p_h::runEscapingHandleScopeImpl<T>(
917 Env(),
918 [&]() {
919 return details_qnapi_p_h::evalWithContextImpl<T>(*this, expr).second;
920 });
921}
922
923template<typename T>
924T Object::get(const Napi::Name &name) const
925{
926 using namespace std::string_literals;
927
928 if (!Has(name)) {
929 throw makeLoggedException(
930 Env(), "object has no property '"s + name.ToString().Utf8Value() + "'"s);
931 }
932
933 return checkedCast<T>(
934 Get(name),
935 [&]() {
936 return "property '"s + name.ToString().Utf8Value() + "'"s;
937 });
938}
939
940template<typename T>
941T Object::eval(const std::string &expr, const std::vector<ValueWrapper> &exprArgs) const
942{
943 using namespace details_qnapi_p_h;
944
945 return runEscapingHandleScope<T>(
946 Env(),
947 [&]() {
948 return evalWithContextImpl<T>(*this, expr, unwrapValues(Env(), exprArgs)).second;
949 });
950}
951
953 const std::string &expr, const std::vector<ValueWrapper> &exprArgs) const
954{
955 return runEscapingHandleScope<QNapi::Promise>(
956 Env(),
957 [&]() {
958 try {
959 return eval<QNapi::Promise>(expr, exprArgs);
960 } catch (const Napi::Error &error) {
961 auto deferred = Napi::Promise::Deferred::New(Env());
962 deferred.Reject(error.Value());
963 return QNapi::Promise(deferred.Promise());
964 }
965 });
966}
967
968inline void Object::set(const std::string &name, const ValueWrapper &value)
969{
970 Napi::HandleScope setPropScope(Env());
971 Set(name, value.mapToValue(Env()));
972}
973
974inline void Object::set(const Napi::Name &name, const ValueWrapper &value)
975{
976 Napi::HandleScope setPropScope(Env());
977 Set(name, value.mapToValue(Env()));
978}
979
980inline void Object::set(const std::vector<std::pair<std::string, ValueWrapper>> &namedValues)
981{
982 Napi::HandleScope setPropsScope(Env());
983 for (const auto &namedValue : namedValues)
984 Set(namedValue.first, namedValue.second.mapToValue(Env()));
985}
986
987template<typename Result>
988Result Object::call(const std::string &methodName, const std::vector<ValueWrapper> &args) const
989{
990 return details_qnapi_p_h::callMethod<Result>(*this, methodName, args);
991}
992
994 napi_key_collection_mode keyMode, napi_key_filter keyFilter) const
995{
996 napi_value keys = nullptr;
997 const napi_status status = napi_get_all_property_names(
998 Env(), *this, keyMode, static_cast<napi_key_filter>(keyFilter | napi_key_skip_symbols),
999 napi_key_numbers_to_strings, &keys);
1000 if (status != napi_ok)
1001 throw Napi::Error::New(Env());
1002
1003 return getArrayElements<std::vector<std::string>, String>(Array(Env(), keys));
1004}
1005
1007 : Napi::Promise(nullptr, nullptr)
1008{
1009}
1010
1011inline Promise::Promise(const Napi::Promise &other)
1012 : Napi::Promise(other)
1013{
1014}
1015
1016inline Promise &Promise::operator=(const Napi::Promise &other)
1017{
1018 Napi::Promise::operator=(other);
1019 return *this;
1020}
1021
1022inline Promise Promise::onThen(CallbackFuncWrapper &&onFulfilledFunc)
1023{
1024 return details_qnapi_p_h::callMethod<Promise>(
1025 *this, "then", {std::move(onFulfilledFunc.callbackFunc())});
1026}
1027
1028inline Promise Promise::onThen(CallbackFuncWrapper &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc)
1029{
1030 return details_qnapi_p_h::callMethod<Promise>(
1031 *this, "then", {std::move(onFulfilledFunc.callbackFunc()), std::move(onRejectedFunc.callbackFunc())});
1032}
1033
1035{
1036 return details_qnapi_p_h::callMethod<Promise>(
1037 *this, "catch", {std::move(onRejectedFunc.callbackFunc())});
1038}
1039
1041{
1042 return details_qnapi_p_h::callMethod<Promise>(
1043 *this, "finally", {std::move(onFinallyFunc.callbackFunc())});
1044}
1045
1047 CallbackFuncWrapper &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc,
1048 CallbackFuncWrapper &&onFinallyFunc)
1049{
1050 return onThen(std::move(onFulfilledFunc), std::move(onRejectedFunc)).onFinally(std::move(onFinallyFunc));
1051}
1052
1053template<typename Context>
1054PromiseWithContext<Context> Promise::withContext(Context &&context)
1055{
1056 static_assert(!std::is_lvalue_reference<Context>::value, "withContext() supports only rvalue contexts");
1057 return PromiseWithContext<Context>(*this, std::make_shared<Context>(std::forward<Context>(context)));
1058}
1059
1060template<typename Context>
1061PromiseWithContext<Context>::PromiseWithContext(const Promise &promise, std::shared_ptr<Context> context)
1062 : Promise(promise)
1063 , m_context(context)
1064{
1065}
1066
1067template<typename Context>
1069 ExtendedCallbackFuncWrapper<Context &> &&onFulfilledFunc)
1070{
1071 return PromiseWithContext(
1072 Promise::onThen(
1073 [context = m_context, onFulfilledFunc = std::move(onFulfilledFunc.callbackFunc())](const Napi::CallbackInfo &cbInfo) {
1074 return onFulfilledFunc(cbInfo, *context);
1075 }),
1076 m_context);
1077}
1078
1079template<typename Context>
1081 ExtendedCallbackFuncWrapper<Context &> &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc)
1082{
1083 return PromiseWithContext(
1084 Promise::onThen(
1085 [context = m_context, onFulfilledFunc = std::move(onFulfilledFunc.callbackFunc())](const Napi::CallbackInfo &cbInfo) {
1086 return onFulfilledFunc(cbInfo, *context);
1087 },
1088 [context = m_context, onRejectedFunc = std::move(onRejectedFunc.callbackFunc())](const Napi::CallbackInfo &cbInfo) {
1089 return onRejectedFunc(cbInfo, *context);
1090 }),
1091 m_context);
1092}
1093
1094template<typename Context>
1096 ExtendedCallbackFuncWrapper<Context &> &&onRejectedFunc)
1097{
1098 return PromiseWithContext(
1100 [context = m_context, onRejectedFunc = std::move(onRejectedFunc.callbackFunc())](const Napi::CallbackInfo &cbInfo) {
1101 return onRejectedFunc(cbInfo, *context);
1102 }),
1103 m_context);
1104}
1105
1106template<typename Context>
1108 ExtendedCallbackFuncWrapper<Context &> &&onFinallyFunc)
1109{
1110 return PromiseWithContext(
1112 [context = m_context, onFinallyFunc = std::move(onFinallyFunc.callbackFunc())](const Napi::CallbackInfo &cbInfo) {
1113 return onFinallyFunc(cbInfo, *context);
1114 }),
1115 m_context);
1116}
1117
1118template<typename T>
1120 : Napi::Reference<T>(std::move(other))
1121{
1122}
1123
1124template<typename T>
1126{
1127 Napi::Reference<T>::operator=(std::move(other));
1128 return *this;
1129}
1130
1131template<typename T>
1132Reference<T>::Reference(Napi::Reference<T> &&other)
1133 : Napi::Reference<T>(std::move(other))
1134{
1135}
1136
1137template<typename T>
1138Reference<T> &Reference<T>::operator=(Napi::Reference<T> &&other)
1139{
1140 Napi::Reference<T>::operator=(std::move(other));
1141 return *this;
1142}
1143
1144template<typename T>
1146{
1147 return Napi::Persistent(value);
1148}
1149
1150template<typename T>
1152{
1153 return Napi::Reference<T>();
1154}
1155
1158{
1159}
1160
1162{
1163 Napi::Reference<Object>::operator=(std::move(other));
1164 return *this;
1165}
1166
1167inline Reference<Object>::Reference(Napi::Reference<Object> &&other)
1169{
1170}
1171
1172inline Reference<Object> &Reference<Object>::operator=(Napi::Reference<Object> &&other)
1173{
1174 Napi::Reference<Object>::operator=(std::move(other));
1175 return *this;
1176}
1177
1178template<typename T>
1179T Reference<Object>::eval(const std::string &expr, const std::vector<ValueWrapper> &exprArgs) const
1180{
1181 return runEscapingHandleScope<T>(
1182 Env(),
1183 [&]() {
1184 return Value().eval<T>(expr, exprArgs);
1185 });
1186}
1187
1189 const std::string &expr, const std::vector<ValueWrapper> &exprArgs) const
1190{
1191 return runEscapingHandleScope<QNapi::Promise>(
1192 Env(),
1193 [&]() {
1194 return Value().evalToPromiseOrRejectOnThrow(expr, exprArgs);
1195 });
1196}
1197
1198inline void Reference<Object>::set(const std::string &name, const ValueWrapper &value)
1199{
1200 Napi::HandleScope scope(Env());
1201 Value().set(name, value);
1202}
1203
1204inline void Reference<Object>::set(const std::vector<std::pair<std::string, ValueWrapper>> &namedValues)
1205{
1206 Napi::HandleScope scope(Env());
1207 Value().set(namedValues);
1208}
1209
1210template<typename Result>
1211Result Reference<Object>::call(const std::string &methodName, const std::vector<ValueWrapper> &args) const
1212{
1213 return runEscapingHandleScope<Result>(
1214 Env(),
1215 [&]() {
1216 return Value().call<Result>(methodName, args);
1217 });
1218}
1219
1221{
1222 return Napi::Persistent(value);
1223}
1224
1226{
1227 return Napi::Reference<Object>();
1228}
1229
1230template<typename T>
1233{
1234 return Napi::Persistent(value);
1235}
1236
1237template<typename T>
1239{
1240 return Napi::Reference<T>();
1241}
1242
1243inline CallbackInfo::CallbackInfo(const Napi::CallbackInfo &cbInfo)
1244 : m_cbInfo(cbInfo)
1245{
1246}
1247
1248inline Napi::Env CallbackInfo::Env() const
1249{
1250 return m_cbInfo.Env();
1251}
1252
1253inline std::size_t CallbackInfo::Length() const
1254{
1255 return m_cbInfo.Length();
1256}
1257
1258template<typename... Args>
1259void CallbackInfo::getLeadingArgs(const std::string &funcName, Args &...args) const
1260{
1261 details_qnapi_p_h::getLeadingArgsImpl(
1262 funcName, m_cbInfo, std::tie(args...), std::make_index_sequence<sizeof...(Args)>());
1263}
1264
1265template<typename Arg>
1266Arg CallbackInfo::getFirstArg(const std::string &funcName) const
1267{
1268 Arg arg;
1269 getLeadingArgs(funcName, arg);
1270 return arg;
1271}
1272
1273inline CallbackInfo::operator const Napi::CallbackInfo &() const
1274{
1275 return m_cbInfo;
1276}
1277
1278inline std::vector<napi_value> unwrapValues(napi_env env, const std::vector<ValueWrapper> &wrappedValues)
1279{
1280 std::vector<napi_value> unwrappedValues;
1281 std::transform(
1282 wrappedValues.begin(), wrappedValues.end(),
1283 std::back_inserter(unwrappedValues),
1284 [&](const ValueWrapper &arg) {
1285 return arg.mapToValue(env);
1286 });
1287 return unwrappedValues;
1288}
1289
1290inline Napi::Error makeLoggedException(napi_env env, const std::string &msg)
1291{
1292 return details_qnapi_p_h::makeLoggedExceptionImpl(env, msg);
1293}
1294
1295template<typename T>
1296bool valueTypeMatches(const Napi::Value &value)
1297{
1298 return details_qnapi_p_h::valueTypeMatchesImpl<T>(value);
1299}
1300
1301template<typename Element>
1302bool arrayElementTypesMatch(const Napi::Value &value)
1303{
1304 if (!valueTypeMatches<Napi::Array>(value))
1305 return false;
1306
1307 auto arrayValue = checkedCast<Napi::Array>(value);
1308 auto arrayLength = arrayValue.Length();
1309
1310 bool allElementsMatch = true;
1311 for (std::size_t i = 0; i < arrayLength; ++i) {
1312 if (!valueTypeMatches<Element>(arrayValue.Get(i))) {
1313 allElementsMatch = false;
1314 break;
1315 }
1316 }
1317
1318 return allElementsMatch;
1319}
1320
1321inline std::string getValueTypeString(const Napi::Value &value)
1322{
1323 return details_qnapi_p_h::getValueTypeStringImpl(value);
1324}
1325
1326template<typename T, typename ValueDescriptionSupplier>
1327T checkedCast(const Napi::Value &value, ValueDescriptionSupplier &&valueDescSupplier)
1328{
1329 return details_qnapi_p_h::checkedCastImpl<T>(
1330 value, std::forward<ValueDescriptionSupplier>(valueDescSupplier));
1331}
1332
1333template<typename T>
1334T checkedCast(const Napi::Value &value)
1335{
1336 return details_qnapi_p_h::checkedCastImpl<T>(
1337 value,
1338 []() {
1339 return std::string();
1340 });
1341}
1342
1343template<typename OutputContainer, typename Element, typename TransFunc>
1344OutputContainer getArrayElements(const Napi::Array &inputArray, TransFunc &&transFunc)
1345{
1346 return getFilteredArrayElements<OutputContainer, Element>(
1347 inputArray,
1348 [&](Element &&elem) {
1349 return std::optional(transFunc(std::forward<Element>(elem)));
1350 });
1351}
1352
1353template<typename OutputContainer, typename Element>
1354OutputContainer getArrayElements(const Napi::Array &inputArray)
1355{
1356 return getArrayElements<OutputContainer, Element>(
1357 inputArray,
1358 [](Element &&elem) {
1359 return std::forward<Element>(elem);
1360 });
1361}
1362
1363template<typename OutputContainer, typename Element, typename TransFilterFunc>
1364OutputContainer getFilteredArrayElements(const Napi::Array &inputArray, TransFilterFunc &&transFilterFunc)
1365{
1366 using namespace std::string_literals;
1367
1368 OutputContainer result;
1369 auto arrayLength = inputArray.Length();
1370 for (std::size_t i = 0; i < arrayLength; ++i) {
1371 auto arg = inputArray.Get(i);
1372 if (!valueTypeMatches<Element>(arg)) {
1373 constexpr const char *expectedTypeName = details_qnapi_p_h::ValueTypeTraits<Element>::typeName;
1374 auto argTypeStr = getValueTypeString(arg);
1375 throw makeLoggedException(
1376 inputArray.Env(),
1377 "wrong type of Napi array element #"s + std::to_string(i)
1378 + ", expected '"s + expectedTypeName + "', got '"s + argTypeStr + "'"s);
1379 }
1380 if (auto optTransformed = transFilterFunc(checkedCast<Element>(arg)))
1381 result.insert(result.end(), std::move(*optTransformed));
1382 }
1383
1384 return result;
1385}
1386
1387inline Object makeNewInstance(const Napi::Function &type, const std::vector<ValueWrapper> &args)
1388{
1389 return type.New(unwrapValues(type.Env(), args));
1390}
1391
1392inline Object makeNewInstance(const Napi::Object &baseObj, const std::string &typePath, const std::vector<ValueWrapper> &args)
1393{
1394 return makeNewInstance(Object(baseObj).get<Napi::Function>(typePath), args);
1395}
1396
1397inline Napi::Value getPropOrUndefined(const Napi::Value &obj, const std::string &propName)
1398{
1399 if (obj.IsEmpty())
1400 return Napi::Value();
1401
1402 if (!obj.IsObject())
1403 return obj.Env().Undefined();
1404
1405 auto typedObj = checkedCast<Napi::Object>(obj);
1406
1407 return typedObj.Has(propName)
1408 ? typedObj.Get(propName)
1409 : typedObj.Env().Undefined();
1410}
1411
1412template<typename T>
1413Napi::Value getPropOrUndefined(const Napi::Reference<T> &objRef, const std::string &propName)
1414{
1415 if (objRef.IsEmpty())
1416 return Napi::Value();
1417
1418 return details_qnapi_p_h::runEscapingHandleScopeImpl<Napi::Value>(
1419 objRef.Env(),
1420 [&]() {
1421 return getPropOrUndefined(objRef.Value(), propName);
1422 });
1423}
1424
1425template<typename T>
1427getOptionalPropOrEmpty(const Napi::Object &optObj, const std::string &propName, const std::string &objDesc)
1428{
1429 return !optObj.IsEmpty()
1430 ? details_qnapi_p_h::getOptionalPropOrEmptyImpl<T>(
1431 optObj, Napi::String::New(optObj.Env(), propName), objDesc)
1432 : T();
1433}
1434
1435template<typename T>
1437getOptionalPropOrEmpty(const Napi::Object &optObj, const Napi::Name &propName, const std::string &objDesc)
1438{
1439 return details_qnapi_p_h::getOptionalPropOrEmptyImpl<T>(optObj, propName, objDesc);
1440}
1441
1442inline Object makeObject(napi_env env, const std::vector<std::pair<std::string, ValueWrapper>> &namedValues)
1443{
1444 auto obj = QNapi::Object::New(env);
1445 obj.set(namedValues);
1446 return obj;
1447}
1448
1449inline Array makeArray(napi_env env, std::initializer_list<ValueWrapper> values)
1450{
1451 return makeArray<std::initializer_list<ValueWrapper> &>(env, values);
1452}
1453
1454template<typename InputContainer, typename TransFunc>
1455Array makeArray(napi_env env, InputContainer &&inputContainer, TransFunc &&transFunc)
1456{
1457 using namespace details_qnapi_p_h;
1458
1459 return runEscapingHandleScopeImpl<Napi::Array>(
1460 env,
1461 [&]() {
1462 auto containerSize = static_cast<std::size_t>(
1463 std::distance(std::begin(inputContainer), std::end(inputContainer)));
1464 auto array = Napi::Array::New(env, containerSize);
1465 std::size_t i = 0;
1466 for (auto &element : inputContainer) {
1467 array.Set(i, ValueWrapper(transFunc(forwardContainerElement<InputContainer>(element))).mapToValue(env));
1468 ++i;
1469 }
1470 return array;
1471 });
1472}
1473
1474template<typename InputContainer>
1475Array makeArray(napi_env env, InputContainer &&inputContainer)
1476{
1477 return makeArray(
1478 env, std::forward<InputContainer>(inputContainer),
1479 [](auto &&element) -> decltype(auto) {
1480 return std::forward<decltype(element)>(element);
1481 });
1482}
1483
1484template<typename Result, typename F>
1485Result runEscapingHandleScope(napi_env env, F &&func)
1486{
1487 return details_qnapi_p_h::runEscapingHandleScopeImpl<Result>(env, std::forward<F>(func));
1488}
1489
1490inline std::string toJsonString(const Napi::Value &value)
1491{
1492 std::string jsonString;
1493 try {
1494 Napi::HandleScope stringifyScope(value.Env());
1495 jsonString = details_qnapi_p_h::callMethod<String>(value.Env().Global(), "JSON.stringify", {value});
1496 } catch (...) {
1497 jsonString = "<stringify-error>";
1498 }
1499 return jsonString;
1500}
1501
1502}
1503
1504QT_END_NAMESPACE
1505
1506#endif // QNAPI_P_H
void fill(const ValueWrapper &value)
Definition qnapi_p.h:897
Array & operator=(const Napi::Array &other)
Definition qnapi_p.h:891
static Array New(napi_env env, std::size_t length=0)
Definition qnapi_p.h:879
Array(const Napi::Array &other)
Definition qnapi_p.h:886
Arg getFirstArg(const std::string &funcName) const
Definition qnapi_p.h:1266
CallbackInfo(const Napi::CallbackInfo &cbInfo)
Definition qnapi_p.h:1243
void getLeadingArgs(const std::string &funcName, Args &...args) const
Definition qnapi_p.h:1259
CallbackInfo(const CallbackInfo &other)=delete
CallbackInfo & operator=(const CallbackInfo &other)=delete
std::size_t Length() const
Definition qnapi_p.h:1253
Napi::Env Env() const
Definition qnapi_p.h:1248
ExtendedCallbackFuncWrapper(Func &&callbackFunc, std::enable_if_t< std::is_void< std::invoke_result_t< Func, const Napi::CallbackInfo &, ExtraArgs... > >::value, char * >=nullptr)
Definition qnapi_p.h:821
std::function< Napi::Value(const Napi::CallbackInfo &, ExtraArgs...)> & callbackFunc()
Definition qnapi_p.h:869
ExtendedCallbackFuncWrapper(Func &&callbackFunc, std::enable_if_t< std::is_base_of< Napi::Value, std::invoke_result_t< Func, const Napi::CallbackInfo &, ExtraArgs... > >::value, short * >=nullptr)
Definition qnapi_p.h:834
ExtendedCallbackFuncWrapper(Func &&callbackFunc, std::enable_if_t< std::is_base_of< Napi::Value, std::invoke_result_t< Func, ExtraArgs... > >::value, long * >=nullptr)
Definition qnapi_p.h:858
QNapi::Promise evalToPromiseOrRejectOnThrow(const std::string &expr, const std::vector< ValueWrapper > &exprArgs={}) const
Definition qnapi_p.h:952
std::vector< std::string > getFilteredStringKeys(napi_key_collection_mode keyMode, napi_key_filter keyFilter) const
Definition qnapi_p.h:993
Object(const Napi::Object &other)
Definition object.cpp:12
T eval(const std::string &expr, const std::vector< ValueWrapper > &exprArgs={}) const
Definition qnapi_p.h:941
void set(const std::vector< std::pair< std::string, ValueWrapper > > &namedValues)
Definition qnapi_p.h:980
void set(const std::string &name, const ValueWrapper &value)
Definition qnapi_p.h:968
Q_DECL_DEPRECATED_X("Use eval() with a methodName() or methodName(*) expression instead.") Result call(const std
Definition qnapi_p.h:146
T get(const std::string &expr) const
Definition qnapi_p.h:914
static Object New(napi_env env)
Definition qnapi_p.h:874
Object & operator=(const Napi::Object &other)
Definition qnapi_p.h:907
PromiseWithContext onFinallyWithContext(ExtendedCallbackFuncWrapper< Context & > &&onFinallyFunc)
Definition qnapi_p.h:1107
PromiseWithContext onCatchWithContext(ExtendedCallbackFuncWrapper< Context & > &&onRejectedFunc)
Definition qnapi_p.h:1095
PromiseWithContext(const Promise &promise, std::shared_ptr< Context > context)
Definition qnapi_p.h:1061
PromiseWithContext onThenWithContext(ExtendedCallbackFuncWrapper< Context & > &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc)
Definition qnapi_p.h:1080
PromiseWithContext onThenWithContext(ExtendedCallbackFuncWrapper< Context & > &&onFulfilledFunc)
Definition qnapi_p.h:1068
Promise onThen(CallbackFuncWrapper &&onFulfilledFunc)
Definition qnapi_p.h:1022
Promise onFinally(CallbackFuncWrapper &&onFinallyFunc)
Definition qnapi_p.h:1040
Promise(const Napi::Promise &other)
Definition qnapi_p.h:1011
Promise & operator=(const Napi::Promise &other)
Definition qnapi_p.h:1016
Promise onThen(CallbackFuncWrapper &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc)
Definition qnapi_p.h:1028
Promise onCatch(CallbackFuncWrapper &&onRejectedFunc)
Definition qnapi_p.h:1034
PromiseWithContext< Context > withContext(Context &&context)
Definition qnapi_p.h:1054
Promise onThenAndFinally(CallbackFuncWrapper &&onFulfilledFunc, CallbackFuncWrapper &&onRejectedFunc, CallbackFuncWrapper &&onFinallyFunc)
Definition qnapi_p.h:1046
QNapi::Promise evalToPromiseOrRejectOnThrow(const std::string &expr, const std::vector< ValueWrapper > &exprArgs={}) const
Definition qnapi_p.h:1188
static Reference< Object > makePersistentFrom(const Object &value)
Definition qnapi_p.h:1220
static Reference< Object > makeEmpty()
Definition qnapi_p.h:1225
void set(const std::string &name, const ValueWrapper &value)
Definition qnapi_p.h:1198
Q_DECL_DEPRECATED_X("Use eval() with a methodName() or methodName(*) expression instead.") Result call(const std
Definition qnapi_p.h:241
Reference< Object > & operator=(Reference< Object > &&other)
Definition qnapi_p.h:1161
void set(const std::vector< std::pair< std::string, ValueWrapper > > &namedValues)
Definition qnapi_p.h:1204
T eval(const std::string &expr, const std::vector< ValueWrapper > &exprArgs={}) const
Definition qnapi_p.h:1179
Reference< Object > & operator=(Napi::Reference< Object > &&other)
Definition qnapi_p.h:1172
Reference< Object > & operator=(const Reference< Object > &other)=delete
Reference(Napi::Reference< Object > &&other)
Definition qnapi_p.h:1167
Reference(const Reference< Object > &other)=delete
Reference(Reference< Object > &&other)
Definition qnapi_p.h:1156
static Reference< T > makeEmpty()
Definition qnapi_p.h:1238
static Reference< T > makePersistentFrom(const T &value)
Definition qnapi_p.h:1145
Reference< T > & operator=(Reference< T > &&other)
Definition qnapi_p.h:1125
Reference(Reference< T > &&other)
Definition qnapi_p.h:1119
static Reference< T > makeEmpty()
Definition qnapi_p.h:1151
Reference(Napi::Reference< T > &&other)
Definition qnapi_p.h:1132
Reference(const Reference< T > &other)=delete
Reference< T > & operator=(const Reference< T > &other)=delete
Reference< T > & operator=(Napi::Reference< T > &&other)
Definition qnapi_p.h:1138
Napi::Value mapToValue(napi_env env) const
Definition qnapi_p.h:814
ValueWrapper(T &&inputValue)
Definition qnapi_p.h:809
Result callMethod(const Napi::Object &obj, const std::string &methodName, const std::vector< ValueWrapper > &args)
Definition qnapi_p.h:738
std::enable_if_t< std::is_same< T, Napi::Value >::value, bool > valueTypeMatchesImpl(const Napi::Value &)
Definition qnapi_p.h:507
constexpr bool isCallbackFuncType()
Definition qnapi_p.h:479
std::enable_if_t< std::is_base_of< Napi::Value, T >::value, T > getOptionalPropOrEmptyImpl(const Napi::Object &optObj, const Napi::Name &propName, const std::string &objDesc)
Definition qnapi_p.h:778
constexpr decltype(auto) forwardContainerElement(Element &element) noexcept
Definition qnapi_p.h:800
void getLeadingArgsImpl(const std::string &funcName, const Napi::CallbackInfo &cbInfo, std::tuple< Args... > args, std::index_sequence< Is... >)
Definition qnapi_p.h:760
std::string getArrayElementValueTypeString(const Napi::Array &arrayValue)
Definition qnapi_p.h:562
std::enable_if_t< isCallbackFuncType< T >(), std::function< Napi::Value(napi_env)> > makeValueFactory(T &&inputValue)
Definition qnapi_p.h:485
std::string getValueTypeStringImpl(const Napi::Value &value)
Definition qnapi_p.h:520
Result runEscapingHandleScopeImpl(napi_env env, F &&func)
Definition qnapi_p.h:614
std::pair< Napi::Object, T > evalWithContextImpl(Napi::Object obj, const std::string &expr, const std::vector< napi_value > &exprArgs={})
Definition qnapi_p.h:641
void getArgImpl(const std::string &funcName, const Napi::CallbackInfo &cbInfo, Arg &arg, std::size_t argIndex)
Definition qnapi_p.h:748
Napi::Error makeLoggedExceptionImpl(napi_env env, const std::string &msg)
Definition qnapi_p.h:500
Napi::Value callMethodWithValueResultImpl(const Napi::Object &obj, const std::string &methodName, const std::vector< napi_value > &args)
Definition qnapi_p.h:704
Result callMethodImpl(const Napi::Object &obj, const std::string &methodName, const std::vector< napi_value > &args)
Definition qnapi_p.h:726
std::vector< napi_value > expandEvalCallArgs(napi_env env, const std::string &callArgsSubExpr, const std::vector< napi_value > &exprArgs)
Definition qnapi_p.h:625
std::enable_if_t< std::is_same< T, Napi::Value >::value, T > checkedCastImpl(const Napi::Value &value, ValueDescriptionSupplier &&)
Definition qnapi_p.h:588
Array makeArray(napi_env env, std::initializer_list< ValueWrapper > values={})
Definition qnapi_p.h:1449
Napi::Error makeLoggedException(napi_env env, const std::string &msg)
Definition qnapi_p.h:1290
std::string getValueTypeString(const Napi::Value &value)
Definition qnapi_p.h:1321
Napi::Value getPropOrUndefined(const Napi::Reference< T > &objRef, const std::string &propName)
Definition qnapi_p.h:1413
OutputContainer getFilteredArrayElements(const Napi::Array &inputArray, TransFilterFunc &&transFilterFunc)
Definition qnapi_p.h:1364
Object makeObject(napi_env env, const std::vector< std::pair< std::string, ValueWrapper > > &namedValues={})
Definition qnapi_p.h:1442
std::enable_if_t< std::is_base_of< Napi::Value, T >::value, T > getOptionalPropOrEmpty(const Napi::Object &optObj, const std::string &propName, const std::string &objDesc={})
Definition qnapi_p.h:1427
T checkedCast(const Napi::Value &value)
Definition qnapi_p.h:1334
OutputContainer getArrayElements(const Napi::Array &inputArray, TransFunc &&transFunc)
Definition qnapi_p.h:1344
Array makeArray(napi_env env, InputContainer &&inputContainer)
Definition qnapi_p.h:1475
Array makeArray(napi_env env, InputContainer &&inputContainer, TransFunc &&transFunc)
Definition qnapi_p.h:1455
std::vector< napi_value > unwrapValues(napi_env env, const std::vector< ValueWrapper > &wrappedValues)
Definition qnapi_p.h:1278
bool valueTypeMatches(const Napi::Value &value)
Definition qnapi_p.h:1296
bool arrayElementTypesMatch(const Napi::Value &value)
Definition qnapi_p.h:1302
OutputContainer getArrayElements(const Napi::Array &inputArray)
Definition qnapi_p.h:1354
Object makeNewInstance(const Napi::Object &baseObj, const std::string &typePath, const std::vector< ValueWrapper > &args={})
Definition qnapi_p.h:1392
T checkedCast(const Napi::Value &value, ValueDescriptionSupplier &&valueDescSupplier)
Definition qnapi_p.h:1327
Result runEscapingHandleScope(napi_env env, F &&func)
Definition qnapi_p.h:1485
ExtendedCallbackFuncWrapper<> CallbackFuncWrapper
Definition qnapi_p.h:58
std::string toJsonString(const Napi::Value &value)
Definition qnapi_p.h:1490
Napi::Value getPropOrUndefined(const Napi::Value &obj, const std::string &propName)
Definition qnapi_p.h:1397
Object makeNewInstance(const Napi::Function &type, const std::vector< ValueWrapper > &args={})
Definition qnapi_p.h:1387