Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
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
4#ifndef QJSENGINE_H
5#define QJSENGINE_H
6
7#include <QtCore/qmetatype.h>
8
9#include <QtCore/qvariant.h>
10#include <QtCore/qsharedpointer.h>
11#include <QtCore/qobject.h>
12#include <QtCore/qtimezone.h>
13#include <QtQml/qjsvalue.h>
14#include <QtQml/qjsmanagedvalue.h>
15#include <QtQml/qqmldebug.h>
16
18
19
20template <typename T>
21inline T qjsvalue_cast(const QJSValue &);
22
24class Q_QML_EXPORT QJSEngine
25 : public QObject
26{
28 Q_PROPERTY(QString uiLanguage READ uiLanguage WRITE setUiLanguage NOTIFY uiLanguageChanged)
29public:
30 QJSEngine();
31 explicit QJSEngine(QObject *parent);
32 ~QJSEngine() override;
33
34 QJSValue globalObject() const;
35
36 QJSValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1, QStringList *exceptionStackTrace = nullptr);
37
38 QJSValue importModule(const QString &fileName);
39 bool registerModule(const QString &moduleName, const QJSValue &value);
40
41 QJSValue newObject();
42 QJSValue newSymbol(const QString &name);
43 QJSValue newArray(uint length = 0);
44
45 QJSValue newQObject(QObject *object);
46
47 QJSValue newQMetaObject(const QMetaObject* metaObject);
48
49 template <typename T>
51 {
52 return newQMetaObject(&T::staticMetaObject);
53 }
54
55 QJSValue newErrorObject(QJSValue::ErrorType errorType, const QString &message = QString());
56
57 template <typename T>
58 inline QJSValue toScriptValue(const T &value)
59 {
60 return create(QMetaType::fromType<T>(), &value);
61 }
62
63 template <typename T>
65 {
66 return createManaged(QMetaType::fromType<T>(), &value);
67 }
68
69 template <typename T>
71 {
72 // In the common case that the argument fits into QJSPrimitiveValue, use it.
73 if constexpr (std::disjunction_v<
74 std::is_same<T, int>,
75 std::is_same<T, bool>,
76 std::is_same<T, double>,
77 std::is_same<T, QString>>) {
79 } else {
80 return createPrimitive(QMetaType::fromType<T>(), &value);
81 }
82 }
83
84 template <typename T>
86 {
87 return qjsvalue_cast<T>(value);
88 }
89
90 template <typename T>
92 {
93 return qjsvalue_cast<T>(value);
94 }
95
96 template <typename T>
98 {
99 if constexpr (std::is_same_v<T, int>)
100 return value.toInteger();
101 if constexpr (std::is_same_v<T, bool>)
102 return value.toBoolean();
103 if constexpr (std::is_same_v<T, double>)
104 return value.toDouble();
105 if constexpr (std::is_same_v<T, QString>)
106 return value.toString();
107 if constexpr (std::is_same_v<T, QVariant>)
108 return value.toVariant();
109 if constexpr (std::is_pointer_v<T>)
110 return nullptr;
111 return qjsvalue_cast<T>(value);
112 }
113
114 template <typename T>
115 inline T fromVariant(const QVariant &value)
116 {
117 if constexpr (std::is_same_v<T, QVariant>)
118 return value;
119
120 const QMetaType sourceType = value.metaType();
121 const QMetaType targetType = QMetaType::fromType<T>();
122 if (sourceType == targetType)
123 return *reinterpret_cast<const T *>(value.constData());
124
125 if constexpr (std::is_same_v<T,std::remove_const_t<std::remove_pointer_t<T>> const *>) {
126 using nonConstT = std::remove_const_t<std::remove_pointer_t<T>> *;
127 const QMetaType nonConstTargetType = QMetaType::fromType<nonConstT>();
128 if (value.metaType() == nonConstTargetType)
129 return *reinterpret_cast<const nonConstT *>(value.constData());
130 }
131
132 if constexpr (std::is_same_v<T, QJSValue>)
133 return toScriptValue(value);
134
135 if constexpr (std::is_same_v<T, QJSManagedValue>)
136 return toManagedValue(value);
137
138 if constexpr (std::is_same_v<T, QJSPrimitiveValue>)
139 return toPrimitiveValue(value);
140
141 if constexpr (std::is_same_v<T, QString>) {
142 if (sourceType.flags() & QMetaType::PointerToQObject) {
143 return convertQObjectToString(
144 *reinterpret_cast<QObject *const *>(value.constData()));
145 }
146 }
147
148 if constexpr (std::is_same_v<QObject, std::remove_const_t<std::remove_pointer_t<T>>>) {
149 if (sourceType.flags() & QMetaType::PointerToQObject) {
150 return *static_cast<QObject *const *>(value.constData());
151
152 // We should not access source->metaObject() here since that may trigger some
153 // rather involved code. convertVariant() can do this using property caches.
154 }
155 }
156
157 if (sourceType == QMetaType::fromType<QJSValue>())
158 return fromScriptValue<T>(*reinterpret_cast<const QJSValue *>(value.constData()));
159
160 if (sourceType == QMetaType::fromType<QJSManagedValue>()) {
161 return fromManagedValue<T>(
162 *reinterpret_cast<const QJSManagedValue *>(value.constData()));
163 }
164
165 if (sourceType == QMetaType::fromType<QJSPrimitiveValue>()) {
166 return fromPrimitiveValue<T>(
167 *reinterpret_cast<const QJSPrimitiveValue *>(value.constData()));
168 }
169
170 {
171 T t{};
172 if (value.metaType() == QMetaType::fromType<QString>()) {
173 if (convertString(value.toString(), targetType, &t))
174 return t;
175 } else if (convertVariant(value, targetType, &t)) {
176 return t;
177 }
178
179 QMetaType::convert(value.metaType(), value.constData(), targetType, &t);
180 return t;
181 }
182 }
183
184 template<typename From, typename To>
185 inline To coerceValue(const From &from)
186 {
187 if constexpr (std::is_base_of_v<To, From>)
188 return from;
189
190 if constexpr (std::is_same_v<To, QJSValue>)
191 return toScriptValue(from);
192
193 if constexpr (std::is_same_v<From, QJSValue>)
194 return fromScriptValue<To>(from);
195
196 if constexpr (std::is_same_v<To, QJSManagedValue>)
197 return toManagedValue(from);
198
199 if constexpr (std::is_same_v<From, QJSManagedValue>)
200 return fromManagedValue<To>(from);
201
202 if constexpr (std::is_same_v<To, QJSPrimitiveValue>)
203 return toPrimitiveValue(from);
204
205 if constexpr (std::is_same_v<From, QJSPrimitiveValue>)
206 return fromPrimitiveValue<To>(from);
207
208 if constexpr (std::is_same_v<From, QVariant>)
209 return fromVariant<To>(from);
210
211 if constexpr (std::is_same_v<To, QVariant>)
212 return QVariant::fromValue(from);
213
214 if constexpr (std::is_same_v<To, QString>) {
215 if constexpr (std::is_base_of_v<QObject, std::remove_const_t<std::remove_pointer_t<From>>>)
216 return convertQObjectToString(from);
217 }
218
219 if constexpr (std::is_same_v<From, QDateTime>) {
220 if constexpr (std::is_same_v<To, QDate>)
221 return convertDateTimeToDate(from.toLocalTime());
222 if constexpr (std::is_same_v<To, QTime>)
223 return from.toLocalTime().time();
224 if constexpr (std::is_same_v<To, QString>)
225 return convertDateTimeToString(from.toLocalTime());
226 if constexpr (std::is_same_v<To, double>)
227 return convertDateTimeToNumber(from.toLocalTime());
228 }
229
230 if constexpr (std::is_same_v<From, QDate>) {
231 if constexpr (std::is_same_v<To, QDateTime>)
232 return from.startOfDay(QTimeZone::UTC);
233 if constexpr (std::is_same_v<To, QTime>) {
234 // This is the current time zone offset, for better or worse
235 return coerceValue<QDateTime, QTime>(coerceValue<QDate, QDateTime>(from));
236 }
237 if constexpr (std::is_same_v<To, QString>)
238 return convertDateTimeToString(coerceValue<QDate, QDateTime>(from));
239 if constexpr (std::is_same_v<To, double>)
240 return convertDateTimeToNumber(coerceValue<QDate, QDateTime>(from));
241 }
242
243 if constexpr (std::is_same_v<From, QTime>) {
244 if constexpr (std::is_same_v<To, QDate>) {
245 // Yes. April Fools' 1971. See qv4dateobject.cpp.
246 return from.isValid() ? QDate(1971, 4, 1) : QDate();
247 }
248
249 if constexpr (std::is_same_v<To, QDateTime>)
250 return QDateTime(coerceValue<QTime, QDate>(from), from, QTimeZone::LocalTime);
251 if constexpr (std::is_same_v<To, QString>)
252 return convertDateTimeToString(coerceValue<QTime, QDateTime>(from));
253 if constexpr (std::is_same_v<To, double>)
254 return convertDateTimeToNumber(coerceValue<QTime, QDateTime>(from));
255 }
256
257 if constexpr (std::is_same_v<To, std::remove_const_t<std::remove_pointer_t<To>> const *>) {
258 using nonConstTo = std::remove_const_t<std::remove_pointer_t<To>> *;
259 if constexpr (std::is_same_v<From, nonConstTo>)
260 return from;
261 }
262
263 {
264 const QMetaType sourceType = QMetaType::fromType<From>();
265 const QMetaType targetType = QMetaType::fromType<To>();
266 To to{};
267 if constexpr (std::is_same_v<From, QString>) {
268 if (convertString(from, targetType, &to))
269 return to;
270 } else if (convertMetaType(sourceType, &from, targetType, &to)) {
271 return to;
272 }
273
274 QMetaType::convert(sourceType, &from, targetType, &to);
275 return to;
276 }
277 }
278
279 void collectGarbage();
280
281 enum ObjectOwnership { CppOwnership, JavaScriptOwnership };
282 static void setObjectOwnership(QObject *, ObjectOwnership);
283 static ObjectOwnership objectOwnership(QObject *);
284
286 TranslationExtension = 0x1,
287 ConsoleExtension = 0x2,
288 GarbageCollectionExtension = 0x4,
289 AllExtensions = 0xffffffff
290 };
291 Q_DECLARE_FLAGS(Extensions, Extension)
292
293 void installExtensions(Extensions extensions, const QJSValue &object = QJSValue());
294
295 void setInterrupted(bool interrupted);
296 bool isInterrupted() const;
297
298 QV4::ExecutionEngine *handle() const { return m_v4Engine; }
299
300 void throwError(const QString &message);
301 void throwError(QJSValue::ErrorType errorType, const QString &message = QString());
302 void throwError(const QJSValue &error);
303 bool hasError() const;
304 QJSValue catchError();
305
306 QString uiLanguage() const;
307 void setUiLanguage(const QString &language);
308
311
312private:
313 QJSPrimitiveValue createPrimitive(QMetaType type, const void *ptr);
314 QJSManagedValue createManaged(QMetaType type, const void *ptr);
315 QJSValue create(QMetaType type, const void *ptr);
316#if QT_QML_REMOVED_SINCE(6, 5)
317 QJSValue create(int id, const void *ptr); // only there for BC reasons
318#endif
319
320 static bool convertPrimitive(const QJSPrimitiveValue &value, QMetaType type, void *ptr);
321 static bool convertManaged(const QJSManagedValue &value, int type, void *ptr);
322 static bool convertManaged(const QJSManagedValue &value, QMetaType type, void *ptr);
323#if QT_QML_REMOVED_SINCE(6, 5)
324 static bool convertV2(const QJSValue &value, int type, void *ptr); // only there for BC reasons
325#endif
326 static bool convertV2(const QJSValue &value, QMetaType metaType, void *ptr);
327 static bool convertString(const QString &string, QMetaType metaType, void *ptr);
328
329 bool convertVariant(const QVariant &value, QMetaType metaType, void *ptr);
330 bool convertMetaType(QMetaType fromType, const void *from, QMetaType toType, void *to);
331
332 QString convertQObjectToString(QObject *object);
333 QString convertDateTimeToString(const QDateTime &dateTime);
334 double convertDateTimeToNumber(const QDateTime &dateTime);
335 static QDate convertDateTimeToDate(const QDateTime &dateTime);
336
337 template<typename T>
338 friend inline T qjsvalue_cast(const QJSValue &);
339
340 template<typename T>
341 friend inline T qjsvalue_cast(const QJSManagedValue &);
342
343 template<typename T>
344 friend inline T qjsvalue_cast(const QJSPrimitiveValue &);
345
346protected:
347 QJSEngine(QJSEnginePrivate &dd, QObject *parent = nullptr);
348
349private:
350 QV4::ExecutionEngine *m_v4Engine;
351 Q_DISABLE_COPY(QJSEngine)
352 Q_DECLARE_PRIVATE(QJSEngine)
353};
354
355Q_DECLARE_OPERATORS_FOR_FLAGS(QJSEngine::Extensions)
356
357template<typename T>
359{
360 if (T t; QJSEngine::convertV2(value, QMetaType::fromType<T>(), &t))
361 return t;
362 return qvariant_cast<T>(value.toVariant());
363}
364
365template<typename T>
367{
368 if (T t; QJSEngine::convertManaged(value, QMetaType::fromType<T>(), &t))
369 return t;
370
371 return qvariant_cast<T>(value.toVariant());
372}
373
374template<typename T>
376{
377 if (T t; QJSEngine::convertPrimitive(value, QMetaType::fromType<T>(), &t))
378 return t;
379
380 return qvariant_cast<T>(value.toVariant());
381}
382
383template <>
385{
386 return value.toVariant();
387}
388
389template <>
391{
392 return value.toVariant();
393}
394
395template <>
397{
398 return value.toVariant();
399}
400
401Q_QML_EXPORT QJSEngine *qjsEngine(const QObject *);
402
404
405#endif // QJSENGINE_H
\inmodule QtCore\reentrant
Definition qdatetime.h:283
\inmodule QtCore \reentrant
Definition qdatetime.h:29
The QJSEngine class provides an environment for evaluating JavaScript code.
Definition qjsengine.h:26
T fromScriptValue(const QJSValue &value)
Returns the given value converted to the template type {T}.
Definition qjsengine.h:85
T fromManagedValue(const QJSManagedValue &value)
Returns the given value converted to the template type {T}.
Definition qjsengine.h:91
QV4::ExecutionEngine * handle() const
Definition qjsengine.h:298
QJSManagedValue toManagedValue(const T &value)
Creates a QJSManagedValue with the given value.
Definition qjsengine.h:64
T fromVariant(const QVariant &value)
Returns the given value converted to the template type {T}.
Definition qjsengine.h:115
To coerceValue(const From &from)
Returns the given from converted to the template type {To}.
Definition qjsengine.h:185
QJSValue toScriptValue(const T &value)
Creates a QJSValue with the given value.
Definition qjsengine.h:58
void uiLanguageChanged()
T fromPrimitiveValue(const QJSPrimitiveValue &value)
Returns the given value converted to the template type {T}.
Definition qjsengine.h:97
Extension
This enum is used to specify extensions to be installed via \l installExtensions().
Definition qjsengine.h:285
QJSValue newQMetaObject()
Definition qjsengine.h:50
ObjectOwnership
ObjectOwnership controls whether or not the JavaScript memory manager automatically destroys the QObj...
Definition qjsengine.h:281
QJSPrimitiveValue toPrimitiveValue(const T &value)
Creates a QJSPrimitiveValue with the given value.
Definition qjsengine.h:70
\inmodule QtQml
The QJSPrimitiveValue class operates on primitive types in JavaScript semantics.
The QJSValue class acts as a container for Qt/JavaScript data types.
Definition qjsvalue.h:31
\inmodule QtCore
Definition qmetatype.h:341
constexpr TypeFlags flags() const
Definition qmetatype.h:2658
@ PointerToQObject
Definition qmetatype.h:406
static bool convert(QMetaType fromType, const void *from, QMetaType toType, void *to)
Converts the object at from from fromType to the preallocated space at to typed toType.
\inmodule QtCore
Definition qobject.h:103
\inmodule QtCore
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
\inmodule QtCore
Definition qvariant.h:65
static auto fromValue(T &&value) noexcept(std::is_nothrow_copy_constructible_v< T > &&Private::CanUseInternalSpace< T >) -> std::enable_if_t< std::conjunction_v< std::is_copy_constructible< T >, std::is_destructible< T > >, QVariant >
Definition qvariant.h:536
Combined button and popup list for selecting options.
DBusConnection const char DBusError * error
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_DECLARE_FLAGS(Flags, Enum)
Definition qflags.h:174
#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags)
Definition qflags.h:194
QVariant qjsvalue_cast< QVariant >(const QJSValue &value)
Definition qjsengine.h:384
QT_BEGIN_NAMESPACE T qjsvalue_cast(const QJSValue &)
Definition qjsengine.h:358
Q_QML_EXPORT QJSEngine * qjsEngine(const QObject *)
static ControlElement< T > * ptr(QWidget *widget)
GLenum GLuint GLenum GLsizei length
GLenum type
GLuint program
GLuint GLsizei const GLchar * message
GLuint name
GLdouble GLdouble t
Definition qopenglext.h:243
#define Q_PROPERTY(...)
#define Q_OBJECT
#define Q_SIGNALS
unsigned int uint
Definition qtypes.h:34
obj metaObject() -> className()
QDateTime dateTime
[12]
view create()
engine globalObject().setProperty("myObject"
engine evaluate("var myObject = new MyObject()")
[8]
\inmodule QtCore