Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: Ie82b8a0f9158ef02bf11209b16e574dedf201e2e
This commit is contained in:
commit
fe1f81484b
|
@ -66,7 +66,7 @@ uint32_t cryptographicallyRandomNumber()
|
|||
return 0;
|
||||
}
|
||||
|
||||
static FilePrintStream* s_dataFile;
|
||||
static FilePrintStream* s_dataFile = nullptr;
|
||||
|
||||
void setDataFile(FilePrintStream *ps)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,8 @@ FilePrintStream::~FilePrintStream()
|
|||
{
|
||||
if (m_adoptionMode == Borrow)
|
||||
return;
|
||||
fclose(m_file);
|
||||
if (m_file)
|
||||
fclose(m_file);
|
||||
}
|
||||
|
||||
std::unique_ptr<FilePrintStream> FilePrintStream::open(const char* filename, const char* mode)
|
||||
|
|
|
@ -2125,7 +2125,15 @@ public:
|
|||
auto outputTermIndexAndNest = [&](size_t index, unsigned termNesting) {
|
||||
for (unsigned nestingDepth = 0; nestingDepth < termIndexNest; nestingDepth++)
|
||||
out.print(" ");
|
||||
#if defined(WIN32) && defined(__MINGW32__)
|
||||
# if __SIZEOF_POINTER__ == 8
|
||||
out.printf("%4I64u", index);
|
||||
# else
|
||||
out.printf("%4I32u", index);
|
||||
# endif
|
||||
#else
|
||||
out.printf("%4zu", index);
|
||||
#endif
|
||||
for (unsigned nestingDepth = 0; nestingDepth < termNesting; nestingDepth++)
|
||||
out.print(" ");
|
||||
};
|
||||
|
|
|
@ -87,14 +87,17 @@ qint64 QV4ProfilerAdapter::appendMemoryEvents(qint64 until, QList<QByteArray> &m
|
|||
qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &messages,
|
||||
qint64 callNext, QQmlDebugPacket &d)
|
||||
{
|
||||
qint64 memoryNext = -1;
|
||||
|
||||
if (callNext == -1) {
|
||||
m_functionLocations.clear();
|
||||
m_functionCallData.clear();
|
||||
m_functionCallPos = 0;
|
||||
memoryNext = appendMemoryEvents(until, messages, d);
|
||||
} else {
|
||||
memoryNext = appendMemoryEvents(qMin(callNext, until), messages, d);
|
||||
}
|
||||
|
||||
qint64 memoryNext = appendMemoryEvents(until, messages, d);
|
||||
|
||||
if (memoryNext == -1) {
|
||||
m_memoryData.clear();
|
||||
m_memoryPos = 0;
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
import QtQml 2.2
|
||||
|
||||
QtObject {
|
||||
function iterate(dictionaryTable, j) {
|
||||
var word = "a" + j.toString()
|
||||
dictionaryTable[word] = null;
|
||||
}
|
||||
|
||||
Component.onCompleted: {
|
||||
var dictionaryTable = {};
|
||||
for (var j = 0; j < 256; ++j)
|
||||
iterate(dictionaryTable, j);
|
||||
}
|
||||
|
||||
property Timer timer: Timer {
|
||||
interval: 1
|
||||
running: true;
|
||||
onTriggered: Qt.quit();
|
||||
}
|
||||
}
|
|
@ -21,4 +21,5 @@ OTHER_FILES += \
|
|||
data/javascript.qml \
|
||||
data/timer.qml \
|
||||
data/qstr.qml \
|
||||
data/memory.qml
|
||||
data/memory.qml \
|
||||
data/batchOverflow.qml
|
||||
|
|
|
@ -225,6 +225,7 @@ private slots:
|
|||
void memory();
|
||||
void compile();
|
||||
void multiEngine();
|
||||
void batchOverflow();
|
||||
|
||||
private:
|
||||
bool m_recordFromStart = true;
|
||||
|
@ -826,6 +827,15 @@ void tst_QQmlProfilerService::multiEngine()
|
|||
QCOMPARE(spy.count(), 1);
|
||||
}
|
||||
|
||||
void tst_QQmlProfilerService::batchOverflow()
|
||||
{
|
||||
// The trace client checks that the events are received in order.
|
||||
QCOMPARE(connect(true, "batchOverflow.qml"), ConnectSuccess);
|
||||
checkProcessTerminated();
|
||||
checkTraceReceived();
|
||||
checkJsHeap();
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QQmlProfilerService)
|
||||
|
||||
#include "tst_qqmlprofilerservice.moc"
|
||||
|
|
|
@ -3,10 +3,12 @@ CONFIG += no_import_scan
|
|||
|
||||
SOURCES += \
|
||||
main.cpp \
|
||||
qmlpreviewapplication.cpp
|
||||
qmlpreviewapplication.cpp \
|
||||
qmlpreviewfilesystemwatcher.cpp
|
||||
|
||||
HEADERS += \
|
||||
qmlpreviewapplication.h
|
||||
qmlpreviewapplication.h \
|
||||
qmlpreviewfilesystemwatcher.h
|
||||
|
||||
QMAKE_TARGET_DESCRIPTION = QML Preview
|
||||
|
||||
|
|
|
@ -63,9 +63,9 @@ QmlPreviewApplication::QmlPreviewApplication(int &argc, char **argv) :
|
|||
connect(m_qmlPreviewClient.data(), &QQmlPreviewClient::request,
|
||||
this, &QmlPreviewApplication::serveRequest);
|
||||
|
||||
connect(&m_watcher, &QFileSystemWatcher::fileChanged,
|
||||
connect(&m_watcher, &QmlPreviewFileSystemWatcher::fileChanged,
|
||||
this, &QmlPreviewApplication::sendFile);
|
||||
connect(&m_watcher, &QFileSystemWatcher::directoryChanged,
|
||||
connect(&m_watcher, &QmlPreviewFileSystemWatcher::directoryChanged,
|
||||
this, &QmlPreviewApplication::sendDirectory);
|
||||
}
|
||||
|
||||
|
@ -105,7 +105,7 @@ void QmlPreviewApplication::parseArguments()
|
|||
parser.addVersionOption();
|
||||
|
||||
parser.addPositionalArgument(QLatin1String("program"),
|
||||
tr("The program to be started and profiled."),
|
||||
tr("The program to be started and previewed."),
|
||||
QLatin1String("[program]"));
|
||||
parser.addPositionalArgument(QLatin1String("parameters"),
|
||||
tr("Parameters for the program to be started."),
|
||||
|
@ -212,17 +212,12 @@ void QmlPreviewApplication::serveRequest(const QString &path)
|
|||
|
||||
if (info.isDir()) {
|
||||
m_qmlPreviewClient->sendDirectory(path, QDir(path).entryList());
|
||||
m_watcher.addPath(path);
|
||||
m_watcher.addDirectory(path);
|
||||
} else {
|
||||
QFile file(path);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
m_qmlPreviewClient->sendFile(path, file.readAll());
|
||||
m_watcher.addPath(path);
|
||||
|
||||
// Also watch the directory, because editors will rather replace a file than change it.
|
||||
// Therefore when the file changes, we can't read it, but when the file is re-added we can
|
||||
// see that from the directory changing.
|
||||
m_watcher.addPath(info.absolutePath());
|
||||
m_watcher.addFile(path);
|
||||
} else {
|
||||
logStatus(QString("Could not open file %1 for reading: %2").arg(path)
|
||||
.arg(file.errorString()));
|
||||
|
@ -236,13 +231,10 @@ bool QmlPreviewApplication::sendFile(const QString &path)
|
|||
QFile file(path);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
m_qmlPreviewClient->sendFile(path, file.readAll());
|
||||
m_pendingFiles.removeAll(path);
|
||||
// Defer the Load, because files tend to change multiple times in a row.
|
||||
m_loadTimer.start();
|
||||
return true;
|
||||
}
|
||||
if (!m_pendingFiles.contains(path))
|
||||
m_pendingFiles.append(path);
|
||||
logStatus(QString("Could not open file %1 for reading: %2").arg(path).arg(file.errorString()));
|
||||
return false;
|
||||
}
|
||||
|
@ -250,17 +242,5 @@ bool QmlPreviewApplication::sendFile(const QString &path)
|
|||
void QmlPreviewApplication::sendDirectory(const QString &path)
|
||||
{
|
||||
m_qmlPreviewClient->sendDirectory(path, QDir(path).entryList());
|
||||
for (auto it = m_pendingFiles.begin(); it != m_pendingFiles.end();) {
|
||||
const QString filePath = *it;
|
||||
QFile file(filePath);
|
||||
if (file.open(QIODevice::ReadOnly)) {
|
||||
logStatus(QString("Sending replaced file %1.").arg(filePath));
|
||||
m_qmlPreviewClient->sendFile(filePath, file.readAll());
|
||||
m_watcher.addPath(filePath);
|
||||
it = m_pendingFiles.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
m_loadTimer.start();
|
||||
}
|
||||
|
|
|
@ -29,13 +29,14 @@
|
|||
#ifndef QMLPREVIEWAPPLICATION_H
|
||||
#define QMLPREVIEWAPPLICATION_H
|
||||
|
||||
#include "qmlpreviewfilesystemwatcher.h"
|
||||
|
||||
#include <private/qqmlpreviewclient_p.h>
|
||||
#include <private/qqmldebugconnection_p.h>
|
||||
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
#include <QtCore/qprocess.h>
|
||||
#include <QtCore/qtimer.h>
|
||||
#include <QtCore/qfilesystemwatcher.h>
|
||||
|
||||
#include <QtNetwork/qabstractsocket.h>
|
||||
|
||||
|
@ -71,13 +72,11 @@ private:
|
|||
|
||||
QScopedPointer<QQmlDebugConnection> m_connection;
|
||||
QScopedPointer<QQmlPreviewClient> m_qmlPreviewClient;
|
||||
QFileSystemWatcher m_watcher;
|
||||
QmlPreviewFileSystemWatcher m_watcher;
|
||||
|
||||
QTimer m_loadTimer;
|
||||
QTimer m_connectTimer;
|
||||
uint m_connectionAttempts;
|
||||
|
||||
QStringList m_pendingFiles;
|
||||
};
|
||||
|
||||
#endif // QMLPREVIEWAPPLICATION_H
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:GPL-EXCEPT$
|
||||
** 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 General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qmlpreviewfilesystemwatcher.h"
|
||||
|
||||
#include <QtCore/qdebug.h>
|
||||
#include <QtCore/qdir.h>
|
||||
#include <QtCore/qfilesystemwatcher.h>
|
||||
|
||||
QmlPreviewFileSystemWatcher::QmlPreviewFileSystemWatcher(QObject *parent) :
|
||||
QObject(parent), m_watcher(new QFileSystemWatcher(this))
|
||||
{
|
||||
connect(m_watcher, &QFileSystemWatcher::fileChanged,
|
||||
this, &QmlPreviewFileSystemWatcher::fileChanged);
|
||||
connect(m_watcher, &QFileSystemWatcher::directoryChanged,
|
||||
this, &QmlPreviewFileSystemWatcher::onDirectoryChanged);
|
||||
}
|
||||
|
||||
bool QmlPreviewFileSystemWatcher::watchesFile(const QString &file) const
|
||||
{
|
||||
return m_files.contains(file);
|
||||
}
|
||||
|
||||
void QmlPreviewFileSystemWatcher::addFile(const QString &file)
|
||||
{
|
||||
if (watchesFile(file)) {
|
||||
qWarning() << "FileSystemWatcher: File" << file << "is already being watched.";
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList toAdd(file);
|
||||
m_files.insert(file);
|
||||
|
||||
const QString directory = QFileInfo(file).path();
|
||||
const int dirCount = ++m_directoryCount[directory];
|
||||
Q_ASSERT(dirCount > 0);
|
||||
|
||||
if (dirCount == 1)
|
||||
toAdd.append(directory);
|
||||
|
||||
m_watcher->addPaths(toAdd);
|
||||
}
|
||||
|
||||
void QmlPreviewFileSystemWatcher::removeFile(const QString &file)
|
||||
{
|
||||
WatchEntrySetIterator it = m_files.find(file);
|
||||
if (it == m_files.end()) {
|
||||
qWarning() << "FileSystemWatcher: File" << file << "is not watched.";
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList toRemove(file);
|
||||
m_files.erase(it);
|
||||
m_watcher->removePath(file);
|
||||
|
||||
const QString directory = QFileInfo(file).path();
|
||||
const int dirCount = --m_directoryCount[directory];
|
||||
Q_ASSERT(dirCount >= 0);
|
||||
|
||||
if (!dirCount)
|
||||
toRemove.append(directory);
|
||||
|
||||
m_watcher->removePaths(toRemove);
|
||||
}
|
||||
|
||||
bool QmlPreviewFileSystemWatcher::watchesDirectory(const QString &directory) const
|
||||
{
|
||||
return m_directories.contains(directory);
|
||||
}
|
||||
|
||||
void QmlPreviewFileSystemWatcher::addDirectory(const QString &directory)
|
||||
{
|
||||
if (watchesDirectory(directory)) {
|
||||
qWarning() << "FileSystemWatcher: Directory" << directory << "is already being watched.";
|
||||
return;
|
||||
}
|
||||
|
||||
m_directories.insert(directory);
|
||||
const int count = ++m_directoryCount[directory];
|
||||
Q_ASSERT(count > 0);
|
||||
|
||||
if (count == 1)
|
||||
m_watcher->addPath(directory);
|
||||
}
|
||||
|
||||
void QmlPreviewFileSystemWatcher::removeDirectory(const QString &directory)
|
||||
{
|
||||
WatchEntrySetIterator it = m_directories.find(directory);
|
||||
if (it == m_directories.end()) {
|
||||
qWarning() << "FileSystemWatcher: Directory" << directory << "is not watched.";
|
||||
return;
|
||||
}
|
||||
|
||||
m_directories.erase(it);
|
||||
|
||||
const int count = --m_directoryCount[directory];
|
||||
Q_ASSERT(count >= 0);
|
||||
|
||||
if (!count)
|
||||
m_watcher->removePath(directory);
|
||||
}
|
||||
|
||||
void QmlPreviewFileSystemWatcher::onDirectoryChanged(const QString &path)
|
||||
{
|
||||
if (m_directories.contains(path))
|
||||
emit directoryChanged(path);
|
||||
|
||||
QStringList toReadd;
|
||||
const QDir dir(path);
|
||||
for (const QFileInfo &entry : dir.entryInfoList(QDir::Files)) {
|
||||
const QString file = entry.filePath();
|
||||
if (m_files.contains(file))
|
||||
toReadd.append(file);
|
||||
}
|
||||
|
||||
if (!toReadd.isEmpty()) {
|
||||
const QStringList remove = m_watcher->addPaths(toReadd);
|
||||
for (const QString &rejected : remove)
|
||||
toReadd.removeOne(rejected);
|
||||
|
||||
// If we've successfully added the file, that means it was deleted and replaced.
|
||||
for (const QString &reAdded : qAsConst(toReadd))
|
||||
emit fileChanged(reAdded);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:GPL-EXCEPT$
|
||||
** 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 General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** 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-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QMLPREVIEWFILESYSTEMWATCHER_H
|
||||
#define QMLPREVIEWFILESYSTEMWATCHER_H
|
||||
|
||||
#include <QtCore/qfilesystemwatcher.h>
|
||||
#include <QtCore/qobject.h>
|
||||
#include <QtCore/qset.h>
|
||||
|
||||
class QmlPreviewFileSystemWatcher : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit QmlPreviewFileSystemWatcher(QObject *parent = nullptr);
|
||||
|
||||
void addFile(const QString &file);
|
||||
void removeFile(const QString &file);
|
||||
bool watchesFile(const QString &file) const;
|
||||
|
||||
void addDirectory(const QString &file);
|
||||
void removeDirectory(const QString &file);
|
||||
bool watchesDirectory(const QString &file) const;
|
||||
|
||||
signals:
|
||||
void fileChanged(const QString &path);
|
||||
void directoryChanged(const QString &path);
|
||||
|
||||
private:
|
||||
using WatchEntrySet = QSet<QString>;
|
||||
using WatchEntrySetIterator = WatchEntrySet::iterator;
|
||||
|
||||
void onDirectoryChanged(const QString &path);
|
||||
|
||||
WatchEntrySet m_files;
|
||||
WatchEntrySet m_directories;
|
||||
|
||||
// Directories watched either explicitly or implicitly through files contained in them.
|
||||
QHash<QString, int> m_directoryCount;
|
||||
|
||||
QFileSystemWatcher *m_watcher = nullptr;
|
||||
};
|
||||
|
||||
#endif // QMLPREVIEWFILESYSTEMWATCHER_H
|
Loading…
Reference in New Issue