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
qjsengine.h
Go to the documentation of this file.
1// Copyright (C) 2016 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// Qt-Security score:significant
4
5#ifndef QJSENGINE_H
6#define QJSENGINE_H
7
8#include <QtCore/qmetatype.h>
9
10#include <QtCore/qvariant.h>
11#include <QtCore/qsharedpointer.h>
12#include <QtCore/qobject.h>
13#include <QtCore/qtimezone.h>
14#include <QtQml/qjsvalue.h>
15#include <QtQml/qjsmanagedvalue.h>
16#include <QtQml/qqmldebug.h>
17
18QT_BEGIN_NAMESPACE
19
20
21template <typename T>
22inline T qjsvalue_cast(const QJSValue &);
23
24class QJSEnginePrivate;
25class Q_QML_EXPORT QJSEngine
26 : public QObject
27{
28 Q_OBJECT
29 Q_PROPERTY(QString uiLanguage READ uiLanguage WRITE setUiLanguage NOTIFY uiLanguageChanged)
30public:
31 QJSEngine();
32 explicit QJSEngine(QObject *parent);
33 ~QJSEngine() override;
34
35 QJSValue globalObject() const;
36
37 QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1, QStringList *exceptionStackTrace = nullptr);
38
39 QJSValue importModule(const QString &fileName);
40 bool registerModule(const QString &moduleName, const QJSValue &value);
41
42 QJSValue newObject();
43 QJSValue newSymbol(const QString &name);
44 QJSValue newArray(uint length = 0);
45
46 QJSValue newQObject(QObject *object);
47
48 QJSValue newQMetaObject(const QMetaObject* metaObject);
49
50 template <typename T>
51 QJSValue newQMetaObject()
52 {
53 return newQMetaObject(&T::staticMetaObject);
54 }
55
56 QJSValue newErrorObject(QJSValue::ErrorType errorType, const QString &message = QString());
57
58 template <typename T>
59 inline QJSValue toScriptValue(const T &value)
60 {
61 return create(QMetaType::fromType<T>(), &value);
62 }
63
64 template <typename T>
65 inline QJSManagedValue toManagedValue(const T &value)
66 {
67 return createManaged(QMetaType::fromType<T>(), &value);
68 }
69
70 template <typename T>
71 inline QJSPrimitiveValue toPrimitiveValue(const T &value)
72 {
73 // In the common case that the argument fits into QJSPrimitiveValue, use it.
74 if constexpr (std::disjunction_v<
75 std::is_same<T, int>,
76 std::is_same<T, bool>,
77 std::is_same<T, double>,
78 std::is_same<T, QString>>) {
79 return QJSPrimitiveValue(value);
80 } else {
81 return createPrimitive(QMetaType::fromType<T>(), &value);
82 }
83 }
84
85 template <typename T>
86 inline T fromScriptValue(const QJSValue &value)
87 {
88 return qjsvalue_cast<T>(value);
89 }
90
91 template <typename T>
92 inline T fromManagedValue(const QJSManagedValue &value)
93 {
94 return qjsvalue_cast<T>(value);
95 }
96
97 template <typename T>
98 inline T fromPrimitiveValue(const QJSPrimitiveValue &value)
99 {
100 if constexpr (std::is_same_v<T, int>)
101 return value.toInteger();
102 if constexpr (std::is_same_v<T, bool>)
103 return value.toBoolean();
104 if constexpr (std::is_same_v<T, double>)
105 return value.toDouble();
106 if constexpr (std::is_same_v<T, QString>)
107 return value.toString();
108 if constexpr (std::is_same_v<T, QVariant>)
109 return value.toVariant();
110 if constexpr (std::is_pointer_v<T>)
111 return nullptr;
112 return qjsvalue_cast<T>(value);
113 }
114
115 template <typename T>
116 inline T fromVariant(const QVariant &value)
117 {
118 // MSVC doesn't like the constexpr chains and complains about "unreachable code"
119 QT_WARNING_PUSH
120 QT_WARNING_DISABLE_MSVC(4702)
121
122 if constexpr (std::is_same_v<T, QVariant>)
123 return value;
124
125 const QMetaType sourceType = value.metaType();
126 const QMetaType targetType = QMetaType::fromType<T>();
127 if (sourceType == targetType)
128 return *reinterpret_cast<const T *>(value.constData());
129
130 if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
131 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
132 const QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
133 if (value.metaType() == nonConstTargetType)
134 return *reinterpret_cast<const nonConstT *>(value.constData());
135 }
136
137 if constexpr (std::is_same_v<T, QJSValue>)
138 return toScriptValue(value);
139
140 if constexpr (std::is_same_v<T, QJSManagedValue>)
141 return toManagedValue(value);
142
143 if constexpr (std::is_same_v<T, QJSPrimitiveValue>)
144 return toPrimitiveValue(value);
145
146 if constexpr (std::is_same_v<T, QString>) {
147 if (sourceType.flags() & QMetaType::PointerToQObject) {
148 return convertQObjectToString(
149 *reinterpret_cast<QObject *const *>(value.constData()));
150 }
151 }
152
153 if constexpr (std::is_same_v<T, double>) {
154 if (sourceType == QMetaType::fromType<int>())
155 return double(*static_cast<const int *>(value.constData()));
156 }
157
158 if constexpr (std::is_same_v<T, int>) {
159 if (sourceType == QMetaType::fromType<double>()) {
160 return QJSNumberCoercion::toInteger(
161 *static_cast<const double *>(value.constData()));
162 }
163 }
164
165 if constexpr (std::is_same_v<QObject, std::remove_const_t<std::remove_pointer_t<T>>>) {
166 if (sourceType.flags() & QMetaType::PointerToQObject) {
167 return *static_cast<QObject *const *>(value.constData());
168
169 // We should not access source->metaObject() here since that may trigger some
170 // rather involved code. convertVariant() can do this using property caches.
171 }
172 }
173
174 if (sourceType == QMetaType::fromType<QJSValue>())
175 return fromScriptValue<T>(*reinterpret_cast<const QJSValue *>(value.constData()));
176
177 if (sourceType == QMetaType::fromType<QJSManagedValue>()) {
178 return fromManagedValue<T>(
179 *reinterpret_cast<const QJSManagedValue *>(value.constData()));
180 }
181
182 if (sourceType == QMetaType::fromType<QJSPrimitiveValue>()) {
183 return fromPrimitiveValue<T>(
184 *reinterpret_cast<const QJSPrimitiveValue *>(value.constData()));
185 }
186
187 return [&] {
188 T t{};
189 if (value.metaType() == QMetaType::fromType<QString>()) {
190 if (convertString(value.toString(), targetType, &t))
191 return t;
192 } else if (convertVariant(value, targetType, &t)) {
193 return t;
194 }
195
196 QMetaType::convert(value.metaType(), value.constData(), targetType, &t);
197 return t;
198 }();
199
200 QT_WARNING_POP
201 }
202
203 template<typename From, typename To>
204 inline To coerceValue(const From &from)
205 {
206 if constexpr (std::is_base_of_v<To, From>)
207 return from;
208
209 if constexpr (std::is_same_v<To, QJSValue>)
210 return toScriptValue(from);
211
212 if constexpr (std::is_same_v<From, QJSValue>)
213 return fromScriptValue<To>(from);
214
215 if constexpr (std::is_same_v<To, QJSManagedValue>)
216 return toManagedValue(from);
217
218 if constexpr (std::is_same_v<From, QJSManagedValue>)
219 return fromManagedValue<To>(from);
220
221 if constexpr (std::is_same_v<To, QJSPrimitiveValue>)
222 return toPrimitiveValue(from);
223
224 if constexpr (std::is_same_v<From, QJSPrimitiveValue>)
225 return fromPrimitiveValue<To>(from);
226
227 if constexpr (std::is_same_v<From, QVariant>)
228 return fromVariant<To>(from);
229
230 if constexpr (std::is_same_v<To, QVariant>)
231 return QVariant::fromValue(from);
232
233 if constexpr (std::is_same_v<To, QString>) {
234 if constexpr (std::is_base_of_v<QObject, std::remove_const_t<std::remove_pointer_t<From>>>)
235 return convertQObjectToString(from);
236 }
237
238 if constexpr (std::is_same_v<From, QDateTime>) {
239 if constexpr (std::is_same_v<To, QDate>)
240 return convertDateTimeToDate(from.toLocalTime());
241 if constexpr (std::is_same_v<To, QTime>)
242 return from.toLocalTime().time();
243 if constexpr (std::is_same_v<To, QString>)
244 return convertDateTimeToString(from.toLocalTime());
245 if constexpr (std::is_same_v<To, double>)
246 return convertDateTimeToNumber(from.toLocalTime());
247 }
248
249 if constexpr (std::is_same_v<From, QDate>) {
250 if constexpr (std::is_same_v<To, QDateTime>)
251 return from.startOfDay(QTimeZone::UTC);
252 if constexpr (std::is_same_v<To, QTime>) {
253 // This is the current time zone offset, for better or worse
254 return coerceValue<QDateTime, QTime>(coerceValue<QDate, QDateTime>(from));
255 }
256 if constexpr (std::is_same_v<To, QString>)
257 return convertDateTimeToString(coerceValue<QDate, QDateTime>(from));
258 if constexpr (std::is_same_v<To, double>)
259 return convertDateTimeToNumber(coerceValue<QDate, QDateTime>(from));
260 }
261
262 if constexpr (std::is_same_v<From, QTime>) {
263 if constexpr (std::is_same_v<To, QDate>) {
264 // Yes. April Fools' 1971. See qv4dateobject.cpp.
265 return from.isValid() ? QDate(1971, 4, 1) : QDate();
266 }
267
268 if constexpr (std::is_same_v<To, QDateTime>)
269 return QDateTime(coerceValue<QTime, QDate>(from), from, QTimeZone::LocalTime);
270 if constexpr (std::is_same_v<To, QString>)
271 return convertDateTimeToString(coerceValue<QTime, QDateTime>(from));
272 if constexpr (std::is_same_v<To, double>)
273 return convertDateTimeToNumber(coerceValue<QTime, QDateTime>(from));
274 }
275
276 if constexpr (std::is_same_v<To, std::remove_const_t<std::remove_pointer_t<To>> const *>) {
277 using nonConstTo = std::remove_const_t<std::remove_pointer_t<To>> *;
278 if constexpr (std::is_same_v<From, nonConstTo>)
279 return from;
280 }
281
282 if constexpr (std::is_same_v<To, double>) {
283 if constexpr (std::is_same_v<From, int>)
284 return double(from);
285 }
286
287 if constexpr (std::is_same_v<To, int>) {
288 if constexpr (std::is_same_v<From, double>)
289 return QJSNumberCoercion::toInteger(from);
290 }
291
292 return [&] {
293 const QMetaType sourceType = QMetaType::fromType<From>();
294 const QMetaType targetType = QMetaType::fromType<To>();
295 To to{};
296 if constexpr (std::is_same_v<From, QString>) {
297 if (convertString(from, targetType, &to))
298 return to;
299 } else if (convertMetaType(sourceType, &from, targetType, &to)) {
300 return to;
301 }
302
303 QMetaType::convert(sourceType, &from, targetType, &to);
304 return to;
305 }();
306 }
307
308 void collectGarbage();
309
310 enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
311 static void setObjectOwnership(QObject *, ObjectOwnership);
312 static ObjectOwnership objectOwnership(QObject *);
313
314 enum Extension {
315 TranslationExtension = 0x1,
316 ConsoleExtension = 0x2,
317 GarbageCollectionExtension = 0x4,
318 AllExtensions = 0xffffffff
319 };
320 Q_DECLARE_FLAGS(Extensions, Extension)
321
322 void installExtensions(Extensions extensions, const QJSValue &object = QJSValue());
323
324 void setInterrupted(bool interrupted);
325 bool isInterrupted() const;
326
327 QV4::ExecutionEngine *handle() const { return m_v4Engine; }
328
329 void throwError(const QString &message);
330 void throwError(QJSValue::ErrorType errorType, const QString &message = QString());
331 void throwError(const QJSValue &error);
332 bool hasError() const;
333 QJSValue catchError();
334
335 QString uiLanguage() const;
336 void setUiLanguage(const QString &language);
337
338Q_SIGNALS:
339 void uiLanguageChanged();
340
341private:
342 QJSPrimitiveValue createPrimitive(QMetaType type, const void *ptr);
343 QJSManagedValue createManaged(QMetaType type, const void *ptr);
344 QJSValue create(QMetaType type, const void *ptr);
345#if QT_QML_REMOVED_SINCE(6, 5)
346 QJSValue create(int id, const void *ptr); // only there for BC reasons
347#endif
348
349 static bool convertPrimitive(const QJSPrimitiveValue &value, QMetaType type, void *ptr);
350 static bool convertManaged(const QJSManagedValue &value, int type, void *ptr);
351 static bool convertManaged(const QJSManagedValue &value, QMetaType type, void *ptr);
352#if QT_QML_REMOVED_SINCE(6, 5)
353 static bool convertV2(const QJSValue &value, int type, void *ptr); // only there for BC reasons
354#endif
355 static bool convertV2(const QJSValue &value, QMetaType metaType, void *ptr);
356 static bool convertString(const QString &string, QMetaType metaType, void *ptr);
357
358 bool convertVariant(const QVariant &value, QMetaType metaType, void *ptr);
359 bool convertMetaType(QMetaType fromType, const void *from, QMetaType toType, void *to);
360
361 QString convertQObjectToString(QObject *object);
362 QString convertDateTimeToString(const QDateTime &dateTime);
363 double convertDateTimeToNumber(const QDateTime &dateTime);
364 static QDate convertDateTimeToDate(const QDateTime &dateTime);
365
366 template<typename T>
367 friend inline T qjsvalue_cast(const QJSValue &);
368
369 template<typename T>
370 friend inline T qjsvalue_cast(const QJSManagedValue &);
371
372 template<typename T>
373 friend inline T qjsvalue_cast(const QJSPrimitiveValue &);
374
375protected:
376 QJSEngine(QJSEnginePrivate &dd, QObject *parent = nullptr);
377
378private:
379 QV4::ExecutionEngine *m_v4Engine;
380 Q_DISABLE_COPY(QJSEngine)
381 Q_DECLARE_PRIVATE(QJSEngine)
382};
383
384Q_DECLARE_OPERATORS_FOR_FLAGS(QJSEngine::Extensions)
385
386template<typename T>
387T qjsvalue_cast(const QJSValue &value)
388{
389 if (T t; QJSEngine::convertV2(value, QMetaType::fromType<T>(), &t))
390 return t;
391 return qvariant_cast<T>(value.toVariant());
392}
393
394template<typename T>
395T qjsvalue_cast(const QJSManagedValue &value)
396{
397 if (T t; QJSEngine::convertManaged(value, QMetaType::fromType<T>(), &t))
398 return t;
399
400 return qvariant_cast<T>(value.toVariant());
401}
402
403template<typename T>
404T qjsvalue_cast(const QJSPrimitiveValue &value)
405{
406 if (T t; QJSEngine::convertPrimitive(value, QMetaType::fromType<T>(), &t))
407 return t;
408
409 return qvariant_cast<T>(value.toVariant());
410}
411
412template <>
413inline QVariant qjsvalue_cast<QVariant>(const QJSValue &value)
414{
415 return value.toVariant();
416}
417
418template <>
419inline QVariant qjsvalue_cast<QVariant>(const QJSManagedValue &value)
420{
421 return value.toVariant();
422}
423
424template <>
425inline QVariant qjsvalue_cast<QVariant>(const QJSPrimitiveValue &value)
426{
427 return value.toVariant();
428}
429
430Q_QML_EXPORT QJSEngine *qjsEngine(const QObject *);
431
432QT_END_NAMESPACE
433
434#endif // QJSENGINE_H
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:27
QJSEngine * qjsEngine(const QObject *object)
T qjsvalue_cast(const QJSManagedValue &value)
Definition qjsengine.h:395