2011-07-29 08:25:44 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
2011-07-29 08:25:44 +00:00
|
|
|
**
|
2012-05-24 08:15:36 +00:00
|
|
|
** This file is part of the QtQml module of the Qt Toolkit.
|
2011-07-29 08:25:44 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** $QT_BEGIN_LICENSE:LGPL$
|
2012-09-20 05:21:40 +00:00
|
|
|
** Commercial License Usage
|
|
|
|
** Licensees holding valid commercial Qt licenses may use this file in
|
|
|
|
** accordance with the commercial license agreement provided with the
|
|
|
|
** Software or, alternatively, in accordance with the terms contained in
|
2015-01-28 11:55:39 +00:00
|
|
|
** a written agreement between you and The Qt Company. For licensing terms
|
2016-01-19 09:38:36 +00:00
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
2012-09-20 05:21:40 +00:00
|
|
|
**
|
2011-07-29 08:25:44 +00:00
|
|
|
** GNU Lesser General Public License Usage
|
2012-09-20 05:21:40 +00:00
|
|
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
2016-01-19 09:38:36 +00:00
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
|
|
|
** packaging of this file. Please review the following information to
|
|
|
|
** ensure the GNU Lesser General Public License version 3 requirements
|
|
|
|
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
2012-05-24 08:15:36 +00:00
|
|
|
**
|
2016-01-19 09:38:36 +00:00
|
|
|
** GNU General Public License Usage
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
** General Public License version 2.0 or (at your option) the GNU General
|
|
|
|
** Public license version 3 or any later version approved by the KDE Free
|
|
|
|
** Qt Foundation. The licenses are as published by the Free Software
|
|
|
|
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
|
|
|
|
** https://www.gnu.org/licenses/gpl-3.0.html.
|
2012-05-24 08:15:36 +00:00
|
|
|
**
|
2011-07-29 08:25:44 +00:00
|
|
|
** $QT_END_LICENSE$
|
|
|
|
**
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
#include "qjsengine.h"
|
2011-11-10 08:33:27 +00:00
|
|
|
#include "qjsengine_p.h"
|
2011-07-29 08:25:44 +00:00
|
|
|
#include "qjsvalue.h"
|
|
|
|
#include "qjsvalue_p.h"
|
2013-08-08 11:02:40 +00:00
|
|
|
#include "private/qv8engine_p.h"
|
2011-07-29 08:25:44 +00:00
|
|
|
|
2013-04-18 10:41:59 +00:00
|
|
|
#include "private/qv4engine_p.h"
|
|
|
|
#include "private/qv4mm_p.h"
|
2017-08-01 14:31:53 +00:00
|
|
|
#include "private/qv4errorobject_p.h"
|
2013-04-18 10:41:59 +00:00
|
|
|
#include "private/qv4globalobject_p.h"
|
2013-05-22 11:49:27 +00:00
|
|
|
#include "private/qv4script_p.h"
|
2013-11-26 09:46:44 +00:00
|
|
|
#include "private/qv4runtime_p.h"
|
2014-06-06 10:42:23 +00:00
|
|
|
#include <private/qqmlbuiltinfunctions_p.h>
|
2015-11-30 19:05:43 +00:00
|
|
|
#include <private/qqmldebugconnector_p.h>
|
2016-03-23 12:17:10 +00:00
|
|
|
#include <private/qv4qobjectwrapper_p.h>
|
2018-06-27 12:18:17 +00:00
|
|
|
#include <private/qv4stackframe_p.h>
|
2018-08-15 14:43:13 +00:00
|
|
|
#include <private/qv4module_p.h>
|
2013-04-18 10:41:59 +00:00
|
|
|
|
2011-07-29 08:25:44 +00:00
|
|
|
#include <QtCore/qdatetime.h>
|
|
|
|
#include <QtCore/qmetaobject.h>
|
|
|
|
#include <QtCore/qstringlist.h>
|
|
|
|
#include <QtCore/qvariant.h>
|
|
|
|
#include <QtCore/qdatetime.h>
|
|
|
|
|
|
|
|
#include <QtCore/qcoreapplication.h>
|
|
|
|
#include <QtCore/qdir.h>
|
|
|
|
#include <QtCore/qfile.h>
|
|
|
|
#include <QtCore/qfileinfo.h>
|
|
|
|
#include <QtCore/qpluginloader.h>
|
|
|
|
#include <qthread.h>
|
|
|
|
#include <qmutex.h>
|
|
|
|
#include <qwaitcondition.h>
|
2012-08-09 03:26:32 +00:00
|
|
|
#include <private/qqmlglobal_p.h>
|
2013-06-13 15:10:35 +00:00
|
|
|
#include <qqmlengine.h>
|
2011-07-29 08:25:44 +00:00
|
|
|
|
|
|
|
#undef Q_D
|
|
|
|
#undef Q_Q
|
|
|
|
#define Q_D(blah)
|
|
|
|
#define Q_Q(blah)
|
|
|
|
|
|
|
|
Q_DECLARE_METATYPE(QList<int>)
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
/*!
|
|
|
|
\since 5.0
|
|
|
|
\class QJSEngine
|
2014-04-10 01:13:23 +00:00
|
|
|
\reentrant
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
\brief The QJSEngine class provides an environment for evaluating JavaScript code.
|
|
|
|
|
|
|
|
\ingroup qtjavascript
|
2012-11-29 12:48:21 +00:00
|
|
|
\inmodule QtQml
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
\section1 Evaluating Scripts
|
|
|
|
|
|
|
|
Use evaluate() to evaluate script code.
|
|
|
|
|
2012-05-28 01:56:24 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 0
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
evaluate() returns a QJSValue that holds the result of the
|
|
|
|
evaluation. The QJSValue class provides functions for converting
|
|
|
|
the result to various C++ types (e.g. QJSValue::toString()
|
|
|
|
and QJSValue::toNumber()).
|
|
|
|
|
|
|
|
The following code snippet shows how a script function can be
|
|
|
|
defined and then invoked from C++ using QJSValue::call():
|
|
|
|
|
2012-05-28 01:56:24 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 1
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
As can be seen from the above snippets, a script is provided to the
|
|
|
|
engine in the form of a string. One common way of loading scripts is
|
|
|
|
by reading the contents of a file and passing it to evaluate():
|
|
|
|
|
2012-05-28 01:56:24 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 2
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
Here we pass the name of the file as the second argument to
|
|
|
|
evaluate(). This does not affect evaluation in any way; the second
|
2015-04-14 23:45:03 +00:00
|
|
|
argument is a general-purpose string that is stored in the \c Error
|
|
|
|
object for debugging purposes.
|
2011-08-11 11:58:53 +00:00
|
|
|
|
2018-08-16 12:19:45 +00:00
|
|
|
For larger pieces of functionality, you may want to encapsulate
|
|
|
|
your code and data into modules. A module is a file that contains
|
|
|
|
script code, variables, etc., and uses export statements to describe
|
|
|
|
its interface towards the rest of the application. With the help of
|
|
|
|
import statements, a module can refer to functionality from other modules.
|
|
|
|
This allows building a scripted application from smaller connected building blocks
|
|
|
|
in a safe way. In contrast, the approach of using evaluate() carries the risk
|
|
|
|
that internal variables or functions from one evaluate() call accidentally pollute the
|
|
|
|
global object and affect subsequent evaluations.
|
|
|
|
|
|
|
|
The following example provides a module that can add numbers:
|
|
|
|
|
|
|
|
\code
|
|
|
|
export function sum(left, right)
|
|
|
|
{
|
|
|
|
return left + right
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
This module can be loaded with QJSEngine::import() if it is saved under
|
|
|
|
the name \c{math.mjs}:
|
|
|
|
|
|
|
|
\code
|
|
|
|
QJSvalue module = myEngine.importModule("./math.mjs");
|
|
|
|
QJSValue sumFunction = module.property("sum");
|
|
|
|
QJSValue result = sumFunction.call(args);
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
Modules can also use functionality from other modules using import
|
|
|
|
statements:
|
|
|
|
|
|
|
|
\code
|
|
|
|
import { sum } from "./math.mjs";
|
|
|
|
export function addTwice(left, right)
|
|
|
|
{
|
|
|
|
return sum(left, right) * 2;
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
\section1 Engine Configuration
|
|
|
|
|
2012-03-01 17:05:16 +00:00
|
|
|
The globalObject() function returns the \b {Global Object}
|
2011-08-11 11:58:53 +00:00
|
|
|
associated with the script engine. Properties of the Global Object
|
|
|
|
are accessible from any script code (i.e. they are global
|
|
|
|
variables). Typically, before evaluating "user" scripts, you will
|
|
|
|
want to configure a script engine by adding one or more properties
|
|
|
|
to the Global Object:
|
|
|
|
|
2012-05-28 01:56:24 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 3
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
Adding custom properties to the scripting environment is one of the
|
|
|
|
standard means of providing a scripting API that is specific to your
|
|
|
|
application. Usually these custom properties are objects created by
|
|
|
|
the newQObject() or newObject() functions.
|
|
|
|
|
|
|
|
\section1 Script Exceptions
|
|
|
|
|
|
|
|
evaluate() can throw a script exception (e.g. due to a syntax
|
2015-04-14 23:45:03 +00:00
|
|
|
error). If it does, then evaluate() returns the value that was thrown
|
|
|
|
(typically an \c{Error} object). Use \l QJSValue::isError() to check
|
|
|
|
for exceptions.
|
|
|
|
|
|
|
|
For detailed information about the error, use \l QJSValue::toString() to
|
|
|
|
obtain an error message, and use \l QJSValue::property() to query the
|
|
|
|
properties of the \c Error object. The following properties are available:
|
|
|
|
|
|
|
|
\list
|
|
|
|
\li \c name
|
|
|
|
\li \c message
|
|
|
|
\li \c fileName
|
|
|
|
\li \c lineNumber
|
|
|
|
\li \c stack
|
|
|
|
\endlist
|
2011-08-11 11:58:53 +00:00
|
|
|
|
2012-05-28 01:56:24 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 4
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
\section1 Script Object Creation
|
|
|
|
|
|
|
|
Use newObject() to create a JavaScript object; this is the
|
|
|
|
C++ equivalent of the script statement \c{new Object()}. You can use
|
|
|
|
the object-specific functionality in QJSValue to manipulate the
|
|
|
|
script object (e.g. QJSValue::setProperty()). Similarly, use
|
2012-01-17 08:25:53 +00:00
|
|
|
newArray() to create a JavaScript array object.
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
\section1 QObject Integration
|
|
|
|
|
|
|
|
Use newQObject() to wrap a QObject (or subclass)
|
|
|
|
pointer. newQObject() returns a proxy script object; properties,
|
|
|
|
children, and signals and slots of the QObject are available as
|
|
|
|
properties of the proxy object. No binding code is needed because it
|
|
|
|
is done dynamically using the Qt meta object system.
|
|
|
|
|
2018-01-30 15:08:30 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 5
|
|
|
|
|
2016-05-29 19:33:59 +00:00
|
|
|
Use newQMetaObject() to wrap a QMetaObject; this gives you a
|
|
|
|
"script representation" of a QObject-based class. newQMetaObject()
|
|
|
|
returns a proxy script object; enum values of the class are available
|
|
|
|
as properties of the proxy object.
|
|
|
|
|
2018-01-30 15:08:30 +00:00
|
|
|
Constructors exposed to the meta-object system (using Q_INVOKABLE) can be
|
2016-05-29 19:33:59 +00:00
|
|
|
called from the script to create a new QObject instance with
|
2018-01-30 15:08:30 +00:00
|
|
|
JavaScriptOwnership. For example, given the following class definition:
|
2016-05-29 19:33:59 +00:00
|
|
|
|
2018-01-30 15:08:30 +00:00
|
|
|
\snippet code/src_script_qjsengine.cpp 7
|
|
|
|
|
|
|
|
The \c staticMetaObject for the class can be exposed to JavaScript like so:
|
|
|
|
|
|
|
|
\snippet code/src_script_qjsengine.cpp 8
|
|
|
|
|
|
|
|
Instances of the class can then be created in JavaScript:
|
|
|
|
|
|
|
|
\snippet code/src_script_qjsengine.cpp 9
|
|
|
|
|
|
|
|
\note Currently only classes using the Q_OBJECT macro are supported; it is
|
|
|
|
not possible to expose the \c staticMetaObject of a Q_GADGET class to
|
|
|
|
JavaScript.
|
2016-05-29 19:33:59 +00:00
|
|
|
|
2017-07-27 09:47:28 +00:00
|
|
|
\section2 Dynamic QObject Properties
|
2016-05-29 19:33:59 +00:00
|
|
|
|
2017-07-27 09:47:28 +00:00
|
|
|
Dynamic QObject properties are not supported. For example, the following code
|
|
|
|
will not work:
|
|
|
|
|
|
|
|
\snippet code/src_script_qjsengine.cpp 6
|
2011-08-11 11:58:53 +00:00
|
|
|
|
2015-09-10 07:11:13 +00:00
|
|
|
\section1 Extensions
|
2011-08-11 11:58:53 +00:00
|
|
|
|
2015-09-10 07:11:13 +00:00
|
|
|
QJSEngine provides a compliant ECMAScript implementation. By default,
|
|
|
|
familiar utilities like logging are not available, but they can can be
|
|
|
|
installed via the \l installExtensions() function.
|
|
|
|
|
|
|
|
\sa QJSValue, {Making Applications Scriptable},
|
|
|
|
{List of JavaScript Objects and Functions}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\enum QJSEngine::Extension
|
|
|
|
|
|
|
|
This enum is used to specify extensions to be installed via
|
|
|
|
\l installExtensions().
|
|
|
|
|
|
|
|
\value TranslationExtension Indicates that translation functions (\c qsTr(),
|
|
|
|
for example) should be installed.
|
|
|
|
|
|
|
|
\value ConsoleExtension Indicates that console functions (\c console.log(),
|
|
|
|
for example) should be installed.
|
|
|
|
|
|
|
|
\value GarbageCollectionExtension Indicates that garbage collection
|
|
|
|
functions (\c gc(), for example) should be installed.
|
|
|
|
|
|
|
|
\value AllExtensions Indicates that all extension should be installed.
|
|
|
|
|
|
|
|
\b TranslationExtension
|
|
|
|
|
|
|
|
The relation between script translation functions and C++ translation
|
|
|
|
functions is described in the following table:
|
|
|
|
|
|
|
|
\table
|
|
|
|
\header \li Script Function \li Corresponding C++ Function
|
|
|
|
\row \li qsTr() \li QObject::tr()
|
|
|
|
\row \li QT_TR_NOOP() \li QT_TR_NOOP()
|
|
|
|
\row \li qsTranslate() \li QCoreApplication::translate()
|
|
|
|
\row \li QT_TRANSLATE_NOOP() \li QT_TRANSLATE_NOOP()
|
|
|
|
\row \li qsTrId() \li qtTrId()
|
|
|
|
\row \li QT_TRID_NOOP() \li QT_TRID_NOOP()
|
|
|
|
\endtable
|
|
|
|
|
|
|
|
This flag also adds an \c arg() function to the string prototype.
|
|
|
|
|
|
|
|
For more information, see the \l {Internationalization with Qt}
|
|
|
|
documentation.
|
|
|
|
|
|
|
|
\b ConsoleExtension
|
|
|
|
|
|
|
|
The \l {Console API}{console} object implements a subset of the
|
|
|
|
\l {https://developer.mozilla.org/en-US/docs/Web/API/Console}{Console API},
|
|
|
|
which provides familiar logging functions, such as \c console.log().
|
|
|
|
|
|
|
|
The list of functions added is as follows:
|
|
|
|
|
|
|
|
\list
|
|
|
|
\li \c console.assert()
|
|
|
|
\li \c console.debug()
|
|
|
|
\li \c console.exception()
|
|
|
|
\li \c console.info()
|
|
|
|
\li \c console.log() (equivalent to \c console.debug())
|
|
|
|
\li \c console.error()
|
|
|
|
\li \c console.time()
|
|
|
|
\li \c console.timeEnd()
|
|
|
|
\li \c console.trace()
|
|
|
|
\li \c console.count()
|
|
|
|
\li \c console.warn()
|
|
|
|
\li \c {print()} (equivalent to \c console.debug())
|
|
|
|
\endlist
|
|
|
|
|
|
|
|
For more information, see the \l {Console API} documentation.
|
|
|
|
|
|
|
|
\b GarbageCollectionExtension
|
|
|
|
|
|
|
|
The \c gc() function is equivalent to calling \l collectGarbage().
|
2011-08-11 11:58:53 +00:00
|
|
|
*/
|
|
|
|
|
2011-07-29 08:25:44 +00:00
|
|
|
QT_BEGIN_NAMESPACE
|
|
|
|
|
2016-04-28 10:24:50 +00:00
|
|
|
static void checkForApplicationInstance()
|
|
|
|
{
|
|
|
|
if (!QCoreApplication::instance())
|
|
|
|
qFatal("QJSEngine: Must construct a QCoreApplication before a QJSEngine");
|
|
|
|
}
|
2011-07-29 08:25:44 +00:00
|
|
|
|
|
|
|
/*!
|
|
|
|
Constructs a QJSEngine object.
|
|
|
|
|
|
|
|
The globalObject() is initialized to have properties as described in
|
|
|
|
\l{ECMA-262}, Section 15.1.
|
|
|
|
*/
|
|
|
|
QJSEngine::QJSEngine()
|
2016-05-06 07:01:09 +00:00
|
|
|
: QJSEngine(nullptr)
|
2011-07-29 08:25:44 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Constructs a QJSEngine object with the given \a parent.
|
|
|
|
|
|
|
|
The globalObject() is initialized to have properties as described in
|
|
|
|
\l{ECMA-262}, Section 15.1.
|
|
|
|
*/
|
|
|
|
|
|
|
|
QJSEngine::QJSEngine(QObject *parent)
|
2015-01-01 15:33:04 +00:00
|
|
|
: QObject(*new QJSEnginePrivate, parent)
|
2017-12-19 16:14:15 +00:00
|
|
|
, m_v4Engine(new QV4::ExecutionEngine(this))
|
2011-07-29 08:25:44 +00:00
|
|
|
{
|
2017-12-19 16:14:15 +00:00
|
|
|
m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
|
2016-04-28 10:24:50 +00:00
|
|
|
checkForApplicationInstance();
|
|
|
|
|
2015-11-30 19:05:43 +00:00
|
|
|
QJSEnginePrivate::addToDebugServer(this);
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
2012-11-29 12:48:21 +00:00
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
*/
|
2011-11-10 08:33:27 +00:00
|
|
|
QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
|
2011-07-29 08:25:44 +00:00
|
|
|
: QObject(dd, parent)
|
2017-12-19 16:14:15 +00:00
|
|
|
, m_v4Engine(new QV4::ExecutionEngine(this))
|
2011-07-29 08:25:44 +00:00
|
|
|
{
|
2017-12-19 16:14:15 +00:00
|
|
|
m_v4Engine->v8Engine = new QV8Engine(m_v4Engine);
|
2016-04-28 10:24:50 +00:00
|
|
|
checkForApplicationInstance();
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
Destroys this QJSEngine.
|
2013-04-01 18:07:18 +00:00
|
|
|
|
|
|
|
Garbage is not collected from the persistent JS heap during QJSEngine
|
|
|
|
destruction. If you need all memory freed, call collectGarbage manually
|
|
|
|
right before destroying the QJSEngine.
|
2011-07-29 08:25:44 +00:00
|
|
|
*/
|
|
|
|
QJSEngine::~QJSEngine()
|
|
|
|
{
|
2015-11-30 19:05:43 +00:00
|
|
|
QJSEnginePrivate::removeFromDebugServer(this);
|
2017-12-19 10:14:27 +00:00
|
|
|
delete m_v4Engine->v8Engine;
|
|
|
|
delete m_v4Engine;
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
/*!
|
2017-12-19 10:14:27 +00:00
|
|
|
\fn QV4::ExecutionEngine *QJSEngine::handle() const
|
2011-08-11 11:58:53 +00:00
|
|
|
\internal
|
|
|
|
*/
|
|
|
|
|
2011-07-29 08:25:44 +00:00
|
|
|
/*!
|
|
|
|
Runs the garbage collector.
|
|
|
|
|
|
|
|
The garbage collector will attempt to reclaim memory by locating and disposing of objects that are
|
|
|
|
no longer reachable in the script environment.
|
|
|
|
|
|
|
|
Normally you don't need to call this function; the garbage collector will automatically be invoked
|
|
|
|
when the QJSEngine decides that it's wise to do so (i.e. when a certain number of new objects
|
|
|
|
have been created). However, you can call this function to explicitly request that garbage
|
|
|
|
collection should be performed as soon as possible.
|
|
|
|
*/
|
|
|
|
void QJSEngine::collectGarbage()
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
m_v4Engine->memoryManager->runGC();
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
2015-09-10 07:11:13 +00:00
|
|
|
#if QT_DEPRECATED_SINCE(5, 6)
|
|
|
|
|
2014-06-06 10:42:23 +00:00
|
|
|
/*!
|
|
|
|
\since 5.4
|
2015-09-10 07:11:13 +00:00
|
|
|
\obsolete
|
2014-06-06 10:42:23 +00:00
|
|
|
|
|
|
|
Installs translator functions on the given \a object, or on the Global
|
|
|
|
Object if no object is specified.
|
|
|
|
|
|
|
|
The relation between script translator functions and C++ translator
|
|
|
|
functions is described in the following table:
|
|
|
|
|
|
|
|
\table
|
|
|
|
\header \li Script Function \li Corresponding C++ Function
|
|
|
|
\row \li qsTr() \li QObject::tr()
|
|
|
|
\row \li QT_TR_NOOP() \li QT_TR_NOOP()
|
|
|
|
\row \li qsTranslate() \li QCoreApplication::translate()
|
|
|
|
\row \li QT_TRANSLATE_NOOP() \li QT_TRANSLATE_NOOP()
|
|
|
|
\row \li qsTrId() \li qtTrId()
|
|
|
|
\row \li QT_TRID_NOOP() \li QT_TRID_NOOP()
|
|
|
|
\endtable
|
|
|
|
|
2014-12-04 13:19:09 +00:00
|
|
|
It also adds an arg() method to the string prototype.
|
|
|
|
|
2014-06-06 10:42:23 +00:00
|
|
|
\sa {Internationalization with Qt}
|
|
|
|
*/
|
|
|
|
void QJSEngine::installTranslatorFunctions(const QJSValue &object)
|
2015-09-10 07:11:13 +00:00
|
|
|
{
|
|
|
|
installExtensions(TranslationExtension, object);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // QT_DEPRECATED_SINCE(5, 6)
|
|
|
|
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\since 5.6
|
|
|
|
|
|
|
|
Installs JavaScript \a extensions to add functionality that is not
|
|
|
|
available in a standard ECMAScript implementation.
|
|
|
|
|
|
|
|
The extensions are installed on the given \a object, or on the
|
|
|
|
\l {globalObject()}{Global Object} if no object is specified.
|
|
|
|
|
|
|
|
Several extensions can be installed at once by \c {OR}-ing the enum values:
|
|
|
|
|
|
|
|
\code
|
|
|
|
installExtensions(QJSEngine::TranslationExtension | QJSEngine::ConsoleExtension);
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\sa Extension
|
|
|
|
*/
|
|
|
|
void QJSEngine::installExtensions(QJSEngine::Extensions extensions, const QJSValue &object)
|
2014-06-06 10:42:23 +00:00
|
|
|
{
|
2015-01-14 15:22:33 +00:00
|
|
|
QV4::ExecutionEngine *otherEngine = QJSValuePrivate::engine(&object);
|
2017-12-19 10:14:27 +00:00
|
|
|
if (otherEngine && otherEngine != m_v4Engine) {
|
2015-09-10 07:11:13 +00:00
|
|
|
qWarning("QJSEngine: Trying to install extensions from a different engine");
|
2015-01-14 15:22:33 +00:00
|
|
|
return;
|
|
|
|
}
|
2015-09-10 07:11:13 +00:00
|
|
|
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::Scope scope(m_v4Engine);
|
2015-01-14 15:22:33 +00:00
|
|
|
QV4::ScopedObject obj(scope);
|
|
|
|
QV4::Value *val = QJSValuePrivate::getValue(&object);
|
|
|
|
if (val)
|
|
|
|
obj = val;
|
2014-06-06 10:42:23 +00:00
|
|
|
if (!obj)
|
2015-03-13 16:21:18 +00:00
|
|
|
obj = scope.engine->globalObject;
|
2015-09-10 07:11:13 +00:00
|
|
|
|
|
|
|
QV4::GlobalExtensions::init(obj, extensions);
|
2014-06-06 10:42:23 +00:00
|
|
|
}
|
|
|
|
|
2018-10-08 13:13:50 +00:00
|
|
|
static QUrl urlForFileName(const QString &fileName)
|
|
|
|
{
|
|
|
|
if (!fileName.startsWith(QLatin1Char(':')))
|
|
|
|
return QUrl::fromLocalFile(fileName);
|
|
|
|
|
|
|
|
QUrl url;
|
|
|
|
url.setPath(fileName.mid(1));
|
|
|
|
url.setScheme(QLatin1String("qrc"));
|
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2011-07-29 08:25:44 +00:00
|
|
|
/*!
|
|
|
|
Evaluates \a program, using \a lineNumber as the base line number,
|
|
|
|
and returns the result of the evaluation.
|
|
|
|
|
2014-05-05 13:45:54 +00:00
|
|
|
The script code will be evaluated in the context of the global object.
|
2011-07-29 08:25:44 +00:00
|
|
|
|
2015-04-14 23:45:03 +00:00
|
|
|
The evaluation of \a program can cause an \l{Script Exceptions}{exception} in the
|
2011-07-29 08:25:44 +00:00
|
|
|
engine; in this case the return value will be the exception
|
2012-08-15 11:02:31 +00:00
|
|
|
that was thrown (typically an \c{Error} object; see
|
|
|
|
QJSValue::isError()).
|
2011-07-29 08:25:44 +00:00
|
|
|
|
|
|
|
\a lineNumber is used to specify a starting line number for \a
|
2013-10-14 13:40:50 +00:00
|
|
|
program; line number information reported by the engine that pertains
|
2012-03-07 12:56:33 +00:00
|
|
|
to this evaluation will be based on this argument. For example, if
|
|
|
|
\a program consists of two lines of code, and the statement on the
|
|
|
|
second line causes a script exception, the exception line number
|
|
|
|
would be \a lineNumber plus one. When no starting line number is
|
|
|
|
specified, line numbers will be 1-based.
|
2011-07-29 08:25:44 +00:00
|
|
|
|
2013-10-14 13:40:50 +00:00
|
|
|
\a fileName is used for error reporting. For example, in error objects
|
|
|
|
the file name is accessible through the "fileName" property if it is
|
2011-07-29 08:25:44 +00:00
|
|
|
provided with this function.
|
2012-08-15 11:02:31 +00:00
|
|
|
|
|
|
|
\note If an exception was thrown and the exception value is not an
|
2013-10-14 13:40:50 +00:00
|
|
|
Error instance (i.e., QJSValue::isError() returns \c false), the
|
2012-08-15 11:02:31 +00:00
|
|
|
exception value will still be returned, but there is currently no
|
|
|
|
API for detecting that an exception did occur in this case.
|
2011-07-29 08:25:44 +00:00
|
|
|
*/
|
|
|
|
QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber)
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::ExecutionEngine *v4 = m_v4Engine;
|
2014-05-05 13:45:54 +00:00
|
|
|
QV4::Scope scope(v4);
|
2013-09-12 13:27:01 +00:00
|
|
|
QV4::ScopedValue result(scope);
|
2013-10-21 07:50:27 +00:00
|
|
|
|
2018-10-08 13:13:50 +00:00
|
|
|
QV4::Script script(v4->rootContext(), QV4::Compiler::ContextType::Global, program, urlForFileName(fileName).toString(), lineNumber);
|
2017-08-07 06:37:45 +00:00
|
|
|
script.strictMode = false;
|
|
|
|
if (v4->currentStackFrame)
|
|
|
|
script.strictMode = v4->currentStackFrame->v4Function->isStrict();
|
|
|
|
else if (v4->globalCode)
|
|
|
|
script.strictMode = v4->globalCode->isStrict();
|
2013-10-21 07:50:27 +00:00
|
|
|
script.inheritContext = true;
|
|
|
|
script.parse();
|
|
|
|
if (!scope.engine->hasException)
|
2013-09-12 13:27:01 +00:00
|
|
|
result = script.run();
|
2013-10-21 07:50:27 +00:00
|
|
|
if (scope.engine->hasException)
|
2014-11-12 12:55:55 +00:00
|
|
|
result = v4->catchException();
|
2015-08-24 14:16:56 +00:00
|
|
|
|
2017-08-08 08:56:34 +00:00
|
|
|
QJSValue retval(v4, result->asReturnedValue());
|
|
|
|
|
|
|
|
return retval;
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
2018-08-15 14:43:13 +00:00
|
|
|
/*!
|
|
|
|
Imports the module located at \a fileName and returns a module namespace object that
|
|
|
|
contains all exported variables, constants and functions as properties.
|
|
|
|
|
|
|
|
If this is the first time the module is imported in the engine, the file is loaded
|
|
|
|
from the specified location in either the local file system or the Qt resource system
|
|
|
|
and evaluated as an ECMAScript module. The file is expected to be encoded in UTF-8 text.
|
|
|
|
|
|
|
|
Subsequent imports of the same module will return the previously imported instance. Modules
|
|
|
|
are singletons and remain around until the engine is destroyed.
|
|
|
|
|
2018-09-27 14:07:34 +00:00
|
|
|
The specified \a fileName will internally be normalized using \l QFileInfo::canonicalFilePath().
|
2018-08-15 14:43:13 +00:00
|
|
|
That means that multiple imports of the same file on disk using different relative paths will
|
|
|
|
load the file only once.
|
|
|
|
|
|
|
|
\note If an exception is thrown during the loading of the module, the return value
|
|
|
|
will be the exception (typically an \c{Error} object; see QJSValue::isError()).
|
|
|
|
|
|
|
|
\since 5.12
|
|
|
|
*/
|
|
|
|
QJSValue QJSEngine::importModule(const QString &fileName)
|
|
|
|
{
|
2018-10-08 13:13:50 +00:00
|
|
|
const QUrl url = urlForFileName(QFileInfo(fileName).canonicalFilePath());
|
2018-08-15 14:43:13 +00:00
|
|
|
auto moduleUnit = m_v4Engine->loadModule(url);
|
|
|
|
if (m_v4Engine->hasException)
|
|
|
|
return QJSValue(m_v4Engine, m_v4Engine->catchException());
|
|
|
|
|
|
|
|
QV4::Scope scope(m_v4Engine);
|
|
|
|
QV4::Scoped<QV4::Module> moduleNamespace(scope, moduleUnit->instantiate(m_v4Engine));
|
|
|
|
if (m_v4Engine->hasException)
|
|
|
|
return QJSValue(m_v4Engine, m_v4Engine->catchException());
|
|
|
|
moduleUnit->evaluate();
|
|
|
|
return QJSValue(m_v4Engine, moduleNamespace->asReturnedValue());
|
|
|
|
}
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
/*!
|
|
|
|
Creates a JavaScript object of class Object.
|
|
|
|
|
|
|
|
The prototype of the created object will be the Object
|
|
|
|
prototype object.
|
|
|
|
|
|
|
|
\sa newArray(), QJSValue::setProperty()
|
|
|
|
*/
|
2011-07-29 08:25:44 +00:00
|
|
|
QJSValue QJSEngine::newObject()
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::Scope scope(m_v4Engine);
|
|
|
|
QV4::ScopedValue v(scope, m_v4Engine->newObject());
|
|
|
|
return QJSValue(m_v4Engine, v->asReturnedValue());
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
2017-08-01 14:31:53 +00:00
|
|
|
/*!
|
|
|
|
\since 5.12
|
|
|
|
Creates a JavaScript object of class Error.
|
|
|
|
|
|
|
|
The prototype of the created object will be \a errorType.
|
|
|
|
|
|
|
|
\sa newObject(), throwError(), QJSValue::isError()
|
|
|
|
*/
|
|
|
|
QJSValue QJSEngine::newErrorObject(QJSValue::ErrorType errorType, const QString &message)
|
|
|
|
{
|
|
|
|
QV4::Scope scope(m_v4Engine);
|
|
|
|
QV4::ScopedObject error(scope);
|
|
|
|
switch (errorType) {
|
|
|
|
case QJSValue::RangeError:
|
|
|
|
error = m_v4Engine->newRangeErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::SyntaxError:
|
|
|
|
error = m_v4Engine->newSyntaxErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::TypeError:
|
|
|
|
error = m_v4Engine->newTypeErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::URIError:
|
|
|
|
error = m_v4Engine->newURIErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::ReferenceError:
|
|
|
|
error = m_v4Engine->newReferenceErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::EvalError:
|
|
|
|
error = m_v4Engine->newEvalErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::GenericError:
|
|
|
|
error = m_v4Engine->newErrorObject(message);
|
|
|
|
break;
|
|
|
|
case QJSValue::NoError:
|
|
|
|
return QJSValue::UndefinedValue;
|
|
|
|
}
|
|
|
|
return QJSValue(m_v4Engine, error->asReturnedValue());
|
|
|
|
}
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
/*!
|
|
|
|
Creates a JavaScript object of class Array with the given \a length.
|
|
|
|
|
|
|
|
\sa newObject()
|
|
|
|
*/
|
2011-07-29 08:25:44 +00:00
|
|
|
QJSValue QJSEngine::newArray(uint length)
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::Scope scope(m_v4Engine);
|
|
|
|
QV4::ScopedArrayObject array(scope, m_v4Engine->newArrayObject());
|
2013-05-03 20:40:43 +00:00
|
|
|
if (length < 0x1000)
|
|
|
|
array->arrayReserve(length);
|
|
|
|
array->setArrayLengthUnchecked(length);
|
2017-12-19 10:14:27 +00:00
|
|
|
return QJSValue(m_v4Engine, array.asReturnedValue());
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
2011-08-11 11:58:53 +00:00
|
|
|
Creates a JavaScript object that wraps the given QObject \a
|
2012-11-29 12:48:21 +00:00
|
|
|
object, using JavaScriptOwnership.
|
2011-07-29 08:25:44 +00:00
|
|
|
|
|
|
|
Signals and slots, properties and children of \a object are
|
2011-08-11 11:58:53 +00:00
|
|
|
available as properties of the created QJSValue.
|
2011-07-29 08:25:44 +00:00
|
|
|
|
2012-01-18 05:53:39 +00:00
|
|
|
If \a object is a null pointer, this function returns a null value.
|
2011-07-29 08:25:44 +00:00
|
|
|
|
|
|
|
If a default prototype has been registered for the \a object's class
|
|
|
|
(or its superclass, recursively), the prototype of the new script
|
|
|
|
object will be set to be that default prototype.
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
If the given \a object is deleted outside of the engine's control, any
|
|
|
|
attempt to access the deleted QObject's members through the JavaScript
|
2011-07-29 08:25:44 +00:00
|
|
|
wrapper object (either by script code or C++) will result in a
|
2015-04-14 23:45:03 +00:00
|
|
|
\l{Script Exceptions}{script exception}.
|
2011-07-29 08:25:44 +00:00
|
|
|
|
2012-05-22 13:13:08 +00:00
|
|
|
\sa QJSValue::toQObject()
|
2011-07-29 08:25:44 +00:00
|
|
|
*/
|
|
|
|
QJSValue QJSEngine::newQObject(QObject *object)
|
|
|
|
{
|
|
|
|
Q_D(QJSEngine);
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::ExecutionEngine *v4 = m_v4Engine;
|
2013-09-12 20:37:41 +00:00
|
|
|
QV4::Scope scope(v4);
|
2014-02-28 15:19:10 +00:00
|
|
|
if (object) {
|
|
|
|
QQmlData *ddata = QQmlData::get(object, true);
|
|
|
|
if (!ddata || !ddata->explicitIndestructibleSet)
|
|
|
|
QQmlEngine::setObjectOwnership(object, QQmlEngine::JavaScriptOwnership);
|
|
|
|
}
|
2013-09-12 20:37:41 +00:00
|
|
|
QV4::ScopedValue v(scope, QV4::QObjectWrapper::wrap(v4, object));
|
2015-01-15 20:28:01 +00:00
|
|
|
return QJSValue(v4, v->asReturnedValue());
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
2016-05-29 19:33:59 +00:00
|
|
|
/*!
|
|
|
|
\since 5.8
|
|
|
|
|
|
|
|
Creates a JavaScript object that wraps the given QMetaObject
|
2017-01-26 14:19:18 +00:00
|
|
|
The \a metaObject must outlive the script engine. It is recommended to only
|
2016-05-29 19:33:59 +00:00
|
|
|
use this method with static metaobjects.
|
|
|
|
|
|
|
|
|
|
|
|
When called as a constructor, a new instance of the class will be created.
|
|
|
|
Only constructors exposed by Q_INVOKABLE will be visible from the script engine.
|
|
|
|
|
2018-01-30 15:08:30 +00:00
|
|
|
\sa newQObject(), {QObject Integration}
|
2016-05-29 19:33:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
QJSValue QJSEngine::newQMetaObject(const QMetaObject* metaObject) {
|
|
|
|
Q_D(QJSEngine);
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::ExecutionEngine *v4 = m_v4Engine;
|
2016-05-29 19:33:59 +00:00
|
|
|
QV4::Scope scope(v4);
|
|
|
|
QV4::ScopedValue v(scope, QV4::QMetaObjectWrapper::create(v4, metaObject));
|
|
|
|
return QJSValue(v4, v->asReturnedValue());
|
|
|
|
}
|
|
|
|
|
2018-02-05 10:21:32 +00:00
|
|
|
/*! \fn template <typename T> QJSValue QJSEngine::newQMetaObject()
|
2016-05-29 19:33:59 +00:00
|
|
|
|
|
|
|
\since 5.8
|
|
|
|
Creates a JavaScript object that wraps the static QMetaObject associated
|
|
|
|
with class \c{T}.
|
|
|
|
|
2018-01-30 15:08:30 +00:00
|
|
|
\sa newQObject(), {QObject Integration}
|
2016-05-29 19:33:59 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2011-08-11 11:58:53 +00:00
|
|
|
/*!
|
|
|
|
Returns this engine's Global Object.
|
|
|
|
|
|
|
|
By default, the Global Object contains the built-in objects that are
|
|
|
|
part of \l{ECMA-262}, such as Math, Date and String. Additionally,
|
|
|
|
you can set properties of the Global Object to make your own
|
|
|
|
extensions available to all script code. Non-local variables in
|
|
|
|
script code will be created as properties of the Global Object, as
|
|
|
|
well as local variables in global code.
|
|
|
|
*/
|
2011-07-29 08:25:44 +00:00
|
|
|
QJSValue QJSEngine::globalObject() const
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::Scope scope(m_v4Engine);
|
|
|
|
QV4::ScopedValue v(scope, m_v4Engine->globalObject);
|
|
|
|
return QJSValue(m_v4Engine, v->asReturnedValue());
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \internal
|
|
|
|
* used by QJSEngine::toScriptValue
|
|
|
|
*/
|
|
|
|
QJSValue QJSEngine::create(int type, const void *ptr)
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
QV4::Scope scope(m_v4Engine);
|
2015-01-02 14:07:35 +00:00
|
|
|
QV4::ScopedValue v(scope, scope.engine->metaTypeToJS(type, ptr));
|
2017-12-19 10:14:27 +00:00
|
|
|
return QJSValue(m_v4Engine, v->asReturnedValue());
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*!
|
|
|
|
\internal
|
|
|
|
convert \a value to \a type, store the result in \a ptr
|
|
|
|
*/
|
|
|
|
bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
|
|
|
|
{
|
2015-01-14 15:22:33 +00:00
|
|
|
QV4::ExecutionEngine *v4 = QJSValuePrivate::engine(&value);
|
2015-01-12 20:55:51 +00:00
|
|
|
QV4::Value scratch;
|
2015-01-14 15:22:33 +00:00
|
|
|
QV4::Value *val = QJSValuePrivate::valueForData(&value, &scratch);
|
2015-01-12 20:55:51 +00:00
|
|
|
if (v4) {
|
|
|
|
QV4::Scope scope(v4);
|
|
|
|
QV4::ScopedValue v(scope, *val);
|
2015-01-02 14:07:35 +00:00
|
|
|
return scope.engine->metaTypeFromJS(v, type, ptr);
|
2015-01-12 20:55:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!val) {
|
2015-01-14 15:22:33 +00:00
|
|
|
QVariant *variant = QJSValuePrivate::getVariant(&value);
|
|
|
|
Q_ASSERT(variant);
|
|
|
|
|
|
|
|
if (variant->userType() == QMetaType::QString) {
|
|
|
|
QString string = variant->toString();
|
2014-09-10 15:13:10 +00:00
|
|
|
// have a string based value without engine. Do conversion manually
|
|
|
|
if (type == QMetaType::Bool) {
|
|
|
|
*reinterpret_cast<bool*>(ptr) = string.length() != 0;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (type == QMetaType::QString) {
|
|
|
|
*reinterpret_cast<QString*>(ptr) = string;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
double d = QV4::RuntimeHelpers::stringToNumber(string);
|
|
|
|
switch (type) {
|
2013-11-26 09:46:44 +00:00
|
|
|
case QMetaType::Int:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::UInt:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::LongLong:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::ULongLong:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::Double:
|
|
|
|
*reinterpret_cast<double*>(ptr) = d;
|
|
|
|
return true;
|
|
|
|
case QMetaType::Float:
|
|
|
|
*reinterpret_cast<float*>(ptr) = d;
|
|
|
|
return true;
|
|
|
|
case QMetaType::Short:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::UShort:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::Char:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::UChar:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
case QMetaType::QChar:
|
2018-09-11 09:07:32 +00:00
|
|
|
*reinterpret_cast<QChar*>(ptr) = QV4::Value::toUInt32(d);
|
2013-11-26 09:46:44 +00:00
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
2014-09-10 15:13:10 +00:00
|
|
|
}
|
|
|
|
} else {
|
2015-01-14 15:22:33 +00:00
|
|
|
return QMetaType::convert(&variant->data_ptr(), variant->userType(), ptr, type);
|
2013-11-26 09:46:44 +00:00
|
|
|
}
|
2015-01-12 20:55:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Q_ASSERT(val);
|
|
|
|
|
|
|
|
switch (type) {
|
|
|
|
case QMetaType::Bool:
|
|
|
|
*reinterpret_cast<bool*>(ptr) = val->toBoolean();
|
|
|
|
return true;
|
|
|
|
case QMetaType::Int:
|
|
|
|
*reinterpret_cast<int*>(ptr) = val->toInt32();
|
|
|
|
return true;
|
|
|
|
case QMetaType::UInt:
|
|
|
|
*reinterpret_cast<uint*>(ptr) = val->toUInt32();
|
|
|
|
return true;
|
|
|
|
case QMetaType::LongLong:
|
|
|
|
*reinterpret_cast<qlonglong*>(ptr) = val->toInteger();
|
|
|
|
return true;
|
|
|
|
case QMetaType::ULongLong:
|
|
|
|
*reinterpret_cast<qulonglong*>(ptr) = val->toInteger();
|
|
|
|
return true;
|
|
|
|
case QMetaType::Double:
|
|
|
|
*reinterpret_cast<double*>(ptr) = val->toNumber();
|
|
|
|
return true;
|
|
|
|
case QMetaType::QString:
|
|
|
|
*reinterpret_cast<QString*>(ptr) = val->toQStringNoThrow();
|
|
|
|
return true;
|
|
|
|
case QMetaType::Float:
|
|
|
|
*reinterpret_cast<float*>(ptr) = val->toNumber();
|
|
|
|
return true;
|
|
|
|
case QMetaType::Short:
|
|
|
|
*reinterpret_cast<short*>(ptr) = val->toInt32();
|
|
|
|
return true;
|
|
|
|
case QMetaType::UShort:
|
|
|
|
*reinterpret_cast<unsigned short*>(ptr) = val->toUInt16();
|
|
|
|
return true;
|
|
|
|
case QMetaType::Char:
|
|
|
|
*reinterpret_cast<char*>(ptr) = val->toInt32();
|
|
|
|
return true;
|
|
|
|
case QMetaType::UChar:
|
|
|
|
*reinterpret_cast<unsigned char*>(ptr) = val->toUInt16();
|
|
|
|
return true;
|
|
|
|
case QMetaType::QChar:
|
|
|
|
*reinterpret_cast<QChar*>(ptr) = val->toUInt16();
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
2011-07-29 08:25:44 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-05 10:21:32 +00:00
|
|
|
/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value)
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
Creates a QJSValue with the given \a value.
|
|
|
|
|
2015-08-25 12:52:27 +00:00
|
|
|
\sa fromScriptValue()
|
2011-08-11 11:58:53 +00:00
|
|
|
*/
|
|
|
|
|
2018-02-05 10:21:32 +00:00
|
|
|
/*! \fn template <typename T> T QJSEngine::fromScriptValue(const QJSValue &value)
|
2011-08-11 11:58:53 +00:00
|
|
|
|
|
|
|
Returns the given \a value converted to the template type \c{T}.
|
|
|
|
|
|
|
|
\sa toScriptValue()
|
|
|
|
*/
|
2011-07-29 08:25:44 +00:00
|
|
|
|
2018-06-26 15:35:06 +00:00
|
|
|
/*!
|
|
|
|
Throws a run-time error (exception) with the given \a message.
|
|
|
|
|
|
|
|
This method is the C++ counterpart of a \c throw() expression in
|
|
|
|
JavaScript. It enables C++ code to report run-time errors to QJSEngine.
|
|
|
|
Therefore it should only be called from C++ code that was invoked by a
|
|
|
|
JavaScript function through QJSEngine.
|
|
|
|
|
|
|
|
When returning from C++, the engine will interrupt the normal flow of
|
|
|
|
execution and call the the next pre-registered exception handler with
|
|
|
|
an error object that contains the given \a message. The error object
|
|
|
|
will point to the location of the top-most context on the JavaScript
|
|
|
|
caller stack; specifically, it will have properties \c lineNumber,
|
|
|
|
\c fileName and \c stack. These properties are described in
|
|
|
|
\l{Script Exceptions}.
|
|
|
|
|
|
|
|
In the following example a C++ method in \e FileAccess.cpp throws an error
|
|
|
|
in \e qmlFile.qml at the position where \c readFileAsText() is called:
|
|
|
|
|
|
|
|
\code
|
|
|
|
// qmlFile.qml
|
|
|
|
function someFunction() {
|
|
|
|
...
|
|
|
|
var text = FileAccess.readFileAsText("/path/to/file.txt");
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\code
|
|
|
|
// FileAccess.cpp
|
|
|
|
// Assuming that FileAccess is a QObject-derived class that has been
|
|
|
|
// registered as a singleton type and provides an invokable method
|
|
|
|
// readFileAsText()
|
|
|
|
|
|
|
|
QJSValue FileAccess::readFileAsText(const QString & filePath) {
|
|
|
|
QFile file(filePath);
|
|
|
|
|
|
|
|
if (!file.open(QIODevice::ReadOnly)) {
|
|
|
|
jsEngine->throwError(file.errorString());
|
|
|
|
return QString();
|
|
|
|
}
|
|
|
|
|
|
|
|
...
|
|
|
|
return content;
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
It is also possible to catch the thrown error in JavaScript:
|
|
|
|
\code
|
|
|
|
// qmlFile.qml
|
|
|
|
function someFunction() {
|
|
|
|
...
|
|
|
|
var text;
|
|
|
|
try {
|
|
|
|
text = FileAccess.readFileAsText("/path/to/file.txt");
|
|
|
|
} catch (error) {
|
|
|
|
console.warn("In " + error.fileName + ":" + "error.lineNumber" +
|
|
|
|
": " + error.message);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
2018-10-26 11:25:22 +00:00
|
|
|
If you need a more specific run-time error to describe an exception, you can use the
|
|
|
|
\l {QJSEngine::}{throwError(QJSValue::ErrorType errorType, const QString &message)}
|
|
|
|
overload.
|
|
|
|
|
2018-06-26 15:35:06 +00:00
|
|
|
\since Qt 5.12
|
|
|
|
\sa {Script Exceptions}
|
|
|
|
*/
|
|
|
|
void QJSEngine::throwError(const QString &message)
|
|
|
|
{
|
|
|
|
m_v4Engine->throwError(message);
|
|
|
|
}
|
2014-11-20 08:07:52 +00:00
|
|
|
|
2017-08-01 14:31:53 +00:00
|
|
|
/*!
|
2018-10-26 11:25:22 +00:00
|
|
|
\overload throwError()
|
|
|
|
|
2017-08-01 14:31:53 +00:00
|
|
|
Throws a run-time error (exception) with the given \a errorType and
|
|
|
|
\a message.
|
|
|
|
|
|
|
|
\code
|
|
|
|
// Assuming that DataEntry is a QObject-derived class that has been
|
|
|
|
// registered as a singleton type and provides an invokable method
|
|
|
|
// setAge().
|
|
|
|
|
|
|
|
void DataEntry::setAge(int age) {
|
|
|
|
if (age < 0 || age > 200) {
|
|
|
|
jsEngine->throwError(QJSValue::RangeError,
|
|
|
|
"Age must be between 0 and 200");
|
|
|
|
}
|
|
|
|
...
|
|
|
|
}
|
|
|
|
\endcode
|
|
|
|
|
|
|
|
\since Qt 5.12
|
|
|
|
\sa {Script Exceptions}, newErrorObject()
|
|
|
|
*/
|
|
|
|
void QJSEngine::throwError(QJSValue::ErrorType errorType, const QString &message)
|
|
|
|
{
|
|
|
|
QV4::Scope scope(m_v4Engine);
|
|
|
|
QJSValue error = newErrorObject(errorType, message);
|
|
|
|
QV4::ScopedObject e(scope, QJSValuePrivate::getValue(&error));
|
|
|
|
if (!e)
|
|
|
|
return;
|
|
|
|
m_v4Engine->throwError(e);
|
|
|
|
}
|
|
|
|
|
2014-11-20 09:42:34 +00:00
|
|
|
QJSEnginePrivate *QJSEnginePrivate::get(QV4::ExecutionEngine *e)
|
|
|
|
{
|
2017-12-19 10:14:27 +00:00
|
|
|
return e->jsEngine()->d_func();
|
2014-11-20 09:42:34 +00:00
|
|
|
}
|
|
|
|
|
2014-11-20 08:07:52 +00:00
|
|
|
QJSEnginePrivate::~QJSEnginePrivate()
|
|
|
|
{
|
2017-06-26 12:52:22 +00:00
|
|
|
QQmlMetaType::freeUnusedTypesAndCaches();
|
2014-11-20 08:07:52 +00:00
|
|
|
}
|
|
|
|
|
2015-11-30 19:05:43 +00:00
|
|
|
void QJSEnginePrivate::addToDebugServer(QJSEngine *q)
|
|
|
|
{
|
|
|
|
if (QCoreApplication::instance()->thread() != q->thread())
|
|
|
|
return;
|
|
|
|
|
|
|
|
QQmlDebugConnector *server = QQmlDebugConnector::instance();
|
|
|
|
if (!server || server->hasEngine(q))
|
|
|
|
return;
|
|
|
|
|
|
|
|
server->open();
|
|
|
|
server->addEngine(q);
|
|
|
|
}
|
|
|
|
|
|
|
|
void QJSEnginePrivate::removeFromDebugServer(QJSEngine *q)
|
|
|
|
{
|
|
|
|
QQmlDebugConnector *server = QQmlDebugConnector::instance();
|
|
|
|
if (server && server->hasEngine(q))
|
|
|
|
server->removeEngine(q);
|
|
|
|
}
|
|
|
|
|
2015-01-12 12:07:38 +00:00
|
|
|
/*!
|
|
|
|
\since 5.5
|
|
|
|
\relates QJSEngine
|
|
|
|
|
|
|
|
Returns the QJSEngine associated with \a object, if any.
|
|
|
|
|
|
|
|
This function is useful if you have exposed a QObject to the JavaScript environment
|
|
|
|
and later in your program would like to regain access. It does not require you to
|
|
|
|
keep the wrapper around that was returned from QJSEngine::newQObject().
|
|
|
|
*/
|
|
|
|
QJSEngine *qjsEngine(const QObject *object)
|
|
|
|
{
|
|
|
|
QQmlData *data = QQmlData::get(object, false);
|
|
|
|
if (!data || data->jsWrapper.isNullOrUndefined())
|
2018-02-21 09:41:54 +00:00
|
|
|
return nullptr;
|
2015-01-12 12:07:38 +00:00
|
|
|
return data->jsWrapper.engine()->jsEngine();
|
|
|
|
}
|
|
|
|
|
2011-07-29 08:25:44 +00:00
|
|
|
QT_END_NAMESPACE
|
|
|
|
|
|
|
|
#include "moc_qjsengine.cpp"
|