1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtScript module of the Qt Toolkit.
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.
17 ** If you have questions regarding the use of this file, please contact
18 ** us via http://www.qt-project.org/.
22 ****************************************************************************/
24 #include "qjsengine.h"
25 #include "qjsengine_p.h"
27 #include "qjsvalue_p.h"
28 #include "qscriptisolate_p.h"
29 #include "qscript_impl_p.h"
30 #include "qv8engine_p.h"
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>
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>
45 #include <qwaitcondition.h>
52 Q_DECLARE_METATYPE(QJSValue)
53 Q_DECLARE_METATYPE(QObjectList)
54 Q_DECLARE_METATYPE(QList<int>)
60 \brief The QJSEngine class provides an environment for evaluating JavaScript code.
65 \section1 Evaluating Scripts
67 Use evaluate() to evaluate script code.
69 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 0
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()).
76 The following code snippet shows how a script function can be
77 defined and then invoked from C++ using QJSValue::call():
79 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 1
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():
85 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 2
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).
93 \section1 Engine Configuration
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:
102 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 3
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.
109 \section1 Script Exceptions
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
121 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 4
123 \section1 Script Object Creation
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.
131 \section1 QObject Integration
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.
139 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 5
141 \sa QJSValue, {Making Applications Scriptable}
149 Constructs a QJSEngine object.
151 The globalObject() is initialized to have properties as described in
152 \l{ECMA-262}, Section 15.1.
154 QJSEngine::QJSEngine()
155 : d(new QV8Engine(this))
164 QJSEngine::QJSEngine(QJSEngine::ContextOwnership ownership)
165 : d(new QV8Engine(this, ownership))
169 #endif // QT_DEPRECATED
172 Constructs a QJSEngine object with the given \a parent.
174 The globalObject() is initialized to have properties as described in
175 \l{ECMA-262}, Section 15.1.
178 QJSEngine::QJSEngine(QObject *parent)
180 , d(new QV8Engine(this))
184 QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
185 : QObject(dd, parent)
186 , d(new QV8Engine(this))
191 Destroys this QJSEngine.
193 QJSEngine::~QJSEngine()
199 \fn QV8Engine *QJSEngine::handle() const
208 Returns true if the last script evaluation resulted in an uncaught
209 exception; otherwise returns false.
211 The exception state is cleared when evaluate() is called.
213 \sa uncaughtException(), uncaughtExceptionLineNumber(),
214 uncaughtExceptionBacktrace()
216 bool QJSEngine::hasUncaughtException() const
218 Q_D(const QJSEngine);
219 QScriptIsolate api(d);
220 return d->hasUncaughtException();
226 Returns the current uncaught exception, or an invalid QJSValue
227 if there is no uncaught exception.
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
233 \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
234 uncaughtExceptionBacktrace()
236 QJSValue QJSEngine::uncaughtException() const
238 Q_D(const QJSEngine);
239 QScriptIsolate api(d);
240 return d->scriptValueFromInternal(d->uncaughtException());
246 Clears any uncaught exceptions in this engine.
248 \sa hasUncaughtException()
250 void QJSEngine::clearExceptions()
253 QScriptIsolate api(d);
254 d->clearExceptions();
257 #endif // QT_DEPRECATED
260 Runs the garbage collector.
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.
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.
270 \sa reportAdditionalMemoryCost()
272 void QJSEngine::collectGarbage()
275 QScriptIsolate api(d);
280 Evaluates \a program, using \a lineNumber as the base line number,
281 and returns the result of the evaluation.
283 The script code will be evaluated in the current context.
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().
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.
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.
304 QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
307 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
308 v8::HandleScope handleScope;
309 return QJSValuePrivate::get(d->evaluate(program, fileName, lineNumber));
313 Creates a JavaScript object of class Object.
315 The prototype of the created object will be the Object
318 \sa newArray(), QJSValue::setProperty()
320 QJSValue QJSEngine::newObject()
323 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
324 v8::HandleScope handleScope;
325 return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
329 Creates a JavaScript object of class Array with the given \a length.
333 QJSValue QJSEngine::newArray(uint length)
336 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
337 v8::HandleScope handleScope;
338 return QJSValuePrivate::get(d->newArray(length));
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.
346 Signals and slots, properties and children of \a object are
347 available as properties of the created QJSValue.
349 If \a object is a null pointer, this function returns a null value.
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.
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
360 \sa QJSValue::toQObject(), reportAdditionalMemoryCost()
362 QJSValue QJSEngine::newQObject(QObject *object)
365 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
366 v8::HandleScope handleScope;
367 return d->scriptValueFromInternal(d->newQObject(object, QV8Engine::JavaScriptOwnership));
371 Returns this engine's Global Object.
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.
380 QJSValue QJSEngine::globalObject() const
382 Q_D(const QJSEngine);
383 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
384 v8::HandleScope handleScope;
385 return d->scriptValueFromInternal(d->global());
390 * used by QJSEngine::toScriptValue
392 QJSValue QJSEngine::create(int type, const void *ptr)
395 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
396 v8::HandleScope handleScope;
397 return d->scriptValueFromInternal(d->metaTypeToJS(type, ptr));
403 convert \a value to \a type, store the result in \a ptr
405 bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
407 QJSValuePrivate *vp = QJSValuePrivate::get(value);
408 QV8Engine *engine = vp->engine();
410 QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
411 v8::HandleScope handleScope;
412 return engine->metaTypeFromJS(*vp, type, ptr);
415 case QMetaType::Bool:
416 *reinterpret_cast<bool*>(ptr) = vp->toBool();
419 *reinterpret_cast<int*>(ptr) = vp->toInt32();
421 case QMetaType::UInt:
422 *reinterpret_cast<uint*>(ptr) = vp->toUInt32();
424 case QMetaType::LongLong:
425 *reinterpret_cast<qlonglong*>(ptr) = vp->toInteger();
427 case QMetaType::ULongLong:
428 *reinterpret_cast<qulonglong*>(ptr) = vp->toInteger();
430 case QMetaType::Double:
431 *reinterpret_cast<double*>(ptr) = vp->toNumber();
433 case QMetaType::QString:
434 *reinterpret_cast<QString*>(ptr) = vp->toString();
436 case QMetaType::Float:
437 *reinterpret_cast<float*>(ptr) = vp->toNumber();
439 case QMetaType::Short:
440 *reinterpret_cast<short*>(ptr) = vp->toInt32();
442 case QMetaType::UShort:
443 *reinterpret_cast<unsigned short*>(ptr) = vp->toUInt16();
445 case QMetaType::Char:
446 *reinterpret_cast<char*>(ptr) = vp->toInt32();
448 case QMetaType::UChar:
449 *reinterpret_cast<unsigned char*>(ptr) = vp->toUInt16();
451 case QMetaType::QChar:
452 *reinterpret_cast<QChar*>(ptr) = vp->toUInt16();
460 /*! \fn QJSValue QJSEngine::toScriptValue(const T &value)
462 Creates a QJSValue with the given \a value.
464 \sa fromScriptValue()
467 /*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
469 Returns the given \a value converted to the template type \c{T}.
476 #include "moc_qjsengine.cpp"