Merge remote branch 'gerrit/api_changes' into merge-master
[profile/ivi/qtdeclarative.git] / src / qml / qml / v8 / qjsengine.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
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-project.org/.
19 **
20 ** $QT_END_LICENSE$
21 **
22 ****************************************************************************/
23
24 #include "qjsengine.h"
25 #include "qjsengine_p.h"
26 #include "qjsvalue.h"
27 #include "qjsvalue_p.h"
28 #include "qscriptisolate_p.h"
29 #include "qscript_impl_p.h"
30 #include "qv8engine_p.h"
31
32 #include <QtCore/qdatetime.h>
33 #include <QtCore/qmetaobject.h>
34 #include <QtCore/qstringlist.h>
35 #include <QtCore/qvariant.h>
36 #include <QtCore/qdatetime.h>
37
38 #include <QtCore/qcoreapplication.h>
39 #include <QtCore/qdir.h>
40 #include <QtCore/qfile.h>
41 #include <QtCore/qfileinfo.h>
42 #include <QtCore/qpluginloader.h>
43 #include <qthread.h>
44 #include <qmutex.h>
45 #include <qwaitcondition.h>
46
47 #undef Q_D
48 #undef Q_Q
49 #define Q_D(blah)
50 #define Q_Q(blah)
51
52 Q_DECLARE_METATYPE(QJSValue)
53 Q_DECLARE_METATYPE(QObjectList)
54 Q_DECLARE_METATYPE(QList<int>)
55
56 /*!
57   \since 5.0
58   \class QJSEngine
59
60   \brief The QJSEngine class provides an environment for evaluating JavaScript code.
61
62   \ingroup qtjavascript
63   \mainclass
64
65   \section1 Evaluating Scripts
66
67   Use evaluate() to evaluate script code.
68
69   \snippet doc/src/snippets/code/src_script_qjsengine.cpp 0
70
71   evaluate() returns a QJSValue that holds the result of the
72   evaluation. The QJSValue class provides functions for converting
73   the result to various C++ types (e.g. QJSValue::toString()
74   and QJSValue::toNumber()).
75
76   The following code snippet shows how a script function can be
77   defined and then invoked from C++ using QJSValue::call():
78
79   \snippet doc/src/snippets/code/src_script_qjsengine.cpp 1
80
81   As can be seen from the above snippets, a script is provided to the
82   engine in the form of a string. One common way of loading scripts is
83   by reading the contents of a file and passing it to evaluate():
84
85   \snippet doc/src/snippets/code/src_script_qjsengine.cpp 2
86
87   Here we pass the name of the file as the second argument to
88   evaluate().  This does not affect evaluation in any way; the second
89   argument is a general-purpose string that is used to identify the
90   script for debugging purposes (for example, our filename will now
91   show up in any uncaughtExceptionBacktrace() involving the script).
92
93   \section1 Engine Configuration
94
95   The globalObject() function returns the \bold {Global Object}
96   associated with the script engine. Properties of the Global Object
97   are accessible from any script code (i.e. they are global
98   variables). Typically, before evaluating "user" scripts, you will
99   want to configure a script engine by adding one or more properties
100   to the Global Object:
101
102   \snippet doc/src/snippets/code/src_script_qjsengine.cpp 3
103
104   Adding custom properties to the scripting environment is one of the
105   standard means of providing a scripting API that is specific to your
106   application. Usually these custom properties are objects created by
107   the newQObject() or newObject() functions.
108
109   \section1 Script Exceptions
110
111   evaluate() can throw a script exception (e.g. due to a syntax
112   error); in that case, the return value is the value that was thrown
113   (typically an \c{Error} object). You can check whether the
114   evaluation caused an exception by calling hasUncaughtException(). In
115   that case, you can call toString() on the error object to obtain an
116   error message. The current uncaught exception is also available
117   through uncaughtException().
118   Calling clearExceptions() will cause any uncaught exceptions to be
119   cleared.
120
121   \snippet doc/src/snippets/code/src_script_qjsengine.cpp 4
122
123   \section1 Script Object Creation
124
125   Use newObject() to create a JavaScript object; this is the
126   C++ equivalent of the script statement \c{new Object()}. You can use
127   the object-specific functionality in QJSValue to manipulate the
128   script object (e.g. QJSValue::setProperty()). Similarly, use
129   newArray() to create a JavaScript array object.
130
131   \section1 QObject Integration
132
133   Use newQObject() to wrap a QObject (or subclass)
134   pointer. newQObject() returns a proxy script object; properties,
135   children, and signals and slots of the QObject are available as
136   properties of the proxy object. No binding code is needed because it
137   is done dynamically using the Qt meta object system.
138
139   \snippet doc/src/snippets/code/src_script_qjsengine.cpp 5
140
141   \sa QJSValue, {Making Applications Scriptable}
142
143 */
144
145 QT_BEGIN_NAMESPACE
146
147
148 /*!
149     Constructs a QJSEngine object.
150
151     The globalObject() is initialized to have properties as described in
152     \l{ECMA-262}, Section 15.1.
153 */
154 QJSEngine::QJSEngine()
155     : d(new QV8Engine(this))
156 {
157 }
158
159 #ifdef QT_DEPRECATED
160
161 /*!
162     \internal
163 */
164 QJSEngine::QJSEngine(QJSEngine::ContextOwnership ownership)
165     : d(new QV8Engine(this, ownership))
166 {
167 }
168
169 #endif // QT_DEPRECATED
170
171 /*!
172     Constructs a QJSEngine object with the given \a parent.
173
174     The globalObject() is initialized to have properties as described in
175     \l{ECMA-262}, Section 15.1.
176 */
177
178 QJSEngine::QJSEngine(QObject *parent)
179     : QObject(parent)
180     , d(new QV8Engine(this))
181 {
182 }
183
184 QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
185     : QObject(dd, parent)
186     , d(new QV8Engine(this))
187 {
188 }
189
190 /*!
191     Destroys this QJSEngine.
192 */
193 QJSEngine::~QJSEngine()
194 {
195     delete d;
196 }
197
198 /*!
199     \fn QV8Engine *QJSEngine::handle() const
200     \internal
201 */
202
203 #ifdef QT_DEPRECATED
204
205 /*!
206     \obsolete
207
208     Returns true if the last script evaluation resulted in an uncaught
209     exception; otherwise returns false.
210
211     The exception state is cleared when evaluate() is called.
212
213     \sa uncaughtException(), uncaughtExceptionLineNumber(),
214       uncaughtExceptionBacktrace()
215 */
216 bool QJSEngine::hasUncaughtException() const
217 {
218     Q_D(const QJSEngine);
219     QScriptIsolate api(d);
220     return d->hasUncaughtException();
221 }
222
223 /*!
224     \obsolete
225
226     Returns the current uncaught exception, or an invalid QJSValue
227     if there is no uncaught exception.
228
229     The exception value is typically an \c{Error} object; in that case,
230     you can call toString() on the return value to obtain an error
231     message.
232
233     \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
234       uncaughtExceptionBacktrace()
235 */
236 QJSValue QJSEngine::uncaughtException() const
237 {
238     Q_D(const QJSEngine);
239     QScriptIsolate api(d);
240     return d->scriptValueFromInternal(d->uncaughtException());
241 }
242
243 /*!
244     \obsolete
245
246     Clears any uncaught exceptions in this engine.
247
248     \sa hasUncaughtException()
249 */
250 void QJSEngine::clearExceptions()
251 {
252     Q_D(QJSEngine);
253     QScriptIsolate api(d);
254     d->clearExceptions();
255 }
256
257 #endif // QT_DEPRECATED
258
259 /*!
260     Runs the garbage collector.
261
262     The garbage collector will attempt to reclaim memory by locating and disposing of objects that are
263     no longer reachable in the script environment.
264
265     Normally you don't need to call this function; the garbage collector will automatically be invoked
266     when the QJSEngine decides that it's wise to do so (i.e. when a certain number of new objects
267     have been created). However, you can call this function to explicitly request that garbage
268     collection should be performed as soon as possible.
269
270     \sa reportAdditionalMemoryCost()
271 */
272 void QJSEngine::collectGarbage()
273 {
274     Q_D(QJSEngine);
275     QScriptIsolate api(d);
276     d->collectGarbage();
277 }
278
279 /*!
280     Evaluates \a program, using \a lineNumber as the base line number,
281     and returns the result of the evaluation.
282
283     The script code will be evaluated in the current context.
284
285     The evaluation of \a program can cause an exception in the
286     engine; in this case the return value will be the exception
287     that was thrown (typically an \c{Error} object). You can call
288     hasUncaughtException() to determine if an exception occurred in
289     the last call to evaluate().
290
291     \a lineNumber is used to specify a starting line number for \a
292     program; line number information reported by the engine that pertain
293     to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
294     based on this argument. For example, if \a program consists of two
295     lines of code, and the statement on the second line causes a script
296     exception, uncaughtExceptionLineNumber() would return the given \a
297     lineNumber plus one. When no starting line number is specified, line
298     numbers will be 1-based.
299
300     \a fileName is used for error reporting. For example in error objects
301     the file name is accessible through the "fileName" property if it's
302     provided with this function.
303 */
304 QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
305 {
306     Q_D(QJSEngine);
307     QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
308     v8::HandleScope handleScope;
309     return QJSValuePrivate::get(d->evaluate(program, fileName, lineNumber));
310 }
311
312 /*!
313   Creates a JavaScript object of class Object.
314
315   The prototype of the created object will be the Object
316   prototype object.
317
318   \sa newArray(), QJSValue::setProperty()
319 */
320 QJSValue QJSEngine::newObject()
321 {
322     Q_D(QJSEngine);
323     QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
324     v8::HandleScope handleScope;
325     return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
326 }
327
328 /*!
329   Creates a JavaScript object of class Array with the given \a length.
330
331   \sa newObject()
332 */
333 QJSValue QJSEngine::newArray(uint length)
334 {
335     Q_D(QJSEngine);
336     QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
337     v8::HandleScope handleScope;
338     return QJSValuePrivate::get(d->newArray(length));
339 }
340
341 /*!
342   Creates a JavaScript object that wraps the given QObject \a
343   object, using JavaScriptOwnership. The given \a options control
344   various aspects of the interaction with the resulting script object.
345
346   Signals and slots, properties and children of \a object are
347   available as properties of the created QJSValue.
348
349   If \a object is a null pointer, this function returns a null value.
350
351   If a default prototype has been registered for the \a object's class
352   (or its superclass, recursively), the prototype of the new script
353   object will be set to be that default prototype.
354
355   If the given \a object is deleted outside of the engine's control, any
356   attempt to access the deleted QObject's members through the JavaScript
357   wrapper object (either by script code or C++) will result in a
358   script exception.
359
360   \sa QJSValue::toQObject(), reportAdditionalMemoryCost()
361 */
362 QJSValue QJSEngine::newQObject(QObject *object)
363 {
364     Q_D(QJSEngine);
365     QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
366     v8::HandleScope handleScope;
367     return d->scriptValueFromInternal(d->newQObject(object, QV8Engine::JavaScriptOwnership));
368 }
369
370 /*!
371   Returns this engine's Global Object.
372
373   By default, the Global Object contains the built-in objects that are
374   part of \l{ECMA-262}, such as Math, Date and String. Additionally,
375   you can set properties of the Global Object to make your own
376   extensions available to all script code. Non-local variables in
377   script code will be created as properties of the Global Object, as
378   well as local variables in global code.
379 */
380 QJSValue QJSEngine::globalObject() const
381 {
382     Q_D(const QJSEngine);
383     QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
384     v8::HandleScope handleScope;
385     return d->scriptValueFromInternal(d->global());
386 }
387
388 /*!
389  *  \internal
390  * used by QJSEngine::toScriptValue
391  */
392 QJSValue QJSEngine::create(int type, const void *ptr)
393 {
394     Q_D(QJSEngine);
395     QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
396     v8::HandleScope handleScope;
397     return d->scriptValueFromInternal(d->metaTypeToJS(type, ptr));
398 }
399
400 /*!
401     \internal
402     \since 4.5
403     convert \a value to \a type, store the result in \a ptr
404 */
405 bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
406 {
407     QJSValuePrivate *vp = QJSValuePrivate::get(value);
408     QV8Engine *engine = vp->engine();
409     if (engine) {
410         QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
411         v8::HandleScope handleScope;
412         return engine->metaTypeFromJS(*vp, type, ptr);
413     } else {
414         switch (type) {
415             case QMetaType::Bool:
416                 *reinterpret_cast<bool*>(ptr) = vp->toBool();
417                 return true;
418             case QMetaType::Int:
419                 *reinterpret_cast<int*>(ptr) = vp->toInt32();
420                 return true;
421             case QMetaType::UInt:
422                 *reinterpret_cast<uint*>(ptr) = vp->toUInt32();
423                 return true;
424             case QMetaType::LongLong:
425                 *reinterpret_cast<qlonglong*>(ptr) = vp->toInteger();
426                 return true;
427             case QMetaType::ULongLong:
428                 *reinterpret_cast<qulonglong*>(ptr) = vp->toInteger();
429                 return true;
430             case QMetaType::Double:
431                 *reinterpret_cast<double*>(ptr) = vp->toNumber();
432                 return true;
433             case QMetaType::QString:
434                 *reinterpret_cast<QString*>(ptr) = vp->toString();
435                 return true;
436             case QMetaType::Float:
437                 *reinterpret_cast<float*>(ptr) = vp->toNumber();
438                 return true;
439             case QMetaType::Short:
440                 *reinterpret_cast<short*>(ptr) = vp->toInt32();
441                 return true;
442             case QMetaType::UShort:
443                 *reinterpret_cast<unsigned short*>(ptr) = vp->toUInt16();
444                 return true;
445             case QMetaType::Char:
446                 *reinterpret_cast<char*>(ptr) = vp->toInt32();
447                 return true;
448             case QMetaType::UChar:
449                 *reinterpret_cast<unsigned char*>(ptr) = vp->toUInt16();
450                 return true;
451             case QMetaType::QChar:
452                 *reinterpret_cast<QChar*>(ptr) = vp->toUInt16();
453                 return true;
454             default:
455                 return false;
456         }
457     }
458 }
459
460 /*! \fn QJSValue QJSEngine::toScriptValue(const T &value)
461
462     Creates a QJSValue with the given \a value.
463
464     \sa fromScriptValue()
465 */
466
467 /*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
468
469     Returns the given \a value converted to the template type \c{T}.
470
471     \sa toScriptValue()
472 */
473
474 QT_END_NAMESPACE
475
476 #include "moc_qjsengine.cpp"