diff options
Diffstat (limited to 'src')
128 files changed, 2716 insertions, 1114 deletions
diff --git a/src/3rdparty/masm/masm-defs.pri b/src/3rdparty/masm/masm-defs.pri index c4c7d3ce9a..b5480babc6 100644 --- a/src/3rdparty/masm/masm-defs.pri +++ b/src/3rdparty/masm/masm-defs.pri @@ -38,6 +38,4 @@ INCLUDEPATH += $$PWD/disassembler INCLUDEPATH += $$PWD/disassembler/udis86 INCLUDEPATH += $$_OUT_PWD -win32-msvc2008|wince*: INCLUDEPATH += $$PWD/stubs/compat - CONFIG(release, debug|release): DEFINES += NDEBUG diff --git a/src/imports/folderlistmodel/plugin.cpp b/src/imports/folderlistmodel/plugin.cpp index c60538673b..38de232dc0 100644 --- a/src/imports/folderlistmodel/plugin.cpp +++ b/src/imports/folderlistmodel/plugin.cpp @@ -59,7 +59,7 @@ class QmlFolderListModelPlugin : public QQmlExtensionPlugin public: QmlFolderListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.folderlistmodel")); #ifndef QT_NO_DIRMODEL diff --git a/src/imports/layouts/plugin.cpp b/src/imports/layouts/plugin.cpp index 248b12ac31..64d687cf3b 100644 --- a/src/imports/layouts/plugin.cpp +++ b/src/imports/layouts/plugin.cpp @@ -61,7 +61,7 @@ public: { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Layouts")); Q_UNUSED(uri); diff --git a/src/imports/localstorage/plugin.cpp b/src/imports/localstorage/plugin.cpp index da1817d309..8780dcc757 100644 --- a/src/imports/localstorage/plugin.cpp +++ b/src/imports/localstorage/plugin.cpp @@ -761,7 +761,7 @@ public: { initResources(); } - void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == "QtQuick.LocalStorage"); qmlRegisterSingletonType<QQuickLocalStorage>(uri, 2, 0, "LocalStorage", module_api_factory); diff --git a/src/imports/models/plugin.cpp b/src/imports/models/plugin.cpp index 9f96ace8fe..046d69cbc5 100644 --- a/src/imports/models/plugin.cpp +++ b/src/imports/models/plugin.cpp @@ -78,7 +78,7 @@ class QtQmlModelsPlugin : public QQmlExtensionPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") public: QtQmlModelsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQml.Models")); Q_UNUSED(uri); diff --git a/src/imports/particles/plugin.cpp b/src/imports/particles/plugin.cpp index 0698f34020..22eea16d4c 100644 --- a/src/imports/particles/plugin.cpp +++ b/src/imports/particles/plugin.cpp @@ -57,7 +57,7 @@ class QtQuick2ParticlesPlugin : public QQmlExtensionPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") public: QtQuick2ParticlesPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Particles")); Q_UNUSED(uri); diff --git a/src/imports/qtquick2/plugin.cpp b/src/imports/qtquick2/plugin.cpp index 315ad0ce58..1e3ff255f8 100644 --- a/src/imports/qtquick2/plugin.cpp +++ b/src/imports/qtquick2/plugin.cpp @@ -57,7 +57,7 @@ class QtQuick2Plugin : public QQmlExtensionPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") public: QtQuick2Plugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick")); Q_UNUSED(uri); diff --git a/src/imports/qtquick2/plugins.qmltypes b/src/imports/qtquick2/plugins.qmltypes index b11906ee09..a1a3723600 100644 --- a/src/imports/qtquick2/plugins.qmltypes +++ b/src/imports/qtquick2/plugins.qmltypes @@ -1730,6 +1730,15 @@ Module { "Capitalize": 4 } } + Enum { + name: "HintingPreference" + values: { + "PreferDefaultHinting": 0, + "PreferNoHinting": 1, + "PreferVerticalHinting": 2, + "PreferFullHinting": 3 + } + } Property { name: "family"; type: "string" } Property { name: "styleName"; type: "string" } Property { name: "bold"; type: "bool" } @@ -1743,6 +1752,7 @@ Module { Property { name: "capitalization"; type: "Capitalization" } Property { name: "letterSpacing"; type: "double" } Property { name: "wordSpacing"; type: "double" } + Property { name: "hintingPreference"; type: "HintingPreference" } Method { name: "toString"; type: "string" } } Component { diff --git a/src/imports/settings/plugin.cpp b/src/imports/settings/plugin.cpp index c97c2b066e..ce498774d2 100644 --- a/src/imports/settings/plugin.cpp +++ b/src/imports/settings/plugin.cpp @@ -58,7 +58,7 @@ class QmlSettingsPlugin : public QQmlExtensionPlugin public: QmlSettingsPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QByteArray(uri) == QByteArray("Qt.labs.settings")); qmlRegisterType<QQmlSettings>(uri, 1, 0, "Settings"); diff --git a/src/imports/statemachine/plugin.cpp b/src/imports/statemachine/plugin.cpp index db79751b69..c061607f40 100644 --- a/src/imports/statemachine/plugin.cpp +++ b/src/imports/statemachine/plugin.cpp @@ -63,7 +63,7 @@ class QtQmlStateMachinePlugin : public QQmlExtensionPlugin public: QtQmlStateMachinePlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { qmlRegisterType<State>(uri, 1, 0, "State"); qmlRegisterType<StateMachine>(uri, 1, 0, "StateMachine"); diff --git a/src/imports/statemachine/statemachine.h b/src/imports/statemachine/statemachine.h index 8a05acfbde..59a810f387 100644 --- a/src/imports/statemachine/statemachine.h +++ b/src/imports/statemachine/statemachine.h @@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE -class QQmlOpenMetaObject; - class StateMachine : public QStateMachine, public QQmlParserStatus { Q_OBJECT diff --git a/src/imports/testlib/main.cpp b/src/imports/testlib/main.cpp index 26ce79c92b..1632d7ba64 100644 --- a/src/imports/testlib/main.cpp +++ b/src/imports/testlib/main.cpp @@ -151,7 +151,7 @@ class QTestQmlModule : public QQmlExtensionPlugin public: QTestQmlModule(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtTest")); qmlRegisterType<QuickTestResult, 0>(uri,1,0,"TestResult"); @@ -159,10 +159,6 @@ public: qmlRegisterType<QuickTestEvent>(uri,1,0,"TestEvent"); qmlRegisterType<QuickTestUtil>(uri,1,0,"TestUtil"); } - - void initializeEngine(QQmlEngine *, const char *) - { - } }; QT_END_NAMESPACE diff --git a/src/imports/window/plugin.cpp b/src/imports/window/plugin.cpp index a0a5724e34..b85ccc6dc7 100644 --- a/src/imports/window/plugin.cpp +++ b/src/imports/window/plugin.cpp @@ -73,7 +73,7 @@ class QtQuick2WindowPlugin : public QQmlExtensionPlugin Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QQmlExtensionInterface/1.0") public: QtQuick2WindowPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.Window")); Q_UNUSED(uri); diff --git a/src/imports/xmllistmodel/plugin.cpp b/src/imports/xmllistmodel/plugin.cpp index e983b494e1..ca676c36b0 100644 --- a/src/imports/xmllistmodel/plugin.cpp +++ b/src/imports/xmllistmodel/plugin.cpp @@ -58,7 +58,7 @@ class QmlXmlListModelPlugin : public QQmlExtensionPlugin public: QmlXmlListModelPlugin(QObject *parent = 0) : QQmlExtensionPlugin(parent) { initResources(); } - virtual void registerTypes(const char *uri) + void registerTypes(const char *uri) Q_DECL_OVERRIDE { Q_ASSERT(QLatin1String(uri) == QLatin1String("QtQuick.XmlListModel")); qmlRegisterType<QQuickXmlListModel>(uri,2,0,"XmlListModel"); diff --git a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp index 877821e03f..075f56226d 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qqmlnativedebugservice.cpp @@ -374,7 +374,7 @@ void Collector::collect(QJsonArray *out, const QString &parentIName, const QStri dict.insert(QStringLiteral("iname"), iname); dict.insert(QStringLiteral("name"), nonEmptyName); - QV4::ScopedValue typeString(scope, QV4::Runtime::typeofValue(m_engine, value)); + QV4::ScopedValue typeString(scope, QV4::Runtime::method_typeofValue(m_engine, value)); dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow()); switch (value.type()) { diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp index 96f60b24bb..b2db23d78c 100644 --- a/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp +++ b/src/plugins/qmltooling/qmldbg_debugger/qv4datacollector.cpp @@ -134,7 +134,7 @@ const QV4::Object *collectProperty(const QV4::ScopedValue &value, QV4::Execution QJsonObject &dict) { QV4::Scope scope(engine); - QV4::ScopedValue typeString(scope, QV4::Runtime::typeofValue(engine, value)); + QV4::ScopedValue typeString(scope, QV4::Runtime::method_typeofValue(engine, value)); dict.insert(QStringLiteral("type"), typeString->toQStringNoThrow()); const QLatin1String valueKey("value"); diff --git a/src/plugins/qmltooling/qmltooling.pro b/src/plugins/qmltooling/qmltooling.pro index 3728126dd9..7682e7b075 100644 --- a/src/plugins/qmltooling/qmltooling.pro +++ b/src/plugins/qmltooling/qmltooling.pro @@ -1,30 +1,32 @@ TEMPLATE = subdirs -# Utilities -SUBDIRS += \ - packetprotocol +!no_network { + # Utilities + SUBDIRS += \ + packetprotocol -# Connectors -SUBDIRS += \ - qmldbg_native \ - qmldbg_server \ + # Connectors + SUBDIRS += \ + qmldbg_native \ + qmldbg_server \ qmldbg_local \ qmldbg_tcp -# Services -SUBDIRS += \ - qmldbg_debugger \ - qmldbg_profiler + # Services + SUBDIRS += \ + qmldbg_debugger \ + qmldbg_profiler -qmldbg_server.depends = packetprotocol -qmldbg_native.depends = packetprotocol -qmldbg_debugger.depends = packetprotocol -qmldbg_profiler.depends = packetprotocol + qmldbg_server.depends = packetprotocol + qmldbg_native.depends = packetprotocol + qmldbg_debugger.depends = packetprotocol + qmldbg_profiler.depends = packetprotocol -qtHaveModule(quick) { - SUBDIRS += \ - qmldbg_inspector \ - qmldbg_quickprofiler - qmldbg_inspector.depends = packetprotocol - qmldbg_quickprofiler.depends = packetprotocol + qtHaveModule(quick) { + SUBDIRS += \ + qmldbg_inspector \ + qmldbg_quickprofiler + qmldbg_inspector.depends = packetprotocol + qmldbg_quickprofiler.depends = packetprotocol + } } diff --git a/src/qml/animations/qabstractanimationjob.cpp b/src/qml/animations/qabstractanimationjob.cpp index 4bd02c1934..f7f6939e4b 100644 --- a/src/qml/animations/qabstractanimationjob.cpp +++ b/src/qml/animations/qabstractanimationjob.cpp @@ -588,8 +588,7 @@ void QAbstractAnimationJob::updateDirection(QAbstractAnimationJob::Direction dir void QAbstractAnimationJob::finished() { //TODO: update this code so it is valid to delete the animation in animationFinished - for (int i = 0; i < changeListeners.count(); ++i) { - const QAbstractAnimationJob::ChangeListener &change = changeListeners.at(i); + for (const auto &change : changeListeners) { if (change.types & QAbstractAnimationJob::Completion) { RETURN_IF_DELETED(change.listener->animationFinished(this)); } @@ -603,8 +602,7 @@ void QAbstractAnimationJob::finished() void QAbstractAnimationJob::stateChanged(QAbstractAnimationJob::State newState, QAbstractAnimationJob::State oldState) { - for (int i = 0; i < changeListeners.count(); ++i) { - const QAbstractAnimationJob::ChangeListener &change = changeListeners.at(i); + for (const auto &change : changeListeners) { if (change.types & QAbstractAnimationJob::StateChange) { RETURN_IF_DELETED(change.listener->animationStateChanged(this, newState, oldState)); } @@ -613,8 +611,7 @@ void QAbstractAnimationJob::stateChanged(QAbstractAnimationJob::State newState, void QAbstractAnimationJob::currentLoopChanged() { - for (int i = 0; i < changeListeners.count(); ++i) { - const QAbstractAnimationJob::ChangeListener &change = changeListeners.at(i); + for (const auto &change : changeListeners) { if (change.types & QAbstractAnimationJob::CurrentLoop) { RETURN_IF_DELETED(change.listener->animationCurrentLoopChanged(this)); } @@ -625,8 +622,7 @@ void QAbstractAnimationJob::currentTimeChanged(int currentTime) { Q_ASSERT(m_hasCurrentTimeChangeListeners); - for (int i = 0; i < changeListeners.count(); ++i) { - const QAbstractAnimationJob::ChangeListener &change = changeListeners.at(i); + for (const auto &change : changeListeners) { if (change.types & QAbstractAnimationJob::CurrentTime) { RETURN_IF_DELETED(change.listener->animationCurrentTimeChanged(this, currentTime)); } @@ -638,17 +634,18 @@ void QAbstractAnimationJob::addAnimationChangeListener(QAnimationJobChangeListen if (changes & QAbstractAnimationJob::CurrentTime) m_hasCurrentTimeChangeListeners = true; - changeListeners.append(ChangeListener(listener, changes)); + changeListeners.push_back(ChangeListener(listener, changes)); } void QAbstractAnimationJob::removeAnimationChangeListener(QAnimationJobChangeListener *listener, QAbstractAnimationJob::ChangeTypes changes) { m_hasCurrentTimeChangeListeners = false; - changeListeners.removeOne(ChangeListener(listener, changes)); + const auto it = std::find(changeListeners.begin(), changeListeners.end(), ChangeListener(listener, changes)); + if (it != changeListeners.end()) + changeListeners.erase(it); - for (int i = 0; i < changeListeners.count(); ++i) { - const QAbstractAnimationJob::ChangeListener &change = changeListeners.at(i); + for (const auto &change: changeListeners) { if (change.types & QAbstractAnimationJob::CurrentTime) { m_hasCurrentTimeChangeListeners = true; break; diff --git a/src/qml/animations/qabstractanimationjob_p.h b/src/qml/animations/qabstractanimationjob_p.h index b04f523585..efc86a5823 100644 --- a/src/qml/animations/qabstractanimationjob_p.h +++ b/src/qml/animations/qabstractanimationjob_p.h @@ -54,7 +54,7 @@ #include <private/qtqmlglobal_p.h> #include <QtCore/QObject> #include <QtCore/private/qabstractanimation_p.h> -#include "private/qpodvector_p.h" +#include <vector> QT_BEGIN_NAMESPACE @@ -164,7 +164,7 @@ protected: QAbstractAnimationJob::ChangeTypes types; bool operator==(const ChangeListener &other) const { return listener == other.listener && types == other.types; } }; - QPODVector<ChangeListener,1> changeListeners; + std::vector<ChangeListener> changeListeners; QAbstractAnimationJob *m_nextSibling; QAbstractAnimationJob *m_previousSibling; diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index 065e91109b..d4757bed39 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -236,7 +236,6 @@ void Document::collectTypeReferences() // ### FIXME: We could report the more accurate location here by using prop->location, but the old // compiler can't and the tests expect it to be the object location right now. QV4::CompiledData::TypeReference &r = typeReferences.add(prop->customTypeNameIndex, obj->location); - r.needsCreation = true; r.errorWhenNotFound = true; } } diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 8c617875e0..6f0b5f9b32 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -91,8 +91,8 @@ struct Unit; struct Location { - qint32 line; - qint32 column; + qint32 line : 20; + qint32 column : 12; Location(): line(-1), column(-1) {} @@ -109,8 +109,8 @@ struct RegExp RegExp_IgnoreCase = 0x02, RegExp_Multiline = 0x04 }; - quint32 flags; - quint32 stringIndex; + quint32 flags : 4; + quint32 stringIndex : 28; static int calculateSize() { return sizeof(RegExp); } }; @@ -125,16 +125,16 @@ struct Lookup Type_IndexedSetter = 4 }; - quint32 type_and_flags; - quint32 nameIndex; + quint32 type_and_flags : 4; + quint32 nameIndex : 28; static int calculateSize() { return sizeof(Lookup); } }; struct JSClassMember { - uint nameOffset : 31; - uint isAccessor : 1; + quint32 nameOffset : 31; + quint32 isAccessor : 1; }; struct JSClass @@ -147,7 +147,6 @@ struct JSClass struct String { - quint32 flags; // isArrayIndex qint32 size; // uint16 strdata[] @@ -326,7 +325,6 @@ struct Parameter quint32 nameIndex; quint32 type; quint32 customTypeNameIndex; - quint32 reserved; Location location; }; diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 3943642146..aacf0e9928 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -82,7 +82,6 @@ void QV4::Compiler::StringTableGenerator::serialize(CompiledData::Unit *unit) const QString &qstr = strings.at(i); QV4::CompiledData::String *s = (QV4::CompiledData::String*)(stringData); - s->flags = 0; // ### s->size = qstr.length(); memcpy(s + 1, qstr.constData(), qstr.length()*sizeof(ushort)); diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index 90010ccf52..93043135a4 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -81,9 +81,19 @@ QT_BEGIN_NAMESPACE F(SetLookup, setLookup) \ F(StoreQObjectProperty, storeQObjectProperty) \ F(LoadQObjectProperty, loadQObjectProperty) \ + F(LoadQRealQObjectPropertyDirectly, loadQRealQObjectPropertyDirectly) \ + F(LoadQObjectQObjectPropertyDirectly, loadQObjectQObjectPropertyDirectly) \ + F(LoadIntQObjectPropertyDirectly, loadIntQObjectPropertyDirectly) \ + F(LoadBoolQObjectPropertyDirectly, loadBoolQObjectPropertyDirectly) \ + F(LoadQStringQObjectPropertyDirectly, loadQStringQObjectPropertyDirectly) \ F(StoreScopeObjectProperty, storeScopeObjectProperty) \ F(StoreContextObjectProperty, storeContextObjectProperty) \ F(LoadScopeObjectProperty, loadScopeObjectProperty) \ + F(LoadScopeObjectQRealPropertyDirectly, loadScopeObjectQRealPropertyDirectly) \ + F(LoadScopeObjectQObjectPropertyDirectly, loadScopeObjectQObjectPropertyDirectly) \ + F(LoadScopeObjectIntPropertyDirectly, loadScopeObjectIntPropertyDirectly) \ + F(LoadScopeObjectBoolPropertyDirectly, loadScopeObjectBoolPropertyDirectly) \ + F(LoadScopeObjectQStringPropertyDirectly, loadScopeObjectQStringPropertyDirectly) \ F(LoadContextObjectProperty, loadContextObjectProperty) \ F(LoadIdObject, loadIdObject) \ F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \ @@ -323,6 +333,36 @@ union Instr Param base; Param result; }; + struct instr_loadScopeObjectQRealPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectIntPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectBoolPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; + struct instr_loadScopeObjectQStringPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + }; struct instr_loadContextObjectProperty { MOTH_INSTR_HEADER int propertyIndex; @@ -342,6 +382,46 @@ union Instr Param result; bool captureRequired; }; + struct instr_loadQRealQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadQObjectQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadIntQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadBoolQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; + struct instr_loadQStringQObjectPropertyDirectly { + MOTH_INSTR_HEADER + Param base; + Param result; + QQmlAccessors *accessors; + int coreIndex; + int notifyIndex; + }; struct instr_loadAttachedQObjectProperty { MOTH_INSTR_HEADER int propertyIndex; @@ -672,7 +752,7 @@ union Instr }; struct instr_binop { MOTH_INSTR_HEADER - QV4::Runtime::BinaryOperation alu; + uint alu; // offset inside the runtime methods Param lhs; Param rhs; Param result; @@ -757,7 +837,7 @@ union Instr }; struct instr_binopContext { MOTH_INSTR_HEADER - QV4::Runtime::BinaryOperationContext alu; + uint alu; // offset inside the runtime methods Param lhs; Param rhs; Param result; @@ -800,9 +880,19 @@ union Instr instr_loadProperty loadProperty; instr_getLookup getLookup; instr_loadScopeObjectProperty loadScopeObjectProperty; + instr_loadScopeObjectQRealPropertyDirectly loadScopeObjectQRealPropertyDirectly; + instr_loadScopeObjectQObjectPropertyDirectly loadScopeObjectQObjectPropertyDirectly; + instr_loadScopeObjectIntPropertyDirectly loadScopeObjectIntPropertyDirectly; + instr_loadScopeObjectBoolPropertyDirectly loadScopeObjectBoolPropertyDirectly; + instr_loadScopeObjectQStringPropertyDirectly loadScopeObjectQStringPropertyDirectly; instr_loadContextObjectProperty loadContextObjectProperty; instr_loadIdObject loadIdObject; instr_loadQObjectProperty loadQObjectProperty; + instr_loadQRealQObjectPropertyDirectly loadQRealQObjectPropertyDirectly; + instr_loadQObjectQObjectPropertyDirectly loadQObjectQObjectPropertyDirectly; + instr_loadIntQObjectPropertyDirectly loadIntQObjectPropertyDirectly; + instr_loadBoolQObjectPropertyDirectly loadBoolQObjectPropertyDirectly; + instr_loadQStringQObjectPropertyDirectly loadQStringQObjectPropertyDirectly; instr_loadAttachedQObjectProperty loadAttachedQObjectProperty; instr_storeProperty storeProperty; instr_setLookup setLookup; diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index be10d50e9b..b452c4b3d9 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -46,6 +46,8 @@ #include <private/qv4regexpobject_p.h> #include <private/qv4compileddata_p.h> #include <private/qqmlengine_p.h> +#include "qml/qqmlaccessors_p.h" +#include "qml/qqmlpropertycache_p.h" #undef USE_TYPE_INFO @@ -54,7 +56,7 @@ using namespace QV4::Moth; namespace { -inline QV4::Runtime::BinaryOperation aluOpFunction(IR::AluOp op) +inline uint aluOpFunction(IR::AluOp op) { switch (op) { case IR::OpInvalid: @@ -70,43 +72,43 @@ inline QV4::Runtime::BinaryOperation aluOpFunction(IR::AluOp op) case IR::OpCompl: return 0; case IR::OpBitAnd: - return QV4::Runtime::bitAnd; + return offsetof(QV4::Runtime, bitAnd); case IR::OpBitOr: - return QV4::Runtime::bitOr; + return offsetof(QV4::Runtime, bitOr); case IR::OpBitXor: - return QV4::Runtime::bitXor; + return offsetof(QV4::Runtime, bitXor); case IR::OpAdd: return 0; case IR::OpSub: - return QV4::Runtime::sub; + return offsetof(QV4::Runtime, sub); case IR::OpMul: - return QV4::Runtime::mul; + return offsetof(QV4::Runtime, mul); case IR::OpDiv: - return QV4::Runtime::div; + return offsetof(QV4::Runtime, div); case IR::OpMod: - return QV4::Runtime::mod; + return offsetof(QV4::Runtime, mod); case IR::OpLShift: - return QV4::Runtime::shl; + return offsetof(QV4::Runtime, shl); case IR::OpRShift: - return QV4::Runtime::shr; + return offsetof(QV4::Runtime, shr); case IR::OpURShift: - return QV4::Runtime::ushr; + return offsetof(QV4::Runtime, ushr); case IR::OpGt: - return QV4::Runtime::greaterThan; + return offsetof(QV4::Runtime, greaterThan); case IR::OpLt: - return QV4::Runtime::lessThan; + return offsetof(QV4::Runtime, lessThan); case IR::OpGe: - return QV4::Runtime::greaterEqual; + return offsetof(QV4::Runtime, greaterEqual); case IR::OpLe: - return QV4::Runtime::lessEqual; + return offsetof(QV4::Runtime, lessEqual); case IR::OpEqual: - return QV4::Runtime::equal; + return offsetof(QV4::Runtime, equal); case IR::OpNotEqual: - return QV4::Runtime::notEqual; + return offsetof(QV4::Runtime, notEqual); case IR::OpStrictEqual: - return QV4::Runtime::strictEqual; + return offsetof(QV4::Runtime, strictEqual); case IR::OpStrictNotEqual: - return QV4::Runtime::strictNotEqual; + return offsetof(QV4::Runtime, strictNotEqual); case IR::OpInstanceof: return 0; case IR::OpIn: @@ -737,8 +739,51 @@ void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *target addInstruction(store); } -void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) -{ +void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, + QQmlPropertyData *property, int index, + IR::Expr *target) +{ + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (kind == IR::Member::MemberOfQmlScopeObject) { + if (property->propType == QMetaType::QReal) { + Instruction::LoadScopeObjectQRealPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->isQObject()) { + Instruction::LoadScopeObjectQObjectPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Int) { + Instruction::LoadScopeObjectIntPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Bool) { + Instruction::LoadScopeObjectBoolPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::QString) { + Instruction::LoadScopeObjectQStringPropertyDirectly load; + load.base = getParam(source); + load.accessors = property->accessors; + load.result = getResultParam(target); + addInstruction(load); + return; + } + } + } + if (kind == IR::Member::MemberOfQmlScopeObject) { Instruction::LoadScopeObjectProperty load; load.base = getParam(source); @@ -762,8 +807,59 @@ void InstructionSelection::getQmlContextProperty(IR::Expr *source, IR::Member::M } } -void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) -{ +void InstructionSelection::getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) +{ + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (!attachedPropertiesId && !isSingletonProperty) { + if (property->propType == QMetaType::QReal) { + Instruction::LoadQRealQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->isQObject()) { + Instruction::LoadQObjectQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Int) { + Instruction::LoadIntQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::Bool) { + Instruction::LoadBoolQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } else if (property->propType == QMetaType::QString) { + Instruction::LoadQStringQObjectPropertyDirectly load; + load.base = getParam(base); + load.accessors = property->accessors; + load.coreIndex = property->coreIndex; + load.notifyIndex = captureRequired ? property->notifyIndex : -1; + load.result = getResultParam(target); + addInstruction(load); + return; + } + } + } + const int propertyIndex = property->coreIndex; if (attachedPropertiesId != 0) { Instruction::LoadAttachedQObjectProperty load; load.propertyIndex = propertyIndex; @@ -1040,11 +1136,11 @@ Param InstructionSelection::binopHelper(IR::AluOp oper, IR::Expr *leftSource, IR if (oper == IR::OpInstanceof || oper == IR::OpIn || oper == IR::OpAdd) { Instruction::BinopContext binop; if (oper == IR::OpInstanceof) - binop.alu = QV4::Runtime::instanceof; + binop.alu = offsetof(QV4::Runtime, instanceof); else if (oper == IR::OpIn) - binop.alu = QV4::Runtime::in; + binop.alu = offsetof(QV4::Runtime, in); else - binop.alu = QV4::Runtime::add; + binop.alu = offsetof(QV4::Runtime, add); binop.lhs = getParam(leftSource); binop.rhs = getParam(rightSource); binop.result = getResultParam(target); diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h index 29d117af38..bf3909682d 100644 --- a/src/qml/compiler/qv4isel_moth_p.h +++ b/src/qml/compiler/qv4isel_moth_p.h @@ -134,8 +134,8 @@ protected: virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target); - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target); + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void getElement(IR::Expr *base, IR::Expr *index, IR::Expr *target); virtual void setElement(IR::Expr *source, IR::Expr *targetBase, IR::Expr *targetIndex); virtual void copyValue(IR::Expr *source, IR::Expr *target); diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp index 0ae08160ab..6ba23a0951 100644 --- a/src/qml/compiler/qv4isel_p.cpp +++ b/src/qml/compiler/qv4isel_p.cpp @@ -156,14 +156,15 @@ void IRDecoder::visitMove(IR::Move *s) } } if (m->kind == IR::Member::MemberOfQmlScopeObject || m->kind == IR::Member::MemberOfQmlContextObject) { - getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property->coreIndex, s->target); + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->property, + m->property->coreIndex, s->target); return; } - getQObjectProperty(m->base, m->property->coreIndex, captureRequired, isSingletonProperty, attachedPropertiesId, s->target); + getQObjectProperty(m->base, m->property, captureRequired, isSingletonProperty, attachedPropertiesId, s->target); #endif // V4_BOOTSTRAP return; } else if (m->kind == IR::Member::MemberOfIdObjectsArray) { - getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, m->idIndex, s->target); + getQmlContextProperty(m->base, (IR::Member::MemberKind)m->kind, nullptr, m->idIndex, s->target); return; } else if (m->base->asTemp() || m->base->asConst() || m->base->asArgLocal()) { getProperty(m->base, *m->name, s->target); diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h index 88d2071c52..2ee776adf4 100644 --- a/src/qml/compiler/qv4isel_p.h +++ b/src/qml/compiler/qv4isel_p.h @@ -61,6 +61,7 @@ QT_BEGIN_NAMESPACE +class QQmlAccessors; class QQmlEnginePrivate; namespace QV4 { @@ -165,8 +166,8 @@ public: // to implement by subclasses: virtual void setActivationProperty(IR::Expr *source, const QString &targetName) = 0; virtual void initClosure(IR::Closure *closure, IR::Expr *target) = 0; virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target) = 0; - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0; - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target) = 0; + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingletonProperty, int attachedPropertiesId, IR::Expr *target) = 0; + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target) = 0; virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName) = 0; virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) = 0; virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) = 0; diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp index b28db59190..370dfd0fae 100644 --- a/src/qml/compiler/qv4jsir.cpp +++ b/src/qml/compiler/qv4jsir.cpp @@ -927,12 +927,16 @@ void IRPrinter::visitMember(Member *e) e->base->accept(this); *out << '.' << *e->name; #ifndef V4_BOOTSTRAP - if (e->property) + if (e->property) { *out << " (meta-property " << e->property->coreIndex - << " <" << QMetaType::typeName(e->property->propType) - << ">)"; - else if (e->kind == Member::MemberOfIdObjectsArray) + << " <" << QMetaType::typeName(e->property->propType) << ">"; + if (e->property->hasAccessors() && e->property->isFullyResolved()) { + *out << ", accessible"; + } + *out << ")"; + } else if (e->kind == Member::MemberOfIdObjectsArray) { *out << "(id object " << e->idIndex << ")"; + } #endif } diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp index f021e1f760..6965d839ab 100644 --- a/src/qml/compiler/qv4ssa.cpp +++ b/src/qml/compiler/qv4ssa.cpp @@ -3748,42 +3748,42 @@ bool tryOptimizingComparison(Expr *&expr) switch (b->op) { case OpGt: - leftConst->value = Runtime::compareGreaterThan(l, r); + leftConst->value = Runtime::method_compareGreaterThan(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpLt: - leftConst->value = Runtime::compareLessThan(l, r); + leftConst->value = Runtime::method_compareLessThan(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpGe: - leftConst->value = Runtime::compareGreaterEqual(l, r); + leftConst->value = Runtime::method_compareGreaterEqual(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpLe: - leftConst->value = Runtime::compareLessEqual(l, r); + leftConst->value = Runtime::method_compareLessEqual(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpStrictEqual: - leftConst->value = Runtime::compareStrictEqual(l, r); + leftConst->value = Runtime::method_compareStrictEqual(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpEqual: - leftConst->value = Runtime::compareEqual(l, r); + leftConst->value = Runtime::method_compareEqual(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpStrictNotEqual: - leftConst->value = Runtime::compareStrictNotEqual(l, r); + leftConst->value = Runtime::method_compareStrictNotEqual(l, r); leftConst->type = BoolType; expr = leftConst; return true; case OpNotEqual: - leftConst->value = Runtime::compareNotEqual(l, r); + leftConst->value = Runtime::method_compareNotEqual(l, r); leftConst->type = BoolType; expr = leftConst; return true; diff --git a/src/qml/doc/snippets/qml/qtLater.qml b/src/qml/doc/snippets/qml/qtLater.qml new file mode 100644 index 0000000000..e2bc02edb4 --- /dev/null +++ b/src/qml/doc/snippets/qml/qtLater.qml @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of The Qt Company Ltd nor the names of its +** contributors may be used to endorse or promote products derived +** from this software without specific prior written permission. +** +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +//![0] +import QtQuick 2.0 + +Rectangle { + width: 480 + height: 320 + + property int callsToUpdateMinimumWidth: 0 + property bool optimize: true + + property int currentTextModel: 0 + property var columnTexts: [ + ["Click on either", "rectangle above", "and note how the counter", "below updates", "significantly faster using the", "regular (non-optimized)", "implementation"], + ["The width", "of this column", "is", "no wider than the", "widest item"], + ["Note how using Qt.callLater()", "the minimum width is", "calculated a bare-minimum", "number", "of times"] + ] + + Text { + x: 20; y: 280 + text: "Times minimum width has been calculated: " + callsToUpdateMinimumWidth + } + + Row { + y: 25; spacing: 30; anchors.horizontalCenter: parent.horizontalCenter + Rectangle { + width: 200; height: 50; color: "lightgreen" + Text { text: "Optimized behavior\nusing Qt.callLater()"; anchors.centerIn: parent } + MouseArea { anchors.fill: parent; onClicked: { optimize = true; currentTextModel++ } } + } + Rectangle { + width: 200; height: 50; color: "lightblue" + Text { text: "Regular behavior"; anchors.centerIn: parent} + MouseArea { anchors.fill: parent; onClicked: { optimize = false; currentTextModel++ } } + } + } + + Column { + id: column + anchors.centerIn: parent + + onChildrenChanged: optimize ? Qt.callLater(updateMinimumWidth) : updateMinimumWidth() + + property int widestChild + function updateMinimumWidth() { + callsToUpdateMinimumWidth++ + var w = 0; + for (var i in children) { + var child = children[i]; + if (child.implicitWidth > w) { + w = child.implicitWidth; + } + } + + widestChild = w; + } + + Repeater { + id: repeater + model: columnTexts[currentTextModel%3] + delegate: Text { + color: "white" + text: modelData + width: column.widestChild + horizontalAlignment: Text.Center + Rectangle { anchors.fill: parent; z: -1; color: index%2 ? "gray" : "darkgray" } + } + } + } +} +//![0] diff --git a/src/qml/doc/src/javascript/functionlist.qdoc b/src/qml/doc/src/javascript/functionlist.qdoc index 7f0e844b65..b9a25a2440 100644 --- a/src/qml/doc/src/javascript/functionlist.qdoc +++ b/src/qml/doc/src/javascript/functionlist.qdoc @@ -174,6 +174,8 @@ \li charAt(pos) \li charCodeAt(pos) \li concat([string1 [, string2 [, ...]]]) + \li endsWith(searchString [, endPosition ]) // ECMAScript 6: Added in Qt 5.8 + \li includes(searchString [, position ]) // ECMAScript 6: Added in 5.8 \li indexOf(searchString ,position) \li lastIndexOf(searchString, position) \li localeCompare(that) @@ -182,6 +184,7 @@ \li search(regexp) \li slice(start, end) \li split(separator, limit) + \li startsWith(searchString [, position ]) // ECMAScript 6: Added in Qt 5.8 \li substring(start, end) \li toLowerCase() \li toLocaleLowerCase() @@ -228,6 +231,26 @@ \li \l {Number::toLocaleString}{toLocaleString(locale, format, precision)} \endlist + \section2 The Number Object + + \section3 Value Properties + + \list + \li NaN + \li NEGATIVE_INFINITY + \li POSITIVE_INFINITY + \li MAX_VALUE + \li MIN_VALUE + \li EPSILON // ECMAScript 6: Added in Qt 5.8 + \endlist + + \section3 Function Properties + + \list + \li isFinite(x) // ECMAScript 6: Added in Qt 5.8 + \li isNaN(x) // ECMAScript 6: Added in Qt 5.8 + \endlist + \section1 The Math Object \section2 Value Properties @@ -261,6 +284,7 @@ \li pow(x, y) \li random() \li round(x) + \li sign(x) // ECMAScript 6: Added in Qt 5.8 \li sin(x) \li sqrt(x) \li tan(x) diff --git a/src/qml/jit/qv4assembler_p.h b/src/qml/jit/qv4assembler_p.h index a5028bc683..6c7d27b2f4 100644 --- a/src/qml/jit/qv4assembler_p.h +++ b/src/qml/jit/qv4assembler_p.h @@ -63,6 +63,8 @@ #include <config.h> #include <wtf/Vector.h> +#include <climits> + #if ENABLE(ASSEMBLER) #include <assembler/MacroAssembler.h> @@ -73,11 +75,6 @@ QT_BEGIN_NAMESPACE namespace QV4 { namespace JIT { -#define OP(op) \ - { isel_stringIfy(op), op, 0, 0, 0 } -#define OPCONTEXT(op) \ - { isel_stringIfy(op), 0, op, 0, 0 } - class InstructionSelection; struct CompilationUnit : public QV4::CompiledData::CompilationUnit @@ -94,14 +91,6 @@ struct CompilationUnit : public QV4::CompiledData::CompilationUnit QList<QVector<QV4::Primitive> > constantValues; }; -struct RelativeCall { - JSC::MacroAssembler::Address addr; - - explicit RelativeCall(const JSC::MacroAssembler::Address &addr) - : addr(addr) - {} -}; - struct LookupCall { JSC::MacroAssembler::Address addr; uint getterSetterOffset; @@ -112,6 +101,13 @@ struct LookupCall { {} }; +struct RuntimeCall { + JSC::MacroAssembler::Address addr; + + inline RuntimeCall(uint offset = INT_MIN); + bool isValid() const { return addr.offset >= 0; } +}; + template <typename T> struct ExceptionCheck { enum { NeedsCheck = 1 }; @@ -321,12 +317,12 @@ public: typedef JSC::FunctionPtr FunctionPtr; - struct CallToLink { - Call call; - FunctionPtr externalFunction; +#ifndef QT_NO_DEBUG + struct CallInfo { Label label; const char* functionName; }; +#endif struct PointerToValue { PointerToValue(IR::Expr *value) : value(value) @@ -349,27 +345,23 @@ public: IR::BasicBlock *block; }; - void callAbsolute(const char* functionName, FunctionPtr function) { - CallToLink ctl; - ctl.call = call(); - ctl.externalFunction = function; - ctl.functionName = functionName; - ctl.label = label(); - _callsToLink.append(ctl); - } - - void callAbsolute(const char* /*functionName*/, Address addr) { - call(addr); - } - - void callAbsolute(const char* /*functionName*/, const RelativeCall &relativeCall) + void callAbsolute(const char* /*functionName*/, const LookupCall &lookupCall) { - call(relativeCall.addr); + call(lookupCall.addr); } - void callAbsolute(const char* /*functionName*/, const LookupCall &lookupCall) + void callAbsolute(const char *functionName, const RuntimeCall &runtimeCall) { - call(lookupCall.addr); + call(runtimeCall.addr); +#ifndef QT_NO_DEBUG + // the code below is to get proper function names in the disassembly + CallInfo info; + info.functionName = functionName; + info.label = label(); + _callInfos.append(info); +#else + Q_UNUSED(functionName) +#endif } void registerBlock(IR::BasicBlock*, IR::BasicBlock *nextBlock); @@ -1184,7 +1176,9 @@ private: IR::Function *_function; QHash<IR::BasicBlock *, Label> _addrs; QHash<IR::BasicBlock *, QVector<Jump> > _patches; - QList<CallToLink> _callsToLink; +#ifndef QT_NO_DEBUG + QVector<CallInfo> _callInfos; +#endif struct DataLabelPatch { DataLabelPtr dataLabel; @@ -1245,24 +1239,21 @@ void Assembler::copyValue(Result result, IR::Expr* source) } } +inline RuntimeCall::RuntimeCall(uint offset) + : addr(Assembler::EngineRegister, offset + qOffsetOf(QV4::ExecutionEngine, runtime)) +{ +} + template <typename T> inline bool prepareCall(T &, Assembler *) { return true; } -template <> inline bool prepareCall(RelativeCall &relativeCall, Assembler *as) -{ - as->loadPtr(Assembler::Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister); - as->loadPtr(Assembler::Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, lookups)), - relativeCall.addr.base); - return true; -} - template <> inline bool prepareCall(LookupCall &lookupCall, Assembler *as) { // IMPORTANT! See generateLookupCall in qv4isel_masm_p.h for details! - // same as prepareCall(RelativeCall ....) : load the table from the context + // load the table from the context as->loadPtr(Assembler::Address(Assembler::EngineRegister, qOffsetOf(QV4::ExecutionEngine, current)), Assembler::ScratchRegister); as->loadPtr(Assembler::Address(Assembler::ScratchRegister, qOffsetOf(QV4::Heap::ExecutionContext, lookups)), lookupCall.addr.base); diff --git a/src/qml/jit/qv4binop.cpp b/src/qml/jit/qv4binop.cpp index 50b6cec975..c09fc6fdca 100644 --- a/src/qml/jit/qv4binop.cpp +++ b/src/qml/jit/qv4binop.cpp @@ -45,14 +45,14 @@ using namespace QV4; using namespace JIT; #define OP(op) \ - { isel_stringIfy(op), op, 0, 0, 0 } + { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, 0, 0 } #define OPCONTEXT(op) \ - { isel_stringIfy(op), 0, op, 0, 0 } + { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), 0, 0 } #define INLINE_OP(op, memOp, immOp) \ - { isel_stringIfy(op), op, 0, memOp, immOp } + { "Runtime::" isel_stringIfy(op), offsetof(QV4::Runtime, op), INT_MIN, memOp, immOp } #define INLINE_OPCONTEXT(op, memOp, immOp) \ - { isel_stringIfy(op), 0, op, memOp, immOp } + { "Runtime::" isel_stringIfy(op), INT_MIN, offsetof(QV4::Runtime, op), memOp, immOp } #define NULL_OP \ { 0, 0, 0, 0, 0 } @@ -67,32 +67,32 @@ const Binop::OpInfo Binop::operations[IR::LastAluOp + 1] = { NULL_OP, // OpIncrement NULL_OP, // OpDecrement - INLINE_OP(Runtime::bitAnd, &Binop::inline_and32, &Binop::inline_and32), // OpBitAnd - INLINE_OP(Runtime::bitOr, &Binop::inline_or32, &Binop::inline_or32), // OpBitOr - INLINE_OP(Runtime::bitXor, &Binop::inline_xor32, &Binop::inline_xor32), // OpBitXor + INLINE_OP(bitAnd, &Binop::inline_and32, &Binop::inline_and32), // OpBitAnd + INLINE_OP(bitOr, &Binop::inline_or32, &Binop::inline_or32), // OpBitOr + INLINE_OP(bitXor, &Binop::inline_xor32, &Binop::inline_xor32), // OpBitXor - INLINE_OPCONTEXT(Runtime::add, &Binop::inline_add32, &Binop::inline_add32), // OpAdd - INLINE_OP(Runtime::sub, &Binop::inline_sub32, &Binop::inline_sub32), // OpSub - INLINE_OP(Runtime::mul, &Binop::inline_mul32, &Binop::inline_mul32), // OpMul + INLINE_OPCONTEXT(add, &Binop::inline_add32, &Binop::inline_add32), // OpAdd + INLINE_OP(sub, &Binop::inline_sub32, &Binop::inline_sub32), // OpSub + INLINE_OP(mul, &Binop::inline_mul32, &Binop::inline_mul32), // OpMul - OP(Runtime::div), // OpDiv - OP(Runtime::mod), // OpMod + OP(div), // OpDiv + OP(mod), // OpMod - INLINE_OP(Runtime::shl, &Binop::inline_shl32, &Binop::inline_shl32), // OpLShift - INLINE_OP(Runtime::shr, &Binop::inline_shr32, &Binop::inline_shr32), // OpRShift - INLINE_OP(Runtime::ushr, &Binop::inline_ushr32, &Binop::inline_ushr32), // OpURShift + INLINE_OP(shl, &Binop::inline_shl32, &Binop::inline_shl32), // OpLShift + INLINE_OP(shr, &Binop::inline_shr32, &Binop::inline_shr32), // OpRShift + INLINE_OP(ushr, &Binop::inline_ushr32, &Binop::inline_ushr32), // OpURShift - OP(Runtime::greaterThan), // OpGt - OP(Runtime::lessThan), // OpLt - OP(Runtime::greaterEqual), // OpGe - OP(Runtime::lessEqual), // OpLe - OP(Runtime::equal), // OpEqual - OP(Runtime::notEqual), // OpNotEqual - OP(Runtime::strictEqual), // OpStrictEqual - OP(Runtime::strictNotEqual), // OpStrictNotEqual + OP(greaterThan), // OpGt + OP(lessThan), // OpLt + OP(greaterEqual), // OpGe + OP(lessEqual), // OpLe + OP(equal), // OpEqual + OP(notEqual), // OpNotEqual + OP(strictEqual), // OpStrictEqual + OP(strictNotEqual), // OpStrictNotEqual - OPCONTEXT(Runtime::instanceof), // OpInstanceof - OPCONTEXT(Runtime::in), // OpIn + OPCONTEXT(instanceof), // OpInstanceof + OPCONTEXT(in), // OpIn NULL_OP, // OpAnd NULL_OP // OpOr @@ -121,16 +121,18 @@ void Binop::generate(IR::Expr *lhs, IR::Expr *rhs, IR::Expr *target) if (op == IR::OpAdd && (lhs->type == IR::StringType || rhs->type == IR::StringType)) { - const Binop::OpInfo stringAdd = OPCONTEXT(Runtime::addString); + const Binop::OpInfo stringAdd = OPCONTEXT(addString); info = stringAdd; } - if (info.fallbackImplementation) { - as->generateFunctionCallImp(target, info.name, info.fallbackImplementation, + RuntimeCall fallBack(info.fallbackImplementation); + RuntimeCall context(info.contextImplementation); + if (fallBack.isValid()) { + as->generateFunctionCallImp(target, info.name, fallBack, Assembler::PointerToValue(lhs), Assembler::PointerToValue(rhs)); - } else if (info.contextImplementation) { - as->generateFunctionCallImp(target, info.name, info.contextImplementation, + } else if (context.isValid()) { + as->generateFunctionCallImp(target, info.name, context, Assembler::EngineRegister, Assembler::PointerToValue(lhs), Assembler::PointerToValue(rhs)); diff --git a/src/qml/jit/qv4binop_p.h b/src/qml/jit/qv4binop_p.h index 791e335970..c246ee43b0 100644 --- a/src/qml/jit/qv4binop_p.h +++ b/src/qml/jit/qv4binop_p.h @@ -77,8 +77,8 @@ struct Binop { struct OpInfo { const char *name; - QV4::Runtime::BinaryOperation fallbackImplementation; - QV4::Runtime::BinaryOperationContext contextImplementation; + int fallbackImplementation; // offsetOf(Runtime,...) + int contextImplementation; // offsetOf(Runtime,...) MemRegOp inlineMemRegOp; ImmRegOp inlineImmRegOp; }; diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp index bf658fe689..1f5a247a17 100644 --- a/src/qml/jit/qv4isel_masm.cpp +++ b/src/qml/jit/qv4isel_masm.cpp @@ -49,6 +49,7 @@ #include "qv4assembler_p.h" #include "qv4unop_p.h" #include "qv4binop_p.h" +#include <private/qqmlpropertycache_p.h> #include <QtCore/QBuffer> #include <QtCore/QCoreApplication> @@ -159,12 +160,6 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) JSC::JSGlobalData dummy(_executableAllocator); JSC::LinkBuffer linkBuffer(dummy, this, 0); - QHash<void*, const char*> functions; - foreach (CallToLink ctl, _callsToLink) { - linkBuffer.link(ctl.call, ctl.externalFunction); - functions[linkBuffer.locationOf(ctl.label).dataLocation()] = ctl.functionName; - } - foreach (const DataLabelPatch &p, _dataLabelPatches) linkBuffer.patch(p.dataLabel, linkBuffer.locationOf(p.target)); @@ -193,6 +188,12 @@ JSC::MacroAssemblerCodeRef Assembler::link(int *codeSize) static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_ASM"); if (showCode) { + QHash<void*, const char*> functions; +#ifndef QT_NO_DEBUG + foreach (CallInfo call, _callInfos) + functions[linkBuffer.locationOf(call.label).dataLocation()] = call.functionName; +#endif + QBuffer buf; buf.open(QIODevice::WriteOnly); WTF::setDataFile(new QIODevicePrintStream(&buf)); @@ -393,12 +394,12 @@ void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args if (useFastLookups && func->global) { uint index = registerGlobalGetterLookup(*func->id); - generateFunctionCall(result, Runtime::callGlobalLookup, + generateRuntimeCall(result, callGlobalLookup, Assembler::EngineRegister, Assembler::TrustedImm32(index), baseAddressForCallData()); } else { - generateFunctionCall(result, Runtime::callActivationProperty, + generateRuntimeCall(result, callActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(*func->id), baseAddressForCallData()); @@ -410,11 +411,11 @@ void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base, int propertyIndex, IR::Expr *result) { if (kind == IR::Member::MemberOfQmlScopeObject) { - generateFunctionCall(result, Runtime::typeofScopeObjectProperty, Assembler::EngineRegister, + generateRuntimeCall(result, typeofScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex)); } else if (kind == IR::Member::MemberOfQmlContextObject) { - generateFunctionCall(result, Runtime::typeofContextObjectProperty, + generateRuntimeCall(result, typeofContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex)); } else { @@ -425,46 +426,46 @@ void InstructionSelection::callBuiltinTypeofQmlContextProperty(IR::Expr *base, void InstructionSelection::callBuiltinTypeofMember(IR::Expr *base, const QString &name, IR::Expr *result) { - generateFunctionCall(result, Runtime::typeofMember, Assembler::EngineRegister, + generateRuntimeCall(result, typeofMember, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::StringToIndex(name)); } void InstructionSelection::callBuiltinTypeofSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) { - generateFunctionCall(result, Runtime::typeofElement, + generateRuntimeCall(result, typeofElement, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::PointerToValue(index)); } void InstructionSelection::callBuiltinTypeofName(const QString &name, IR::Expr *result) { - generateFunctionCall(result, Runtime::typeofName, Assembler::EngineRegister, + generateRuntimeCall(result, typeofName, Assembler::EngineRegister, Assembler::StringToIndex(name)); } void InstructionSelection::callBuiltinTypeofValue(IR::Expr *value, IR::Expr *result) { - generateFunctionCall(result, Runtime::typeofValue, Assembler::EngineRegister, + generateRuntimeCall(result, typeofValue, Assembler::EngineRegister, Assembler::PointerToValue(value)); } void InstructionSelection::callBuiltinDeleteMember(IR::Expr *base, const QString &name, IR::Expr *result) { - generateFunctionCall(result, Runtime::deleteMember, Assembler::EngineRegister, + generateRuntimeCall(result, deleteMember, Assembler::EngineRegister, Assembler::Reference(base), Assembler::StringToIndex(name)); } void InstructionSelection::callBuiltinDeleteSubscript(IR::Expr *base, IR::Expr *index, IR::Expr *result) { - generateFunctionCall(result, Runtime::deleteElement, Assembler::EngineRegister, + generateRuntimeCall(result, deleteElement, Assembler::EngineRegister, Assembler::Reference(base), Assembler::PointerToValue(index)); } void InstructionSelection::callBuiltinDeleteName(const QString &name, IR::Expr *result) { - generateFunctionCall(result, Runtime::deleteName, Assembler::EngineRegister, + generateRuntimeCall(result, deleteName, Assembler::EngineRegister, Assembler::StringToIndex(name)); } @@ -475,7 +476,7 @@ void InstructionSelection::callBuiltinDeleteValue(IR::Expr *result) void InstructionSelection::callBuiltinThrow(IR::Expr *arg) { - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::throwException, Assembler::EngineRegister, + generateRuntimeCall(Assembler::ReturnValueRegister, throwException, Assembler::EngineRegister, Assembler::PointerToValue(arg)); } @@ -486,13 +487,13 @@ void InstructionSelection::callBuiltinReThrow() void InstructionSelection::callBuiltinUnwindException(IR::Expr *result) { - generateFunctionCall(result, Runtime::unwindException, Assembler::EngineRegister); + generateRuntimeCall(result, unwindException, Assembler::EngineRegister); } void InstructionSelection::callBuiltinPushCatchScope(const QString &exceptionName) { - generateFunctionCall(Assembler::Void, Runtime::pushCatchScope, Assembler::EngineRegister, Assembler::StringToIndex(exceptionName)); + generateRuntimeCall(Assembler::Void, pushCatchScope, Assembler::EngineRegister, Assembler::StringToIndex(exceptionName)); } void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::Expr *result) @@ -500,7 +501,7 @@ void InstructionSelection::callBuiltinForeachIteratorObject(IR::Expr *arg, IR::E Q_ASSERT(arg); Q_ASSERT(result); - generateFunctionCall(result, Runtime::foreachIterator, Assembler::EngineRegister, Assembler::PointerToValue(arg)); + generateRuntimeCall(result, foreachIterator, Assembler::EngineRegister, Assembler::PointerToValue(arg)); } void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR::Expr *result) @@ -508,24 +509,24 @@ void InstructionSelection::callBuiltinForeachNextPropertyname(IR::Expr *arg, IR: Q_ASSERT(arg); Q_ASSERT(result); - generateFunctionCall(result, Runtime::foreachNextPropertyName, Assembler::Reference(arg)); + generateRuntimeCall(result, foreachNextPropertyName, Assembler::Reference(arg)); } void InstructionSelection::callBuiltinPushWithScope(IR::Expr *arg) { Q_ASSERT(arg); - generateFunctionCall(Assembler::Void, Runtime::pushWithScope, Assembler::Reference(arg), Assembler::EngineRegister); + generateRuntimeCall(Assembler::Void, pushWithScope, Assembler::Reference(arg), Assembler::EngineRegister); } void InstructionSelection::callBuiltinPopScope() { - generateFunctionCall(Assembler::Void, Runtime::popScope, Assembler::EngineRegister); + generateRuntimeCall(Assembler::Void, popScope, Assembler::EngineRegister); } void InstructionSelection::callBuiltinDeclareVar(bool deletable, const QString &name) { - generateFunctionCall(Assembler::Void, Runtime::declareVar, Assembler::EngineRegister, + generateRuntimeCall(Assembler::Void, declareVar, Assembler::EngineRegister, Assembler::TrustedImm32(deletable), Assembler::StringToIndex(name)); } @@ -534,7 +535,7 @@ void InstructionSelection::callBuiltinDefineArray(IR::Expr *result, IR::ExprList Q_ASSERT(result); int length = prepareVariableArguments(args); - generateFunctionCall(result, Runtime::arrayLiteral, Assembler::EngineRegister, + generateRuntimeCall(result, arrayLiteral, Assembler::EngineRegister, baseAddressForCallArguments(), Assembler::TrustedImm32(length)); } @@ -614,19 +615,19 @@ void InstructionSelection::callBuiltinDefineObjectLiteral(IR::Expr *result, int it = it->next; } - generateFunctionCall(result, Runtime::objectLiteral, Assembler::EngineRegister, + generateRuntimeCall(result, objectLiteral, Assembler::EngineRegister, baseAddressForCallArguments(), Assembler::TrustedImm32(classId), Assembler::TrustedImm32(arrayValueCount), Assembler::TrustedImm32(arrayGetterSetterCount | (needSparseArray << 30))); } void InstructionSelection::callBuiltinSetupArgumentObject(IR::Expr *result) { - generateFunctionCall(result, Runtime::setupArgumentsObject, Assembler::EngineRegister); + generateRuntimeCall(result, setupArgumentsObject, Assembler::EngineRegister); } void InstructionSelection::callBuiltinConvertThisToObject() { - generateFunctionCall(Assembler::Void, Runtime::convertThisToObject, Assembler::EngineRegister); + generateRuntimeCall(Assembler::Void, convertThisToObject, Assembler::EngineRegister); } void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Expr *result) @@ -635,11 +636,11 @@ void InstructionSelection::callValue(IR::Expr *value, IR::ExprList *args, IR::Ex prepareCallData(args, 0); if (value->asConst()) - generateFunctionCall(result, Runtime::callValue, Assembler::EngineRegister, + generateRuntimeCall(result, callValue, Assembler::EngineRegister, Assembler::PointerToValue(value), baseAddressForCallData()); else - generateFunctionCall(result, Runtime::callValue, Assembler::EngineRegister, + generateRuntimeCall(result, callValue, Assembler::EngineRegister, Assembler::Reference(value), baseAddressForCallData()); } @@ -659,17 +660,17 @@ void InstructionSelection::loadThisObject(IR::Expr *temp) void InstructionSelection::loadQmlContext(IR::Expr *temp) { - generateFunctionCall(temp, Runtime::getQmlContext, Assembler::EngineRegister); + generateRuntimeCall(temp, getQmlContext, Assembler::EngineRegister); } void InstructionSelection::loadQmlImportedScripts(IR::Expr *temp) { - generateFunctionCall(temp, Runtime::getQmlImportedScripts, Assembler::EngineRegister); + generateRuntimeCall(temp, getQmlImportedScripts, Assembler::EngineRegister); } void InstructionSelection::loadQmlSingleton(const QString &name, IR::Expr *temp) { - generateFunctionCall(temp, Runtime::getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name)); + generateRuntimeCall(temp, getQmlSingleton, Assembler::EngineRegister, Assembler::StringToIndex(name)); } void InstructionSelection::loadConst(IR::Const *sourceConst, IR::Expr *target) @@ -716,7 +717,7 @@ void InstructionSelection::loadString(const QString &str, IR::Expr *target) void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target) { int id = registerRegExp(sourceRegexp); - generateFunctionCall(target, Runtime::regexpLiteral, Assembler::EngineRegister, Assembler::TrustedImm32(id)); + generateRuntimeCall(target, regexpLiteral, Assembler::EngineRegister, Assembler::TrustedImm32(id)); } void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target) @@ -726,20 +727,20 @@ void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr generateLookupCall(target, index, qOffsetOf(QV4::Lookup, globalGetter), Assembler::EngineRegister, Assembler::Void); return; } - generateFunctionCall(target, Runtime::getActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(*name->id)); + generateRuntimeCall(target, getActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(*name->id)); } void InstructionSelection::setActivationProperty(IR::Expr *source, const QString &targetName) { // ### should use a lookup call here - generateFunctionCall(Assembler::Void, Runtime::setActivationProperty, + generateRuntimeCall(Assembler::Void, setActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(targetName), Assembler::PointerToValue(source)); } void InstructionSelection::initClosure(IR::Closure *closure, IR::Expr *target) { int id = closure->value; - generateFunctionCall(target, Runtime::closure, Assembler::EngineRegister, Assembler::TrustedImm32(id)); + generateRuntimeCall(target, closure, Assembler::EngineRegister, Assembler::TrustedImm32(id)); } void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR::Expr *target) @@ -748,32 +749,106 @@ void InstructionSelection::getProperty(IR::Expr *base, const QString &name, IR:: uint index = registerGetterLookup(name); generateLookupCall(target, index, qOffsetOf(QV4::Lookup, getter), Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::Void); } else { - generateFunctionCall(target, Runtime::getProperty, Assembler::EngineRegister, + generateRuntimeCall(target, getProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::StringToIndex(name)); } } -void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, int index, IR::Expr *target) +void InstructionSelection::getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target) { + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (kind == IR::Member::MemberOfQmlScopeObject) { + if (property->propType == QMetaType::QReal) { + generateRuntimeCall(target, accessQmlScopeObjectQRealProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->isQObject()) { + generateRuntimeCall(target, accessQmlScopeObjectQObjectProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->propType == QMetaType::Int) { + generateRuntimeCall(target, accessQmlScopeObjectIntProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->propType == QMetaType::Bool) { + generateRuntimeCall(target, accessQmlScopeObjectBoolProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } else if (property->propType == QMetaType::QString) { + generateRuntimeCall(target, accessQmlScopeObjectQStringProperty, + Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors)); + return; + } + } + } + if (kind == IR::Member::MemberOfQmlScopeObject) - generateFunctionCall(target, Runtime::getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); + generateRuntimeCall(target, getQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); else if (kind == IR::Member::MemberOfQmlContextObject) - generateFunctionCall(target, Runtime::getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); + generateRuntimeCall(target, getQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); else if (kind == IR::Member::MemberOfIdObjectsArray) - generateFunctionCall(target, Runtime::getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); + generateRuntimeCall(target, getQmlIdObject, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(index)); else Q_ASSERT(false); } -void InstructionSelection::getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target) +void InstructionSelection::getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target) { + if (property && property->hasAccessors() && property->isFullyResolved()) { + if (!attachedPropertiesId && !isSingleton) { + const int notifyIndex = captureRequired ? property->notifyIndex : -1; + if (property->propType == QMetaType::QReal) { + generateRuntimeCall(target, accessQObjectQRealProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->isQObject()) { + generateRuntimeCall(target, accessQObjectQObjectProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->propType == QMetaType::Int) { + generateRuntimeCall(target, accessQObjectIntProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->propType == QMetaType::Bool) { + generateRuntimeCall(target, accessQObjectBoolProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } else if (property->propType == QMetaType::QString) { + generateRuntimeCall(target, accessQObjectQStringProperty, + Assembler::EngineRegister, Assembler::PointerToValue(base), + Assembler::TrustedImmPtr(property->accessors), + Assembler::TrustedImm32(property->coreIndex), + Assembler::TrustedImm32(notifyIndex)); + return; + } + } + } + + const int propertyIndex = property->coreIndex; if (attachedPropertiesId != 0) - generateFunctionCall(target, Runtime::getQmlAttachedProperty, Assembler::EngineRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex)); + generateRuntimeCall(target, getQmlAttachedProperty, Assembler::EngineRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex)); else if (isSingleton) - generateFunctionCall(target, Runtime::getQmlSingletonQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex), + generateRuntimeCall(target, getQmlSingletonQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex), Assembler::TrustedImm32(captureRequired)); else - generateFunctionCall(target, Runtime::getQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex), + generateRuntimeCall(target, getQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex), Assembler::TrustedImm32(captureRequired)); } @@ -787,7 +862,7 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase, Assembler::PointerToValue(targetBase), Assembler::PointerToValue(source)); } else { - generateFunctionCall(Assembler::Void, Runtime::setProperty, Assembler::EngineRegister, + generateRuntimeCall(Assembler::Void, setProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), Assembler::StringToIndex(targetName), Assembler::PointerToValue(source)); } @@ -796,10 +871,10 @@ void InstructionSelection::setProperty(IR::Expr *source, IR::Expr *targetBase, void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex) { if (kind == IR::Member::MemberOfQmlScopeObject) - generateFunctionCall(Assembler::Void, Runtime::setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), + generateRuntimeCall(Assembler::Void, setQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source)); else if (kind == IR::Member::MemberOfQmlContextObject) - generateFunctionCall(Assembler::Void, Runtime::setQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), + generateRuntimeCall(Assembler::Void, setQmlContextObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source)); else Q_ASSERT(false); @@ -807,7 +882,7 @@ void InstructionSelection::setQmlContextProperty(IR::Expr *source, IR::Expr *tar void InstructionSelection::setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex) { - generateFunctionCall(Assembler::Void, Runtime::setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), + generateRuntimeCall(Assembler::Void, setQmlQObjectProperty, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), Assembler::TrustedImm32(propertyIndex), Assembler::PointerToValue(source)); } @@ -821,7 +896,7 @@ void InstructionSelection::getElement(IR::Expr *base, IR::Expr *index, IR::Expr return; } - generateFunctionCall(target, Runtime::getElement, Assembler::EngineRegister, + generateRuntimeCall(target, getElement, Assembler::EngineRegister, Assembler::PointerToValue(base), Assembler::PointerToValue(index)); } @@ -834,7 +909,7 @@ void InstructionSelection::setElement(IR::Expr *source, IR::Expr *targetBase, IR Assembler::PointerToValue(source)); return; } - generateFunctionCall(Assembler::Void, Runtime::setElement, Assembler::EngineRegister, + generateRuntimeCall(Assembler::Void, setElement, Assembler::EngineRegister, Assembler::PointerToValue(targetBase), Assembler::PointerToValue(targetIndex), Assembler::PointerToValue(source)); } @@ -981,9 +1056,9 @@ void InstructionSelection::swapValues(IR::Expr *source, IR::Expr *target) } #define setOp(op, opName, operation) \ - do { op = operation; opName = isel_stringIfy(operation); } while (0) + do { op = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); } while (0) #define setOpContext(op, opName, operation) \ - do { opContext = operation; opName = isel_stringIfy(operation); } while (0) + do { opContext = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); opName = "Runtime::" isel_stringIfy(operation); } while (0) void InstructionSelection::unop(IR::AluOp oper, IR::Expr *source, IR::Expr *target) { @@ -1003,12 +1078,12 @@ void InstructionSelection::callQmlContextProperty(IR::Expr *base, IR::Member::Me prepareCallData(args, base); if (kind == IR::Member::MemberOfQmlScopeObject) - generateFunctionCall(result, Runtime::callQmlScopeObjectProperty, + generateRuntimeCall(result, callQmlScopeObjectProperty, Assembler::EngineRegister, Assembler::TrustedImm32(propertyIndex), baseAddressForCallData()); else if (kind == IR::Member::MemberOfQmlContextObject) - generateFunctionCall(result, Runtime::callQmlContextObjectProperty, + generateRuntimeCall(result, callQmlContextObjectProperty, Assembler::EngineRegister, Assembler::TrustedImm32(propertyIndex), baseAddressForCallData()); @@ -1025,12 +1100,12 @@ void InstructionSelection::callProperty(IR::Expr *base, const QString &name, IR: if (useFastLookups) { uint index = registerGetterLookup(name); - generateFunctionCall(result, Runtime::callPropertyLookup, + generateRuntimeCall(result, callPropertyLookup, Assembler::EngineRegister, Assembler::TrustedImm32(index), baseAddressForCallData()); } else { - generateFunctionCall(result, Runtime::callProperty, Assembler::EngineRegister, + generateRuntimeCall(result, callProperty, Assembler::EngineRegister, Assembler::StringToIndex(name), baseAddressForCallData()); } @@ -1042,7 +1117,7 @@ void InstructionSelection::callSubscript(IR::Expr *base, IR::Expr *index, IR::Ex Q_ASSERT(base != 0); prepareCallData(args, base); - generateFunctionCall(result, Runtime::callElement, Assembler::EngineRegister, + generateRuntimeCall(result, callElement, Assembler::EngineRegister, Assembler::PointerToValue(index), baseAddressForCallData()); } @@ -1118,7 +1193,7 @@ void InstructionSelection::convertTypeToDouble(IR::Expr *source, IR::Expr *targe Assembler::TrustedImm32(Value::NotDouble_Mask)); #endif - generateFunctionCall(target, Runtime::toDouble, Assembler::PointerToValue(source)); + generateRuntimeCall(target, toDouble, Assembler::PointerToValue(source)); Assembler::Jump noDoubleDone = _as->jump(); // it is a double: @@ -1183,7 +1258,7 @@ void InstructionSelection::convertTypeToBool(IR::Expr *source, IR::Expr *target) case IR::StringType: case IR::VarType: default: - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toBoolean, + generateRuntimeCall(Assembler::ReturnValueRegister, toBoolean, Assembler::PointerToValue(source)); _as->storeBool(Assembler::ReturnValueRegister, target); break; @@ -1215,7 +1290,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe // not an int: fallback.link(_as); - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt, + generateRuntimeCall(Assembler::ReturnValueRegister, toInt, _as->loadAddress(Assembler::ScratchRegister, source)); isInt.link(_as); @@ -1253,7 +1328,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe // not an int: fallback.link(_as); - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt, + generateRuntimeCall(Assembler::ReturnValueRegister, toInt, _as->loadAddress(Assembler::ScratchRegister, source)); _as->storeInt32(Assembler::ReturnValueRegister, target); @@ -1266,7 +1341,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe _as->branchTruncateDoubleToInt32(_as->toDoubleRegister(source), Assembler::ReturnValueRegister, Assembler::BranchIfTruncateSuccessful); - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::doubleToInt, + generateRuntimeCall(Assembler::ReturnValueRegister, doubleToInt, Assembler::PointerToValue(source)); success.link(_as); _as->storeInt32(Assembler::ReturnValueRegister, target); @@ -1284,7 +1359,7 @@ void InstructionSelection::convertTypeToSInt32(IR::Expr *source, IR::Expr *targe break; case IR::StringType: default: - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toInt, + generateRuntimeCall(Assembler::ReturnValueRegister, toInt, _as->loadAddress(Assembler::ScratchRegister, source)); _as->storeInt32(Assembler::ReturnValueRegister, target); break; @@ -1309,7 +1384,7 @@ void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *targe // not an int: isNoInt.link(_as); - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toUInt, + generateRuntimeCall(Assembler::ReturnValueRegister, toUInt, _as->loadAddress(Assembler::ScratchRegister, source)); _as->storeInt32(Assembler::ReturnValueRegister, target); @@ -1320,7 +1395,7 @@ void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *targe Assembler::Jump success = _as->branchTruncateDoubleToUint32(reg, Assembler::ReturnValueRegister, Assembler::BranchIfTruncateSuccessful); - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::doubleToUInt, + generateRuntimeCall(Assembler::ReturnValueRegister, doubleToUInt, Assembler::PointerToValue(source)); success.link(_as); _as->storeUInt32(Assembler::ReturnValueRegister, target); @@ -1331,7 +1406,7 @@ void InstructionSelection::convertTypeToUInt32(IR::Expr *source, IR::Expr *targe _as->storeUInt32(Assembler::ReturnValueRegister, target); break; case IR::StringType: - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toUInt, + generateRuntimeCall(Assembler::ReturnValueRegister, toUInt, Assembler::PointerToValue(source)); _as->storeUInt32(Assembler::ReturnValueRegister, target); break; @@ -1351,13 +1426,13 @@ void InstructionSelection::constructActivationProperty(IR::Name *func, IR::ExprL if (useFastLookups && func->global) { uint index = registerGlobalGetterLookup(*func->id); - generateFunctionCall(result, Runtime::constructGlobalLookup, + generateRuntimeCall(result, constructGlobalLookup, Assembler::EngineRegister, Assembler::TrustedImm32(index), baseAddressForCallData()); return; } - generateFunctionCall(result, Runtime::constructActivationProperty, + generateRuntimeCall(result, constructActivationProperty, Assembler::EngineRegister, Assembler::StringToIndex(*func->id), baseAddressForCallData()); @@ -1369,14 +1444,14 @@ void InstructionSelection::constructProperty(IR::Expr *base, const QString &name prepareCallData(args, base); if (useFastLookups) { uint index = registerGetterLookup(name); - generateFunctionCall(result, Runtime::constructPropertyLookup, + generateRuntimeCall(result, constructPropertyLookup, Assembler::EngineRegister, Assembler::TrustedImm32(index), baseAddressForCallData()); return; } - generateFunctionCall(result, Runtime::constructProperty, Assembler::EngineRegister, + generateRuntimeCall(result, constructProperty, Assembler::EngineRegister, Assembler::StringToIndex(name), baseAddressForCallData()); } @@ -1386,7 +1461,7 @@ void InstructionSelection::constructValue(IR::Expr *value, IR::ExprList *args, I Q_ASSERT(value != 0); prepareCallData(args, 0); - generateFunctionCall(result, Runtime::constructValue, + generateRuntimeCall(result, constructValue, Assembler::EngineRegister, Assembler::Reference(value), baseAddressForCallData()); @@ -1422,7 +1497,7 @@ void InstructionSelection::visitCJump(IR::CJump *s) booleanConversion.link(_as); reg = Assembler::ReturnValueRegister; - generateFunctionCall(reg, Runtime::toBoolean, Assembler::Reference(s->cond)); + generateRuntimeCall(reg, toBoolean, Assembler::Reference(s->cond)); testBoolean.link(_as); } @@ -1432,7 +1507,7 @@ void InstructionSelection::visitCJump(IR::CJump *s) } else if (IR::Const *c = s->cond->asConst()) { // TODO: SSA optimization for constant condition evaluation should remove this. // See also visitCJump() in RegAllocInfo. - generateFunctionCall(Assembler::ReturnValueRegister, Runtime::toBoolean, + generateRuntimeCall(Assembler::ReturnValueRegister, toBoolean, Assembler::PointerToValue(c)); _as->generateCJumpOnNonZero(Assembler::ReturnValueRegister, _block, s->iftrue, s->iffalse); return; @@ -1454,8 +1529,8 @@ void InstructionSelection::visitCJump(IR::CJump *s) return; } - Runtime::CompareOperation op = 0; - Runtime::CompareOperationContext opContext = 0; + RuntimeCall op; + RuntimeCall opContext; const char *opName = 0; switch (b->op) { default: Q_UNREACHABLE(); Q_ASSERT(!"todo"); break; @@ -1476,7 +1551,7 @@ void InstructionSelection::visitCJump(IR::CJump *s) // if (true === true) ..... // Of course, after folding the CJUMP to a JUMP, dead-code (dead-basic-block) // elimination (which isn't there either) would remove the whole else block. - if (opContext) + if (opContext.isValid()) _as->generateFunctionCallImp(Assembler::ReturnValueRegister, opName, opContext, Assembler::EngineRegister, Assembler::PointerToValue(b->left), @@ -1800,7 +1875,7 @@ void InstructionSelection::visitCJumpStrict(IR::Binop *binop, IR::BasicBlock *tr IR::Expr *left = binop->left; IR::Expr *right = binop->right; - _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "Runtime::compareStrictEqual", Runtime::compareStrictEqual, + generateRuntimeCall(Assembler::ReturnValueRegister, compareStrictEqual, Assembler::PointerToValue(left), Assembler::PointerToValue(right)); _as->generateCJumpOnCompare(binop->op == IR::OpStrictEqual ? Assembler::NotEqual : Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0), @@ -1954,7 +2029,7 @@ void InstructionSelection::visitCJumpEqual(IR::Binop *binop, IR::BasicBlock *tru IR::Expr *left = binop->left; IR::Expr *right = binop->right; - _as->generateFunctionCallImp(Assembler::ReturnValueRegister, "Runtime::compareEqual", Runtime::compareEqual, + generateRuntimeCall(Assembler::ReturnValueRegister, compareEqual, Assembler::PointerToValue(left), Assembler::PointerToValue(right)); _as->generateCJumpOnCompare(binop->op == IR::OpEqual ? Assembler::NotEqual : Assembler::Equal, Assembler::ReturnValueRegister, Assembler::TrustedImm32(0), diff --git a/src/qml/jit/qv4isel_masm_p.h b/src/qml/jit/qv4isel_masm_p.h index 366d510072..db9d440e83 100644 --- a/src/qml/jit/qv4isel_masm_p.h +++ b/src/qml/jit/qv4isel_masm_p.h @@ -124,8 +124,8 @@ protected: virtual void setActivationProperty(IR::Expr *source, const QString &targetName); virtual void initClosure(IR::Closure *closure, IR::Expr *target); virtual void getProperty(IR::Expr *base, const QString &name, IR::Expr *target); - virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, int index, IR::Expr *target); - virtual void getQObjectProperty(IR::Expr *base, int propertyIndex, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); + virtual void getQmlContextProperty(IR::Expr *source, IR::Member::MemberKind kind, QQmlPropertyData *property, int index, IR::Expr *target); + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData *property, bool captureRequired, bool isSingleton, int attachedPropertiesId, IR::Expr *target); virtual void setProperty(IR::Expr *source, IR::Expr *targetBase, const QString &targetName); virtual void setQmlContextProperty(IR::Expr *source, IR::Expr *targetBase, IR::Member::MemberKind kind, int propertyIndex); virtual void setQObjectProperty(IR::Expr *source, IR::Expr *targetBase, int propertyIndex); @@ -244,8 +244,8 @@ private: #define isel_stringIfyx(s) #s #define isel_stringIfy(s) isel_stringIfyx(s) - #define generateFunctionCall(t, function, ...) \ - _as->generateFunctionCallImp(t, isel_stringIfy(function), function, __VA_ARGS__) + #define generateRuntimeCall(t, function, ...) \ + _as->generateFunctionCallImp(t, "Runtime::" isel_stringIfy(function), RuntimeCall(qOffsetOf(QV4::Runtime, function)), __VA_ARGS__) int prepareVariableArguments(IR::ExprList* args); int prepareCallData(IR::ExprList* args, IR::Expr *thisObject); diff --git a/src/qml/jit/qv4regalloc.cpp b/src/qml/jit/qv4regalloc.cpp index 131e0a5b0a..6b5b79e458 100644 --- a/src/qml/jit/qv4regalloc.cpp +++ b/src/qml/jit/qv4regalloc.cpp @@ -528,14 +528,14 @@ protected: // IRDecoder addCall(); } - virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, int /*index*/, IR::Expr *target) + virtual void getQmlContextProperty(IR::Expr *base, IR::Member::MemberKind /*kind*/, QQmlPropertyData * /*property*/, int /*index*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); addCall(); } - virtual void getQObjectProperty(IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target) + virtual void getQObjectProperty(IR::Expr *base, QQmlPropertyData * /*property*/, bool /*captureRequired*/, bool /*isSingleton*/, int /*attachedPropertiesId*/, IR::Expr *target) { addDef(target); addUses(base->asTemp(), Use::CouldHaveRegister); diff --git a/src/qml/jit/qv4unop.cpp b/src/qml/jit/qv4unop.cpp index cb9131d731..6a32069ac4 100644 --- a/src/qml/jit/qv4unop.cpp +++ b/src/qml/jit/qv4unop.cpp @@ -47,11 +47,11 @@ using namespace JIT; #define stringIfyx(s) #s #define stringIfy(s) stringIfyx(s) #define setOp(operation) \ - do { call = operation; name = stringIfy(operation); } while (0) + do { call = RuntimeCall(qOffsetOf(QV4::Runtime, operation)); name = "Runtime::" stringIfy(operation); } while (0) void Unop::generate(IR::Expr *source, IR::Expr *target) { - Runtime::UnaryOperation call = 0; + RuntimeCall call; const char *name = 0; switch (op) { case IR::OpNot: @@ -60,19 +60,18 @@ void Unop::generate(IR::Expr *source, IR::Expr *target) case IR::OpUMinus: generateUMinus(source, target); return; - case IR::OpUPlus: setOp(Runtime::uPlus); break; + case IR::OpUPlus: setOp(uPlus); break; case IR::OpCompl: generateCompl(source, target); return; - case IR::OpIncrement: setOp(Runtime::increment); break; - case IR::OpDecrement: setOp(Runtime::decrement); break; + case IR::OpIncrement: setOp(increment); break; + case IR::OpDecrement: setOp(decrement); break; default: Q_UNREACHABLE(); } // switch - if (call) { - as->generateFunctionCallImp(target, name, call, Assembler::PointerToValue(source)); - } + Q_ASSERT(call.isValid()); + _as->generateFunctionCallImp(target, name, call, Assembler::PointerToValue(source)); } void Unop::generateUMinus(IR::Expr *source, IR::Expr *target) @@ -82,15 +81,15 @@ void Unop::generateUMinus(IR::Expr *source, IR::Expr *target) Assembler::RegisterID tReg = Assembler::ScratchRegister; if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) tReg = (Assembler::RegisterID) targetTemp->index; - Assembler::RegisterID sReg = as->toInt32Register(source, tReg); - as->move(sReg, tReg); - as->neg32(tReg); + Assembler::RegisterID sReg = _as->toInt32Register(source, tReg); + _as->move(sReg, tReg); + _as->neg32(tReg); if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister) - as->storeInt32(tReg, target); + _as->storeInt32(tReg, target); return; } - as->generateFunctionCallImp(target, "Runtime::uMinus", Runtime::uMinus, Assembler::PointerToValue(source)); + generateRuntimeCall(target, uMinus, Assembler::PointerToValue(source)); } void Unop::generateNot(IR::Expr *source, IR::Expr *target) @@ -100,26 +99,26 @@ void Unop::generateNot(IR::Expr *source, IR::Expr *target) Assembler::RegisterID tReg = Assembler::ScratchRegister; if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) tReg = (Assembler::RegisterID) targetTemp->index; - as->xor32(Assembler::TrustedImm32(0x1), as->toInt32Register(source, tReg), tReg); + _as->xor32(Assembler::TrustedImm32(0x1), _as->toInt32Register(source, tReg), tReg); if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister) - as->storeBool(tReg, target); + _as->storeBool(tReg, target); return; } else if (source->type == IR::SInt32Type) { Assembler::RegisterID tReg = Assembler::ScratchRegister; if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) tReg = (Assembler::RegisterID) targetTemp->index; - as->compare32(Assembler::Equal, - as->toInt32Register(source, Assembler::ScratchRegister), Assembler::TrustedImm32(0), + _as->compare32(Assembler::Equal, + _as->toInt32Register(source, Assembler::ScratchRegister), Assembler::TrustedImm32(0), tReg); if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister) - as->storeBool(tReg, target); + _as->storeBool(tReg, target); return; } else if (source->type == IR::DoubleType) { // ### } // ## generic implementation testing for int/bool - as->generateFunctionCallImp(target, "Runtime::uNot", Runtime::uNot, Assembler::PointerToValue(source)); + generateRuntimeCall(target, uNot, Assembler::PointerToValue(source)); } void Unop::generateCompl(IR::Expr *source, IR::Expr *target) @@ -129,12 +128,12 @@ void Unop::generateCompl(IR::Expr *source, IR::Expr *target) Assembler::RegisterID tReg = Assembler::ScratchRegister; if (targetTemp && targetTemp->kind == IR::Temp::PhysicalRegister) tReg = (Assembler::RegisterID) targetTemp->index; - as->xor32(Assembler::TrustedImm32(0xffffffff), as->toInt32Register(source, tReg), tReg); + _as->xor32(Assembler::TrustedImm32(0xffffffff), _as->toInt32Register(source, tReg), tReg); if (!targetTemp || targetTemp->kind != IR::Temp::PhysicalRegister) - as->storeInt32(tReg, target); + _as->storeInt32(tReg, target); return; } - as->generateFunctionCallImp(target, "Runtime::complement", Runtime::complement, Assembler::PointerToValue(source)); + generateRuntimeCall(target, complement, Assembler::PointerToValue(source)); } #endif diff --git a/src/qml/jit/qv4unop_p.h b/src/qml/jit/qv4unop_p.h index f0b5b9c223..1141a84913 100644 --- a/src/qml/jit/qv4unop_p.h +++ b/src/qml/jit/qv4unop_p.h @@ -64,7 +64,7 @@ class Assembler; struct Unop { Unop(Assembler *assembler, IR::AluOp operation) - : as(assembler) + : _as(assembler) , op(operation) {} @@ -74,7 +74,7 @@ struct Unop { void generateNot(IR::Expr *source, IR::Expr *target); void generateCompl(IR::Expr *source, IR::Expr *target); - Assembler *as; + Assembler *_as; IR::AluOp op; }; diff --git a/src/qml/jsapi/qjsvalue.cpp b/src/qml/jsapi/qjsvalue.cpp index e369842252..edb23d94db 100644 --- a/src/qml/jsapi/qjsvalue.cpp +++ b/src/qml/jsapi/qjsvalue.cpp @@ -938,7 +938,7 @@ bool QJSValue::equals(const QJSValue& other) const if (!ov) return other.equals(*this); - return Runtime::compareEqual(*v, *ov); + return Runtime::method_compareEqual(*v, *ov); } /*! diff --git a/src/qml/jsruntime/jsruntime.pri b/src/qml/jsruntime/jsruntime.pri index 038b23e8d3..6ef92511e2 100644 --- a/src/qml/jsruntime/jsruntime.pri +++ b/src/qml/jsruntime/jsruntime.pri @@ -99,6 +99,7 @@ HEADERS += \ HEADERS += \ $$PWD/qv4runtime_p.h \ + $$PWD/qv4runtimeapi_p.h \ $$PWD/qv4value_p.h \ $$PWD/qv4string_p.h \ $$PWD/qv4value_p.h diff --git a/src/qml/jsruntime/qv4arraydata.cpp b/src/qml/jsruntime/qv4arraydata.cpp index 728ee38e76..73aa7047b8 100644 --- a/src/qml/jsruntime/qv4arraydata.cpp +++ b/src/qml/jsruntime/qv4arraydata.cpp @@ -676,7 +676,7 @@ bool ArrayElementLessThan::operator()(Value v1, Value v2) const callData->thisObject = Primitive::undefinedValue(); callData->args[0] = v1; callData->args[1] = v2; - result = Runtime::callValue(scope.engine, m_comparefn, callData); + result = scope.engine->runtime.callValue(scope.engine, m_comparefn, callData); return result->toNumber() < 0; } diff --git a/src/qml/jsruntime/qv4dateobject.cpp b/src/qml/jsruntime/qv4dateobject.cpp index 8e4ebb3cb0..5783e8fa2b 100644 --- a/src/qml/jsruntime/qv4dateobject.cpp +++ b/src/qml/jsruntime/qv4dateobject.cpp @@ -466,7 +466,7 @@ static inline double ParseString(const QString &s) if (format < Minute || format >= TimezoneHour) error = true; format = TimezoneHour; - } else if (*ch == 'Z' || *ch == 0) { + } else if (*ch == 'Z' || ch->unicode() == 0) { format = Done; } current = 0; diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp index bc64bbfe06..55ea1f91c3 100644 --- a/src/qml/jsruntime/qv4engine.cpp +++ b/src/qml/jsruntime/qv4engine.cpp @@ -1220,7 +1220,7 @@ static QVariant toVariant(QV4::ExecutionEngine *e, const QV4::Value &value, int return ld->d()->locale; if (const QV4::DateObject *d = value.as<DateObject>()) return d->toQDateTime(); - if (const QV4::ArrayBuffer *d = value.as<ArrayBuffer>()) + if (const ArrayBuffer *d = value.as<ArrayBuffer>()) return d->asByteArray(); // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)! @@ -1348,6 +1348,8 @@ QV4::ReturnedValue QV4::ExecutionEngine::fromVariant(const QVariant &variant) return QV4::Encode(*reinterpret_cast<const double*>(ptr)); case QMetaType::QString: return newString(*reinterpret_cast<const QString*>(ptr))->asReturnedValue(); + case QMetaType::QByteArray: + return newArrayBuffer(*reinterpret_cast<const QByteArray*>(ptr))->asReturnedValue(); case QMetaType::Float: return QV4::Encode(*reinterpret_cast<const float*>(ptr)); case QMetaType::Short: @@ -1524,6 +1526,8 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data) return QV4::Encode(*reinterpret_cast<const double*>(data)); case QMetaType::QString: return newString(*reinterpret_cast<const QString*>(data))->asReturnedValue(); + case QMetaType::QByteArray: + return newArrayBuffer(*reinterpret_cast<const QByteArray*>(data))->asReturnedValue(); case QMetaType::Float: return QV4::Encode(*reinterpret_cast<const float*>(data)); case QMetaType::Short: @@ -1616,6 +1620,12 @@ bool ExecutionEngine::metaTypeFromJS(const Value *value, int type, void *data) else *reinterpret_cast<QString*>(data) = value->toQString(); return true; + case QMetaType::QByteArray: + if (const ArrayBuffer *ab = value->as<ArrayBuffer>()) + *reinterpret_cast<QByteArray*>(data) = ab->asByteArray(); + else + *reinterpret_cast<QByteArray*>(data) = QByteArray(); + return true; case QMetaType::Float: *reinterpret_cast<float*>(data) = value->toNumber(); return true; diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h index 7da4a1c3c1..57a5952a6d 100644 --- a/src/qml/jsruntime/qv4engine_p.h +++ b/src/qml/jsruntime/qv4engine_p.h @@ -55,6 +55,7 @@ #include "qv4managed_p.h" #include "qv4context_p.h" #include "qv4internalclass_p.h" +#include "qv4runtimeapi_p.h" #include <private/qintrusivelist_p.h> namespace WTF { @@ -109,6 +110,8 @@ public: Value *jsStackLimit; quintptr cStackLimit; + Runtime runtime; + WTF::BumpPointerAllocator *bumperPointerAllocator; // Used by Yarr Regex engine. enum { JSStackLimit = 4*1024*1024 }; @@ -473,6 +476,13 @@ public: void assertObjectBelongsToEngine(const Heap::Base &baseObject); }; +// This is a trick to tell the code generators that functions taking a NoThrowContext won't +// throw exceptions and therefore don't need a check after the call. +struct NoThrowEngine : public ExecutionEngine +{ +}; + + inline void ExecutionEngine::pushContext(Heap::ExecutionContext *context) { Q_ASSERT(currentContext && context); diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index 29f83da522..b3462fe9b1 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -41,8 +41,10 @@ #include "qv4scopedvalue_p.h" #include <QtQml/qjsengine.h> +#ifndef QT_NO_NETWORK #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkreply.h> +#endif #include <QtCore/qfile.h> #include <QtQml/qqmlfile.h> @@ -57,7 +59,10 @@ QT_BEGIN_NAMESPACE QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, QV4::QmlContext *qmlContext, const QV4::Value &callback) - : v4(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0) + : v4(engine), m_url(url) +#ifndef QT_NO_NETWORK + , m_redirectCount(0), m_network(0) , m_reply(0) +#endif { if (qmlContext) m_qmlContext.set(engine, *qmlContext); @@ -66,6 +71,7 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, m_resultObject.set(v4, resultValue(v4)); +#ifndef QT_NO_NETWORK m_network = engine->v8Engine->networkAccessManager(); QNetworkRequest request; @@ -73,11 +79,17 @@ QV4Include::QV4Include(const QUrl &url, QV4::ExecutionEngine *engine, m_reply = m_network->get(request); QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished())); +#else + finished(); +#endif } QV4Include::~QV4Include() { - delete m_reply; m_reply = 0; +#ifndef QT_NO_NETWORK + delete m_reply; + m_reply = 0; +#endif } QV4::ReturnedValue QV4Include::resultValue(QV4::ExecutionEngine *v4, Status status) @@ -123,6 +135,7 @@ QV4::ReturnedValue QV4Include::result() #define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15 void QV4Include::finished() { +#ifndef QT_NO_NETWORK m_redirectCount++; if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) { @@ -166,6 +179,12 @@ void QV4Include::finished() } else { resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError))); } +#else + QV4::Scope scope(v4); + QV4::ScopedObject resultObj(scope, m_resultObject.value()); + QV4::ScopedString status(scope, v4->newString(QStringLiteral("status"))); + resultObj->put(status, QV4::ScopedValue(scope, QV4::Primitive::fromInt32(NetworkError))); +#endif //QT_NO_NETWORK QV4::ScopedValue cb(scope, m_callbackFunction.value()); callback(cb, resultObj); @@ -188,14 +207,15 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) if (!context || !context->isJSContext) V4THROW_ERROR("Qt.include(): Can only be called from JavaScript files"); - QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow())); - if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor()) - url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile); - QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue()); if (ctx->argc() >= 2 && ctx->args()[1].as<QV4::FunctionObject>()) callbackFunction = ctx->args()[1]; +#ifndef QT_NO_NETWORK + QUrl url(scope.engine->resolvedUrl(ctx->args()[0].toQStringNoThrow())); + if (scope.engine->qmlEngine() && scope.engine->qmlEngine()->urlInterceptor()) + url = scope.engine->qmlEngine()->urlInterceptor()->intercept(url, QQmlAbstractUrlInterceptor::JavaScriptFile); + QString localFile = QQmlFile::urlToLocalFileOrQrc(url); QV4::ScopedValue result(scope); @@ -243,6 +263,12 @@ QV4::ReturnedValue QV4Include::method_include(QV4::CallContext *ctx) } return result->asReturnedValue(); +#else + QV4::ScopedValue result(scope); + result = resultValue(scope.engine, NetworkError); + callback(callbackFunction, result); + return result->asReturnedValue(); +#endif } QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4include_p.h b/src/qml/jsruntime/qv4include_p.h index 257dc05e65..1750e6a7e1 100644 --- a/src/qml/jsruntime/qv4include_p.h +++ b/src/qml/jsruntime/qv4include_p.h @@ -62,7 +62,9 @@ QT_BEGIN_NAMESPACE class QQmlEngine; +#ifndef QT_NO_NETWORK class QNetworkAccessManager; +#endif class QNetworkReply; class QV4Include : public QObject { @@ -90,15 +92,16 @@ private: static void callback(const QV4::Value &callback, const QV4::Value &status); QV4::ExecutionEngine *v4; - QNetworkAccessManager *m_network; - QPointer<QNetworkReply> m_reply; - QUrl m_url; + +#ifndef QT_NO_NETWORK int m_redirectCount; + QNetworkAccessManager *m_network; + QPointer<QNetworkReply> m_reply; +#endif QV4::PersistentValue m_callbackFunction; QV4::PersistentValue m_resultObject; - QV4::PersistentValue m_qmlContext; }; diff --git a/src/qml/jsruntime/qv4mathobject.cpp b/src/qml/jsruntime/qv4mathobject.cpp index 50b81098b2..5528409b40 100644 --- a/src/qml/jsruntime/qv4mathobject.cpp +++ b/src/qml/jsruntime/qv4mathobject.cpp @@ -80,6 +80,7 @@ Heap::MathObject::MathObject() m->defineDefaultProperty(QStringLiteral("pow"), QV4::MathObject::method_pow, 2); m->defineDefaultProperty(QStringLiteral("random"), QV4::MathObject::method_random, 0); m->defineDefaultProperty(QStringLiteral("round"), QV4::MathObject::method_round, 1); + m->defineDefaultProperty(QStringLiteral("sign"), QV4::MathObject::method_sign, 1); m->defineDefaultProperty(QStringLiteral("sin"), QV4::MathObject::method_sin, 1); m->defineDefaultProperty(QStringLiteral("sqrt"), QV4::MathObject::method_sqrt, 1); m->defineDefaultProperty(QStringLiteral("tan"), QV4::MathObject::method_tan, 1); @@ -300,6 +301,19 @@ ReturnedValue MathObject::method_round(CallContext *context) return Encode(v); } +ReturnedValue MathObject::method_sign(CallContext *context) +{ + double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); + + if (std::isnan(v)) + return Encode(qt_qnan()); + + if (qIsNull(v)) + return v; + + return Encode(std::signbit(v) ? -1 : 1); +} + ReturnedValue MathObject::method_sin(CallContext *context) { double v = context->argc() ? context->args()[0].toNumber() : qt_qnan(); diff --git a/src/qml/jsruntime/qv4mathobject_p.h b/src/qml/jsruntime/qv4mathobject_p.h index 2b842a312f..01e778d9ec 100644 --- a/src/qml/jsruntime/qv4mathobject_p.h +++ b/src/qml/jsruntime/qv4mathobject_p.h @@ -84,6 +84,7 @@ struct MathObject: Object static ReturnedValue method_pow(CallContext *context); static ReturnedValue method_random(CallContext *context); static ReturnedValue method_round(CallContext *context); + static ReturnedValue method_sign(CallContext *context); static ReturnedValue method_sin(CallContext *context); static ReturnedValue method_sqrt(CallContext *context); static ReturnedValue method_tan(CallContext *context); diff --git a/src/qml/jsruntime/qv4numberobject.cpp b/src/qml/jsruntime/qv4numberobject.cpp index ab3e03b183..f6b3e9a2b3 100644 --- a/src/qml/jsruntime/qv4numberobject.cpp +++ b/src/qml/jsruntime/qv4numberobject.cpp @@ -45,6 +45,7 @@ #include <QtCore/qmath.h> #include <QtCore/QDebug> #include <cassert> +#include <limits> using namespace QV4; @@ -99,12 +100,16 @@ void NumberPrototype::init(ExecutionEngine *engine, Object *ctor) ctor->defineReadonlyProperty(QStringLiteral("NEGATIVE_INFINITY"), Primitive::fromDouble(-qInf())); ctor->defineReadonlyProperty(QStringLiteral("POSITIVE_INFINITY"), Primitive::fromDouble(qInf())); ctor->defineReadonlyProperty(QStringLiteral("MAX_VALUE"), Primitive::fromDouble(1.7976931348623158e+308)); + ctor->defineReadonlyProperty(QStringLiteral("EPSILON"), Primitive::fromDouble(std::numeric_limits<double>::epsilon())); QT_WARNING_PUSH QT_WARNING_DISABLE_INTEL(239) ctor->defineReadonlyProperty(QStringLiteral("MIN_VALUE"), Primitive::fromDouble(5e-324)); QT_WARNING_POP + ctor->defineDefaultProperty(QStringLiteral("isFinite"), method_isFinite, 1); + ctor->defineDefaultProperty(QStringLiteral("isNaN"), method_isNaN, 1); + defineDefaultProperty(QStringLiteral("constructor"), (o = ctor)); defineDefaultProperty(engine->id_toString(), method_toString); defineDefaultProperty(QStringLiteral("toLocaleString"), method_toLocaleString); @@ -134,6 +139,24 @@ inline double thisNumber(ExecutionContext *ctx) return n->value(); } +ReturnedValue NumberPrototype::method_isFinite(CallContext *ctx) +{ + if (!ctx->argc()) + return Encode(false); + + double v = ctx->args()[0].toNumber(); + return Encode(!std::isnan(v) && !qt_is_inf(v)); +} + +ReturnedValue NumberPrototype::method_isNaN(CallContext *ctx) +{ + if (!ctx->argc()) + return Encode(false); + + double v = ctx->args()[0].toNumber(); + return Encode(std::isnan(v)); +} + ReturnedValue NumberPrototype::method_toString(CallContext *ctx) { Scope scope(ctx); diff --git a/src/qml/jsruntime/qv4numberobject_p.h b/src/qml/jsruntime/qv4numberobject_p.h index ca6f686304..bbe22af4bb 100644 --- a/src/qml/jsruntime/qv4numberobject_p.h +++ b/src/qml/jsruntime/qv4numberobject_p.h @@ -87,6 +87,8 @@ struct NumberPrototype: NumberObject { void init(ExecutionEngine *engine, Object *ctor); + static ReturnedValue method_isFinite(CallContext *ctx); + static ReturnedValue method_isNaN(CallContext *ctx); static ReturnedValue method_toString(CallContext *ctx); static ReturnedValue method_toLocaleString(CallContext *ctx); static ReturnedValue method_valueOf(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 5fb44307a9..fca218d9d0 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -54,6 +54,7 @@ #include <private/qqmlbuiltinfunctions_p.h> #include <private/qv8engine_p.h> +#include <private/qv4arraybuffer_p.h> #include <private/qv4functionobject_p.h> #include <private/qv4runtime_p.h> #include <private/qv4variantobject_p.h> @@ -83,7 +84,7 @@ QT_WARNING_DISABLE_GCC("-Wstrict-aliasing") using namespace QV4; -static QPair<QObject *, int> extractQtMethod(QV4::FunctionObject *function) +QPair<QObject *, int> QObjectMethod::extractQtMethod(const QV4::FunctionObject *function) { QV4::ExecutionEngine *v4 = function->engine(); if (v4) { @@ -103,7 +104,7 @@ static QPair<QObject *, int> extractQtSignal(const Value &value) QV4::Scope scope(v4); QV4::ScopedFunctionObject function(scope, value); if (function) - return extractQtMethod(function); + return QObjectMethod::extractQtMethod(function); QV4::Scoped<QV4::QmlSignalHandler> handler(scope, value); if (handler) @@ -862,7 +863,7 @@ struct QObjectSlotDispatcher : public QtPrivate::QSlotObjectBase (connection->thisObject.isUndefined() || RuntimeHelpers::strictEqual(*connection->thisObject.valueRef(), thisObject))) { QV4::ScopedFunctionObject f(scope, connection->function.value()); - QPair<QObject *, int> connectedFunctionData = extractQtMethod(f); + QPair<QObject *, int> connectedFunctionData = QObjectMethod::extractQtMethod(f); if (connectedFunctionData.first == receiverToDisconnect && connectedFunctionData.second == slotIndexToDisconnect) { *ret = true; @@ -977,7 +978,7 @@ ReturnedValue QObjectWrapper::method_disconnect(CallContext *ctx) if (!functionThisValue->isUndefined() && !functionThisValue->isObject()) V4THROW_ERROR("Function.prototype.disconnect: target this is not an object"); - QPair<QObject *, int> functionData = extractQtMethod(functionValue); + QPair<QObject *, int> functionData = QObjectMethod::extractQtMethod(functionValue); void *a[] = { ctx->d()->engine, @@ -1101,6 +1102,7 @@ private: // Pointers to allocData union { QString *qstringPtr; + QByteArray *qbyteArrayPtr; QVariant *qvariantPtr; QList<QObject *> *qlistPtr; QJSValue *qjsValuePtr; @@ -1222,6 +1224,13 @@ static int MatchScore(const QV4::Value &actual, int conversionType) default: return 10; } + } else if (actual.as<ArrayBuffer>()) { + switch (conversionType) { + case QMetaType::QByteArray: + return 0; + default: + return 10; + } } else if (actual.as<ArrayObject>()) { switch (conversionType) { case QMetaType::QJsonArray: @@ -1478,6 +1487,8 @@ void CallArgument::cleanup() { if (type == QMetaType::QString) { qstringPtr->~QString(); + } else if (type == QMetaType::QByteArray) { + qbyteArrayPtr->~QByteArray(); } else if (type == -1 || type == QMetaType::QVariant) { qvariantPtr->~QVariant(); } else if (type == qMetaTypeId<QJSValue>()) { @@ -1677,6 +1688,8 @@ QV4::ReturnedValue CallArgument::toValue(QV4::ExecutionEngine *engine) return QV4::Encode(floatValue); } else if (type == QMetaType::QString) { return QV4::Encode(engine->newString(*qstringPtr)); + } else if (type == QMetaType::QByteArray) { + return QV4::Encode(engine->newArrayBuffer(*qbyteArrayPtr)); } else if (type == QMetaType::QObjectStar) { QObject *object = qobjectPtr; if (object) diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h index d25279e783..0186a8381a 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper_p.h +++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h @@ -59,6 +59,7 @@ #include <private/qqmldata_p.h> #include <private/qqmlpropertycache_p.h> #include <private/qintrusivelist_p.h> +#include <private/qqmlaccessors_p.h> #include <private/qv4value_p.h> #include <private/qv4functionobject_p.h> @@ -170,6 +171,8 @@ struct Q_QML_EXPORT QObjectMethod : public QV4::FunctionObject ReturnedValue callInternal(CallData *callData) const; static void markObjects(Heap::Base *that, QV4::ExecutionEngine *e); + + static QPair<QObject *, int> extractQtMethod(const QV4::FunctionObject *function); }; struct QmlSignalHandler : public QV4::Object diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp index 92971e2298..a974909798 100644 --- a/src/qml/jsruntime/qv4runtime.cpp +++ b/src/qml/jsruntime/qv4runtime.cpp @@ -297,14 +297,14 @@ void RuntimeHelpers::numberToString(QString *result, double num, int radix) result->prepend(QLatin1Char('-')); } -ReturnedValue Runtime::closure(ExecutionEngine *engine, int functionId) +ReturnedValue Runtime::method_closure(ExecutionEngine *engine, int functionId) { QV4::Function *clos = engine->current->compilationUnit->runtimeFunctions[functionId]; Q_ASSERT(clos); return FunctionObject::createScriptFunction(engine->currentContext, clos)->asReturnedValue(); } -ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, const Value &index) +ReturnedValue Runtime::method_deleteElement(ExecutionEngine *engine, const Value &base, const Value &index) { Scope scope(engine); ScopedObject o(scope, base); @@ -316,17 +316,17 @@ ReturnedValue Runtime::deleteElement(ExecutionEngine *engine, const Value &base, } ScopedString name(scope, index.toString(engine)); - return Runtime::deleteMemberString(engine, base, name); + return method_deleteMemberString(engine, base, name); } -ReturnedValue Runtime::deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex) +ReturnedValue Runtime::method_deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); - return deleteMemberString(engine, base, name); + return method_deleteMemberString(engine, base, name); } -ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value &base, String *name) +ReturnedValue Runtime::method_deleteMemberString(ExecutionEngine *engine, const Value &base, String *name) { Scope scope(engine); ScopedObject obj(scope, base.toObject(engine)); @@ -335,14 +335,14 @@ ReturnedValue Runtime::deleteMemberString(ExecutionEngine *engine, const Value & return Encode(obj->deleteProperty(name)); } -ReturnedValue Runtime::deleteName(ExecutionEngine *engine, int nameIndex) +ReturnedValue Runtime::method_deleteName(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); return Encode(engine->currentContext->deleteProperty(name)); } -QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_instanceof(ExecutionEngine *engine, const Value &left, const Value &right) { Scope scope(engine); ScopedFunctionObject f(scope, right.as<FunctionObject>()); @@ -372,7 +372,7 @@ QV4::ReturnedValue Runtime::instanceof(ExecutionEngine *engine, const Value &lef return Encode(false); } -QV4::ReturnedValue Runtime::in(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_in(ExecutionEngine *engine, const Value &left, const Value &right) { if (!right.isObject()) return engine->throwTypeError(); @@ -561,7 +561,7 @@ QV4::ReturnedValue RuntimeHelpers::addHelper(ExecutionEngine *engine, const Valu return Encode(x + y); } -QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left, const Value &right) +QV4::ReturnedValue Runtime::method_addString(ExecutionEngine *engine, const Value &left, const Value &right) { Q_ASSERT(left.isString() || right.isString()); @@ -592,7 +592,7 @@ QV4::ReturnedValue Runtime::addString(ExecutionEngine *engine, const Value &left return (mm->alloc<String>(mm, pleft->stringValue()->d(), pright->stringValue()->d()))->asReturnedValue(); } -void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) +void Runtime::method_setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -602,7 +602,7 @@ void Runtime::setProperty(ExecutionEngine *engine, const Value &object, int name o->put(name, value); } -ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object, const Value &index) +ReturnedValue Runtime::method_getElement(ExecutionEngine *engine, const Value &object, const Value &index) { Scope scope(engine); uint idx = index.asArrayIndex(); @@ -645,7 +645,7 @@ ReturnedValue Runtime::getElement(ExecutionEngine *engine, const Value &object, return o->get(name); } -void Runtime::setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) +void Runtime::method_setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value) { Scope scope(engine); ScopedObject o(scope, object.toObject(engine)); @@ -669,7 +669,7 @@ void Runtime::setElement(ExecutionEngine *engine, const Value &object, const Val o->put(name, value); } -ReturnedValue Runtime::foreachIterator(ExecutionEngine *engine, const Value &in) +ReturnedValue Runtime::method_foreachIterator(ExecutionEngine *engine, const Value &in) { Scope scope(engine); ScopedObject o(scope, (Object *)0); @@ -678,7 +678,7 @@ ReturnedValue Runtime::foreachIterator(ExecutionEngine *engine, const Value &in) return engine->newForEachIteratorObject(o)->asReturnedValue(); } -ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator) +ReturnedValue Runtime::method_foreachNextPropertyName(const Value &foreach_iterator) { Q_ASSERT(foreach_iterator.isObject()); @@ -689,14 +689,14 @@ ReturnedValue Runtime::foreachNextPropertyName(const Value &foreach_iterator) } -void Runtime::setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value) +void Runtime::method_setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); engine->currentContext->setProperty(name, value); } -ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, int nameIndex) +ReturnedValue Runtime::method_getProperty(ExecutionEngine *engine, const Value &object, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -716,7 +716,7 @@ ReturnedValue Runtime::getProperty(ExecutionEngine *engine, const Value &object, return o->get(name); } -ReturnedValue Runtime::getActivationProperty(ExecutionEngine *engine, int nameIndex) +ReturnedValue Runtime::method_getActivationProperty(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -742,9 +742,9 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y) double dx = RuntimeHelpers::toNumber(x); return dx == y.asDouble(); } else if (x.isBoolean()) { - return Runtime::compareEqual(Primitive::fromDouble((double) x.booleanValue()), y); + return Runtime::method_compareEqual(Primitive::fromDouble((double) x.booleanValue()), y); } else if (y.isBoolean()) { - return Runtime::compareEqual(x, Primitive::fromDouble((double) y.booleanValue())); + return Runtime::method_compareEqual(x, Primitive::fromDouble((double) y.booleanValue())); } else { #ifdef V4_BOOTSTRAP Q_UNIMPLEMENTED(); @@ -752,11 +752,11 @@ uint RuntimeHelpers::equalHelper(const Value &x, const Value &y) if ((x.isNumber() || x.isString()) && y.isObject()) { Scope scope(y.objectValue()->engine()); ScopedValue py(scope, RuntimeHelpers::toPrimitive(y, PREFERREDTYPE_HINT)); - return Runtime::compareEqual(x, py); + return Runtime::method_compareEqual(x, py); } else if (x.isObject() && (y.isNumber() || y.isString())) { Scope scope(x.objectValue()->engine()); ScopedValue px(scope, RuntimeHelpers::toPrimitive(x, PREFERREDTYPE_HINT)); - return Runtime::compareEqual(px, y); + return Runtime::method_compareEqual(px, y); } #endif } @@ -779,7 +779,7 @@ Bool RuntimeHelpers::strictEqual(const Value &x, const Value &y) return false; } -QV4::Bool Runtime::compareGreaterThan(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareGreaterThan(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -803,7 +803,7 @@ QV4::Bool Runtime::compareGreaterThan(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareGreaterThan(pl, pr); + return Runtime::method_compareGreaterThan(pl, pr); #endif } @@ -812,7 +812,7 @@ QV4::Bool Runtime::compareGreaterThan(const Value &l, const Value &r) return dl > dr; } -QV4::Bool Runtime::compareLessThan(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareLessThan(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -836,7 +836,7 @@ QV4::Bool Runtime::compareLessThan(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareLessThan(pl, pr); + return Runtime::method_compareLessThan(pl, pr); #endif } @@ -845,7 +845,7 @@ QV4::Bool Runtime::compareLessThan(const Value &l, const Value &r) return dl < dr; } -QV4::Bool Runtime::compareGreaterEqual(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareGreaterEqual(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -869,7 +869,7 @@ QV4::Bool Runtime::compareGreaterEqual(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareGreaterEqual(pl, pr); + return Runtime::method_compareGreaterEqual(pl, pr); #endif } @@ -878,7 +878,7 @@ QV4::Bool Runtime::compareGreaterEqual(const Value &l, const Value &r) return dl >= dr; } -QV4::Bool Runtime::compareLessEqual(const Value &l, const Value &r) +QV4::Bool Runtime::method_compareLessEqual(const Value &l, const Value &r) { TRACE2(l, r); if (l.isInteger() && r.isInteger()) @@ -902,7 +902,7 @@ QV4::Bool Runtime::compareLessEqual(const Value &l, const Value &r) QV4::Scope scope(e); QV4::ScopedValue pl(scope, RuntimeHelpers::toPrimitive(l, QV4::NUMBER_HINT)); QV4::ScopedValue pr(scope, RuntimeHelpers::toPrimitive(r, QV4::NUMBER_HINT)); - return Runtime::compareLessEqual(pl, pr); + return Runtime::method_compareLessEqual(pl, pr); #endif } @@ -912,26 +912,26 @@ QV4::Bool Runtime::compareLessEqual(const Value &l, const Value &r) } #ifndef V4_BOOTSTRAP -Bool Runtime::compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right) +Bool Runtime::method_compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); Scope scope(engine); - ScopedValue v(scope, Runtime::instanceof(engine, left, right)); + ScopedValue v(scope, method_instanceof(engine, left, right)); return v->booleanValue(); } -uint Runtime::compareIn(ExecutionEngine *engine, const Value &left, const Value &right) +uint Runtime::method_compareIn(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); Scope scope(engine); - ScopedValue v(scope, Runtime::in(engine, left, right)); + ScopedValue v(scope, method_in(engine, left, right)); return v->booleanValue(); } -ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) { Scope scope(engine); Q_ASSERT(callData->thisObject.isUndefined()); @@ -949,7 +949,7 @@ ReturnedValue Runtime::callGlobalLookup(ExecutionEngine *engine, uint index, Cal } -ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Q_ASSERT(callData->thisObject.isUndefined()); Scope scope(engine); @@ -979,10 +979,10 @@ ReturnedValue Runtime::callActivationProperty(ExecutionEngine *engine, int nameI return o->call(callData); } -ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) +ReturnedValue Runtime::method_callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) { Scope scope(engine); - ScopedFunctionObject o(scope, getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex)); + ScopedFunctionObject o(scope, method_getQmlScopeObjectProperty(engine, callData->thisObject, propertyIndex)); if (!o) { QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow()); return engine->throwTypeError(error); @@ -991,10 +991,10 @@ ReturnedValue Runtime::callQmlScopeObjectProperty(ExecutionEngine *engine, int p return o->call(callData); } -ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) +ReturnedValue Runtime::method_callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData) { Scope scope(engine); - ScopedFunctionObject o(scope, getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex)); + ScopedFunctionObject o(scope, method_getQmlContextObjectProperty(engine, callData->thisObject, propertyIndex)); if (!o) { QString error = QStringLiteral("Property '%1' of object %2 is not a function").arg(propertyIndex).arg(callData->thisObject.toQStringNoThrow()); return engine->throwTypeError(error); @@ -1003,7 +1003,7 @@ ReturnedValue Runtime::callQmlContextObjectProperty(ExecutionEngine *engine, int return o->call(callData); } -ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -1030,7 +1030,7 @@ ReturnedValue Runtime::callProperty(ExecutionEngine *engine, int nameIndex, Call return o->call(callData); } -ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { Lookup *l = engine->current->lookups + index; Value v; @@ -1041,7 +1041,7 @@ ReturnedValue Runtime::callPropertyLookup(ExecutionEngine *engine, uint index, C return v.objectValue()->call(callData); } -ReturnedValue Runtime::callElement(ExecutionEngine *engine, const Value &index, CallData *callData) +ReturnedValue Runtime::method_callElement(ExecutionEngine *engine, const Value &index, CallData *callData) { Scope scope(engine); ScopedObject baseObject(scope, callData->thisObject.toObject(engine)); @@ -1058,7 +1058,7 @@ ReturnedValue Runtime::callElement(ExecutionEngine *engine, const Value &index, return o->call(callData); } -ReturnedValue Runtime::callValue(ExecutionEngine *engine, const Value &func, CallData *callData) +ReturnedValue Runtime::method_callValue(ExecutionEngine *engine, const Value &func, CallData *callData) { if (!func.isObject()) return engine->throwTypeError(QStringLiteral("%1 is not a function").arg(func.toQStringNoThrow())); @@ -1067,7 +1067,7 @@ ReturnedValue Runtime::callValue(ExecutionEngine *engine, const Value &func, Cal } -ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData) { Scope scope(engine); Q_ASSERT(callData->thisObject.isUndefined()); @@ -1081,7 +1081,7 @@ ReturnedValue Runtime::constructGlobalLookup(ExecutionEngine *engine, uint index } -ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -1096,7 +1096,7 @@ ReturnedValue Runtime::constructActivationProperty(ExecutionEngine *engine, int return f->construct(callData); } -ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func, CallData *callData) +ReturnedValue Runtime::method_constructValue(ExecutionEngine *engine, const Value &func, CallData *callData) { const Object *f = func.as<Object>(); if (!f) @@ -1105,7 +1105,7 @@ ReturnedValue Runtime::constructValue(ExecutionEngine *engine, const Value &func return f->construct(callData); } -ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) +ReturnedValue Runtime::method_constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData) { Scope scope(engine); ScopedObject thisObject(scope, callData->thisObject.toObject(engine)); @@ -1120,7 +1120,7 @@ ReturnedValue Runtime::constructProperty(ExecutionEngine *engine, int nameIndex, return f->construct(callData); } -ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) +ReturnedValue Runtime::method_constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData) { Lookup *l = engine->current->lookups + index; Value v; @@ -1132,13 +1132,13 @@ ReturnedValue Runtime::constructPropertyLookup(ExecutionEngine *engine, uint ind } -void Runtime::throwException(ExecutionEngine *engine, const Value &value) +void Runtime::method_throwException(ExecutionEngine *engine, const Value &value) { if (!value.isEmpty()) engine->throwError(value); } -ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value) +ReturnedValue Runtime::method_typeofValue(ExecutionEngine *engine, const Value &value) { Scope scope(engine); ScopedString res(scope); @@ -1167,39 +1167,37 @@ ReturnedValue Runtime::typeofValue(ExecutionEngine *engine, const Value &value) return res.asReturnedValue(); } -QV4::ReturnedValue Runtime::typeofName(ExecutionEngine *engine, int nameIndex) +QV4::ReturnedValue Runtime::method_typeofName(ExecutionEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); ScopedValue prop(scope, engine->currentContext->getProperty(name)); // typeof doesn't throw. clear any possible exception scope.engine->hasException = false; - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } #ifndef V4_BOOTSTRAP -ReturnedValue Runtime::typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, - int propertyIndex) +ReturnedValue Runtime::method_typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { Scope scope(engine); - ScopedValue prop(scope, getQmlScopeObjectProperty(engine, context, propertyIndex)); + ScopedValue prop(scope, method_getQmlScopeObjectProperty(engine, context, propertyIndex)); if (scope.engine->hasException) return Encode::undefined(); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } -ReturnedValue Runtime::typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, - int propertyIndex) +ReturnedValue Runtime::method_typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { Scope scope(engine); - ScopedValue prop(scope, getQmlContextObjectProperty(engine, context, propertyIndex)); + ScopedValue prop(scope, method_getQmlContextObjectProperty(engine, context, propertyIndex)); if (scope.engine->hasException) return Encode::undefined(); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } #endif // V4_BOOTSTRAP -QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex) +QV4::ReturnedValue Runtime::method_typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); @@ -1207,10 +1205,10 @@ QV4::ReturnedValue Runtime::typeofMember(ExecutionEngine *engine, const Value &b if (scope.engine->hasException) return Encode::undefined(); ScopedValue prop(scope, obj->get(name)); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } -QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value &base, const Value &index) +QV4::ReturnedValue Runtime::method_typeofElement(ExecutionEngine *engine, const Value &base, const Value &index) { Scope scope(engine); ScopedString name(scope, index.toString(engine)); @@ -1218,10 +1216,10 @@ QV4::ReturnedValue Runtime::typeofElement(ExecutionEngine *engine, const Value & if (scope.engine->hasException) return Encode::undefined(); ScopedValue prop(scope, obj->get(name)); - return Runtime::typeofValue(engine, prop); + return method_typeofValue(engine, prop); } -ReturnedValue Runtime::unwindException(ExecutionEngine *engine) +ReturnedValue Runtime::method_unwindException(ExecutionEngine *engine) { if (!engine->hasException) return Primitive::emptyValue().asReturnedValue(); @@ -1233,39 +1231,39 @@ ReturnedValue Runtime::unwindException(ExecutionEngine *engine) * * Instead the push/pop pair acts as a non local scope. */ -void Runtime::pushWithScope(const Value &o, ExecutionEngine *engine) +void Runtime::method_pushWithScope(const Value &o, ExecutionEngine *engine) { engine->pushContext(engine->currentContext->newWithContext(o.toObject(engine))); Q_ASSERT(engine->jsStackTop = engine->currentContext + 2); } -void Runtime::pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex) +void Runtime::method_pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex) { ExecutionContext *c = engine->currentContext; engine->pushContext(c->newCatchContext(c->d()->compilationUnit->runtimeStrings[exceptionVarNameIndex], engine->catchException(0))); Q_ASSERT(engine->jsStackTop = engine->currentContext + 2); } -void Runtime::popScope(ExecutionEngine *engine) +void Runtime::method_popScope(ExecutionEngine *engine) { Q_ASSERT(engine->jsStackTop = engine->currentContext + 2); engine->popContext(); engine->jsStackTop -= 2; } -void Runtime::declareVar(ExecutionEngine *engine, bool deletable, int nameIndex) +void Runtime::method_declareVar(ExecutionEngine *engine, bool deletable, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); engine->currentContext->createMutableBinding(name, deletable); } -ReturnedValue Runtime::arrayLiteral(ExecutionEngine *engine, Value *values, uint length) +ReturnedValue Runtime::method_arrayLiteral(ExecutionEngine *engine, Value *values, uint length) { return engine->newArrayObject(values, length)->asReturnedValue(); } -ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) +ReturnedValue Runtime::method_objectLiteral(ExecutionEngine *engine, const QV4::Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags) { Scope scope(engine); QV4::InternalClass *klass = engine->current->compilationUnit->runtimeClasses[classId]; @@ -1307,7 +1305,7 @@ ReturnedValue Runtime::objectLiteral(ExecutionEngine *engine, const QV4::Value * return o.asReturnedValue(); } -QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine) +QV4::ReturnedValue Runtime::method_setupArgumentsObject(ExecutionEngine *engine) { Q_ASSERT(engine->current->type == Heap::ExecutionContext::Type_CallContext); QV4::CallContext *c = static_cast<QV4::CallContext *>(engine->currentContext); @@ -1317,7 +1315,7 @@ QV4::ReturnedValue Runtime::setupArgumentsObject(ExecutionEngine *engine) #endif // V4_BOOTSTRAP -QV4::ReturnedValue Runtime::increment(const Value &value) +QV4::ReturnedValue Runtime::method_increment(const Value &value) { TRACE1(value); @@ -1329,7 +1327,7 @@ QV4::ReturnedValue Runtime::increment(const Value &value) } } -QV4::ReturnedValue Runtime::decrement(const Value &value) +QV4::ReturnedValue Runtime::method_decrement(const Value &value) { TRACE1(value); @@ -1364,31 +1362,31 @@ QV4::ReturnedValue RuntimeHelpers::toObject(ExecutionEngine *engine, const Value #endif // V4_BOOTSTRAP -ReturnedValue Runtime::toDouble(const Value &value) +ReturnedValue Runtime::method_toDouble(const Value &value) { TRACE1(value); return Encode(value.toNumber()); } -int Runtime::toInt(const Value &value) +int Runtime::method_toInt(const Value &value) { TRACE1(value); return value.toInt32(); } -int Runtime::doubleToInt(const double &d) +int Runtime::method_doubleToInt(const double &d) { TRACE0(); return Primitive::toInt32(d); } -unsigned Runtime::toUInt(const Value &value) +unsigned Runtime::method_toUInt(const Value &value) { TRACE1(value); return value.toUInt32(); } -unsigned Runtime::doubleToUInt(const double &d) +unsigned Runtime::method_doubleToUInt(const double &d) { TRACE0(); return Primitive::toUInt32(d); @@ -1396,17 +1394,17 @@ unsigned Runtime::doubleToUInt(const double &d) #ifndef V4_BOOTSTRAP -ReturnedValue Runtime::getQmlContext(NoThrowEngine *engine) +ReturnedValue Runtime::method_getQmlContext(NoThrowEngine *engine) { return engine->qmlContext()->asReturnedValue(); } -ReturnedValue Runtime::regexpLiteral(ExecutionEngine *engine, int id) +ReturnedValue Runtime::method_regexpLiteral(ExecutionEngine *engine, int id) { return engine->current->compilationUnit->runtimeRegularExpressions[id].asReturnedValue(); } -ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) +ReturnedValue Runtime::method_getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) { Scope scope(engine); QV4::Scoped<QObjectWrapper> wrapper(scope, object); @@ -1417,7 +1415,117 @@ ReturnedValue Runtime::getQmlQObjectProperty(ExecutionEngine *engine, const Valu return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->object(), propertyIndex, captureRequired); } -QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex) +template <typename PropertyType> +static inline PropertyType getQObjectProperty(QObject *object, ExecutionEngine *engine, QQmlAccessors *accessors, int coreIndex, int notifyIndex) +{ + PropertyType t; + accessors->read(object, &t); + if (notifyIndex != -1) { + QQmlEnginePrivate *ep = engine->qmlEngine() ? QQmlEnginePrivate::get(engine->qmlEngine()) : 0; + if (ep && ep->propertyCapture) { + if (accessors->notifier) { + QQmlNotifier *n = nullptr; + accessors->notifier(object, &n); + if (n) { + ep->propertyCapture->captureProperty(n); + } + } else { + ep->propertyCapture->captureProperty(object, coreIndex, notifyIndex); + } + } + } + + return t; +} + +ReturnedValue Runtime::method_accessQObjectQRealProperty(ExecutionEngine *engine, + const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(getQObjectProperty<qreal>(o, engine, accessors, coreIndex, notifyIndex)); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectQObjectProperty(ExecutionEngine *engine, + const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::QObjectWrapper::wrap(engine, getQObjectProperty<QObject *>(o, engine, accessors, + coreIndex, + notifyIndex)); + } + + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectIntProperty(ExecutionEngine *engine, const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(getQObjectProperty<int>(o, engine, accessors, coreIndex, notifyIndex)); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectBoolProperty(ExecutionEngine *engine, const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(getQObjectProperty<bool>(o, engine, accessors, coreIndex, notifyIndex)); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQObjectQStringProperty(ExecutionEngine *engine, + const Value &object, + QQmlAccessors *accessors, int coreIndex, + int notifyIndex) +{ + auto casted = object.as<QObjectWrapper>(); + QObject *o = casted ? casted->object() : nullptr; + if (Q_LIKELY(o)) { + return QV4::Encode(engine->newString(getQObjectProperty<QString>(o, engine, accessors, + coreIndex, notifyIndex))); + } + engine->throwTypeError(QStringLiteral("Cannot read property of null")); + return Encode::undefined(); +} + +ReturnedValue Runtime::method_accessQmlScopeObjectQObjectProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + QObject *rv = 0; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::QObjectWrapper::wrap(c.engine(), rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +QV4::ReturnedValue Runtime::method_getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex) { QObject *scopeObject = engine->qmlScopeObject(); QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject); @@ -1427,19 +1535,19 @@ QV4::ReturnedValue Runtime::getQmlAttachedProperty(ExecutionEngine *engine, int return QV4::QObjectWrapper::getProperty(engine, attachedObject, propertyIndex, /*captureRequired*/true); } -ReturnedValue Runtime::getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +ReturnedValue Runtime::method_getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { const QmlContext &c = static_cast<const QmlContext &>(context); return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->scopeObject, propertyIndex, false); } -ReturnedValue Runtime::getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) +ReturnedValue Runtime::method_getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex) { const QmlContext &c = static_cast<const QmlContext &>(context); return QV4::QObjectWrapper::getProperty(engine, c.d()->qml->context->contextObject, propertyIndex, false); } -ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) +ReturnedValue Runtime::method_getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired) { Scope scope(engine); QV4::Scoped<QmlTypeWrapper> wrapper(scope, object); @@ -1450,7 +1558,7 @@ ReturnedValue Runtime::getQmlSingletonQObjectProperty(ExecutionEngine *engine, c return QV4::QObjectWrapper::getProperty(scope.engine, wrapper->singletonObject(), propertyIndex, captureRequired); } -ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index) +ReturnedValue Runtime::method_getQmlIdObject(ExecutionEngine *engine, const Value &c, uint index) { Scope scope(engine); const QmlContext &qmlContext = static_cast<const QmlContext &>(c); @@ -1465,19 +1573,19 @@ ReturnedValue Runtime::getQmlIdObject(ExecutionEngine *engine, const Value &c, u return QObjectWrapper::wrap(engine, context->idValues[index].data()); } -void Runtime::setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) +void Runtime::method_setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) { const QmlContext &c = static_cast<const QmlContext &>(context); return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->scopeObject, propertyIndex, value); } -void Runtime::setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) +void Runtime::method_setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value) { const QmlContext &c = static_cast<const QmlContext &>(context); return QV4::QObjectWrapper::setProperty(engine, c.d()->qml->context->contextObject, propertyIndex, value); } -void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) +void Runtime::method_setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value) { Scope scope(engine); QV4::Scoped<QObjectWrapper> wrapper(scope, object); @@ -1488,7 +1596,7 @@ void Runtime::setQmlQObjectProperty(ExecutionEngine *engine, const Value &object wrapper->setProperty(engine, propertyIndex, value); } -ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine) +ReturnedValue Runtime::method_getQmlImportedScripts(NoThrowEngine *engine) { QQmlContextData *context = engine->callingQmlContext(); if (!context) @@ -1496,14 +1604,14 @@ ReturnedValue Runtime::getQmlImportedScripts(NoThrowEngine *engine) return context->importedScripts.value(); } -QV4::ReturnedValue Runtime::getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex) +QV4::ReturnedValue Runtime::method_getQmlSingleton(QV4::NoThrowEngine *engine, int nameIndex) { Scope scope(engine); ScopedString name(scope, engine->current->compilationUnit->runtimeStrings[nameIndex]); return engine->qmlSingletonWrapper(name); } -void Runtime::convertThisToObject(ExecutionEngine *engine) +void Runtime::method_convertThisToObject(ExecutionEngine *engine) { Value *t = &engine->current->callData->thisObject; if (t->isObject()) diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h index 51cc4f50b0..ffae55995f 100644 --- a/src/qml/jsruntime/qv4runtime_p.h +++ b/src/qml/jsruntime/qv4runtime_p.h @@ -55,10 +55,14 @@ #include "qv4context_p.h" #include "qv4engine_p.h" #include "qv4math_p.h" +#include "qv4runtimeapi_p.h" +#ifndef V4_BOOTSTRAP +#include <private/qqmlaccessors_p.h> +#include <private/qqmlcontextwrapper_p.h> +#endif #include <QtCore/qnumeric.h> - QT_BEGIN_NAMESPACE #undef QV4_COUNT_RUNTIME_FUNCTIONS @@ -98,150 +102,6 @@ enum TypeHint { STRING_HINT }; -// This is a trick to tell the code generators that functions taking a NoThrowContext won't -// throw exceptions and therefore don't need a check after the call. -struct NoThrowEngine : public ExecutionEngine -{ -}; - -struct Q_QML_PRIVATE_EXPORT Runtime { - // call - static ReturnedValue callGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData); - static ReturnedValue callActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData); - static ReturnedValue callQmlScopeObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData); - static ReturnedValue callQmlContextObjectProperty(ExecutionEngine *engine, int propertyIndex, CallData *callData); - static ReturnedValue callProperty(ExecutionEngine *engine, int nameIndex, CallData *callData); - static ReturnedValue callPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData); - static ReturnedValue callElement(ExecutionEngine *engine, const Value &index, CallData *callData); - static ReturnedValue callValue(ExecutionEngine *engine, const Value &func, CallData *callData); - - // construct - static ReturnedValue constructGlobalLookup(ExecutionEngine *engine, uint index, CallData *callData); - static ReturnedValue constructActivationProperty(ExecutionEngine *engine, int nameIndex, CallData *callData); - static ReturnedValue constructProperty(ExecutionEngine *engine, int nameIndex, CallData *callData); - static ReturnedValue constructPropertyLookup(ExecutionEngine *engine, uint index, CallData *callData); - static ReturnedValue constructValue(ExecutionEngine *engine, const Value &func, CallData *callData); - - // set & get - static void setActivationProperty(ExecutionEngine *engine, int nameIndex, const Value &value); - static void setProperty(ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value); - static void setElement(ExecutionEngine *engine, const Value &object, const Value &index, const Value &value); - static ReturnedValue getProperty(ExecutionEngine *engine, const Value &object, int nameIndex); - static ReturnedValue getActivationProperty(ExecutionEngine *engine, int nameIndex); - static ReturnedValue getElement(ExecutionEngine *engine, const Value &object, const Value &index); - - // typeof - static ReturnedValue typeofValue(ExecutionEngine *engine, const Value &val); - static ReturnedValue typeofName(ExecutionEngine *engine, int nameIndex); - static ReturnedValue typeofScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex); - static ReturnedValue typeofContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex); - static ReturnedValue typeofMember(ExecutionEngine *engine, const Value &base, int nameIndex); - static ReturnedValue typeofElement(ExecutionEngine *engine, const Value &base, const Value &index); - - // delete - static ReturnedValue deleteElement(ExecutionEngine *engine, const Value &base, const Value &index); - static ReturnedValue deleteMember(ExecutionEngine *engine, const Value &base, int nameIndex); - static ReturnedValue deleteMemberString(ExecutionEngine *engine, const Value &base, String *name); - static ReturnedValue deleteName(ExecutionEngine *engine, int nameIndex); - - // exceptions & scopes - static void throwException(ExecutionEngine *engine, const Value &value); - static ReturnedValue unwindException(ExecutionEngine *engine); - static void pushWithScope(const Value &o, ExecutionEngine *engine); - static void pushCatchScope(NoThrowEngine *engine, int exceptionVarNameIndex); - static void popScope(ExecutionEngine *engine); - - // closures - static ReturnedValue closure(ExecutionEngine *engine, int functionId); - - // function header - static void declareVar(ExecutionEngine *engine, bool deletable, int nameIndex); - static ReturnedValue setupArgumentsObject(ExecutionEngine *engine); - static void convertThisToObject(ExecutionEngine *engine); - - // literals - static ReturnedValue arrayLiteral(ExecutionEngine *engine, Value *values, uint length); - static ReturnedValue objectLiteral(ExecutionEngine *engine, const Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags); - static ReturnedValue regexpLiteral(ExecutionEngine *engine, int id); - - // foreach - static ReturnedValue foreachIterator(ExecutionEngine *engine, const Value &in); - static ReturnedValue foreachNextPropertyName(const Value &foreach_iterator); - - // unary operators - typedef ReturnedValue (*UnaryOperation)(const Value &value); - static ReturnedValue uPlus(const Value &value); - static ReturnedValue uMinus(const Value &value); - static ReturnedValue uNot(const Value &value); - static ReturnedValue complement(const Value &value); - static ReturnedValue increment(const Value &value); - static ReturnedValue decrement(const Value &value); - - // binary operators - typedef ReturnedValue (*BinaryOperation)(const Value &left, const Value &right); - typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *engine, const Value &left, const Value &right); - - static ReturnedValue instanceof(ExecutionEngine *engine, const Value &left, const Value &right); - static ReturnedValue in(ExecutionEngine *engine, const Value &left, const Value &right); - static ReturnedValue add(ExecutionEngine *engine, const Value &left, const Value &right); - static ReturnedValue addString(ExecutionEngine *engine, const Value &left, const Value &right); - static ReturnedValue bitOr(const Value &left, const Value &right); - static ReturnedValue bitXor(const Value &left, const Value &right); - static ReturnedValue bitAnd(const Value &left, const Value &right); - static ReturnedValue sub(const Value &left, const Value &right); - static ReturnedValue mul(const Value &left, const Value &right); - static ReturnedValue div(const Value &left, const Value &right); - static ReturnedValue mod(const Value &left, const Value &right); - static ReturnedValue shl(const Value &left, const Value &right); - static ReturnedValue shr(const Value &left, const Value &right); - static ReturnedValue ushr(const Value &left, const Value &right); - static ReturnedValue greaterThan(const Value &left, const Value &right); - static ReturnedValue lessThan(const Value &left, const Value &right); - static ReturnedValue greaterEqual(const Value &left, const Value &right); - static ReturnedValue lessEqual(const Value &left, const Value &right); - static ReturnedValue equal(const Value &left, const Value &right); - static ReturnedValue notEqual(const Value &left, const Value &right); - static ReturnedValue strictEqual(const Value &left, const Value &right); - static ReturnedValue strictNotEqual(const Value &left, const Value &right); - - // comparisons - typedef Bool (*CompareOperation)(const Value &left, const Value &right); - static Bool compareGreaterThan(const Value &l, const Value &r); - static Bool compareLessThan(const Value &l, const Value &r); - static Bool compareGreaterEqual(const Value &l, const Value &r); - static Bool compareLessEqual(const Value &l, const Value &r); - static Bool compareEqual(const Value &left, const Value &right); - static Bool compareNotEqual(const Value &left, const Value &right); - static Bool compareStrictEqual(const Value &left, const Value &right); - static Bool compareStrictNotEqual(const Value &left, const Value &right); - - typedef Bool (*CompareOperationContext)(ExecutionEngine *engine, const Value &left, const Value &right); - static Bool compareInstanceof(ExecutionEngine *engine, const Value &left, const Value &right); - static Bool compareIn(ExecutionEngine *engine, const Value &left, const Value &right); - - // conversions - static Bool toBoolean(const Value &value); - static ReturnedValue toDouble(const Value &value); - static int toInt(const Value &value); - static int doubleToInt(const double &d); - static unsigned toUInt(const Value &value); - static unsigned doubleToUInt(const double &d); - - // qml - static ReturnedValue getQmlContext(NoThrowEngine *engine); - static ReturnedValue getQmlImportedScripts(NoThrowEngine *engine); - static ReturnedValue getQmlSingleton(NoThrowEngine *engine, int nameIndex); - static ReturnedValue getQmlAttachedProperty(ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex); - static ReturnedValue getQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex); - static ReturnedValue getQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex); - static ReturnedValue getQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired); - static ReturnedValue getQmlSingletonQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired); - static ReturnedValue getQmlIdObject(ExecutionEngine *engine, const Value &context, uint index); - - static void setQmlScopeObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value); - static void setQmlContextObjectProperty(ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value); - static void setQmlQObjectProperty(ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value); -}; struct Q_QML_PRIVATE_EXPORT RuntimeHelpers { static ReturnedValue objectDefaultValue(const Object *object, int typeHint); @@ -281,7 +141,7 @@ inline double RuntimeHelpers::toNumber(const Value &value) return value.toNumber(); } -inline ReturnedValue Runtime::uPlus(const Value &value) +inline ReturnedValue Runtime::method_uPlus(const Value &value) { TRACE1(value); @@ -294,7 +154,7 @@ inline ReturnedValue Runtime::uPlus(const Value &value) return Encode(n); } -inline ReturnedValue Runtime::uMinus(const Value &value) +inline ReturnedValue Runtime::method_uMinus(const Value &value) { TRACE1(value); @@ -307,7 +167,7 @@ inline ReturnedValue Runtime::uMinus(const Value &value) } } -inline ReturnedValue Runtime::complement(const Value &value) +inline ReturnedValue Runtime::method_complement(const Value &value) { TRACE1(value); @@ -315,7 +175,7 @@ inline ReturnedValue Runtime::complement(const Value &value) return Encode((int)~n); } -inline ReturnedValue Runtime::uNot(const Value &value) +inline ReturnedValue Runtime::method_uNot(const Value &value) { TRACE1(value); @@ -324,7 +184,7 @@ inline ReturnedValue Runtime::uNot(const Value &value) } // binary operators -inline ReturnedValue Runtime::bitOr(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_bitOr(const Value &left, const Value &right) { TRACE2(left, right); @@ -333,7 +193,7 @@ inline ReturnedValue Runtime::bitOr(const Value &left, const Value &right) return Encode(lval | rval); } -inline ReturnedValue Runtime::bitXor(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_bitXor(const Value &left, const Value &right) { TRACE2(left, right); @@ -342,7 +202,7 @@ inline ReturnedValue Runtime::bitXor(const Value &left, const Value &right) return Encode(lval ^ rval); } -inline ReturnedValue Runtime::bitAnd(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_bitAnd(const Value &left, const Value &right) { TRACE2(left, right); @@ -352,7 +212,7 @@ inline ReturnedValue Runtime::bitAnd(const Value &left, const Value &right) } #ifndef V4_BOOTSTRAP -inline ReturnedValue Runtime::add(ExecutionEngine *engine, const Value &left, const Value &right) +inline ReturnedValue Runtime::method_add(ExecutionEngine *engine, const Value &left, const Value &right) { TRACE2(left, right); @@ -365,7 +225,7 @@ inline ReturnedValue Runtime::add(ExecutionEngine *engine, const Value &left, co } #endif // V4_BOOTSTRAP -inline ReturnedValue Runtime::sub(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_sub(const Value &left, const Value &right) { TRACE2(left, right); @@ -378,7 +238,7 @@ inline ReturnedValue Runtime::sub(const Value &left, const Value &right) return Primitive::fromDouble(lval - rval).asReturnedValue(); } -inline ReturnedValue Runtime::mul(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_mul(const Value &left, const Value &right) { TRACE2(left, right); @@ -391,7 +251,7 @@ inline ReturnedValue Runtime::mul(const Value &left, const Value &right) return Primitive::fromDouble(lval * rval).asReturnedValue(); } -inline ReturnedValue Runtime::div(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_div(const Value &left, const Value &right) { TRACE2(left, right); @@ -409,7 +269,7 @@ inline ReturnedValue Runtime::div(const Value &left, const Value &right) return Primitive::fromDouble(lval / rval).asReturnedValue(); } -inline ReturnedValue Runtime::mod(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_mod(const Value &left, const Value &right) { TRACE2(left, right); @@ -424,7 +284,7 @@ inline ReturnedValue Runtime::mod(const Value &left, const Value &right) return Primitive::fromDouble(std::fmod(lval, rval)).asReturnedValue(); } -inline ReturnedValue Runtime::shl(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_shl(const Value &left, const Value &right) { TRACE2(left, right); @@ -433,7 +293,7 @@ inline ReturnedValue Runtime::shl(const Value &left, const Value &right) return Encode((int)(lval << rval)); } -inline ReturnedValue Runtime::shr(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_shr(const Value &left, const Value &right) { TRACE2(left, right); @@ -442,7 +302,7 @@ inline ReturnedValue Runtime::shr(const Value &left, const Value &right) return Encode((int)(lval >> rval)); } -inline ReturnedValue Runtime::ushr(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_ushr(const Value &left, const Value &right) { TRACE2(left, right); @@ -453,39 +313,39 @@ inline ReturnedValue Runtime::ushr(const Value &left, const Value &right) return Encode(res); } -inline ReturnedValue Runtime::greaterThan(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_greaterThan(const Value &left, const Value &right) { TRACE2(left, right); - bool r = Runtime::compareGreaterThan(left, right); + bool r = method_compareGreaterThan(left, right); return Encode(r); } -inline ReturnedValue Runtime::lessThan(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_lessThan(const Value &left, const Value &right) { TRACE2(left, right); - bool r = Runtime::compareLessThan(left, right); + bool r = method_compareLessThan(left, right); return Encode(r); } -inline ReturnedValue Runtime::greaterEqual(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_greaterEqual(const Value &left, const Value &right) { TRACE2(left, right); - bool r = Runtime::compareGreaterEqual(left, right); + bool r = method_compareGreaterEqual(left, right); return Encode(r); } -inline ReturnedValue Runtime::lessEqual(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_lessEqual(const Value &left, const Value &right) { TRACE2(left, right); - bool r = Runtime::compareLessEqual(left, right); + bool r = method_compareLessEqual(left, right); return Encode(r); } -inline Bool Runtime::compareEqual(const Value &left, const Value &right) +inline Bool Runtime::method_compareEqual(const Value &left, const Value &right) { TRACE2(left, right); @@ -503,23 +363,23 @@ inline Bool Runtime::compareEqual(const Value &left, const Value &right) return RuntimeHelpers::equalHelper(left, right); } -inline ReturnedValue Runtime::equal(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_equal(const Value &left, const Value &right) { TRACE2(left, right); - bool r = Runtime::compareEqual(left, right); + bool r = method_compareEqual(left, right); return Encode(r); } -inline ReturnedValue Runtime::notEqual(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_notEqual(const Value &left, const Value &right) { TRACE2(left, right); - bool r = !Runtime::compareEqual(left, right); + bool r = !method_compareEqual(left, right); return Encode(r); } -inline ReturnedValue Runtime::strictEqual(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_strictEqual(const Value &left, const Value &right) { TRACE2(left, right); @@ -527,7 +387,7 @@ inline ReturnedValue Runtime::strictEqual(const Value &left, const Value &right) return Encode(r); } -inline ReturnedValue Runtime::strictNotEqual(const Value &left, const Value &right) +inline ReturnedValue Runtime::method_strictNotEqual(const Value &left, const Value &right) { TRACE2(left, right); @@ -535,32 +395,94 @@ inline ReturnedValue Runtime::strictNotEqual(const Value &left, const Value &rig return Encode(r); } -inline Bool Runtime::compareNotEqual(const Value &left, const Value &right) +inline Bool Runtime::method_compareNotEqual(const Value &left, const Value &right) { TRACE2(left, right); - return !Runtime::compareEqual(left, right); + return !Runtime::method_compareEqual(left, right); } -inline Bool Runtime::compareStrictEqual(const Value &left, const Value &right) +inline Bool Runtime::method_compareStrictEqual(const Value &left, const Value &right) { TRACE2(left, right); return RuntimeHelpers::strictEqual(left, right); } -inline Bool Runtime::compareStrictNotEqual(const Value &left, const Value &right) +inline Bool Runtime::method_compareStrictNotEqual(const Value &left, const Value &right) { TRACE2(left, right); return ! RuntimeHelpers::strictEqual(left, right); } -inline Bool Runtime::toBoolean(const Value &value) +inline Bool Runtime::method_toBoolean(const Value &value) { return value.toBoolean(); } +inline ReturnedValue Runtime::method_accessQmlScopeObjectQRealProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + qreal rv = 0; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +inline ReturnedValue Runtime::method_accessQmlScopeObjectIntProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + int rv = 0; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +inline ReturnedValue Runtime::method_accessQmlScopeObjectBoolProperty(const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + bool rv = false; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(rv); +#else + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + +inline ReturnedValue Runtime::method_accessQmlScopeObjectQStringProperty(ExecutionEngine *engine, + const Value &context, + QQmlAccessors *accessors) +{ +#ifndef V4_BOOTSTRAP + const QmlContext &c = static_cast<const QmlContext &>(context); + QString rv; + accessors->read(c.d()->qml->scopeObject, &rv); + return QV4::Encode(engine->newString(rv)); +#else + Q_UNUSED(engine); + Q_UNUSED(context); + Q_UNUSED(accessors); + return QV4::Encode::undefined(); +#endif +} + } // namespace QV4 QT_END_NAMESPACE diff --git a/src/qml/jsruntime/qv4runtimeapi_p.h b/src/qml/jsruntime/qv4runtimeapi_p.h new file mode 100644 index 0000000000..bf153223a0 --- /dev/null +++ b/src/qml/jsruntime/qv4runtimeapi_p.h @@ -0,0 +1,325 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#ifndef QV4RUNTIMEAPI_P_H +#define QV4RUNTIMEAPI_P_H + +#include <private/qv4global_p.h> + +QT_BEGIN_NAMESPACE + +namespace QV4 { + +struct NoThrowEngine; + +#define RUNTIME_METHOD(returnvalue, name, args) \ + typedef returnvalue (*Method_##name)args; \ + static returnvalue method_##name args; \ + const Method_##name name + +#define INIT_RUNTIME_METHOD(name) \ + name(method_##name) + +struct Q_QML_PRIVATE_EXPORT Runtime { + Runtime() + : INIT_RUNTIME_METHOD(callGlobalLookup) + , INIT_RUNTIME_METHOD(callActivationProperty) + , INIT_RUNTIME_METHOD(callQmlScopeObjectProperty) + , INIT_RUNTIME_METHOD(callQmlContextObjectProperty) + , INIT_RUNTIME_METHOD(callProperty) + , INIT_RUNTIME_METHOD(callPropertyLookup) + , INIT_RUNTIME_METHOD(callElement) + , INIT_RUNTIME_METHOD(callValue) + , INIT_RUNTIME_METHOD(constructGlobalLookup) + , INIT_RUNTIME_METHOD(constructActivationProperty) + , INIT_RUNTIME_METHOD(constructProperty) + , INIT_RUNTIME_METHOD(constructPropertyLookup) + , INIT_RUNTIME_METHOD(constructValue) + , INIT_RUNTIME_METHOD(setActivationProperty) + , INIT_RUNTIME_METHOD(setProperty) + , INIT_RUNTIME_METHOD(setElement) + , INIT_RUNTIME_METHOD(getProperty) + , INIT_RUNTIME_METHOD(getActivationProperty) + , INIT_RUNTIME_METHOD(getElement) + , INIT_RUNTIME_METHOD(typeofValue) + , INIT_RUNTIME_METHOD(typeofName) + , INIT_RUNTIME_METHOD(typeofScopeObjectProperty) + , INIT_RUNTIME_METHOD(typeofContextObjectProperty) + , INIT_RUNTIME_METHOD(typeofMember) + , INIT_RUNTIME_METHOD(typeofElement) + , INIT_RUNTIME_METHOD(deleteElement) + , INIT_RUNTIME_METHOD(deleteMember) + , INIT_RUNTIME_METHOD(deleteMemberString) + , INIT_RUNTIME_METHOD(deleteName) + , INIT_RUNTIME_METHOD(throwException) + , INIT_RUNTIME_METHOD(unwindException) + , INIT_RUNTIME_METHOD(pushWithScope) + , INIT_RUNTIME_METHOD(pushCatchScope) + , INIT_RUNTIME_METHOD(popScope) + , INIT_RUNTIME_METHOD(closure) + , INIT_RUNTIME_METHOD(declareVar) + , INIT_RUNTIME_METHOD(setupArgumentsObject) + , INIT_RUNTIME_METHOD(convertThisToObject) + , INIT_RUNTIME_METHOD(arrayLiteral) + , INIT_RUNTIME_METHOD(objectLiteral) + , INIT_RUNTIME_METHOD(regexpLiteral) + , INIT_RUNTIME_METHOD(foreachIterator) + , INIT_RUNTIME_METHOD(foreachNextPropertyName) + , INIT_RUNTIME_METHOD(uPlus) + , INIT_RUNTIME_METHOD(uMinus) + , INIT_RUNTIME_METHOD(uNot) + , INIT_RUNTIME_METHOD(complement) + , INIT_RUNTIME_METHOD(increment) + , INIT_RUNTIME_METHOD(decrement) + , INIT_RUNTIME_METHOD(instanceof) + , INIT_RUNTIME_METHOD(in) + , INIT_RUNTIME_METHOD(add) + , INIT_RUNTIME_METHOD(addString) + , INIT_RUNTIME_METHOD(bitOr) + , INIT_RUNTIME_METHOD(bitXor) + , INIT_RUNTIME_METHOD(bitAnd) + , INIT_RUNTIME_METHOD(sub) + , INIT_RUNTIME_METHOD(mul) + , INIT_RUNTIME_METHOD(div) + , INIT_RUNTIME_METHOD(mod) + , INIT_RUNTIME_METHOD(shl) + , INIT_RUNTIME_METHOD(shr) + , INIT_RUNTIME_METHOD(ushr) + , INIT_RUNTIME_METHOD(greaterThan) + , INIT_RUNTIME_METHOD(lessThan) + , INIT_RUNTIME_METHOD(greaterEqual) + , INIT_RUNTIME_METHOD(lessEqual) + , INIT_RUNTIME_METHOD(equal) + , INIT_RUNTIME_METHOD(notEqual) + , INIT_RUNTIME_METHOD(strictEqual) + , INIT_RUNTIME_METHOD(strictNotEqual) + , INIT_RUNTIME_METHOD(compareGreaterThan) + , INIT_RUNTIME_METHOD(compareLessThan) + , INIT_RUNTIME_METHOD(compareGreaterEqual) + , INIT_RUNTIME_METHOD(compareLessEqual) + , INIT_RUNTIME_METHOD(compareEqual) + , INIT_RUNTIME_METHOD(compareNotEqual) + , INIT_RUNTIME_METHOD(compareStrictEqual) + , INIT_RUNTIME_METHOD(compareStrictNotEqual) + , INIT_RUNTIME_METHOD(compareInstanceof) + , INIT_RUNTIME_METHOD(compareIn) + , INIT_RUNTIME_METHOD(toBoolean) + , INIT_RUNTIME_METHOD(toDouble) + , INIT_RUNTIME_METHOD(toInt) + , INIT_RUNTIME_METHOD(doubleToInt) + , INIT_RUNTIME_METHOD(toUInt) + , INIT_RUNTIME_METHOD(doubleToUInt) + , INIT_RUNTIME_METHOD(getQmlContext) + , INIT_RUNTIME_METHOD(getQmlImportedScripts) + , INIT_RUNTIME_METHOD(getQmlSingleton) + , INIT_RUNTIME_METHOD(getQmlAttachedProperty) + , INIT_RUNTIME_METHOD(getQmlScopeObjectProperty) + , INIT_RUNTIME_METHOD(getQmlContextObjectProperty) + , INIT_RUNTIME_METHOD(getQmlQObjectProperty) + , INIT_RUNTIME_METHOD(getQmlSingletonQObjectProperty) + , INIT_RUNTIME_METHOD(getQmlIdObject) + , INIT_RUNTIME_METHOD(setQmlScopeObjectProperty) + , INIT_RUNTIME_METHOD(setQmlContextObjectProperty) + , INIT_RUNTIME_METHOD(setQmlQObjectProperty) + , INIT_RUNTIME_METHOD(accessQObjectQRealProperty) + , INIT_RUNTIME_METHOD(accessQObjectQObjectProperty) + , INIT_RUNTIME_METHOD(accessQObjectIntProperty) + , INIT_RUNTIME_METHOD(accessQObjectBoolProperty) + , INIT_RUNTIME_METHOD(accessQObjectQStringProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectQRealProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectQObjectProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectIntProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectBoolProperty) + , INIT_RUNTIME_METHOD(accessQmlScopeObjectQStringProperty) + { } + + // call + RUNTIME_METHOD(ReturnedValue, callGlobalLookup, (ExecutionEngine *engine, uint index, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callActivationProperty, (ExecutionEngine *engine, int nameIndex, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callQmlScopeObjectProperty, (ExecutionEngine *engine, int propertyIndex, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callQmlContextObjectProperty, (ExecutionEngine *engine, int propertyIndex, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callProperty, (ExecutionEngine *engine, int nameIndex, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callPropertyLookup, (ExecutionEngine *engine, uint index, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callElement, (ExecutionEngine *engine, const Value &index, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, callValue, (ExecutionEngine *engine, const Value &func, CallData *callData)); + + // construct + RUNTIME_METHOD(ReturnedValue, constructGlobalLookup, (ExecutionEngine *engine, uint index, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, constructActivationProperty, (ExecutionEngine *engine, int nameIndex, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, constructProperty, (ExecutionEngine *engine, int nameIndex, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, constructPropertyLookup, (ExecutionEngine *engine, uint index, CallData *callData)); + RUNTIME_METHOD(ReturnedValue, constructValue, (ExecutionEngine *engine, const Value &func, CallData *callData)); + + // set & get + RUNTIME_METHOD(void, setActivationProperty, (ExecutionEngine *engine, int nameIndex, const Value &value)); + RUNTIME_METHOD(void, setProperty, (ExecutionEngine *engine, const Value &object, int nameIndex, const Value &value)); + RUNTIME_METHOD(void, setElement, (ExecutionEngine *engine, const Value &object, const Value &index, const Value &value)); + RUNTIME_METHOD(ReturnedValue, getProperty, (ExecutionEngine *engine, const Value &object, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, getActivationProperty, (ExecutionEngine *engine, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, getElement, (ExecutionEngine *engine, const Value &object, const Value &index)); + + // typeof + RUNTIME_METHOD(ReturnedValue, typeofValue, (ExecutionEngine *engine, const Value &val)); + RUNTIME_METHOD(ReturnedValue, typeofName, (ExecutionEngine *engine, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, typeofScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex)); + RUNTIME_METHOD(ReturnedValue, typeofContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex)); + RUNTIME_METHOD(ReturnedValue, typeofMember, (ExecutionEngine *engine, const Value &base, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, typeofElement, (ExecutionEngine *engine, const Value &base, const Value &index)); + + // delete + RUNTIME_METHOD(ReturnedValue, deleteElement, (ExecutionEngine *engine, const Value &base, const Value &index)); + RUNTIME_METHOD(ReturnedValue, deleteMember, (ExecutionEngine *engine, const Value &base, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, deleteMemberString, (ExecutionEngine *engine, const Value &base, String *name)); + RUNTIME_METHOD(ReturnedValue, deleteName, (ExecutionEngine *engine, int nameIndex)); + + // exceptions & scopes + RUNTIME_METHOD(void, throwException, (ExecutionEngine *engine, const Value &value)); + RUNTIME_METHOD(ReturnedValue, unwindException, (ExecutionEngine *engine)); + RUNTIME_METHOD(void, pushWithScope, (const Value &o, ExecutionEngine *engine)); + RUNTIME_METHOD(void, pushCatchScope, (NoThrowEngine *engine, int exceptionVarNameIndex)); + RUNTIME_METHOD(void, popScope, (ExecutionEngine *engine)); + + // closures + RUNTIME_METHOD(ReturnedValue, closure, (ExecutionEngine *engine, int functionId)); + + // function header + RUNTIME_METHOD(void, declareVar, (ExecutionEngine *engine, bool deletable, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, setupArgumentsObject, (ExecutionEngine *engine)); + RUNTIME_METHOD(void, convertThisToObject, (ExecutionEngine *engine)); + + // literals + RUNTIME_METHOD(ReturnedValue, arrayLiteral, (ExecutionEngine *engine, Value *values, uint length)); + RUNTIME_METHOD(ReturnedValue, objectLiteral, (ExecutionEngine *engine, const Value *args, int classId, int arrayValueCount, int arrayGetterSetterCountAndFlags)); + RUNTIME_METHOD(ReturnedValue, regexpLiteral, (ExecutionEngine *engine, int id)); + + // foreach + RUNTIME_METHOD(ReturnedValue, foreachIterator, (ExecutionEngine *engine, const Value &in)); + RUNTIME_METHOD(ReturnedValue, foreachNextPropertyName, (const Value &foreach_iterator)); + + // unary operators + typedef ReturnedValue (*UnaryOperation)(const Value &value); + RUNTIME_METHOD(ReturnedValue, uPlus, (const Value &value)); + RUNTIME_METHOD(ReturnedValue, uMinus, (const Value &value)); + RUNTIME_METHOD(ReturnedValue, uNot, (const Value &value)); + RUNTIME_METHOD(ReturnedValue, complement, (const Value &value)); + RUNTIME_METHOD(ReturnedValue, increment, (const Value &value)); + RUNTIME_METHOD(ReturnedValue, decrement, (const Value &value)); + + // binary operators + typedef ReturnedValue (*BinaryOperation)(const Value &left, const Value &right); + typedef ReturnedValue (*BinaryOperationContext)(ExecutionEngine *engine, const Value &left, const Value &right); + + RUNTIME_METHOD(ReturnedValue, instanceof, (ExecutionEngine *engine, const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, in, (ExecutionEngine *engine, const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, add, (ExecutionEngine *engine, const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, addString, (ExecutionEngine *engine, const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, bitOr, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, bitXor, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, bitAnd, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, sub, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, mul, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, div, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, mod, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, shl, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, shr, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, ushr, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, greaterThan, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, lessThan, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, greaterEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, lessEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, equal, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, notEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, strictEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(ReturnedValue, strictNotEqual, (const Value &left, const Value &right)); + + // comparisons + RUNTIME_METHOD(Bool, compareGreaterThan, (const Value &l, const Value &r)); + RUNTIME_METHOD(Bool, compareLessThan, (const Value &l, const Value &r)); + RUNTIME_METHOD(Bool, compareGreaterEqual, (const Value &l, const Value &r)); + RUNTIME_METHOD(Bool, compareLessEqual, (const Value &l, const Value &r)); + RUNTIME_METHOD(Bool, compareEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(Bool, compareNotEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(Bool, compareStrictEqual, (const Value &left, const Value &right)); + RUNTIME_METHOD(Bool, compareStrictNotEqual, (const Value &left, const Value &right)); + + RUNTIME_METHOD(Bool, compareInstanceof, (ExecutionEngine *engine, const Value &left, const Value &right)); + RUNTIME_METHOD(Bool, compareIn, (ExecutionEngine *engine, const Value &left, const Value &right)); + + // conversions + RUNTIME_METHOD(Bool, toBoolean, (const Value &value)); + RUNTIME_METHOD(ReturnedValue, toDouble, (const Value &value)); + RUNTIME_METHOD(int, toInt, (const Value &value)); + RUNTIME_METHOD(int, doubleToInt, (const double &d)); + RUNTIME_METHOD(unsigned, toUInt, (const Value &value)); + RUNTIME_METHOD(unsigned, doubleToUInt, (const double &d)); + + // qml + RUNTIME_METHOD(ReturnedValue, getQmlContext, (NoThrowEngine *engine)); + RUNTIME_METHOD(ReturnedValue, getQmlImportedScripts, (NoThrowEngine *engine)); + RUNTIME_METHOD(ReturnedValue, getQmlSingleton, (NoThrowEngine *engine, int nameIndex)); + RUNTIME_METHOD(ReturnedValue, getQmlAttachedProperty, (ExecutionEngine *engine, int attachedPropertiesId, int propertyIndex)); + RUNTIME_METHOD(ReturnedValue, getQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex)); + RUNTIME_METHOD(ReturnedValue, getQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex)); + RUNTIME_METHOD(ReturnedValue, getQmlQObjectProperty, (ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)); + RUNTIME_METHOD(ReturnedValue, getQmlSingletonQObjectProperty, (ExecutionEngine *engine, const Value &object, int propertyIndex, bool captureRequired)); + RUNTIME_METHOD(ReturnedValue, getQmlIdObject, (ExecutionEngine *engine, const Value &context, uint index)); + + RUNTIME_METHOD(void, setQmlScopeObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)); + RUNTIME_METHOD(void, setQmlContextObjectProperty, (ExecutionEngine *engine, const Value &context, int propertyIndex, const Value &value)); + RUNTIME_METHOD(void, setQmlQObjectProperty, (ExecutionEngine *engine, const Value &object, int propertyIndex, const Value &value)); + + RUNTIME_METHOD(ReturnedValue, accessQObjectQRealProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectQObjectProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectIntProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectBoolProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQObjectQStringProperty, (ExecutionEngine *engine, const Value &object, QQmlAccessors *accessors, int coreIndex, int notifyIndex)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectQRealProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectQObjectProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectIntProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectBoolProperty, (const Value &context, QQmlAccessors *accessors)); + RUNTIME_METHOD(ReturnedValue, accessQmlScopeObjectQStringProperty, (ExecutionEngine *engine, const Value &context, QQmlAccessors *accessors)); +}; + +#undef RUNTIME_METHOD +#undef INIT_RUNTIME_METHOD + +} // namespace QV4 + +QT_END_NAMESPACE + +#endif // QV4RUNTIMEAPI_P_H diff --git a/src/qml/jsruntime/qv4stringobject.cpp b/src/qml/jsruntime/qv4stringobject.cpp index b874766655..b4f04bbc76 100644 --- a/src/qml/jsruntime/qv4stringobject.cpp +++ b/src/qml/jsruntime/qv4stringobject.cpp @@ -196,7 +196,9 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("charAt"), method_charAt, 1); defineDefaultProperty(QStringLiteral("charCodeAt"), method_charCodeAt, 1); defineDefaultProperty(QStringLiteral("concat"), method_concat, 1); + defineDefaultProperty(QStringLiteral("endsWith"), method_endsWith, 1); defineDefaultProperty(QStringLiteral("indexOf"), method_indexOf, 1); + defineDefaultProperty(QStringLiteral("includes"), method_includes, 1); defineDefaultProperty(QStringLiteral("lastIndexOf"), method_lastIndexOf, 1); defineDefaultProperty(QStringLiteral("localeCompare"), method_localeCompare, 1); defineDefaultProperty(QStringLiteral("match"), method_match, 1); @@ -204,6 +206,7 @@ void StringPrototype::init(ExecutionEngine *engine, Object *ctor) defineDefaultProperty(QStringLiteral("search"), method_search, 1); defineDefaultProperty(QStringLiteral("slice"), method_slice, 2); defineDefaultProperty(QStringLiteral("split"), method_split, 2); + defineDefaultProperty(QStringLiteral("startsWith"), method_startsWith, 1); defineDefaultProperty(QStringLiteral("substr"), method_substr, 2); defineDefaultProperty(QStringLiteral("substring"), method_substring, 2); defineDefaultProperty(QStringLiteral("toLowerCase"), method_toLowerCase); @@ -293,6 +296,30 @@ ReturnedValue StringPrototype::method_concat(CallContext *context) return context->d()->engine->newString(value)->asReturnedValue(); } +ReturnedValue StringPrototype::method_endsWith(CallContext *context) +{ + QString value = getThisString(context); + if (context->d()->engine->hasException) + return Encode::undefined(); + + QString searchString; + if (context->argc()) { + if (context->args()[0].as<RegExpObject>()) + return context->engine()->throwTypeError(); + searchString = context->args()[0].toQString(); + } + + int pos = value.length(); + if (context->argc() > 1) + pos = (int) context->args()[1].toInteger(); + + if (pos == value.length()) + return Encode(value.endsWith(searchString)); + + QStringRef stringToSearch = value.leftRef(pos); + return Encode(stringToSearch.endsWith(searchString)); +} + ReturnedValue StringPrototype::method_indexOf(CallContext *context) { QString value = getThisString(context); @@ -314,6 +341,35 @@ ReturnedValue StringPrototype::method_indexOf(CallContext *context) return Encode(index); } +ReturnedValue StringPrototype::method_includes(CallContext *context) +{ + QString value = getThisString(context); + if (context->d()->engine->hasException) + return Encode::undefined(); + + QString searchString; + if (context->argc()) { + if (context->args()[0].as<RegExpObject>()) + return context->engine()->throwTypeError(); + searchString = context->args()[0].toQString(); + } + + int pos = 0; + if (context->argc() > 1) { + Scope scope(context); + ScopedValue posArg(scope, context->argument(1)); + pos = (int) posArg->toInteger(); + if (!posArg->isInteger() && posArg->isNumber() && qIsInf(posArg->toNumber())) + pos = value.length(); + } + + if (pos == 0) + return Encode(value.contains(searchString)); + + QStringRef stringToSearch = value.midRef(pos); + return Encode(stringToSearch.contains(searchString)); +} + ReturnedValue StringPrototype::method_lastIndexOf(CallContext *context) { Scope scope(context); @@ -716,6 +772,30 @@ ReturnedValue StringPrototype::method_split(CallContext *ctx) return array.asReturnedValue(); } +ReturnedValue StringPrototype::method_startsWith(CallContext *context) +{ + QString value = getThisString(context); + if (context->d()->engine->hasException) + return Encode::undefined(); + + QString searchString; + if (context->argc()) { + if (context->args()[0].as<RegExpObject>()) + return context->engine()->throwTypeError(); + searchString = context->args()[0].toQString(); + } + + int pos = 0; + if (context->argc() > 1) + pos = (int) context->args()[1].toInteger(); + + if (pos == 0) + return Encode(value.startsWith(searchString)); + + QStringRef stringToSearch = value.midRef(pos); + return Encode(stringToSearch.startsWith(searchString)); +} + ReturnedValue StringPrototype::method_substr(CallContext *context) { const QString value = getThisString(context); diff --git a/src/qml/jsruntime/qv4stringobject_p.h b/src/qml/jsruntime/qv4stringobject_p.h index 3930a011e6..fb229d4aff 100644 --- a/src/qml/jsruntime/qv4stringobject_p.h +++ b/src/qml/jsruntime/qv4stringobject_p.h @@ -115,7 +115,9 @@ struct StringPrototype: StringObject static ReturnedValue method_charAt(CallContext *context); static ReturnedValue method_charCodeAt(CallContext *context); static ReturnedValue method_concat(CallContext *context); + static ReturnedValue method_endsWith(CallContext *ctx); static ReturnedValue method_indexOf(CallContext *context); + static ReturnedValue method_includes(CallContext *context); static ReturnedValue method_lastIndexOf(CallContext *context); static ReturnedValue method_localeCompare(CallContext *context); static ReturnedValue method_match(CallContext *context); @@ -123,6 +125,7 @@ struct StringPrototype: StringObject static ReturnedValue method_search(CallContext *ctx); static ReturnedValue method_slice(CallContext *ctx); static ReturnedValue method_split(CallContext *ctx); + static ReturnedValue method_startsWith(CallContext *ctx); static ReturnedValue method_substr(CallContext *context); static ReturnedValue method_substring(CallContext *context); static ReturnedValue method_toLowerCase(CallContext *ctx); diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp index ecbc243baa..9ad21305f7 100644 --- a/src/qml/jsruntime/qv4vme_moth.cpp +++ b/src/qml/jsruntime/qv4vme_moth.cpp @@ -451,12 +451,12 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(LoadRegExp) MOTH_BEGIN_INSTR(LoadClosure) - STOREVALUE(instr.result, Runtime::closure(engine, instr.value)); + STOREVALUE(instr.result, engine->runtime.closure(engine, instr.value)); MOTH_END_INSTR(LoadClosure) MOTH_BEGIN_INSTR(LoadName) TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData()); - STOREVALUE(instr.result, Runtime::getActivationProperty(engine, instr.name)); + STOREVALUE(instr.result, engine->runtime.getActivationProperty(engine, instr.name)); MOTH_END_INSTR(LoadName) MOTH_BEGIN_INSTR(GetGlobalLookup) @@ -466,12 +466,12 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_BEGIN_INSTR(StoreName) TRACE(inline, "property name = %s", runtimeStrings[instr.name]->toQString().toUtf8().constData()); - Runtime::setActivationProperty(engine, instr.name, VALUE(instr.source)); + engine->runtime.setActivationProperty(engine, instr.name, VALUE(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreName) MOTH_BEGIN_INSTR(LoadElement) - STOREVALUE(instr.result, Runtime::getElement(engine, VALUE(instr.base), VALUE(instr.index))); + STOREVALUE(instr.result, engine->runtime.getElement(engine, VALUE(instr.base), VALUE(instr.index))); MOTH_END_INSTR(LoadElement) MOTH_BEGIN_INSTR(LoadElementLookup) @@ -480,7 +480,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(LoadElementLookup) MOTH_BEGIN_INSTR(StoreElement) - Runtime::setElement(engine, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source)); + engine->runtime.setElement(engine, VALUE(instr.base), VALUE(instr.index), VALUE(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreElement) @@ -491,7 +491,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(StoreElementLookup) MOTH_BEGIN_INSTR(LoadProperty) - STOREVALUE(instr.result, Runtime::getProperty(engine, VALUE(instr.base), instr.name)); + STOREVALUE(instr.result, engine->runtime.getProperty(engine, VALUE(instr.base), instr.name)); MOTH_END_INSTR(LoadProperty) MOTH_BEGIN_INSTR(GetLookup) @@ -500,7 +500,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(GetLookup) MOTH_BEGIN_INSTR(StoreProperty) - Runtime::setProperty(engine, VALUE(instr.base), instr.name, VALUE(instr.source)); + engine->runtime.setProperty(engine, VALUE(instr.base), instr.name, VALUE(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreProperty) @@ -511,42 +511,82 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(SetLookup) MOTH_BEGIN_INSTR(StoreQObjectProperty) - Runtime::setQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); + engine->runtime.setQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreQObjectProperty) MOTH_BEGIN_INSTR(LoadQObjectProperty) - STOREVALUE(instr.result, Runtime::getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); + STOREVALUE(instr.result, engine->runtime.getQmlQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); MOTH_END_INSTR(LoadQObjectProperty) + MOTH_BEGIN_INSTR(LoadQRealQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectQRealProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQRealQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadQObjectQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectQObjectProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQObjectQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadIntQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectIntProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadIntQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadBoolQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectBoolProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQRealQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadQStringQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQObjectQStringProperty(engine, VALUE(instr.base), instr.accessors, instr.coreIndex, instr.notifyIndex)); + MOTH_END_INSTR(LoadQStringQObjectPropertyDirectly) + MOTH_BEGIN_INSTR(StoreScopeObjectProperty) - Runtime::setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); + engine->runtime.setQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreScopeObjectProperty) MOTH_BEGIN_INSTR(LoadScopeObjectProperty) - STOREVALUE(instr.result, Runtime::getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); + STOREVALUE(instr.result, engine->runtime.getQmlScopeObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); MOTH_END_INSTR(LoadScopeObjectProperty) + MOTH_BEGIN_INSTR(LoadScopeObjectQRealPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectQRealProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectQRealPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectQObjectPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectQObjectProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectQObjectPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectIntPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectIntProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectIntPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectBoolPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectBoolProperty(VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectBoolPropertyDirectly) + + MOTH_BEGIN_INSTR(LoadScopeObjectQStringPropertyDirectly) + STOREVALUE(instr.result, engine->runtime.accessQmlScopeObjectQStringProperty(engine, VALUE(instr.base), instr.accessors)); + MOTH_END_INSTR(LoadScopeObjectQStringPropertyDirectly) + MOTH_BEGIN_INSTR(StoreContextObjectProperty) - Runtime::setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); + engine->runtime.setQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, VALUE(instr.source)); CHECK_EXCEPTION; MOTH_END_INSTR(StoreContextObjectProperty) MOTH_BEGIN_INSTR(LoadContextObjectProperty) - STOREVALUE(instr.result, Runtime::getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); + STOREVALUE(instr.result, engine->runtime.getQmlContextObjectProperty(engine, VALUE(instr.base), instr.propertyIndex)); MOTH_END_INSTR(LoadContextObjectProperty) MOTH_BEGIN_INSTR(LoadIdObject) - STOREVALUE(instr.result, Runtime::getQmlIdObject(engine, VALUE(instr.base), instr.index)); + STOREVALUE(instr.result, engine->runtime.getQmlIdObject(engine, VALUE(instr.base), instr.index)); MOTH_END_INSTR(LoadIdObject) MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty) - STOREVALUE(instr.result, Runtime::getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex)); + STOREVALUE(instr.result, engine->runtime.getQmlAttachedProperty(engine, instr.attachedPropertiesId, instr.propertyIndex)); MOTH_END_INSTR(LoadAttachedQObjectProperty) MOTH_BEGIN_INSTR(LoadSingletonQObjectProperty) - STOREVALUE(instr.result, Runtime::getQmlSingletonQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); + STOREVALUE(instr.result, engine->runtime.getQmlSingletonQObjectProperty(engine, VALUE(instr.base), instr.propertyIndex, instr.captureRequired)); MOTH_END_INSTR(LoadSingletonQObjectProperty) MOTH_BEGIN_INSTR(Push) @@ -572,7 +612,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); - STOREVALUE(instr.result, Runtime::callValue(engine, VALUE(instr.dest), callData)); + STOREVALUE(instr.result, engine->runtime.callValue(engine, VALUE(instr.dest), callData)); MOTH_END_INSTR(CallValue) MOTH_BEGIN_INSTR(CallProperty) @@ -582,7 +622,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::callProperty(engine, instr.name, callData)); + STOREVALUE(instr.result, engine->runtime.callProperty(engine, instr.name, callData)); MOTH_END_INSTR(CallProperty) MOTH_BEGIN_INSTR(CallPropertyLookup) @@ -591,7 +631,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::callPropertyLookup(engine, instr.lookupIndex, callData)); + STOREVALUE(instr.result, engine->runtime.callPropertyLookup(engine, instr.lookupIndex, callData)); MOTH_END_INSTR(CallPropertyLookup) MOTH_BEGIN_INSTR(CallScopeObjectProperty) @@ -601,7 +641,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::callQmlScopeObjectProperty(engine, instr.index, callData)); + STOREVALUE(instr.result, engine->runtime.callQmlScopeObjectProperty(engine, instr.index, callData)); MOTH_END_INSTR(CallScopeObjectProperty) MOTH_BEGIN_INSTR(CallContextObjectProperty) @@ -611,7 +651,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::callQmlContextObjectProperty(engine, instr.index, callData)); + STOREVALUE(instr.result, engine->runtime.callQmlContextObjectProperty(engine, instr.index, callData)); MOTH_END_INSTR(CallContextObjectProperty) MOTH_BEGIN_INSTR(CallElement) @@ -620,7 +660,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::callElement(engine, VALUE(instr.index), callData)); + STOREVALUE(instr.result, engine->runtime.callElement(engine, VALUE(instr.index), callData)); MOTH_END_INSTR(CallElement) MOTH_BEGIN_INSTR(CallActivationProperty) @@ -629,7 +669,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); - STOREVALUE(instr.result, Runtime::callActivationProperty(engine, instr.name, callData)); + STOREVALUE(instr.result, engine->runtime.callActivationProperty(engine, instr.name, callData)); MOTH_END_INSTR(CallActivationProperty) MOTH_BEGIN_INSTR(CallGlobalLookup) @@ -638,7 +678,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); - STOREVALUE(instr.result, Runtime::callGlobalLookup(engine, instr.index, callData)); + STOREVALUE(instr.result, Runtime::method_callGlobalLookup(engine, instr.index, callData)); MOTH_END_INSTR(CallGlobalLookup) MOTH_BEGIN_INSTR(SetExceptionHandler) @@ -646,95 +686,95 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(SetExceptionHandler) MOTH_BEGIN_INSTR(CallBuiltinThrow) - Runtime::throwException(engine, VALUE(instr.arg)); + engine->runtime.throwException(engine, VALUE(instr.arg)); CHECK_EXCEPTION; MOTH_END_INSTR(CallBuiltinThrow) MOTH_BEGIN_INSTR(CallBuiltinUnwindException) - STOREVALUE(instr.result, Runtime::unwindException(engine)); + STOREVALUE(instr.result, engine->runtime.unwindException(engine)); MOTH_END_INSTR(CallBuiltinUnwindException) MOTH_BEGIN_INSTR(CallBuiltinPushCatchScope) - Runtime::pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name); + engine->runtime.pushCatchScope(static_cast<QV4::NoThrowEngine*>(engine), instr.name); context = engine->currentContext; MOTH_END_INSTR(CallBuiltinPushCatchScope) MOTH_BEGIN_INSTR(CallBuiltinPushScope) - Runtime::pushWithScope(VALUE(instr.arg), engine); + engine->runtime.pushWithScope(VALUE(instr.arg), engine); context = engine->currentContext; CHECK_EXCEPTION; MOTH_END_INSTR(CallBuiltinPushScope) MOTH_BEGIN_INSTR(CallBuiltinPopScope) - Runtime::popScope(engine); + engine->runtime.popScope(engine); context = engine->currentContext; MOTH_END_INSTR(CallBuiltinPopScope) MOTH_BEGIN_INSTR(CallBuiltinForeachIteratorObject) - STOREVALUE(instr.result, Runtime::foreachIterator(engine, VALUE(instr.arg))); + STOREVALUE(instr.result, engine->runtime.foreachIterator(engine, VALUE(instr.arg))); MOTH_END_INSTR(CallBuiltinForeachIteratorObject) MOTH_BEGIN_INSTR(CallBuiltinForeachNextPropertyName) - STOREVALUE(instr.result, Runtime::foreachNextPropertyName(VALUE(instr.arg))); + STOREVALUE(instr.result, engine->runtime.foreachNextPropertyName(VALUE(instr.arg))); MOTH_END_INSTR(CallBuiltinForeachNextPropertyName) MOTH_BEGIN_INSTR(CallBuiltinDeleteMember) - STOREVALUE(instr.result, Runtime::deleteMember(engine, VALUE(instr.base), instr.member)); + STOREVALUE(instr.result, engine->runtime.deleteMember(engine, VALUE(instr.base), instr.member)); MOTH_END_INSTR(CallBuiltinDeleteMember) MOTH_BEGIN_INSTR(CallBuiltinDeleteSubscript) - STOREVALUE(instr.result, Runtime::deleteElement(engine, VALUE(instr.base), VALUE(instr.index))); + STOREVALUE(instr.result, engine->runtime.deleteElement(engine, VALUE(instr.base), VALUE(instr.index))); MOTH_END_INSTR(CallBuiltinDeleteSubscript) MOTH_BEGIN_INSTR(CallBuiltinDeleteName) - STOREVALUE(instr.result, Runtime::deleteName(engine, instr.name)); + STOREVALUE(instr.result, engine->runtime.deleteName(engine, instr.name)); MOTH_END_INSTR(CallBuiltinDeleteName) MOTH_BEGIN_INSTR(CallBuiltinTypeofScopeObjectProperty) - STOREVALUE(instr.result, Runtime::typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index)); + STOREVALUE(instr.result, engine->runtime.typeofScopeObjectProperty(engine, VALUE(instr.base), instr.index)); MOTH_END_INSTR(CallBuiltinTypeofMember) MOTH_BEGIN_INSTR(CallBuiltinTypeofContextObjectProperty) - STOREVALUE(instr.result, Runtime::typeofContextObjectProperty(engine, VALUE(instr.base), instr.index)); + STOREVALUE(instr.result, engine->runtime.typeofContextObjectProperty(engine, VALUE(instr.base), instr.index)); MOTH_END_INSTR(CallBuiltinTypeofMember) MOTH_BEGIN_INSTR(CallBuiltinTypeofMember) - STOREVALUE(instr.result, Runtime::typeofMember(engine, VALUE(instr.base), instr.member)); + STOREVALUE(instr.result, engine->runtime.typeofMember(engine, VALUE(instr.base), instr.member)); MOTH_END_INSTR(CallBuiltinTypeofMember) MOTH_BEGIN_INSTR(CallBuiltinTypeofSubscript) - STOREVALUE(instr.result, Runtime::typeofElement(engine, VALUE(instr.base), VALUE(instr.index))); + STOREVALUE(instr.result, engine->runtime.typeofElement(engine, VALUE(instr.base), VALUE(instr.index))); MOTH_END_INSTR(CallBuiltinTypeofSubscript) MOTH_BEGIN_INSTR(CallBuiltinTypeofName) - STOREVALUE(instr.result, Runtime::typeofName(engine, instr.name)); + STOREVALUE(instr.result, engine->runtime.typeofName(engine, instr.name)); MOTH_END_INSTR(CallBuiltinTypeofName) MOTH_BEGIN_INSTR(CallBuiltinTypeofValue) - STOREVALUE(instr.result, Runtime::typeofValue(engine, VALUE(instr.value))); + STOREVALUE(instr.result, engine->runtime.typeofValue(engine, VALUE(instr.value))); MOTH_END_INSTR(CallBuiltinTypeofValue) MOTH_BEGIN_INSTR(CallBuiltinDeclareVar) - Runtime::declareVar(engine, instr.isDeletable, instr.varName); + engine->runtime.declareVar(engine, instr.isDeletable, instr.varName); MOTH_END_INSTR(CallBuiltinDeclareVar) MOTH_BEGIN_INSTR(CallBuiltinDefineArray) Q_ASSERT(instr.args + instr.argc <= stackSize); QV4::Value *args = stack + instr.args; - STOREVALUE(instr.result, Runtime::arrayLiteral(engine, args, instr.argc)); + STOREVALUE(instr.result, engine->runtime.arrayLiteral(engine, args, instr.argc)); MOTH_END_INSTR(CallBuiltinDefineArray) MOTH_BEGIN_INSTR(CallBuiltinDefineObjectLiteral) QV4::Value *args = stack + instr.args; - STOREVALUE(instr.result, Runtime::objectLiteral(engine, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags)); + STOREVALUE(instr.result, engine->runtime.objectLiteral(engine, args, instr.internalClassId, instr.arrayValueCount, instr.arrayGetterSetterCountAndFlags)); MOTH_END_INSTR(CallBuiltinDefineObjectLiteral) MOTH_BEGIN_INSTR(CallBuiltinSetupArgumentsObject) - STOREVALUE(instr.result, Runtime::setupArgumentsObject(engine)); + STOREVALUE(instr.result, engine->runtime.setupArgumentsObject(engine)); MOTH_END_INSTR(CallBuiltinSetupArgumentsObject) MOTH_BEGIN_INSTR(CallBuiltinConvertThisToObject) - Runtime::convertThisToObject(engine); + engine->runtime.convertThisToObject(engine); CHECK_EXCEPTION; MOTH_END_INSTR(CallBuiltinConvertThisToObject) @@ -744,7 +784,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); - STOREVALUE(instr.result, Runtime::constructValue(engine, VALUE(instr.func), callData)); + STOREVALUE(instr.result, engine->runtime.constructValue(engine, VALUE(instr.func), callData)); MOTH_END_INSTR(CreateValue) MOTH_BEGIN_INSTR(CreateProperty) @@ -753,7 +793,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::constructProperty(engine, instr.name, callData)); + STOREVALUE(instr.result, engine->runtime.constructProperty(engine, instr.name, callData)); MOTH_END_INSTR(CreateProperty) MOTH_BEGIN_INSTR(ConstructPropertyLookup) @@ -762,7 +802,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = VALUE(instr.base); - STOREVALUE(instr.result, Runtime::constructPropertyLookup(engine, instr.index, callData)); + STOREVALUE(instr.result, engine->runtime.constructPropertyLookup(engine, instr.index, callData)); MOTH_END_INSTR(ConstructPropertyLookup) MOTH_BEGIN_INSTR(CreateActivationProperty) @@ -771,7 +811,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); - STOREVALUE(instr.result, Runtime::constructActivationProperty(engine, instr.name, callData)); + STOREVALUE(instr.result, engine->runtime.constructActivationProperty(engine, instr.name, callData)); MOTH_END_INSTR(CreateActivationProperty) MOTH_BEGIN_INSTR(ConstructGlobalLookup) @@ -780,7 +820,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code callData->tag = QV4::Value::Integer_Type; callData->argc = instr.argc; callData->thisObject = QV4::Primitive::undefinedValue(); - STOREVALUE(instr.result, Runtime::constructGlobalLookup(engine, instr.index, callData)); + STOREVALUE(instr.result, engine->runtime.constructGlobalLookup(engine, instr.index, callData)); MOTH_END_INSTR(ConstructGlobalLookup) MOTH_BEGIN_INSTR(Jump) @@ -802,7 +842,7 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(JumpNe) MOTH_BEGIN_INSTR(UNot) - STOREVALUE(instr.result, Runtime::uNot(VALUE(instr.source))); + STOREVALUE(instr.result, engine->runtime.uNot(VALUE(instr.source))); MOTH_END_INSTR(UNot) MOTH_BEGIN_INSTR(UNotBool) @@ -811,15 +851,15 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(UNotBool) MOTH_BEGIN_INSTR(UPlus) - STOREVALUE(instr.result, Runtime::uPlus(VALUE(instr.source))); + STOREVALUE(instr.result, engine->runtime.uPlus(VALUE(instr.source))); MOTH_END_INSTR(UPlus) MOTH_BEGIN_INSTR(UMinus) - STOREVALUE(instr.result, Runtime::uMinus(VALUE(instr.source))); + STOREVALUE(instr.result, engine->runtime.uMinus(VALUE(instr.source))); MOTH_END_INSTR(UMinus) MOTH_BEGIN_INSTR(UCompl) - STOREVALUE(instr.result, Runtime::complement(VALUE(instr.source))); + STOREVALUE(instr.result, engine->runtime.complement(VALUE(instr.source))); MOTH_END_INSTR(UCompl) MOTH_BEGIN_INSTR(UComplInt) @@ -827,31 +867,32 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(UComplInt) MOTH_BEGIN_INSTR(Increment) - STOREVALUE(instr.result, Runtime::increment(VALUE(instr.source))); + STOREVALUE(instr.result, engine->runtime.increment(VALUE(instr.source))); MOTH_END_INSTR(Increment) MOTH_BEGIN_INSTR(Decrement) - STOREVALUE(instr.result, Runtime::decrement(VALUE(instr.source))); + STOREVALUE(instr.result, engine->runtime.decrement(VALUE(instr.source))); MOTH_END_INSTR(Decrement) MOTH_BEGIN_INSTR(Binop) - STOREVALUE(instr.result, instr.alu(VALUE(instr.lhs), VALUE(instr.rhs))); + QV4::Runtime::BinaryOperation op = *reinterpret_cast<QV4::Runtime::BinaryOperation *>(reinterpret_cast<char *>(&engine->runtime) + instr.alu); + STOREVALUE(instr.result, op(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(Binop) MOTH_BEGIN_INSTR(Add) - STOREVALUE(instr.result, Runtime::add(engine, VALUE(instr.lhs), VALUE(instr.rhs))); + STOREVALUE(instr.result, engine->runtime.add(engine, VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(Add) MOTH_BEGIN_INSTR(BitAnd) - STOREVALUE(instr.result, Runtime::bitAnd(VALUE(instr.lhs), VALUE(instr.rhs))); + STOREVALUE(instr.result, engine->runtime.bitAnd(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(BitAnd) MOTH_BEGIN_INSTR(BitOr) - STOREVALUE(instr.result, Runtime::bitOr(VALUE(instr.lhs), VALUE(instr.rhs))); + STOREVALUE(instr.result, engine->runtime.bitOr(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(BitOr) MOTH_BEGIN_INSTR(BitXor) - STOREVALUE(instr.result, Runtime::bitXor(VALUE(instr.lhs), VALUE(instr.rhs))); + STOREVALUE(instr.result, engine->runtime.bitXor(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(BitXor) MOTH_BEGIN_INSTR(Shr) @@ -886,15 +927,16 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(ShlConst) MOTH_BEGIN_INSTR(Mul) - STOREVALUE(instr.result, Runtime::mul(VALUE(instr.lhs), VALUE(instr.rhs))); + STOREVALUE(instr.result, engine->runtime.mul(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(Mul) MOTH_BEGIN_INSTR(Sub) - STOREVALUE(instr.result, Runtime::sub(VALUE(instr.lhs), VALUE(instr.rhs))); + STOREVALUE(instr.result, engine->runtime.sub(VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(Sub) MOTH_BEGIN_INSTR(BinopContext) - STOREVALUE(instr.result, instr.alu(engine, VALUE(instr.lhs), VALUE(instr.rhs))); + QV4::Runtime::BinaryOperationContext op = *reinterpret_cast<QV4::Runtime::BinaryOperationContext *>(reinterpret_cast<char *>(&engine->runtime) + instr.alu); + STOREVALUE(instr.result, op(engine, VALUE(instr.lhs), VALUE(instr.rhs))); MOTH_END_INSTR(BinopContext) MOTH_BEGIN_INSTR(Ret) @@ -922,15 +964,15 @@ QV4::ReturnedValue VME::run(ExecutionEngine *engine, const uchar *code MOTH_END_INSTR(LoadThis) MOTH_BEGIN_INSTR(LoadQmlContext) - VALUE(instr.result) = Runtime::getQmlContext(static_cast<QV4::NoThrowEngine*>(engine)); + VALUE(instr.result) = engine->runtime.getQmlContext(static_cast<QV4::NoThrowEngine*>(engine)); MOTH_END_INSTR(LoadQmlContext) MOTH_BEGIN_INSTR(LoadQmlImportedScripts) - VALUE(instr.result) = Runtime::getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine)); + VALUE(instr.result) = engine->runtime.getQmlImportedScripts(static_cast<QV4::NoThrowEngine*>(engine)); MOTH_END_INSTR(LoadQmlImportedScripts) MOTH_BEGIN_INSTR(LoadQmlSingleton) - VALUE(instr.result) = Runtime::getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name); + VALUE(instr.result) = engine->runtime.getQmlSingleton(static_cast<QV4::NoThrowEngine*>(engine), instr.name); MOTH_END_INSTR(LoadQmlSingleton) #ifdef MOTH_THREADED_INTERPRETER diff --git a/src/qml/qml.pro b/src/qml/qml.pro index e30c39c8b9..bae8f25efc 100644 --- a/src/qml/qml.pro +++ b/src/qml/qml.pro @@ -1,11 +1,17 @@ TARGET = QtQml -QT = core-private network +QT = core-private + +no_network { + DEFINES += QT_NO_NETWORK +} else { + QT += network +} DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x66000000 win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS -win32:!wince*:!winrt:LIBS += -lshell32 +win32:!winrt:LIBS += -lshell32 solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 # Ensure this gcc optimization is switched off for mips platforms to avoid trouble with JIT. diff --git a/src/qml/qml/ftw/ftw.pri b/src/qml/qml/ftw/ftw.pri index a671cfa12d..addf1d9ff8 100644 --- a/src/qml/qml/ftw/ftw.pri +++ b/src/qml/qml/ftw/ftw.pri @@ -11,7 +11,6 @@ HEADERS += \ $$PWD/qdeletewatcher_p.h \ $$PWD/qrecyclepool_p.h \ $$PWD/qflagpointer_p.h \ - $$PWD/qpointervaluepair_p.h \ $$PWD/qlazilyallocated_p.h \ $$PWD/qqmlnullablevalue_p.h \ diff --git a/src/qml/qml/ftw/qpointervaluepair_p.h b/src/qml/qml/ftw/qpointervaluepair_p.h deleted file mode 100644 index 3d0644039f..0000000000 --- a/src/qml/qml/ftw/qpointervaluepair_p.h +++ /dev/null @@ -1,194 +0,0 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ - -#ifndef QPOINTERVALUEPAIR_P_H -#define QPOINTERVALUEPAIR_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/qglobal.h> -#include <private/qflagpointer_p.h> - -QT_BEGIN_NAMESPACE - -// QPointerValuePair is intended to help reduce the memory consumption of a class. -// In the common case, QPointerValuePair behaves like a pointer. In this mode, it -// consumes the same memory as a regular pointer. -// Additionally, QPointerValuePair can store an arbitrary value type in *addition* -// to the pointer. In this case, it uses slightly more memory than the pointer and -// value type combined. -// Consequently, this class is most useful in cases where a pointer is always stored -// and a value type is rarely stored. -template<typename P, typename V> -class QPointerValuePair { -public: - inline QPointerValuePair(); - inline QPointerValuePair(P *); - inline ~QPointerValuePair(); - - inline bool isNull() const; - - inline bool flag() const; - inline void setFlag(); - inline void clearFlag(); - inline void setFlagValue(bool); - - inline QPointerValuePair<P, V> &operator=(P *); - - inline P *operator->() const; - inline P *operator*() const; - - inline bool hasValue() const; - inline V &value(); - inline const V *constValue() const; - -private: - struct Value { P *pointer; V value; }; - QBiPointer<P, Value> d; -}; - -template<typename P, typename V> -QPointerValuePair<P, V>::QPointerValuePair() -{ -} - -template<typename P, typename V> -QPointerValuePair<P, V>::QPointerValuePair(P *p) -: d(p) -{ -} - -template<typename P, typename V> -QPointerValuePair<P, V>::~QPointerValuePair() -{ - if (d.isT2()) delete d.asT2(); -} - -template<typename P, typename V> -bool QPointerValuePair<P, V>::isNull() const -{ - if (d.isT1()) return 0 == d.asT1(); - else return d.asT2()->pointer == 0; -} - -template<typename P, typename V> -bool QPointerValuePair<P, V>::flag() const -{ - return d.flag(); -} - -template<typename P, typename V> -void QPointerValuePair<P, V>::setFlag() -{ - d.setFlag(); -} - -template<typename P, typename V> -void QPointerValuePair<P, V>::clearFlag() -{ - d.clearFlag(); -} - -template<typename P, typename V> -void QPointerValuePair<P, V>::setFlagValue(bool v) -{ - d.setFlagValue(v); -} - -template<typename P, typename V> -QPointerValuePair<P, V> &QPointerValuePair<P, V>::operator=(P *o) -{ - if (d.isT1()) d = o; - else d.asT2()->pointer = o; - return *this; -} - -template<typename P, typename V> -P *QPointerValuePair<P, V>::operator->() const -{ - if (d.isT1()) return d.asT1(); - else return d.asT2()->pointer; -} - -template<typename P, typename V> -P *QPointerValuePair<P, V>::operator*() const -{ - if (d.isT1()) return d.asT1(); - else return d.asT2()->pointer; -} - -template<typename P, typename V> -bool QPointerValuePair<P, V>::hasValue() const -{ - return d.isT2(); -} - -template<typename P, typename V> -V &QPointerValuePair<P, V>::value() -{ - if (d.isT1()) { - P *p = d.asT1(); - Value *value = new Value; - value->pointer = p; - d = value; - } - - return d.asT2()->value; -} - -// Will return null if hasValue() == false -template<typename P, typename V> -const V *QPointerValuePair<P, V>::constValue() const -{ - if (d.isT2()) return &d.asT2()->value; - else return 0; -} - -QT_END_NAMESPACE - -#endif // QPOINTERVALUEPAIR_P_H diff --git a/src/qml/qml/qml.pri b/src/qml/qml/qml.pri index 4d84cc82ae..91d883c29f 100644 --- a/src/qml/qml/qml.pri +++ b/src/qml/qml/qml.pri @@ -50,7 +50,8 @@ SOURCES += \ $$PWD/qqmltypewrapper.cpp \ $$PWD/qqmlfileselector.cpp \ $$PWD/qqmlobjectcreator.cpp \ - $$PWD/qqmldirparser.cpp + $$PWD/qqmldirparser.cpp \ + $$PWD/qqmldelayedcallqueue.cpp HEADERS += \ $$PWD/qqmlglobal_p.h \ @@ -122,7 +123,8 @@ HEADERS += \ $$PWD/qqmlfileselector_p.h \ $$PWD/qqmlfileselector.h \ $$PWD/qqmlobjectcreator_p.h \ - $$PWD/qqmldirparser_p.h + $$PWD/qqmldirparser_p.h \ + $$PWD/qqmldelayedcallqueue_p.h include(ftw/ftw.pri) include(v8/v8.pri) diff --git a/src/qml/qml/qqmlabstractbinding_p.h b/src/qml/qml/qqmlabstractbinding_p.h index 674178153a..45221a4bcd 100644 --- a/src/qml/qml/qqmlabstractbinding_p.h +++ b/src/qml/qml/qqmlabstractbinding_p.h @@ -55,7 +55,6 @@ #include <QtCore/qshareddata.h> #include <private/qtqmlglobal_p.h> #include <private/qqmlproperty_p.h> -#include <private/qpointervaluepair_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlbinding_p.h b/src/qml/qml/qqmlbinding_p.h index 7814b9dee8..45c360f07e 100644 --- a/src/qml/qml/qqmlbinding_p.h +++ b/src/qml/qml/qqmlbinding_p.h @@ -61,7 +61,6 @@ #include <QtCore/QObject> #include <QtCore/QMetaProperty> -#include <private/qpointervaluepair_p.h> #include <private/qqmlabstractbinding_p.h> #include <private/qqmljavascriptexpression_p.h> @@ -86,12 +85,10 @@ public: void setNotifyOnValueChanged(bool); - // Inherited from QQmlJavaScriptExpression - virtual void refresh(); + void refresh() Q_DECL_OVERRIDE; - // Inherited from QQmlAbstractBinding - virtual void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding); - virtual QString expression() const; + void setEnabled(bool, QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding) Q_DECL_OVERRIDE; + QString expression() const Q_DECL_OVERRIDE; void update(QQmlPropertyPrivate::WriteFlags flags = QQmlPropertyPrivate::DontRemoveBinding); typedef int Identifier; @@ -101,8 +98,8 @@ public: QVariant evaluate(); - virtual QString expressionIdentifier(); - virtual void expressionChanged(); + QString expressionIdentifier() Q_DECL_OVERRIDE; + void expressionChanged() Q_DECL_OVERRIDE; private: inline bool updatingFlag() const; diff --git a/src/qml/qml/qqmldelayedcallqueue.cpp b/src/qml/qml/qqmldelayedcallqueue.cpp new file mode 100644 index 0000000000..8d0fb22866 --- /dev/null +++ b/src/qml/qml/qqmldelayedcallqueue.cpp @@ -0,0 +1,214 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#include "qqmldelayedcallqueue_p.h" +#include <private/qv8engine_p.h> +#include <private/qqmlengine_p.h> +#include <private/qqmljavascriptexpression_p.h> +#include <private/qv4value_p.h> +#include <private/qv4qobjectwrapper_p.h> + +#include <QQmlError> + +QT_BEGIN_NAMESPACE + +// +// struct QQmlDelayedCallQueue::DelayedFunctionCall +// + +void QQmlDelayedCallQueue::DelayedFunctionCall::execute(QV4::ExecutionEngine *engine) const +{ + if (!m_guarded || + (!m_objectGuard.isNull() && + !QQmlData::wasDeleted(m_objectGuard) && + QQmlData::get(m_objectGuard) && + !QQmlData::get(m_objectGuard)->isQueuedForDeletion)) { + + QV4::Scope scope(engine); + + QV4::ArrayObject *array = m_args.as<QV4::ArrayObject>(); + const int argCount = array ? array->getLength() : 0; + QV4::ScopedCallData callData(scope, argCount); + callData->thisObject = QV4::Encode::undefined(); + + for (int i = 0; i < argCount; i++) { + callData->args[i] = array->getIndexed(i); + } + + const QV4::FunctionObject *callback = m_function.as<QV4::FunctionObject>(); + Q_ASSERT(callback); + callback->call(callData); + + if (scope.engine->hasException) { + QQmlError error = scope.engine->catchExceptionAsQmlError(); + error.setDescription(error.description() + QLatin1String(" (exception occurred during delayed function evaluation)")); + QQmlEnginePrivate::warning(QQmlEnginePrivate::get(scope.engine->qmlEngine()), error); + } + } +} + +// +// class QQmlDelayedCallQueue +// + +QQmlDelayedCallQueue::QQmlDelayedCallQueue() + : QObject(0), m_engine(0), m_callbackOutstanding(false) +{ +} + +QQmlDelayedCallQueue::~QQmlDelayedCallQueue() +{ +} + +void QQmlDelayedCallQueue::init(QV4::ExecutionEngine* engine) +{ + m_engine = engine; + + const QMetaObject &metaObject = QQmlDelayedCallQueue::staticMetaObject; + int methodIndex = metaObject.indexOfSlot("ticked()"); + m_tickedMethod = metaObject.method(methodIndex); +} + +QV4::ReturnedValue QQmlDelayedCallQueue::addUniquelyAndExecuteLater(QV4::CallContext *ctx) +{ + const QV4::CallData *callData = ctx->d()->callData; + + if (callData->argc == 0) + V4THROW_ERROR("Qt.callLater: no arguments given"); + + const QV4::FunctionObject *func = callData->args[0].as<QV4::FunctionObject>(); + + if (!func) + V4THROW_ERROR("Qt.callLater: first argument not a function or signal"); + + QPair<QObject *, int> functionData = QV4::QObjectMethod::extractQtMethod(func); + + QVector<DelayedFunctionCall>::Iterator iter; + if (functionData.second != -1) { + // This is a QObject function wrapper + iter = m_delayedFunctionCalls.begin(); + while (iter != m_delayedFunctionCalls.end()) { + DelayedFunctionCall& dfc = *iter; + QPair<QObject *, int> storedFunctionData = QV4::QObjectMethod::extractQtMethod(dfc.m_function.as<QV4::FunctionObject>()); + if (storedFunctionData == functionData) { + break; // Already stored! + } + ++iter; + } + } else { + // This is a JavaScript function (dynamic slot on VMEMO) + iter = m_delayedFunctionCalls.begin(); + while (iter != m_delayedFunctionCalls.end()) { + DelayedFunctionCall& dfc = *iter; + if (callData->argument(0) == dfc.m_function.value()) { + break; // Already stored! + } + ++iter; + } + } + + const bool functionAlreadyStored = (iter != m_delayedFunctionCalls.end()); + if (functionAlreadyStored) { + DelayedFunctionCall dfc = *iter; + m_delayedFunctionCalls.erase(iter); + m_delayedFunctionCalls.append(dfc); + } else { + m_delayedFunctionCalls.append(QV4::PersistentValue(m_engine, callData->argument(0))); + } + + DelayedFunctionCall& dfc = m_delayedFunctionCalls.last(); + if (dfc.m_objectGuard.isNull()) { + if (functionData.second != -1) { + // if it's a qobject function wrapper, guard against qobject deletion + dfc.m_objectGuard = QQmlGuard<QObject>(functionData.first); + dfc.m_guarded = true; + } else if (func->scope()->type == QV4::Heap::ExecutionContext::Type_QmlContext) { + QV4::QmlContext::Data *g = static_cast<QV4::QmlContext::Data *>(func->scope()); + Q_ASSERT(g->qml->scopeObject); + dfc.m_objectGuard = QQmlGuard<QObject>(g->qml->scopeObject); + dfc.m_guarded = true; + } + } + storeAnyArguments(dfc, callData, 1, m_engine); + + if (!m_callbackOutstanding) { + m_tickedMethod.invoke(this, Qt::QueuedConnection); + m_callbackOutstanding = true; + } + return QV4::Encode::undefined(); +} + +void QQmlDelayedCallQueue::storeAnyArguments(DelayedFunctionCall &dfc, const QV4::CallData *callData, int offset, QV4::ExecutionEngine *engine) +{ + const int length = callData->argc - offset; + if (length == 0) { + dfc.m_args.clear(); + return; + } + QV4::Scope scope(engine); + QV4::ScopedArrayObject array(scope, engine->newArrayObject(length)); + int i = 0; + for (int j = offset; j < callData->argc; ++i, ++j) { + array->putIndexed(i, callData->args[j]); + } + dfc.m_args.set(engine, array); +} + +void QQmlDelayedCallQueue::executeAllExpired_Later() +{ + // Make a local copy of the list and clear m_delayedFunctionCalls + // This ensures correct behavior in the case of recursive calls to Qt.callLater() + QVector<DelayedFunctionCall> delayedCalls = m_delayedFunctionCalls; + m_delayedFunctionCalls.clear(); + + QVector<DelayedFunctionCall>::Iterator iter = delayedCalls.begin(); + while (iter != delayedCalls.end()) { + DelayedFunctionCall& dfc = *iter; + dfc.execute(m_engine); + ++iter; + } +} + +void QQmlDelayedCallQueue::ticked() +{ + m_callbackOutstanding = false; + executeAllExpired_Later(); +} + +QT_END_NAMESPACE diff --git a/src/3rdparty/masm/stubs/compat/stdint.h b/src/qml/qml/qqmldelayedcallqueue_p.h index 394a3d824f..ef899170a2 100644 --- a/src/3rdparty/masm/stubs/compat/stdint.h +++ b/src/qml/qml/qqmldelayedcallqueue_p.h @@ -36,18 +36,69 @@ ** $QT_END_LICENSE$ ** ****************************************************************************/ -#ifndef QSTDINT_WRAPPER_H -#define QSTDINT_WRAPPER_H -/* Needed for VS 2008 and earlier that don't ship stdint.h */ +#ifndef QQMLDELAYEDCALLQUEUE_P_H +#define QQMLDELAYEDCALLQUEUE_P_H -typedef signed char int8_t; -typedef signed short int16_t; -typedef signed int int32_t; -typedef signed long long int64_t; -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// -#endif +#include <QtCore/qglobal.h> +#include <QtCore/qobject.h> +#include <QtCore/qmetaobject.h> +#include <QtCore/qmetatype.h> +#include <private/qqmlguard_p.h> +#include <private/qv4context_p.h> + +QT_BEGIN_NAMESPACE + +class QV8Engine; +class QQmlDelayedCallQueue : public QObject +{ + Q_OBJECT +public: + QQmlDelayedCallQueue(); + ~QQmlDelayedCallQueue(); + + void init(QV4::ExecutionEngine *); + + QV4::ReturnedValue addUniquelyAndExecuteLater(QV4::CallContext *ctx); + +public Q_SLOTS: + void ticked(); + +private: + struct DelayedFunctionCall + { + DelayedFunctionCall() {} + DelayedFunctionCall(QV4::PersistentValue function) + : m_function(function), m_guarded(false) { } + + void execute(QV4::ExecutionEngine *engine) const; + + QV4::PersistentValue m_function; + QV4::PersistentValue m_args; + QQmlGuard<QObject> m_objectGuard; + bool m_guarded; + }; + + void storeAnyArguments(DelayedFunctionCall& dfc, const QV4::CallData *callData, int offset, QV4::ExecutionEngine *engine); + void executeAllExpired_Later(); + + QV4::ExecutionEngine *m_engine; + QVector<DelayedFunctionCall> m_delayedFunctionCalls; + QMetaMethod m_tickedMethod; + bool m_callbackOutstanding; +}; + +QT_END_NAMESPACE + +#endif // QQMLDELAYEDCALLQUEUE_P_H diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 55053c8733..99ae367773 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -53,7 +53,6 @@ #include "qqmlscriptstring.h" #include "qqmlglobal_p.h" #include "qqmlcomponent_p.h" -#include "qqmlnetworkaccessmanagerfactory.h" #include "qqmldirparser_p.h" #include "qqmlextensioninterface.h" #include "qqmllist_p.h" @@ -63,25 +62,25 @@ #include "qqmlincubator.h" #include "qqmlabstracturlinterceptor.h" #include <private/qqmlboundsignal_p.h> - #include <QtCore/qstandardpaths.h> #include <QtCore/qsettings.h> - #include <QtCore/qmetaobject.h> -#include <QNetworkAccessManager> #include <QDebug> #include <QtCore/qcoreapplication.h> #include <QtCore/qdir.h> #include <QtCore/qmutex.h> #include <QtCore/qthread.h> #include <private/qthread_p.h> + +#ifndef QT_NO_NETWORK +#include "qqmlnetworkaccessmanagerfactory.h" +#include <QNetworkAccessManager> #include <QtNetwork/qnetworkconfigmanager.h> +#endif #include <private/qobject_p.h> #include <private/qmetaobject_p.h> - #include <private/qqmllocale_p.h> - #include <private/qqmlbind_p.h> #include <private/qqmlconnections_p.h> #include <private/qqmltimer_p.h> @@ -94,17 +93,15 @@ #include <private/qqmlinstantiator_p.h> #ifdef Q_OS_WIN // for %APPDATA% -#include <qt_windows.h> -# if !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +# include <qt_windows.h> +# ifndef Q_OS_WINRT # include <shlobj.h> # endif -#include <qlibrary.h> -#include <windows.h> - -#ifndef CSIDL_APPDATA -# define CSIDL_APPDATA 0x001a // <username>\Application Data -#endif -#endif +# include <qlibrary.h> +# ifndef CSIDL_APPDATA +# define CSIDL_APPDATA 0x001a // <username>\Application Data +# endif +#endif // Q_OS_WIN Q_DECLARE_METATYPE(QQmlProperty) @@ -182,6 +179,7 @@ void QQmlEnginePrivate::registerBaseTypes(const char *uri, int versionMajor, int qmlRegisterType<QQmlComponent>(uri,versionMajor,versionMinor,"Component"); qmlRegisterType<QObject>(uri,versionMajor,versionMinor,"QtObject"); qmlRegisterType<QQmlBind>(uri, versionMajor, versionMinor,"Binding"); + qmlRegisterType<QQmlBind,8>(uri, versionMajor, (versionMinor < 8 ? 8 : versionMinor), "Binding"); //Only available in >=2.8 qmlRegisterType<QQmlConnections,1>(uri, versionMajor, (versionMinor < 3 ? 3 : versionMinor), "Connections"); //Only available in >=2.3 qmlRegisterType<QQmlConnections>(uri, versionMajor, versionMinor,"Connections"); qmlRegisterType<QQmlTimer>(uri, versionMajor, versionMinor,"Timer"); @@ -493,6 +491,10 @@ The following functions are also on the Qt object. from right to left. \endlist \row + \li \c application.font + \li This read-only property holds the default application font as + returned by \l QGuiApplication::font(). + \row \li \c application.arguments \li This is a string list of the arguments the executable was invoked with. \row @@ -531,6 +533,7 @@ The following functions are also on the Qt object. \li application.active \li application.state \li application.layoutDirection + \li application.font \endlist */ @@ -605,8 +608,10 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQmlEngine *e) cleanup(0), erroredBindings(0), inProgressCreations(0), workerScriptEngine(0), activeObjectCreator(0), - networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0), - scarceResourcesRefCount(0), importDatabase(e), typeLoader(e), +#ifndef QT_NO_NETWORK + networkAccessManager(0), networkAccessManagerFactory(0), +#endif + urlInterceptor(0), scarceResourcesRefCount(0), importDatabase(e), typeLoader(e), uniqueId(1), incubatorCount(0), incubationController(0) { } @@ -1066,7 +1071,17 @@ QQmlAbstractUrlInterceptor *QQmlEngine::urlInterceptor() const return d->urlInterceptor; } +void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) +{ + if (activeObjectCreator) { + activeObjectCreator->finalizeCallbacks()->append(qMakePair(QPointer<QObject>(obj), index)); + } else { + void *args[] = { 0 }; + QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args); + } +} +#ifndef QT_NO_NETWORK /*! Sets the \a factory to use for creating QNetworkAccessManager(s). @@ -1095,16 +1110,6 @@ QQmlNetworkAccessManagerFactory *QQmlEngine::networkAccessManagerFactory() const return d->networkAccessManagerFactory; } -void QQmlEnginePrivate::registerFinalizeCallback(QObject *obj, int index) -{ - if (activeObjectCreator) { - activeObjectCreator->finalizeCallbacks()->append(qMakePair(QPointer<QObject>(obj), index)); - } else { - void *args[] = { 0 }; - QMetaObject::metacall(obj, QMetaObject::InvokeMetaMethod, index, args); - } -} - QNetworkAccessManager *QQmlEnginePrivate::createNetworkAccessManager(QObject *parent) const { QMutexLocker locker(&networkAccessManagerMutex); @@ -1143,6 +1148,7 @@ QNetworkAccessManager *QQmlEngine::networkAccessManager() const Q_D(const QQmlEngine); return d->getNetworkAccessManager(); } +#endif // QT_NO_NETWORK /*! @@ -1894,28 +1900,16 @@ void QQmlEnginePrivate::warning(QQmlEnginePrivate *engine, const QList<QQmlError dumpwarning(error); } -/* - This function should be called after evaluation of the js expression is - complete, and so the scarce resources may be freed safely. - */ -void QQmlEnginePrivate::dereferenceScarceResources() -{ - Q_ASSERT(scarceResourcesRefCount > 0); - scarceResourcesRefCount -= 1; - - // if the refcount is zero, then evaluation of the "top level" - // expression must have completed. We can safely release the - // scarce resources. - if (Q_UNLIKELY(scarceResourcesRefCount == 0)) { - // iterate through the list and release them all. - // note that the actual SRD is owned by the JS engine, - // so we cannot delete the SRD; but we can free the - // memory used by the variant in the SRD. - QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); - while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) { - sr->data = QVariant(); - engine->scarceResources.remove(sr); - } +void QQmlEnginePrivate::cleanupScarceResources() +{ + // iterate through the list and release them all. + // note that the actual SRD is owned by the JS engine, + // so we cannot delete the SRD; but we can free the + // memory used by the variant in the SRD. + QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); + while (QV4::ExecutionEngine::ScarceResourceData *sr = engine->scarceResources.first()) { + sr->data = QVariant(); + engine->scarceResources.remove(sr); } } @@ -2332,7 +2326,7 @@ bool QQmlEnginePrivate::isScriptLoaded(const QUrl &url) const return typeLoader.isScriptLoaded(url); } -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) // Normalize a file name using Shell API. As opposed to converting it // to a short 8.3 name and back, this also works for drives where 8.3 notation // is disabled (see 8dot3name options of fsutil.exe). @@ -2364,7 +2358,7 @@ static inline QString shellNormalizeFileName(const QString &name) canonicalName[0] = canonicalName.at(0).toUpper(); return QDir::cleanPath(canonicalName); } -#endif // Q_OS_WIN && !Q_OS_WINCE && !Q_OS_WINRT +#endif // Q_OS_WIN && !Q_OS_WINRT bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */) { @@ -2372,7 +2366,7 @@ bool QQml_isFileCaseCorrect(const QString &fileName, int lengthIn /* = -1 */) QFileInfo info(fileName); const QString absolute = info.absoluteFilePath(); -#if defined(Q_OS_MAC) || defined(Q_OS_WINCE) || defined(Q_OS_WINRT) +#if defined(Q_OS_DARWIN) || defined(Q_OS_WINRT) const QString canonical = info.canonicalFilePath(); #elif defined(Q_OS_WIN) // No difference if the path is qrc based diff --git a/src/qml/qml/qqmlengine.h b/src/qml/qml/qqmlengine.h index bd2a3cfc48..132af78f80 100644 --- a/src/qml/qml/qqmlengine.h +++ b/src/qml/qml/qqmlengine.h @@ -87,8 +87,10 @@ class QQmlExpression; class QQmlContext; class QQmlType; class QUrl; +#ifndef QT_NO_NETWORK class QNetworkAccessManager; class QQmlNetworkAccessManagerFactory; +#endif class QQmlIncubationController; class Q_QML_EXPORT QQmlEngine : public QJSEngine { @@ -115,10 +117,12 @@ public: bool importPlugin(const QString &filePath, const QString &uri, QList<QQmlError> *errors); +#ifndef QT_NO_NETWORK void setNetworkAccessManagerFactory(QQmlNetworkAccessManagerFactory *); QQmlNetworkAccessManagerFactory *networkAccessManagerFactory() const; QNetworkAccessManager *networkAccessManager() const; +#endif void setUrlInterceptor(QQmlAbstractUrlInterceptor* urlInterceptor); QQmlAbstractUrlInterceptor* urlInterceptor() const; diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index df73118b36..440840d3c9 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -158,12 +158,12 @@ public: void registerFinalizeCallback(QObject *obj, int index); QQmlObjectCreator *activeObjectCreator; - +#ifndef QT_NO_NETWORK QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const; QNetworkAccessManager *getNetworkAccessManager() const; mutable QNetworkAccessManager *networkAccessManager; mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory; - +#endif QHash<QString,QSharedPointer<QQmlImageProviderBase> > imageProviders; QQmlAbstractUrlInterceptor* urlInterceptor; @@ -267,6 +267,8 @@ private: struct Deletable { Deletable():next(0) {} virtual ~Deletable() {} Deletable *next; }; QFieldList<Deletable, &Deletable::next> toDeleteInEngineThread; void doDeleteInEngineThread(); + + void cleanupScarceResources(); }; /* @@ -279,6 +281,26 @@ inline void QQmlEnginePrivate::referenceScarceResources() scarceResourcesRefCount += 1; } +/* + This function should be called after evaluation of the js expression is + complete, and so the scarce resources may be freed safely. + */ +inline void QQmlEnginePrivate::dereferenceScarceResources() +{ + Q_ASSERT(scarceResourcesRefCount > 0); + scarceResourcesRefCount -= 1; + + // if the refcount is zero, then evaluation of the "top level" + // expression must have completed. We can safely release the + // scarce resources. + if (scarceResourcesRefCount == 0) { + QV4::ExecutionEngine *engine = QV8Engine::getV4(v8engine()); + if (Q_UNLIKELY(!engine->scarceResources.isEmpty())) { + cleanupScarceResources(); + } + } +} + /*! Returns true if the calling thread is the QQmlEngine thread. */ diff --git a/src/qml/qml/qqmlexpression_p.h b/src/qml/qml/qqmlexpression_p.h index 3d1df55a2d..ccc629a3a3 100644 --- a/src/qml/qml/qqmlexpression_p.h +++ b/src/qml/qml/qqmlexpression_p.h @@ -57,7 +57,6 @@ #include <private/qfieldlist_p.h> #include <private/qflagpointer_p.h> #include <private/qdeletewatcher_p.h> -#include <private/qpointervaluepair_p.h> #include <private/qqmljavascriptexpression_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlfile.cpp b/src/qml/qml/qqmlfile.cpp index ea4e9a1013..8ce0cc2026 100644 --- a/src/qml/qml/qqmlfile.cpp +++ b/src/qml/qml/qqmlfile.cpp @@ -67,6 +67,8 @@ static char assets_string[] = "assets"; #endif class QQmlFilePrivate; + +#ifndef QT_NO_NETWORK class QQmlFileNetworkReply : public QObject { Q_OBJECT @@ -97,6 +99,7 @@ private: int m_redirectCount; QNetworkReply *m_reply; }; +#endif class QQmlFilePrivate { @@ -114,10 +117,12 @@ public: Error error; QString errorString; - +#ifndef QT_NO_NETWORK QQmlFileNetworkReply *reply; +#endif }; +#ifndef QT_NO_NETWORK int QQmlFileNetworkReply::finishedIndex = -1; int QQmlFileNetworkReply::downloadProgressIndex = -1; int QQmlFileNetworkReply::networkFinishedIndex = -1; @@ -200,9 +205,13 @@ void QQmlFileNetworkReply::networkDownloadProgress(qint64 a, qint64 b) { emit downloadProgress(a, b); } +#endif // QT_NO_NETWORK QQmlFilePrivate::QQmlFilePrivate() -: error(None), reply(0) +: error(None) +#ifndef QT_NO_NETWORK +, reply(0) +#endif { } @@ -225,7 +234,9 @@ QQmlFile::QQmlFile(QQmlEngine *e, const QString &url) QQmlFile::~QQmlFile() { +#ifndef QT_NO_NETWORK delete d->reply; +#endif delete d; d = 0; } @@ -263,8 +274,10 @@ QQmlFile::Status QQmlFile::status() const { if (d->url.isEmpty() && d->urlString.isEmpty()) return Null; +#ifndef QT_NO_NETWORK else if (d->reply) return Loading; +#endif else if (d->error != QQmlFilePrivate::None) return Error; else @@ -321,7 +334,11 @@ void QQmlFile::load(QQmlEngine *engine, const QUrl &url) d->error = QQmlFilePrivate::NotFound; } } else { +#ifndef QT_NO_NETWORK d->reply = new QQmlFileNetworkReply(engine, d, url); +#else + d->error = QQmlFilePrivate::NotFound; +#endif } } @@ -348,10 +365,14 @@ void QQmlFile::load(QQmlEngine *engine, const QString &url) d->error = QQmlFilePrivate::NotFound; } } else { +#ifndef QT_NO_NETWORK QUrl qurl(url); d->url = qurl; d->urlString = QString(); d->reply = new QQmlFileNetworkReply(engine, d, qurl); +#else + d->error = QQmlFilePrivate::NotFound; +#endif } } @@ -368,6 +389,7 @@ void QQmlFile::clear(QObject *) clear(); } +#ifndef QT_NO_NETWORK bool QQmlFile::connectFinished(QObject *object, const char *method) { if (!d || !d->reply) { @@ -411,6 +433,7 @@ bool QQmlFile::connectDownloadProgress(QObject *object, int method) return QMetaObject::connect(d->reply, QQmlFileNetworkReply::downloadProgressIndex, object, method); } +#endif /*! Returns true if QQmlFile will open \a url synchronously. diff --git a/src/qml/qml/qqmlfile.h b/src/qml/qml/qqmlfile.h index b0910cc0f4..3dd683a2cd 100644 --- a/src/qml/qml/qqmlfile.h +++ b/src/qml/qml/qqmlfile.h @@ -80,10 +80,12 @@ public: void clear(); void clear(QObject *); +#ifndef QT_NO_NETWORK bool connectFinished(QObject *, const char *); bool connectFinished(QObject *, int); bool connectDownloadProgress(QObject *, const char *); bool connectDownloadProgress(QObject *, int); +#endif static bool isSynchronous(const QString &url); static bool isSynchronous(const QUrl &url); diff --git a/src/qml/qml/qqmljavascriptexpression_p.h b/src/qml/qml/qqmljavascriptexpression_p.h index 64cb1bb242..94479f6c5e 100644 --- a/src/qml/qml/qqmljavascriptexpression_p.h +++ b/src/qml/qml/qqmljavascriptexpression_p.h @@ -54,7 +54,6 @@ #include <QtCore/qglobal.h> #include <QtQml/qqmlerror.h> #include <private/qqmlengine_p.h> -#include <private/qpointervaluepair_p.h> QT_BEGIN_NAMESPACE diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp index f9fea0279e..c94db8e168 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.cpp @@ -41,6 +41,8 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_NETWORK + /*! \class QQmlNetworkAccessManagerFactory \since 5.0 @@ -101,4 +103,6 @@ QQmlNetworkAccessManagerFactory::~QQmlNetworkAccessManagerFactory() implementation of this method is reentrant. */ +#endif //QT_NO_NETWORK + QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h index 8e3b94fad3..ba3561b9f4 100644 --- a/src/qml/qml/qqmlnetworkaccessmanagerfactory.h +++ b/src/qml/qml/qqmlnetworkaccessmanagerfactory.h @@ -45,6 +45,7 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_NETWORK class QNetworkAccessManager; class Q_QML_EXPORT QQmlNetworkAccessManagerFactory @@ -55,6 +56,8 @@ public: }; +#endif //QT_NO_NETWORK + QT_END_NAMESPACE #endif // QQMLNETWORKACCESSMANAGERFACTORY_H diff --git a/src/qml/qml/qqmlplatform.cpp b/src/qml/qml/qqmlplatform.cpp index 37d8d4748a..a47a0ab4a4 100644 --- a/src/qml/qml/qqmlplatform.cpp +++ b/src/qml/qml/qqmlplatform.cpp @@ -67,8 +67,6 @@ QString QQmlPlatform::os() return QStringLiteral("tvos"); #elif defined(Q_OS_MAC) return QStringLiteral("osx"); -#elif defined(Q_OS_WINCE) - return QStringLiteral("wince"); #elif defined(Q_OS_WINPHONE) return QStringLiteral("winphone"); #elif defined(Q_OS_WINRT) diff --git a/src/qml/qml/qqmlpropertycache_p.h b/src/qml/qml/qqmlpropertycache_p.h index 96dbc72f32..b2171dd86b 100644 --- a/src/qml/qml/qqmlpropertycache_p.h +++ b/src/qml/qml/qqmlpropertycache_p.h @@ -162,6 +162,8 @@ public: overrideIndex >= 0; } bool hasRevision() const { return !(flags & HasAccessors) && revision != 0; } + bool isFullyResolved() const { return !(flags & NotFullyResolved); } + // Returns -1 if not a value type virtual property inline int getValueTypeCoreIndex() const; diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index 52a7562b58..15e8d62efc 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -112,6 +112,7 @@ namespace { }; } +#ifndef QT_NO_NETWORK // This is a lame object that we need to ensure that slots connected to // QNetworkReply get called in the correct thread (the loader thread). // As QQmlTypeLoader lives in the main thread, and we can't use @@ -131,6 +132,7 @@ public slots: private: QQmlTypeLoader *l; }; +#endif // QT_NO_NETWORK class QQmlTypeLoaderThread : public QQmlThread { @@ -138,9 +140,10 @@ class QQmlTypeLoaderThread : public QQmlThread public: QQmlTypeLoaderThread(QQmlTypeLoader *loader); +#ifndef QT_NO_NETWORK QNetworkAccessManager *networkAccessManager() const; QQmlTypeLoaderNetworkReplyProxy *networkReplyProxy() const; - +#endif // QT_NO_NETWORK void load(QQmlDataBlob *b); void loadAsync(QQmlDataBlob *b); void loadWithStaticData(QQmlDataBlob *b, const QByteArray &); @@ -163,11 +166,13 @@ private: void initializeEngineMain(QQmlExtensionInterface *iface, const char *uri); QQmlTypeLoader *m_loader; +#ifndef QT_NO_NETWORK mutable QNetworkAccessManager *m_networkAccessManager; mutable QQmlTypeLoaderNetworkReplyProxy *m_networkReplyProxy; +#endif // QT_NO_NETWORK }; - +#ifndef QT_NO_NETWORK QQmlTypeLoaderNetworkReplyProxy::QQmlTypeLoaderNetworkReplyProxy(QQmlTypeLoader *l) : l(l) { @@ -196,7 +201,7 @@ void QQmlTypeLoaderNetworkReplyProxy::manualFinished(QNetworkReply *reply) l->networkReplyProgress(reply, replySize, replySize); l->networkReplyFinished(reply); } - +#endif // QT_NO_NETWORK /*! \class QQmlDataBlob @@ -480,6 +485,7 @@ void QQmlDataBlob::done() { } +#ifndef QT_NO_NETWORK /*! Invoked if there is a network error while fetching this blob. @@ -532,6 +538,7 @@ void QQmlDataBlob::networkError(QNetworkReply::NetworkError networkError) setError(error); } +#endif // QT_NO_NETWORK /*! Called if \a blob, which was previously waited for, has an error. @@ -730,12 +737,16 @@ void QQmlDataBlob::ThreadData::setProgress(quint8 v) } QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader) -: m_loader(loader), m_networkAccessManager(0), m_networkReplyProxy(0) +: m_loader(loader) +#ifndef QT_NO_NETWORK +, m_networkAccessManager(0), m_networkReplyProxy(0) +#endif // QT_NO_NETWORK { // Do that after initializing all the members. startup(); } +#ifndef QT_NO_NETWORK QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const { Q_ASSERT(isThisThread()); @@ -753,6 +764,7 @@ QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first return m_networkReplyProxy; } +#endif // QT_NO_NETWORK void QQmlTypeLoaderThread::load(QQmlDataBlob *b) { @@ -810,10 +822,12 @@ void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface, void QQmlTypeLoaderThread::shutdownThread() { +#ifndef QT_NO_NETWORK delete m_networkAccessManager; m_networkAccessManager = 0; delete m_networkReplyProxy; m_networkReplyProxy = 0; +#endif // QT_NO_NETWORK } void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b) @@ -899,12 +913,14 @@ void QQmlTypeLoader::invalidate() m_thread = 0; } +#ifndef QT_NO_NETWORK // Need to delete the network replies after // the loader thread is shutdown as it could be // getting new replies while we clear them for (NetworkReplies::Iterator iter = m_networkReplies.begin(); iter != m_networkReplies.end(); ++iter) (*iter)->release(); m_networkReplies.clear(); +#endif // QT_NO_NETWORK } void QQmlTypeLoader::lock() @@ -1082,7 +1098,7 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) setData(blob, &file); } else { - +#ifndef QT_NO_NETWORK QNetworkReply *reply = m_thread->networkAccessManager()->get(QNetworkRequest(blob->m_url)); QQmlTypeLoaderNetworkReplyProxy *nrp = m_thread->networkReplyProxy(); blob->addref(); @@ -1099,13 +1115,14 @@ void QQmlTypeLoader::loadThread(QQmlDataBlob *blob) #ifdef DATABLOB_DEBUG qWarning("QQmlDataBlob: requested %s", qPrintable(blob->url().toString())); -#endif - +#endif // DATABLOB_DEBUG +#endif // QT_NO_NETWORK } } #define DATALOADER_MAXIMUM_REDIRECT_RECURSION 16 +#ifndef QT_NO_NETWORK void QQmlTypeLoader::networkReplyFinished(QNetworkReply *reply) { Q_ASSERT(m_thread->isThisThread()); @@ -1161,6 +1178,7 @@ void QQmlTypeLoader::networkReplyProgress(QNetworkReply *reply, m_thread->callDownloadProgressChanged(blob, blob->m_data.progress()); } } +#endif // QT_NO_NETWORK /*! Return the QQmlEngine associated with this loader diff --git a/src/qml/qml/qqmltypeloader_p.h b/src/qml/qml/qqmltypeloader_p.h index 01d223bbce..49a4ac716a 100644 --- a/src/qml/qml/qqmltypeloader_p.h +++ b/src/qml/qml/qqmltypeloader_p.h @@ -53,7 +53,9 @@ #include <QtCore/qobject.h> #include <QtCore/qatomic.h> +#ifndef QT_NO_NETWORK #include <QtNetwork/qnetworkreply.h> +#endif #include <QtQml/qqmlerror.h> #include <QtQml/qqmlengine.h> #include <QtQml/qqmlfile.h> @@ -156,7 +158,9 @@ protected: virtual void dataReceived(const Data &) = 0; virtual void initializeFromCachedUnit(const QQmlPrivate::CachedQmlUnit*) = 0; virtual void done(); +#ifndef QT_NO_NETWORK virtual void networkError(QNetworkReply::NetworkError); +#endif virtual void dependencyError(QQmlDataBlob *); virtual void dependencyComplete(QQmlDataBlob *); virtual void allDependenciesDone(); @@ -320,17 +324,21 @@ public: private: friend class QQmlDataBlob; friend class QQmlTypeLoaderThread; +#ifndef QT_NO_NETWORK friend class QQmlTypeLoaderNetworkReplyProxy; +#endif // QT_NO_NETWORK void shutdownThread(); void loadThread(QQmlDataBlob *); void loadWithStaticDataThread(QQmlDataBlob *, const QByteArray &); void loadWithCachedUnitThread(QQmlDataBlob *blob, const QQmlPrivate::CachedQmlUnit *unit); +#ifndef QT_NO_NETWORK void networkReplyFinished(QNetworkReply *); void networkReplyProgress(QNetworkReply *, qint64, qint64); typedef QHash<QNetworkReply *, QQmlDataBlob *> NetworkReplies; +#endif void setData(QQmlDataBlob *, const QByteArray &); void setData(QQmlDataBlob *, QQmlFile *); @@ -362,7 +370,9 @@ private: QQmlEngine *m_engine; QQmlTypeLoaderThread *m_thread; +#ifndef QT_NO_NETWORK NetworkReplies m_networkReplies; +#endif TypeCache m_typeCache; ScriptCache m_scriptCache; QmldirCache m_qmldirCache; diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index c81f665ad3..ef00a582ef 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -58,6 +58,32 @@ QT_BEGIN_NAMESPACE +static void list_append(QQmlListProperty<QObject> *prop, QObject *o) +{ + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); + list->append(o); + static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0); +} + +static int list_count(QQmlListProperty<QObject> *prop) +{ + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); + return list->count(); +} + +static QObject *list_at(QQmlListProperty<QObject> *prop, int index) +{ + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); + return list->at(index); +} + +static void list_clear(QQmlListProperty<QObject> *prop) +{ + QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); + list->clear(); + static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0); +} + QQmlVMEVariantQObjectPtr::QQmlVMEVariantQObjectPtr() : QQmlGuard<QObject>(0), m_target(0), m_index(-1) { @@ -1013,37 +1039,6 @@ void QQmlVMEMetaObject::writeProperty(int id, const QVariant &value) } } -void QQmlVMEMetaObject::listChanged(int id) -{ - activate(object, methodOffset() + id, 0); -} - -void QQmlVMEMetaObject::list_append(QQmlListProperty<QObject> *prop, QObject *o) -{ - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - list->append(o); - static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0); -} - -int QQmlVMEMetaObject::list_count(QQmlListProperty<QObject> *prop) -{ - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - return list->count(); -} - -QObject *QQmlVMEMetaObject::list_at(QQmlListProperty<QObject> *prop, int index) -{ - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - return list->at(index); -} - -void QQmlVMEMetaObject::list_clear(QQmlListProperty<QObject> *prop) -{ - QList<QObject *> *list = static_cast<QList<QObject *> *>(prop->data); - list->clear(); - static_cast<QQmlVMEMetaObject *>(prop->dummy1)->activate(prop->object, reinterpret_cast<quintptr>(prop->dummy2), 0); -} - quint16 QQmlVMEMetaObject::vmeMethodLineNumber(int index) { if (index < methodOffset()) { @@ -1133,8 +1128,7 @@ void QQmlVMEMetaObject::allocateProperties() QV4::ExecutionEngine *v4 = cache->engine; QV4::Heap::MemberData *data = QV4::MemberData::allocate(v4, metaData->propertyCount); properties.set(v4, data); - for (uint i = 0; i < data->size; ++i) - data->data[i] = QV4::Encode::undefined(); + std::fill(data->data, data->data + data->size, QV4::Encode::undefined()); } bool QQmlVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const diff --git a/src/qml/qml/qqmlvmemetaobject_p.h b/src/qml/qml/qqmlvmemetaobject_p.h index 98fdae60ee..fcdac3cc53 100644 --- a/src/qml/qml/qqmlvmemetaobject_p.h +++ b/src/qml/qml/qqmlvmemetaobject_p.h @@ -165,13 +165,13 @@ public: static QQmlInterceptorMetaObject *get(QObject *obj); - virtual QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o); + QAbstractDynamicMetaObject *toDynamicMetaObject(QObject *o) Q_DECL_OVERRIDE; // Used by auto-tests for inspection QQmlPropertyCache *propertyCache() const { return cache; } protected: - virtual int metaCall(QObject *o, QMetaObject::Call c, int id, void **a); + int metaCall(QObject *o, QMetaObject::Call c, int id, void **a) Q_DECL_OVERRIDE; bool intercept(QMetaObject::Call c, int id, void **a); public: @@ -195,8 +195,6 @@ inline QQmlInterceptorMetaObject *QQmlInterceptorMetaObject::get(QObject *obj) return 0; } -class QQmlVMEVariant; -class QQmlRefCount; class QQmlVMEMetaObjectEndpoint; class Q_QML_PRIVATE_EXPORT QQmlVMEMetaObject : public QQmlInterceptorMetaObject { @@ -219,13 +217,9 @@ public: static QQmlVMEMetaObject *getForSignal(QObject *o, int coreIndex); protected: - virtual int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a); + int metaCall(QObject *o, QMetaObject::Call _c, int _id, void **_a) Q_DECL_OVERRIDE; public: - friend class QQmlVMEMetaObjectEndpoint; - friend class QQmlVMEVariantQObjectPtr; - friend class QQmlPropertyCache; - QQmlGuardedContextData ctxt; const QQmlVMEMetaData *metaData; @@ -281,13 +275,6 @@ public: inline QQmlVMEMetaObject *parentVMEMetaObject() const; - void listChanged(int); - - static void list_append(QQmlListProperty<QObject> *, QObject *); - static int list_count(QQmlListProperty<QObject> *); - static QObject *list_at(QQmlListProperty<QObject> *, int); - static void list_clear(QQmlListProperty<QObject> *); - void activate(QObject *, int, void **); QList<QQmlVMEVariantQObjectPtr *> varObjectGuards; diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index fe02c6633e..e9644839d1 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -70,7 +70,7 @@ using namespace QV4; -#ifndef QT_NO_XMLSTREAMREADER +#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK) #define V4THROW_REFERENCE(string) { \ ScopedObject error(scope, ctx->engine()->newReferenceErrorObject(QStringLiteral(string))); \ @@ -117,10 +117,8 @@ class NodeImpl public: NodeImpl() : type(Element), document(0), parent(0) {} virtual ~NodeImpl() { - for (int ii = 0; ii < children.count(); ++ii) - delete children.at(ii); - for (int ii = 0; ii < attributes.count(); ++ii) - delete attributes.at(ii); + qDeleteAll(children); + qDeleteAll(attributes); } // These numbers are copied from the Node IDL definition @@ -160,7 +158,7 @@ class DocumentImpl : public QQmlRefCount, public NodeImpl public: DocumentImpl() : root(0) { type = Document; } virtual ~DocumentImpl() { - if (root) delete root; + delete root; } QString version; @@ -2040,6 +2038,6 @@ void *qt_add_qmlxmlhttprequest(ExecutionEngine *v4) QT_END_NAMESPACE -#endif // QT_NO_XMLSTREAMREADER +#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK #include <qqmlxmlhttprequest.moc> diff --git a/src/qml/qml/qqmlxmlhttprequest_p.h b/src/qml/qml/qqmlxmlhttprequest_p.h index 7bbfb5243c..df30873915 100644 --- a/src/qml/qml/qqmlxmlhttprequest_p.h +++ b/src/qml/qml/qqmlxmlhttprequest_p.h @@ -55,7 +55,7 @@ #include <QtCore/qglobal.h> #include <private/qqmlglobal_p.h> -#ifndef QT_NO_XMLSTREAMREADER +#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK) QT_BEGIN_NAMESPACE @@ -64,7 +64,7 @@ void qt_rem_qmlxmlhttprequest(QV4::ExecutionEngine *engine, void *); QT_END_NAMESPACE -#endif // QT_NO_XMLSTREAMREADER +#endif // QT_NO_XMLSTREAMREADER && QT_NO_NETWORK #endif // QQMLXMLHTTPREQUEST_P_H diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp index 333b1903f5..ac40b627d9 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions.cpp +++ b/src/qml/qml/v8/qqmlbuiltinfunctions.cpp @@ -45,6 +45,7 @@ #include <private/qqmlstringconverters_p.h> #include <private/qqmllocale_p.h> #include <private/qv8engine_p.h> +#include <private/qqmldelayedcallqueue_p.h> #include <QFileInfo> #include <private/qqmldebugconnector_p.h> @@ -149,6 +150,8 @@ Heap::QtObject::QtObject(QQmlEngine *qmlEngine) o->defineAccessorProperty(QStringLiteral("inputMethod"), QV4::QtObject::method_get_inputMethod, 0); #endif o->defineAccessorProperty(QStringLiteral("styleHints"), QV4::QtObject::method_get_styleHints, 0); + + o->defineDefaultProperty(QStringLiteral("callLater"), QV4::QtObject::method_callLater); } @@ -1934,6 +1937,30 @@ ReturnedValue GlobalExtensions::method_string_arg(CallContext *ctx) return ctx->d()->engine->newString(value.arg(arg->toQString()))->asReturnedValue(); } +/*! +\qmlmethod Qt::callLater(function) +\qmlmethod Qt::callLater(function, argument1, argument2, ...) +Use this function to eliminate redundant calls to a function or signal. + +The function passed as the first argument to \l{QML:Qt::callLater()}{Qt.callLater()} +will be called later, once the QML engine returns to the event loop. + +When this function is called multiple times in quick succession with the +same function as its first argument, that function will be called only once. + +For example: +\snippet doc/src/snippets/qml/qtLater.qml 0 + +Any additional arguments passed to \l{QML:Qt::callLater()}{Qt.callLater()} will +be passed on to the function invoked. Note that if redundant calls +are eliminated, then only the last set of arguments will be passed to the +function. +*/ +ReturnedValue QtObject::method_callLater(CallContext *ctx) +{ + QV8Engine *v8engine = ctx->engine()->v8Engine; + return v8engine->delayedCallQueue()->addUniquelyAndExecuteLater(ctx); +} QT_END_NAMESPACE diff --git a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h index 53468f062b..99c8b69724 100644 --- a/src/qml/qml/v8/qqmlbuiltinfunctions_p.h +++ b/src/qml/qml/v8/qqmlbuiltinfunctions_p.h @@ -124,6 +124,8 @@ struct QtObject : Object static ReturnedValue method_get_inputMethod(CallContext *ctx); #endif static ReturnedValue method_get_styleHints(CallContext *ctx); + + static ReturnedValue method_callLater(CallContext *ctx); }; struct ConsoleObject : Object diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index d322088f61..73128f6344 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -149,6 +149,7 @@ QV8Engine::QV8Engine(QJSEngine* qq) m_v4Engine = new QV4::ExecutionEngine; m_v4Engine->v8Engine = this; + m_delayedCallQueue.init(m_v4Engine); QV4::QObjectWrapper::initializeBindings(m_v4Engine); } @@ -159,18 +160,22 @@ QV8Engine::~QV8Engine() delete m_extensionData[ii]; m_extensionData.clear(); +#if !defined(QT_NO_XMLSTREAMREADER) && defined(QT_NO_NETWORK) qt_rem_qmlxmlhttprequest(m_v4Engine, m_xmlHttpRequestData); m_xmlHttpRequestData = 0; +#endif delete m_listModelData; m_listModelData = 0; delete m_v4Engine; } +#ifndef QT_NO_NETWORK QNetworkAccessManager *QV8Engine::networkAccessManager() { return QQmlEnginePrivate::get(m_engine)->getNetworkAccessManager(); } +#endif const QSet<QString> &QV8Engine::illegalNames() const { @@ -189,8 +194,10 @@ void QV8Engine::initializeGlobal() QQmlDateExtension::registerExtension(m_v4Engine); QQmlNumberExtension::registerExtension(m_v4Engine); +#if !defined(QT_NO_XMLSTREAMREADER) && !defined(QT_NO_NETWORK) qt_add_domexceptions(m_v4Engine); m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(m_v4Engine); +#endif qt_add_sqlexceptions(m_v4Engine); diff --git a/src/qml/qml/v8/qv8engine_p.h b/src/qml/qml/v8/qv8engine_p.h index 4ffd36ca34..c5041c54e0 100644 --- a/src/qml/qml/v8/qv8engine_p.h +++ b/src/qml/qml/v8/qv8engine_p.h @@ -70,6 +70,7 @@ #include <private/qv4object_p.h> #include <private/qv4identifier_p.h> #include <private/qqmlcontextwrapper_p.h> +#include <private/qqmldelayedcallqueue_p.h> QT_BEGIN_NAMESPACE @@ -78,12 +79,6 @@ namespace QV4 { struct ExecutionEngine; } -// Uncomment the following line to enable global handle debugging. When enabled, all the persistent -// handles allocated using qPersistentNew() (or registered with qPersistentRegsiter()) and disposed -// with qPersistentDispose() are tracked. If you try and do something illegal, like double disposing -// a handle, qFatal() is called. -// #define QML_GLOBAL_HANDLE_DEBUGGING - #define V4THROW_ERROR(string) \ return ctx->engine()->throwError(QString::fromUtf8(string)); @@ -186,6 +181,7 @@ public: QQmlEngine *engine() { return m_engine; } QJSEngine *publicEngine() { return q; } QV4::ReturnedValue global(); + QQmlDelayedCallQueue *delayedCallQueue() { return &m_delayedCallQueue; } void *xmlHttpRequestData() { return m_xmlHttpRequestData; } @@ -194,10 +190,12 @@ public: void freezeObject(const QV4::Value &value); +#ifndef QT_NO_NETWORK // Return the network access manager for this engine. By default this returns the network // access manager of the QQmlEngine. It is overridden in the case of a threaded v8 // instance (like in WorkerScript). virtual QNetworkAccessManager *networkAccessManager(); +#endif // Return the list of illegal id names (the names of the properties on the global object) const QSet<QString> &illegalNames() const; @@ -219,6 +217,7 @@ public: protected: QJSEngine* q; QQmlEngine *m_engine; + QQmlDelayedCallQueue m_delayedCallQueue; QV4::ExecutionEngine *m_v4Engine; diff --git a/src/qml/qml/v8/v8.pri b/src/qml/qml/v8/v8.pri index 3d6a012481..4592022939 100644 --- a/src/qml/qml/v8/v8.pri +++ b/src/qml/qml/v8/v8.pri @@ -9,4 +9,3 @@ SOURCES += \ $$PWD/qv4domerrors.cpp \ $$PWD/qv4sqlerrors.cpp \ $$PWD/qqmlbuiltinfunctions.cpp - diff --git a/src/qml/types/qqmlbind.cpp b/src/qml/types/qqmlbind.cpp index ed9a8533c0..3102da3f20 100644 --- a/src/qml/types/qqmlbind.cpp +++ b/src/qml/types/qqmlbind.cpp @@ -51,6 +51,7 @@ #include <QtCore/qfile.h> #include <QtCore/qdebug.h> +#include <QtCore/qtimer.h> #include <private/qobject_p.h> @@ -59,16 +60,18 @@ QT_BEGIN_NAMESPACE class QQmlBindPrivate : public QObjectPrivate { public: - QQmlBindPrivate() : componentComplete(true), obj(0) {} + QQmlBindPrivate() : obj(0), componentComplete(true), delayed(false), pendingEval(false) {} ~QQmlBindPrivate() { } QQmlNullableValue<bool> when; - bool componentComplete; QPointer<QObject> obj; QString propName; QQmlNullableValue<QVariant> value; QQmlProperty prop; QQmlAbstractBinding::Ptr prevBind; + bool componentComplete:1; + bool delayed:1; + bool pendingEval:1; void validate(QObject *binding) const; }; @@ -281,7 +284,42 @@ void QQmlBind::setValue(const QVariant &v) { Q_D(QQmlBind); d->value = v; - eval(); + prepareEval(); +} + +/*! + \qmlproperty bool QtQml::Binding::delayed + + This property holds whether the binding should be delayed. + + A delayed binding will not immediately update the target, but rather wait + until the event queue has been cleared. This can be used as an optimization, + or to prevent intermediary values from being assigned. + + \code + Binding { + target: contactName; property: 'text' + value: givenName + " " + familyName; when: list.ListView.isCurrentItem + delayed: true + } + \endcode +*/ +bool QQmlBind::delayed() const +{ + Q_D(const QQmlBind); + return d->delayed; +} + +void QQmlBind::setDelayed(bool delayed) +{ + Q_D(QQmlBind); + if (d->delayed == delayed) + return; + + d->delayed = delayed; + + if (!d->delayed) + eval(); } void QQmlBind::setTarget(const QQmlProperty &p) @@ -307,9 +345,22 @@ void QQmlBind::componentComplete() eval(); } +void QQmlBind::prepareEval() +{ + Q_D(QQmlBind); + if (d->delayed) { + if (!d->pendingEval) + QTimer::singleShot(0, this, &QQmlBind::eval); + d->pendingEval = true; + } else { + eval(); + } +} + void QQmlBind::eval() { Q_D(QQmlBind); + d->pendingEval = false; if (!d->prop.isValid() || d->value.isNull || !d->componentComplete) return; diff --git a/src/qml/types/qqmlbind_p.h b/src/qml/types/qqmlbind_p.h index 581995af56..77939a40bc 100644 --- a/src/qml/types/qqmlbind_p.h +++ b/src/qml/types/qqmlbind_p.h @@ -68,6 +68,7 @@ class Q_AUTOTEST_EXPORT QQmlBind : public QObject, public QQmlPropertyValueSourc Q_PROPERTY(QString property READ property WRITE setProperty) Q_PROPERTY(QVariant value READ value WRITE setValue) Q_PROPERTY(bool when READ when WRITE setWhen) + Q_PROPERTY(bool delayed READ delayed WRITE setDelayed REVISION 8) public: QQmlBind(QObject *parent=0); @@ -85,12 +86,16 @@ public: QVariant value() const; void setValue(const QVariant &); + bool delayed() const; + void setDelayed(bool); + protected: virtual void setTarget(const QQmlProperty &); virtual void classBegin(); virtual void componentComplete(); private: + void prepareEval(); void eval(); }; diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 91eef2d982..9cbda4516e 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -79,13 +79,16 @@ static bool isMemoryUsed(const char *mem) static QString roleTypeName(ListLayout::Role::DataType t) { - QString result; - const char *roleTypeNames[] = { "String", "Number", "Bool", "List", "QObject", "VariantMap", "DateTime" }; + static const QString roleTypeNames[] = { + QStringLiteral("String"), QStringLiteral("Number"), QStringLiteral("Bool"), + QStringLiteral("List"), QStringLiteral("QObject"), QStringLiteral("VariantMap"), + QStringLiteral("DateTime") + }; if (t > ListLayout::Role::Invalid && t < ListLayout::Role::MaxDataType) - result = QString::fromLatin1(roleTypeNames[t]); + return roleTypeNames[t]; - return result; + return QString(); } const ListLayout::Role &ListLayout::getRoleOrCreate(const QString &key, Role::DataType type) @@ -169,9 +172,7 @@ ListLayout::ListLayout(const ListLayout *other) : currentBlock(0), currentBlockO ListLayout::~ListLayout() { - for (int i=0 ; i < roles.count() ; ++i) { - delete roles[i]; - } + qDeleteAll(roles); } void ListLayout::sync(ListLayout *src, ListLayout *target) @@ -1440,8 +1441,7 @@ void DynamicRoleModelNode::updateValues(const QVariantMap &object, QVector<int> const QByteArray &keyUtf8 = key.toUtf8(); QQmlListModel *existingModel = qobject_cast<QQmlListModel *>(m_meta->value(keyUtf8).value<QObject *>()); - if (existingModel) - delete existingModel; + delete existingModel; if (m_meta->setValue(keyUtf8, value)) roles << roleIndex; @@ -1457,8 +1457,7 @@ DynamicRoleModelNodeMetaObject::~DynamicRoleModelNodeMetaObject() { for (int i=0 ; i < count() ; ++i) { QQmlListModel *subModel = qobject_cast<QQmlListModel *>(value(i).value<QObject *>()); - if (subModel) - delete subModel; + delete subModel; } } @@ -1469,8 +1468,7 @@ void DynamicRoleModelNodeMetaObject::propertyWrite(int index) QVariant v = value(index); QQmlListModel *model = qobject_cast<QQmlListModel *>(v.value<QObject *>()); - if (model) - delete model; + delete model; } void DynamicRoleModelNodeMetaObject::propertyWritten(int index) @@ -1662,8 +1660,7 @@ QQmlListModel::QQmlListModel(QQmlListModel *orig, QQmlListModelWorkerAgent *agen QQmlListModel::~QQmlListModel() { - for (int i=0 ; i < m_modelObjects.count() ; ++i) - delete m_modelObjects[i]; + qDeleteAll(m_modelObjects); if (m_primary) { m_listModel->destroy(); @@ -1982,15 +1979,7 @@ void QQmlListModel::setDynamicRoles(bool enableDynamicRoles) */ int QQmlListModel::count() const { - int count; - - if (m_dynamicRoles) - count = m_modelObjects.count(); - else { - count = m_listModel->elementCount(); - } - - return count; + return m_dynamicRoles ? m_modelObjects.count() : m_listModel->elementCount(); } /*! @@ -2002,13 +1991,12 @@ int QQmlListModel::count() const */ void QQmlListModel::clear() { - int cleared = count(); + const int cleared = count(); emitItemsAboutToBeRemoved(0, cleared); if (m_dynamicRoles) { - for (int i=0 ; i < m_modelObjects.count() ; ++i) - delete m_modelObjects[i]; + qDeleteAll(m_modelObjects); m_modelObjects.clear(); } else { m_listModel->clear(); diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h index b35a5a1224..e71b1e24b8 100644 --- a/src/qml/types/qqmllistmodel_p.h +++ b/src/qml/types/qqmllistmodel_p.h @@ -187,8 +187,8 @@ public: QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {} - virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings); - virtual void applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings); + void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE; + void applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE; private: bool verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding); diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index a59b8de525..431e6aca9f 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -198,7 +198,7 @@ public: explicit Role(const Role *other); ~Role(); - // This enum must be kept in sync with the roleTypeNames variable in qdeclarativelistmodel.cpp + // This enum must be kept in sync with the roleTypeNames variable in qqmllistmodel.cpp enum DataType { Invalid = -1, diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index e819e4ee7d..bc15b2fd9b 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -52,10 +52,12 @@ #include <QtCore/qwaitcondition.h> #include <QtCore/qfile.h> #include <QtCore/qdatetime.h> -#include <QtNetwork/qnetworkaccessmanager.h> #include <QtQml/qqmlinfo.h> #include <QtQml/qqmlfile.h> +#ifndef QT_NO_NETWORK +#include <QtNetwork/qnetworkaccessmanager.h> #include "qqmlnetworkaccessmanagerfactory.h" +#endif #include <private/qv8engine_p.h> #include <private/qv4serialize_p.h> @@ -141,7 +143,10 @@ public: ~WorkerEngine(); void init(); + +#ifndef QT_NO_NETWORK virtual QNetworkAccessManager *networkAccessManager(); +#endif QQuickWorkerScriptEnginePrivate *p; @@ -150,7 +155,9 @@ public: QV4::PersistentValue onmessage; private: QV4::PersistentValue createsend; +#ifndef QT_NO_NETWORK QNetworkAccessManager *accessManager; +#endif }; WorkerEngine *workerEngine; @@ -194,14 +201,19 @@ private: }; QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent) -: QV8Engine(0), p(parent), accessManager(0) +: QV8Engine(0), p(parent) +#ifndef QT_NO_NETWORK +, accessManager(0) +#endif { m_v4Engine->v8Engine = this; } QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() { +#ifndef QT_NO_NETWORK delete accessManager; +#endif } void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() @@ -262,6 +274,7 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(i return v->asReturnedValue(); } +#ifndef QT_NO_NETWORK QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager() { if (!accessManager) { @@ -273,6 +286,7 @@ QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAcc } return accessManager; } +#endif QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine) : workerEngine(0), qmlengine(engine), m_nextId(0) diff --git a/src/quick/items/qquickanchors.cpp b/src/quick/items/qquickanchors.cpp index 193be7c45b..d87669df56 100644 --- a/src/quick/items/qquickanchors.cpp +++ b/src/quick/items/qquickanchors.cpp @@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE //TODO: should we cache relationships, so we don't have to check each time (parent-child or sibling)? //TODO: support non-parent, non-sibling (need to find lowest common ancestor) -static inline qreal hcenter(QQuickItem *item) +static inline qreal hcenter(QQuickItem const *item) { qreal width = item->width(); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { @@ -63,7 +63,7 @@ static inline qreal hcenter(QQuickItem *item) return width / 2; } -static inline qreal vcenter(QQuickItem *item) +static inline qreal vcenter(QQuickItem const *item) { qreal height = item->height(); if (QQuickAnchors *anchors = QQuickItemPrivate::get(item)->_anchors) { @@ -77,9 +77,8 @@ static inline qreal vcenter(QQuickItem *item) return height / 2; } -//### const item? //local position -static qreal position(QQuickItem *item, QQuickAnchorLine::AnchorLine anchorLine) +static qreal position(QQuickItem const *item, QQuickAnchorLine::AnchorLine anchorLine) { qreal ret = 0.0; switch (anchorLine) { diff --git a/src/quick/items/qquickanimatedimage.cpp b/src/quick/items/qquickanimatedimage.cpp index 3ae2512c98..42033b6135 100644 --- a/src/quick/items/qquickanimatedimage.cpp +++ b/src/quick/items/qquickanimatedimage.cpp @@ -47,8 +47,10 @@ #include <QtQml/qqmlfile.h> #include <QtQml/qqmlengine.h> #include <QtGui/qmovie.h> +#ifndef QT_NO_NETWORK #include <QtNetwork/qnetworkrequest.h> #include <QtNetwork/qnetworkreply.h> +#endif QT_BEGIN_NAMESPACE @@ -144,8 +146,10 @@ QQuickAnimatedImage::QQuickAnimatedImage(QQuickItem *parent) QQuickAnimatedImage::~QQuickAnimatedImage() { Q_D(QQuickAnimatedImage); +#ifndef QT_NO_NETWORK if (d->reply) d->reply->deleteLater(); +#endif delete d->_movie; qDeleteAll(d->frameMap); d->frameMap.clear(); @@ -264,10 +268,12 @@ void QQuickAnimatedImage::setSource(const QUrl &url) if (url == d->url) return; +#ifndef QT_NO_NETWORK if (d->reply) { d->reply->deleteLater(); d->reply = 0; } +#endif d->setImage(QImage()); qDeleteAll(d->frameMap); @@ -318,6 +324,7 @@ void QQuickAnimatedImage::load() d->_movie = new QMovie(lf); movieRequestFinished(); } else { +#ifndef QT_NO_NETWORK if (d->status != Loading) { d->status = Loading; emit statusChanged(d->status); @@ -334,6 +341,7 @@ void QQuickAnimatedImage::load() this, SLOT(movieRequestFinished())); QObject::connect(d->reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(requestProgress(qint64,qint64))); +#endif } } } @@ -342,8 +350,10 @@ void QQuickAnimatedImage::load() void QQuickAnimatedImage::movieRequestFinished() { + Q_D(QQuickAnimatedImage); +#ifndef QT_NO_NETWORK if (d->reply) { d->redirectCount++; if (d->redirectCount < ANIMATEDIMAGE_MAXIMUM_REDIRECT_RECURSION) { @@ -359,6 +369,7 @@ void QQuickAnimatedImage::movieRequestFinished() d->redirectCount=0; d->_movie = new QMovie(d->reply); } +#endif if (!d->_movie->isValid()) { qmlInfo(this) << "Error Reading Animated Image File " << d->url.toString(); diff --git a/src/quick/items/qquickanimatedimage_p_p.h b/src/quick/items/qquickanimatedimage_p_p.h index 9474254252..9b284f966d 100644 --- a/src/quick/items/qquickanimatedimage_p_p.h +++ b/src/quick/items/qquickanimatedimage_p_p.h @@ -58,7 +58,9 @@ QT_BEGIN_NAMESPACE class QMovie; +#ifndef QT_NO_NETWORK class QNetworkReply; +#endif class QQuickAnimatedImagePrivate : public QQuickImagePrivate { @@ -66,7 +68,10 @@ class QQuickAnimatedImagePrivate : public QQuickImagePrivate public: QQuickAnimatedImagePrivate() - : playing(true), paused(false), preset_currentframe(0), _movie(0), reply(0), redirectCount(0), oldPlaying(false) + : playing(true), paused(false), preset_currentframe(0), _movie(0), oldPlaying(false) +#ifndef QT_NO_NETWORK + , reply(0), redirectCount(0) +#endif { } @@ -76,9 +81,11 @@ public: bool paused; int preset_currentframe; QMovie *_movie; + bool oldPlaying; +#ifndef QT_NO_NETWORK QNetworkReply *reply; int redirectCount; - bool oldPlaying; +#endif QMap<int, QQuickPixmap *> frameMap; }; diff --git a/src/quick/items/qquickborderimage.cpp b/src/quick/items/qquickborderimage.cpp index 66f414d816..5f8dd7b989 100644 --- a/src/quick/items/qquickborderimage.cpp +++ b/src/quick/items/qquickborderimage.cpp @@ -43,7 +43,9 @@ #include <QtQml/qqmlinfo.h> #include <QtQml/qqmlfile.h> #include <QtQml/qqmlengine.h> +#ifndef QT_NO_NETWORK #include <QtNetwork/qnetworkreply.h> +#endif #include <QtCore/qfile.h> #include <QtCore/qmath.h> #include <QtGui/qguiapplication.h> @@ -169,9 +171,11 @@ QQuickBorderImage::QQuickBorderImage(QQuickItem *parent) QQuickBorderImage::~QQuickBorderImage() { +#ifndef QT_NO_NETWORK Q_D(QQuickBorderImage); if (d->sciReply) d->sciReply->deleteLater(); +#endif } /*! @@ -270,10 +274,12 @@ void QQuickBorderImage::setSource(const QUrl &url) if (url == d->url) return; +#ifndef QT_NO_NETWORK if (d->sciReply) { d->sciReply->deleteLater(); d->sciReply = 0; } +#endif d->url = url; d->sciurl = QUrl(); @@ -311,6 +317,7 @@ void QQuickBorderImage::load() setGridScaledImage(QQuickGridScaledImage(&file)); return; } else { +#ifndef QT_NO_NETWORK if (d->progress != 0.0) { d->progress = 0.0; emit progressChanged(d->progress); @@ -320,6 +327,7 @@ void QQuickBorderImage::load() d->sciReply = qmlEngine(this)->networkAccessManager()->get(req); qmlobject_connect(d->sciReply, QNetworkReply, SIGNAL(finished()), this, QQuickBorderImage, SLOT(sciRequestFinished())) +#endif } } else { QQuickPixmap::Options options; @@ -529,6 +537,7 @@ void QQuickBorderImage::requestFinished() pixmapChange(); } +#ifndef QT_NO_NETWORK #define BORDERIMAGE_MAX_REDIRECT 16 void QQuickBorderImage::sciRequestFinished() @@ -558,6 +567,7 @@ void QQuickBorderImage::sciRequestFinished() setGridScaledImage(sci); } } +#endif // QT_NO_NETWORK void QQuickBorderImage::doUpdate() { diff --git a/src/quick/items/qquickborderimage_p.h b/src/quick/items/qquickborderimage_p.h index 7f8b172a21..f2764660f6 100644 --- a/src/quick/items/qquickborderimage_p.h +++ b/src/quick/items/qquickborderimage_p.h @@ -101,7 +101,9 @@ private: private Q_SLOTS: void doUpdate(); void requestFinished() Q_DECL_OVERRIDE; +#ifndef QT_NO_NETWORK void sciRequestFinished(); +#endif private: Q_DISABLE_COPY(QQuickBorderImage) diff --git a/src/quick/items/qquickborderimage_p_p.h b/src/quick/items/qquickborderimage_p_p.h index 478de88a52..1dc530e34e 100644 --- a/src/quick/items/qquickborderimage_p_p.h +++ b/src/quick/items/qquickborderimage_p_p.h @@ -58,17 +58,20 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_NETWORK class QNetworkReply; +#endif class QQuickBorderImagePrivate : public QQuickImageBasePrivate { Q_DECLARE_PUBLIC(QQuickBorderImage) public: QQuickBorderImagePrivate() - : border(0), sciReply(0), - horizontalTileMode(QQuickBorderImage::Stretch), - verticalTileMode(QQuickBorderImage::Stretch), - redirectCount(0), pixmapChanged(false) + : border(0), horizontalTileMode(QQuickBorderImage::Stretch), + verticalTileMode(QQuickBorderImage::Stretch), pixmapChanged(false) +#ifndef QT_NO_NETWORK + , sciReply(0), redirectCount(0) +#endif { } @@ -90,12 +93,14 @@ public: QQuickScaleGrid *border; QUrl sciurl; - QNetworkReply *sciReply; QQuickBorderImage::TileMode horizontalTileMode; QQuickBorderImage::TileMode verticalTileMode; - int redirectCount; - bool pixmapChanged : 1; + +#ifndef QT_NO_NETWORK + QNetworkReply *sciReply; + int redirectCount; +#endif }; QT_END_NAMESPACE diff --git a/src/quick/items/qquickitem.cpp b/src/quick/items/qquickitem.cpp index 6f8fc2e874..1100b12cbc 100644 --- a/src/quick/items/qquickitem.cpp +++ b/src/quick/items/qquickitem.cpp @@ -84,6 +84,8 @@ QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(DBG_MOUSE_TARGET) + #ifndef QT_NO_DEBUG static const bool qsg_leak_check = !qEnvironmentVariableIsEmpty("QML_LEAK_CHECK"); #endif @@ -2889,6 +2891,8 @@ void QQuickItemPrivate::addChild(QQuickItem *child) if (childPrivate->hasCursorInChild && !hasCursorInChild) setHasCursorInChild(true); #endif + if (childPrivate->hasHoverInChild && !hasHoverInChild) + setHasHoverInChild(true); markSortedChildrenDirty(child); dirty(QQuickItemPrivate::ChildrenChanged); @@ -2914,6 +2918,8 @@ void QQuickItemPrivate::removeChild(QQuickItem *child) if (childPrivate->hasCursorInChild && hasCursorInChild) setHasCursorInChild(false); #endif + if (childPrivate->hasHoverInChild && hasHoverInChild) + setHasHoverInChild(false); markSortedChildrenDirty(child); dirty(QQuickItemPrivate::ChildrenChanged); @@ -3137,6 +3143,7 @@ QQuickItemPrivate::QQuickItemPrivate() , culled(false) , hasCursor(false) , hasCursorInChild(false) + , hasHoverInChild(false) , activeFocusOnTab(false) , implicitAntialiasing(false) , antialiasingValid(false) @@ -6925,7 +6932,7 @@ void QQuickItem::setAcceptedMouseButtons(Qt::MouseButtons buttons) } /*! - Returns whether mouse events of this item's children should be filtered + Returns whether mouse and touch events of this item's children should be filtered through this item. \sa setFiltersChildMouseEvents(), childMouseEventFilter() @@ -6937,7 +6944,7 @@ bool QQuickItem::filtersChildMouseEvents() const } /*! - Sets whether mouse events of this item's children should be filtered + Sets whether mouse and touch events of this item's children should be filtered through this item. If \a filter is true, childMouseEventFilter() will be called when @@ -6988,6 +6995,7 @@ void QQuickItem::setAcceptHoverEvents(bool enabled) { Q_D(QQuickItem); d->hoverEnabled = enabled; + d->setHasHoverInChild(enabled); } void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) @@ -7015,6 +7023,29 @@ void QQuickItemPrivate::setHasCursorInChild(bool hasCursor) #endif } +void QQuickItemPrivate::setHasHoverInChild(bool hasHover) +{ + Q_Q(QQuickItem); + + // if we're asked to turn it off (because of a setAcceptHoverEvents call, or a node + // removal) then we should check our children and make sure it's really ok + // to turn it off. + if (!hasHover && hasHoverInChild) { + foreach (QQuickItem *otherChild, childItems) { + QQuickItemPrivate *otherChildPrivate = QQuickItemPrivate::get(otherChild); + if (otherChildPrivate->hasHoverInChild) + return; // nope! sorry, something else wants it kept on. + } + } + + hasHoverInChild = hasHover; + QQuickItem *parent = q->parentItem(); + if (parent) { + QQuickItemPrivate *parentPrivate = QQuickItemPrivate::get(parent); + parentPrivate->setHasHoverInChild(hasHover); + } +} + void QQuickItemPrivate::markObjects(QV4::ExecutionEngine *e) { Q_Q(QQuickItem); @@ -7140,6 +7171,7 @@ void QQuickItem::ungrabMouse() return; } + qCDebug(DBG_MOUSE_TARGET) << "ungrabMouse" << windowPriv->mouseGrabberItem << "-> null"; windowPriv->mouseGrabberItem = 0; QEvent ev(QEvent::UngrabMouse); @@ -7209,6 +7241,7 @@ void QQuickItem::grabTouchPoints(const QVector<int> &ids) QQuickItem *mouseGrabber = windowPriv->mouseGrabberItem; if (windowPriv->touchMouseId == ids.at(i) && mouseGrabber && mouseGrabber != this) { + qCDebug(DBG_MOUSE_TARGET) << "grabTouchPoints: grabber" << windowPriv->mouseGrabberItem << "-> null"; windowPriv->mouseGrabberItem = 0; QEvent ev(QEvent::UngrabMouse); d->window->sendEvent(mouseGrabber, &ev); diff --git a/src/quick/items/qquickitem_p.h b/src/quick/items/qquickitem_p.h index 5a28b202fd..da1d430ac2 100644 --- a/src/quick/items/qquickitem_p.h +++ b/src/quick/items/qquickitem_p.h @@ -430,6 +430,7 @@ public: bool hasCursor:1; // Bit 32 bool hasCursorInChild:1; + bool hasHoverInChild:1; bool activeFocusOnTab:1; bool implicitAntialiasing:1; bool antialiasingValid:1; @@ -607,6 +608,7 @@ public: virtual void mirrorChange() {} void setHasCursorInChild(bool hasCursor); + void setHasHoverInChild(bool hasHover); // recursive helper to let a visual parent mark its visual children void markObjects(QV4::ExecutionEngine *e); diff --git a/src/quick/items/qquicktext.cpp b/src/quick/items/qquicktext.cpp index f3254cf8d7..65044d33d4 100644 --- a/src/quick/items/qquicktext.cpp +++ b/src/quick/items/qquicktext.cpp @@ -1423,6 +1423,39 @@ QQuickText::~QQuickText() Text { text: "Hello"; font.capitalization: Font.AllLowercase } \endqml */ + +/*! + \qmlproperty enumeration QtQuick::Text::font.hintingPreference + \since 5.8 + + Sets the preferred hinting on the text. This is a hint to the underlying text rendering system + to use a certain level of hinting, and has varying support across platforms. See the table in + the documentation for QFont::HintingPreference for more details. + + \note This property only has an effect when used together with render type Text.NativeRendering. + + \list + \value Font.PreferDefaultHinting - Use the default hinting level for the target platform. + \value Font.PreferNoHinting - If possible, render text without hinting the outlines + of the glyphs. The text layout will be typographically accurate, using the same metrics + as are used e.g. when printing. + \value Font.PreferVerticalHinting - If possible, render text with no horizontal hinting, + but align glyphs to the pixel grid in the vertical direction. The text will appear + crisper on displays where the density is too low to give an accurate rendering + of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's + layout will be scalable to higher density devices (such as printers) without impacting + details such as line breaks. + \value Font.PreferFullHinting - If possible, render text with hinting in both horizontal and + vertical directions. The text will be altered to optimize legibility on the target + device, but since the metrics will depend on the target size of the text, the positions + of glyphs, line breaks, and other typographical detail will not scale, meaning that a + text layout may look different on devices with different pixel densities. + \endlist + + \qml + Text { text: "Hello"; renderType: Text.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting } + \endqml +*/ QFont QQuickText::font() const { Q_D(const QQuickText); diff --git a/src/quick/items/qquicktextcontrol.cpp b/src/quick/items/qquicktextcontrol.cpp index e2f4d51542..8b6cc221d5 100644 --- a/src/quick/items/qquicktextcontrol.cpp +++ b/src/quick/items/qquicktextcontrol.cpp @@ -44,6 +44,7 @@ #include <qcoreapplication.h> #include <qfont.h> +#include <qfontmetrics.h> #include <qevent.h> #include <qdebug.h> #include <qdrag.h> @@ -965,6 +966,14 @@ process: { QString text = e->text(); if (!text.isEmpty() && (text.at(0).isPrint() || text.at(0) == QLatin1Char('\t'))) { + if (overwriteMode + // no need to call deleteChar() if we have a selection, insertText + // does it already + && !cursor.hasSelection() + && !cursor.atBlockEnd()) { + cursor.deleteChar(); + } + cursor.insertText(text); selectionChanged(); } else { @@ -1007,6 +1016,12 @@ QRectF QQuickTextControlPrivate::rectForPosition(int position) const if (line.isValid()) { qreal x = line.cursorToX(relativePos); qreal w = 0; + if (overwriteMode) { + if (relativePos < line.textLength() - line.textStart()) + w = line.cursorToX(relativePos + 1) - x; + else + w = QFontMetrics(block.layout()->font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw() + } r = QRectF(layoutPos.x() + x, layoutPos.y() + line.y(), textCursorWidth + w, line.height()); } else { r = QRectF(layoutPos.x(), layoutPos.y(), textCursorWidth, 10); // #### correct height @@ -1489,6 +1504,21 @@ bool QQuickTextControl::hasImState() const return d->hasImState; } +bool QQuickTextControl::overwriteMode() const +{ + Q_D(const QQuickTextControl); + return d->overwriteMode; +} + +void QQuickTextControl::setOverwriteMode(bool overwrite) +{ + Q_D(QQuickTextControl); + if (d->overwriteMode == overwrite) + return; + d->overwriteMode = overwrite; + emit overwriteModeChanged(overwrite); +} + bool QQuickTextControl::cursorVisible() const { Q_D(const QQuickTextControl); diff --git a/src/quick/items/qquicktextcontrol_p.h b/src/quick/items/qquicktextcontrol_p.h index ca5a3d3191..602e457cb8 100644 --- a/src/quick/items/qquicktextcontrol_p.h +++ b/src/quick/items/qquicktextcontrol_p.h @@ -94,6 +94,8 @@ public: #endif bool hasImState() const; + bool overwriteMode() const; + void setOverwriteMode(bool overwrite); bool cursorVisible() const; void setCursorVisible(bool visible); QRectF anchorRect() const; @@ -149,6 +151,7 @@ Q_SIGNALS: void copyAvailable(bool b); void selectionChanged(); void cursorPositionChanged(); + void overwriteModeChanged(bool overwriteMode); // control signals void updateCursorRequest(); diff --git a/src/quick/items/qquicktextedit.cpp b/src/quick/items/qquicktextedit.cpp index d9c0e428a4..8bb788d008 100644 --- a/src/quick/items/qquicktextedit.cpp +++ b/src/quick/items/qquicktextedit.cpp @@ -323,6 +323,39 @@ QString QQuickTextEdit::text() const */ /*! + \qmlproperty enumeration QtQuick::TextEdit::font.hintingPreference + \since 5.8 + + Sets the preferred hinting on the text. This is a hint to the underlying text rendering system + to use a certain level of hinting, and has varying support across platforms. See the table in + the documentation for QFont::HintingPreference for more details. + + \note This property only has an effect when used together with render type TextEdit.NativeRendering. + + \list + \value Font.PreferDefaultHinting - Use the default hinting level for the target platform. + \value Font.PreferNoHinting - If possible, render text without hinting the outlines + of the glyphs. The text layout will be typographically accurate, using the same metrics + as are used e.g. when printing. + \value Font.PreferVerticalHinting - If possible, render text with no horizontal hinting, + but align glyphs to the pixel grid in the vertical direction. The text will appear + crisper on displays where the density is too low to give an accurate rendering + of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's + layout will be scalable to higher density devices (such as printers) without impacting + details such as line breaks. + \value Font.PreferFullHinting - If possible, render text with hinting in both horizontal and + vertical directions. The text will be altered to optimize legibility on the target + device, but since the metrics will depend on the target size of the text, the positions + of glyphs, line breaks, and other typographical detail will not scale, meaning that a + text layout may look different on devices with different pixel densities. + \endlist + + \qml + TextEdit { text: "Hello"; renderType: TextEdit.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting } + \endqml +*/ + +/*! \qmlproperty string QtQuick::TextEdit::text The text to display. If the text format is AutoText the text edit will @@ -1583,6 +1616,32 @@ bool QQuickTextEdit::event(QEvent *event) } /*! + \qmlproperty bool QtQuick::TextEdit::overwriteMode + \since 5.8 + Whether text entered by the user will overwrite existing text. + + As with many text editors, the text editor widget can be configured + to insert or overwrite existing text with new text entered by the user. + + If this property is \c true, existing text is overwritten, character-for-character + by new text; otherwise, text is inserted at the cursor position, displacing + existing text. + + By default, this property is \c false (new text does not overwrite existing text). +*/ +bool QQuickTextEdit::overwriteMode() const +{ + Q_D(const QQuickTextEdit); + return d->control->overwriteMode(); +} + +void QQuickTextEdit::setOverwriteMode(bool overwrite) +{ + Q_D(QQuickTextEdit); + d->control->setOverwriteMode(overwrite); +} + +/*! \overload Handles the given key \a event. */ @@ -2190,6 +2249,7 @@ void QQuickTextEditPrivate::init() qmlobject_connect(control, QQuickTextControl, SIGNAL(cursorRectangleChanged()), q, QQuickTextEdit, SLOT(moveCursorDelegate())); qmlobject_connect(control, QQuickTextControl, SIGNAL(linkActivated(QString)), q, QQuickTextEdit, SIGNAL(linkActivated(QString))); qmlobject_connect(control, QQuickTextControl, SIGNAL(linkHovered(QString)), q, QQuickTextEdit, SIGNAL(linkHovered(QString))); + qmlobject_connect(control, QQuickTextControl, SIGNAL(overwriteModeChanged(bool)), q, QQuickTextEdit, SIGNAL(overwriteModeChanged(bool))); qmlobject_connect(control, QQuickTextControl, SIGNAL(textChanged()), q, QQuickTextEdit, SLOT(q_textChanged())); qmlobject_connect(control, QQuickTextControl, SIGNAL(preeditTextChanged()), q, QQuickTextEdit, SIGNAL(preeditTextChanged())); #ifndef QT_NO_CLIPBOARD diff --git a/src/quick/items/qquicktextedit_p.h b/src/quick/items/qquicktextedit_p.h index f6ecb984e3..42c9064860 100644 --- a/src/quick/items/qquicktextedit_p.h +++ b/src/quick/items/qquicktextedit_p.h @@ -86,6 +86,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextEdit : public QQuickImplicitSizeItem Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) Q_PROPERTY(QQmlComponent* cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged) + Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged) Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged) Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged) @@ -199,6 +200,9 @@ public: QQmlComponent* cursorDelegate() const; void setCursorDelegate(QQmlComponent*); + bool overwriteMode() const; + void setOverwriteMode(bool overwrite); + int selectionStart() const; int selectionEnd() const; @@ -313,6 +317,7 @@ Q_SIGNALS: void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); void cursorDelegateChanged(); + void overwriteModeChanged(bool overwriteMode); void activeFocusOnPressChanged(bool activeFocusOnPressed); void persistentSelectionChanged(bool isPersistentSelection); void textMarginChanged(qreal textMargin); diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp index f93857a892..f361d46424 100644 --- a/src/quick/items/qquicktextinput.cpp +++ b/src/quick/items/qquicktextinput.cpp @@ -345,6 +345,38 @@ QString QQuickTextInputPrivate::realText() const \endqml */ +/*! + \qmlproperty enumeration QtQuick::TextInput::font.hintingPreference + \since 5.8 + + Sets the preferred hinting on the text. This is a hint to the underlying text rendering system + to use a certain level of hinting, and has varying support across platforms. See the table in + the documentation for QFont::HintingPreference for more details. + + \note This property only has an effect when used together with render type TextInput.NativeRendering. + + \list + \value Font.PreferDefaultHinting - Use the default hinting level for the target platform. + \value Font.PreferNoHinting - If possible, render text without hinting the outlines + of the glyphs. The text layout will be typographically accurate, using the same metrics + as are used e.g. when printing. + \value Font.PreferVerticalHinting - If possible, render text with no horizontal hinting, + but align glyphs to the pixel grid in the vertical direction. The text will appear + crisper on displays where the density is too low to give an accurate rendering + of the glyphs. But since the horizontal metrics of the glyphs are unhinted, the text's + layout will be scalable to higher density devices (such as printers) without impacting + details such as line breaks. + \value Font.PreferFullHinting - If possible, render text with hinting in both horizontal and + vertical directions. The text will be altered to optimize legibility on the target + device, but since the metrics will depend on the target size of the text, the positions + of glyphs, line breaks, and other typographical detail will not scale, meaning that a + text layout may look different on devices with different pixel densities. + \endlist + + \qml + TextInput { text: "Hello"; renderType: TextInput.NativeRendering; font.hintingPreference: Font.PreferVerticalHinting } + \endqml +*/ QFont QQuickTextInput::font() const { Q_D(const QQuickTextInput); @@ -812,7 +844,14 @@ QRectF QQuickTextInput::cursorRectangle() const return QRectF(); qreal x = l.cursorToX(c) - d->hscroll + leftPadding(); qreal y = l.y() - d->vscroll + topPadding(); - return QRectF(x, y, 1, l.height()); + qreal w = 1; + if (d->overwriteMode) { + if (c < text().length()) + w = l.cursorToX(c + 1) - x; + else + w = QFontMetrics(font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw() + } + return QRectF(x, y, w, l.height()); } /*! @@ -1292,7 +1331,14 @@ QRectF QQuickTextInput::positionToRectangle(int pos) const return QRectF(); qreal x = l.cursorToX(pos) - d->hscroll; qreal y = l.y() - d->vscroll; - return QRectF(x, y, 1, l.height()); + qreal w = 1; + if (d->overwriteMode) { + if (pos < text().length()) + w = l.cursorToX(pos + 1) - x; + else + w = QFontMetrics(font()).width(QLatin1Char(' ')); // in sync with QTextLine::draw() + } + return QRectF(x, y, w, l.height()); } /*! @@ -1374,6 +1420,36 @@ int QQuickTextInputPrivate::positionAt(qreal x, qreal y, QTextLine::CursorPositi return line.isValid() ? line.xToCursor(x, position) : 0; } +/*! + \qmlproperty bool QtQuick::TextInput::overwriteMode + \since 5.8 + + Whether text entered by the user will overwrite existing text. + + As with many text editors, the text editor widget can be configured + to insert or overwrite existing text with new text entered by the user. + + If this property is \c true, existing text is overwritten, character-for-character + by new text; otherwise, text is inserted at the cursor position, displacing + existing text. + + By default, this property is \c false (new text does not overwrite existing text). +*/ +bool QQuickTextInput::overwriteMode() const +{ + Q_D(const QQuickTextInput); + return d->overwriteMode; +} + +void QQuickTextInput::setOverwriteMode(bool overwrite) +{ + Q_D(QQuickTextInput); + if (d->overwriteMode == overwrite) + return; + d->overwriteMode = overwrite; + emit overwriteModeChanged(overwrite); +} + void QQuickTextInput::keyPressEvent(QKeyEvent* ev) { Q_D(QQuickTextInput); @@ -2769,7 +2845,7 @@ void QQuickTextInputPrivate::updateDisplayText(bool forceUpdate) // characters) QChar* uc = str.data(); for (int i = 0; i < (int)str.length(); ++i) { - if ((uc[i] < 0x20 && uc[i] != 0x09) + if ((uc[i].unicode() < 0x20 && uc[i] != QChar::Tabulation) || uc[i] == QChar::LineSeparator || uc[i] == QChar::ParagraphSeparator || uc[i] == QChar::ObjectReplacementCharacter) @@ -4449,6 +4525,14 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event) if (unknown && !m_readOnly) { QString t = event->text(); if (!t.isEmpty() && t.at(0).isPrint()) { + if (overwriteMode + // no need to call del() if we have a selection, insert + // does it already + && !hasSelectedText() + && !(m_cursor == q_func()->text().length())) { + del(); + } + insert(t); event->accept(); return; diff --git a/src/quick/items/qquicktextinput_p.h b/src/quick/items/qquicktextinput_p.h index 06ca1acb0d..d2dee2c284 100644 --- a/src/quick/items/qquicktextinput_p.h +++ b/src/quick/items/qquicktextinput_p.h @@ -79,6 +79,7 @@ class Q_QUICK_PRIVATE_EXPORT QQuickTextInput : public QQuickImplicitSizeItem Q_PROPERTY(int cursorPosition READ cursorPosition WRITE setCursorPosition NOTIFY cursorPositionChanged) Q_PROPERTY(QRectF cursorRectangle READ cursorRectangle NOTIFY cursorRectangleChanged) Q_PROPERTY(QQmlComponent *cursorDelegate READ cursorDelegate WRITE setCursorDelegate NOTIFY cursorDelegateChanged) + Q_PROPERTY(bool overwriteMode READ overwriteMode WRITE setOverwriteMode NOTIFY overwriteModeChanged) Q_PROPERTY(int selectionStart READ selectionStart NOTIFY selectionStartChanged) Q_PROPERTY(int selectionEnd READ selectionEnd NOTIFY selectionEndChanged) Q_PROPERTY(QString selectedText READ selectedText NOTIFY selectedTextChanged) @@ -245,6 +246,9 @@ public: QQmlComponent* cursorDelegate() const; void setCursorDelegate(QQmlComponent*); + bool overwriteMode() const; + void setOverwriteMode(bool overwrite); + bool focusOnPress() const; void setFocusOnPress(bool); @@ -325,6 +329,7 @@ Q_SIGNALS: void readOnlyChanged(bool isReadOnly); void cursorVisibleChanged(bool isCursorVisible); void cursorDelegateChanged(); + void overwriteModeChanged(bool overwriteMode); void maximumLengthChanged(int maximumLength); void validatorChanged(); void inputMaskChanged(const QString &inputMask); diff --git a/src/quick/items/qquicktextinput_p_p.h b/src/quick/items/qquicktextinput_p_p.h index 9d3c66f04a..e6bd29bf67 100644 --- a/src/quick/items/qquicktextinput_p_p.h +++ b/src/quick/items/qquicktextinput_p_p.h @@ -158,6 +158,7 @@ public: , m_passwordEchoEditing(false) , inLayout(false) , requireImplicitWidth(false) + , overwriteMode(false) { } @@ -299,6 +300,7 @@ public: bool m_passwordEchoEditing : 1; bool inLayout:1; bool requireImplicitWidth:1; + bool overwriteMode:1; static inline QQuickTextInputPrivate *get(QQuickTextInput *t) { return t->d_func(); diff --git a/src/quick/items/qquicktextnodeengine.cpp b/src/quick/items/qquicktextnodeengine.cpp index 2872c3e230..7b600adf53 100644 --- a/src/quick/items/qquicktextnodeengine.cpp +++ b/src/quick/items/qquicktextnodeengine.cpp @@ -731,10 +731,13 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN QVector<QPointF> glyphPositions = glyphRun.positions(); glyphPositions.reserve(count); + QRectF glyphBoundingRect = glyphRun.boundingRect(); + for (int j = 1; j < nodes.size(); ++j) { BinaryTreeNode *otherNode = nodes.at(j); glyphIndexes += otherNode->glyphRun.glyphIndexes(); primaryNode->ranges += otherNode->ranges; + glyphBoundingRect = glyphBoundingRect.united(otherNode->glyphRun.boundingRect()); QVector<QPointF> otherPositions = otherNode->glyphRun.positions(); for (int k = 0; k < otherPositions.size(); ++k) @@ -746,6 +749,7 @@ void QQuickTextNodeEngine::mergeProcessedNodes(QList<BinaryTreeNode *> *regularN glyphRun.setGlyphIndexes(glyphIndexes); glyphRun.setPositions(glyphPositions); + glyphRun.setBoundingRect(glyphBoundingRect); } } } diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index bb3f5138ad..cae32dfa49 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -79,11 +79,12 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch"); -Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target"); -Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse"); -Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus"); -Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty"); +Q_LOGGING_CATEGORY(DBG_TOUCH, "qt.quick.touch") +Q_LOGGING_CATEGORY(DBG_TOUCH_TARGET, "qt.quick.touch.target") +Q_LOGGING_CATEGORY(DBG_MOUSE, "qt.quick.mouse") +Q_LOGGING_CATEGORY(DBG_MOUSE_TARGET, "qt.quick.mouse.target") +Q_LOGGING_CATEGORY(DBG_FOCUS, "qt.quick.focus") +Q_LOGGING_CATEGORY(DBG_DIRTY, "qt.quick.dirty") extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); @@ -715,6 +716,7 @@ void QQuickWindowPrivate::setMouseGrabber(QQuickItem *grabber) if (mouseGrabberItem == grabber) return; + qCDebug(DBG_MOUSE_TARGET) << "grabber" << mouseGrabberItem << "->" << grabber; QQuickItem *oldGrabber = mouseGrabberItem; mouseGrabberItem = grabber; @@ -1623,7 +1625,7 @@ void QQuickWindow::mouseReleaseEvent(QMouseEvent *event) return; } - qCDebug(DBG_MOUSE) << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons(); + qCDebug(DBG_MOUSE) << "QQuickWindow::mouseReleaseEvent()" << event->localPos() << event->button() << event->buttons() << "grabber:" << d->mouseGrabberItem; if (!d->mouseGrabberItem) { QWindow::mouseReleaseEvent(event); @@ -1730,13 +1732,15 @@ bool QQuickWindowPrivate::deliverHoverEvent(QQuickItem *item, const QPointF &sce return false; } - QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); - for (int ii = children.count() - 1; ii >= 0; --ii) { - QQuickItem *child = children.at(ii); - if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) - continue; - if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted)) - return true; + if (itemPrivate->hasHoverInChild) { + QList<QQuickItem *> children = itemPrivate->paintOrderChildItems(); + for (int ii = children.count() - 1; ii >= 0; --ii) { + QQuickItem *child = children.at(ii); + if (!child->isVisible() || !child->isEnabled() || QQuickItemPrivate::get(child)->culled) + continue; + if (deliverHoverEvent(child, scenePos, lastScenePos, modifiers, accepted)) + return true; + } } if (itemPrivate->hoverEnabled) { @@ -2151,7 +2155,7 @@ bool QQuickWindowPrivate::deliverTouchPoints(QQuickItem *item, QTouchEvent *even return (acceptedNewPoints->count() == newPoints.count() && updatedPoints->isEmpty()); } -// touchEventForItemBounds has no means to generate a touch event that contains +// touchEventForItem has no means to generate a touch event that contains // only the points that are relevant for this item. Thus the need for // matchingPoints to already be that set of interesting points. // They are all pre-transformed, too. @@ -2213,7 +2217,7 @@ bool QQuickWindowPrivate::deliverMatchingPointsToItem(QQuickItem *item, QTouchEv return touchEventAccepted; } -QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent) +QTouchEvent *QQuickWindowPrivate::touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds) { const QList<QTouchEvent::TouchPoint> &touchPoints = originalEvent.touchPoints(); QList<QTouchEvent::TouchPoint> pointsInBounds; @@ -2221,7 +2225,10 @@ QTouchEvent *QQuickWindowPrivate::touchEventForItemBounds(QQuickItem *target, co if (originalEvent.touchPointStates() != Qt::TouchPointStationary) { for (int i = 0; i < touchPoints.count(); ++i) { const QTouchEvent::TouchPoint &tp = touchPoints.at(i); - if (tp.state() == Qt::TouchPointPressed) { + // Touch presses are relevant to the target item only if they occur inside its bounds. + // Touch updates and releases are relevant if they occur inside, or if we want to + // finish the sequence because the press occurred inside. + if (tp.state() == Qt::TouchPointPressed || alwaysCheckBounds) { QPointF p = target->mapFromScene(tp.scenePos()); if (target->contains(p)) pointsInBounds.append(tp); @@ -2450,7 +2457,7 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem QQuickItemPrivate *targetPrivate = QQuickItemPrivate::get(target); if (targetPrivate->filtersChildMouseEvents && !hasFiltered->contains(target)) { hasFiltered->insert(target); - QScopedPointer<QTouchEvent> targetEvent(touchEventForItemBounds(target, *event)); + QScopedPointer<QTouchEvent> targetEvent(touchEventForItem(target, *event)); if (!targetEvent->touchPoints().isEmpty()) { if (target->childMouseEventFilter(item, targetEvent.data())) { qCDebug(DBG_TOUCH) << " - first chance intercepted on childMouseEventFilter by " << target; @@ -2530,6 +2537,7 @@ bool QQuickWindowPrivate::sendFilteredMouseEvent(QQuickItem *target, QQuickItem hasFiltered->insert(target); if (target->childMouseEventFilter(item, event)) filtered = true; + qCDebug(DBG_MOUSE_TARGET) << target << "childMouseEventFilter ->" << filtered; } return sendFilteredMouseEvent(target->parentItem(), item, event, hasFiltered) || filtered; @@ -2550,6 +2558,15 @@ bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent return overThreshold; } +bool QQuickWindowPrivate::dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold) +{ + QStyleHints *styleHints = qApp->styleHints(); + bool overThreshold = qAbs(d) > (startDragThreshold >= 0 ? startDragThreshold : styleHints->startDragDistance()); + qreal velocity = axis == Qt::XAxis ? tp->velocity().x() : tp->velocity().y(); + overThreshold |= qAbs(velocity) > styleHints->startDragVelocity(); + return overThreshold; +} + /*! \qmlproperty list<Object> Window::data \default diff --git a/src/quick/items/qquickwindow_p.h b/src/quick/items/qquickwindow_p.h index 1064be7178..1486e20e1e 100644 --- a/src/quick/items/qquickwindow_p.h +++ b/src/quick/items/qquickwindow_p.h @@ -163,8 +163,8 @@ public: void flushDelayedTouchEvent(); bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted); bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered); - QTouchEvent *touchEventForItemBounds(QQuickItem *target, const QTouchEvent &originalEvent); - QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints); + static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false); + static QTouchEvent *touchEventWithPoints(const QTouchEvent &event, const QList<QTouchEvent::TouchPoint> &newPoints); bool sendFilteredTouchEvent(QQuickItem *target, QQuickItem *item, QTouchEvent *event, QSet<QQuickItem*> *filtered); bool sendHoverEvent(QEvent::Type, QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool accepted); @@ -265,6 +265,7 @@ public: static bool defaultAlphaBuffer; static bool dragOverThreshold(qreal d, Qt::Axis axis, QMouseEvent *event, int startDragThreshold = -1); + static bool dragOverThreshold(qreal d, Qt::Axis axis, const QTouchEvent::TouchPoint *tp, int startDragThreshold = -1); // data property static void data_append(QQmlListProperty<QObject> *, QObject *); diff --git a/src/quick/quick.pro b/src/quick/quick.pro index 1c14ff8d57..f74a554aa9 100644 --- a/src/quick/quick.pro +++ b/src/quick/quick.pro @@ -1,12 +1,17 @@ TARGET = QtQuick QT = core-private gui-private qml-private -QT_PRIVATE = network +!no_network { + QT_PRIVATE = network +} +no_network { + DEFINES += QT_NO_NETWORK +} DEFINES += QT_NO_URL_CAST_FROM_STRING QT_NO_INTEGER_EVENT_COORDINATES win32-msvc*:DEFINES *= _CRT_SECURE_NO_WARNINGS solaris-cc*:QMAKE_CXXFLAGS_RELEASE -= -O2 -win32:!wince:!winrt: LIBS += -luser32 +win32:!winrt: LIBS += -luser32 exists("qqml_enable_gcov") { QMAKE_CXXFLAGS = -fprofile-arcs -ftest-coverage -fno-elide-constructors @@ -27,7 +32,7 @@ ANDROID_BUNDLED_FILES += \ include(util/util.pri) include(scenegraph/scenegraph.pri) include(items/items.pri) -!wince:include(designer/designer.pri) +include(designer/designer.pri) contains(QT_CONFIG, accessibility) { include(accessible/accessible.pri) } diff --git a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp index 97d7e69407..3a35632d5c 100644 --- a/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp +++ b/src/quick/scenegraph/coreapi/qsgshaderrewriter.cpp @@ -89,9 +89,6 @@ void Tokenizer::initialize(const char *input) identifier = input; } -#define foo - - Tokenizer::Token Tokenizer::next() { while (*pos != 0) { diff --git a/src/quick/scenegraph/qsgadaptationlayer.cpp b/src/quick/scenegraph/qsgadaptationlayer.cpp index 682423726e..eb6a846a81 100644 --- a/src/quick/scenegraph/qsgadaptationlayer.cpp +++ b/src/quick/scenegraph/qsgadaptationlayer.cpp @@ -65,7 +65,7 @@ QSGDistanceFieldGlyphCache::QSGDistanceFieldGlyphCache(QSGDistanceFieldGlyphCach QRawFontPrivate *fontD = QRawFontPrivate::get(font); m_glyphCount = fontD->fontEngine->glyphCount(); - m_doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT; + m_doubleGlyphResolution = qt_fontHasNarrowOutlines(font) && m_glyphCount < QT_DISTANCEFIELD_HIGHGLYPHCOUNT(); m_referenceFont = font; // we set the same pixel size as used by the distance field internally. diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp index 6572ceb2ce..2ba16e7328 100644 --- a/src/quick/scenegraph/qsgcontext.cpp +++ b/src/quick/scenegraph/qsgcontext.cpp @@ -136,9 +136,9 @@ public: bool distanceFieldAntialiasingDecided; }; -static bool qsg_useConsistentTiming() +bool qsg_useConsistentTiming() { - static int use = -1; + int use = -1; if (use < 0) { use = !qEnvironmentVariableIsEmpty("QSG_FIXED_ANIMATION_STEP") && qgetenv("QSG_FIXED_ANIMATION_STEP") != "no" ? 1 : 0; diff --git a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp index 1fc63db1b2..650700e37a 100644 --- a/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp +++ b/src/quick/scenegraph/qsgdefaultdistancefieldglyphcache.cpp @@ -503,7 +503,7 @@ bool QSGDefaultDistanceFieldGlyphCache::useTextureUploadWorkaround() const bool QSGDefaultDistanceFieldGlyphCache::createFullSizeTextures() const { - return qsgPreferFullSizeGlyphCacheTextures() && glyphCount() > QT_DISTANCEFIELD_HIGHGLYPHCOUNT; + return qsgPreferFullSizeGlyphCacheTextures() && glyphCount() > QT_DISTANCEFIELD_HIGHGLYPHCOUNT(); } int QSGDefaultDistanceFieldGlyphCache::maxTextureSize() const diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp index b5f149eff7..1b0b1acc0e 100644 --- a/src/quick/scenegraph/qsgrenderloop.cpp +++ b/src/quick/scenegraph/qsgrenderloop.cpp @@ -67,7 +67,7 @@ QT_BEGIN_NAMESPACE - +extern bool qsg_useConsistentTiming(); extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha); /*! @@ -253,13 +253,13 @@ void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window, const bool signalEmitted = QQuickWindowPrivate::get(window)->emitError(QQuickWindow::ContextNotAvailable, translatedMessage); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) if (!signalEmitted && !QLibraryInfo::isDebugBuild() && !GetConsoleWindow()) { MessageBox(0, (LPCTSTR) translatedMessage.utf16(), (LPCTSTR)(QCoreApplication::applicationName().utf16()), MB_OK | MB_ICONERROR); } -#endif // Q_OS_WIN && !Q_OS_WINCE && !Q_OS_WINRT +#endif // Q_OS_WIN && !Q_OS_WINRT if (!signalEmitted) qFatal("%s", qPrintable(untranslatedMessage)); } @@ -267,6 +267,10 @@ void QSGRenderLoop::handleContextCreationFailure(QQuickWindow *window, QSGGuiThreadRenderLoop::QSGGuiThreadRenderLoop() : gl(0) { + if (qsg_useConsistentTiming()) { + QUnifiedTimer::instance(true)->setConsistentTiming(true); + qCDebug(QSG_LOG_INFO, "using fixed animation steps"); + } sg = QSGContext::createDefaultContext(); rc = sg->createRenderContext(); } diff --git a/src/quick/util/qquickapplication.cpp b/src/quick/util/qquickapplication.cpp index a4e2f0eb0e..5c26b23ff7 100644 --- a/src/quick/util/qquickapplication.cpp +++ b/src/quick/util/qquickapplication.cpp @@ -90,4 +90,9 @@ Qt::ApplicationState QQuickApplication::state() const return QGuiApplication::applicationState(); } +QFont QQuickApplication::font() const +{ + return QGuiApplication::font(); +} + QT_END_NAMESPACE diff --git a/src/quick/util/qquickapplication_p.h b/src/quick/util/qquickapplication_p.h index 971c9a203a..091cb094ed 100644 --- a/src/quick/util/qquickapplication_p.h +++ b/src/quick/util/qquickapplication_p.h @@ -52,6 +52,7 @@ // #include <QtCore/QObject> +#include <QtGui/QFont> #include <qqml.h> #include <QtQml/private/qqmlglobal_p.h> #include <private/qtquickglobal_p.h> @@ -66,6 +67,7 @@ class Q_AUTOTEST_EXPORT QQuickApplication : public QQmlApplication Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection NOTIFY layoutDirectionChanged) Q_PROPERTY(bool supportsMultipleWindows READ supportsMultipleWindows CONSTANT) Q_PROPERTY(Qt::ApplicationState state READ state NOTIFY stateChanged) + Q_PROPERTY(QFont font READ font CONSTANT) public: explicit QQuickApplication(QObject *parent = 0); @@ -74,6 +76,7 @@ public: Qt::LayoutDirection layoutDirection() const; bool supportsMultipleWindows() const; Qt::ApplicationState state() const; + QFont font() const; Q_SIGNALS: void activeChanged(); diff --git a/src/quick/util/qquickfontloader.cpp b/src/quick/util/qquickfontloader.cpp index 64fd458ef0..b7367f3934 100644 --- a/src/quick/util/qquickfontloader.cpp +++ b/src/quick/util/qquickfontloader.cpp @@ -45,14 +45,18 @@ #include <QStringList> #include <QUrl> #include <QDebug> -#include <QNetworkRequest> -#include <QNetworkReply> + #include <QFontDatabase> #include <private/qobject_p.h> #include <qqmlinfo.h> #include <qqmlfile.h> +#ifndef QT_NO_NETWORK +#include <QNetworkRequest> +#include <QNetworkReply> +#endif + #include <QtCore/QCoreApplication> QT_BEGIN_NAMESPACE @@ -66,28 +70,37 @@ Q_OBJECT public: explicit QQuickFontObject(int _id = -1); +#ifndef QT_NO_NETWORK void download(const QUrl &url, QNetworkAccessManager *manager); Q_SIGNALS: void fontDownloaded(const QString&, QQuickFontLoader::Status); +private: + int redirectCount; + QNetworkReply *reply; + private Q_SLOTS: void replyFinished(); +#endif // QT_NO_NETWORK public: int id; -private: - QNetworkReply *reply; - int redirectCount; - Q_DISABLE_COPY(QQuickFontObject) }; QQuickFontObject::QQuickFontObject(int _id) - : QObject(0), id(_id), reply(0), redirectCount(0) {} + : QObject(0) +#ifndef QT_NO_NETWORK + ,redirectCount(0), reply(0) +#endif + ,id(_id) +{ +} +#ifndef QT_NO_NETWORK void QQuickFontObject::download(const QUrl &url, QNetworkAccessManager *manager) { QNetworkRequest req(url); @@ -128,7 +141,7 @@ void QQuickFontObject::replyFinished() reply = 0; } } - +#endif // QT_NO_NETWORK class QQuickFontLoaderPrivate : public QObjectPrivate { @@ -255,6 +268,7 @@ void QQuickFontLoader::setSource(const QUrl &url) } } else { if (!fontLoaderFonts()->map.contains(d->url)) { +#ifndef QT_NO_NETWORK QQuickFontObject *fo = new QQuickFontObject; fontLoaderFonts()->map[d->url] = fo; fo->download(d->url, qmlEngine(this)->networkAccessManager()); @@ -262,13 +276,20 @@ void QQuickFontLoader::setSource(const QUrl &url) emit statusChanged(); QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)), this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status))); +#else +// Silently fail if compiled with no_network +#endif } else { QQuickFontObject *fo = fontLoaderFonts()->map[d->url]; if (fo->id == -1) { +#ifndef QT_NO_NETWORK d->status = Loading; emit statusChanged(); QObject::connect(fo, SIGNAL(fontDownloaded(QString,QQuickFontLoader::Status)), this, SLOT(updateFontInfo(QString,QQuickFontLoader::Status))); +#else +// Silently fail if compiled with no_network +#endif } else updateFontInfo(QFontDatabase::applicationFontFamilies(fo->id).at(0), Ready); diff --git a/src/quick/util/qquickglobal.cpp b/src/quick/util/qquickglobal.cpp index ef54917434..4ad6fdd854 100644 --- a/src/quick/util/qquickglobal.cpp +++ b/src/quick/util/qquickglobal.cpp @@ -301,6 +301,7 @@ public: QV4::ScopedValue vundl(scope, obj->get((s = v4->newString(QStringLiteral("underline"))))); QV4::ScopedValue vweight(scope, obj->get((s = v4->newString(QStringLiteral("weight"))))); QV4::ScopedValue vwspac(scope, obj->get((s = v4->newString(QStringLiteral("wordSpacing"))))); + QV4::ScopedValue vhint(scope, obj->get((s = v4->newString(QStringLiteral("hintingPreference"))))); // pull out the values, set ok to true if at least one valid field is given. if (vbold->isBoolean()) { @@ -351,6 +352,10 @@ public: retn.setWordSpacing(vwspac->asDouble()); if (ok) *ok = true; } + if (vhint->isInt32()) { + retn.setHintingPreference(static_cast<QFont::HintingPreference>(vhint->integerValue())); + if (ok) *ok = true; + } return retn; } diff --git a/src/quick/util/qquickpixmapcache.cpp b/src/quick/util/qquickpixmapcache.cpp index 6dee84b005..2b6e8f68c3 100644 --- a/src/quick/util/qquickpixmapcache.cpp +++ b/src/quick/util/qquickpixmapcache.cpp @@ -38,7 +38,6 @@ ****************************************************************************/ #include "qquickpixmapcache_p.h" -#include <qqmlnetworkaccessmanagerfactory.h> #include <qquickimageprovider.h> #include <qqmlengine.h> @@ -55,7 +54,6 @@ #include <QCoreApplication> #include <QImageReader> #include <QHash> -#include <QNetworkReply> #include <QPixmapCache> #include <QFile> #include <QThread> @@ -66,10 +64,15 @@ #include <QWaitCondition> #include <QtCore/qdebug.h> #include <private/qobject_p.h> -#include <QSslError> #include <QQmlFile> #include <QMetaMethod> +#ifndef QT_NO_NETWORK +#include <qqmlnetworkaccessmanagerfactory.h> +#include <QNetworkReply> +#include <QSslError> +#endif + #include <private/qquickprofiler_p.h> #define IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT 8 @@ -203,7 +206,9 @@ private: friend class QQuickPixmapReaderThreadObject; void processJobs(); void processJob(QQuickPixmapReply *, const QUrl &, const QString &, AutoTransform, QQuickImageProvider::ImageType, QQuickImageProvider *); +#ifndef QT_NO_NETWORK void networkRequestDone(QNetworkReply *); +#endif void asyncResponseFinished(QQuickImageResponse *); QList<QQuickPixmapReply*> jobs; @@ -215,10 +220,11 @@ private: QQuickPixmapReaderThreadObject *threadObject; QWaitCondition waitCondition; +#ifndef QT_NO_NETWORK QNetworkAccessManager *networkAccessManager(); QNetworkAccessManager *accessManager; - QHash<QNetworkReply*,QQuickPixmapReply*> networkJobs; +#endif QHash<QQuickImageResponse*,QQuickPixmapReply*> asyncResponses; static int replyDownloadProgress; @@ -343,6 +349,7 @@ QQuickPixmapReply::Event::~Event() delete textureFactory; } +#ifndef QT_NO_NETWORK QNetworkAccessManager *QQuickPixmapReader::networkAccessManager() { if (!accessManager) { @@ -351,6 +358,7 @@ QNetworkAccessManager *QQuickPixmapReader::networkAccessManager() } return accessManager; } +#endif static void maybeRemoveAlpha(QImage *image) { @@ -421,7 +429,10 @@ static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *e } QQuickPixmapReader::QQuickPixmapReader(QQmlEngine *eng) -: QThread(eng), engine(eng), threadObject(0), accessManager(0) +: QThread(eng), engine(eng), threadObject(0) +#ifndef QT_NO_NETWORK +, accessManager(0) +#endif { eventLoopQuitHack = new QObject; eventLoopQuitHack->moveToThread(this); @@ -443,6 +454,7 @@ QQuickPixmapReader::~QQuickPixmapReader() delete reply; } jobs.clear(); +#ifndef QT_NO_NETWORK QList<QQuickPixmapReply*> activeJobs = networkJobs.values() + asyncResponses.values(); foreach (QQuickPixmapReply *reply, activeJobs ) { if (reply->loading) { @@ -450,6 +462,7 @@ QQuickPixmapReader::~QQuickPixmapReader() reply->data = 0; } } +#endif if (threadObject) threadObject->processJobs(); mutex.unlock(); @@ -457,6 +470,7 @@ QQuickPixmapReader::~QQuickPixmapReader() wait(); } +#ifndef QT_NO_NETWORK void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) { QQuickPixmapReply *job = networkJobs.take(reply); @@ -506,6 +520,7 @@ void QQuickPixmapReader::networkRequestDone(QNetworkReply *reply) // kick off event loop again incase we have dropped below max request count threadObject->processJobs(); } +#endif // QT_NO_NETWORK void QQuickPixmapReader::asyncResponseFinished(QQuickImageResponse *response) { @@ -556,8 +571,10 @@ bool QQuickPixmapReaderThreadObject::event(QEvent *e) void QQuickPixmapReaderThreadObject::networkRequestDone() { +#ifndef QT_NO_NETWORK QNetworkReply *reply = static_cast<QNetworkReply *>(sender()); reader->networkRequestDone(reply); +#endif } void QQuickPixmapReaderThreadObject::asyncResponseFinished() @@ -576,6 +593,7 @@ void QQuickPixmapReader::processJobs() // Clean cancelled jobs if (!cancelled.isEmpty()) { +#ifndef QT_NO_NETWORK for (int i = 0; i < cancelled.count(); ++i) { QQuickPixmapReply *job = cancelled.at(i); QNetworkReply *reply = networkJobs.key(job, 0); @@ -598,6 +616,7 @@ void QQuickPixmapReader::processJobs() job->deleteLater(); } cancelled.clear(); +#endif } if (!jobs.isEmpty()) { @@ -618,7 +637,11 @@ void QQuickPixmapReader::processJobs() usableJob = true; } else { localFile = QQmlFile::urlToLocalFileOrQrc(url); - usableJob = !localFile.isEmpty() || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT; + usableJob = !localFile.isEmpty() +#ifndef QT_NO_NETWORK + || networkJobs.count() < IMAGEREQUEST_MAX_NETWORK_REQUEST_COUNT +#endif + ; } @@ -743,6 +766,7 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u runningJob->postReply(errorCode, errorStr, readSize, QQuickTextureFactory::textureFactoryForImage(image)); mutex.unlock(); } else { +#ifndef QT_NO_NETWORK // Network resource QNetworkRequest req(url); req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); @@ -752,6 +776,9 @@ void QQuickPixmapReader::processJob(QQuickPixmapReply *runningJob, const QUrl &u QMetaObject::connect(reply, replyFinished, threadObject, threadNetworkRequestDone); networkJobs.insert(reply, runningJob); +#else +// Silently fail if compiled with no_network +#endif } } } @@ -808,11 +835,13 @@ void QQuickPixmapReader::cancel(QQuickPixmapReply *reply) void QQuickPixmapReader::run() { if (replyDownloadProgress == -1) { +#ifndef QT_NO_NETWORK replyDownloadProgress = QMetaMethod::fromSignal(&QNetworkReply::downloadProgress).methodIndex(); replyFinished = QMetaMethod::fromSignal(&QNetworkReply::finished).methodIndex(); - downloadProgress = QMetaMethod::fromSignal(&QQuickPixmapReply::downloadProgress).methodIndex(); const QMetaObject *ir = &QQuickPixmapReaderThreadObject::staticMetaObject; threadNetworkRequestDone = ir->indexOfSlot("networkRequestDone()"); +#endif + downloadProgress = QMetaMethod::fromSignal(&QQuickPixmapReply::downloadProgress).methodIndex(); } mutex.lock(); diff --git a/src/quick/util/qquickvaluetypes.cpp b/src/quick/util/qquickvaluetypes.cpp index 416a325238..7b9b6068bd 100644 --- a/src/quick/util/qquickvaluetypes.cpp +++ b/src/quick/util/qquickvaluetypes.cpp @@ -676,4 +676,14 @@ void QQuickFontValueType::setWordSpacing(qreal size) v.setWordSpacing(size); } +QQuickFontValueType::HintingPreference QQuickFontValueType::hintingPreference() const +{ + return QQuickFontValueType::HintingPreference(v.hintingPreference()); +} + +void QQuickFontValueType::setHintingPreference(QQuickFontValueType::HintingPreference hintingPreference) +{ + v.setHintingPreference(QFont::HintingPreference(hintingPreference)); +} + QT_END_NAMESPACE diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h index 80b9ce3109..05e954f915 100644 --- a/src/quick/util/qquickvaluetypes_p.h +++ b/src/quick/util/qquickvaluetypes_p.h @@ -304,6 +304,7 @@ class QQuickFontValueType Q_PROPERTY(Capitalization capitalization READ capitalization WRITE setCapitalization FINAL) Q_PROPERTY(qreal letterSpacing READ letterSpacing WRITE setLetterSpacing FINAL) Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing FINAL) + Q_PROPERTY(HintingPreference hintingPreference READ hintingPreference WRITE setHintingPreference FINAL) public: enum FontWeight { Thin = QFont::Thin, @@ -323,6 +324,14 @@ public: Capitalize = QFont::Capitalize }; Q_ENUM(Capitalization) + enum HintingPreference { + PreferDefaultHinting = QFont::PreferDefaultHinting, + PreferNoHinting = QFont::PreferNoHinting, + PreferVerticalHinting = QFont::PreferVerticalHinting, + PreferFullHinting = QFont::PreferFullHinting + }; + Q_ENUM(HintingPreference) + Q_INVOKABLE QString toString() const; QString family() const; @@ -363,6 +372,9 @@ public: qreal wordSpacing() const; void setWordSpacing(qreal spacing); + + HintingPreference hintingPreference() const; + void setHintingPreference(HintingPreference); }; QT_END_NAMESPACE diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp index f720513b85..3bce7827bc 100644 --- a/src/quickwidgets/qquickwidget.cpp +++ b/src/quickwidgets/qquickwidget.cpp @@ -700,10 +700,10 @@ void QQuickWidgetPrivate::handleContextCreationFailure(const QSurfaceFormat &for if (signalConnected) emit q->sceneGraphError(QQuickWindow::ContextNotAvailable, translatedMessage); -#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) if (!signalConnected && !QLibraryInfo::isDebugBuild() && !GetConsoleWindow()) QMessageBox::critical(q, QCoreApplication::applicationName(), translatedMessage); -#endif // Q_OS_WIN && !Q_OS_WINCE && !Q_OS_WINRT +#endif // Q_OS_WIN && !Q_OS_WINRT if (!signalConnected) qFatal("%s", qPrintable(untranslatedMessage)); } |