aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2017-03-14 10:49:51 +0100
committerLiang Qi <liang.qi@qt.io>2017-03-14 10:49:51 +0100
commit12e82111ab86669969430ab10118236d8d846d33 (patch)
treefb2345160fbe9d46cb61212f4a5eac81389464ba
parent30635ee2424dbd08bb5c2170be0c2dc5f9d23b2c (diff)
parent77e0dc0485953427320ed0b442ba24eef4f9d73b (diff)
Merge remote-tracking branch 'origin/5.9' into dev
-rw-r--r--examples/qml/referenceexamples/properties/birthdayparty.cpp31
-rw-r--r--examples/qml/referenceexamples/properties/birthdayparty.h10
-rw-r--r--src/3rdparty/masm/assembler/X86Assembler.h2
-rw-r--r--src/imports/imports.pro2
-rw-r--r--src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp7
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp25
-rw-r--r--src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h3
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp17
-rw-r--r--src/qml/compiler/qv4codegen.cpp12
-rw-r--r--src/qml/compiler/qv4compilationunitmapper.cpp2
-rw-r--r--src/qml/compiler/qv4compileddata.cpp34
-rw-r--r--src/qml/compiler/qv4compileddata_p.h8
-rw-r--r--src/qml/compiler/qv4jsir.cpp6
-rw-r--r--src/qml/debugger/qqmldebug.cpp10
-rw-r--r--src/qml/qml/qqmlimport.cpp39
-rw-r--r--src/qml/qml/qqmltypeloader.cpp5
-rw-r--r--src/qml/types/qqmldelegatemodel.cpp7
-rw-r--r--src/quick/items/context2d/qquickcanvasitem.cpp1
-rw-r--r--src/quick/items/context2d/qquickcontext2d.cpp2
-rw-r--r--src/quick/items/qquickpainteditem_p.h1
-rw-r--r--src/quick/items/qquickwindow.cpp13
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp9
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h2
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode.cpp128
-rw-r--r--src/quick/scenegraph/qsgdefaultglyphnode_p.h23
-rw-r--r--src/quick/util/qquickanimatorjob.cpp3
-rw-r--r--src/quickwidgets/qquickwidget.cpp2
-rw-r--r--src/src.pro2
-rw-r--r--tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp71
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/BLACKLIST2
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp2
-rw-r--r--tests/auto/quick/qquickwindow/tst_qquickwindow.cpp258
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp76
-rw-r--r--tests/auto/toolsupport/tst_toolsupport.cpp2
-rw-r--r--tools/qmlcachegen/qmlcache.prf52
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp89
-rw-r--r--tools/qmlcachegen/qmlcachegen.pro18
37 files changed, 831 insertions, 145 deletions
diff --git a/examples/qml/referenceexamples/properties/birthdayparty.cpp b/examples/qml/referenceexamples/properties/birthdayparty.cpp
index b69b7c8a11..0b426fc00b 100644
--- a/examples/qml/referenceexamples/properties/birthdayparty.cpp
+++ b/examples/qml/referenceexamples/properties/birthdayparty.cpp
@@ -57,9 +57,18 @@ void BirthdayParty::setHost(Person *c)
QQmlListProperty<Person> BirthdayParty::guests()
{
- return QQmlListProperty<Person>(this, m_guests);
+ return QQmlListProperty<Person>(this, this,
+ &BirthdayParty::appendGuest,
+ &BirthdayParty::guestCount,
+ &BirthdayParty::guest,
+ &BirthdayParty::clearGuests);
}
+void BirthdayParty::appendGuest(Person* p) {
+ m_guests.append(p);
+}
+
+
int BirthdayParty::guestCount() const
{
return m_guests.count();
@@ -69,5 +78,25 @@ Person *BirthdayParty::guest(int index) const
{
return m_guests.at(index);
}
+
+void BirthdayParty::clearGuests() {
+ return m_guests.clear();
+}
+
// ![0]
+void BirthdayParty::appendGuest(QQmlListProperty<Person>* list, Person* p) {
+ reinterpret_cast< BirthdayParty* >(list->data)->appendGuest(p);
+}
+
+void BirthdayParty::clearGuests(QQmlListProperty<Person>* list) {
+ reinterpret_cast< BirthdayParty* >(list->data)->clearGuests();
+}
+
+Person* BirthdayParty::guest(QQmlListProperty<Person>* list, int i) {
+ return reinterpret_cast< BirthdayParty* >(list->data)->guest(i);
+}
+
+int BirthdayParty::guestCount(QQmlListProperty<Person>* list) {
+ return reinterpret_cast< BirthdayParty* >(list->data)->guestCount();
+}
diff --git a/examples/qml/referenceexamples/properties/birthdayparty.h b/examples/qml/referenceexamples/properties/birthdayparty.h
index d0a2cad285..df55df3e80 100644
--- a/examples/qml/referenceexamples/properties/birthdayparty.h
+++ b/examples/qml/referenceexamples/properties/birthdayparty.h
@@ -41,6 +41,7 @@
#define BIRTHDAYPARTY_H
#include <QObject>
+#include <QVector>
#include <QQmlListProperty>
#include "person.h"
@@ -63,12 +64,19 @@ public:
void setHost(Person *);
QQmlListProperty<Person> guests();
+ void appendGuest(Person*);
int guestCount() const;
Person *guest(int) const;
+ void clearGuests();
private:
+ static void appendGuest(QQmlListProperty<Person>*, Person*);
+ static int guestCount(QQmlListProperty<Person>*);
+ static Person* guest(QQmlListProperty<Person>*, int);
+ static void clearGuests(QQmlListProperty<Person>*);
+
Person *m_host;
- QList<Person *> m_guests;
+ QVector<Person *> m_guests;
};
// ![3]
diff --git a/src/3rdparty/masm/assembler/X86Assembler.h b/src/3rdparty/masm/assembler/X86Assembler.h
index e79cea7414..b71cf290f8 100644
--- a/src/3rdparty/masm/assembler/X86Assembler.h
+++ b/src/3rdparty/masm/assembler/X86Assembler.h
@@ -253,6 +253,7 @@ public:
{
}
+#if defined(V4_BOOTSTRAP)
template <typename LabelType>
class Jump {
template<class TemplateAssemblerType>
@@ -291,6 +292,7 @@ public:
private:
AssemblerLabel m_label;
};
+#endif
// Stack operations:
diff --git a/src/imports/imports.pro b/src/imports/imports.pro
index 45719df874..0ba949f070 100644
--- a/src/imports/imports.pro
+++ b/src/imports/imports.pro
@@ -20,7 +20,7 @@ qtHaveModule(quick) {
sharedimage \
testlib
- qtConfig(quick-sprite):qtConfig(opengl(es1|es2)?): \
+ qtConfig(quick-shadereffect):qtConfig(quick-sprite):qtConfig(opengl(es1|es2)?): \
SUBDIRS += particles
}
diff --git a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
index 5cc2043cb1..75cbc9eba1 100644
--- a/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
+++ b/src/plugins/qmltooling/qmldbg_debugger/qv4debugger.cpp
@@ -230,7 +230,12 @@ void QV4Debugger::leavingFunction(const QV4::ReturnedValue &retVal)
QMutexLocker locker(&m_lock);
if (m_stepping != NotStepping && m_currentContext.asManaged()->d() == m_engine->current) {
- m_currentContext.set(m_engine, *m_engine->parentContext(m_engine->currentContext));
+ if (QV4::ExecutionContext *parentContext
+ = m_engine->parentContext(m_engine->currentContext)) {
+ m_currentContext.set(m_engine, *parentContext);
+ } else {
+ m_currentContext.clear();
+ }
m_stepping = StepOver;
m_returnedValue.set(m_engine, retVal);
}
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp
index dd630c776f..df47e920af 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp
+++ b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.cpp
@@ -94,7 +94,7 @@ void QSGOpenVGFontGlyphCache::populate(const QVector<quint32> &glyphs)
referencedGlyphs.insert(glyphIndex);
- if (!m_cachedGlyphs.contains(glyphIndex)) {
+ if (!m_glyphReferences.contains(glyphIndex)) {
newGlyphs.insert(glyphIndex);
}
}
@@ -119,17 +119,9 @@ void QSGOpenVGFontGlyphCache::requestGlyphs(const QSet<quint32> &glyphs)
{
VGfloat origin[2];
VGfloat escapement[2];
- QRectF metrics;
QRawFont rawFont = m_referenceFont;
- // Before adding any new glyphs, remove any unused glyphs
- for (auto glyph : qAsConst(m_unusedGlyphs)) {
- vgClearGlyph(m_font, glyph);
- }
-
for (auto glyph : glyphs) {
- m_cachedGlyphs.insert(glyph);
-
// Calculate the path for the glyph and cache it.
QPainterPath path = rawFont.pathForGlyph(glyph);
VGPath vgPath;
@@ -151,12 +143,23 @@ void QSGOpenVGFontGlyphCache::requestGlyphs(const QSet<quint32> &glyphs)
void QSGOpenVGFontGlyphCache::referenceGlyphs(const QSet<quint32> &glyphs)
{
- m_unusedGlyphs -= glyphs;
+ for (auto glyph : glyphs) {
+ if (m_glyphReferences.contains(glyph))
+ m_glyphReferences[glyph] += 1;
+ else
+ m_glyphReferences.insert(glyph, 1);
+ }
}
void QSGOpenVGFontGlyphCache::releaseGlyphs(const QSet<quint32> &glyphs)
{
- m_unusedGlyphs += glyphs;
+ for (auto glyph : glyphs) {
+ int references = m_glyphReferences[glyph] -= 1;
+ if (references == 0) {
+ vgClearGlyph(m_font, glyph);
+ m_glyphReferences.remove(glyph);
+ }
+ }
}
QT_END_NAMESPACE
diff --git a/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h
index a88d28b0fe..107ec0c892 100644
--- a/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h
+++ b/src/plugins/scenegraph/openvg/qsgopenvgfontglyphcache.h
@@ -87,8 +87,7 @@ private:
int m_glyphCount;
VGFont m_font;
- QSet<quint32> m_cachedGlyphs;
- QSet<quint32> m_unusedGlyphs;
+ QHash<quint32, int> m_glyphReferences;
};
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 030f485504..18fccc8f43 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -2116,7 +2116,8 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
object->indexOfDefaultPropertyOrAlias = serializedObject->indexOfDefaultPropertyOrAlias;
object->defaultPropertyIsAlias = serializedObject->defaultPropertyIsAlias;
-
+ object->flags = serializedObject->flags;
+ object->id = serializedObject->id;
object->location = serializedObject->location;
object->locationOfIdProperty = serializedObject->locationOfIdProperty;
@@ -2175,6 +2176,15 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
object->properties->append(p);
}
+ {
+ const QV4::CompiledData::Alias *serializedAlias = serializedObject->aliasTable();
+ for (uint i = 0; i < serializedObject->nAliases; ++i, ++serializedAlias) {
+ QmlIR::Alias *a = pool->New<QmlIR::Alias>();
+ *static_cast<QV4::CompiledData::Alias*>(a) = *serializedAlias;
+ object->aliases->append(a);
+ }
+ }
+
QQmlJS::Engine *jsParserEngine = &output->jsParserEngine;
const QV4::CompiledData::LEUInt32 *functionIdx = serializedObject->functionOffsetTable();
@@ -2205,6 +2215,11 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO
const QString name = unit->stringAt(compiledFunction->nameIndex);
f->functionDeclaration = new(pool) QQmlJS::AST::FunctionDeclaration(jsParserEngine->newStringRef(name), paramList, /*body*/0);
+ f->formals.allocate(pool, int(compiledFunction->nFormals));
+ formalNameIdx = compiledFunction->formalsTable();
+ for (uint i = 0; i < compiledFunction->nFormals; ++i, ++formalNameIdx)
+ f->formals[i] = *formalNameIdx;
+
object->functions->append(f);
}
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 0afc97e4bf..ecec0cf49a 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -2269,7 +2269,7 @@ bool Codegen::visit(DoWhileStatement *ast)
_block = loopbody;
statement(ast->statement);
- _block->JUMP(loopcond);
+ setLocation(_block->JUMP(loopcond), ast->statement->lastSourceLocation());
_block = loopcond;
condition(ast->expression, loopbody, loopend);
@@ -2334,7 +2334,7 @@ bool Codegen::visit(ForEachStatement *ast)
return false;
move(*init, _block->TEMP(temp));
statement(ast->statement);
- _block->JUMP(foreachin);
+ setLocation(_block->JUMP(foreachin), ast->lastSourceLocation());
_block = foreachin;
@@ -2373,7 +2373,7 @@ bool Codegen::visit(ForStatement *ast)
_block = forbody;
statement(ast->statement);
- _block->JUMP(forstep);
+ setLocation(_block->JUMP(forstep), ast->lastSourceLocation());
_block = forstep;
statement(ast->expression);
@@ -2473,7 +2473,7 @@ bool Codegen::visit(LocalForEachStatement *ast)
int temp = _block->newTemp();
move(identifier(ast->declaration->name.toString()), _block->TEMP(temp));
statement(ast->statement);
- _block->JUMP(foreachin);
+ setLocation(_block->JUMP(foreachin), ast->lastSourceLocation());
_block = foreachin;
@@ -2512,7 +2512,7 @@ bool Codegen::visit(LocalForStatement *ast)
_block = forbody;
statement(ast->statement);
- _block->JUMP(forstep);
+ setLocation(_block->JUMP(forstep), ast->lastSourceLocation());
_block = forstep;
statement(ast->expression);
@@ -2813,7 +2813,7 @@ bool Codegen::visit(WhileStatement *ast)
_block = whilebody;
statement(ast->statement);
- _block->JUMP(whilecond);
+ setLocation(_block->JUMP(whilecond), ast->lastSourceLocation());
_block = whileend;
leaveLoop();
diff --git a/src/qml/compiler/qv4compilationunitmapper.cpp b/src/qml/compiler/qv4compilationunitmapper.cpp
index 2e1213464c..1ae0fb190c 100644
--- a/src/qml/compiler/qv4compilationunitmapper.cpp
+++ b/src/qml/compiler/qv4compilationunitmapper.cpp
@@ -76,7 +76,7 @@ bool CompilationUnitMapper::verifyHeader(const CompiledData::Unit *header, const
return false;
}
- {
+ if (header->sourceTimeStamp) {
QFileInfo sourceCode(sourcePath);
QDateTime sourceTimeStamp;
if (sourceCode.exists())
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp
index d0dfb81f80..0cee2996d7 100644
--- a/src/qml/compiler/qv4compileddata.cpp
+++ b/src/qml/compiler/qv4compileddata.cpp
@@ -77,13 +77,7 @@ namespace QV4 {
namespace CompiledData {
-#ifdef V4_BOOTSTRAP
-static QString cacheFilePath(const QString &localSourcePath)
-{
- const QString localCachePath = localSourcePath + QLatin1Char('c');
- return localCachePath;
-}
-#else
+#if !defined(V4_BOOTSTRAP)
static QString cacheFilePath(const QUrl &url)
{
const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url);
@@ -101,8 +95,8 @@ static QString cacheFilePath(const QUrl &url)
#ifndef V4_BOOTSTRAP
CompilationUnit::CompilationUnit()
: data(0)
- , engine(0)
, runtimeStrings(0)
+ , engine(0)
, runtimeLookups(0)
, runtimeRegularExpressions(0)
, runtimeClasses(0)
@@ -374,7 +368,7 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, EvalISelFactory *iselFactory
const Unit * const oldDataPtr = (data && !(data->flags & QV4::CompiledData::Unit::StaticData)) ? data : nullptr;
QScopedValueRollback<const Unit *> dataPtrChange(data, mappedUnit);
- if (sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
+ if (data->sourceFileIndex != 0 && sourcePath != QQmlFile::urlToLocalFileOrQrc(stringAt(data->sourceFileIndex))) {
*errorString = QStringLiteral("QML source file has moved to a different location.");
return false;
}
@@ -415,28 +409,29 @@ bool CompilationUnit::memoryMapCode(QString *errorString)
#endif // V4_BOOTSTRAP
#if defined(V4_BOOTSTRAP)
-bool CompilationUnit::saveToDisk(const QString &unitUrl, QString *errorString)
+bool CompilationUnit::saveToDisk(const QString &outputFileName, QString *errorString)
#else
bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString)
#endif
{
errorString->clear();
+#if !defined(V4_BOOTSTRAP)
if (data->sourceTimeStamp == 0) {
*errorString = QStringLiteral("Missing time stamp for source file");
return false;
}
-#if !defined(V4_BOOTSTRAP)
if (!QQmlFile::isLocalFile(unitUrl)) {
*errorString = QStringLiteral("File has to be a local file.");
return false;
}
+ const QString outputFileName = cacheFilePath(unitUrl);
#endif
#if QT_CONFIG(temporaryfile)
// Foo.qml -> Foo.qmlc
- QSaveFile cacheFile(cacheFilePath(unitUrl));
+ QSaveFile cacheFile(outputFileName);
if (!cacheFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
*errorString = cacheFile.errorString();
return false;
@@ -492,10 +487,22 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
return irDocument->jsGenerator.generateUnit(QV4::Compiler::JSUnitGenerator::GenerateWithoutStringTable);
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit = irDocument->javaScriptCompilationUnit;
- QV4::CompiledData::Unit *jsUnit = const_cast<QV4::CompiledData::Unit*>(irDocument->javaScriptCompilationUnit->data);
+ QV4::CompiledData::Unit *jsUnit = const_cast<QV4::CompiledData::Unit*>(compilationUnit->data);
+ auto ensureWritableUnit = [&jsUnit, &compilationUnit]() {
+ if (jsUnit == compilationUnit->data) {
+ char *unitCopy = (char*)malloc(jsUnit->unitSize);
+ memcpy(unitCopy, jsUnit, jsUnit->unitSize);
+ jsUnit = reinterpret_cast<QV4::CompiledData::Unit*>(unitCopy);
+ }
+ };
QV4::Compiler::StringTableGenerator &stringTable = irDocument->jsGenerator.stringTable;
+ if (jsUnit->sourceFileIndex == quint32(0) || jsUnit->stringAt(jsUnit->sourceFileIndex) != irDocument->jsModule.fileName) {
+ ensureWritableUnit();
+ jsUnit->sourceFileIndex = stringTable.registerString(irDocument->jsModule.fileName);
+ }
+
// Collect signals that have had a change in signature (from onClicked to onClicked(mouse) for example)
// and now need fixing in the QV4::CompiledData. Also register strings at the same time, to finalize
// the string table.
@@ -558,6 +565,7 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
}
if (!signalParameterNameTable.isEmpty()) {
+ ensureWritableUnit();
Q_ASSERT(jsUnit != compilationUnit->data);
const uint signalParameterTableSize = signalParameterNameTable.count() * sizeof(quint32);
uint newSize = jsUnit->unitSize + signalParameterTableSize;
diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h
index a1833f2937..48c78c6a01 100644
--- a/src/qml/compiler/qv4compileddata_p.h
+++ b/src/qml/compiler/qv4compileddata_p.h
@@ -817,13 +817,11 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
// Called only when building QML, when we build the header for JS first and append QML data
virtual QV4::CompiledData::Unit *createUnitData(QmlIR::Document *irDocument);
-#ifndef V4_BOOTSTRAP
- ExecutionEngine *engine;
-#endif
-
QV4::Heap::String **runtimeStrings; // Array
#ifndef V4_BOOTSTRAP
+ ExecutionEngine *engine;
+
QString fileName() const { return data->stringAt(data->sourceFileIndex); }
QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; }
@@ -909,7 +907,7 @@ protected:
public:
#if defined(V4_BOOTSTRAP)
- bool saveToDisk(const QString &unitUrl, QString *errorString);
+ bool saveToDisk(const QString &outputFileName, QString *errorString);
#else
bool saveToDisk(const QUrl &unitUrl, QString *errorString);
#endif
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 5687834b00..cc2f9b7cf2 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -348,11 +348,7 @@ Module::~Module()
void Module::setFileName(const QString &name)
{
- if (fileName.isEmpty())
- fileName = name;
- else {
- Q_ASSERT(fileName == name);
- }
+ fileName = name;
}
Function::Function(Module *module, Function *outer, const QString &name)
diff --git a/src/qml/debugger/qqmldebug.cpp b/src/qml/debugger/qqmldebug.cpp
index 15230d75a5..681dc06215 100644
--- a/src/qml/debugger/qqmldebug.cpp
+++ b/src/qml/debugger/qqmldebug.cpp
@@ -42,6 +42,7 @@
#include "qqmldebugserviceinterfaces_p.h"
#include <private/qqmlengine_p.h>
+#include <private/qv4compileddata_p.h>
QT_BEGIN_NAMESPACE
@@ -181,12 +182,12 @@ bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName,
return connector ? connector->open(configuration) : false;
}
-enum { HookCount = 3 };
+enum { HookCount = 4 };
// Only add to the end, and bump version if you do.
quintptr Q_QML_EXPORT qtDeclarativeHookData[] = {
// Version of this Array. Bump if you add to end.
- 1,
+ 2,
// Number of entries in this array.
HookCount,
@@ -194,7 +195,10 @@ quintptr Q_QML_EXPORT qtDeclarativeHookData[] = {
// TypeInformationVersion, an integral value, bumped whenever private
// object sizes or member offsets that are used in Qt Creator's
// data structure "pretty printing" change.
- 2
+ 3,
+
+ // Version of the cache data.
+ QV4_DATA_STRUCTURE_VERSION
};
Q_STATIC_ASSERT(HookCount == sizeof(qtDeclarativeHookData) / sizeof(qtDeclarativeHookData[0]));
diff --git a/src/qml/qml/qqmlimport.cpp b/src/qml/qml/qqmlimport.cpp
index c07d5c740a..ee5b38717b 100644
--- a/src/qml/qml/qqmlimport.cpp
+++ b/src/qml/qml/qqmlimport.cpp
@@ -210,7 +210,6 @@ QQmlType *fetchOrCreateTypeForUrl(const QString &urlString, const QHashedStringR
} // namespace
-#if QT_CONFIG(library)
struct RegisteredPlugin {
QString uri;
QPluginLoader* loader;
@@ -221,21 +220,23 @@ struct StringRegisteredPluginMap : public QMap<QString, RegisteredPlugin> {
};
Q_GLOBAL_STATIC(StringRegisteredPluginMap, qmlEnginePluginsWithRegisteredTypes); // stores the uri and the PluginLoaders
+
void qmlClearEnginePlugins()
{
StringRegisteredPluginMap *plugins = qmlEnginePluginsWithRegisteredTypes();
QMutexLocker lock(&plugins->mutex);
+#if QT_CONFIG(library)
for (auto &plugin : qAsConst(*plugins)) {
QPluginLoader* loader = plugin.loader;
if (loader && !loader->unload())
qWarning("Unloading %s failed: %s", qPrintable(plugin.uri), qPrintable(loader->errorString()));
delete loader;
}
+#endif
plugins->clear();
}
typedef QPair<QStaticPlugin, QJsonArray> StaticPluginPair;
-#endif
/*!
\internal
@@ -332,10 +333,9 @@ public:
const QString &uri, const QString &url,
int vmaj, int vmin, QV4::CompiledData::Import::ImportType type,
QList<QQmlError> *errors, bool lowPrecedence = false);
-#if QT_CONFIG(library)
- bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
+
+ bool populatePluginPairVector(QVector<StaticPluginPair> &result, const QString &uri, const QStringList &versionUris,
const QString &qmldirPath, QList<QQmlError> *errors);
-#endif
};
/*!
@@ -959,7 +959,6 @@ static QStringList versionUriList(const QString &uri, int vmaj, int vmin)
return result;
}
-#if QT_CONFIG(library)
static QVector<QStaticPlugin> makePlugins()
{
QVector<QStaticPlugin> plugins;
@@ -1009,7 +1008,6 @@ bool QQmlImportsPrivate::populatePluginPairVector(QVector<StaticPluginPair> &res
}
return true;
}
-#endif
#if defined(QT_SHARED) || !QT_CONFIG(library)
static inline QString msgCannotLoadPlugin(const QString &uri, const QString &why)
@@ -1030,7 +1028,6 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
const QQmlTypeLoaderQmldirContent *qmldir,
QList<QQmlError> *errors)
{
-#if QT_CONFIG(library)
Q_ASSERT(qmldir);
if (qmlImportTrace())
@@ -1143,22 +1140,6 @@ bool QQmlImportsPrivate::importExtension(const QString &qmldirFilePath,
database->qmlDirFilesForWhichPluginsHaveBeenLoaded.insert(qmldirFilePath);
}
-
-#else
- Q_UNUSED(vmaj);
- Q_UNUSED(vmin);
- Q_UNUSED(database);
- Q_UNUSED(qmldir);
-
- if (errors) {
- QQmlError error;
- error.setDescription(msgCannotLoadPlugin(uri, QQmlImportDatabase::tr("library loading is disabled")));
- error.setUrl(QUrl::fromLocalFile(qmldirFilePath));
- errors->prepend(error);
- }
-
- return false;
-#endif // library
return true;
}
@@ -2014,7 +1995,6 @@ bool QQmlImportDatabase::registerPluginTypes(QObject *instance, const QString &b
bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &basePath,
const QString &uri, const QString &typeNamespace, int vmaj, QList<QQmlError> *errors)
{
-#if QT_CONFIG(library)
// Dynamic plugins are differentiated by their filepath. For static plugins we
// don't have that information so we use their address as key instead.
const QString uniquePluginID = QString::asprintf("%p", instance);
@@ -2050,15 +2030,6 @@ bool QQmlImportDatabase::importStaticPlugin(QObject *instance, const QString &ba
}
return true;
-#else
- Q_UNUSED(instance);
- Q_UNUSED(basePath);
- Q_UNUSED(uri);
- Q_UNUSED(typeNamespace);
- Q_UNUSED(vmaj);
- Q_UNUSED(errors);
- return false;
-#endif
}
/*!
diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp
index f4f04e12c0..68eb989c70 100644
--- a/src/qml/qml/qqmltypeloader.cpp
+++ b/src/qml/qml/qqmltypeloader.cpp
@@ -2407,6 +2407,7 @@ void QQmlTypeData::restoreIR(QQmlRefPointer<QV4::CompiledData::CompilationUnit>
m_document.reset(new QmlIR::Document(isDebugging()));
QmlIR::IRLoader loader(unit->data, m_document.data());
loader.load();
+ m_document->jsModule.setFileName(finalUrlString());
m_document->javaScriptCompilationUnit = unit;
continueLoadFromIR();
}
@@ -2507,6 +2508,8 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach
{
Q_ASSERT(m_compiledData.isNull());
+ const bool typeRecompilation = m_document && m_document->javaScriptCompilationUnit && m_document->javaScriptCompilationUnit->data->flags & QV4::CompiledData::Unit::PendingTypeCompilation;
+
QQmlEnginePrivate * const enginePrivate = QQmlEnginePrivate::get(typeLoader()->engine());
QQmlTypeCompiler compiler(enginePrivate, this, m_document.data(), typeNameCache, resolvedTypeCache);
m_compiledData = compiler.compile();
@@ -2515,7 +2518,7 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach
return;
}
- const bool trySaveToDisk = (!disableDiskCache() || forceDiskCache()) && !m_document->jsModule.debugMode;
+ const bool trySaveToDisk = (!disableDiskCache() || forceDiskCache()) && !m_document->jsModule.debugMode && !typeRecompilation;
if (trySaveToDisk) {
QString errorString;
if (m_compiledData->saveToDisk(url(), &errorString)) {
diff --git a/src/qml/types/qqmldelegatemodel.cpp b/src/qml/types/qqmldelegatemodel.cpp
index a5878dcffd..34bc266cb5 100644
--- a/src/qml/types/qqmldelegatemodel.cpp
+++ b/src/qml/types/qqmldelegatemodel.cpp
@@ -837,10 +837,9 @@ void QQDMIncubationTask::statusChanged(Status status)
} else if (isDoneIncubating(status)) {
Q_ASSERT(incubating);
// The model was deleted from under our feet, cleanup ourselves
- if (incubating->object) {
- delete incubating->object;
-
- incubating->object = 0;
+ delete incubating->object;
+ incubating->object = 0;
+ if (incubating->contextData) {
incubating->contextData->destroy();
incubating->contextData = 0;
}
diff --git a/src/quick/items/context2d/qquickcanvasitem.cpp b/src/quick/items/context2d/qquickcanvasitem.cpp
index 1167f408f5..a81ab619ac 100644
--- a/src/quick/items/context2d/qquickcanvasitem.cpp
+++ b/src/quick/items/context2d/qquickcanvasitem.cpp
@@ -44,6 +44,7 @@
#include <private/qquickcontext2d_p.h>
#include <private/qquickcontext2dtexture_p.h>
#include <private/qsgadaptationlayer_p.h>
+#include <qsgtextureprovider.h>
#include <QtQuick/private/qquickpixmapcache_p.h>
#include <QtGui/QGuiApplication>
diff --git a/src/quick/items/context2d/qquickcontext2d.cpp b/src/quick/items/context2d/qquickcontext2d.cpp
index b9b701313e..cf34523693 100644
--- a/src/quick/items/context2d/qquickcontext2d.cpp
+++ b/src/quick/items/context2d/qquickcontext2d.cpp
@@ -42,7 +42,9 @@
#include "qquickcanvasitem_p.h"
#include <private/qquickcontext2dtexture_p.h>
#include <private/qquickitem_p.h>
+#if QT_CONFIG(quick_shadereffect)
#include <QtQuick/private/qquickshadereffectsource_p.h>
+#endif
#include <qsgrendererinterface.h>
#include <QtQuick/private/qsgcontext_p.h>
diff --git a/src/quick/items/qquickpainteditem_p.h b/src/quick/items/qquickpainteditem_p.h
index 742e786335..229fbf1007 100644
--- a/src/quick/items/qquickpainteditem_p.h
+++ b/src/quick/items/qquickpainteditem_p.h
@@ -52,6 +52,7 @@
//
#include "qquickitem_p.h"
+#include "qquickpainteditem.h"
#include <QtGui/qcolor.h>
QT_BEGIN_NAMESPACE
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp
index 4dc8cd0a37..e6245f90f3 100644
--- a/src/quick/items/qquickwindow.cpp
+++ b/src/quick/items/qquickwindow.cpp
@@ -2397,7 +2397,6 @@ void QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QEvent *e
} else for (; grabItem != grabber->end(); grabItem = grabber->release(grabItem)) {
QDragMoveEvent *moveEvent = static_cast<QDragMoveEvent *>(event);
if (deliverDragEvent(grabber, **grabItem, moveEvent)) {
- moveEvent->setAccepted(true);
for (++grabItem; grabItem != grabber->end();) {
QPointF p = (**grabItem)->mapFromScene(moveEvent->pos());
if ((**grabItem)->contains(p)) {
@@ -2472,7 +2471,10 @@ bool QQuickWindowPrivate::deliverDragEvent(QQuickDragGrabber *grabber, QQuickIte
event->keyboardModifiers(),
event->type());
QQuickDropEventEx::copyActions(&translatedEvent, *event);
+ translatedEvent.setAccepted(event->isAccepted());
QCoreApplication::sendEvent(item, &translatedEvent);
+ event->setAccepted(translatedEvent.isAccepted());
+ event->setDropAction(translatedEvent.dropAction());
if (event->type() == QEvent::DragEnter) {
if (translatedEvent.isAccepted()) {
grabber->grab(item);
@@ -2593,9 +2595,14 @@ bool QQuickWindowPrivate::sendFilteredTouchEvent(QQuickItem *target, QQuickItem
qCDebug(DBG_TOUCH) << " - second chance intercepted on childMouseEventFilter by " << target;
if (t != QEvent::MouseButtonRelease) {
qCDebug(DBG_TOUCH_TARGET) << "TP" << tp.id() << "->" << target;
- touchMouseId = tp.id();
touchMouseDevice = event->device();
- touchMouseDevice->pointerEvent()->pointById(tp.id())->setGrabber(target);
+ if (touchMouseId == -1) {
+ // the point was grabbed as a pure touch point before, now it will be treated as mouse
+ // but the old receiver still needs to be informed
+ if (auto oldGrabber = touchMouseDevice->pointerEvent()->pointById(tp.id())->grabber())
+ oldGrabber->touchUngrabEvent();
+ }
+ touchMouseId = tp.id();
target->grabMouse();
}
filtered = true;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
index 6856d34616..b3b8274a73 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop.cpp
@@ -101,7 +101,7 @@ void QSGSoftwareRenderLoop::windowDestroyed(QQuickWindow *window)
}
}
-void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
+void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window, bool isNewExpose)
{
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(window);
if (!m_windows.contains(window))
@@ -174,7 +174,10 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
if (alsoSwap && window->isVisible()) {
//Flush backingstore to window
- m_backingStores[window]->flush(softwareRenderer->flushRegion());
+ if (!isNewExpose)
+ m_backingStores[window]->flush(softwareRenderer->flushRegion());
+ else
+ m_backingStores[window]->flush(QRegion(QRect(QPoint(0,0), window->size())));
cd->fireFrameSwapped();
}
@@ -206,7 +209,7 @@ void QSGSoftwareRenderLoop::exposureChanged(QQuickWindow *window)
{
if (window->isExposed()) {
m_windows[window].updatePending = true;
- renderWindow(window);
+ renderWindow(window, true);
}
}
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h
index 02dcf4eefa..c724d18298 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarerenderloop_p.h
@@ -69,7 +69,7 @@ public:
void windowDestroyed(QQuickWindow *window) override;
- void renderWindow(QQuickWindow *window);
+ void renderWindow(QQuickWindow *window, bool isNewExpose = false);
void exposureChanged(QQuickWindow *window) override;
QImage grab(QQuickWindow *window) override;
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode.cpp b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
index b856d99bc1..0d42102f36 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode.cpp
+++ b/src/quick/scenegraph/qsgdefaultglyphnode.cpp
@@ -42,11 +42,33 @@
QT_BEGIN_NAMESPACE
+QSGDefaultGlyphNode::QSGDefaultGlyphNode()
+ : m_glyphNodeType(RootGlyphNode)
+ , m_dirtyGeometry(false)
+{
+ setFlag(UsePreprocess);
+}
+
+QSGDefaultGlyphNode::~QSGDefaultGlyphNode()
+{
+ if (m_glyphNodeType == SubGlyphNode)
+ return;
+
+ qDeleteAll(m_nodesToDelete);
+ m_nodesToDelete.clear();
+}
+
void QSGDefaultGlyphNode::setMaterialColor(const QColor &color)
{
static_cast<QSGTextMaskMaterial *>(m_material)->setColor(color);
}
+void QSGDefaultGlyphNode::setGlyphs(const QPointF &position, const QGlyphRun &glyphs)
+{
+ QSGBasicGlyphNode::setGlyphs(position, glyphs);
+ m_dirtyGeometry = true;
+}
+
void QSGDefaultGlyphNode::update()
{
QRawFont font = m_glyphs.rawFont();
@@ -84,4 +106,110 @@ void QSGDefaultGlyphNode::update()
markDirty(DirtyGeometry);
}
+void QSGDefaultGlyphNode::preprocess()
+{
+ qDeleteAll(m_nodesToDelete);
+ m_nodesToDelete.clear();
+
+ if (m_dirtyGeometry)
+ updateGeometry();
+}
+
+void QSGDefaultGlyphNode::updateGeometry()
+{
+ // Remove previously created sub glyph nodes
+ // We assume all the children are sub glyph nodes
+ QSGNode *subnode = firstChild();
+ while (subnode) {
+ // We can't delete the node now as it might be in the preprocess list
+ // It will be deleted in the next preprocess
+ m_nodesToDelete.append(subnode);
+ subnode = subnode->nextSibling();
+ }
+ removeAllChildNodes();
+
+ GlyphInfo glyphInfo;
+
+ const QVector<quint32> indexes = m_glyphs.glyphIndexes();
+ const QVector<QPointF> positions = m_glyphs.positions();
+
+ const int maxGlyphs = (USHRT_MAX + 1) / 4; // 16384
+ const int maxVertices = maxGlyphs * 4; // 65536
+ const int maxIndexes = maxGlyphs * 6; // 98304
+
+ for (int i = 0; i < indexes.size(); ++i) {
+ const int glyphIndex = indexes.at(i);
+ const QPointF position = positions.at(i);
+
+ // As we use UNSIGNED_SHORT indexing in the geometry, we overload the
+ // "glyphsInOtherNodes" concept as overflow for if there are more than
+ // 65536 (16384 * 4) vertices to render which would otherwise exceed
+ // the maximum index size. This will cause sub-nodes to be recursively
+ // created to handle any number of glyphs.
+ if (i >= maxGlyphs) {
+ glyphInfo.indexes.append(glyphIndex);
+ glyphInfo.positions.append(position);
+ continue;
+ }
+ }
+
+ if (!glyphInfo.indexes.isEmpty()) {
+ QGlyphRun subNodeGlyphRun(m_glyphs);
+ subNodeGlyphRun.setGlyphIndexes(glyphInfo.indexes);
+ subNodeGlyphRun.setPositions(glyphInfo.positions);
+
+ QSGDefaultGlyphNode *subNode = new QSGDefaultGlyphNode();
+ subNode->setGlyphNodeType(SubGlyphNode);
+ subNode->setColor(m_color);
+ subNode->setStyle(m_style);
+ subNode->setStyleColor(m_styleColor);
+ subNode->setGlyphs(m_position, subNodeGlyphRun);
+ subNode->update();
+ subNode->updateGeometry(); // we have to explicitly call this now as preprocess won't be called before it's rendered
+ appendChildNode(subNode);
+
+ QSGGeometry *g = geometry();
+
+ QSGGeometry::TexturedPoint2D *vertexData = g->vertexDataAsTexturedPoint2D();
+ quint16 *indexData = g->indexDataAsUShort();
+
+ QVector<QSGGeometry::TexturedPoint2D> tempVertexData(maxVertices);
+ QVector<quint16> tempIndexData(maxIndexes);
+
+ for (int i = 0; i < maxGlyphs; i++) {
+ tempVertexData[i * 4 + 0] = vertexData[i * 4 + 0];
+ tempVertexData[i * 4 + 1] = vertexData[i * 4 + 1];
+ tempVertexData[i * 4 + 2] = vertexData[i * 4 + 2];
+ tempVertexData[i * 4 + 3] = vertexData[i * 4 + 3];
+
+ tempIndexData[i * 6 + 0] = indexData[i * 6 + 0];
+ tempIndexData[i * 6 + 1] = indexData[i * 6 + 1];
+ tempIndexData[i * 6 + 2] = indexData[i * 6 + 2];
+ tempIndexData[i * 6 + 3] = indexData[i * 6 + 3];
+ tempIndexData[i * 6 + 4] = indexData[i * 6 + 4];
+ tempIndexData[i * 6 + 5] = indexData[i * 6 + 5];
+ }
+
+ g->allocate(maxVertices, maxIndexes);
+ vertexData = g->vertexDataAsTexturedPoint2D();
+ indexData = g->indexDataAsUShort();
+
+ for (int i = 0; i < maxGlyphs; i++) {
+ vertexData[i * 4 + 0] = tempVertexData[i * 4 + 0];
+ vertexData[i * 4 + 1] = tempVertexData[i * 4 + 1];
+ vertexData[i * 4 + 2] = tempVertexData[i * 4 + 2];
+ vertexData[i * 4 + 3] = tempVertexData[i * 4 + 3];
+
+ indexData[i * 6 + 0] = tempIndexData[i * 6 + 0];
+ indexData[i * 6 + 1] = tempIndexData[i * 6 + 1];
+ indexData[i * 6 + 2] = tempIndexData[i * 6 + 2];
+ indexData[i * 6 + 3] = tempIndexData[i * 6 + 3];
+ indexData[i * 6 + 4] = tempIndexData[i * 6 + 4];
+ indexData[i * 6 + 5] = tempIndexData[i * 6 + 5];
+ }
+ }
+
+ m_dirtyGeometry = false;
+}
+
QT_END_NAMESPACE
diff --git a/src/quick/scenegraph/qsgdefaultglyphnode_p.h b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
index 0eb7a4e4bd..37a89c70b9 100644
--- a/src/quick/scenegraph/qsgdefaultglyphnode_p.h
+++ b/src/quick/scenegraph/qsgdefaultglyphnode_p.h
@@ -59,8 +59,31 @@ QT_BEGIN_NAMESPACE
class QSGDefaultGlyphNode : public QSGBasicGlyphNode
{
public:
+ QSGDefaultGlyphNode();
+ ~QSGDefaultGlyphNode();
void setMaterialColor(const QColor &color) override;
+ void setGlyphs(const QPointF &position, const QGlyphRun &glyphs) override;
void update() override;
+ void preprocess() override;
+ void updateGeometry();
+
+private:
+ enum DefaultGlyphNodeType {
+ RootGlyphNode,
+ SubGlyphNode
+ };
+
+ void setGlyphNodeType(DefaultGlyphNodeType type) { m_glyphNodeType = type; }
+
+ DefaultGlyphNodeType m_glyphNodeType;
+ QLinkedList<QSGNode *> m_nodesToDelete;
+
+ struct GlyphInfo {
+ QVector<quint32> indexes;
+ QVector<QPointF> positions;
+ };
+
+ uint m_dirtyGeometry: 1;
};
QT_END_NAMESPACE
diff --git a/src/quick/util/qquickanimatorjob.cpp b/src/quick/util/qquickanimatorjob.cpp
index 4aacb09c97..89007cff1f 100644
--- a/src/quick/util/qquickanimatorjob.cpp
+++ b/src/quick/util/qquickanimatorjob.cpp
@@ -345,12 +345,13 @@ void QQuickTransformAnimatorJob::postSync()
}
QQuickItemPrivate *d = QQuickItemPrivate::get(m_target);
+#if QT_CONFIG(quick_shadereffect)
if (d->extra.isAllocated()
&& d->extra->layer
&& d->extra->layer->enabled()) {
d = QQuickItemPrivate::get(d->extra->layer->m_effectSource);
}
-
+#endif
m_helper->node = d->itemNode();
}
diff --git a/src/quickwidgets/qquickwidget.cpp b/src/quickwidgets/qquickwidget.cpp
index 4ed41a0c6c..ea02723db8 100644
--- a/src/quickwidgets/qquickwidget.cpp
+++ b/src/quickwidgets/qquickwidget.cpp
@@ -1140,7 +1140,7 @@ QSize QQuickWidget::initialSize() const
/*!
Returns the view's root \l {QQuickItem} {item}. Can be null
- when setContents/setSource has not been called, if they were called with
+ when setSource() has not been called, if it was called with
broken QtQuick code or while the QtQuick contents are being created.
*/
QQuickItem *QQuickWidget::rootObject() const
diff --git a/src/src.pro b/src/src.pro
index 4e2de8da14..24e139415b 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -10,7 +10,7 @@ qtHaveModule(gui):qtConfig(animation) {
quick \
qmltest
- qtConfig(quick-sprite):qtConfig(opengl(es1|es2)?): \
+ qtConfig(quick-shadereffect):qtConfig(quick-sprite):qtConfig(opengl(es1|es2)?): \
SUBDIRS += particles
qtHaveModule(widgets): SUBDIRS += quickwidgets
}
diff --git a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
index 6793596174..56320b8365 100644
--- a/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
+++ b/tests/auto/qml/debugger/qv4debugger/tst_qv4debugger.cpp
@@ -176,6 +176,7 @@ public:
, m_captureContextInfo(false)
, m_thrownValue(-1)
, collector(engine)
+ , m_resumeSpeed(QV4Debugger::FullThrottle)
, m_debugger(0)
{
}
@@ -214,7 +215,7 @@ public slots:
if (m_captureContextInfo)
captureContextInfo(debugger);
- debugger->resume(QV4Debugger::FullThrottle);
+ debugger->resume(m_resumeSpeed);
}
public:
@@ -280,6 +281,7 @@ public:
int context;
};
QVector<ExpressionRequest> m_expressionRequests;
+ QV4Debugger::Speed m_resumeSpeed;
QList<QJsonObject> m_expressionResults;
QList<QJsonArray> m_expressionRefs;
QV4Debugger *m_debugger;
@@ -324,7 +326,10 @@ private slots:
void breakInWith();
void evaluateExpression();
+ void stepToEndOfScript();
+ void lastLineOfLoop_data();
+ void lastLineOfLoop();
private:
QV4Debugger *debugger() const
{
@@ -758,6 +763,70 @@ void tst_qv4debugger::evaluateExpression()
}
}
+void tst_qv4debugger::stepToEndOfScript()
+{
+ QString script =
+ "var ret = 0;\n"
+ "ret += 4;\n"
+ "ret += 1;\n"
+ "ret += 5;\n";
+
+ debugger()->addBreakPoint("toEnd", 1);
+ m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver;
+ evaluateJavaScript(script, "toEnd");
+ QVERIFY(m_debuggerAgent->m_wasPaused);
+ QCOMPARE(m_debuggerAgent->m_pauseReason, QV4Debugger::Step);
+ QCOMPARE(m_debuggerAgent->m_statesWhenPaused.count(), 5);
+ for (int i = 0; i < 4; ++i) {
+ QV4Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.at(i);
+ QCOMPARE(state.fileName, QString("toEnd"));
+ QCOMPARE(state.lineNumber, i + 1);
+ }
+
+ QV4Debugger::ExecutionState state = m_debuggerAgent->m_statesWhenPaused.at(4);
+ QCOMPARE(state.fileName, QString("toEnd"));
+ QCOMPARE(state.lineNumber, -4); // A return instruction without proper line number.
+}
+
+void tst_qv4debugger::lastLineOfLoop_data()
+{
+ QTest::addColumn<QString>("loopHead");
+ QTest::addColumn<QString>("loopTail");
+
+ QTest::newRow("for") << "for (var i = 0; i < 10; ++i) {\n" << "}\n";
+ QTest::newRow("for..in") << "for (var i in [0, 1, 2, 3, 4]) {\n" << "}\n";
+ QTest::newRow("while") << "while (ret < 10) {\n" << "}\n";
+ QTest::newRow("do..while") << "do {\n" << "} while (ret < 10);\n";
+}
+
+void tst_qv4debugger::lastLineOfLoop()
+{
+ QFETCH(QString, loopHead);
+ QFETCH(QString, loopTail);
+
+ QString script =
+ "var ret = 0;\n"
+ + loopHead +
+ " if (ret == 2)\n"
+ " ret += 4;\n" // breakpoint, then step over
+ " else \n"
+ " ret += 1;\n"
+ + loopTail;
+
+ debugger()->addBreakPoint("trueBranch", 4);
+ m_debuggerAgent->m_resumeSpeed = QV4Debugger::StepOver;
+ evaluateJavaScript(script, "trueBranch");
+ QVERIFY(m_debuggerAgent->m_wasPaused);
+ QCOMPARE(m_debuggerAgent->m_pauseReason, QV4Debugger::Step);
+ QVERIFY(m_debuggerAgent->m_statesWhenPaused.count() > 1);
+ QV4Debugger::ExecutionState firstState = m_debuggerAgent->m_statesWhenPaused.first();
+ QCOMPARE(firstState.fileName, QString("trueBranch"));
+ QCOMPARE(firstState.lineNumber, 4);
+ QV4Debugger::ExecutionState secondState = m_debuggerAgent->m_statesWhenPaused.at(1);
+ QCOMPARE(secondState.fileName, QString("trueBranch"));
+ QCOMPARE(secondState.lineNumber, 7);
+}
+
QTEST_MAIN(tst_qv4debugger)
#include "tst_qv4debugger.moc"
diff --git a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST b/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
deleted file mode 100644
index 1777af9e0c..0000000000
--- a/tests/auto/quick/qquickmultipointtoucharea/BLACKLIST
+++ /dev/null
@@ -1,2 +0,0 @@
-[inFlickable]
-*
diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
index 2872556a94..87acd67f6a 100644
--- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
+++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp
@@ -800,7 +800,7 @@ void tst_QQuickMultiPointTouchArea::inFlickable2()
QVERIFY(flickable->contentY() < 0);
QVERIFY(flickable->isMoving());
- QCOMPARE(point11->pressed(), true);
+ QCOMPARE(point11->pressed(), false);
QTest::touchEvent(window.data(), device).release(0, p1);
QQuickTouchUtils::flush(window.data());
diff --git a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
index cd503a88d4..d454f9b7bc 100644
--- a/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
+++ b/tests/auto/quick/qquickwindow/tst_qquickwindow.cpp
@@ -28,6 +28,7 @@
#include <qtest.h>
#include <QDebug>
+#include <QMimeData>
#include <QTouchEvent>
#include <QtQuick/QQuickItem>
#include <QtQuick/QQuickView>
@@ -372,6 +373,8 @@ private slots:
void grabContentItemToImage();
+ void testDragEventPropertyPropagation();
+
private:
QTouchDevice *touchDevice;
QTouchDevice *touchDeviceWithVelocity;
@@ -2567,6 +2570,261 @@ void tst_qquickwindow::grabContentItemToImage()
QTRY_COMPARE(created->property("success").toInt(), 1);
}
+class TestDropTarget : public QQuickItem
+{
+ Q_OBJECT
+public:
+ TestDropTarget(QQuickItem *parent = 0)
+ : QQuickItem(parent)
+ , enterDropAction(Qt::CopyAction)
+ , moveDropAction(Qt::CopyAction)
+ , dropDropAction(Qt::CopyAction)
+ , enterAccept(true)
+ , moveAccept(true)
+ , dropAccept(true)
+ {
+ setFlags(ItemAcceptsDrops);
+ }
+
+ void reset()
+ {
+ enterDropAction = Qt::CopyAction;
+ moveDropAction = Qt::CopyAction;
+ dropDropAction = Qt::CopyAction;
+ enterAccept = true;
+ moveAccept = true;
+ dropAccept = true;
+ }
+
+ void dragEnterEvent(QDragEnterEvent *event)
+ {
+ event->setAccepted(enterAccept);
+ event->setDropAction(enterDropAction);
+ }
+
+ void dragMoveEvent(QDragMoveEvent *event)
+ {
+ event->setAccepted(moveAccept);
+ event->setDropAction(moveDropAction);
+ }
+
+ void dropEvent(QDropEvent *event)
+ {
+ event->setAccepted(dropAccept);
+ event->setDropAction(dropDropAction);
+ }
+
+ Qt::DropAction enterDropAction;
+ Qt::DropAction moveDropAction;
+ Qt::DropAction dropDropAction;
+ bool enterAccept;
+ bool moveAccept;
+ bool dropAccept;
+};
+
+class DragEventTester {
+public:
+ DragEventTester()
+ : pos(60, 60)
+ , actions(Qt::CopyAction | Qt::MoveAction | Qt::LinkAction)
+ , buttons(Qt::LeftButton)
+ , modifiers(Qt::NoModifier)
+ {
+ }
+
+ ~DragEventTester() {
+ qDeleteAll(events);
+ events.clear();
+ enterEvent = 0;
+ moveEvent = 0;
+ dropEvent = 0;
+ leaveEvent = 0;
+ }
+
+ void addEnterEvent()
+ {
+ enterEvent = new QDragEnterEvent(pos, actions, &data, buttons, modifiers);
+ events.append(enterEvent);
+ }
+
+ void addMoveEvent()
+ {
+ moveEvent = new QDragMoveEvent(pos, actions, &data, buttons, modifiers, QEvent::DragMove);
+ events.append(moveEvent);
+ }
+
+ void addDropEvent()
+ {
+ dropEvent = new QDropEvent(pos, actions, &data, buttons, modifiers, QEvent::Drop);
+ events.append(dropEvent);
+ }
+
+ void addLeaveEvent()
+ {
+ leaveEvent = new QDragLeaveEvent();
+ events.append(leaveEvent);
+ }
+
+ void sendDragEventSequence(QQuickWindow *window) const {
+ for (int i = 0; i < events.size(); ++i) {
+ QCoreApplication::sendEvent(window, events[i]);
+ }
+ }
+
+ // Used for building events.
+ QMimeData data;
+ QPoint pos;
+ Qt::DropActions actions;
+ Qt::MouseButtons buttons;
+ Qt::KeyboardModifiers modifiers;
+
+ // Owns events.
+ QList<QEvent *> events;
+
+ // Non-owner pointers for easy acccess.
+ QDragEnterEvent *enterEvent;
+ QDragMoveEvent *moveEvent;
+ QDropEvent *dropEvent;
+ QDragLeaveEvent *leaveEvent;
+};
+
+void tst_qquickwindow::testDragEventPropertyPropagation()
+{
+ QQuickWindow window;
+ TestDropTarget dropTarget(window.contentItem());
+
+ // Setting the size is important because the QQuickWindow checks if the drag happened inside
+ // the drop target.
+ dropTarget.setSize(QSizeF(100, 100));
+
+ // Test enter events property propagation.
+ // For enter events, only isAccepted gets propagated.
+ {
+ DragEventTester builder;
+ dropTarget.enterAccept = false;
+ dropTarget.enterDropAction = Qt::IgnoreAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragEnterEvent* enterEvent = builder.enterEvent;
+ QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.enterAccept = false;
+ dropTarget.enterDropAction = Qt::CopyAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragEnterEvent* enterEvent = builder.enterEvent;
+ QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.enterAccept = true;
+ dropTarget.enterDropAction = Qt::IgnoreAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragEnterEvent* enterEvent = builder.enterEvent;
+ QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.enterAccept = true;
+ dropTarget.enterDropAction = Qt::CopyAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragEnterEvent* enterEvent = builder.enterEvent;
+ QCOMPARE(enterEvent->isAccepted(), dropTarget.enterAccept);
+ }
+
+ // Test move events property propagation.
+ // For move events, both isAccepted and dropAction get propagated.
+ dropTarget.reset();
+ {
+ DragEventTester builder;
+ dropTarget.moveAccept = false;
+ dropTarget.moveDropAction = Qt::IgnoreAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragMoveEvent* moveEvent = builder.moveEvent;
+ QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept);
+ QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.moveAccept = false;
+ dropTarget.moveDropAction = Qt::CopyAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragMoveEvent* moveEvent = builder.moveEvent;
+ QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept);
+ QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.moveAccept = true;
+ dropTarget.moveDropAction = Qt::IgnoreAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragMoveEvent* moveEvent = builder.moveEvent;
+ QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept);
+ QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.moveAccept = true;
+ dropTarget.moveDropAction = Qt::CopyAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addLeaveEvent();
+ builder.sendDragEventSequence(&window);
+ QDragMoveEvent* moveEvent = builder.moveEvent;
+ QCOMPARE(moveEvent->isAccepted(), dropTarget.moveAccept);
+ QCOMPARE(moveEvent->dropAction(), dropTarget.moveDropAction);
+ }
+
+ // Test drop events property propagation.
+ // For drop events, both isAccepted and dropAction get propagated.
+ dropTarget.reset();
+ {
+ DragEventTester builder;
+ dropTarget.dropAccept = false;
+ dropTarget.dropDropAction = Qt::IgnoreAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent();
+ builder.sendDragEventSequence(&window);
+ QDropEvent* dropEvent = builder.dropEvent;
+ QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept);
+ QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.dropAccept = false;
+ dropTarget.dropDropAction = Qt::CopyAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent();
+ builder.sendDragEventSequence(&window);
+ QDropEvent* dropEvent = builder.dropEvent;
+ QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept);
+ QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.dropAccept = true;
+ dropTarget.dropDropAction = Qt::IgnoreAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent();
+ builder.sendDragEventSequence(&window);
+ QDropEvent* dropEvent = builder.dropEvent;
+ QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept);
+ QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction);
+ }
+ {
+ DragEventTester builder;
+ dropTarget.dropAccept = true;
+ dropTarget.dropDropAction = Qt::CopyAction;
+ builder.addEnterEvent(); builder.addMoveEvent(); builder.addDropEvent();
+ builder.sendDragEventSequence(&window);
+ QDropEvent* dropEvent = builder.dropEvent;
+ QCOMPARE(dropEvent->isAccepted(), dropTarget.dropAccept);
+ QCOMPARE(dropEvent->dropAction(), dropTarget.dropDropAction);
+ }
+}
+
QTEST_MAIN(tst_qquickwindow)
#include "tst_qquickwindow.moc"
diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
index 032e682137..671cefd6f5 100644
--- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp
+++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp
@@ -71,7 +71,7 @@ Q_SIGNALS:
public:
EventItem(QQuickItem *parent = 0)
- : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1)
+ : QQuickItem(parent), touchUngrabCount(0), acceptMouse(false), acceptTouch(false), filterTouch(false), point0(-1)
{
setAcceptedMouseButtons(Qt::LeftButton);
}
@@ -111,11 +111,17 @@ public:
eventList.append(Event(QEvent::UngrabMouse, QPoint(0,0), QPoint(0,0)));
}
+ void touchUngrabEvent()
+ {
+ ++touchUngrabCount;
+ }
+
bool event(QEvent *event) {
return QQuickItem::event(event);
}
QList<Event> eventList;
+ int touchUngrabCount;
bool acceptMouse;
bool acceptTouch;
bool filterTouch; // when used as event filter
@@ -158,6 +164,7 @@ private slots:
void mouseOverTouch();
void buttonOnFlickable();
+ void touchButtonOnFlickable();
void buttonOnDelayedPressFlickable_data();
void buttonOnDelayedPressFlickable();
void buttonOnTouch();
@@ -568,9 +575,10 @@ void tst_TouchMouse::buttonOnFlickable()
QCOMPARE(pointerEvent->point(0)->grabber(), eventItem1);
QCOMPARE(window->mouseGrabberItem(), eventItem1);
- p1 += QPoint(0, -10);
- QPoint p2 = p1 + QPoint(0, -10);
- QPoint p3 = p2 + QPoint(0, -10);
+ int dragDelta = -qApp->styleHints()->startDragDistance();
+ p1 += QPoint(0, dragDelta);
+ QPoint p2 = p1 + QPoint(0, dragDelta);
+ QPoint p3 = p2 + QPoint(0, dragDelta);
QQuickTouchUtils::flush(window.data());
QTest::touchEvent(window.data(), device).move(0, p1, window.data());
QQuickTouchUtils::flush(window.data());
@@ -593,6 +601,66 @@ void tst_TouchMouse::buttonOnFlickable()
QQuickTouchUtils::flush(window.data());
}
+void tst_TouchMouse::touchButtonOnFlickable()
+{
+ // flickable - height 500 / 1000
+ // - eventItem1 y: 100, height 100
+ // - eventItem2 y: 300, height 100
+
+ QScopedPointer<QQuickView> window(createView());
+ window->setSource(testFileUrl("buttononflickable.qml"));
+ window->show();
+ QQuickViewTestUtil::centerOnScreen(window.data());
+ QVERIFY(QTest::qWaitForWindowActive(window.data()));
+ QVERIFY(window->rootObject() != 0);
+
+ QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
+ QVERIFY(flickable);
+
+ EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
+ QVERIFY(eventItem2);
+ QCOMPARE(eventItem2->eventList.size(), 0);
+ eventItem2->acceptTouch = true;
+
+ // press via touch, then drag: check that flickable moves and that the button gets ungrabbed
+ QCOMPARE(eventItem2->eventList.size(), 0);
+ QPoint p1 = QPoint(10, 310);
+ QTest::touchEvent(window.data(), device).press(0, p1, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QCOMPARE(eventItem2->eventList.size(), 1);
+ QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
+
+ QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window.data());
+ QVERIFY(windowPriv->touchMouseId == -1);
+ auto pointerEvent = QQuickPointerDevice::touchDevices().at(0)->pointerEvent();
+ QCOMPARE(pointerEvent->point(0)->grabber(), eventItem2);
+ QCOMPARE(window->mouseGrabberItem(), nullptr);
+
+ int dragDelta = qApp->styleHints()->startDragDistance() * -0.7;
+ p1 += QPoint(0, dragDelta);
+ QPoint p2 = p1 + QPoint(0, dragDelta);
+ QPoint p3 = p2 + QPoint(0, dragDelta);
+
+ QQuickTouchUtils::flush(window.data());
+ QTest::touchEvent(window.data(), device).move(0, p1, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QTest::touchEvent(window.data(), device).move(0, p2, window.data());
+ QQuickTouchUtils::flush(window.data());
+ QTest::touchEvent(window.data(), device).move(0, p3, window.data());
+ QQuickTouchUtils::flush(window.data());
+
+ QVERIFY(eventItem2->eventList.size() > 2);
+ QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
+ QCOMPARE(eventItem2->touchUngrabCount, 1);
+ QCOMPARE(window->mouseGrabberItem(), flickable);
+ QVERIFY(windowPriv->touchMouseId != -1);
+ QCOMPARE(pointerEvent->point(0)->grabber(), flickable);
+ QVERIFY(flickable->isMovingVertically());
+
+ QTest::touchEvent(window.data(), device).release(0, p3, window.data());
+ QQuickTouchUtils::flush(window.data());
+}
+
void tst_TouchMouse::buttonOnDelayedPressFlickable_data()
{
QTest::addColumn<bool>("scrollBeforeDelayIsOver");
diff --git a/tests/auto/toolsupport/tst_toolsupport.cpp b/tests/auto/toolsupport/tst_toolsupport.cpp
index 9a11a67e65..526ba8f375 100644
--- a/tests/auto/toolsupport/tst_toolsupport.cpp
+++ b/tests/auto/toolsupport/tst_toolsupport.cpp
@@ -109,7 +109,7 @@ void tst_toolsupport::offsets_data()
= QTest::newRow("CompiledData::CompilationUnit::runtimeStrings")
<< pmm_to_offsetof(&QV4::CompiledData::CompilationUnit::runtimeStrings);
- data << 16 << 32;
+ data << 12 << 24;
}
{
diff --git a/tools/qmlcachegen/qmlcache.prf b/tools/qmlcachegen/qmlcache.prf
index fed9f0d2f3..31c18a231b 100644
--- a/tools/qmlcachegen/qmlcache.prf
+++ b/tools/qmlcachegen/qmlcache.prf
@@ -1,12 +1,52 @@
-qtPrepareTool(QML_CACHEGEN, qmlcachegen)
+static {
+ message("QML cache generation ahead of time is not supported in static builds")
+ return()
+}
+
+qtPrepareTool(QML_CACHEGEN, qmlcachegen, _ARCH_CHECK)
+
+isEmpty(TARGETPATH): error("Must set TARGETPATH (QML import name) for ahead-of-time QML cache generation")
!isEmpty(QT_TARGET_ARCH):QML_CACHEGEN_ARCH=$$QT_TARGET_ARCH
else:QML_CACHEGEN_ARCH=$$QT_ARCH
-qmlcachegen.input = QML_FILES
-qmlcachegen.output = ${QMAKE_FILE_IN}c
-qmlcachegen.commands = $$QML_CACHEGEN --target-architecture=$$QML_CACHEGEN_ARCH ${QMAKE_FILE_IN}
+QML_CACHEGEN_ARGS=--target-architecture=$$QML_CACHEGEN_ARCH
+
+!system($$QML_CACHEGEN_ARCH_CHECK $$QML_CACHEGEN_ARGS --check-if-supported) {
+ message("QML cache generation requested but target architecture $$QML_CACHEGEN_ARCH is not supported.")
+ return()
+}
+
+load(qt_build_paths)
+
+prefix_build: QMLCACHE_DESTDIR = $$MODULE_BASE_OUTDIR/qml/$$TARGETPATH
+else: QMLCACHE_DESTDIR = $$[QT_INSTALL_QML]/$$TARGETPATH
+
+CACHEGEN_FILES=
+qmlcacheinst.files =
+for(qmlf, QML_FILES) {
+ contains(qmlf,.*\\.js$)|contains(qmlf,.*\\.qml$) {
+ CACHEGEN_FILES += $$absolute_path($$qmlf, $$_PRO_FILE_PWD_)
+ qmlcacheinst.files += $$QMLCACHE_DESTDIR/$$relative_path($$qmlf, $$_PRO_FILE_PWD_)c
+ }
+}
+
+defineReplace(qmlCacheOutputFileName) {
+ return($$relative_path($$QMLCACHE_DESTDIR/$$relative_path($$1, $$_PRO_FILE_PWD_)c, $$OUT_PWD))
+}
+
+qmlcacheinst.base = $$QMLCACHE_DESTDIR
+qmlcacheinst.path = $$[QT_INSTALL_QML]/$$TARGETPATH
+qmlcacheinst.CONFIG = no_check_exist
+
+qmlcachegen.input = CACHEGEN_FILES
+qmlcachegen.output = ${QMAKE_FUNC_FILE_IN_qmlCacheOutputFileName}
+qmlcachegen.CONFIG = no_link target_predeps
+qmlcachegen.commands = $$QML_CACHEGEN $$QML_CACHEGEN_ARGS -o ${QMAKE_FILE_OUT} ${QMAKE_FILE_IN}
qmlcachegen.name = Generate QML Cache ${QMAKE_FILE_IN}
-qmlcachegen.variable_out = AUX_QML_FILES
+qmlcachegen.variable_out = GENERATED_FILES
-QMAKE_EXTRA_COMPILERS += qmlcachegen
+!debug_and_release|!build_all|CONFIG(release, debug|release) {
+ QMAKE_EXTRA_COMPILERS += qmlcachegen
+ INSTALLS += qmlcacheinst
+}
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 977c5b6ff1..9a68e2ac97 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -80,7 +80,40 @@ QString diagnosticErrorMessage(const QString &fileName, const QQmlJS::Diagnostic
return message;
}
-static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
+// Ensure that ListElement objects keep all property assignments in their string form
+static void annotateListElements(QmlIR::Document *document)
+{
+ QStringList listElementNames;
+
+ foreach (const QV4::CompiledData::Import *import, document->imports) {
+ const QString uri = document->stringAt(import->uriIndex);
+ if (uri != QStringLiteral("QtQml.Models") && uri != QStringLiteral("QtQuick"))
+ continue;
+
+ QString listElementName = QStringLiteral("ListElement");
+ const QString qualifier = document->stringAt(import->qualifierIndex);
+ if (!qualifier.isEmpty()) {
+ listElementName.prepend(QLatin1Char('.'));
+ listElementName.prepend(qualifier);
+ }
+ listElementNames.append(listElementName);
+ }
+
+ if (listElementNames.isEmpty())
+ return;
+
+ foreach (QmlIR::Object *object, document->objects) {
+ if (!listElementNames.contains(document->stringAt(object->inheritedTypeNameIndex)))
+ continue;
+ for (QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
+ if (binding->type != QV4::CompiledData::Binding::Type_Script)
+ continue;
+ binding->stringIndex = document->registerString(object->bindingAsString(document, binding->value.compiledScriptIndex));
+ }
+ }
+}
+
+static bool compileQmlFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
{
QmlIR::Document irDocument(/*debugMode*/false);
@@ -96,7 +129,6 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString();
return false;
}
- irDocument.jsModule.sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
}
{
@@ -112,8 +144,10 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
}
}
+ annotateListElements(&irDocument);
+
{
- QmlIR::JSCodeGen v4CodeGen(inputFileName, irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable);
+ QmlIR::JSCodeGen v4CodeGen(/*empty input file name*/QString(), irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable);
for (QmlIR::Object *object: qAsConst(irDocument.objects)) {
if (object->functionsAndExpressions->count == 0)
continue;
@@ -153,7 +187,7 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
unit->flags |= QV4::CompiledData::Unit::PendingTypeCompilation;
irDocument.javaScriptCompilationUnit->data = unit;
- if (!irDocument.javaScriptCompilationUnit->saveToDisk(inputFileName, &error->message))
+ if (!irDocument.javaScriptCompilationUnit->saveToDisk(outputFileName, &error->message))
return false;
free(unit);
@@ -161,7 +195,7 @@ static bool compileQmlFile(const QString &inputFileName, QV4::EvalISelFactory *i
return true;
}
-static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
+static bool compileJSFile(const QString &inputFileName, const QString &outputFileName, QV4::EvalISelFactory *iselFactory, Error *error)
{
QmlIR::Document irDocument(/*debugMode*/false);
@@ -177,7 +211,6 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
error->message = QLatin1String("Error reading from ") + inputFileName + QLatin1Char(':') + f.errorString();
return false;
}
- irDocument.jsModule.sourceTimeStamp = QFileInfo(f).lastModified().toMSecsSinceEpoch();
}
QQmlJS::Engine *engine = &irDocument.jsParserEngine;
@@ -217,7 +250,7 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
{
QmlIR::JSCodeGen v4CodeGen(inputFileName, irDocument.code, &irDocument.jsModule, &irDocument.jsParserEngine, irDocument.program, /*import cache*/0, &irDocument.jsGenerator.stringTable);
- v4CodeGen.generateFromProgram(inputFileName, sourceCode, program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode);
+ v4CodeGen.generateFromProgram(/*empty input file name*/QString(), sourceCode, program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode);
QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors();
if (!jsErrors.isEmpty()) {
for (const QQmlJS::DiagnosticMessage &e: qAsConst(jsErrors)) {
@@ -233,7 +266,8 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
// ### translation binding simplification
- QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, /*executable allocator*/nullptr, &irDocument.jsModule, &irDocument.jsGenerator));
+ QV4::ExecutableAllocator allocator;
+ QScopedPointer<QV4::EvalInstructionSelection> isel(iselFactory->create(/*engine*/nullptr, &allocator, &irDocument.jsModule, &irDocument.jsGenerator));
// Disable lookups in non-standalone (aka QML) mode
isel->setUseFastLookups(false);
irDocument.javaScriptCompilationUnit = isel->compile(/*generate unit*/false);
@@ -243,7 +277,7 @@ static bool compileJSFile(const QString &inputFileName, QV4::EvalISelFactory *is
unit->flags |= QV4::CompiledData::Unit::StaticData;
irDocument.javaScriptCompilationUnit->data = unit;
- if (!irDocument.javaScriptCompilationUnit->saveToDisk(inputFileName, &error->message)) {
+ if (!irDocument.javaScriptCompilationUnit->saveToDisk(outputFileName, &error->message)) {
engine->setDirectives(oldDirs);
return false;
}
@@ -270,37 +304,60 @@ int main(int argc, char **argv)
QCommandLineOption targetArchitectureOption(QStringLiteral("target-architecture"), QCoreApplication::translate("main", "Target architecture"), QCoreApplication::translate("main", "architecture"));
parser.addOption(targetArchitectureOption);
+ QCommandLineOption outputFileOption(QStringLiteral("o"), QCoreApplication::translate("main", "Output file name"), QCoreApplication::translate("main", "file name"));
+ parser.addOption(outputFileOption);
+
+ QCommandLineOption checkIfSupportedOption(QStringLiteral("check-if-supported"), QCoreApplication::translate("main", "Check if cache generate is supported on the specified target architecture"));
+ parser.addOption(checkIfSupportedOption);
+
parser.addPositionalArgument(QStringLiteral("[qml file]"),
QStringLiteral("QML source file to generate cache for."));
parser.process(app);
- const QStringList sources = parser.positionalArguments();
- if (sources.isEmpty()){
+ if (!parser.isSet(targetArchitectureOption)) {
+ fprintf(stderr, "Target architecture not specified. Please specify with --target-architecture=<arch>\n");
parser.showHelp();
- } else if (sources.count() > 1) {
- fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\'')));
return EXIT_FAILURE;
}
- const QString inputFile = sources.first();
QScopedPointer<QV4::EvalISelFactory> isel;
const QString targetArchitecture = parser.value(targetArchitectureOption);
isel.reset(QV4::JIT::createISelForArchitecture(targetArchitecture));
+ if (parser.isSet(checkIfSupportedOption)) {
+ if (isel.isNull())
+ return EXIT_FAILURE;
+ else
+ return EXIT_SUCCESS;
+ }
+
+ const QStringList sources = parser.positionalArguments();
+ if (sources.isEmpty()){
+ parser.showHelp();
+ } else if (sources.count() > 1) {
+ fprintf(stderr, "%s\n", qPrintable(QStringLiteral("Too many input files specified: '") + sources.join(QStringLiteral("' '")) + QLatin1Char('\'')));
+ return EXIT_FAILURE;
+ }
+ const QString inputFile = sources.first();
+
if (!isel)
isel.reset(new QV4::Moth::ISelFactory);
Error error;
+ QString outputFileName = inputFile + QLatin1Char('c');
+ if (parser.isSet(outputFileOption))
+ outputFileName = parser.value(outputFileOption);
+
if (inputFile.endsWith(QLatin1String(".qml"))) {
- if (!compileQmlFile(inputFile, isel.data(), &error)) {
+ if (!compileQmlFile(inputFile, outputFileName, isel.data(), &error)) {
error.augment(QLatin1String("Error compiling qml file: ")).print();
return EXIT_FAILURE;
}
} else if (inputFile.endsWith(QLatin1String(".js"))) {
- if (!compileJSFile(inputFile, isel.data(), &error)) {
+ if (!compileJSFile(inputFile, outputFileName, isel.data(), &error)) {
error.augment(QLatin1String("Error compiling qml file: ")).print();
return EXIT_FAILURE;
}
diff --git a/tools/qmlcachegen/qmlcachegen.pro b/tools/qmlcachegen/qmlcachegen.pro
index 81783d0396..25afc2860d 100644
--- a/tools/qmlcachegen/qmlcachegen.pro
+++ b/tools/qmlcachegen/qmlcachegen.pro
@@ -6,19 +6,9 @@ DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII
SOURCES = qmlcachegen.cpp
TARGET = qmlcachegen
-BUILD_INTEGRATION = qmlcache.prf
-!force_independent {
- qmake_integration.input = BUILD_INTEGRATION
- qmake_integration.output = $$[QT_HOST_DATA]/mkspecs/features/${QMAKE_FILE_BASE}.prf
- qmake_integration.commands = $$QMAKE_COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
- qmake_integration.name = COPY ${QMAKE_FILE_IN} ${QMAKE_FILE_OUT}
- qmake_integration.CONFIG = no_clean no_link
- !contains(TEMPLATE, vc.*): qmake_integration.variable_out = GENERATED_FILES
- QMAKE_EXTRA_COMPILERS += qmake_integration
-}
-
-qmake_integration_installs.files = $$BUILD_INTEGRATION
-qmake_integration_installs.path = $$[QT_HOST_DATA]/mkspecs/features
-INSTALLS += qmake_integration_installs
+build_integration.files = qmlcache.prf
+build_integration.path = $$[QT_HOST_DATA]/mkspecs/features
+prefix_build: INSTALLS += build_integration
+else: COPIES += build_integration
load(qt_tool)