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