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. Use newDate() to
130 create a \c{Date} object, and newRegExp() to create a \c{RegExp}
133 \section1 QObject Integration
135 Use newQObject() to wrap a QObject (or subclass)
136 pointer. newQObject() returns a proxy script object; properties,
137 children, and signals and slots of the QObject are available as
138 properties of the proxy object. No binding code is needed because it
139 is done dynamically using the Qt meta object system.
141 \snippet doc/src/snippets/code/src_script_qjsengine.cpp 5
143 \sa QJSValue, {Making Applications Scriptable}
151 Constructs a QJSEngine object.
153 The globalObject() is initialized to have properties as described in
154 \l{ECMA-262}, Section 15.1.
156 QJSEngine::QJSEngine()
157 : d(new QV8Engine(this))
166 QJSEngine::QJSEngine(QJSEngine::ContextOwnership ownership)
167 : d(new QV8Engine(this, ownership))
171 #endif // QT_DEPRECATED
174 Constructs a QJSEngine object with the given \a parent.
176 The globalObject() is initialized to have properties as described in
177 \l{ECMA-262}, Section 15.1.
180 QJSEngine::QJSEngine(QObject *parent)
182 , d(new QV8Engine(this))
186 QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
187 : QObject(dd, parent)
188 , d(new QV8Engine(this))
193 Destroys this QJSEngine.
195 QJSEngine::~QJSEngine()
201 \fn QV8Engine *QJSEngine::handle() const
210 Returns true if the last script evaluation resulted in an uncaught
211 exception; otherwise returns false.
213 The exception state is cleared when evaluate() is called.
215 \sa uncaughtException(), uncaughtExceptionLineNumber(),
216 uncaughtExceptionBacktrace()
218 bool QJSEngine::hasUncaughtException() const
220 Q_D(const QJSEngine);
221 QScriptIsolate api(d);
222 return d->hasUncaughtException();
228 Returns the current uncaught exception, or an invalid QJSValue
229 if there is no uncaught exception.
231 The exception value is typically an \c{Error} object; in that case,
232 you can call toString() on the return value to obtain an error
235 \sa hasUncaughtException(), uncaughtExceptionLineNumber(),
236 uncaughtExceptionBacktrace()
238 QJSValue QJSEngine::uncaughtException() const
240 Q_D(const QJSEngine);
241 QScriptIsolate api(d);
242 return d->scriptValueFromInternal(d->uncaughtException());
248 Clears any uncaught exceptions in this engine.
250 \sa hasUncaughtException()
252 void QJSEngine::clearExceptions()
255 QScriptIsolate api(d);
256 d->clearExceptions();
259 #endif // QT_DEPRECATED
262 Runs the garbage collector.
264 The garbage collector will attempt to reclaim memory by locating and disposing of objects that are
265 no longer reachable in the script environment.
267 Normally you don't need to call this function; the garbage collector will automatically be invoked
268 when the QJSEngine decides that it's wise to do so (i.e. when a certain number of new objects
269 have been created). However, you can call this function to explicitly request that garbage
270 collection should be performed as soon as possible.
272 \sa reportAdditionalMemoryCost()
274 void QJSEngine::collectGarbage()
277 QScriptIsolate api(d);
282 Evaluates \a program, using \a lineNumber as the base line number,
283 and returns the result of the evaluation.
285 The script code will be evaluated in the current context.
287 The evaluation of \a program can cause an exception in the
288 engine; in this case the return value will be the exception
289 that was thrown (typically an \c{Error} object). You can call
290 hasUncaughtException() to determine if an exception occurred in
291 the last call to evaluate().
293 \a lineNumber is used to specify a starting line number for \a
294 program; line number information reported by the engine that pertain
295 to this evaluation (e.g. uncaughtExceptionLineNumber()) will be
296 based on this argument. For example, if \a program consists of two
297 lines of code, and the statement on the second line causes a script
298 exception, uncaughtExceptionLineNumber() would return the given \a
299 lineNumber plus one. When no starting line number is specified, line
300 numbers will be 1-based.
302 \a fileName is used for error reporting. For example in error objects
303 the file name is accessible through the "fileName" property if it's
304 provided with this function.
306 QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
309 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
310 v8::HandleScope handleScope;
311 return QJSValuePrivate::get(d->evaluate(program, fileName, lineNumber));
319 Returns a QJSValue of the primitive type Null.
323 QJSValue QJSEngine::nullValue()
326 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
327 v8::HandleScope handleScope;
328 return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Null()));
334 Returns a QJSValue of the primitive type Undefined.
338 QJSValue QJSEngine::undefinedValue()
341 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
342 v8::HandleScope handleScope;
343 return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Undefined()));
346 #endif // QT_DEPRECATED
349 Creates a JavaScript object of class Object.
351 The prototype of the created object will be the Object
354 \sa newArray(), QJSValue::setProperty()
356 QJSValue QJSEngine::newObject()
359 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
360 v8::HandleScope handleScope;
361 return QJSValuePrivate::get(new QJSValuePrivate(d, v8::Object::New()));
365 Creates a JavaScript object of class Array with the given \a length.
369 QJSValue QJSEngine::newArray(uint length)
372 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
373 v8::HandleScope handleScope;
374 return QJSValuePrivate::get(d->newArray(length));
378 Creates a JavaScript object that wraps the given QObject \a
379 object, using the given \a ownership. The given \a options control
380 various aspects of the interaction with the resulting script object.
382 Signals and slots, properties and children of \a object are
383 available as properties of the created QJSValue.
385 If \a object is a null pointer, this function returns nullValue().
387 If a default prototype has been registered for the \a object's class
388 (or its superclass, recursively), the prototype of the new script
389 object will be set to be that default prototype.
391 If the given \a object is deleted outside of the engine's control, any
392 attempt to access the deleted QObject's members through the JavaScript
393 wrapper object (either by script code or C++) will result in a
396 \sa QJSValue::toQObject(), reportAdditionalMemoryCost()
398 QJSValue QJSEngine::newQObject(QObject *object)
401 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
402 v8::HandleScope handleScope;
403 return d->scriptValueFromInternal(d->newQObject(object, QV8Engine::JavaScriptOwnership));
411 Creates a JavaScript object holding the given variant \a value.
413 If a default prototype has been registered with the meta type id of
414 \a value, then the prototype of the created object will be that
415 prototype; otherwise, the prototype will be the Object prototype
418 \sa setDefaultPrototype(), QJSValue::toVariant(), reportAdditionalMemoryCost()
420 QJSValue QJSEngine::newVariant(const QVariant &value)
423 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
424 v8::HandleScope handleScope;
425 return d->scriptValueFromInternal(d->newVariant(value));
428 #endif // QT_DEPRECATED
431 Returns this engine's Global Object.
433 By default, the Global Object contains the built-in objects that are
434 part of \l{ECMA-262}, such as Math, Date and String. Additionally,
435 you can set properties of the Global Object to make your own
436 extensions available to all script code. Non-local variables in
437 script code will be created as properties of the Global Object, as
438 well as local variables in global code.
440 QJSValue QJSEngine::globalObject() const
442 Q_D(const QJSEngine);
443 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
444 v8::HandleScope handleScope;
445 return d->scriptValueFromInternal(d->global());
453 Converts the given \a value to an object, if such a conversion is
454 possible; otherwise returns an invalid QJSValue. The conversion
455 is performed according to the following table:
458 \header \o Input Type \o Result
459 \row \o Undefined \o An invalid QJSValue.
460 \row \o Null \o An invalid QJSValue.
461 \row \o Boolean \o A new Boolean object whose internal value is set to the value of the boolean.
462 \row \o Number \o A new Number object whose internal value is set to the value of the number.
463 \row \o String \o A new String object whose internal value is set to the value of the string.
464 \row \o Object \o The result is the object itself (no conversion).
469 QJSValue QJSEngine::toObject(const QJSValue& value)
472 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
473 v8::HandleScope handleScope;
474 return QJSValuePrivate::get(QJSValuePrivate::get(value)->toObject(d));
480 Creates a JavaScript object of class Date from the given \a value.
482 \sa QJSValue::toDateTime()
484 QJSValue QJSEngine::newDate(const QDateTime &dt)
487 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
488 v8::HandleScope handleScope;
489 return d->scriptValueFromInternal(QJSConverter::toDateTime(dt));
495 Creates a JavaScript object of class Date with the given
496 \a value (the number of milliseconds since 01 January 1970,
499 QJSValue QJSEngine::newDate(double date)
502 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
503 v8::HandleScope handleScope;
504 return d->scriptValueFromInternal(v8::Handle<v8::Value>(v8::Date::New(date)));
510 Creates a JavaScript object of class RegExp with the given
513 \sa QJSValue::toRegExp()
515 QJSValue QJSEngine::newRegExp(const QRegExp ®exp)
518 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
519 v8::HandleScope handleScope;
520 return QJSValuePrivate::get(d->newRegExp(regexp));
526 Creates a JavaScript object of class RegExp with the given
527 \a pattern and \a flags.
529 The legal flags are 'g' (global), 'i' (ignore case), and 'm'
532 QJSValue QJSEngine::newRegExp(const QString &pattern, const QString &flags)
535 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
536 v8::HandleScope handleScope;
537 return QJSValuePrivate::get(d->newRegExp(pattern, flags));
540 #endif // QT_DEPRECATED
544 * used by QJSEngine::toScriptValue
546 QJSValue QJSEngine::create(int type, const void *ptr)
549 QScriptIsolate api(d, QScriptIsolate::NotNullEngine);
550 v8::HandleScope handleScope;
551 return d->scriptValueFromInternal(d->metaTypeToJS(type, ptr));
557 convert \a value to \a type, store the result in \a ptr
559 bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
561 QJSValuePrivate *vp = QJSValuePrivate::get(value);
562 QV8Engine *engine = vp->engine();
564 QScriptIsolate api(engine, QScriptIsolate::NotNullEngine);
565 v8::HandleScope handleScope;
566 return engine->metaTypeFromJS(*vp, type, ptr);
569 case QMetaType::Bool:
570 *reinterpret_cast<bool*>(ptr) = vp->toBool();
573 *reinterpret_cast<int*>(ptr) = vp->toInt32();
575 case QMetaType::UInt:
576 *reinterpret_cast<uint*>(ptr) = vp->toUInt32();
578 case QMetaType::LongLong:
579 *reinterpret_cast<qlonglong*>(ptr) = vp->toInteger();
581 case QMetaType::ULongLong:
582 *reinterpret_cast<qulonglong*>(ptr) = vp->toInteger();
584 case QMetaType::Double:
585 *reinterpret_cast<double*>(ptr) = vp->toNumber();
587 case QMetaType::QString:
588 *reinterpret_cast<QString*>(ptr) = vp->toString();
590 case QMetaType::Float:
591 *reinterpret_cast<float*>(ptr) = vp->toNumber();
593 case QMetaType::Short:
594 *reinterpret_cast<short*>(ptr) = vp->toInt32();
596 case QMetaType::UShort:
597 *reinterpret_cast<unsigned short*>(ptr) = vp->toUInt16();
599 case QMetaType::Char:
600 *reinterpret_cast<char*>(ptr) = vp->toInt32();
602 case QMetaType::UChar:
603 *reinterpret_cast<unsigned char*>(ptr) = vp->toUInt16();
605 case QMetaType::QChar:
606 *reinterpret_cast<QChar*>(ptr) = vp->toUInt16();
614 /*! \fn QJSValue QJSEngine::toScriptValue(const T &value)
616 Creates a QJSValue with the given \a value.
618 \sa fromScriptValue()
621 /*! \fn T QJSEngine::fromScriptValue(const QJSValue &value)
623 Returns the given \a value converted to the template type \c{T}.
630 #include "moc_qjsengine.cpp"