aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsapi/qjsengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/jsapi/qjsengine.cpp')
-rw-r--r--src/qml/jsapi/qjsengine.cpp481
1 files changed, 349 insertions, 132 deletions
diff --git a/src/qml/jsapi/qjsengine.cpp b/src/qml/jsapi/qjsengine.cpp
index dbb35cdde8..8346ef5d84 100644
--- a/src/qml/jsapi/qjsengine.cpp
+++ b/src/qml/jsapi/qjsengine.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtQml module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** 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
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** 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.
-**
-** 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.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qjsengine.h"
#include "qjsengine_p.h"
@@ -48,11 +12,14 @@
#include "private/qv4globalobject_p.h"
#include "private/qv4script_p.h"
#include "private/qv4runtime_p.h"
+#include <private/qv4dateobject_p.h>
#include <private/qqmlbuiltinfunctions_p.h>
#include <private/qqmldebugconnector_p.h>
#include <private/qv4qobjectwrapper_p.h>
+#include <private/qv4qmetaobjectwrapper_p.h>
#include <private/qv4stackframe_p.h>
#include <private/qv4module_p.h>
+#include <private/qv4symbol_p.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qmetaobject.h>
@@ -149,6 +116,46 @@ Q_DECLARE_METATYPE(QList<int>)
}
\endcode
+ Modules don't have to be files. They can be values registered with
+ QJSEngine::registerModule():
+
+ \code
+ import version from "version";
+
+ export function getVersion()
+ {
+ return version;
+ }
+ \endcode
+
+ \code
+ QJSValue version(610);
+ myEngine.registerModule("version", version);
+ QJSValue module = myEngine.importModule("./myprint.mjs");
+ QJSValue getVersion = module.property("getVersion");
+ QJSValue result = getVersion.call();
+ \endcode
+
+ Named exports are supported, but because they are treated as members of an
+ object, the default export must be an ECMAScript object. Most of the newXYZ
+ functions in QJSValue will return an object.
+
+ \code
+ QJSValue name("Qt6");
+ QJSValue obj = myEngine.newObject();
+ obj.setProperty("name", name);
+ myEngine.registerModule("info", obj);
+ \endcode
+
+ \code
+ import { name } from "info";
+
+ export function getName()
+ {
+ return name;
+ }
+ \endcode
+
\section1 Engine Configuration
The globalObject() function returns the \b {Global Object}
@@ -237,7 +244,7 @@ Q_DECLARE_METATYPE(QList<int>)
\section1 Extensions
QJSEngine provides a compliant ECMAScript implementation. By default,
- familiar utilities like logging are not available, but they can can be
+ familiar utilities like logging are not available, but they can be
installed via the \l installExtensions() function.
\sa QJSValue, {Making Applications Scriptable},
@@ -339,11 +346,8 @@ QJSEngine::QJSEngine()
*/
QJSEngine::QJSEngine(QObject *parent)
- : QObject(*new QJSEnginePrivate, parent)
- , m_v4Engine(new QV4::ExecutionEngine(this))
+ : QJSEngine(*new QJSEnginePrivate, parent)
{
- checkForApplicationInstance();
-
QJSEnginePrivate::addToDebugServer(this);
}
@@ -361,11 +365,12 @@ QJSEngine::QJSEngine(QJSEnginePrivate &dd, QObject *parent)
Destroys this QJSEngine.
Garbage is not collected from the persistent JS heap during QJSEngine
- destruction. If you need all memory freed, call collectGarbage manually
+ destruction. If you need all memory freed, call collectGarbage() manually
right before destroying the QJSEngine.
*/
QJSEngine::~QJSEngine()
{
+ m_v4Engine->inShutdown = true;
QJSEnginePrivate::removeFromDebugServer(this);
delete m_v4Engine;
}
@@ -385,7 +390,11 @@ QJSEngine::~QJSEngine()
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.
-*/
+
+
+ \sa {Garbage Collection}
+ \sa {Qt::}{gc()}
+ */
void QJSEngine::collectGarbage()
{
m_v4Engine->memoryManager->runGC();
@@ -437,7 +446,7 @@ void QJSEngine::installExtensions(QJSEngine::Extensions extensions, const QJSVal
*/
void QJSEngine::setInterrupted(bool interrupted)
{
- m_v4Engine->isInterrupted = interrupted;
+ m_v4Engine->isInterrupted.storeRelaxed(interrupted);
}
/*!
@@ -448,7 +457,7 @@ void QJSEngine::setInterrupted(bool interrupted)
*/
bool QJSEngine::isInterrupted() const
{
- return m_v4Engine->isInterrupted.loadAcquire();
+ return m_v4Engine->isInterrupted.loadRelaxed();
}
static QUrl urlForFileName(const QString &fileName)
@@ -468,6 +477,9 @@ static QUrl urlForFileName(const QString &fileName)
The script code will be evaluated in the context of the global object.
+ \note If you need to evaluate inside a QML context, use \l QQmlExpression
+ instead.
+
The evaluation of \a program can cause an \l{Script Exceptions}{exception} in the
engine; in this case the return value will be the exception
that was thrown (typically an \c{Error} object; see
@@ -498,6 +510,8 @@ static QUrl urlForFileName(const QString &fileName)
exception value will still be returned. Use \c exceptionStackTrace->isEmpty()
to distinguish whether the value was a normal or an exceptional return
value.
+
+ \sa QQmlExpression::evaluate
*/
QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, int lineNumber, QStringList *exceptionStackTrace)
{
@@ -513,24 +527,24 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
script.strictMode = v4->globalCode->isStrict();
script.inheritContext = true;
script.parse();
- if (!scope.engine->hasException)
+ if (!scope.hasException())
result = script.run();
if (exceptionStackTrace)
exceptionStackTrace->clear();
- if (scope.engine->hasException) {
+ if (scope.hasException()) {
QV4::StackTrace trace;
result = v4->catchException(&trace);
if (exceptionStackTrace) {
for (auto &&frame: trace)
- exceptionStackTrace->push_back(QString::fromLatin1("%1:%2:%3:%4").arg(
+ exceptionStackTrace->push_back(QLatin1StringView("%1:%2:%3:%4").arg(
frame.function,
- QString::number(frame.line),
+ QString::number(qAbs(frame.line)),
QString::number(frame.column),
frame.source)
);
}
}
- if (v4->isInterrupted.loadAcquire())
+ if (v4->isInterrupted.loadRelaxed())
result = v4->newErrorObject(QStringLiteral("Interrupted"));
return QJSValuePrivate::fromReturnedValue(result->asReturnedValue());
@@ -554,25 +568,68 @@ QJSValue QJSEngine::evaluate(const QString& program, const QString& fileName, in
\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()).
+ \sa registerModule()
+
\since 5.12
*/
QJSValue QJSEngine::importModule(const QString &fileName)
{
const QUrl url = urlForFileName(QFileInfo(fileName).canonicalFilePath());
- auto moduleUnit = m_v4Engine->loadModule(url);
+ const auto module = m_v4Engine->loadModule(url);
if (m_v4Engine->hasException)
return QJSValuePrivate::fromReturnedValue(m_v4Engine->catchException());
QV4::Scope scope(m_v4Engine);
- QV4::Scoped<QV4::Module> moduleNamespace(scope, moduleUnit->instantiate(m_v4Engine));
- if (m_v4Engine->hasException)
- return QJSValuePrivate::fromReturnedValue(m_v4Engine->catchException());
- moduleUnit->evaluate();
- if (!m_v4Engine->isInterrupted.loadAcquire())
- return QJSValuePrivate::fromReturnedValue(moduleNamespace->asReturnedValue());
+ if (const auto compiled = module.compiled) {
+ QV4::Scoped<QV4::Module> moduleNamespace(scope, compiled->instantiate());
+ if (m_v4Engine->hasException)
+ return QJSValuePrivate::fromReturnedValue(m_v4Engine->catchException());
+ compiled->evaluate();
+ if (!m_v4Engine->isInterrupted.loadRelaxed())
+ return QJSValuePrivate::fromReturnedValue(moduleNamespace->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(
+ m_v4Engine->newErrorObject(QStringLiteral("Interrupted"))->asReturnedValue());
+ }
+
+ // If there is neither a native nor a compiled module, we should have seen an exception
+ Q_ASSERT(module.native);
- return QJSValuePrivate::fromReturnedValue(
- m_v4Engine->newErrorObject(QStringLiteral("Interrupted"))->asReturnedValue());
+ return QJSValuePrivate::fromReturnedValue(module.native->asReturnedValue());
+}
+
+/*!
+ Registers a QJSValue to serve as a module. After this function is called,
+ all modules that import \a moduleName will import the value of \a value
+ instead of loading \a moduleName from the filesystem.
+
+ Any valid QJSValue can be registered, but named exports (i.e.
+ \c {import { name } from "info"} are treated as members of an object, so
+ the default export must be created with one of the newXYZ methods of
+ QJSEngine.
+
+ Because this allows modules that do not exist on the filesystem to be imported,
+ scripting applications can use this to provide built-in modules, similar to
+ Node.js.
+
+ Returns \c true on success, \c false otherwise.
+
+ \note The QJSValue \a value is not called or read until it is used by another module.
+ This means that there is no code to evaluate, so no errors will be seen until
+ another module throws an exception while trying to load this module.
+
+ \warning Attempting to access a named export from a QJSValue that is not an
+ object will trigger a \l{Script Exceptions}{exception}.
+
+ \sa importModule()
+ */
+bool QJSEngine::registerModule(const QString &moduleName, const QJSValue &value)
+{
+ QV4::Scope scope(m_v4Engine);
+ QV4::ScopedValue v4Value(scope, QJSValuePrivate::asReturnedValue(&value));
+ m_v4Engine->registerNativeModule(QUrl(moduleName), v4Value);
+ if (m_v4Engine->hasException)
+ return false;
+ return true;
}
/*!
@@ -591,6 +648,22 @@ QJSValue QJSEngine::newObject()
}
/*!
+ \since 6.2
+
+ Creates a JavaScript object of class Symbol, with value \a name.
+
+ The prototype of the created object will be the Symbol prototype object.
+
+ \sa newObject()
+*/
+QJSValue QJSEngine::newSymbol(const QString &name)
+{
+ QV4::Scope scope(m_v4Engine);
+ QV4::ScopedValue v(scope, QV4::Symbol::create(m_v4Engine, u'@' + name));
+ return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
+}
+
+/*!
\since 5.12
Creates a JavaScript object of class Error, with \a message as the error
@@ -728,6 +801,13 @@ QJSValue QJSEngine::globalObject() const
return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
+QJSPrimitiveValue QJSEngine::createPrimitive(QMetaType type, const void *ptr)
+{
+ QV4::Scope scope(m_v4Engine);
+ QV4::ScopedValue v(scope, m_v4Engine->metaTypeToJS(type, ptr));
+ return QV4::ExecutionEngine::createPrimitive(v);
+}
+
QJSManagedValue QJSEngine::createManaged(QMetaType type, const void *ptr)
{
QJSManagedValue result(m_v4Engine);
@@ -746,92 +826,224 @@ QJSValue QJSEngine::create(QMetaType type, const void *ptr)
return QJSValuePrivate::fromReturnedValue(v->asReturnedValue());
}
+bool QJSEngine::convertPrimitive(const QJSPrimitiveValue &value, QMetaType type, void *ptr)
+{
+ switch (value.type()) {
+ case QJSPrimitiveValue::Undefined:
+ return QV4::ExecutionEngine::metaTypeFromJS(QV4::Value::undefinedValue(), type, ptr);
+ case QJSPrimitiveValue::Null:
+ return QV4::ExecutionEngine::metaTypeFromJS(QV4::Value::nullValue(), type, ptr);
+ case QJSPrimitiveValue::Boolean:
+ return QV4::ExecutionEngine::metaTypeFromJS(QV4::Value::fromBoolean(value.toBoolean()), type, ptr);
+ case QJSPrimitiveValue::Integer:
+ return QV4::ExecutionEngine::metaTypeFromJS(QV4::Value::fromInt32(value.toInteger()), type, ptr);
+ case QJSPrimitiveValue::Double:
+ return QV4::ExecutionEngine::metaTypeFromJS(QV4::Value::fromDouble(value.toDouble()), type, ptr);
+ case QJSPrimitiveValue::String:
+ return convertString(value.toString(), type, ptr);
+ }
+
+ Q_UNREACHABLE_RETURN(false);
+}
+
bool QJSEngine::convertManaged(const QJSManagedValue &value, int type, void *ptr)
{
+ return convertManaged(value, QMetaType(type), ptr);
+}
+
+bool QJSEngine::convertManaged(const QJSManagedValue &value, QMetaType type, void *ptr)
+{
return QV4::ExecutionEngine::metaTypeFromJS(*value.d, type, ptr);
}
+bool QJSEngine::convertString(const QString &string, QMetaType metaType, void *ptr)
+{
+ // have a string based value without engine. Do conversion manually
+ if (metaType == QMetaType::fromType<bool>()) {
+ *reinterpret_cast<bool*>(ptr) = string.size() != 0;
+ return true;
+ }
+ if (metaType == QMetaType::fromType<QString>()) {
+ *reinterpret_cast<QString*>(ptr) = string;
+ return true;
+ }
+ if (metaType == QMetaType::fromType<QUrl>()) {
+ *reinterpret_cast<QUrl *>(ptr) = QUrl(string);
+ return true;
+ }
+
+ double d = QV4::RuntimeHelpers::stringToNumber(string);
+ switch (metaType.id()) {
+ case QMetaType::Int:
+ *reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
+ return true;
+ case QMetaType::UInt:
+ *reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ case QMetaType::Long:
+ *reinterpret_cast<long*>(ptr) = QV4::Value::toInteger(d);
+ return true;
+ case QMetaType::ULong:
+ *reinterpret_cast<ulong*>(ptr) = QV4::Value::toInteger(d);
+ return true;
+ case QMetaType::LongLong:
+ *reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
+ return true;
+ case QMetaType::ULongLong:
+ *reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
+ 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:
+ *reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
+ return true;
+ case QMetaType::UShort:
+ *reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ case QMetaType::Char:
+ *reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
+ return true;
+ case QMetaType::UChar:
+ *reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ case QMetaType::QChar:
+ *reinterpret_cast<QChar*>(ptr) = QChar(QV4::Value::toUInt32(d));
+ return true;
+ case QMetaType::Char16:
+ *reinterpret_cast<char16_t *>(ptr) = QV4::Value::toUInt32(d);
+ return true;
+ default:
+ return false;
+ }
+}
+
/*!
\internal
convert \a value to \a type, store the result in \a ptr
*/
-bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
+bool QJSEngine::convertV2(const QJSValue &value, QMetaType metaType, void *ptr)
{
- if (const QString *string = QJSValuePrivate::asQString(&value)) {
- // 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;
- }
- if (type == QMetaType::QUrl) {
- *reinterpret_cast<QUrl *>(ptr) = QUrl(*string);
- return true;
- }
+ if (const QString *string = QJSValuePrivate::asQString(&value))
+ return convertString(*string, metaType, ptr);
- double d = QV4::RuntimeHelpers::stringToNumber(*string);
- switch (type) {
- case QMetaType::Int:
- *reinterpret_cast<int*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UInt:
- *reinterpret_cast<uint*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::LongLong:
- *reinterpret_cast<qlonglong*>(ptr) = QV4::Value::toInteger(d);
- return true;
- case QMetaType::ULongLong:
- *reinterpret_cast<qulonglong*>(ptr) = QV4::Value::toInteger(d);
- 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:
- *reinterpret_cast<short*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UShort:
- *reinterpret_cast<unsigned short*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::Char:
- *reinterpret_cast<char*>(ptr) = QV4::Value::toInt32(d);
- return true;
- case QMetaType::UChar:
- *reinterpret_cast<unsigned char*>(ptr) = QV4::Value::toUInt32(d);
- return true;
- case QMetaType::QChar:
- *reinterpret_cast<QChar*>(ptr) = QChar(QV4::Value::toUInt32(d));
- return true;
- case QMetaType::Char16:
- *reinterpret_cast<char16_t *>(ptr) = QV4::Value::toUInt32(d);
- return true;
- default:
- return false;
- }
- }
+ // Does not need scoping since QJSValue still holds on to the value.
+ return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), metaType, ptr);
+}
+
+bool QJSEngine::convertVariant(const QVariant &value, QMetaType metaType, void *ptr)
+{
+ // TODO: We could probably avoid creating a QV4::Value in many cases, but we'd have to
+ // duplicate much of metaTypeFromJS and some methods of QV4::Value itself here.
+ QV4::Scope scope(handle());
+ QV4::ScopedValue scoped(scope, scope.engine->fromVariant(value));
+ return QV4::ExecutionEngine::metaTypeFromJS(scoped, metaType, ptr);
+}
+
+bool QJSEngine::convertMetaType(QMetaType fromType, const void *from, QMetaType toType, void *to)
+{
+ // TODO: We could probably avoid creating a QV4::Value in many cases, but we'd have to
+ // duplicate much of metaTypeFromJS and some methods of QV4::Value itself here.
+ QV4::Scope scope(handle());
+ QV4::ScopedValue scoped(scope, scope.engine->fromData(fromType, from));
+ return QV4::ExecutionEngine::metaTypeFromJS(scoped, toType, to);
+}
- return QV4::ExecutionEngine::metaTypeFromJS(QJSValuePrivate::asReturnedValue(&value), type, ptr);
+QString QJSEngine::convertQObjectToString(QObject *object)
+{
+ return QV4::QObjectWrapper::objectToString(
+ handle(), object ? object->metaObject() : nullptr, object);
+}
+
+QString QJSEngine::convertDateTimeToString(const QDateTime &dateTime)
+{
+ return QV4::DateObject::dateTimeToString(dateTime, handle());
+}
+
+double QJSEngine::convertDateTimeToNumber(const QDateTime &dateTime)
+{
+ return QV4::DateObject::dateTimeToNumber(dateTime);
+}
+
+QDate QJSEngine::convertDateTimeToDate(const QDateTime &dateTime)
+{
+ return QV4::DateObject::dateTimeToDate(dateTime);
}
/*! \fn template <typename T> QJSValue QJSEngine::toScriptValue(const T &value)
Creates a QJSValue with the given \a value.
- This works with any type \c{T} that has a \c{QMetaType}.
- \sa fromScriptValue()
+ \sa fromScriptValue(), coerceValue()
+*/
+
+/*! \fn template <typename T> QJSManagedValue QJSEngine::toManagedValue(const T &value)
+
+ Creates a QJSManagedValue with the given \a value.
+
+ \sa fromManagedValue(), coerceValue()
+*/
+
+/*! \fn template <typename T> QJSPrimitiveValue QJSEngine::toPrimitiveValue(const T &value)
+
+ Creates a QJSPrimitiveValue with the given \a value.
+
+ Since QJSPrimitiveValue can only hold int, bool, double, QString, and the
+ equivalents of JavaScript \c null and \c undefined, the value will be
+ coerced aggressively if you pass any other type.
+
+ \sa fromPrimitiveValue(), coerceValue()
*/
/*! \fn template <typename T> T QJSEngine::fromScriptValue(const QJSValue &value)
Returns the given \a value converted to the template type \c{T}.
- This works with any type \c{T} that has a \c{QMetaType}.
- \sa toScriptValue()
+ \sa toScriptValue(), coerceValue()
+*/
+
+/*! \fn template <typename T> T QJSEngine::fromManagedValue(const QJSManagedValue &value)
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ \sa toManagedValue(), coerceValue()
+*/
+
+/*! \fn template <typename T> T QJSEngine::fromPrimitiveValue(const QJSPrimitiveValue &value)
+
+ Returns the given \a value converted to the template type \c{T}.
+
+ Since QJSPrimitiveValue can only hold int, bool, double, QString, and the
+ equivalents of JavaScript \c null and \c undefined, the value will be
+ coerced aggressively if you request any other type.
+
+ \sa toPrimitiveValue(), coerceValue()
+*/
+
+/*! \fn template <typename T> T QJSEngine::fromVariant(const QVariant &value)
+
+ Returns the given \a value converted to the template type \c{T}.
+ The conversion is done in JavaScript semantics. Those differ from
+ qvariant_cast's semantics. There are a number of implicit
+ conversions between JavaScript-equivalent types that are not
+ performed by qvariant_cast by default.
+
+ \sa coerceValue(), fromScriptValue(), {QVariant::}{qvariant_cast()}
+*/
+
+/*! \fn template <typename From, typename To> T QJSEngine::coerceValue(const From &from)
+
+ Returns the given \a from converted to the template type \c{To}.
+ The conversion is done in JavaScript semantics. Those differ from
+ qvariant_cast's semantics. There are a number of implicit
+ conversions between JavaScript-equivalent types that are not
+ performed by qvariant_cast by default. This method is a generalization of
+ all the other conversion methods in this class.
+
+ \sa fromVariant(), {QVariant::}{qvariant_cast()}, fromScriptValue(), toScriptValue()
*/
/*!
@@ -843,7 +1055,7 @@ bool QJSEngine::convertV2(const QJSValue &value, int type, void *ptr)
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
+ execution and call 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,
@@ -995,13 +1207,9 @@ QJSValue QJSEngine::catchError()
after installing translators in your application. By convention, an empty string
means no translation from the language used in the source code is intended to occur.
*/
-void QJSEngine::setUiLanguage(const QString &language)
-{
+void QJSEngine::setUiLanguage(const QString &language) {
Q_D(QJSEngine);
- if (language == d->uiLanguage)
- return;
- d->uiLanguage = language;
- emit uiLanguageChanged();
+ d->uiLanguage = language; // property takes care of signal emission if necessary
}
QString QJSEngine::uiLanguage() const
@@ -1052,7 +1260,7 @@ void QJSEnginePrivate::removeFromDebugServer(QJSEngine *q)
*/
QJSEngine *qjsEngine(const QObject *object)
{
- QQmlData *data = QQmlData::get(object, false);
+ QQmlData *data = QQmlData::get(object);
if (!data || data->jsWrapper.isNullOrUndefined())
return nullptr;
return data->jsWrapper.engine()->jsEngine();
@@ -1078,7 +1286,7 @@ QJSEngine *qjsEngine(const QObject *object)
two different engines will not be valid if one of these engines is deleted. This option is similar
to QScriptEngine::ScriptOwnership.
- Generally an application doesn't need to set an object's ownership explicitly. the JavaScript
+ Generally an application doesn't need to set an object's ownership explicitly. The JavaScript
memory manager uses a heuristic to set the default ownership. By default, an object that is
created by the JavaScript memory manager has JavaScriptOwnership. The exception to this are the
root objects created by calling QQmlComponent::create() or QQmlComponent::beginCreate(), which
@@ -1091,10 +1299,17 @@ QJSEngine *qjsEngine(const QObject *object)
but not to property getter invocations.
Calling setObjectOwnership() overrides the default ownership.
+
+ \sa {Data Ownership}
*/
/*!
Sets the \a ownership of \a object.
+
+ An object with \c JavaScriptOwnership is not garbage collected as long
+ as it still has a parent, even if there are no references to it.
+
+ \sa QJSEngine::ObjectOwnership
*/
void QJSEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
{
@@ -1111,6 +1326,8 @@ void QJSEngine::setObjectOwnership(QObject *object, ObjectOwnership ownership)
/*!
Returns the ownership of \a object.
+
+ \sa QJSEngine::ObjectOwnership
*/
QJSEngine::ObjectOwnership QJSEngine::objectOwnership(QObject *object)
{