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