1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
42 #include "qjsengine.h"
43 #include "qjsengine_p.h"
45 #include "qjsvalue_p.h"
46 #include "qscriptisolate_p.h"
47 #include "qscript_impl_p.h"
48 #include "qv8engine_p.h"
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>
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>
63 #include <qwaitcondition.h>
64 #include <private/qqmlglobal_p.h>
71 Q_DECLARE_METATYPE(QJSValue)
72 Q_DECLARE_METATYPE(QObjectList)
73 Q_DECLARE_METATYPE(QList<int>)
79 \brief The QJSEngine class provides an environment for evaluating JavaScript code.
84 \section1 Evaluating Scripts
86 Use evaluate() to evaluate script code.
88 \snippet code/src_script_qjsengine.cpp 0
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()).
95 The following code snippet shows how a script function can be
96 defined and then invoked from C++ using QJSValue::call():
98 \snippet code/src_script_qjsengine.cpp 1
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():
104 \snippet code/src_script_qjsengine.cpp 2
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.
111 \section1 Engine Configuration
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:
120 \snippet code/src_script_qjsengine.cpp 3
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.
127 \section1 Script Exceptions
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.
136 \snippet code/src_script_qjsengine.cpp 4
138 \section1 Script Object Creation
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.
146 \section1 QObject Integration
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.
154 \snippet code/src_script_qjsengine.cpp 5
156 \sa QJSValue, {Making Applications Scriptable}
164 Constructs a QJSEngine object.
166 The globalObject() is initialized to have properties as described in
167 \l{ECMA-262}, Section 15.1.
169 QJSEngine::QJSEngine()
170 : d(new QV8Engine(this))
175 Constructs a QJSEngine object with the given \a parent.
177 The globalObject() is initialized to have properties as described in
178 \l{ECMA-262}, Section 15.1.
181 QJSEngine::QJSEngine(QObject *parent)
183 , d(new QV8Engine(this))
187 QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
188 : QObject(dd, parent)
189 , d(new QV8Engine(this))
194 Destroys this QJSEngine.
196 QJSEngine::~QJSEngine()
202 \fn QV8Engine *QJSEngine::handle() const
207 Runs the garbage collector.
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.
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.
217 void QJSEngine::collectGarbage()
220 QScriptIsolate api(d);
225 Evaluates \a program, using \a lineNumber as the base line number,
226 and returns the result of the evaluation.
228 The script code will be evaluated in the current context.
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()).
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.
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.
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.
252 QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
255 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
256 v8::HandleScope handleScope;
257 return QJSValuePrivate::get(d->evaluate(program, fileName, qmlSourceCoordinate(lineNumber)));
261 Creates a JavaScript object of class Object.
263 The prototype of the created object will be the Object
266 \sa newArray(), QJSValue::setProperty()
268 QJSValue QJSEngine::newObject()
271 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
272 v8::HandleScope handleScope;
273 return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
277 Creates a JavaScript object of class Array with the given \a length.
281 QJSValue QJSEngine::newArray(uint length)
284 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
285 v8::HandleScope handleScope;
286 return QJSValuePrivate::get(d->newArray(length));
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.
294 Signals and slots, properties and children of \a object are
295 available as properties of the created QJSValue.
297 If \a object is a null pointer, this function returns a null value.
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.
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
308 \sa QJSValue::toQObject()
310 QJSValue QJSEngine::newQObject(QObject *object)
313 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
314 v8::HandleScope handleScope;
315 return d->scriptValueFromInternal(d->newQObject(object, QV8Engine::JavaScriptOwnership));
319 Returns this engine's Global Object.
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.
328 QJSValue QJSEngine::globalObject() const
330 Q_D(const QJSEngine);
331 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
332 v8::HandleScope handleScope;
333 return d->scriptValueFromInternal(d->global());
338 * used by QJSEngine::toScriptValue
340 QJSValue QJSEngine::create(int type, const void *ptr)
343 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
344 v8::HandleScope handleScope;
345 return d->scriptValueFromInternal(d->metaTypeToJS(type, ptr));
351 convert \a value to \a type, store the result in \a ptr
353 bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
355 QJSValuePrivate *vp = QJSValuePrivate::get(value);
356 QV8Engine *engine = vp->engine();
358 QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
359 v8::HandleScope handleScope;
360 return engine->metaTypeFromJS(*vp, type, ptr);
363 case QMetaType::Bool:
364 *reinterpret_cast<bool*>(ptr) = vp->toBool();
367 *reinterpret_cast<int*>(ptr) = vp->toInt32();
369 case QMetaType::UInt:
370 *reinterpret_cast<uint*>(ptr) = vp->toUInt32();
372 case QMetaType::LongLong:
373 *reinterpret_cast<qlonglong*>(ptr) = vp->toInteger();
375 case QMetaType::ULongLong:
376 *reinterpret_cast<qulonglong*>(ptr) = vp->toInteger();
378 case QMetaType::Double:
379 *reinterpret_cast<double*>(ptr) = vp->toNumber();
381 case QMetaType::QString:
382 *reinterpret_cast<QString*>(ptr) = vp->toString();
384 case QMetaType::Float:
385 *reinterpret_cast<float*>(ptr) = vp->toNumber();
387 case QMetaType::Short:
388 *reinterpret_cast<short*>(ptr) = vp->toInt32();
390 case QMetaType::UShort:
391 *reinterpret_cast<unsigned short*>(ptr) = vp->toUInt16();
393 case QMetaType::Char:
394 *reinterpret_cast<char*>(ptr) = vp->toInt32();
396 case QMetaType::UChar:
397 *reinterpret_cast<unsigned char*>(ptr) = vp->toUInt16();
399 case QMetaType::QChar:
400 *reinterpret_cast<QChar*>(ptr) = vp->toUInt16();
408 /*! \fn QJSValue QJSEngine::toScriptValue(const T &value)
410 Creates a QJSValue with the given \a value.
412 \sa fromScriptValue()
415 /*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
417 Returns the given \a value converted to the template type \c{T}.
425 Returns this engine's internal V8 context.
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.
435 v8::HandleScope handleScope;
436 v8::Local<v8::Context> context = qt_QJSEngineV8Context(&eng);
437 v8::Context::Scope contextScope(context);
439 // Do stuff (e.g., call v8::Script::Compile()) ...
442 \sa qt_QJSValueV8Value()
444 Q_QML_EXPORT v8::Local<v8::Context> qt_QJSEngineV8Context(QJSEngine *engine)
446 Q_ASSERT(engine != 0);
447 QV8Engine *d = engine->handle();
448 return v8::Local<v8::Context>::New(d->context());
453 #include "moc_qjsengine.cpp"