1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2015 The Qt Company Ltd. |
4 | ** Contact: http://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtScript module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QSCRIPTENGINE_H |
41 | #define QSCRIPTENGINE_H |
42 | |
43 | #include <QtCore/qmetatype.h> |
44 | |
45 | #include <QtCore/qvariant.h> |
46 | #include <QtCore/qsharedpointer.h> |
47 | |
48 | #ifndef QT_NO_QOBJECT |
49 | #include <QtCore/qobject.h> |
50 | #else |
51 | #include <QtCore/qobjectdefs.h> |
52 | #endif |
53 | |
54 | #include <QtScript/qscriptvalue.h> |
55 | #include <QtScript/qscriptcontext.h> |
56 | #include <QtScript/qscriptstring.h> |
57 | #include <QtScript/qscriptprogram.h> |
58 | |
59 | QT_BEGIN_NAMESPACE |
60 | |
61 | |
62 | class QDateTime; |
63 | class QScriptClass; |
64 | class QScriptEngineAgent; |
65 | class QScriptEnginePrivate; |
66 | |
67 | #ifndef QT_NO_QOBJECT |
68 | |
69 | template <class T> |
70 | inline QScriptValue qscriptQMetaObjectConstructor(QScriptContext *, QScriptEngine *, T *) |
71 | { |
72 | return QScriptValue(); |
73 | } |
74 | |
75 | #endif // QT_NO_QOBJECT |
76 | |
77 | #ifndef QT_NO_REGEXP |
78 | class QRegExp; |
79 | #endif |
80 | |
81 | template <typename T> |
82 | inline QScriptValue qScriptValueFromValue(QScriptEngine *, const T &); |
83 | |
84 | template <typename T> |
85 | inline T qscriptvalue_cast(const QScriptValue &); |
86 | |
87 | class QScriptSyntaxCheckResultPrivate; |
88 | class Q_SCRIPT_EXPORT QScriptSyntaxCheckResult |
89 | { |
90 | public: |
91 | enum State { |
92 | Error, |
93 | Intermediate, |
94 | Valid |
95 | }; |
96 | |
97 | QScriptSyntaxCheckResult(const QScriptSyntaxCheckResult &other); |
98 | ~QScriptSyntaxCheckResult(); |
99 | |
100 | State state() const; |
101 | int errorLineNumber() const; |
102 | int errorColumnNumber() const; |
103 | QString errorMessage() const; |
104 | |
105 | QScriptSyntaxCheckResult &operator=(const QScriptSyntaxCheckResult &other); |
106 | |
107 | private: |
108 | QScriptSyntaxCheckResult(); |
109 | QScriptSyntaxCheckResult(QScriptSyntaxCheckResultPrivate *d); |
110 | QExplicitlySharedDataPointer<QScriptSyntaxCheckResultPrivate> d_ptr; |
111 | |
112 | Q_DECLARE_PRIVATE(QScriptSyntaxCheckResult) |
113 | friend class QScriptEngine; |
114 | friend class QScriptEnginePrivate; |
115 | }; |
116 | |
117 | class Q_SCRIPT_EXPORT QScriptEngine |
118 | #ifndef QT_NO_QOBJECT |
119 | : public QObject |
120 | #endif |
121 | { |
122 | #ifndef QT_NO_QOBJECT |
123 | Q_OBJECT |
124 | #endif |
125 | public: |
126 | enum ValueOwnership { |
127 | QtOwnership, |
128 | ScriptOwnership, |
129 | AutoOwnership |
130 | }; |
131 | |
132 | enum QObjectWrapOption { |
133 | ExcludeChildObjects = 0x0001, |
134 | ExcludeSuperClassMethods = 0x0002, |
135 | ExcludeSuperClassProperties = 0x0004, |
136 | ExcludeSuperClassContents = 0x0006, |
137 | SkipMethodsInEnumeration = 0x0008, |
138 | ExcludeDeleteLater = 0x0010, |
139 | ExcludeSlots = 0x0020, |
140 | |
141 | AutoCreateDynamicProperties = 0x0100, |
142 | PreferExistingWrapperObject = 0x0200 |
143 | }; |
144 | Q_DECLARE_FLAGS(QObjectWrapOptions, QObjectWrapOption) |
145 | |
146 | QScriptEngine(); |
147 | #ifndef QT_NO_QOBJECT |
148 | explicit QScriptEngine(QObject *parent); |
149 | #endif |
150 | virtual ~QScriptEngine(); |
151 | |
152 | QScriptValue globalObject() const; |
153 | void setGlobalObject(const QScriptValue &object); |
154 | |
155 | QScriptContext *currentContext() const; |
156 | QScriptContext *pushContext(); |
157 | void popContext(); |
158 | |
159 | bool canEvaluate(const QString &program) const; |
160 | static QScriptSyntaxCheckResult checkSyntax(const QString &program); |
161 | |
162 | QScriptValue evaluate(const QString &program, const QString &fileName = QString(), int lineNumber = 1); |
163 | |
164 | QScriptValue evaluate(const QScriptProgram &program); |
165 | |
166 | bool isEvaluating() const; |
167 | void abortEvaluation(const QScriptValue &result = QScriptValue()); |
168 | |
169 | bool hasUncaughtException() const; |
170 | QScriptValue uncaughtException() const; |
171 | int uncaughtExceptionLineNumber() const; |
172 | QStringList uncaughtExceptionBacktrace() const; |
173 | void clearExceptions(); |
174 | |
175 | QScriptValue nullValue(); |
176 | QScriptValue undefinedValue(); |
177 | |
178 | typedef QScriptValue (*FunctionSignature)(QScriptContext *, QScriptEngine *); |
179 | typedef QScriptValue (*FunctionWithArgSignature)(QScriptContext *, QScriptEngine *, void *); |
180 | |
181 | QScriptValue newFunction(FunctionSignature signature, int length = 0); |
182 | QScriptValue newFunction(FunctionSignature signature, const QScriptValue &prototype, int length = 0); |
183 | |
184 | QScriptValue newFunction(FunctionWithArgSignature signature, void *arg); |
185 | |
186 | QScriptValue newVariant(const QVariant &value); |
187 | QScriptValue newVariant(const QScriptValue &object, const QVariant &value); |
188 | |
189 | #ifndef QT_NO_REGEXP |
190 | QScriptValue newRegExp(const QRegExp ®exp); |
191 | #endif |
192 | |
193 | QScriptValue newObject(); |
194 | QScriptValue newObject(QScriptClass *scriptClass, const QScriptValue &data = QScriptValue()); |
195 | QScriptValue newArray(uint length = 0); |
196 | QScriptValue newRegExp(const QString &pattern, const QString &flags); |
197 | QScriptValue newDate(qsreal value); |
198 | QScriptValue newDate(const QDateTime &value); |
199 | QScriptValue newActivationObject(); |
200 | |
201 | #ifndef QT_NO_QOBJECT |
202 | QScriptValue newQObject(QObject *object, ValueOwnership ownership = QtOwnership, |
203 | const QObjectWrapOptions &options = QObjectWrapOptions()); |
204 | QScriptValue newQObject(const QScriptValue &scriptObject, QObject *qtObject, |
205 | ValueOwnership ownership = QtOwnership, |
206 | const QObjectWrapOptions &options = QObjectWrapOptions()); |
207 | |
208 | QScriptValue newQMetaObject(const QMetaObject *metaObject, const QScriptValue &ctor = QScriptValue()); |
209 | |
210 | template <class T> QScriptValue scriptValueFromQMetaObject(); |
211 | |
212 | #endif // QT_NO_QOBJECT |
213 | |
214 | |
215 | |
216 | QScriptValue defaultPrototype(int metaTypeId) const; |
217 | void setDefaultPrototype(int metaTypeId, const QScriptValue &prototype); |
218 | |
219 | |
220 | typedef QScriptValue (*MarshalFunction)(QScriptEngine *, const void *); |
221 | typedef void (*DemarshalFunction)(const QScriptValue &, void *); |
222 | |
223 | |
224 | |
225 | template <typename T> |
226 | inline QScriptValue toScriptValue(const T &value) |
227 | { |
228 | return qScriptValueFromValue(this, value); |
229 | } |
230 | template <typename T> |
231 | inline T fromScriptValue(const QScriptValue &value) |
232 | { |
233 | return qscriptvalue_cast<T>(value); |
234 | } |
235 | |
236 | void installTranslatorFunctions(const QScriptValue &object = QScriptValue()); |
237 | |
238 | QScriptValue importExtension(const QString &extension); |
239 | QStringList availableExtensions() const; |
240 | QStringList importedExtensions() const; |
241 | |
242 | void collectGarbage(); |
243 | void reportAdditionalMemoryCost(int size); |
244 | |
245 | void setProcessEventsInterval(int interval); |
246 | int processEventsInterval() const; |
247 | |
248 | void setAgent(QScriptEngineAgent *agent); |
249 | QScriptEngineAgent *agent() const; |
250 | |
251 | QScriptString toStringHandle(const QString &str); |
252 | QScriptValue toObject(const QScriptValue &value); |
253 | |
254 | QScriptValue objectById(qint64 id) const; |
255 | |
256 | #ifndef QT_NO_QOBJECT |
257 | Q_SIGNALS: |
258 | void signalHandlerException(const QScriptValue &exception); |
259 | #endif |
260 | |
261 | private: |
262 | QScriptValue create(int type, const void *ptr); |
263 | |
264 | bool convert(const QScriptValue &value, int type, void *ptr); |
265 | static bool convertV2(const QScriptValue &value, int type, void *ptr); |
266 | |
267 | void registerCustomType(int type, MarshalFunction mf, DemarshalFunction df, |
268 | const QScriptValue &prototype); |
269 | |
270 | friend inline void qScriptRegisterMetaType_helper(QScriptEngine *, |
271 | int, MarshalFunction, DemarshalFunction, const QScriptValue &); |
272 | |
273 | friend inline QScriptValue qScriptValueFromValue_helper(QScriptEngine *, int, const void *); |
274 | |
275 | friend inline bool qscriptvalue_cast_helper(const QScriptValue &, int, void *); |
276 | |
277 | protected: |
278 | #ifdef QT_NO_QOBJECT |
279 | QScopedPointer<QScriptEnginePrivate> d_ptr; |
280 | |
281 | QScriptEngine(QScriptEnginePrivate &dd); |
282 | #else |
283 | explicit QScriptEngine(QScriptEnginePrivate &dd, QObject *parent = nullptr); |
284 | #endif |
285 | |
286 | private: |
287 | Q_DECLARE_PRIVATE(QScriptEngine) |
288 | Q_DISABLE_COPY(QScriptEngine) |
289 | #ifndef QT_NO_QOBJECT |
290 | Q_PRIVATE_SLOT(d_func(), void _q_objectDestroyed(QObject *)) |
291 | #endif |
292 | }; |
293 | |
294 | #ifndef QT_NO_QOBJECT |
295 | |
296 | #define Q_SCRIPT_DECLARE_QMETAOBJECT(T, _Arg1) \ |
297 | template<> inline QScriptValue qscriptQMetaObjectConstructor<T>(QScriptContext *ctx, QScriptEngine *eng, T *) \ |
298 | { \ |
299 | _Arg1 arg1 = qscriptvalue_cast<_Arg1> (ctx->argument(0)); \ |
300 | T* t = new T(arg1); \ |
301 | if (ctx->isCalledAsConstructor()) \ |
302 | return eng->newQObject(ctx->thisObject(), t, QScriptEngine::AutoOwnership); \ |
303 | QScriptValue o = eng->newQObject(t, QScriptEngine::AutoOwnership); \ |
304 | o.setPrototype(ctx->callee().property(QString::fromLatin1("prototype"))); \ |
305 | return o; \ |
306 | } |
307 | |
308 | template <class T> QScriptValue QScriptEngine::scriptValueFromQMetaObject() |
309 | { |
310 | typedef QScriptValue(*ConstructPtr)(QScriptContext *, QScriptEngine *, T *); |
311 | ConstructPtr cptr = qscriptQMetaObjectConstructor<T>; |
312 | return newQMetaObject(metaObject: &T::staticMetaObject, |
313 | ctor: newFunction(signature: reinterpret_cast<FunctionWithArgSignature>(cptr), arg: 0)); |
314 | } |
315 | |
316 | #ifdef QT_DEPRECATED |
317 | template <class T> |
318 | inline QT_DEPRECATED QScriptValue qScriptValueFromQMetaObject( |
319 | QScriptEngine *engine |
320 | #ifndef qdoc |
321 | , T * /* dummy */ = 0 |
322 | #endif |
323 | ) |
324 | { |
325 | return engine->scriptValueFromQMetaObject<T>(); |
326 | } |
327 | #endif |
328 | |
329 | #endif // QT_NO_QOBJECT |
330 | |
331 | inline QScriptValue qScriptValueFromValue_helper(QScriptEngine *engine, int type, const void *ptr) |
332 | { |
333 | if (!engine) |
334 | return QScriptValue(); |
335 | |
336 | return engine->create(type, ptr); |
337 | } |
338 | |
339 | template <typename T> |
340 | inline QScriptValue qScriptValueFromValue(QScriptEngine *engine, const T &t) |
341 | { |
342 | return qScriptValueFromValue_helper(engine, qMetaTypeId<T>(), &t); |
343 | } |
344 | |
345 | template <> |
346 | inline QScriptValue qScriptValueFromValue<QVariant>(QScriptEngine *engine, const QVariant &v) |
347 | { |
348 | return qScriptValueFromValue_helper(engine, type: v.userType(), ptr: v.data()); |
349 | } |
350 | |
351 | inline bool qscriptvalue_cast_helper(const QScriptValue &value, int type, void *ptr) |
352 | { |
353 | return QScriptEngine::convertV2(value, type, ptr); |
354 | } |
355 | |
356 | template<typename T> |
357 | T qscriptvalue_cast(const QScriptValue &value) |
358 | { |
359 | T t; |
360 | const int id = qMetaTypeId<T>(); |
361 | |
362 | if (qscriptvalue_cast_helper(value, id, &t)) |
363 | return t; |
364 | else if (value.isVariant()) |
365 | return qvariant_cast<T>(value.toVariant()); |
366 | |
367 | return T(); |
368 | } |
369 | |
370 | template <> |
371 | inline QVariant qscriptvalue_cast<QVariant>(const QScriptValue &value) |
372 | { |
373 | return value.toVariant(); |
374 | } |
375 | |
376 | #ifdef QT_DEPRECATED |
377 | template <typename T> |
378 | inline QT_DEPRECATED T qScriptValueToValue(const QScriptValue &value) |
379 | { |
380 | return qscriptvalue_cast<T>(value); |
381 | } |
382 | #endif |
383 | |
384 | inline void qScriptRegisterMetaType_helper(QScriptEngine *eng, int type, |
385 | QScriptEngine::MarshalFunction mf, |
386 | QScriptEngine::DemarshalFunction df, |
387 | const QScriptValue &prototype) |
388 | { |
389 | eng->registerCustomType(type, mf, df, prototype); |
390 | } |
391 | |
392 | template<typename T> |
393 | int qScriptRegisterMetaType( |
394 | QScriptEngine *eng, |
395 | QScriptValue (*toScriptValue)(QScriptEngine *, const T &t), |
396 | void (*fromScriptValue)(const QScriptValue &, T &t), |
397 | const QScriptValue &prototype = QScriptValue(), |
398 | T * /* dummy */ = 0) |
399 | { |
400 | const int id = qRegisterMetaType<T>(); // make sure it's registered |
401 | |
402 | qScriptRegisterMetaType_helper( |
403 | eng, type: id, mf: reinterpret_cast<QScriptEngine::MarshalFunction>(toScriptValue), |
404 | df: reinterpret_cast<QScriptEngine::DemarshalFunction>(fromScriptValue), |
405 | prototype); |
406 | |
407 | return id; |
408 | } |
409 | |
410 | template <class Container> |
411 | QScriptValue qScriptValueFromSequence(QScriptEngine *eng, const Container &cont) |
412 | { |
413 | QScriptValue a = eng->newArray(); |
414 | typename Container::const_iterator begin = cont.begin(); |
415 | typename Container::const_iterator end = cont.end(); |
416 | typename Container::const_iterator it; |
417 | quint32 i; |
418 | for (it = begin, i = 0; it != end; ++it, ++i) |
419 | a.setProperty(i, eng->toScriptValue(*it)); |
420 | return a; |
421 | } |
422 | |
423 | template <class Container> |
424 | void qScriptValueToSequence(const QScriptValue &value, Container &cont) |
425 | { |
426 | quint32 len = value.property(name: QLatin1String("length" )).toUInt32(); |
427 | for (quint32 i = 0; i < len; ++i) { |
428 | QScriptValue item = value.property(arrayIndex: i); |
429 | cont.push_back(qscriptvalue_cast<typename Container::value_type>(item)); |
430 | } |
431 | } |
432 | |
433 | template<typename T> |
434 | int qScriptRegisterSequenceMetaType( |
435 | QScriptEngine *engine, |
436 | const QScriptValue &prototype = QScriptValue(), |
437 | T * /* dummy */ = 0) |
438 | { |
439 | return qScriptRegisterMetaType<T>(engine, qScriptValueFromSequence, |
440 | qScriptValueToSequence, prototype); |
441 | } |
442 | |
443 | #ifndef QT_NO_QOBJECT |
444 | Q_SCRIPT_EXPORT bool qScriptConnect(QObject *sender, const char *signal, |
445 | const QScriptValue &receiver, |
446 | const QScriptValue &function); |
447 | Q_SCRIPT_EXPORT bool qScriptDisconnect(QObject *sender, const char *signal, |
448 | const QScriptValue &receiver, |
449 | const QScriptValue &function); |
450 | #endif // QT_NO_QOBJECT |
451 | |
452 | Q_DECLARE_OPERATORS_FOR_FLAGS(QScriptEngine::QObjectWrapOptions) |
453 | |
454 | QT_END_NAMESPACE |
455 | |
456 | #endif // QSCRIPTENGINE_H |
457 | |