Merge remote-tracking branch 'origin/dev' into scenegraphng
Change-Id: I35715e07b6f837f21cd8e8898f19d97af92c6b69
This commit is contained in:
commit
91e1a65cdb
|
@ -4628,6 +4628,7 @@ Module {
|
||||||
Property { name: "pixelDelta"; type: "QPoint"; isReadonly: true }
|
Property { name: "pixelDelta"; type: "QPoint"; isReadonly: true }
|
||||||
Property { name: "buttons"; type: "int"; isReadonly: true }
|
Property { name: "buttons"; type: "int"; isReadonly: true }
|
||||||
Property { name: "modifiers"; type: "int"; isReadonly: true }
|
Property { name: "modifiers"; type: "int"; isReadonly: true }
|
||||||
|
Property { name: "inverted"; type: "bool" }
|
||||||
Property { name: "accepted"; type: "bool" }
|
Property { name: "accepted"; type: "bool" }
|
||||||
}
|
}
|
||||||
Component {
|
Component {
|
||||||
|
|
|
@ -145,7 +145,7 @@ void SignalTransition::invoke()
|
||||||
|
|
||||||
void SignalTransition::connectTriggered()
|
void SignalTransition::connectTriggered()
|
||||||
{
|
{
|
||||||
if (!m_complete || !m_cdata)
|
if (!m_complete || !m_compilationUnit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QObject *target = senderObject();
|
QObject *target = senderObject();
|
||||||
|
@ -165,7 +165,7 @@ void SignalTransition::connectTriggered()
|
||||||
|
|
||||||
QQmlBoundSignalExpression *expression = ctxtdata ?
|
QQmlBoundSignalExpression *expression = ctxtdata ?
|
||||||
new QQmlBoundSignalExpression(target, signalIndex,
|
new QQmlBoundSignalExpression(target, signalIndex,
|
||||||
ctxtdata, this, m_cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
|
ctxtdata, this, m_compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
|
||||||
if (expression)
|
if (expression)
|
||||||
expression->setNotifyOnValueChanged(false);
|
expression->setNotifyOnValueChanged(false);
|
||||||
m_signalExpression = expression;
|
m_signalExpression = expression;
|
||||||
|
@ -190,10 +190,10 @@ void SignalTransitionParser::verifyBindings(const QV4::CompiledData::Unit *qmlUn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SignalTransitionParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
|
void SignalTransitionParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
|
||||||
{
|
{
|
||||||
SignalTransition *st = qobject_cast<SignalTransition*>(object);
|
SignalTransition *st = qobject_cast<SignalTransition*>(object);
|
||||||
st->m_cdata = cdata;
|
st->m_compilationUnit = compilationUnit;
|
||||||
st->m_bindings = bindings;
|
st->m_bindings = bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ private:
|
||||||
QJSValue m_signal;
|
QJSValue m_signal;
|
||||||
QQmlScriptString m_guard;
|
QQmlScriptString m_guard;
|
||||||
bool m_complete;
|
bool m_complete;
|
||||||
QQmlRefPointer<QQmlCompiledData> m_cdata;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> m_compilationUnit;
|
||||||
QList<const QV4::CompiledData::Binding *> m_bindings;
|
QList<const QV4::CompiledData::Binding *> m_bindings;
|
||||||
QQmlBoundSignalExpressionPointer m_signalExpression;
|
QQmlBoundSignalExpressionPointer m_signalExpression;
|
||||||
};
|
};
|
||||||
|
@ -99,7 +99,7 @@ class SignalTransitionParser : public QQmlCustomParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) Q_DECL_OVERRIDE;
|
void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props) Q_DECL_OVERRIDE;
|
||||||
void applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
|
void applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
@ -114,7 +114,7 @@ void QV4DebuggerAgent::addDebugger(QV4Debugger *debugger)
|
||||||
|
|
||||||
debugger->setBreakOnThrow(m_breakOnThrow);
|
debugger->setBreakOnThrow(m_breakOnThrow);
|
||||||
|
|
||||||
foreach (const BreakPoint &breakPoint, m_breakPoints.values())
|
for (const BreakPoint &breakPoint : qAsConst(m_breakPoints))
|
||||||
if (breakPoint.enabled)
|
if (breakPoint.enabled)
|
||||||
debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
|
debugger->addBreakPoint(breakPoint.fileName, breakPoint.lineNr, breakPoint.condition);
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
|
||||||
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
|
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
|
||||||
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
|
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
|
||||||
engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
|
engine->profiler, SLOT(stopProfiling()), Qt::DirectConnection);
|
||||||
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
|
connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
|
||||||
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
|
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
|
||||||
engine->profiler, SLOT(setTimer(QElapsedTimer)));
|
engine->profiler, SLOT(setTimer(QElapsedTimer)));
|
||||||
connect(engine->profiler,
|
connect(engine->profiler,
|
||||||
|
@ -68,49 +68,65 @@ QQmlProfilerAdapter::QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEngin
|
||||||
// use of QDataStream can skew results
|
// use of QDataStream can skew results
|
||||||
// (see tst_qqmldebugtrace::trace() benchmark)
|
// (see tst_qqmldebugtrace::trace() benchmark)
|
||||||
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
|
static void qQmlProfilerDataToByteArrays(const QQmlProfilerData &d,
|
||||||
const QQmlProfiler::LocationHash &locations,
|
QQmlProfiler::LocationHash &locations,
|
||||||
QList<QByteArray> &messages)
|
QList<QByteArray> &messages,
|
||||||
|
bool trackLocations)
|
||||||
{
|
{
|
||||||
QQmlDebugPacket ds;
|
QQmlDebugPacket ds;
|
||||||
Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
|
Q_ASSERT_X((d.messageType & (1 << 31)) == 0, Q_FUNC_INFO,
|
||||||
"You can use at most 31 message types.");
|
"You can use at most 31 message types.");
|
||||||
for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0;
|
for (quint32 decodedMessageType = 0; (d.messageType >> decodedMessageType) != 0;
|
||||||
++decodedMessageType) {
|
++decodedMessageType) {
|
||||||
if ((d.messageType & (1 << decodedMessageType)) == 0)
|
if (decodedMessageType == QQmlProfilerDefinitions::RangeData
|
||||||
continue;
|
|| (d.messageType & (1 << decodedMessageType)) == 0) {
|
||||||
|
continue; // RangeData is sent together with RangeLocation
|
||||||
|
}
|
||||||
|
|
||||||
//### using QDataStream is relatively expensive
|
if (decodedMessageType == QQmlProfilerDefinitions::RangeEnd
|
||||||
|
|| decodedMessageType == QQmlProfilerDefinitions::RangeStart) {
|
||||||
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
|
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
|
||||||
|
if (trackLocations && d.locationId != 0)
|
||||||
QQmlProfiler::Location l = locations.value(d.locationId);
|
ds << static_cast<qint64>(d.locationId);
|
||||||
|
} else {
|
||||||
switch (decodedMessageType) {
|
auto i = locations.find(d.locationId);
|
||||||
case QQmlProfilerDefinitions::RangeStart:
|
if (i != locations.end()) {
|
||||||
case QQmlProfilerDefinitions::RangeEnd:
|
ds << d.time << decodedMessageType << static_cast<quint32>(d.detailType);
|
||||||
break;
|
ds << (i->url.isEmpty() ? i->location.sourceFile : i->url.toString())
|
||||||
case QQmlProfilerDefinitions::RangeData:
|
<< static_cast<qint32>(i->location.line)
|
||||||
ds << (l.location.sourceFile.isEmpty() ? l.url.toString() : l.location.sourceFile);
|
<< static_cast<qint32>(i->location.column);
|
||||||
break;
|
if (d.messageType & (1 << QQmlProfilerDefinitions::RangeData)) {
|
||||||
case QQmlProfilerDefinitions::RangeLocation:
|
// Send both, location and data ...
|
||||||
ds << (l.url.isEmpty() ? l.location.sourceFile : l.url.toString())
|
if (trackLocations)
|
||||||
<< static_cast<qint32>(l.location.line) << static_cast<qint32>(l.location.column);
|
ds << static_cast<qint64>(d.locationId);
|
||||||
break;
|
messages.append(ds.squeezedData());
|
||||||
default:
|
ds.clear();
|
||||||
Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
|
ds << d.time << QQmlProfilerDefinitions::RangeData
|
||||||
break;
|
<< static_cast<quint32>(d.detailType)
|
||||||
|
<< (i->location.sourceFile.isEmpty() ? i->url.toString() :
|
||||||
|
i->location.sourceFile);
|
||||||
|
}
|
||||||
|
if (trackLocations) {
|
||||||
|
ds << static_cast<qint64>(d.locationId);
|
||||||
|
locations.erase(i); // ... so that we can erase here without missing anything.
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Skip RangeData and RangeLocation: We've already sent them
|
||||||
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
messages.append(ds.squeezedData());
|
messages.append(ds.squeezedData());
|
||||||
ds.clear();
|
ds.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
|
qint64 QQmlProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
|
||||||
|
bool trackLocations)
|
||||||
{
|
{
|
||||||
while (next != data.length()) {
|
while (next != data.length()) {
|
||||||
const QQmlProfilerData &nextData = data.at(next);
|
const QQmlProfilerData &nextData = data.at(next);
|
||||||
if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
|
if (nextData.time > until || messages.length() > s_numMessagesPerBatch)
|
||||||
return nextData.time;
|
return nextData.time;
|
||||||
qQmlProfilerDataToByteArrays(nextData, locations, messages);
|
qQmlProfilerDataToByteArrays(nextData, locations, messages, trackLocations);
|
||||||
++next;
|
++next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,8 @@ class QQmlProfilerAdapter : public QQmlAbstractProfilerAdapter {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
|
QQmlProfilerAdapter(QQmlProfilerService *service, QQmlEnginePrivate *engine);
|
||||||
qint64 sendMessages(qint64 until, QList<QByteArray> &messages) Q_DECL_OVERRIDE;
|
qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
|
||||||
|
bool trackLocations) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void receiveData(const QVector<QQmlProfilerData> &new_data,
|
void receiveData(const QVector<QQmlProfilerData> &new_data,
|
||||||
|
|
|
@ -57,7 +57,7 @@ Q_QML_DEBUG_PLUGIN_LOADER(QQmlAbstractProfilerAdapter)
|
||||||
|
|
||||||
QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
|
QQmlProfilerServiceImpl::QQmlProfilerServiceImpl(QObject *parent) :
|
||||||
QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
|
QQmlConfigurableDebugService<QQmlProfilerService>(1, parent),
|
||||||
m_waitingForStop(false)
|
m_waitingForStop(false), m_useMessageTypes(false)
|
||||||
{
|
{
|
||||||
m_timer.start();
|
m_timer.start();
|
||||||
QQmlAbstractProfilerAdapter *quickAdapter =
|
QQmlAbstractProfilerAdapter *quickAdapter =
|
||||||
|
@ -309,7 +309,7 @@ void QQmlProfilerServiceImpl::stopProfiling(QJSEngine *engine)
|
||||||
m_waitingForStop = true;
|
m_waitingForStop = true;
|
||||||
|
|
||||||
foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
|
foreach (QQmlAbstractProfilerAdapter *profiler, reporting)
|
||||||
profiler->reportData();
|
profiler->reportData(m_useMessageTypes);
|
||||||
|
|
||||||
foreach (QQmlAbstractProfilerAdapter *profiler, stopping)
|
foreach (QQmlAbstractProfilerAdapter *profiler, stopping)
|
||||||
profiler->stopProfiling();
|
profiler->stopProfiling();
|
||||||
|
@ -343,7 +343,8 @@ void QQmlProfilerServiceImpl::sendMessages()
|
||||||
m_startTimes.erase(m_startTimes.begin());
|
m_startTimes.erase(m_startTimes.begin());
|
||||||
qint64 next = first->sendMessages(m_startTimes.isEmpty() ?
|
qint64 next = first->sendMessages(m_startTimes.isEmpty() ?
|
||||||
std::numeric_limits<qint64>::max() :
|
std::numeric_limits<qint64>::max() :
|
||||||
m_startTimes.begin().key(), messages);
|
m_startTimes.begin().key(), messages,
|
||||||
|
m_useMessageTypes);
|
||||||
if (next != -1)
|
if (next != -1)
|
||||||
m_startTimes.insert(next, first);
|
m_startTimes.insert(next, first);
|
||||||
|
|
||||||
|
@ -418,6 +419,8 @@ void QQmlProfilerServiceImpl::messageReceived(const QByteArray &message)
|
||||||
disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
|
disconnect(this, SIGNAL(stopFlushTimer()), &m_flushTimer, SLOT(stop()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!stream.atEnd())
|
||||||
|
stream >> m_useMessageTypes;
|
||||||
|
|
||||||
// If engineId == -1 objectForId() and then the cast will return 0.
|
// If engineId == -1 objectForId() and then the cast will return 0.
|
||||||
if (enabled)
|
if (enabled)
|
||||||
|
@ -435,14 +438,14 @@ void QQmlProfilerServiceImpl::flush()
|
||||||
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
|
foreach (QQmlAbstractProfilerAdapter *profiler, m_engineProfilers) {
|
||||||
if (profiler->isRunning()) {
|
if (profiler->isRunning()) {
|
||||||
m_startTimes.insert(-1, profiler);
|
m_startTimes.insert(-1, profiler);
|
||||||
profiler->reportData();
|
profiler->reportData(m_useMessageTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
|
foreach (QQmlAbstractProfilerAdapter *profiler, m_globalProfilers) {
|
||||||
if (profiler->isRunning()) {
|
if (profiler->isRunning()) {
|
||||||
m_startTimes.insert(-1, profiler);
|
m_startTimes.insert(-1, profiler);
|
||||||
profiler->reportData();
|
profiler->reportData(m_useMessageTypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -116,6 +116,7 @@ private:
|
||||||
QElapsedTimer m_timer;
|
QElapsedTimer m_timer;
|
||||||
QTimer m_flushTimer;
|
QTimer m_flushTimer;
|
||||||
bool m_waitingForStop;
|
bool m_waitingForStop;
|
||||||
|
bool m_useMessageTypes;
|
||||||
|
|
||||||
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
|
QList<QQmlAbstractProfilerAdapter *> m_globalProfilers;
|
||||||
QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
|
QMultiHash<QJSEngine *, QQmlAbstractProfilerAdapter *> m_engineProfilers;
|
||||||
|
|
|
@ -58,7 +58,7 @@ QV4ProfilerAdapter::QV4ProfilerAdapter(QQmlProfilerService *service, QV4::Execut
|
||||||
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
|
connect(this, SIGNAL(profilingDisabled()), engine->profiler, SLOT(stopProfiling()));
|
||||||
connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
|
connect(this, SIGNAL(profilingDisabledWhileWaiting()), engine->profiler, SLOT(stopProfiling()),
|
||||||
Qt::DirectConnection);
|
Qt::DirectConnection);
|
||||||
connect(this, SIGNAL(dataRequested()), engine->profiler, SLOT(reportData()));
|
connect(this, SIGNAL(dataRequested(bool)), engine->profiler, SLOT(reportData(bool)));
|
||||||
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
|
connect(this, SIGNAL(referenceTimeKnown(QElapsedTimer)),
|
||||||
engine->profiler, SLOT(setTimer(QElapsedTimer)));
|
engine->profiler, SLOT(setTimer(QElapsedTimer)));
|
||||||
connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
|
connect(engine->profiler, SIGNAL(dataReady(QV4::Profiling::FunctionLocationHash,
|
||||||
|
@ -105,13 +105,13 @@ qint64 QV4ProfilerAdapter::finalizeMessages(qint64 until, QList<QByteArray> &mes
|
||||||
return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
|
return callNext == -1 ? memoryNext : qMin(callNext, memoryNext);
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
|
qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
|
||||||
|
bool trackLocations)
|
||||||
{
|
{
|
||||||
QQmlDebugPacket d;
|
QQmlDebugPacket d;
|
||||||
|
|
||||||
// Make it const, so that we cannot accidentally detach it.
|
// Make it const, so that we cannot accidentally detach it.
|
||||||
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData;
|
const QVector<QV4::Profiling::FunctionCallProperties> &functionCallData = m_functionCallData;
|
||||||
const QV4::Profiling::FunctionLocationHash &functionLocations = m_functionLocations;
|
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
while (!m_stack.isEmpty() &&
|
while (!m_stack.isEmpty() &&
|
||||||
|
@ -133,17 +133,27 @@ qint64 QV4ProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &message
|
||||||
return finalizeMessages(until, messages, props.start, d);
|
return finalizeMessages(until, messages, props.start, d);
|
||||||
|
|
||||||
appendMemoryEvents(props.start, messages, d);
|
appendMemoryEvents(props.start, messages, d);
|
||||||
auto location = functionLocations.constFind(props.id);
|
auto location = m_functionLocations.find(props.id);
|
||||||
Q_ASSERT(location != functionLocations.constEnd());
|
|
||||||
|
|
||||||
d << props.start << RangeStart << Javascript;
|
d << props.start << RangeStart << Javascript;
|
||||||
|
if (trackLocations)
|
||||||
|
d << static_cast<qint64>(props.id);
|
||||||
|
if (location != m_functionLocations.end()) {
|
||||||
messages.push_back(d.squeezedData());
|
messages.push_back(d.squeezedData());
|
||||||
d.clear();
|
d.clear();
|
||||||
d << props.start << RangeLocation << Javascript << location->file << location->line
|
d << props.start << RangeLocation << Javascript << location->file << location->line
|
||||||
<< location->column;
|
<< location->column;
|
||||||
|
if (trackLocations)
|
||||||
|
d << static_cast<qint64>(props.id);
|
||||||
messages.push_back(d.squeezedData());
|
messages.push_back(d.squeezedData());
|
||||||
d.clear();
|
d.clear();
|
||||||
d << props.start << RangeData << Javascript << location->name;
|
d << props.start << RangeData << Javascript << location->name;
|
||||||
|
|
||||||
|
if (trackLocations) {
|
||||||
|
d << static_cast<qint64>(props.id);
|
||||||
|
m_functionLocations.erase(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
messages.push_back(d.squeezedData());
|
messages.push_back(d.squeezedData());
|
||||||
d.clear();
|
d.clear();
|
||||||
m_stack.push(props.end);
|
m_stack.push(props.end);
|
||||||
|
|
|
@ -67,7 +67,8 @@ class QV4ProfilerAdapter : public QQmlAbstractProfilerAdapter {
|
||||||
public:
|
public:
|
||||||
QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine);
|
QV4ProfilerAdapter(QQmlProfilerService *service, QV4::ExecutionEngine *engine);
|
||||||
|
|
||||||
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
|
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages,
|
||||||
|
bool trackLocations) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void v4ProfilingEnabled(quint64 v4Features);
|
void v4ProfilingEnabled(quint64 v4Features);
|
||||||
|
|
|
@ -61,8 +61,8 @@ QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
|
||||||
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
|
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
|
||||||
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
|
connect(this, SIGNAL(profilingDisabledWhileWaiting()),
|
||||||
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
|
QQuickProfiler::s_instance, SLOT(stopProfilingImpl()), Qt::DirectConnection);
|
||||||
connect(this, SIGNAL(dataRequested()),
|
connect(this, SIGNAL(dataRequested(bool)),
|
||||||
QQuickProfiler::s_instance, SLOT(reportDataImpl()), Qt::DirectConnection);
|
QQuickProfiler::s_instance, SLOT(reportDataImpl(bool)), Qt::DirectConnection);
|
||||||
connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
|
connect(QQuickProfiler::s_instance, SIGNAL(dataReady(QVector<QQuickProfilerData>)),
|
||||||
this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
|
this, SLOT(receiveData(QVector<QQuickProfilerData>)), Qt::DirectConnection);
|
||||||
}
|
}
|
||||||
|
@ -150,8 +150,10 @@ static void qQuickProfilerDataToByteArrays(const QQuickProfilerData &data,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
|
qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages,
|
||||||
|
bool trackLocations)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(trackLocations);
|
||||||
while (next < m_data.size()) {
|
while (next < m_data.size()) {
|
||||||
if (m_data[next].time <= until && messages.length() <= s_numMessagesPerBatch)
|
if (m_data[next].time <= until && messages.length() <= s_numMessagesPerBatch)
|
||||||
qQuickProfilerDataToByteArrays(m_data[next++], messages);
|
qQuickProfilerDataToByteArrays(m_data[next++], messages);
|
||||||
|
|
|
@ -61,7 +61,7 @@ class QQuickProfilerAdapter : public QQmlAbstractProfilerAdapter {
|
||||||
public:
|
public:
|
||||||
QQuickProfilerAdapter(QObject *parent = 0);
|
QQuickProfilerAdapter(QObject *parent = 0);
|
||||||
~QQuickProfilerAdapter();
|
~QQuickProfilerAdapter();
|
||||||
qint64 sendMessages(qint64 until, QList<QByteArray> &messages);
|
qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void receiveData(const QVector<QQuickProfilerData> &new_data);
|
void receiveData(const QVector<QQuickProfilerData> &new_data);
|
||||||
|
|
|
@ -1089,7 +1089,7 @@ void QSGD3D12RenderLoop::polishAndSync(WindowData *w, bool inExpose)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush pending touch events.
|
// Flush pending touch events.
|
||||||
QQuickWindowPrivate::get(window)->flushDelayedTouchEvent();
|
QQuickWindowPrivate::get(window)->flushFrameSynchronousEvents();
|
||||||
// The delivery of the event might have caused the window to stop rendering
|
// The delivery of the event might have caused the window to stop rendering
|
||||||
w = windowFor(windows, window);
|
w = windowFor(windows, window);
|
||||||
if (!w || !w->thread || !w->thread->exposedWindow) {
|
if (!w || !w->thread || !w->thread->exposedWindow) {
|
||||||
|
|
|
@ -72,23 +72,24 @@ using namespace QmlIR;
|
||||||
return false; \
|
return false; \
|
||||||
}
|
}
|
||||||
|
|
||||||
void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &loc)
|
void Object::init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &loc)
|
||||||
{
|
{
|
||||||
inheritedTypeNameIndex = typeNameIndex;
|
inheritedTypeNameIndex = typeNameIndex;
|
||||||
|
|
||||||
location.line = loc.startLine;
|
location.line = loc.startLine;
|
||||||
location.column = loc.startColumn;
|
location.column = loc.startColumn;
|
||||||
|
|
||||||
idIndex = id;
|
idNameIndex = idIndex;
|
||||||
|
id = -1;
|
||||||
indexOfDefaultPropertyOrAlias = -1;
|
indexOfDefaultPropertyOrAlias = -1;
|
||||||
defaultPropertyIsAlias = false;
|
defaultPropertyIsAlias = false;
|
||||||
|
flags = QV4::CompiledData::Object::NoFlag;
|
||||||
properties = pool->New<PoolList<Property> >();
|
properties = pool->New<PoolList<Property> >();
|
||||||
aliases = pool->New<PoolList<Alias> >();
|
aliases = pool->New<PoolList<Alias> >();
|
||||||
qmlSignals = pool->New<PoolList<Signal> >();
|
qmlSignals = pool->New<PoolList<Signal> >();
|
||||||
bindings = pool->New<PoolList<Binding> >();
|
bindings = pool->New<PoolList<Binding> >();
|
||||||
functions = pool->New<PoolList<Function> >();
|
functions = pool->New<PoolList<Function> >();
|
||||||
functionsAndExpressions = pool->New<PoolList<CompiledFunctionOrExpression> >();
|
functionsAndExpressions = pool->New<PoolList<CompiledFunctionOrExpression> >();
|
||||||
runtimeFunctionIndices = 0;
|
|
||||||
declarationsOverride = 0;
|
declarationsOverride = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1237,10 +1238,10 @@ bool IRBuilder::setId(const QQmlJS::AST::SourceLocation &idLocation, QQmlJS::AST
|
||||||
if (illegalNames.contains(idQString))
|
if (illegalNames.contains(idQString))
|
||||||
COMPILE_EXCEPTION(loc, tr( "ID illegally masks global JavaScript property"));
|
COMPILE_EXCEPTION(loc, tr( "ID illegally masks global JavaScript property"));
|
||||||
|
|
||||||
if (_object->idIndex != emptyStringIndex)
|
if (_object->idNameIndex != emptyStringIndex)
|
||||||
COMPILE_EXCEPTION(idLocation, tr("Property value set multiple times"));
|
COMPILE_EXCEPTION(idLocation, tr("Property value set multiple times"));
|
||||||
|
|
||||||
_object->idIndex = registerString(idQString);
|
_object->idNameIndex = registerString(idQString);
|
||||||
_object->locationOfIdProperty.line = idLocation.startLine;
|
_object->locationOfIdProperty.line = idLocation.startLine;
|
||||||
_object->locationOfIdProperty.column = idLocation.startColumn;
|
_object->locationOfIdProperty.column = idLocation.startColumn;
|
||||||
|
|
||||||
|
@ -1368,12 +1369,12 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
||||||
const int importSize = sizeof(QV4::CompiledData::Import) * output.imports.count();
|
const int importSize = sizeof(QV4::CompiledData::Import) * output.imports.count();
|
||||||
const int objectOffsetTableSize = output.objects.count() * sizeof(quint32);
|
const int objectOffsetTableSize = output.objects.count() * sizeof(quint32);
|
||||||
|
|
||||||
QHash<Object*, quint32> objectOffsets;
|
QHash<const Object*, quint32> objectOffsets;
|
||||||
|
|
||||||
int objectsSize = 0;
|
int objectsSize = 0;
|
||||||
foreach (Object *o, output.objects) {
|
foreach (Object *o, output.objects) {
|
||||||
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
|
objectOffsets.insert(o, unitSize + importSize + objectOffsetTableSize + objectsSize);
|
||||||
objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
|
objectsSize += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
|
||||||
|
|
||||||
int signalTableSize = 0;
|
int signalTableSize = 0;
|
||||||
for (const Signal *s = o->firstSignal(); s; s = s->next)
|
for (const Signal *s = o->firstSignal(); s; s = s->next)
|
||||||
|
@ -1413,14 +1414,17 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
||||||
// write objects
|
// write objects
|
||||||
quint32 *objectTable = reinterpret_cast<quint32*>(data + qmlUnit->offsetToObjects);
|
quint32 *objectTable = reinterpret_cast<quint32*>(data + qmlUnit->offsetToObjects);
|
||||||
char *objectPtr = data + qmlUnit->offsetToObjects + objectOffsetTableSize;
|
char *objectPtr = data + qmlUnit->offsetToObjects + objectOffsetTableSize;
|
||||||
foreach (Object *o, output.objects) {
|
for (int i = 0; i < output.objects.count(); ++i) {
|
||||||
|
const Object *o = output.objects.at(i);
|
||||||
*objectTable++ = objectOffsets.value(o);
|
*objectTable++ = objectOffsets.value(o);
|
||||||
|
|
||||||
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
|
QV4::CompiledData::Object *objectToWrite = reinterpret_cast<QV4::CompiledData::Object*>(objectPtr);
|
||||||
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
|
objectToWrite->inheritedTypeNameIndex = o->inheritedTypeNameIndex;
|
||||||
objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
|
objectToWrite->indexOfDefaultPropertyOrAlias = o->indexOfDefaultPropertyOrAlias;
|
||||||
objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
|
objectToWrite->defaultPropertyIsAlias = o->defaultPropertyIsAlias;
|
||||||
objectToWrite->idIndex = o->idIndex;
|
objectToWrite->flags = o->flags;
|
||||||
|
objectToWrite->idNameIndex = o->idNameIndex;
|
||||||
|
objectToWrite->id = o->id;
|
||||||
objectToWrite->location = o->location;
|
objectToWrite->location = o->location;
|
||||||
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
|
objectToWrite->locationOfIdProperty = o->locationOfIdProperty;
|
||||||
|
|
||||||
|
@ -1446,9 +1450,13 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
||||||
objectToWrite->offsetToBindings = nextOffset;
|
objectToWrite->offsetToBindings = nextOffset;
|
||||||
nextOffset += objectToWrite->nBindings * sizeof(QV4::CompiledData::Binding);
|
nextOffset += objectToWrite->nBindings * sizeof(QV4::CompiledData::Binding);
|
||||||
|
|
||||||
|
objectToWrite->nNamedObjectsInComponent = o->namedObjectsInComponent.count;
|
||||||
|
objectToWrite->offsetToNamedObjectsInComponent = nextOffset;
|
||||||
|
nextOffset += objectToWrite->nNamedObjectsInComponent * sizeof(quint32);
|
||||||
|
|
||||||
quint32 *functionsTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToFunctions);
|
quint32 *functionsTable = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToFunctions);
|
||||||
for (const Function *f = o->firstFunction(); f; f = f->next)
|
for (const Function *f = o->firstFunction(); f; f = f->next)
|
||||||
*functionsTable++ = o->runtimeFunctionIndices->at(f->index);
|
*functionsTable++ = o->runtimeFunctionIndices.at(f->index);
|
||||||
|
|
||||||
char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties;
|
char *propertiesPtr = objectPtr + objectToWrite->offsetToProperties;
|
||||||
for (const Property *p = o->firstProperty(); p; p = p->next) {
|
for (const Property *p = o->firstProperty(); p; p = p->next) {
|
||||||
|
@ -1492,7 +1500,12 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
||||||
signalPtr += size;
|
signalPtr += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount());
|
quint32 *namedObjectInComponentPtr = reinterpret_cast<quint32*>(objectPtr + objectToWrite->offsetToNamedObjectsInComponent);
|
||||||
|
for (int i = 0; i < o->namedObjectsInComponent.count; ++i) {
|
||||||
|
*namedObjectInComponentPtr++ = o->namedObjectsInComponent.at(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
objectPtr += QV4::CompiledData::Object::calculateSizeExcludingSignals(o->functionCount(), o->propertyCount(), o->aliasCount(), o->signalCount(), o->bindingCount(), o->namedObjectsInComponent.count);
|
||||||
objectPtr += signalTableSize;
|
objectPtr += signalTableSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1509,7 +1522,7 @@ QV4::CompiledData::Unit *QmlUnitGenerator::generate(Document &output)
|
||||||
return qmlUnit;
|
return qmlUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter filter) const
|
char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const
|
||||||
{
|
{
|
||||||
for (const Binding *b = o->firstBinding(); b; b = b->next) {
|
for (const Binding *b = o->firstBinding(); b; b = b->next) {
|
||||||
if (!(b->*(filter))())
|
if (!(b->*(filter))())
|
||||||
|
@ -1517,7 +1530,7 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, Object *o, BindingFilter
|
||||||
QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr);
|
QV4::CompiledData::Binding *bindingToWrite = reinterpret_cast<QV4::CompiledData::Binding*>(bindingPtr);
|
||||||
*bindingToWrite = *b;
|
*bindingToWrite = *b;
|
||||||
if (b->type == QV4::CompiledData::Binding::Type_Script)
|
if (b->type == QV4::CompiledData::Binding::Type_Script)
|
||||||
bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices->at(b->value.compiledScriptIndex);
|
bindingToWrite->value.compiledScriptIndex = o->runtimeFunctionIndices.at(b->value.compiledScriptIndex);
|
||||||
bindingPtr += sizeof(QV4::CompiledData::Binding);
|
bindingPtr += sizeof(QV4::CompiledData::Binding);
|
||||||
}
|
}
|
||||||
return bindingPtr;
|
return bindingPtr;
|
||||||
|
|
|
@ -170,7 +170,12 @@ class FixedPoolArray
|
||||||
public:
|
public:
|
||||||
int count;
|
int count;
|
||||||
|
|
||||||
void init(QQmlJS::MemoryPool *pool, const QVector<T> &vector)
|
FixedPoolArray()
|
||||||
|
: data(0)
|
||||||
|
, count(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void allocate(QQmlJS::MemoryPool *pool, const QVector<T> &vector)
|
||||||
{
|
{
|
||||||
count = vector.count();
|
count = vector.count();
|
||||||
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
|
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
|
||||||
|
@ -183,6 +188,16 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Container>
|
||||||
|
void allocate(QQmlJS::MemoryPool *pool, const Container &container)
|
||||||
|
{
|
||||||
|
count = container.count();
|
||||||
|
data = reinterpret_cast<T*>(pool->allocate(count * sizeof(T)));
|
||||||
|
typename Container::ConstIterator it = container.constBegin();
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
new (data + i) T(*it++);
|
||||||
|
}
|
||||||
|
|
||||||
const T &at(int index) const {
|
const T &at(int index) const {
|
||||||
Q_ASSERT(index >= 0 && index < count);
|
Q_ASSERT(index >= 0 && index < count);
|
||||||
return data[index];
|
return data[index];
|
||||||
|
@ -274,9 +289,11 @@ struct Q_QML_PRIVATE_EXPORT Object
|
||||||
Q_DECLARE_TR_FUNCTIONS(Object)
|
Q_DECLARE_TR_FUNCTIONS(Object)
|
||||||
public:
|
public:
|
||||||
quint32 inheritedTypeNameIndex;
|
quint32 inheritedTypeNameIndex;
|
||||||
quint32 idIndex;
|
quint32 idNameIndex;
|
||||||
int indexOfDefaultPropertyOrAlias : 31;
|
int id;
|
||||||
int defaultPropertyIsAlias : 1;
|
int indexOfDefaultPropertyOrAlias;
|
||||||
|
bool defaultPropertyIsAlias;
|
||||||
|
int flags;
|
||||||
|
|
||||||
QV4::CompiledData::Location location;
|
QV4::CompiledData::Location location;
|
||||||
QV4::CompiledData::Location locationOfIdProperty;
|
QV4::CompiledData::Location locationOfIdProperty;
|
||||||
|
@ -296,7 +313,7 @@ public:
|
||||||
// specified object. Used for declarations inside group properties.
|
// specified object. Used for declarations inside group properties.
|
||||||
Object *declarationsOverride;
|
Object *declarationsOverride;
|
||||||
|
|
||||||
void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int id, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation());
|
void init(QQmlJS::MemoryPool *pool, int typeNameIndex, int idIndex, const QQmlJS::AST::SourceLocation &location = QQmlJS::AST::SourceLocation());
|
||||||
|
|
||||||
QString sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
|
QString sanityCheckFunctionNames(const QSet<QString> &illegalNames, QQmlJS::AST::SourceLocation *errorLocation);
|
||||||
|
|
||||||
|
@ -312,7 +329,9 @@ public:
|
||||||
QString bindingAsString(Document *doc, int scriptIndex) const;
|
QString bindingAsString(Document *doc, int scriptIndex) const;
|
||||||
|
|
||||||
PoolList<CompiledFunctionOrExpression> *functionsAndExpressions;
|
PoolList<CompiledFunctionOrExpression> *functionsAndExpressions;
|
||||||
FixedPoolArray<int> *runtimeFunctionIndices;
|
FixedPoolArray<int> runtimeFunctionIndices;
|
||||||
|
|
||||||
|
FixedPoolArray<quint32> namedObjectsInComponent;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct IRLoader;
|
friend struct IRLoader;
|
||||||
|
@ -467,7 +486,7 @@ struct Q_QML_PRIVATE_EXPORT QmlUnitGenerator
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef bool (Binding::*BindingFilter)() const;
|
typedef bool (Binding::*BindingFilter)() const;
|
||||||
char *writeBindings(char *bindingPtr, Object *o, BindingFilter filter) const;
|
char *writeBindings(char *bindingPtr, const Object *o, BindingFilter filter) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef V4_BOOTSTRAP
|
#ifndef V4_BOOTSTRAP
|
||||||
|
|
|
@ -65,16 +65,16 @@ QQmlTypeCompiler::QQmlTypeCompiler(QQmlEnginePrivate *engine, QQmlCompiledData *
|
||||||
|
|
||||||
bool QQmlTypeCompiler::compile()
|
bool QQmlTypeCompiler::compile()
|
||||||
{
|
{
|
||||||
compiledData->importCache = new QQmlTypeNameCache;
|
importCache = new QQmlTypeNameCache;
|
||||||
|
|
||||||
foreach (const QString &ns, typeData->namespaces())
|
foreach (const QString &ns, typeData->namespaces())
|
||||||
compiledData->importCache->add(ns);
|
importCache->add(ns);
|
||||||
|
|
||||||
// Add any Composite Singletons that were used to the import cache
|
// Add any Composite Singletons that were used to the import cache
|
||||||
foreach (const QQmlTypeData::TypeReference &singleton, typeData->compositeSingletons())
|
foreach (const QQmlTypeData::TypeReference &singleton, typeData->compositeSingletons())
|
||||||
compiledData->importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
|
importCache->add(singleton.type->qmlTypeName(), singleton.type->sourceUrl(), singleton.prefix);
|
||||||
|
|
||||||
typeData->imports().populateCache(compiledData->importCache);
|
typeData->imports().populateCache(importCache.data());
|
||||||
|
|
||||||
const QHash<int, QQmlTypeData::TypeReference> &resolvedTypes = typeData->resolvedTypeRefs();
|
const QHash<int, QQmlTypeData::TypeReference> &resolvedTypes = typeData->resolvedTypeRefs();
|
||||||
for (QHash<int, QQmlTypeData::TypeReference>::ConstIterator resolvedType = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
|
for (QHash<int, QQmlTypeData::TypeReference>::ConstIterator resolvedType = resolvedTypes.constBegin(), end = resolvedTypes.constEnd();
|
||||||
|
@ -137,8 +137,6 @@ bool QQmlTypeCompiler::compile()
|
||||||
customParsers.insert(it.key(), customParser);
|
customParsers.insert(it.key(), customParser);
|
||||||
}
|
}
|
||||||
|
|
||||||
compiledData->propertyCaches.reserve(document->objects.count());
|
|
||||||
|
|
||||||
{
|
{
|
||||||
QQmlPropertyCacheCreator propertyCacheBuilder(this);
|
QQmlPropertyCacheCreator propertyCacheBuilder(this);
|
||||||
if (!propertyCacheBuilder.buildMetaObjects())
|
if (!propertyCacheBuilder.buildMetaObjects())
|
||||||
|
@ -174,7 +172,8 @@ bool QQmlTypeCompiler::compile()
|
||||||
|
|
||||||
// Collect imported scripts
|
// Collect imported scripts
|
||||||
const QList<QQmlTypeData::ScriptReference> &scripts = typeData->resolvedScripts();
|
const QList<QQmlTypeData::ScriptReference> &scripts = typeData->resolvedScripts();
|
||||||
compiledData->scripts.reserve(scripts.count());
|
QVector<QQmlScriptData *> dependentScripts;
|
||||||
|
dependentScripts.reserve(scripts.count());
|
||||||
for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
|
for (int scriptIndex = 0; scriptIndex < scripts.count(); ++scriptIndex) {
|
||||||
const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
|
const QQmlTypeData::ScriptReference &script = scripts.at(scriptIndex);
|
||||||
|
|
||||||
|
@ -187,10 +186,10 @@ bool QQmlTypeCompiler::compile()
|
||||||
qualifier = qualifier.mid(lastDotIndex+1);
|
qualifier = qualifier.mid(lastDotIndex+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
compiledData->importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
|
importCache->add(qualifier.toString(), scriptIndex, enclosingNamespace);
|
||||||
QQmlScriptData *scriptData = script.script->scriptData();
|
QQmlScriptData *scriptData = script.script->scriptData();
|
||||||
scriptData->addref();
|
scriptData->addref();
|
||||||
compiledData->scripts << scriptData;
|
dependentScripts << scriptData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resolve component boundaries and aliases
|
// Resolve component boundaries and aliases
|
||||||
|
@ -202,6 +201,12 @@ bool QQmlTypeCompiler::compile()
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
QQmlDeferredAndCustomParserBindingScanner deferredAndCustomParserBindingScanner(this);
|
||||||
|
if (!deferredAndCustomParserBindingScanner.scanObject())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Compile JS binding expressions and signal handlers
|
// Compile JS binding expressions and signal handlers
|
||||||
if (!document->javaScriptCompilationUnit) {
|
if (!document->javaScriptCompilationUnit) {
|
||||||
{
|
{
|
||||||
|
@ -211,7 +216,7 @@ bool QQmlTypeCompiler::compile()
|
||||||
sss.scan();
|
sss.scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, compiledData->importCache, &document->jsGenerator.stringTable);
|
QmlIR::JSCodeGen v4CodeGenerator(typeData->finalUrlString(), document->code, &document->jsModule, &document->jsParserEngine, document->program, importCache, &document->jsGenerator.stringTable);
|
||||||
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
|
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
|
||||||
if (!jsCodeGen.generateCodeForComponents())
|
if (!jsCodeGen.generateCodeForComponents())
|
||||||
return false;
|
return false;
|
||||||
|
@ -236,9 +241,12 @@ bool QQmlTypeCompiler::compile()
|
||||||
document->javaScriptCompilationUnit->data = qmlUnit;
|
document->javaScriptCompilationUnit->data = qmlUnit;
|
||||||
|
|
||||||
compiledData->compilationUnit = document->javaScriptCompilationUnit;
|
compiledData->compilationUnit = document->javaScriptCompilationUnit;
|
||||||
|
compiledData->compilationUnit->propertyCaches = m_propertyCaches;
|
||||||
|
compiledData->compilationUnit->importCache = importCache;
|
||||||
|
compiledData->compilationUnit->dependentScripts = dependentScripts;
|
||||||
|
|
||||||
// Add to type registry of composites
|
// Add to type registry of composites
|
||||||
if (compiledData->isCompositeType())
|
if (compiledData->compilationUnit->isCompositeType())
|
||||||
engine->registerInternalCompositeType(compiledData);
|
engine->registerInternalCompositeType(compiledData);
|
||||||
else {
|
else {
|
||||||
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
|
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(qmlUnit->indexOfRootObject);
|
||||||
|
@ -272,18 +280,18 @@ bool QQmlTypeCompiler::compile()
|
||||||
}
|
}
|
||||||
++objectCount;
|
++objectCount;
|
||||||
if (typeRef->component) {
|
if (typeRef->component) {
|
||||||
bindingCount += typeRef->component->totalBindingsCount;
|
bindingCount += typeRef->component->compilationUnit->totalBindingsCount;
|
||||||
parserStatusCount += typeRef->component->totalParserStatusCount;
|
parserStatusCount += typeRef->component->compilationUnit->totalParserStatusCount;
|
||||||
objectCount += typeRef->component->totalObjectCount;
|
objectCount += typeRef->component->compilationUnit->totalObjectCount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compiledData->totalBindingsCount = bindingCount;
|
compiledData->compilationUnit->totalBindingsCount = bindingCount;
|
||||||
compiledData->totalParserStatusCount = parserStatusCount;
|
compiledData->compilationUnit->totalParserStatusCount = parserStatusCount;
|
||||||
compiledData->totalObjectCount = objectCount;
|
compiledData->compilationUnit->totalObjectCount = objectCount;
|
||||||
|
|
||||||
Q_ASSERT(compiledData->propertyCaches.count() == static_cast<int>(compiledData->compilationUnit->data->nObjects));
|
Q_ASSERT(compiledData->compilationUnit->propertyCaches.count() == static_cast<int>(compiledData->compilationUnit->data->nObjects));
|
||||||
|
|
||||||
return errors.isEmpty();
|
return errors.isEmpty();
|
||||||
}
|
}
|
||||||
|
@ -337,28 +345,13 @@ int QQmlTypeCompiler::rootObjectIndex() const
|
||||||
|
|
||||||
void QQmlTypeCompiler::setPropertyCaches(const QQmlPropertyCacheVector &caches)
|
void QQmlTypeCompiler::setPropertyCaches(const QQmlPropertyCacheVector &caches)
|
||||||
{
|
{
|
||||||
compiledData->propertyCaches = caches;
|
m_propertyCaches = caches;
|
||||||
Q_ASSERT(caches.count() >= document->indexOfRootObject);
|
Q_ASSERT(caches.count() >= document->indexOfRootObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QQmlPropertyCacheVector &QQmlTypeCompiler::propertyCaches() const
|
const QQmlPropertyCacheVector &QQmlTypeCompiler::propertyCaches() const
|
||||||
{
|
{
|
||||||
return compiledData->propertyCaches;
|
return m_propertyCaches;
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, int> *QQmlTypeCompiler::objectIndexToIdForRoot()
|
|
||||||
{
|
|
||||||
return &compiledData->objectIndexToIdForRoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QHash<int, int> > *QQmlTypeCompiler::objectIndexToIdPerComponent()
|
|
||||||
{
|
|
||||||
return &compiledData->objectIndexToIdPerComponent;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<int, QBitArray> *QQmlTypeCompiler::customParserBindings()
|
|
||||||
{
|
|
||||||
return &compiledData->customParserBindings;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlJS::MemoryPool *QQmlTypeCompiler::memoryPool()
|
QQmlJS::MemoryPool *QQmlTypeCompiler::memoryPool()
|
||||||
|
@ -376,11 +369,6 @@ const QV4::Compiler::StringTableGenerator *QQmlTypeCompiler::stringPool() const
|
||||||
return &document->jsGenerator.stringTable;
|
return &document->jsGenerator.stringTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlTypeCompiler::setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject)
|
|
||||||
{
|
|
||||||
compiledData->deferredBindingsPerObject = deferredBindingsPerObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
|
void QQmlTypeCompiler::setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData)
|
||||||
{
|
{
|
||||||
compiledData->compilationUnit->bindingPropertyDataPerObject = propertyData;
|
compiledData->compilationUnit->bindingPropertyDataPerObject = propertyData;
|
||||||
|
@ -1324,11 +1312,8 @@ QQmlComponentAndAliasResolver::QQmlComponentAndAliasResolver(QQmlTypeCompiler *t
|
||||||
, qmlObjects(typeCompiler->qmlObjects())
|
, qmlObjects(typeCompiler->qmlObjects())
|
||||||
, indexOfRootObject(typeCompiler->rootObjectIndex())
|
, indexOfRootObject(typeCompiler->rootObjectIndex())
|
||||||
, _componentIndex(-1)
|
, _componentIndex(-1)
|
||||||
, _objectIndexToIdInScope(0)
|
|
||||||
, resolvedTypes(typeCompiler->resolvedTypes())
|
, resolvedTypes(typeCompiler->resolvedTypes())
|
||||||
, propertyCaches(typeCompiler->propertyCaches())
|
, propertyCaches(typeCompiler->propertyCaches())
|
||||||
, objectIndexToIdForRoot(typeCompiler->objectIndexToIdForRoot())
|
|
||||||
, objectIndexToIdPerComponent(typeCompiler->objectIndexToIdPerComponent())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1351,7 +1336,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
|
||||||
if (targetType->metaObject() == &QQmlComponent::staticMetaObject)
|
if (targetType->metaObject() == &QQmlComponent::staticMetaObject)
|
||||||
continue;
|
continue;
|
||||||
} else if (tr->component) {
|
} else if (tr->component) {
|
||||||
if (tr->component->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject)
|
if (tr->component->compilationUnit->rootPropertyCache()->firstCppMetaObject() == &QQmlComponent::staticMetaObject)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1382,6 +1367,7 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
|
||||||
QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>();
|
QmlIR::Object *syntheticComponent = pool->New<QmlIR::Object>();
|
||||||
syntheticComponent->init(pool, compiler->registerString(QString::fromUtf8(componentType->typeName())), compiler->registerString(QString()));
|
syntheticComponent->init(pool, compiler->registerString(QString::fromUtf8(componentType->typeName())), compiler->registerString(QString()));
|
||||||
syntheticComponent->location = binding->valueLocation;
|
syntheticComponent->location = binding->valueLocation;
|
||||||
|
syntheticComponent->flags |= QV4::CompiledData::Object::IsComponent;
|
||||||
|
|
||||||
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
|
if (!resolvedTypes->contains(syntheticComponent->inheritedTypeNameIndex)) {
|
||||||
QQmlCompiledData::TypeReference *typeRef = new QQmlCompiledData::TypeReference;
|
QQmlCompiledData::TypeReference *typeRef = new QQmlCompiledData::TypeReference;
|
||||||
|
@ -1408,7 +1394,6 @@ void QQmlComponentAndAliasResolver::findAndRegisterImplicitComponents(const QmlI
|
||||||
binding->value.objectIndex = componentIndex;
|
binding->value.objectIndex = componentIndex;
|
||||||
|
|
||||||
componentRoots.append(componentIndex);
|
componentRoots.append(componentIndex);
|
||||||
componentBoundaries.append(syntheticBinding->value.objectIndex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1420,7 +1405,7 @@ bool QQmlComponentAndAliasResolver::resolve()
|
||||||
// on the left hand side is of QQmlComponent type.
|
// on the left hand side is of QQmlComponent type.
|
||||||
const int objCountWithoutSynthesizedComponents = qmlObjects->count();
|
const int objCountWithoutSynthesizedComponents = qmlObjects->count();
|
||||||
for (int i = 0; i < objCountWithoutSynthesizedComponents; ++i) {
|
for (int i = 0; i < objCountWithoutSynthesizedComponents; ++i) {
|
||||||
const QmlIR::Object *obj = qmlObjects->at(i);
|
QmlIR::Object *obj = qmlObjects->at(i);
|
||||||
QQmlPropertyCache *cache = propertyCaches.at(i).data();
|
QQmlPropertyCache *cache = propertyCaches.at(i).data();
|
||||||
if (obj->inheritedTypeNameIndex == 0 && !cache)
|
if (obj->inheritedTypeNameIndex == 0 && !cache)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1439,7 +1424,7 @@ bool QQmlComponentAndAliasResolver::resolve()
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
componentRoots.append(i);
|
obj->flags |= QV4::CompiledData::Object::IsComponent;
|
||||||
|
|
||||||
if (obj->functionCount() > 0)
|
if (obj->functionCount() > 0)
|
||||||
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
|
COMPILE_EXCEPTION(obj, tr("Component objects cannot declare new functions."));
|
||||||
|
@ -1461,20 +1446,20 @@ bool QQmlComponentAndAliasResolver::resolve()
|
||||||
if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
|
if (rootBinding->next || rootBinding->type != QV4::CompiledData::Binding::Type_Object)
|
||||||
COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
|
COMPILE_EXCEPTION(obj, tr("Invalid component body specification"));
|
||||||
|
|
||||||
componentBoundaries.append(rootBinding->value.objectIndex);
|
// We are going to collect ids/aliases and resolve them for the root object as a separate
|
||||||
|
// last pass.
|
||||||
|
if (i != indexOfRootObject)
|
||||||
|
componentRoots.append(i);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(componentBoundaries.begin(), componentBoundaries.end());
|
|
||||||
|
|
||||||
for (int i = 0; i < componentRoots.count(); ++i) {
|
for (int i = 0; i < componentRoots.count(); ++i) {
|
||||||
const QmlIR::Object *component = qmlObjects->at(componentRoots.at(i));
|
QmlIR::Object *component = qmlObjects->at(componentRoots.at(i));
|
||||||
const QmlIR::Binding *rootBinding = component->firstBinding();
|
const QmlIR::Binding *rootBinding = component->firstBinding();
|
||||||
|
|
||||||
_componentIndex = i;
|
_componentIndex = i;
|
||||||
_idToObjectIndex.clear();
|
_idToObjectIndex.clear();
|
||||||
|
|
||||||
_objectIndexToIdInScope = &(*objectIndexToIdPerComponent)[componentRoots.at(i)];
|
|
||||||
|
|
||||||
_objectsWithAliases.clear();
|
_objectsWithAliases.clear();
|
||||||
|
|
||||||
if (!collectIdsAndAliases(rootBinding->value.objectIndex))
|
if (!collectIdsAndAliases(rootBinding->value.objectIndex))
|
||||||
|
@ -1482,51 +1467,56 @@ bool QQmlComponentAndAliasResolver::resolve()
|
||||||
|
|
||||||
if (!resolveAliases())
|
if (!resolveAliases())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
component->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Collect ids and aliases for root
|
// Collect ids and aliases for root
|
||||||
_componentIndex = -1;
|
_componentIndex = -1;
|
||||||
_idToObjectIndex.clear();
|
_idToObjectIndex.clear();
|
||||||
_objectIndexToIdInScope = objectIndexToIdForRoot;
|
|
||||||
_objectsWithAliases.clear();
|
_objectsWithAliases.clear();
|
||||||
|
|
||||||
collectIdsAndAliases(indexOfRootObject);
|
collectIdsAndAliases(indexOfRootObject);
|
||||||
|
|
||||||
resolveAliases();
|
resolveAliases();
|
||||||
|
|
||||||
|
QmlIR::Object *rootComponent = qmlObjects->at(indexOfRootObject);
|
||||||
|
rootComponent->namedObjectsInComponent.allocate(pool, _idToObjectIndex);
|
||||||
|
|
||||||
// Implicit component insertion may have added objects and thus we also need
|
// Implicit component insertion may have added objects and thus we also need
|
||||||
// to extend the symmetric propertyCaches.
|
// to extend the symmetric propertyCaches.
|
||||||
compiler->setPropertyCaches(propertyCaches);
|
compiler->setPropertyCaches(propertyCaches);
|
||||||
|
compiler->setComponentRoots(componentRoots);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
|
bool QQmlComponentAndAliasResolver::collectIdsAndAliases(int objectIndex)
|
||||||
{
|
{
|
||||||
const QmlIR::Object *obj = qmlObjects->at(objectIndex);
|
QmlIR::Object *obj = qmlObjects->at(objectIndex);
|
||||||
|
|
||||||
if (obj->idIndex != 0) {
|
if (obj->idNameIndex != 0) {
|
||||||
if (_idToObjectIndex.contains(obj->idIndex)) {
|
if (_idToObjectIndex.contains(obj->idNameIndex)) {
|
||||||
recordError(obj->locationOfIdProperty, tr("id is not unique"));
|
recordError(obj->locationOfIdProperty, tr("id is not unique"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_idToObjectIndex.insert(obj->idIndex, objectIndex);
|
obj->id = _idToObjectIndex.count();
|
||||||
_objectIndexToIdInScope->insert(objectIndex, _objectIndexToIdInScope->count());
|
_idToObjectIndex.insert(obj->idNameIndex, objectIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->aliasCount() > 0)
|
if (obj->aliasCount() > 0)
|
||||||
_objectsWithAliases.append(objectIndex);
|
_objectsWithAliases.append(objectIndex);
|
||||||
|
|
||||||
|
// Stop at Component boundary
|
||||||
|
if (obj->flags & QV4::CompiledData::Object::IsComponent && objectIndex != compiler->rootObjectIndex())
|
||||||
|
return true;
|
||||||
|
|
||||||
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
for (const QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||||
if (binding->type != QV4::CompiledData::Binding::Type_Object
|
if (binding->type != QV4::CompiledData::Binding::Type_Object
|
||||||
&& binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
|
&& binding->type != QV4::CompiledData::Binding::Type_AttachedProperty
|
||||||
&& binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
|
&& binding->type != QV4::CompiledData::Binding::Type_GroupProperty)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Stop at Component boundary
|
|
||||||
if (std::binary_search(componentBoundaries.constBegin(), componentBoundaries.constEnd(), binding->value.objectIndex))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!collectIdsAndAliases(binding->value.objectIndex))
|
if (!collectIdsAndAliases(binding->value.objectIndex))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1555,8 +1545,9 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
||||||
}
|
}
|
||||||
Q_ASSERT(!(alias->flags & QV4::CompiledData::Alias::Resolved));
|
Q_ASSERT(!(alias->flags & QV4::CompiledData::Alias::Resolved));
|
||||||
alias->flags |= QV4::CompiledData::Alias::Resolved;
|
alias->flags |= QV4::CompiledData::Alias::Resolved;
|
||||||
Q_ASSERT(_objectIndexToIdInScope->contains(targetObjectIndex));
|
const QmlIR::Object *targetObject = qmlObjects->at(targetObjectIndex);
|
||||||
alias->targetObjectId = _objectIndexToIdInScope->value(targetObjectIndex);
|
Q_ASSERT(targetObject->id >= 0);
|
||||||
|
alias->targetObjectId = targetObject->id;
|
||||||
|
|
||||||
const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
|
const QString aliasPropertyValue = stringAt(alias->propertyNameIndex);
|
||||||
|
|
||||||
|
@ -1668,6 +1659,126 @@ bool QQmlComponentAndAliasResolver::resolveAliases()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QQmlDeferredAndCustomParserBindingScanner::QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler)
|
||||||
|
: QQmlCompilePass(typeCompiler)
|
||||||
|
, qmlObjects(typeCompiler->qmlObjects())
|
||||||
|
, propertyCaches(typeCompiler->propertyCaches())
|
||||||
|
, customParsers(typeCompiler->customParserCache())
|
||||||
|
, _seenObjectWithId(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QQmlDeferredAndCustomParserBindingScanner::scanObject()
|
||||||
|
{
|
||||||
|
return scanObject(compiler->rootObjectIndex());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QQmlDeferredAndCustomParserBindingScanner::scanObject(int objectIndex)
|
||||||
|
{
|
||||||
|
QmlIR::Object *obj = qmlObjects->at(objectIndex);
|
||||||
|
if (obj->idNameIndex != 0)
|
||||||
|
_seenObjectWithId = true;
|
||||||
|
|
||||||
|
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
|
||||||
|
Q_ASSERT(obj->bindingCount() == 1);
|
||||||
|
const QV4::CompiledData::Binding *componentBinding = obj->firstBinding();
|
||||||
|
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
|
||||||
|
return scanObject(componentBinding->value.objectIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
QQmlPropertyCache *propertyCache = propertyCaches.at(objectIndex).data();
|
||||||
|
if (!propertyCache)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
QString defaultPropertyName;
|
||||||
|
QQmlPropertyData *defaultProperty = 0;
|
||||||
|
if (obj->indexOfDefaultPropertyOrAlias != -1) {
|
||||||
|
QQmlPropertyCache *cache = propertyCache->parent();
|
||||||
|
defaultPropertyName = cache->defaultPropertyName();
|
||||||
|
defaultProperty = cache->defaultProperty();
|
||||||
|
} else {
|
||||||
|
defaultPropertyName = propertyCache->defaultPropertyName();
|
||||||
|
defaultProperty = propertyCache->defaultProperty();
|
||||||
|
}
|
||||||
|
|
||||||
|
QQmlCustomParser *customParser = customParsers.value(obj->inheritedTypeNameIndex);
|
||||||
|
|
||||||
|
QmlIR::PropertyResolver propertyResolver(propertyCache);
|
||||||
|
|
||||||
|
QStringList deferredPropertyNames;
|
||||||
|
{
|
||||||
|
const QMetaObject *mo = propertyCache->firstCppMetaObject();
|
||||||
|
const int namesIndex = mo->indexOfClassInfo("DeferredPropertyNames");
|
||||||
|
if (namesIndex != -1) {
|
||||||
|
QMetaClassInfo classInfo = mo->classInfo(namesIndex);
|
||||||
|
deferredPropertyNames = QString::fromUtf8(classInfo.value()).split(QLatin1Char(','));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (QmlIR::Binding *binding = obj->firstBinding(); binding; binding = binding->next) {
|
||||||
|
QQmlPropertyData *pd = 0;
|
||||||
|
QString name = stringAt(binding->propertyNameIndex);
|
||||||
|
|
||||||
|
if (customParser) {
|
||||||
|
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
||||||
|
if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
|
||||||
|
binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
|
||||||
|
obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else if (QmlIR::IRBuilder::isSignalPropertyName(name)
|
||||||
|
&& !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
|
||||||
|
obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
|
||||||
|
binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
pd = defaultProperty;
|
||||||
|
name = defaultPropertyName;
|
||||||
|
} else {
|
||||||
|
if (name.constData()->isUpper())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool notInRevision = false;
|
||||||
|
pd = propertyResolver.property(name, ¬InRevision, QmlIR::PropertyResolver::CheckRevision);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool seenSubObjectWithId = false;
|
||||||
|
|
||||||
|
if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
|
||||||
|
qSwap(_seenObjectWithId, seenSubObjectWithId);
|
||||||
|
const bool subObjectValid = scanObject(binding->value.objectIndex);
|
||||||
|
qSwap(_seenObjectWithId, seenSubObjectWithId);
|
||||||
|
if (!subObjectValid)
|
||||||
|
return false;
|
||||||
|
_seenObjectWithId |= seenSubObjectWithId;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!seenSubObjectWithId
|
||||||
|
&& !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
|
||||||
|
|
||||||
|
binding->flags |= QV4::CompiledData::Binding::IsDeferredBinding;
|
||||||
|
obj->flags |= QV4::CompiledData::Object::HasDeferredBindings;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerExpression
|
||||||
|
|| binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!pd) {
|
||||||
|
if (customParser) {
|
||||||
|
obj->flags |= QV4::CompiledData::Object::HasCustomParserBindings;
|
||||||
|
binding->flags |= QV4::CompiledData::Binding::IsCustomParserBinding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
|
QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
|
||||||
: QQmlCompilePass(typeCompiler)
|
: QQmlCompilePass(typeCompiler)
|
||||||
, enginePrivate(typeCompiler->enginePrivate())
|
, enginePrivate(typeCompiler->enginePrivate())
|
||||||
|
@ -1675,9 +1786,6 @@ QQmlPropertyValidator::QQmlPropertyValidator(QQmlTypeCompiler *typeCompiler)
|
||||||
, resolvedTypes(*typeCompiler->resolvedTypes())
|
, resolvedTypes(*typeCompiler->resolvedTypes())
|
||||||
, customParsers(typeCompiler->customParserCache())
|
, customParsers(typeCompiler->customParserCache())
|
||||||
, propertyCaches(typeCompiler->propertyCaches())
|
, propertyCaches(typeCompiler->propertyCaches())
|
||||||
, objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
|
|
||||||
, customParserBindingsPerObject(typeCompiler->customParserBindings())
|
|
||||||
, _seenObjectWithId(false)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1686,7 +1794,6 @@ bool QQmlPropertyValidator::validate()
|
||||||
_bindingPropertyDataPerObject.resize(qmlUnit->nObjects);
|
_bindingPropertyDataPerObject.resize(qmlUnit->nObjects);
|
||||||
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
|
if (!validateObject(qmlUnit->indexOfRootObject, /*instantiatingBinding*/0))
|
||||||
return false;
|
return false;
|
||||||
compiler->setDeferredBindingsPerObject(_deferredBindingsPerObject);
|
|
||||||
compiler->setBindingPropertyDataPerObject(_bindingPropertyDataPerObject);
|
compiler->setBindingPropertyDataPerObject(_bindingPropertyDataPerObject);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1717,10 +1824,8 @@ struct BindingFinder
|
||||||
bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const
|
bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledData::Binding *instantiatingBinding, bool populatingValueTypeGroupProperty) const
|
||||||
{
|
{
|
||||||
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
|
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(objectIndex);
|
||||||
if (obj->idIndex != 0)
|
|
||||||
_seenObjectWithId = true;
|
|
||||||
|
|
||||||
if (isComponent(objectIndex)) {
|
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
|
||||||
Q_ASSERT(obj->nBindings == 1);
|
Q_ASSERT(obj->nBindings == 1);
|
||||||
const QV4::CompiledData::Binding *componentBinding = obj->bindingTable();
|
const QV4::CompiledData::Binding *componentBinding = obj->bindingTable();
|
||||||
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
|
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
|
||||||
|
@ -1764,9 +1869,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
groupProperties.insert(pos, binding);
|
groupProperties.insert(pos, binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
QBitArray customParserBindings(obj->nBindings);
|
|
||||||
QBitArray deferredBindings;
|
|
||||||
|
|
||||||
QmlIR::PropertyResolver propertyResolver(propertyCache);
|
QmlIR::PropertyResolver propertyResolver(propertyCache);
|
||||||
|
|
||||||
QString defaultPropertyName;
|
QString defaultPropertyName;
|
||||||
|
@ -1790,13 +1892,11 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
if (binding->type == QV4::CompiledData::Binding::Type_AttachedProperty) {
|
||||||
if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
|
if (customParser->flags() & QQmlCustomParser::AcceptsAttachedProperties) {
|
||||||
customBindings << binding;
|
customBindings << binding;
|
||||||
customParserBindings.setBit(i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} else if (QmlIR::IRBuilder::isSignalPropertyName(name)
|
} else if (QmlIR::IRBuilder::isSignalPropertyName(name)
|
||||||
&& !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
|
&& !(customParser->flags() & QQmlCustomParser::AcceptsSignalHandlers)) {
|
||||||
customBindings << binding;
|
customBindings << binding;
|
||||||
customParserBindings.setBit(i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1845,24 +1945,10 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool seenSubObjectWithId = false;
|
|
||||||
|
|
||||||
if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
|
if (binding->type >= QV4::CompiledData::Binding::Type_Object && (pd || binding->isAttachedProperty())) {
|
||||||
qSwap(_seenObjectWithId, seenSubObjectWithId);
|
|
||||||
const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
|
const bool subObjectValid = validateObject(binding->value.objectIndex, binding, pd && QQmlValueTypeFactory::metaObjectForMetaType(pd->propType));
|
||||||
qSwap(_seenObjectWithId, seenSubObjectWithId);
|
|
||||||
if (!subObjectValid)
|
if (!subObjectValid)
|
||||||
return false;
|
return false;
|
||||||
_seenObjectWithId |= seenSubObjectWithId;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!seenSubObjectWithId
|
|
||||||
&& !deferredPropertyNames.isEmpty() && deferredPropertyNames.contains(name)) {
|
|
||||||
|
|
||||||
if (deferredBindings.isEmpty())
|
|
||||||
deferredBindings.resize(obj->nBindings);
|
|
||||||
|
|
||||||
deferredBindings.setBit(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal handlers were resolved and checked earlier in the signal handler conversion pass.
|
// Signal handlers were resolved and checked earlier in the signal handler conversion pass.
|
||||||
|
@ -1947,7 +2033,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
} else {
|
} else {
|
||||||
if (customParser) {
|
if (customParser) {
|
||||||
customBindings << binding;
|
customBindings << binding;
|
||||||
customParserBindings.setBit(i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (bindingToDefaultProperty) {
|
if (bindingToDefaultProperty) {
|
||||||
|
@ -1958,7 +2043,7 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (obj->idIndex) {
|
if (obj->idNameIndex) {
|
||||||
bool notInRevision = false;
|
bool notInRevision = false;
|
||||||
collectedBindingPropertyData << propertyResolver.property(QStringLiteral("id"), ¬InRevision);
|
collectedBindingPropertyData << propertyResolver.property(QStringLiteral("id"), ¬InRevision);
|
||||||
}
|
}
|
||||||
|
@ -1972,7 +2057,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
customParser->validator = 0;
|
customParser->validator = 0;
|
||||||
customParser->engine = 0;
|
customParser->engine = 0;
|
||||||
customParser->imports = (QQmlImports*)0;
|
customParser->imports = (QQmlImports*)0;
|
||||||
customParserBindingsPerObject->insert(objectIndex, customParserBindings);
|
|
||||||
const QList<QQmlError> parserErrors = customParser->errors();
|
const QList<QQmlError> parserErrors = customParser->errors();
|
||||||
if (!parserErrors.isEmpty()) {
|
if (!parserErrors.isEmpty()) {
|
||||||
foreach (const QQmlError &error, parserErrors)
|
foreach (const QQmlError &error, parserErrors)
|
||||||
|
@ -1981,9 +2065,6 @@ bool QQmlPropertyValidator::validateObject(int objectIndex, const QV4::CompiledD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deferredBindings.isEmpty())
|
|
||||||
_deferredBindingsPerObject.insert(objectIndex, deferredBindings);
|
|
||||||
|
|
||||||
_bindingPropertyDataPerObject[objectIndex] = collectedBindingPropertyData;
|
_bindingPropertyDataPerObject[objectIndex] = collectedBindingPropertyData;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2328,7 +2409,7 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if (isComponent(binding->value.objectIndex)) {
|
} else if (qmlUnit->objectAt(binding->value.objectIndex)->flags & QV4::CompiledData::Object::IsComponent) {
|
||||||
return true;
|
return true;
|
||||||
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
|
} else if (binding->flags & QV4::CompiledData::Binding::IsSignalHandlerObject && property->isFunction()) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -2365,7 +2446,6 @@ bool QQmlPropertyValidator::validateObjectBinding(QQmlPropertyData *property, co
|
||||||
|
|
||||||
QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen)
|
QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::JSCodeGen *v4CodeGen)
|
||||||
: QQmlCompilePass(typeCompiler)
|
: QQmlCompilePass(typeCompiler)
|
||||||
, objectIndexToIdPerComponent(*typeCompiler->objectIndexToIdPerComponent())
|
|
||||||
, resolvedTypes(*typeCompiler->resolvedTypes())
|
, resolvedTypes(*typeCompiler->resolvedTypes())
|
||||||
, customParsers(typeCompiler->customParserCache())
|
, customParsers(typeCompiler->customParserCache())
|
||||||
, qmlObjects(*typeCompiler->qmlObjects())
|
, qmlObjects(*typeCompiler->qmlObjects())
|
||||||
|
@ -2376,38 +2456,33 @@ QQmlJSCodeGenerator::QQmlJSCodeGenerator(QQmlTypeCompiler *typeCompiler, QmlIR::
|
||||||
|
|
||||||
bool QQmlJSCodeGenerator::generateCodeForComponents()
|
bool QQmlJSCodeGenerator::generateCodeForComponents()
|
||||||
{
|
{
|
||||||
const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent = *compiler->objectIndexToIdPerComponent();
|
const QVector<quint32> &componentRoots = compiler->componentRoots();
|
||||||
for (QHash<int, QHash<int, int> >::ConstIterator component = objectIndexToIdPerComponent.constBegin(), end = objectIndexToIdPerComponent.constEnd();
|
for (int i = 0; i < componentRoots.count(); ++i) {
|
||||||
component != end; ++component) {
|
if (!compileComponent(componentRoots.at(i)))
|
||||||
if (!compileComponent(component.key(), component.value()))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return compileComponent(compiler->rootObjectIndex(), *compiler->objectIndexToIdForRoot());
|
return compileComponent(compiler->rootObjectIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QQmlJSCodeGenerator::compileComponent(int contextObject, const QHash<int, int> &objectIndexToId)
|
bool QQmlJSCodeGenerator::compileComponent(int contextObject)
|
||||||
{
|
{
|
||||||
if (isComponent(contextObject)) {
|
const QmlIR::Object *obj = qmlObjects.at(contextObject);
|
||||||
const QmlIR::Object *component = qmlObjects.at(contextObject);
|
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
|
||||||
Q_ASSERT(component->bindingCount() == 1);
|
Q_ASSERT(obj->bindingCount() == 1);
|
||||||
const QV4::CompiledData::Binding *componentBinding = component->firstBinding();
|
const QV4::CompiledData::Binding *componentBinding = obj->firstBinding();
|
||||||
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
|
Q_ASSERT(componentBinding->type == QV4::CompiledData::Binding::Type_Object);
|
||||||
contextObject = componentBinding->value.objectIndex;
|
contextObject = componentBinding->value.objectIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
QmlIR::JSCodeGen::ObjectIdMapping idMapping;
|
QmlIR::JSCodeGen::ObjectIdMapping idMapping;
|
||||||
if (!objectIndexToId.isEmpty()) {
|
idMapping.reserve(obj->namedObjectsInComponent.count);
|
||||||
idMapping.reserve(objectIndexToId.count());
|
for (int i = 0; i < obj->namedObjectsInComponent.count; ++i) {
|
||||||
|
const int objectIndex = obj->namedObjectsInComponent.at(i);
|
||||||
for (QHash<int, int>::ConstIterator idIt = objectIndexToId.constBegin(), end = objectIndexToId.constEnd();
|
|
||||||
idIt != end; ++idIt) {
|
|
||||||
|
|
||||||
const int objectIndex = idIt.key();
|
|
||||||
QmlIR::JSCodeGen::IdMapping m;
|
QmlIR::JSCodeGen::IdMapping m;
|
||||||
const QmlIR::Object *obj = qmlObjects.at(objectIndex);
|
const QmlIR::Object *obj = qmlObjects.at(objectIndex);
|
||||||
m.name = stringAt(obj->idIndex);
|
m.name = stringAt(obj->idNameIndex);
|
||||||
m.idIndex = idIt.value();
|
m.idIndex = obj->id;
|
||||||
m.type = propertyCaches.at(objectIndex).data();
|
m.type = propertyCaches.at(objectIndex).data();
|
||||||
|
|
||||||
QQmlCompiledData::TypeReference *tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
|
QQmlCompiledData::TypeReference *tref = resolvedTypes.value(obj->inheritedTypeNameIndex);
|
||||||
|
@ -2416,7 +2491,6 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject, const QHash<int, i
|
||||||
|
|
||||||
idMapping << m;
|
idMapping << m;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
v4CodeGen->beginContextScope(idMapping, propertyCaches.at(contextObject).data());
|
v4CodeGen->beginContextScope(idMapping, propertyCaches.at(contextObject).data());
|
||||||
|
|
||||||
if (!compileJavaScriptCodeInObjectsRecursively(contextObject, contextObject))
|
if (!compileJavaScriptCodeInObjectsRecursively(contextObject, contextObject))
|
||||||
|
@ -2427,10 +2501,10 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject, const QHash<int, i
|
||||||
|
|
||||||
bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex)
|
bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex)
|
||||||
{
|
{
|
||||||
if (isComponent(objectIndex))
|
QmlIR::Object *object = qmlObjects.at(objectIndex);
|
||||||
|
if (object->flags & QV4::CompiledData::Object::IsComponent)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
QmlIR::Object *object = qmlObjects.at(objectIndex);
|
|
||||||
if (object->functionsAndExpressions->count > 0) {
|
if (object->functionsAndExpressions->count > 0) {
|
||||||
QQmlPropertyCache *scopeObject = propertyCaches.at(scopeObjectIndex).data();
|
QQmlPropertyCache *scopeObject = propertyCaches.at(scopeObjectIndex).data();
|
||||||
v4CodeGen->beginObjectScope(scopeObject);
|
v4CodeGen->beginObjectScope(scopeObject);
|
||||||
|
@ -2451,8 +2525,7 @@ bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIn
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlJS::MemoryPool *pool = compiler->memoryPool();
|
QQmlJS::MemoryPool *pool = compiler->memoryPool();
|
||||||
object->runtimeFunctionIndices = pool->New<QmlIR::FixedPoolArray<int> >();
|
object->runtimeFunctionIndices.allocate(pool, runtimeFunctionIndices);
|
||||||
object->runtimeFunctionIndices->init(pool, runtimeFunctionIndices);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
|
for (const QmlIR::Binding *binding = object->firstBinding(); binding; binding = binding->next) {
|
||||||
|
@ -2551,7 +2624,7 @@ void QQmlJavaScriptBindingExpressionSimplificationPass::reduceTranslationBinding
|
||||||
if (binding->type != QV4::CompiledData::Binding::Type_Script)
|
if (binding->type != QV4::CompiledData::Binding::Type_Script)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const int irFunctionIndex = obj->runtimeFunctionIndices->at(binding->value.compiledScriptIndex);
|
const int irFunctionIndex = obj->runtimeFunctionIndices.at(binding->value.compiledScriptIndex);
|
||||||
QV4::IR::Function *irFunction = jsModule->functions.at(irFunctionIndex);
|
QV4::IR::Function *irFunction = jsModule->functions.at(irFunctionIndex);
|
||||||
if (simplifyBinding(irFunction, binding)) {
|
if (simplifyBinding(irFunction, binding)) {
|
||||||
irFunctionsToRemove.append(irFunctionIndex);
|
irFunctionsToRemove.append(irFunctionIndex);
|
||||||
|
@ -2838,10 +2911,8 @@ void QQmlIRFunctionCleanser::clean()
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (QmlIR::Object *obj, *compiler->qmlObjects()) {
|
foreach (QmlIR::Object *obj, *compiler->qmlObjects()) {
|
||||||
if (!obj->runtimeFunctionIndices)
|
for (int i = 0; i < obj->runtimeFunctionIndices.count; ++i)
|
||||||
continue;
|
obj->runtimeFunctionIndices[i] = newFunctionIndices[obj->runtimeFunctionIndices.at(i)];
|
||||||
for (int i = 0; i < obj->runtimeFunctionIndices->count; ++i)
|
|
||||||
(*obj->runtimeFunctionIndices)[i] = newFunctionIndices[obj->runtimeFunctionIndices->at(i)];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,13 +101,11 @@ public:
|
||||||
int rootObjectIndex() const;
|
int rootObjectIndex() const;
|
||||||
void setPropertyCaches(const QQmlPropertyCacheVector &caches);
|
void setPropertyCaches(const QQmlPropertyCacheVector &caches);
|
||||||
const QQmlPropertyCacheVector &propertyCaches() const;
|
const QQmlPropertyCacheVector &propertyCaches() const;
|
||||||
QHash<int, int> *objectIndexToIdForRoot();
|
void setComponentRoots(const QVector<quint32> &roots) { m_componentRoots = roots; }
|
||||||
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent();
|
const QVector<quint32> &componentRoots() const { return m_componentRoots; }
|
||||||
QHash<int, QBitArray> *customParserBindings();
|
|
||||||
QQmlJS::MemoryPool *memoryPool();
|
QQmlJS::MemoryPool *memoryPool();
|
||||||
QStringRef newStringRef(const QString &string);
|
QStringRef newStringRef(const QString &string);
|
||||||
const QV4::Compiler::StringTableGenerator *stringPool() const;
|
const QV4::Compiler::StringTableGenerator *stringPool() const;
|
||||||
void setDeferredBindingsPerObject(const QHash<int, QBitArray> &deferredBindingsPerObject);
|
|
||||||
void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
|
void setBindingPropertyDataPerObject(const QVector<QV4::CompiledData::BindingPropertyData> &propertyData);
|
||||||
|
|
||||||
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
|
const QHash<int, QQmlCustomParser*> &customParserCache() const { return customParsers; }
|
||||||
|
@ -119,9 +117,14 @@ private:
|
||||||
QQmlEnginePrivate *engine;
|
QQmlEnginePrivate *engine;
|
||||||
QQmlCompiledData *compiledData;
|
QQmlCompiledData *compiledData;
|
||||||
QQmlTypeData *typeData;
|
QQmlTypeData *typeData;
|
||||||
|
QQmlRefPointer<QQmlTypeNameCache> importCache;
|
||||||
QmlIR::Document *document;
|
QmlIR::Document *document;
|
||||||
// index is string index of type name (use obj->inheritedTypeNameIndex)
|
// index is string index of type name (use obj->inheritedTypeNameIndex)
|
||||||
QHash<int, QQmlCustomParser*> customParsers;
|
QHash<int, QQmlCustomParser*> customParsers;
|
||||||
|
|
||||||
|
// index in first hash is component index, vector inside contains object indices of objects with id property
|
||||||
|
QVector<quint32> m_componentRoots;
|
||||||
|
QQmlPropertyCacheVector m_propertyCaches;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct QQmlCompilePass
|
struct QQmlCompilePass
|
||||||
|
@ -268,20 +271,31 @@ protected:
|
||||||
const int indexOfRootObject;
|
const int indexOfRootObject;
|
||||||
|
|
||||||
// indices of the objects that are actually Component {}
|
// indices of the objects that are actually Component {}
|
||||||
QVector<int> componentRoots;
|
QVector<quint32> componentRoots;
|
||||||
// indices of objects that are the beginning of a new component
|
|
||||||
// scope. This is sorted and used for binary search.
|
|
||||||
QVector<quint32> componentBoundaries;
|
|
||||||
|
|
||||||
int _componentIndex;
|
int _componentIndex;
|
||||||
QHash<int, int> _idToObjectIndex;
|
QHash<int, int> _idToObjectIndex;
|
||||||
QHash<int, int> *_objectIndexToIdInScope;
|
|
||||||
QList<int> _objectsWithAliases;
|
QList<int> _objectsWithAliases;
|
||||||
|
|
||||||
QHash<int, QQmlCompiledData::TypeReference*> *resolvedTypes;
|
QHash<int, QQmlCompiledData::TypeReference*> *resolvedTypes;
|
||||||
QQmlPropertyCacheVector propertyCaches;
|
QQmlPropertyCacheVector propertyCaches;
|
||||||
QHash<int, int> *objectIndexToIdForRoot;
|
};
|
||||||
QHash<int, QHash<int, int> > *objectIndexToIdPerComponent;
|
|
||||||
|
class QQmlDeferredAndCustomParserBindingScanner : public QQmlCompilePass
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
QQmlDeferredAndCustomParserBindingScanner(QQmlTypeCompiler *typeCompiler);
|
||||||
|
|
||||||
|
bool scanObject();
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool scanObject(int objectIndex);
|
||||||
|
|
||||||
|
QList<QmlIR::Object*> *qmlObjects;
|
||||||
|
QQmlPropertyCacheVector propertyCaches;
|
||||||
|
const QHash<int, QQmlCustomParser*> &customParsers;
|
||||||
|
|
||||||
|
bool _seenObjectWithId;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QQmlPropertyValidator : public QQmlCompilePass
|
class QQmlPropertyValidator : public QQmlCompilePass
|
||||||
|
@ -300,8 +314,6 @@ private:
|
||||||
bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const;
|
bool validateLiteralBinding(QQmlPropertyCache *propertyCache, QQmlPropertyData *property, const QV4::CompiledData::Binding *binding) const;
|
||||||
bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const;
|
bool validateObjectBinding(QQmlPropertyData *property, const QString &propertyName, const QV4::CompiledData::Binding *binding) const;
|
||||||
|
|
||||||
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
|
|
||||||
|
|
||||||
bool canCoerce(int to, QQmlPropertyCache *fromMo) const;
|
bool canCoerce(int to, QQmlPropertyCache *fromMo) const;
|
||||||
|
|
||||||
QQmlEnginePrivate *enginePrivate;
|
QQmlEnginePrivate *enginePrivate;
|
||||||
|
@ -309,12 +321,8 @@ private:
|
||||||
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
|
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
|
||||||
const QHash<int, QQmlCustomParser*> &customParsers;
|
const QHash<int, QQmlCustomParser*> &customParsers;
|
||||||
const QQmlPropertyCacheVector &propertyCaches;
|
const QQmlPropertyCacheVector &propertyCaches;
|
||||||
const QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
|
|
||||||
QHash<int, QBitArray> *customParserBindingsPerObject;
|
|
||||||
|
|
||||||
// collected state variables, essentially write-only
|
// collected state variables, essentially write-only
|
||||||
mutable QHash<int, QBitArray> _deferredBindingsPerObject;
|
|
||||||
mutable bool _seenObjectWithId;
|
|
||||||
mutable QVector<QV4::CompiledData::BindingPropertyData> _bindingPropertyDataPerObject;
|
mutable QVector<QV4::CompiledData::BindingPropertyData> _bindingPropertyDataPerObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -327,12 +335,9 @@ public:
|
||||||
bool generateCodeForComponents();
|
bool generateCodeForComponents();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool compileComponent(int componentRoot, const QHash<int, int> &objectIndexToId);
|
bool compileComponent(int componentRoot);
|
||||||
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
|
bool compileJavaScriptCodeInObjectsRecursively(int objectIndex, int scopeObjectIndex);
|
||||||
|
|
||||||
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
|
|
||||||
|
|
||||||
const QHash<int, QHash<int, int> > &objectIndexToIdPerComponent;
|
|
||||||
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
|
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
|
||||||
const QHash<int, QQmlCustomParser*> &customParsers;
|
const QHash<int, QQmlCustomParser*> &customParsers;
|
||||||
const QList<QmlIR::Object*> &qmlObjects;
|
const QList<QmlIR::Object*> &qmlObjects;
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
#include <private/qv4lookup_p.h>
|
#include <private/qv4lookup_p.h>
|
||||||
#include <private/qv4regexpobject_p.h>
|
#include <private/qv4regexpobject_p.h>
|
||||||
#include <private/qqmlpropertycache_p.h>
|
#include <private/qqmlpropertycache_p.h>
|
||||||
|
#include <private/qqmltypeloader_p.h>
|
||||||
#endif
|
#endif
|
||||||
#include <private/qqmlirbuilder_p.h>
|
#include <private/qqmlirbuilder_p.h>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
|
@ -67,6 +68,9 @@ CompilationUnit::CompilationUnit()
|
||||||
, runtimeLookups(0)
|
, runtimeLookups(0)
|
||||||
, runtimeRegularExpressions(0)
|
, runtimeRegularExpressions(0)
|
||||||
, runtimeClasses(0)
|
, runtimeClasses(0)
|
||||||
|
, totalBindingsCount(0)
|
||||||
|
, totalParserStatusCount(0)
|
||||||
|
, totalObjectCount(0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
CompilationUnit::~CompilationUnit()
|
CompilationUnit::~CompilationUnit()
|
||||||
|
@ -165,6 +169,18 @@ void CompilationUnit::unlink()
|
||||||
{
|
{
|
||||||
if (engine)
|
if (engine)
|
||||||
engine->compilationUnits.erase(engine->compilationUnits.find(this));
|
engine->compilationUnits.erase(engine->compilationUnits.find(this));
|
||||||
|
|
||||||
|
for (int ii = 0; ii < propertyCaches.count(); ++ii)
|
||||||
|
if (propertyCaches.at(ii).data())
|
||||||
|
propertyCaches.at(ii)->release();
|
||||||
|
propertyCaches.clear();
|
||||||
|
|
||||||
|
for (int ii = 0; ii < dependentScripts.count(); ++ii)
|
||||||
|
dependentScripts.at(ii)->release();
|
||||||
|
dependentScripts.clear();
|
||||||
|
|
||||||
|
importCache = nullptr;
|
||||||
|
|
||||||
engine = 0;
|
engine = 0;
|
||||||
free(runtimeStrings);
|
free(runtimeStrings);
|
||||||
runtimeStrings = 0;
|
runtimeStrings = 0;
|
||||||
|
@ -189,6 +205,22 @@ void CompilationUnit::markObjects(QV4::ExecutionEngine *e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdentifierHash<int> CompilationUnit::namedObjectsPerComponent(int componentObjectIndex)
|
||||||
|
{
|
||||||
|
auto it = namedObjectsPerComponentCache.find(componentObjectIndex);
|
||||||
|
if (it == namedObjectsPerComponentCache.end()) {
|
||||||
|
IdentifierHash<int> namedObjectCache(engine);
|
||||||
|
const CompiledData::Object *component = data->objectAt(componentObjectIndex);
|
||||||
|
const quint32 *namedObjectIndexPtr = component->namedObjectsInComponentTable();
|
||||||
|
for (quint32 i = 0; i < component->nNamedObjectsInComponent; ++i, ++namedObjectIndexPtr) {
|
||||||
|
const CompiledData::Object *namedObject = data->objectAt(*namedObjectIndexPtr);
|
||||||
|
namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->id);
|
||||||
|
}
|
||||||
|
it = namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
|
||||||
|
}
|
||||||
|
return *it;
|
||||||
|
}
|
||||||
|
|
||||||
#endif // V4_BOOTSTRAP
|
#endif // V4_BOOTSTRAP
|
||||||
|
|
||||||
Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
|
Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument)
|
||||||
|
|
|
@ -60,11 +60,22 @@
|
||||||
#include <private/qv4executableallocator_p.h>
|
#include <private/qv4executableallocator_p.h>
|
||||||
#include <private/qqmlrefcount_p.h>
|
#include <private/qqmlrefcount_p.h>
|
||||||
#include <private/qqmlnullablevalue_p.h>
|
#include <private/qqmlnullablevalue_p.h>
|
||||||
|
#include <private/qv4identifier_p.h>
|
||||||
|
#include <private/qflagpointer_p.h>
|
||||||
|
#ifndef V4_BOOTSTRAP
|
||||||
|
#include <private/qqmltypenamecache_p.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QQmlPropertyCache;
|
class QQmlPropertyCache;
|
||||||
class QQmlPropertyData;
|
class QQmlPropertyData;
|
||||||
|
class QQmlTypeNameCache;
|
||||||
|
class QQmlScriptData;
|
||||||
|
|
||||||
|
// The vector is indexed by QV4::CompiledData::Object index and the flag
|
||||||
|
// indicates whether instantiation of the object requires a VME meta-object.
|
||||||
|
typedef QVector<QFlagPointer<QQmlPropertyCache>> QQmlPropertyCacheVector;
|
||||||
|
|
||||||
namespace QmlIR {
|
namespace QmlIR {
|
||||||
struct Document;
|
struct Document;
|
||||||
|
@ -234,7 +245,9 @@ struct Q_QML_PRIVATE_EXPORT Binding
|
||||||
InitializerForReadOnlyDeclaration = 0x8,
|
InitializerForReadOnlyDeclaration = 0x8,
|
||||||
IsResolvedEnum = 0x10,
|
IsResolvedEnum = 0x10,
|
||||||
IsListItem = 0x20,
|
IsListItem = 0x20,
|
||||||
IsBindingToAlias = 0x40
|
IsBindingToAlias = 0x40,
|
||||||
|
IsDeferredBinding = 0x80,
|
||||||
|
IsCustomParserBinding = 0x100,
|
||||||
};
|
};
|
||||||
|
|
||||||
quint32 flags : 16;
|
quint32 flags : 16;
|
||||||
|
@ -391,13 +404,22 @@ struct Alias {
|
||||||
|
|
||||||
struct Object
|
struct Object
|
||||||
{
|
{
|
||||||
|
enum Flags {
|
||||||
|
NoFlag = 0x0,
|
||||||
|
IsComponent = 0x1, // object was identified to be an explicit or implicit component boundary
|
||||||
|
HasDeferredBindings = 0x2, // any of the bindings are deferred
|
||||||
|
HasCustomParserBindings = 0x4
|
||||||
|
};
|
||||||
|
|
||||||
// Depending on the use, this may be the type name to instantiate before instantiating this
|
// Depending on the use, this may be the type name to instantiate before instantiating this
|
||||||
// object. For grouped properties the type name will be empty and for attached properties
|
// object. For grouped properties the type name will be empty and for attached properties
|
||||||
// it will be the name of the attached type.
|
// it will be the name of the attached type.
|
||||||
quint32 inheritedTypeNameIndex;
|
quint32 inheritedTypeNameIndex;
|
||||||
quint32 idIndex;
|
quint32 idNameIndex;
|
||||||
qint32 indexOfDefaultPropertyOrAlias : 31; // -1 means no default property declared in this object
|
qint32 id : 16;
|
||||||
|
qint32 flags : 15;
|
||||||
quint32 defaultPropertyIsAlias : 1;
|
quint32 defaultPropertyIsAlias : 1;
|
||||||
|
qint32 indexOfDefaultPropertyOrAlias; // -1 means no default property declared in this object
|
||||||
quint32 nFunctions;
|
quint32 nFunctions;
|
||||||
quint32 offsetToFunctions;
|
quint32 offsetToFunctions;
|
||||||
quint32 nProperties;
|
quint32 nProperties;
|
||||||
|
@ -408,6 +430,8 @@ struct Object
|
||||||
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
|
quint32 offsetToSignals; // which in turn will be a table with offsets to variable-sized Signal objects
|
||||||
quint32 nBindings;
|
quint32 nBindings;
|
||||||
quint32 offsetToBindings;
|
quint32 offsetToBindings;
|
||||||
|
quint32 nNamedObjectsInComponent;
|
||||||
|
quint32 offsetToNamedObjectsInComponent;
|
||||||
Location location;
|
Location location;
|
||||||
Location locationOfIdProperty;
|
Location locationOfIdProperty;
|
||||||
// Function[]
|
// Function[]
|
||||||
|
@ -415,7 +439,7 @@ struct Object
|
||||||
// Signal[]
|
// Signal[]
|
||||||
// Binding[]
|
// Binding[]
|
||||||
|
|
||||||
static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings)
|
static int calculateSizeExcludingSignals(int nFunctions, int nProperties, int nAliases, int nSignals, int nBindings, int nNamedObjectsInComponent)
|
||||||
{
|
{
|
||||||
return ( sizeof(Object)
|
return ( sizeof(Object)
|
||||||
+ nFunctions * sizeof(quint32)
|
+ nFunctions * sizeof(quint32)
|
||||||
|
@ -423,6 +447,7 @@ struct Object
|
||||||
+ nAliases * sizeof(Alias)
|
+ nAliases * sizeof(Alias)
|
||||||
+ nSignals * sizeof(quint32)
|
+ nSignals * sizeof(quint32)
|
||||||
+ nBindings * sizeof(Binding)
|
+ nBindings * sizeof(Binding)
|
||||||
|
+ nNamedObjectsInComponent * sizeof(int)
|
||||||
+ 0x7
|
+ 0x7
|
||||||
) & ~0x7;
|
) & ~0x7;
|
||||||
}
|
}
|
||||||
|
@ -453,6 +478,11 @@ struct Object
|
||||||
const uint offset = offsetTable[idx];
|
const uint offset = offsetTable[idx];
|
||||||
return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
|
return reinterpret_cast<const Signal*>(reinterpret_cast<const char*>(this) + offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const quint32 *namedObjectsInComponentTable() const
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const quint32*>(reinterpret_cast<const char *>(this) + offsetToNamedObjectsInComponent);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Import
|
struct Import
|
||||||
|
@ -641,11 +671,29 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public QQmlRefCount
|
||||||
QVector<QV4::Function *> runtimeFunctions;
|
QVector<QV4::Function *> runtimeFunctions;
|
||||||
mutable QQmlNullableValue<QUrl> m_url;
|
mutable QQmlNullableValue<QUrl> m_url;
|
||||||
|
|
||||||
|
// QML specific fields
|
||||||
|
QQmlPropertyCacheVector propertyCaches;
|
||||||
|
QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(data->indexOfRootObject).data(); }
|
||||||
|
bool isCompositeType() const { return propertyCaches.at(data->indexOfRootObject).flag(); }
|
||||||
|
|
||||||
|
QQmlRefPointer<QQmlTypeNameCache> importCache;
|
||||||
|
|
||||||
// index is object index. This allows fast access to the
|
// index is object index. This allows fast access to the
|
||||||
// property data when initializing bindings, avoiding expensive
|
// property data when initializing bindings, avoiding expensive
|
||||||
// lookups by string (property name).
|
// lookups by string (property name).
|
||||||
QVector<BindingPropertyData> bindingPropertyDataPerObject;
|
QVector<BindingPropertyData> bindingPropertyDataPerObject;
|
||||||
|
|
||||||
|
// mapping from component object index (CompiledData::Unit object index that points to component) to identifier hash of named objects
|
||||||
|
// this is initialized on-demand by QQmlContextData
|
||||||
|
QHash<int, IdentifierHash<int>> namedObjectsPerComponentCache;
|
||||||
|
IdentifierHash<int> namedObjectsPerComponent(int componentObjectIndex);
|
||||||
|
|
||||||
|
int totalBindingsCount; // Number of bindings used in this type
|
||||||
|
int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
|
||||||
|
int totalObjectCount; // Number of objects explicitly instantiated
|
||||||
|
|
||||||
|
QVector<QQmlScriptData *> dependentScripts;
|
||||||
|
|
||||||
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
|
QV4::Function *linkToEngine(QV4::ExecutionEngine *engine);
|
||||||
void unlink();
|
void unlink();
|
||||||
|
|
||||||
|
|
|
@ -71,13 +71,13 @@ public:
|
||||||
virtual ~QQmlAbstractProfilerAdapter() {}
|
virtual ~QQmlAbstractProfilerAdapter() {}
|
||||||
void setService(QQmlProfilerService *new_service) { service = new_service; }
|
void setService(QQmlProfilerService *new_service) { service = new_service; }
|
||||||
|
|
||||||
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages) = 0;
|
virtual qint64 sendMessages(qint64 until, QList<QByteArray> &messages, bool trackLocations) = 0;
|
||||||
|
|
||||||
void startProfiling(quint64 features);
|
void startProfiling(quint64 features);
|
||||||
|
|
||||||
void stopProfiling();
|
void stopProfiling();
|
||||||
|
|
||||||
void reportData() { emit dataRequested(); }
|
void reportData(bool trackLocations) { emit dataRequested(trackLocations); }
|
||||||
|
|
||||||
void stopWaiting() { waiting = false; }
|
void stopWaiting() { waiting = false; }
|
||||||
void startWaiting() { waiting = true; }
|
void startWaiting() { waiting = true; }
|
||||||
|
@ -94,7 +94,7 @@ signals:
|
||||||
void profilingDisabled();
|
void profilingDisabled();
|
||||||
void profilingDisabledWhileWaiting();
|
void profilingDisabledWhileWaiting();
|
||||||
|
|
||||||
void dataRequested();
|
void dataRequested(bool trackLocations);
|
||||||
void referenceTimeKnown(const QElapsedTimer &timer);
|
void referenceTimeKnown(const QElapsedTimer &timer);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -59,19 +59,21 @@ void QQmlProfiler::startProfiling(quint64 features)
|
||||||
void QQmlProfiler::stopProfiling()
|
void QQmlProfiler::stopProfiling()
|
||||||
{
|
{
|
||||||
featuresEnabled = false;
|
featuresEnabled = false;
|
||||||
reportData();
|
reportData(true);
|
||||||
|
m_locations.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlProfiler::reportData()
|
void QQmlProfiler::reportData(bool trackLocations)
|
||||||
{
|
{
|
||||||
LocationHash resolved;
|
LocationHash resolved;
|
||||||
resolved.reserve(m_locations.size());
|
resolved.reserve(m_locations.size());
|
||||||
for (auto it = m_locations.constBegin(), end = m_locations.constEnd(); it != end; ++it)
|
for (auto it = m_locations.begin(), end = m_locations.end(); it != end; ++it) {
|
||||||
|
if (!trackLocations || !it->sent) {
|
||||||
resolved.insert(it.key(), it.value());
|
resolved.insert(it.key(), it.value());
|
||||||
|
if (trackLocations)
|
||||||
// This unrefs all the objects. We have to make sure we do this in the GUI thread. Also, it's
|
it->sent = true;
|
||||||
// a good idea to release the memory before creating the packets to be sent.
|
}
|
||||||
m_locations.clear();
|
}
|
||||||
|
|
||||||
QVector<QQmlProfilerData> data;
|
QVector<QQmlProfilerData> data;
|
||||||
data.swap(m_data);
|
data.swap(m_data);
|
||||||
|
|
|
@ -146,26 +146,27 @@ public:
|
||||||
// Unfortunately we have to resolve the locations right away because the QML context might not
|
// Unfortunately we have to resolve the locations right away because the QML context might not
|
||||||
// be available anymore when we send the data.
|
// be available anymore when we send the data.
|
||||||
struct RefLocation : public Location {
|
struct RefLocation : public Location {
|
||||||
RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr)
|
RefLocation() : Location(), locationType(MaximumRangeType), ref(nullptr), sent(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
|
RefLocation(QQmlBinding *binding, QV4::FunctionObject *function) :
|
||||||
Location(function->sourceLocation()), locationType(Binding),
|
Location(function->sourceLocation()), locationType(Binding),
|
||||||
ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt)
|
ref(new BindingRefCount(binding), QQmlRefPointer<QQmlRefCount>::Adopt), sent(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
|
RefLocation(QQmlCompiledData *ref, const QUrl &url, const QV4::CompiledData::Object *obj,
|
||||||
const QString &type) :
|
const QString &type) :
|
||||||
Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
|
Location(QQmlSourceLocation(type, obj->location.line, obj->location.column), url),
|
||||||
locationType(Creating), ref(ref)
|
locationType(Creating), ref(ref), sent(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RefLocation(QQmlBoundSignalExpression *ref) :
|
RefLocation(QQmlBoundSignalExpression *ref) :
|
||||||
Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref)
|
Location(ref->sourceLocation()), locationType(HandlingSignal), ref(ref), sent(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
RefLocation(QQmlDataBlob *ref) :
|
RefLocation(QQmlDataBlob *ref) :
|
||||||
Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref)
|
Location(QQmlSourceLocation(), ref->url()), locationType(Compiling), ref(ref),
|
||||||
|
sent(false)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool isValid() const
|
bool isValid() const
|
||||||
|
@ -175,6 +176,7 @@ public:
|
||||||
|
|
||||||
RangeType locationType;
|
RangeType locationType;
|
||||||
QQmlRefPointer<QQmlRefCount> ref;
|
QQmlRefPointer<QQmlRefCount> ref;
|
||||||
|
bool sent;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QHash<quintptr, Location> LocationHash;
|
typedef QHash<quintptr, Location> LocationHash;
|
||||||
|
@ -217,11 +219,6 @@ public:
|
||||||
location = RefLocation(expression);
|
location = RefLocation(expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
void startCreating()
|
|
||||||
{
|
|
||||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(), 1 << RangeStart, Creating));
|
|
||||||
}
|
|
||||||
|
|
||||||
void startCreating(const QV4::CompiledData::Object *obj)
|
void startCreating(const QV4::CompiledData::Object *obj)
|
||||||
{
|
{
|
||||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
||||||
|
@ -233,10 +230,6 @@ public:
|
||||||
const QUrl &url, const QString &type)
|
const QUrl &url, const QString &type)
|
||||||
{
|
{
|
||||||
quintptr locationId(id(obj));
|
quintptr locationId(id(obj));
|
||||||
m_data.append(QQmlProfilerData(m_timer.nsecsElapsed(),
|
|
||||||
(1 << RangeLocation | 1 << RangeData),
|
|
||||||
Creating, locationId));
|
|
||||||
|
|
||||||
RefLocation &location = m_locations[locationId];
|
RefLocation &location = m_locations[locationId];
|
||||||
if (!location.isValid())
|
if (!location.isValid())
|
||||||
location = RefLocation(ref, url, obj, type);
|
location = RefLocation(ref, url, obj, type);
|
||||||
|
@ -261,7 +254,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
void startProfiling(quint64 features);
|
void startProfiling(quint64 features);
|
||||||
void stopProfiling();
|
void stopProfiling();
|
||||||
void reportData();
|
void reportData(bool trackLocations);
|
||||||
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -363,9 +356,10 @@ private:
|
||||||
class QQmlObjectCreationProfiler {
|
class QQmlObjectCreationProfiler {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
QQmlObjectCreationProfiler(QQmlProfiler *profiler) : profiler(profiler)
|
QQmlObjectCreationProfiler(QQmlProfiler *profiler, const QV4::CompiledData::Object *obj)
|
||||||
|
: profiler(profiler)
|
||||||
{
|
{
|
||||||
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating());
|
Q_QML_PROFILE(QQmlProfilerDefinitions::ProfileCreating, profiler, startCreating(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
~QQmlObjectCreationProfiler()
|
~QQmlObjectCreationProfiler()
|
||||||
|
|
|
@ -64,12 +64,33 @@ IdentifierHashData::IdentifierHashData(int numBits)
|
||||||
memset(entries, 0, alloc*sizeof(IdentifierHashEntry));
|
memset(entries, 0, alloc*sizeof(IdentifierHashEntry));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IdentifierHashData::IdentifierHashData(IdentifierHashData *other)
|
||||||
|
: size(other->size)
|
||||||
|
, numBits(other->numBits)
|
||||||
|
, identifierTable(other->identifierTable)
|
||||||
|
{
|
||||||
|
refCount.store(1);
|
||||||
|
alloc = other->alloc;
|
||||||
|
entries = (IdentifierHashEntry *)malloc(alloc*sizeof(IdentifierHashEntry));
|
||||||
|
memcpy(entries, other->entries, alloc*sizeof(IdentifierHashEntry));
|
||||||
|
}
|
||||||
|
|
||||||
IdentifierHashBase::IdentifierHashBase(ExecutionEngine *engine)
|
IdentifierHashBase::IdentifierHashBase(ExecutionEngine *engine)
|
||||||
{
|
{
|
||||||
d = new IdentifierHashData(3);
|
d = new IdentifierHashData(3);
|
||||||
d->identifierTable = engine->identifierTable;
|
d->identifierTable = engine->identifierTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IdentifierHashBase::detach()
|
||||||
|
{
|
||||||
|
if (!d || d->refCount == 1)
|
||||||
|
return;
|
||||||
|
IdentifierHashData *newData = new IdentifierHashData(d);
|
||||||
|
if (d && !d->refCount.deref())
|
||||||
|
delete d;
|
||||||
|
d = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
IdentifierHashEntry *IdentifierHashBase::addEntry(const Identifier *identifier)
|
IdentifierHashEntry *IdentifierHashBase::addEntry(const Identifier *identifier)
|
||||||
{
|
{
|
||||||
|
|
|
@ -85,6 +85,7 @@ struct IdentifierHashEntry {
|
||||||
struct IdentifierHashData
|
struct IdentifierHashData
|
||||||
{
|
{
|
||||||
IdentifierHashData(int numBits);
|
IdentifierHashData(int numBits);
|
||||||
|
explicit IdentifierHashData(IdentifierHashData *other);
|
||||||
~IdentifierHashData() {
|
~IdentifierHashData() {
|
||||||
free(entries);
|
free(entries);
|
||||||
}
|
}
|
||||||
|
@ -115,6 +116,8 @@ struct IdentifierHashBase
|
||||||
bool contains(const QString &str) const;
|
bool contains(const QString &str) const;
|
||||||
bool contains(String *str) const;
|
bool contains(String *str) const;
|
||||||
|
|
||||||
|
void detach();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
IdentifierHashEntry *addEntry(const Identifier *i);
|
IdentifierHashEntry *addEntry(const Identifier *i);
|
||||||
const IdentifierHashEntry *lookup(const Identifier *identifier) const;
|
const IdentifierHashEntry *lookup(const Identifier *identifier) const;
|
||||||
|
@ -141,6 +144,7 @@ struct IdentifierHash : public IdentifierHashBase
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(const QString &str, const T &value);
|
void add(const QString &str, const T &value);
|
||||||
|
void add(Heap::String *str, const T &value);
|
||||||
|
|
||||||
inline T value(const QString &str) const;
|
inline T value(const QString &str) const;
|
||||||
inline T value(String *str) const;
|
inline T value(String *str) const;
|
||||||
|
@ -197,6 +201,13 @@ void IdentifierHash<T>::add(const QString &str, const T &value)
|
||||||
e->value = value;
|
e->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void IdentifierHash<T>::add(Heap::String *str, const T &value)
|
||||||
|
{
|
||||||
|
IdentifierHashEntry *e = addEntry(toIdentifier(str));
|
||||||
|
e->value = value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
inline T IdentifierHash<T>::value(const QString &str) const
|
inline T IdentifierHash<T>::value(const QString &str) const
|
||||||
{
|
{
|
||||||
|
@ -223,7 +234,6 @@ QString IdentifierHash<T>::findId(T value) const
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
@ -78,7 +78,8 @@ Profiler::Profiler(QV4::ExecutionEngine *engine) : featuresEnabled(0), m_engine(
|
||||||
void Profiler::stopProfiling()
|
void Profiler::stopProfiling()
|
||||||
{
|
{
|
||||||
featuresEnabled = 0;
|
featuresEnabled = 0;
|
||||||
reportData();
|
reportData(true);
|
||||||
|
m_sentLocations.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const FunctionCall &call1, const FunctionCall &call2)
|
bool operator<(const FunctionCall &call1, const FunctionCall &call2)
|
||||||
|
@ -88,7 +89,7 @@ bool operator<(const FunctionCall &call1, const FunctionCall &call2)
|
||||||
(call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
|
(call1.m_end == call2.m_end && call1.m_function < call2.m_function)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Profiler::reportData()
|
void Profiler::reportData(bool trackLocations)
|
||||||
{
|
{
|
||||||
std::sort(m_data.begin(), m_data.end());
|
std::sort(m_data.begin(), m_data.end());
|
||||||
QVector<FunctionCallProperties> properties;
|
QVector<FunctionCallProperties> properties;
|
||||||
|
@ -97,9 +98,15 @@ void Profiler::reportData()
|
||||||
|
|
||||||
foreach (const FunctionCall &call, m_data) {
|
foreach (const FunctionCall &call, m_data) {
|
||||||
properties.append(call.properties());
|
properties.append(call.properties());
|
||||||
|
Function *function = call.function();
|
||||||
|
SentMarker &marker = m_sentLocations[reinterpret_cast<quintptr>(function)];
|
||||||
|
if (!trackLocations || !marker.isValid()) {
|
||||||
FunctionLocation &location = locations[properties.constLast().id];
|
FunctionLocation &location = locations[properties.constLast().id];
|
||||||
if (!location.isValid())
|
if (!location.isValid())
|
||||||
location = call.resolveLocation();
|
location = call.resolveLocation();
|
||||||
|
if (trackLocations)
|
||||||
|
marker.setFunction(function);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emit dataReady(locations, properties, m_memory_data);
|
emit dataReady(locations, properties, m_memory_data);
|
||||||
|
|
|
@ -134,6 +134,11 @@ public:
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Function *function() const
|
||||||
|
{
|
||||||
|
return m_function;
|
||||||
|
}
|
||||||
|
|
||||||
FunctionLocation resolveLocation() const;
|
FunctionLocation resolveLocation() const;
|
||||||
FunctionCallProperties properties() const;
|
FunctionCallProperties properties() const;
|
||||||
|
|
||||||
|
@ -165,6 +170,46 @@ class Q_QML_EXPORT Profiler : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_DISABLE_COPY(Profiler)
|
Q_DISABLE_COPY(Profiler)
|
||||||
public:
|
public:
|
||||||
|
struct SentMarker {
|
||||||
|
SentMarker() : m_function(nullptr) {}
|
||||||
|
|
||||||
|
SentMarker(const SentMarker &other) : m_function(other.m_function)
|
||||||
|
{
|
||||||
|
if (m_function)
|
||||||
|
m_function->compilationUnit->addref();
|
||||||
|
}
|
||||||
|
|
||||||
|
~SentMarker()
|
||||||
|
{
|
||||||
|
if (m_function)
|
||||||
|
m_function->compilationUnit->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
SentMarker &operator=(const SentMarker &other)
|
||||||
|
{
|
||||||
|
if (&other != this) {
|
||||||
|
if (m_function)
|
||||||
|
m_function->compilationUnit->release();
|
||||||
|
m_function = other.m_function;
|
||||||
|
m_function->compilationUnit->addref();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFunction(Function *function)
|
||||||
|
{
|
||||||
|
Q_ASSERT(m_function == nullptr);
|
||||||
|
m_function = function;
|
||||||
|
m_function->compilationUnit->addref();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValid() const
|
||||||
|
{ return m_function != nullptr; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Function *m_function;
|
||||||
|
};
|
||||||
|
|
||||||
Profiler(QV4::ExecutionEngine *engine);
|
Profiler(QV4::ExecutionEngine *engine);
|
||||||
|
|
||||||
size_t trackAlloc(size_t size, MemoryType type)
|
size_t trackAlloc(size_t size, MemoryType type)
|
||||||
|
@ -186,7 +231,7 @@ public:
|
||||||
public slots:
|
public slots:
|
||||||
void stopProfiling();
|
void stopProfiling();
|
||||||
void startProfiling(quint64 features);
|
void startProfiling(quint64 features);
|
||||||
void reportData();
|
void reportData(bool trackLocations);
|
||||||
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
void setTimer(const QElapsedTimer &timer) { m_timer = timer; }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -199,6 +244,7 @@ private:
|
||||||
QElapsedTimer m_timer;
|
QElapsedTimer m_timer;
|
||||||
QVector<FunctionCall> m_data;
|
QVector<FunctionCall> m_data;
|
||||||
QVector<MemoryAllocationProperties> m_memory_data;
|
QVector<MemoryAllocationProperties> m_memory_data;
|
||||||
|
QHash<quintptr, SentMarker> m_sentLocations;
|
||||||
|
|
||||||
friend class FunctionCallProfiler;
|
friend class FunctionCallProfiler;
|
||||||
};
|
};
|
||||||
|
@ -237,6 +283,7 @@ Q_DECLARE_TYPEINFO(QV4::Profiling::MemoryAllocationProperties, Q_MOVABLE_TYPE);
|
||||||
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCallProperties, Q_MOVABLE_TYPE);
|
||||||
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionCall, Q_MOVABLE_TYPE);
|
||||||
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QV4::Profiling::FunctionLocation, Q_MOVABLE_TYPE);
|
||||||
|
Q_DECLARE_TYPEINFO(QV4::Profiling::Profiler::SentMarker, Q_MOVABLE_TYPE);
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
|
Q_DECLARE_METATYPE(QV4::Profiling::FunctionLocationHash)
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
#include <pthread_np.h>
|
#include <pthread_np.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT (std::size_t)128*1024
|
#define MIN_UNMANAGED_HEAPSIZE_GC_LIMIT std::size_t(128 * 1024)
|
||||||
|
|
||||||
using namespace WTF;
|
using namespace WTF;
|
||||||
|
|
||||||
|
@ -108,29 +108,20 @@ using namespace QV4;
|
||||||
|
|
||||||
struct MemoryManager::Data
|
struct MemoryManager::Data
|
||||||
{
|
{
|
||||||
|
const size_t pageSize;
|
||||||
|
|
||||||
struct ChunkHeader {
|
struct ChunkHeader {
|
||||||
Heap::Base freeItems;
|
Heap::Base freeItems;
|
||||||
ChunkHeader *nextNonFull;
|
ChunkHeader *nextNonFull;
|
||||||
char *itemStart;
|
char *itemStart;
|
||||||
char *itemEnd;
|
char *itemEnd;
|
||||||
int itemSize;
|
unsigned itemSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool gcBlocked;
|
|
||||||
bool aggressiveGC;
|
|
||||||
bool gcStats;
|
|
||||||
ExecutionEngine *engine;
|
ExecutionEngine *engine;
|
||||||
|
|
||||||
enum { MaxItemSize = 512 };
|
|
||||||
ChunkHeader *nonFullChunks[MaxItemSize/16];
|
|
||||||
uint nChunks[MaxItemSize/16];
|
|
||||||
uint availableItems[MaxItemSize/16];
|
|
||||||
uint allocCount[MaxItemSize/16];
|
|
||||||
int totalItems;
|
|
||||||
int totalAlloc;
|
|
||||||
uint maxShift;
|
|
||||||
std::size_t maxChunkSize;
|
std::size_t maxChunkSize;
|
||||||
QVector<PageAllocation> heapChunks;
|
std::vector<PageAllocation> heapChunks;
|
||||||
std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
|
std::size_t unmanagedHeapSize; // the amount of bytes of heap that is not managed by the memory manager, but which is held onto by managed items.
|
||||||
std::size_t unmanagedHeapSizeGCLimit;
|
std::size_t unmanagedHeapSizeGCLimit;
|
||||||
|
|
||||||
|
@ -147,24 +138,39 @@ struct MemoryManager::Data
|
||||||
LargeItem *largeItems;
|
LargeItem *largeItems;
|
||||||
std::size_t totalLargeItemsAllocated;
|
std::size_t totalLargeItemsAllocated;
|
||||||
|
|
||||||
|
enum { MaxItemSize = 512 };
|
||||||
|
ChunkHeader *nonFullChunks[MaxItemSize/16];
|
||||||
|
uint nChunks[MaxItemSize/16];
|
||||||
|
uint availableItems[MaxItemSize/16];
|
||||||
|
uint allocCount[MaxItemSize/16];
|
||||||
|
int totalItems;
|
||||||
|
int totalAlloc;
|
||||||
|
uint maxShift;
|
||||||
|
|
||||||
|
bool gcBlocked;
|
||||||
|
bool aggressiveGC;
|
||||||
|
bool gcStats;
|
||||||
|
bool unused; // suppress padding warning
|
||||||
|
|
||||||
// statistics:
|
// statistics:
|
||||||
#ifdef DETAILED_MM_STATS
|
#ifdef DETAILED_MM_STATS
|
||||||
QVector<unsigned> allocSizeCounters;
|
QVector<unsigned> allocSizeCounters;
|
||||||
#endif // DETAILED_MM_STATS
|
#endif // DETAILED_MM_STATS
|
||||||
|
|
||||||
Data()
|
Data()
|
||||||
: gcBlocked(false)
|
: pageSize(WTF::pageSize())
|
||||||
, aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
|
|
||||||
, gcStats(!qEnvironmentVariableIsEmpty("QV4_MM_STATS"))
|
|
||||||
, engine(0)
|
, engine(0)
|
||||||
, totalItems(0)
|
|
||||||
, totalAlloc(0)
|
|
||||||
, maxShift(maxShiftValue())
|
|
||||||
, maxChunkSize(maxChunkSizeValue())
|
, maxChunkSize(maxChunkSizeValue())
|
||||||
, unmanagedHeapSize(0)
|
, unmanagedHeapSize(0)
|
||||||
, unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
|
, unmanagedHeapSizeGCLimit(MIN_UNMANAGED_HEAPSIZE_GC_LIMIT)
|
||||||
, largeItems(0)
|
, largeItems(0)
|
||||||
, totalLargeItemsAllocated(0)
|
, totalLargeItemsAllocated(0)
|
||||||
|
, totalItems(0)
|
||||||
|
, totalAlloc(0)
|
||||||
|
, maxShift(maxShiftValue())
|
||||||
|
, gcBlocked(false)
|
||||||
|
, aggressiveGC(!qEnvironmentVariableIsEmpty("QV4_MM_AGGRESSIVE_GC"))
|
||||||
|
, gcStats(!qEnvironmentVariableIsEmpty("QV4_MM_STATS"))
|
||||||
{
|
{
|
||||||
memset(nonFullChunks, 0, sizeof(nonFullChunks));
|
memset(nonFullChunks, 0, sizeof(nonFullChunks));
|
||||||
memset(nChunks, 0, sizeof(nChunks));
|
memset(nChunks, 0, sizeof(nChunks));
|
||||||
|
@ -174,7 +180,7 @@ struct MemoryManager::Data
|
||||||
|
|
||||||
~Data()
|
~Data()
|
||||||
{
|
{
|
||||||
for (QVector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
|
for (std::vector<PageAllocation>::iterator i = heapChunks.begin(), ei = heapChunks.end(); i != ei; ++i) {
|
||||||
Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
|
Q_V4_PROFILE_DEALLOC(engine, 0, i->size(), Profiling::HeapPage);
|
||||||
i->deallocate();
|
i->deallocate();
|
||||||
}
|
}
|
||||||
|
@ -198,7 +204,7 @@ bool sweepChunk(MemoryManager::Data::ChunkHeader *header, uint *itemsInUse, Exec
|
||||||
// qDebug("chunk @ %p, in use: %s, mark bit: %s",
|
// qDebug("chunk @ %p, in use: %s, mark bit: %s",
|
||||||
// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false"));
|
// item, (m->inUse() ? "yes" : "no"), (m->isMarked() ? "true" : "false"));
|
||||||
|
|
||||||
Q_ASSERT((qintptr) item % 16 == 0);
|
Q_ASSERT(qintptr(item) % 16 == 0);
|
||||||
|
|
||||||
if (m->isMarked()) {
|
if (m->isMarked()) {
|
||||||
Q_ASSERT(m->inUse());
|
Q_ASSERT(m->inUse());
|
||||||
|
@ -324,14 +330,15 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
|
||||||
if (shift > m_d->maxShift)
|
if (shift > m_d->maxShift)
|
||||||
shift = m_d->maxShift;
|
shift = m_d->maxShift;
|
||||||
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
|
std::size_t allocSize = m_d->maxChunkSize*(size_t(1) << shift);
|
||||||
allocSize = roundUpToMultipleOf(WTF::pageSize(), allocSize);
|
allocSize = roundUpToMultipleOf(m_d->pageSize, allocSize);
|
||||||
PageAllocation allocation = PageAllocation::allocate(
|
PageAllocation allocation = PageAllocation::allocate(
|
||||||
Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
|
Q_V4_PROFILE_ALLOC(engine, allocSize, Profiling::HeapPage),
|
||||||
OSAllocator::JSGCHeapPages);
|
OSAllocator::JSGCHeapPages);
|
||||||
m_d->heapChunks.append(allocation);
|
m_d->heapChunks.push_back(allocation);
|
||||||
|
|
||||||
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
|
header = reinterpret_cast<Data::ChunkHeader *>(allocation.base());
|
||||||
header->itemSize = int(size);
|
Q_ASSERT(size <= UINT_MAX);
|
||||||
|
header->itemSize = unsigned(size);
|
||||||
header->itemStart = reinterpret_cast<char *>(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader));
|
header->itemStart = reinterpret_cast<char *>(allocation.base()) + roundUpToMultipleOf(16, sizeof(Data::ChunkHeader));
|
||||||
header->itemEnd = reinterpret_cast<char *>(allocation.base()) + allocation.size() - header->itemSize;
|
header->itemEnd = reinterpret_cast<char *>(allocation.base()) + allocation.size() - header->itemSize;
|
||||||
|
|
||||||
|
@ -347,7 +354,8 @@ Heap::Base *MemoryManager::allocData(std::size_t size, std::size_t unmanagedSize
|
||||||
}
|
}
|
||||||
last->setNextFree(0);
|
last->setNextFree(0);
|
||||||
m = header->freeItems.nextFree();
|
m = header->freeItems.nextFree();
|
||||||
const size_t increase = (header->itemEnd - header->itemStart) / header->itemSize;
|
Q_ASSERT(header->itemEnd >= header->itemStart);
|
||||||
|
const size_t increase = quintptr(header->itemEnd - header->itemStart) / header->itemSize;
|
||||||
m_d->availableItems[pos] += uint(increase);
|
m_d->availableItems[pos] += uint(increase);
|
||||||
m_d->totalItems += int(increase);
|
m_d->totalItems += int(increase);
|
||||||
#ifdef V4_USE_VALGRIND
|
#ifdef V4_USE_VALGRIND
|
||||||
|
@ -465,22 +473,23 @@ void MemoryManager::sweep(bool lastSweep)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool *chunkIsEmpty = (bool *)alloca(m_d->heapChunks.size() * sizeof(bool));
|
bool *chunkIsEmpty = static_cast<bool *>(alloca(m_d->heapChunks.size() * sizeof(bool)));
|
||||||
uint itemsInUse[MemoryManager::Data::MaxItemSize/16];
|
uint itemsInUse[MemoryManager::Data::MaxItemSize/16];
|
||||||
memset(itemsInUse, 0, sizeof(itemsInUse));
|
memset(itemsInUse, 0, sizeof(itemsInUse));
|
||||||
memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks));
|
memset(m_d->nonFullChunks, 0, sizeof(m_d->nonFullChunks));
|
||||||
|
|
||||||
for (int i = 0; i < m_d->heapChunks.size(); ++i) {
|
for (size_t i = 0; i < m_d->heapChunks.size(); ++i) {
|
||||||
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
|
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(m_d->heapChunks[i].base());
|
||||||
chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
|
chunkIsEmpty[i] = sweepChunk(header, &itemsInUse[header->itemSize >> 4], engine, &m_d->unmanagedHeapSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
|
std::vector<PageAllocation>::iterator chunkIter = m_d->heapChunks.begin();
|
||||||
for (int i = 0; i < m_d->heapChunks.size(); ++i) {
|
for (size_t i = 0; i < m_d->heapChunks.size(); ++i) {
|
||||||
Q_ASSERT(chunkIter != m_d->heapChunks.end());
|
Q_ASSERT(chunkIter != m_d->heapChunks.end());
|
||||||
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(chunkIter->base());
|
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(chunkIter->base());
|
||||||
const size_t pos = header->itemSize >> 4;
|
const size_t pos = header->itemSize >> 4;
|
||||||
const size_t decrease = (header->itemEnd - header->itemStart) / header->itemSize;
|
Q_ASSERT(header->itemEnd >= header->itemStart);
|
||||||
|
const size_t decrease = quintptr(header->itemEnd - header->itemStart) / header->itemSize;
|
||||||
|
|
||||||
// Release that chunk if it could have been spared since the last GC run without any difference.
|
// Release that chunk if it could have been spared since the last GC run without any difference.
|
||||||
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
|
if (chunkIsEmpty[i] && m_d->availableItems[pos] - decrease >= itemsInUse[pos]) {
|
||||||
|
@ -561,7 +570,7 @@ void MemoryManager::runGC()
|
||||||
t.restart();
|
t.restart();
|
||||||
const size_t usedBefore = getUsedMem();
|
const size_t usedBefore = getUsedMem();
|
||||||
const size_t largeItemsBefore = getLargeItemsMem();
|
const size_t largeItemsBefore = getLargeItemsMem();
|
||||||
int chunksBefore = m_d->heapChunks.size();
|
size_t chunksBefore = m_d->heapChunks.size();
|
||||||
sweep();
|
sweep();
|
||||||
const size_t usedAfter = getUsedMem();
|
const size_t usedAfter = getUsedMem();
|
||||||
const size_t largeItemsAfter = getLargeItemsMem();
|
const size_t largeItemsAfter = getLargeItemsMem();
|
||||||
|
@ -589,11 +598,11 @@ void MemoryManager::runGC()
|
||||||
size_t MemoryManager::getUsedMem() const
|
size_t MemoryManager::getUsedMem() const
|
||||||
{
|
{
|
||||||
size_t usedMem = 0;
|
size_t usedMem = 0;
|
||||||
for (QVector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
|
for (std::vector<PageAllocation>::const_iterator i = m_d->heapChunks.cbegin(), ei = m_d->heapChunks.cend(); i != ei; ++i) {
|
||||||
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
|
Data::ChunkHeader *header = reinterpret_cast<Data::ChunkHeader *>(i->base());
|
||||||
for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
|
for (char *item = header->itemStart; item <= header->itemEnd; item += header->itemSize) {
|
||||||
Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
|
Heap::Base *m = reinterpret_cast<Heap::Base *>(item);
|
||||||
Q_ASSERT((qintptr) item % 16 == 0);
|
Q_ASSERT(qintptr(item) % 16 == 0);
|
||||||
if (m->inUse())
|
if (m->inUse())
|
||||||
usedMem += header->itemSize;
|
usedMem += header->itemSize;
|
||||||
}
|
}
|
||||||
|
@ -604,7 +613,7 @@ size_t MemoryManager::getUsedMem() const
|
||||||
size_t MemoryManager::getAllocatedMem() const
|
size_t MemoryManager::getAllocatedMem() const
|
||||||
{
|
{
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
for (int i = 0; i < m_d->heapChunks.size(); ++i)
|
for (size_t i = 0; i < m_d->heapChunks.size(); ++i)
|
||||||
total += m_d->heapChunks.at(i).size();
|
total += m_d->heapChunks.at(i).size();
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,8 +55,7 @@
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
|
QQmlCompiledData::QQmlCompiledData(QQmlEngine *engine)
|
||||||
: engine(engine), importCache(0), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false),
|
: engine(engine), metaTypeId(-1), listMetaTypeId(-1), isRegisteredWithEngine(false)
|
||||||
totalBindingsCount(0), totalParserStatusCount(0)
|
|
||||||
{
|
{
|
||||||
Q_ASSERT(engine);
|
Q_ASSERT(engine);
|
||||||
}
|
}
|
||||||
|
@ -85,16 +84,6 @@ QQmlCompiledData::~QQmlCompiledData()
|
||||||
}
|
}
|
||||||
qDeleteAll(resolvedTypes);
|
qDeleteAll(resolvedTypes);
|
||||||
resolvedTypes.clear();
|
resolvedTypes.clear();
|
||||||
|
|
||||||
for (int ii = 0; ii < scripts.count(); ++ii)
|
|
||||||
scripts.at(ii)->release();
|
|
||||||
|
|
||||||
if (importCache)
|
|
||||||
importCache->release();
|
|
||||||
|
|
||||||
for (int ii = 0; ii < propertyCaches.count(); ++ii)
|
|
||||||
if (propertyCaches.at(ii).data())
|
|
||||||
propertyCaches.at(ii)->release();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlCompiledData::clear()
|
void QQmlCompiledData::clear()
|
||||||
|
@ -109,7 +98,7 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::propertyCache() const
|
||||||
if (type)
|
if (type)
|
||||||
return typePropertyCache;
|
return typePropertyCache;
|
||||||
else
|
else
|
||||||
return component->rootPropertyCache();
|
return component->compilationUnit->rootPropertyCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -124,7 +113,7 @@ QQmlPropertyCache *QQmlCompiledData::TypeReference::createPropertyCache(QQmlEngi
|
||||||
typePropertyCache->addref();
|
typePropertyCache->addref();
|
||||||
return typePropertyCache;
|
return typePropertyCache;
|
||||||
} else {
|
} else {
|
||||||
return component->rootPropertyCache();
|
return component->compilationUnit->rootPropertyCache();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,7 +135,7 @@ void QQmlCompiledData::TypeReference::doDynamicTypeCheck()
|
||||||
else if (type)
|
else if (type)
|
||||||
mo = type->metaObject();
|
mo = type->metaObject();
|
||||||
else if (component)
|
else if (component)
|
||||||
mo = component->rootPropertyCache()->firstCppMetaObject();
|
mo = component->compilationUnit->rootPropertyCache()->firstCppMetaObject();
|
||||||
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
|
isFullyDynamicType = qtTypeInherits<QQmlPropertyMap>(mo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,10 +80,6 @@ class QQmlComponent;
|
||||||
class QQmlContext;
|
class QQmlContext;
|
||||||
class QQmlContextData;
|
class QQmlContextData;
|
||||||
|
|
||||||
// The vector is indexed by QV4::CompiledData::Object index and the flag
|
|
||||||
// indicates whether instantiation of the object requires a VME meta-object.
|
|
||||||
typedef QVector<QFlagPointer<QQmlPropertyCache>> QQmlPropertyCacheVector;
|
|
||||||
|
|
||||||
// ### Merge with QV4::CompiledData::CompilationUnit
|
// ### Merge with QV4::CompiledData::CompilationUnit
|
||||||
class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
|
class Q_AUTOTEST_EXPORT QQmlCompiledData : public QQmlRefCount, public QQmlCleanup
|
||||||
{
|
{
|
||||||
|
@ -93,8 +89,6 @@ public:
|
||||||
|
|
||||||
QQmlEngine *engine;
|
QQmlEngine *engine;
|
||||||
|
|
||||||
QQmlTypeNameCache *importCache;
|
|
||||||
|
|
||||||
int metaTypeId;
|
int metaTypeId;
|
||||||
int listMetaTypeId;
|
int listMetaTypeId;
|
||||||
bool isRegisteredWithEngine;
|
bool isRegisteredWithEngine;
|
||||||
|
@ -126,23 +120,7 @@ public:
|
||||||
// map from name index
|
// map from name index
|
||||||
QHash<int, TypeReference*> resolvedTypes;
|
QHash<int, TypeReference*> resolvedTypes;
|
||||||
|
|
||||||
QQmlPropertyCache *rootPropertyCache() const { return propertyCaches.at(compilationUnit->data->indexOfRootObject).data(); }
|
|
||||||
QQmlPropertyCacheVector propertyCaches;
|
|
||||||
QList<QQmlScriptData *> scripts;
|
|
||||||
|
|
||||||
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
||||||
// index in first hash is component index, hash inside maps from object index in that scope to integer id
|
|
||||||
QHash<int, QHash<int, int> > objectIndexToIdPerComponent;
|
|
||||||
QHash<int, int> objectIndexToIdForRoot;
|
|
||||||
// hash key is object index, value is indicies of bindings covered by custom parser
|
|
||||||
QHash<int, QBitArray> customParserBindings;
|
|
||||||
QHash<int, QBitArray> deferredBindingsPerObject; // index is object index
|
|
||||||
int totalBindingsCount; // Number of bindings used in this type
|
|
||||||
int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses
|
|
||||||
int totalObjectCount; // Number of objects explicitly instantiated
|
|
||||||
|
|
||||||
bool isComponent(int objectIndex) const { return objectIndexToIdPerComponent.contains(objectIndex); }
|
|
||||||
bool isCompositeType() const { return propertyCaches.at(compilationUnit->data->indexOfRootObject).flag(); }
|
|
||||||
|
|
||||||
bool isInitialized() const { return hasEngine(); }
|
bool isInitialized() const { return hasEngine(); }
|
||||||
void initialize(QQmlEngine *);
|
void initialize(QQmlEngine *);
|
||||||
|
|
|
@ -310,7 +310,7 @@ void QQmlContext::setContextProperty(const QString &name, const QVariant &value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QV4::IdentifierHash<int> &properties = data->propertyNames();
|
QV4::IdentifierHash<int> &properties = data->detachedPropertyNames();
|
||||||
int idx = properties.value(name);
|
int idx = properties.value(name);
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
properties.add(name, data->idValueCount + d->propertyValues.count());
|
properties.add(name, data->idValueCount + d->propertyValues.count());
|
||||||
|
@ -346,7 +346,7 @@ void QQmlContext::setContextProperty(const QString &name, QObject *value)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QV4::IdentifierHash<int> &properties = data->propertyNames();
|
QV4::IdentifierHash<int> &properties = data->detachedPropertyNames();
|
||||||
int idx = properties.value(name);
|
int idx = properties.value(name);
|
||||||
|
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
|
@ -523,7 +523,7 @@ QQmlContextData::QQmlContextData()
|
||||||
QQmlContextData::QQmlContextData(QQmlContext *ctxt)
|
QQmlContextData::QQmlContextData(QQmlContext *ctxt)
|
||||||
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
|
: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false),
|
||||||
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
|
isPragmaLibraryContext(false), unresolvedNames(false), hasEmittedDestruction(false), isRootObjectInCreation(false),
|
||||||
publicContext(ctxt), activeVMEData(0),
|
publicContext(ctxt), activeVMEData(0), componentObjectIndex(-1),
|
||||||
contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
|
contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
|
||||||
expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
|
expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), linkedContext(0),
|
||||||
componentAttached(0)
|
componentAttached(0)
|
||||||
|
@ -760,15 +760,6 @@ void QQmlContextData::setIdProperty(int idx, QObject *obj)
|
||||||
idValues[idx].context = this;
|
idValues[idx].context = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlContextData::setIdPropertyData(const QHash<int, int> &data)
|
|
||||||
{
|
|
||||||
Q_ASSERT(objectIndexToId.isEmpty());
|
|
||||||
objectIndexToId = data;
|
|
||||||
Q_ASSERT(propertyNameCache.isEmpty());
|
|
||||||
idValueCount = data.count();
|
|
||||||
idValues = new ContextGuard[idValueCount];
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QQmlContextData::findObjectId(const QObject *obj) const
|
QString QQmlContextData::findObjectId(const QObject *obj) const
|
||||||
{
|
{
|
||||||
const QV4::IdentifierHash<int> &properties = propertyNames();
|
const QV4::IdentifierHash<int> &properties = propertyNames();
|
||||||
|
@ -804,18 +795,30 @@ QQmlContextPrivate *QQmlContextData::asQQmlContextPrivate()
|
||||||
return QQmlContextPrivate::get(asQQmlContext());
|
return QQmlContextPrivate::get(asQQmlContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
|
void QQmlContextData::initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex)
|
||||||
|
{
|
||||||
|
typeCompilationUnit = unit;
|
||||||
|
componentObjectIndex = subComponentIndex == -1 ? typeCompilationUnit->data->indexOfRootObject : subComponentIndex;
|
||||||
|
Q_ASSERT(!idValues);
|
||||||
|
idValueCount = typeCompilationUnit->data->objectAt(componentObjectIndex)->nNamedObjectsInComponent;
|
||||||
|
idValues = new ContextGuard[idValueCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
const QV4::IdentifierHash<int> &QQmlContextData::propertyNames() const
|
||||||
{
|
{
|
||||||
if (propertyNameCache.isEmpty()) {
|
if (propertyNameCache.isEmpty()) {
|
||||||
propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine->handle()));
|
if (typeCompilationUnit)
|
||||||
for (QHash<int, int>::ConstIterator it = objectIndexToId.cbegin(), end = objectIndexToId.cend();
|
propertyNameCache = typeCompilationUnit->namedObjectsPerComponent(componentObjectIndex);
|
||||||
it != end; ++it) {
|
else
|
||||||
const QV4::CompiledData::Object *obj = typeCompilationUnit->data->objectAt(it.key());
|
propertyNameCache = QV4::IdentifierHash<int>(QV8Engine::getV4(engine));
|
||||||
const QString name = typeCompilationUnit->data->stringAt(obj->idIndex);
|
|
||||||
propertyNameCache.add(name, it.value());
|
|
||||||
}
|
}
|
||||||
objectIndexToId.clear();
|
return propertyNameCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QV4::IdentifierHash<int> &QQmlContextData::detachedPropertyNames()
|
||||||
|
{
|
||||||
|
propertyNames();
|
||||||
|
propertyNameCache.detach();
|
||||||
return propertyNameCache;
|
return propertyNameCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,9 +151,15 @@ public:
|
||||||
// Compilation unit for contexts that belong to a compiled type.
|
// Compilation unit for contexts that belong to a compiled type.
|
||||||
QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> typeCompilationUnit;
|
||||||
|
|
||||||
mutable QHash<int, int> objectIndexToId;
|
// object index in CompiledData::Unit to component that created this context
|
||||||
|
int componentObjectIndex;
|
||||||
|
|
||||||
|
void initFromTypeCompilationUnit(const QQmlRefPointer<QV4::CompiledData::CompilationUnit> &unit, int subComponentIndex);
|
||||||
|
|
||||||
|
// flag indicates whether the context owns the cache (after mutation) or not.
|
||||||
mutable QV4::IdentifierHash<int> propertyNameCache;
|
mutable QV4::IdentifierHash<int> propertyNameCache;
|
||||||
QV4::IdentifierHash<int> &propertyNames() const;
|
const QV4::IdentifierHash<int> &propertyNames() const;
|
||||||
|
QV4::IdentifierHash<int> &detachedPropertyNames();
|
||||||
|
|
||||||
// Context object
|
// Context object
|
||||||
QObject *contextObject;
|
QObject *contextObject;
|
||||||
|
@ -201,7 +207,6 @@ public:
|
||||||
ContextGuard *idValues;
|
ContextGuard *idValues;
|
||||||
int idValueCount;
|
int idValueCount;
|
||||||
void setIdProperty(int, QObject *);
|
void setIdProperty(int, QObject *);
|
||||||
void setIdPropertyData(const QHash<int, int> &);
|
|
||||||
|
|
||||||
// Linked contexts. this owns linkedContext.
|
// Linked contexts. this owns linkedContext.
|
||||||
QQmlContextData *linkedContext;
|
QQmlContextData *linkedContext;
|
||||||
|
|
|
@ -82,7 +82,7 @@ public:
|
||||||
Flags flags() const { return m_flags; }
|
Flags flags() const { return m_flags; }
|
||||||
|
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
|
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
|
||||||
virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) = 0;
|
virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) = 0;
|
||||||
|
|
||||||
QList<QQmlError> errors() const { return exceptions; }
|
QList<QQmlError> errors() const { return exceptions; }
|
||||||
|
|
||||||
|
|
|
@ -2227,7 +2227,7 @@ QQmlMetaObject QQmlEnginePrivate::rawMetaObjectForType(int t) const
|
||||||
Locker locker(this);
|
Locker locker(this);
|
||||||
QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
|
QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
|
||||||
if (iter != m_compositeTypes.cend()) {
|
if (iter != m_compositeTypes.cend()) {
|
||||||
return QQmlMetaObject((*iter)->rootPropertyCache());
|
return QQmlMetaObject((*iter)->compilationUnit->rootPropertyCache());
|
||||||
} else {
|
} else {
|
||||||
QQmlType *type = QQmlMetaType::qmlType(t);
|
QQmlType *type = QQmlMetaType::qmlType(t);
|
||||||
return QQmlMetaObject(type?type->baseMetaObject():0);
|
return QQmlMetaObject(type?type->baseMetaObject():0);
|
||||||
|
@ -2239,7 +2239,7 @@ QQmlMetaObject QQmlEnginePrivate::metaObjectForType(int t) const
|
||||||
Locker locker(this);
|
Locker locker(this);
|
||||||
QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
|
QHash<int, QQmlCompiledData *>::ConstIterator iter = m_compositeTypes.constFind(t);
|
||||||
if (iter != m_compositeTypes.cend()) {
|
if (iter != m_compositeTypes.cend()) {
|
||||||
return QQmlMetaObject((*iter)->rootPropertyCache());
|
return QQmlMetaObject((*iter)->compilationUnit->rootPropertyCache());
|
||||||
} else {
|
} else {
|
||||||
QQmlType *type = QQmlMetaType::qmlType(t);
|
QQmlType *type = QQmlMetaType::qmlType(t);
|
||||||
return QQmlMetaObject(type?type->metaObject():0);
|
return QQmlMetaObject(type?type->metaObject():0);
|
||||||
|
@ -2251,7 +2251,7 @@ QQmlPropertyCache *QQmlEnginePrivate::propertyCacheForType(int t)
|
||||||
Locker locker(this);
|
Locker locker(this);
|
||||||
QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
|
QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
|
||||||
if (iter != m_compositeTypes.cend()) {
|
if (iter != m_compositeTypes.cend()) {
|
||||||
return (*iter)->rootPropertyCache();
|
return (*iter)->compilationUnit->rootPropertyCache();
|
||||||
} else {
|
} else {
|
||||||
QQmlType *type = QQmlMetaType::qmlType(t);
|
QQmlType *type = QQmlMetaType::qmlType(t);
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
|
@ -2264,7 +2264,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
|
||||||
Locker locker(this);
|
Locker locker(this);
|
||||||
QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
|
QHash<int, QQmlCompiledData*>::ConstIterator iter = m_compositeTypes.constFind(t);
|
||||||
if (iter != m_compositeTypes.cend()) {
|
if (iter != m_compositeTypes.cend()) {
|
||||||
return (*iter)->rootPropertyCache();
|
return (*iter)->compilationUnit->rootPropertyCache();
|
||||||
} else {
|
} else {
|
||||||
QQmlType *type = QQmlMetaType::qmlType(t);
|
QQmlType *type = QQmlMetaType::qmlType(t);
|
||||||
locker.unlock();
|
locker.unlock();
|
||||||
|
@ -2274,7 +2274,7 @@ QQmlPropertyCache *QQmlEnginePrivate::rawPropertyCacheForType(int t)
|
||||||
|
|
||||||
void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
|
void QQmlEnginePrivate::registerInternalCompositeType(QQmlCompiledData *data)
|
||||||
{
|
{
|
||||||
QByteArray name = data->rootPropertyCache()->className();
|
QByteArray name = data->compilationUnit->rootPropertyCache()->className();
|
||||||
|
|
||||||
QByteArray ptr = name + '*';
|
QByteArray ptr = name + '*';
|
||||||
QByteArray lst = "QQmlListProperty<" + name + '>';
|
QByteArray lst = "QQmlListProperty<" + name + '>';
|
||||||
|
|
|
@ -494,7 +494,7 @@ QQmlType *QQmlType::resolveCompositeBaseType(QQmlEnginePrivate *engine) const
|
||||||
if (!td || !td->isComplete())
|
if (!td || !td->isComplete())
|
||||||
return 0;
|
return 0;
|
||||||
QQmlCompiledData *cd = td->compiledData();
|
QQmlCompiledData *cd = td->compiledData();
|
||||||
const QMetaObject *mo = cd->rootPropertyCache()->firstCppMetaObject();
|
const QMetaObject *mo = cd->compilationUnit->rootPropertyCache()->firstCppMetaObject();
|
||||||
return QQmlMetaType::qmlType(mo);
|
return QQmlMetaType::qmlType(mo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -73,7 +73,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
|
||||||
: phase(Startup)
|
: phase(Startup)
|
||||||
, compiledData(compiledData)
|
, compiledData(compiledData)
|
||||||
, resolvedTypes(compiledData->resolvedTypes)
|
, resolvedTypes(compiledData->resolvedTypes)
|
||||||
, propertyCaches(compiledData->propertyCaches)
|
, propertyCaches(compiledData->compilationUnit->propertyCaches)
|
||||||
, activeVMEDataForRootContext(activeVMEDataForRootContext)
|
, activeVMEDataForRootContext(activeVMEDataForRootContext)
|
||||||
{
|
{
|
||||||
init(parentContext);
|
init(parentContext);
|
||||||
|
@ -81,23 +81,23 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile
|
||||||
sharedState = new QQmlObjectCreatorSharedState;
|
sharedState = new QQmlObjectCreatorSharedState;
|
||||||
topLevelCreator = true;
|
topLevelCreator = true;
|
||||||
sharedState->componentAttached = 0;
|
sharedState->componentAttached = 0;
|
||||||
sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount);
|
sharedState->allCreatedBindings.allocate(compiledData->compilationUnit->totalBindingsCount);
|
||||||
sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount);
|
sharedState->allParserStatusCallbacks.allocate(compiledData->compilationUnit->totalParserStatusCount);
|
||||||
sharedState->allCreatedObjects.allocate(compiledData->totalObjectCount);
|
sharedState->allCreatedObjects.allocate(compiledData->compilationUnit->totalObjectCount);
|
||||||
sharedState->allJavaScriptObjects = 0;
|
sharedState->allJavaScriptObjects = 0;
|
||||||
sharedState->creationContext = creationContext;
|
sharedState->creationContext = creationContext;
|
||||||
sharedState->rootContext = 0;
|
sharedState->rootContext = 0;
|
||||||
|
|
||||||
QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
|
QQmlProfiler *profiler = QQmlEnginePrivate::get(engine)->profiler;
|
||||||
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
|
Q_QML_PROFILE_IF_ENABLED(QQmlProfilerDefinitions::ProfileCreating, profiler,
|
||||||
sharedState->profiler.init(profiler, compiledData->totalParserStatusCount));
|
sharedState->profiler.init(profiler, compiledData->compilationUnit->totalParserStatusCount));
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
|
QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompiledData *compiledData, QQmlObjectCreatorSharedState *inheritedSharedState)
|
||||||
: phase(Startup)
|
: phase(Startup)
|
||||||
, compiledData(compiledData)
|
, compiledData(compiledData)
|
||||||
, resolvedTypes(compiledData->resolvedTypes)
|
, resolvedTypes(compiledData->resolvedTypes)
|
||||||
, propertyCaches(compiledData->propertyCaches)
|
, propertyCaches(compiledData->compilationUnit->propertyCaches)
|
||||||
, activeVMEDataForRootContext(0)
|
, activeVMEDataForRootContext(0)
|
||||||
{
|
{
|
||||||
init(parentContext);
|
init(parentContext);
|
||||||
|
@ -158,19 +158,17 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
|
||||||
int objectToCreate;
|
int objectToCreate;
|
||||||
|
|
||||||
if (subComponentIndex == -1) {
|
if (subComponentIndex == -1) {
|
||||||
objectIndexToId = compiledData->objectIndexToIdForRoot;
|
|
||||||
objectToCreate = qmlUnit->indexOfRootObject;
|
objectToCreate = qmlUnit->indexOfRootObject;
|
||||||
} else {
|
} else {
|
||||||
objectIndexToId = compiledData->objectIndexToIdPerComponent[subComponentIndex];
|
|
||||||
const QV4::CompiledData::Object *compObj = qmlUnit->objectAt(subComponentIndex);
|
const QV4::CompiledData::Object *compObj = qmlUnit->objectAt(subComponentIndex);
|
||||||
objectToCreate = compObj->bindingTable()->value.objectIndex;
|
objectToCreate = compObj->bindingTable()->value.objectIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
context = new QQmlContextData;
|
context = new QQmlContextData;
|
||||||
context->isInternal = true;
|
context->isInternal = true;
|
||||||
context->imports = compiledData->importCache;
|
context->imports = compiledData->compilationUnit->importCache;
|
||||||
context->imports->addref();
|
context->imports->addref();
|
||||||
context->typeCompilationUnit = compiledData->compilationUnit;
|
context->initFromTypeCompilationUnit(compiledData->compilationUnit, subComponentIndex);
|
||||||
context->setParent(parentContext);
|
context->setParent(parentContext);
|
||||||
|
|
||||||
if (!sharedState->rootContext) {
|
if (!sharedState->rootContext) {
|
||||||
|
@ -183,16 +181,14 @@ QObject *QQmlObjectCreator::create(int subComponentIndex, QObject *parent, QQmlI
|
||||||
|
|
||||||
Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
|
Q_ASSERT(sharedState->allJavaScriptObjects || topLevelCreator);
|
||||||
if (topLevelCreator)
|
if (topLevelCreator)
|
||||||
sharedState->allJavaScriptObjects = scope.alloc(compiledData->totalObjectCount);
|
sharedState->allJavaScriptObjects = scope.alloc(compiledData->compilationUnit->totalObjectCount);
|
||||||
|
|
||||||
context->setIdPropertyData(objectIndexToId);
|
if (subComponentIndex == -1 && compiledData->compilationUnit->dependentScripts.count()) {
|
||||||
|
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->compilationUnit->dependentScripts.count()));
|
||||||
if (subComponentIndex == -1 && compiledData->scripts.count()) {
|
|
||||||
QV4::ScopedObject scripts(scope, v4->newArrayObject(compiledData->scripts.count()));
|
|
||||||
context->importedScripts.set(v4, scripts);
|
context->importedScripts.set(v4, scripts);
|
||||||
QV4::ScopedValue v(scope);
|
QV4::ScopedValue v(scope);
|
||||||
for (int i = 0; i < compiledData->scripts.count(); ++i) {
|
for (int i = 0; i < compiledData->compilationUnit->dependentScripts.count(); ++i) {
|
||||||
QQmlScriptData *s = compiledData->scripts.at(i);
|
QQmlScriptData *s = compiledData->compilationUnit->dependentScripts.at(i);
|
||||||
scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
|
scripts->putIndexed(i, (v = s->scriptValueForContext(context)));
|
||||||
}
|
}
|
||||||
} else if (sharedState->creationContext) {
|
} else if (sharedState->creationContext) {
|
||||||
|
@ -240,7 +236,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
|
||||||
|
|
||||||
Q_ASSERT(topLevelCreator);
|
Q_ASSERT(topLevelCreator);
|
||||||
Q_ASSERT(!sharedState->allJavaScriptObjects);
|
Q_ASSERT(!sharedState->allJavaScriptObjects);
|
||||||
sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->totalObjectCount);
|
sharedState->allJavaScriptObjects = valueScope.alloc(compiledData->compilationUnit->totalObjectCount);
|
||||||
|
|
||||||
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
|
QV4::QmlContext *qmlContext = static_cast<QV4::QmlContext *>(valueScope.alloc(1));
|
||||||
|
|
||||||
|
@ -259,11 +255,7 @@ bool QQmlObjectCreator::populateDeferredProperties(QObject *instance)
|
||||||
qSwap(_bindingTarget, bindingTarget);
|
qSwap(_bindingTarget, bindingTarget);
|
||||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||||
|
|
||||||
QBitArray bindingSkipList = compiledData->deferredBindingsPerObject.value(_compiledObjectIndex);
|
setupBindings(/*applyDeferredBindings=*/true);
|
||||||
for (int i = 0; i < bindingSkipList.count(); ++i)
|
|
||||||
bindingSkipList.setBit(i, !bindingSkipList.testBit(i));
|
|
||||||
|
|
||||||
setupBindings(bindingSkipList);
|
|
||||||
|
|
||||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||||
qSwap(_bindingTarget, bindingTarget);
|
qSwap(_bindingTarget, bindingTarget);
|
||||||
|
@ -630,14 +622,14 @@ static QQmlType *qmlTypeForObject(QObject *object)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
|
void QQmlObjectCreator::setupBindings(bool applyDeferredBindings)
|
||||||
{
|
{
|
||||||
QQmlListProperty<void> savedList;
|
QQmlListProperty<void> savedList;
|
||||||
qSwap(_currentList, savedList);
|
qSwap(_currentList, savedList);
|
||||||
|
|
||||||
const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
|
const QV4::CompiledData::BindingPropertyData &propertyData = compiledData->compilationUnit->bindingPropertyDataPerObject.at(_compiledObjectIndex);
|
||||||
|
|
||||||
if (_compiledObject->idIndex) {
|
if (_compiledObject->idNameIndex) {
|
||||||
const QQmlPropertyData *idProperty = propertyData.last();
|
const QQmlPropertyData *idProperty = propertyData.last();
|
||||||
Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
|
Q_ASSERT(!idProperty || !idProperty->isValid() || idProperty->name(_qobject) == QLatin1String("id"));
|
||||||
if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
|
if (idProperty && idProperty->isValid() && idProperty->isWritable() && idProperty->propType == QMetaType::QString) {
|
||||||
|
@ -645,7 +637,7 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
|
||||||
idBinding.propertyNameIndex = 0; // Not used
|
idBinding.propertyNameIndex = 0; // Not used
|
||||||
idBinding.flags = 0;
|
idBinding.flags = 0;
|
||||||
idBinding.type = QV4::CompiledData::Binding::Type_String;
|
idBinding.type = QV4::CompiledData::Binding::Type_String;
|
||||||
idBinding.stringIndex = _compiledObject->idIndex;
|
idBinding.stringIndex = _compiledObject->idNameIndex;
|
||||||
idBinding.location = _compiledObject->location; // ###
|
idBinding.location = _compiledObject->location; // ###
|
||||||
setPropertyValue(idProperty, &idBinding);
|
setPropertyValue(idProperty, &idBinding);
|
||||||
}
|
}
|
||||||
|
@ -681,9 +673,17 @@ void QQmlObjectCreator::setupBindings(const QBitArray &bindingsToSkip)
|
||||||
|
|
||||||
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
|
const QV4::CompiledData::Binding *binding = _compiledObject->bindingTable();
|
||||||
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
|
for (quint32 i = 0; i < _compiledObject->nBindings; ++i, ++binding) {
|
||||||
if (static_cast<int>(i) < bindingsToSkip.size() && bindingsToSkip.testBit(i))
|
if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (binding->flags & QV4::CompiledData::Binding::IsDeferredBinding) {
|
||||||
|
if (!applyDeferredBindings)
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
if (applyDeferredBindings)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const QQmlPropertyData *property = propertyData.at(i);
|
const QQmlPropertyData *property = propertyData.at(i);
|
||||||
|
|
||||||
if (property && property->isQList()) {
|
if (property && property->isQList()) {
|
||||||
|
@ -1005,11 +1005,10 @@ void QQmlObjectCreator::recordError(const QV4::CompiledData::Location &location,
|
||||||
errors << error;
|
errors << error;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlObjectCreator::registerObjectWithContextById(int objectIndex, QObject *instance) const
|
void QQmlObjectCreator::registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const
|
||||||
{
|
{
|
||||||
QHash<int, int>::ConstIterator idEntry = objectIndexToId.find(objectIndex);
|
if (object->id >= 0)
|
||||||
if (idEntry != objectIndexToId.constEnd())
|
context->setIdProperty(object->id, instance);
|
||||||
context->setIdProperty(idEntry.value(), instance);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
|
QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
|
||||||
|
@ -1022,7 +1021,9 @@ QV4::Heap::QmlContext *QQmlObjectCreator::currentQmlContext()
|
||||||
|
|
||||||
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
|
QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isContextObject)
|
||||||
{
|
{
|
||||||
QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler);
|
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
|
||||||
|
QQmlObjectCreationProfiler profiler(sharedState->profiler.profiler, obj);
|
||||||
|
|
||||||
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
|
ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine));
|
||||||
|
|
||||||
bool isComponent = false;
|
bool isComponent = false;
|
||||||
|
@ -1032,8 +1033,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
||||||
QQmlParserStatus *parserStatus = 0;
|
QQmlParserStatus *parserStatus = 0;
|
||||||
bool installPropertyCache = true;
|
bool installPropertyCache = true;
|
||||||
|
|
||||||
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
|
if (obj->flags & QV4::CompiledData::Object::IsComponent) {
|
||||||
if (compiledData->isComponent(index)) {
|
|
||||||
isComponent = true;
|
isComponent = true;
|
||||||
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
|
QQmlComponent *component = new QQmlComponent(engine, compiledData, index, parent);
|
||||||
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
|
Q_QML_OC_PROFILE(sharedState->profiler, profiler.update(
|
||||||
|
@ -1125,28 +1125,26 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
||||||
if (isContextObject)
|
if (isContextObject)
|
||||||
context->contextObject = instance;
|
context->contextObject = instance;
|
||||||
|
|
||||||
QBitArray bindingsToSkip;
|
if (customParser && obj->flags & QV4::CompiledData::Object::HasCustomParserBindings) {
|
||||||
if (customParser) {
|
|
||||||
QHash<int, QBitArray>::ConstIterator customParserBindings = compiledData->customParserBindings.constFind(index);
|
|
||||||
if (customParserBindings != compiledData->customParserBindings.constEnd()) {
|
|
||||||
customParser->engine = QQmlEnginePrivate::get(engine);
|
customParser->engine = QQmlEnginePrivate::get(engine);
|
||||||
customParser->imports = compiledData->importCache;
|
customParser->imports = compiledData->compilationUnit->importCache;
|
||||||
|
|
||||||
QList<const QV4::CompiledData::Binding *> bindings;
|
QList<const QV4::CompiledData::Binding *> bindings;
|
||||||
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
|
const QV4::CompiledData::Object *obj = qmlUnit->objectAt(index);
|
||||||
for (int i = 0; i < customParserBindings->count(); ++i)
|
const QV4::CompiledData::Binding *binding = obj->bindingTable();
|
||||||
if (customParserBindings->testBit(i))
|
for (quint32 i = 0; i < obj->nBindings; ++i, ++binding) {
|
||||||
bindings << obj->bindingTable() + i;
|
if (binding->flags & QV4::CompiledData::Binding::IsCustomParserBinding) {
|
||||||
customParser->applyBindings(instance, compiledData, bindings);
|
bindings << binding;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customParser->applyBindings(instance, compiledData->compilationUnit.data(), bindings);
|
||||||
|
|
||||||
customParser->engine = 0;
|
customParser->engine = 0;
|
||||||
customParser->imports = (QQmlTypeNameCache*)0;
|
customParser->imports = (QQmlTypeNameCache*)0;
|
||||||
bindingsToSkip = *customParserBindings;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isComponent) {
|
if (isComponent) {
|
||||||
registerObjectWithContextById(index, instance);
|
registerObjectWithContextById(obj, instance);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1171,7 +1169,7 @@ QObject *QQmlObjectCreator::createInstance(int index, QObject *parent, bool isCo
|
||||||
|
|
||||||
qSwap(_qmlContext, qmlContext);
|
qSwap(_qmlContext, qmlContext);
|
||||||
|
|
||||||
bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0, bindingsToSkip);
|
bool result = populateInstance(index, instance, /*binding target*/instance, /*value type property*/0);
|
||||||
|
|
||||||
qSwap(_qmlContext, qmlContext);
|
qSwap(_qmlContext, qmlContext);
|
||||||
qSwap(_scopeObject, scopeObject);
|
qSwap(_scopeObject, scopeObject);
|
||||||
|
@ -1266,7 +1264,7 @@ void QQmlObjectCreator::clear()
|
||||||
phase = Done;
|
phase = Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty, const QBitArray &bindingsToSkip)
|
bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty)
|
||||||
{
|
{
|
||||||
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
|
QQmlData *declarativeData = QQmlData::get(instance, /*create*/true);
|
||||||
|
|
||||||
|
@ -1298,21 +1296,12 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
|
||||||
vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
|
vmeMetaObject = QQmlVMEMetaObject::get(_qobject);
|
||||||
}
|
}
|
||||||
|
|
||||||
registerObjectWithContextById(_compiledObjectIndex, _qobject);
|
registerObjectWithContextById(_compiledObject, _qobject);
|
||||||
|
|
||||||
qSwap(_propertyCache, cache);
|
qSwap(_propertyCache, cache);
|
||||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||||
|
|
||||||
QBitArray bindingSkipList = bindingsToSkip;
|
if (_compiledObject->flags & QV4::CompiledData::Object::HasDeferredBindings) {
|
||||||
{
|
|
||||||
QHash<int, QBitArray>::ConstIterator deferredBindings = compiledData->deferredBindingsPerObject.constFind(_compiledObjectIndex);
|
|
||||||
if (deferredBindings != compiledData->deferredBindingsPerObject.constEnd()) {
|
|
||||||
if (bindingSkipList.isEmpty())
|
|
||||||
bindingSkipList.resize(deferredBindings->count());
|
|
||||||
|
|
||||||
for (int i = 0; i < deferredBindings->count(); ++i)
|
|
||||||
if (deferredBindings->testBit(i))
|
|
||||||
bindingSkipList.setBit(i);
|
|
||||||
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
|
QQmlData::DeferredData *deferData = new QQmlData::DeferredData;
|
||||||
deferData->deferredIdx = _compiledObjectIndex;
|
deferData->deferredIdx = _compiledObjectIndex;
|
||||||
deferData->compiledData = compiledData;
|
deferData->compiledData = compiledData;
|
||||||
|
@ -1320,11 +1309,10 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject *
|
||||||
deferData->context = context;
|
deferData->context = context;
|
||||||
_ddata->deferredData = deferData;
|
_ddata->deferredData = deferData;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_compiledObject->nFunctions > 0)
|
if (_compiledObject->nFunctions > 0)
|
||||||
setupFunctions();
|
setupFunctions();
|
||||||
setupBindings(bindingSkipList);
|
setupBindings();
|
||||||
|
|
||||||
qSwap(_vmeMetaObject, vmeMetaObject);
|
qSwap(_vmeMetaObject, vmeMetaObject);
|
||||||
qSwap(_bindingTarget, bindingTarget);
|
qSwap(_bindingTarget, bindingTarget);
|
||||||
|
|
|
@ -111,10 +111,9 @@ private:
|
||||||
QObject *createInstance(int index, QObject *parent = 0, bool isContextObject = false);
|
QObject *createInstance(int index, QObject *parent = 0, bool isContextObject = false);
|
||||||
|
|
||||||
bool populateInstance(int index, QObject *instance,
|
bool populateInstance(int index, QObject *instance,
|
||||||
QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty,
|
QObject *bindingTarget, const QQmlPropertyData *valueTypeProperty);
|
||||||
const QBitArray &bindingsToSkip = QBitArray());
|
|
||||||
|
|
||||||
void setupBindings(const QBitArray &bindingsToSkip);
|
void setupBindings(bool applyDeferredBindings = false);
|
||||||
bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
|
bool setPropertyBinding(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
|
||||||
void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
|
void setPropertyValue(const QQmlPropertyData *property, const QV4::CompiledData::Binding *binding);
|
||||||
void setupFunctions();
|
void setupFunctions();
|
||||||
|
@ -122,7 +121,7 @@ private:
|
||||||
QString stringAt(int idx) const { return qmlUnit->stringAt(idx); }
|
QString stringAt(int idx) const { return qmlUnit->stringAt(idx); }
|
||||||
void recordError(const QV4::CompiledData::Location &location, const QString &description);
|
void recordError(const QV4::CompiledData::Location &location, const QString &description);
|
||||||
|
|
||||||
void registerObjectWithContextById(int objectIndex, QObject *instance) const;
|
void registerObjectWithContextById(const QV4::CompiledData::Object *object, QObject *instance) const;
|
||||||
|
|
||||||
QV4::Heap::QmlContext *currentQmlContext();
|
QV4::Heap::QmlContext *currentQmlContext();
|
||||||
|
|
||||||
|
@ -143,7 +142,6 @@ private:
|
||||||
QQmlContextData *context;
|
QQmlContextData *context;
|
||||||
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
|
const QHash<int, QQmlCompiledData::TypeReference*> &resolvedTypes;
|
||||||
const QQmlPropertyCacheVector &propertyCaches;
|
const QQmlPropertyCacheVector &propertyCaches;
|
||||||
QHash<int, int> objectIndexToId;
|
|
||||||
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
|
QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState;
|
||||||
bool topLevelCreator;
|
bool topLevelCreator;
|
||||||
void *activeVMEDataForRootContext;
|
void *activeVMEDataForRootContext;
|
||||||
|
|
|
@ -452,7 +452,12 @@ QQmlPropertyCache *QQmlPropertyCache::parent() const
|
||||||
|
|
||||||
void QQmlPropertyCache::setParent(QQmlPropertyCache *newParent)
|
void QQmlPropertyCache::setParent(QQmlPropertyCache *newParent)
|
||||||
{
|
{
|
||||||
|
if (_parent == newParent)
|
||||||
|
return;
|
||||||
|
if (_parent)
|
||||||
|
_parent->release();
|
||||||
_parent = newParent;
|
_parent = newParent;
|
||||||
|
_parent->addref();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
|
// Returns the first C++ type's QMetaObject - that is, the first QMetaObject not created by
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
bool ignoreUnknownSignals;
|
bool ignoreUnknownSignals;
|
||||||
bool componentcomplete;
|
bool componentcomplete;
|
||||||
|
|
||||||
QQmlRefPointer<QQmlCompiledData> cdata;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
||||||
QList<const QV4::CompiledData::Binding *> bindings;
|
QList<const QV4::CompiledData::Binding *> bindings;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -258,11 +258,11 @@ void QQmlConnectionsParser::verifyBindings(const QV4::CompiledData::Unit *qmlUni
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlConnectionsParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
|
void QQmlConnectionsParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
|
||||||
{
|
{
|
||||||
QQmlConnectionsPrivate *p =
|
QQmlConnectionsPrivate *p =
|
||||||
static_cast<QQmlConnectionsPrivate *>(QObjectPrivate::get(object));
|
static_cast<QQmlConnectionsPrivate *>(QObjectPrivate::get(object));
|
||||||
p->cdata = cdata;
|
p->compilationUnit = compilationUnit;
|
||||||
p->bindings = bindings;
|
p->bindings = bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -278,7 +278,7 @@ void QQmlConnections::connectSignals()
|
||||||
QQmlData *ddata = QQmlData::get(this);
|
QQmlData *ddata = QQmlData::get(this);
|
||||||
QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0;
|
QQmlContextData *ctxtdata = ddata ? ddata->outerContext : 0;
|
||||||
|
|
||||||
const QV4::CompiledData::Unit *qmlUnit = d->cdata->compilationUnit->data;
|
const QV4::CompiledData::Unit *qmlUnit = d->compilationUnit->data;
|
||||||
foreach (const QV4::CompiledData::Binding *binding, d->bindings) {
|
foreach (const QV4::CompiledData::Binding *binding, d->bindings) {
|
||||||
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
|
Q_ASSERT(binding->type == QV4::CompiledData::Binding::Type_Script);
|
||||||
QString propName = qmlUnit->stringAt(binding->propertyNameIndex);
|
QString propName = qmlUnit->stringAt(binding->propertyNameIndex);
|
||||||
|
@ -291,7 +291,7 @@ void QQmlConnections::connectSignals()
|
||||||
|
|
||||||
QQmlBoundSignalExpression *expression = ctxtdata ?
|
QQmlBoundSignalExpression *expression = ctxtdata ?
|
||||||
new QQmlBoundSignalExpression(target, signalIndex,
|
new QQmlBoundSignalExpression(target, signalIndex,
|
||||||
ctxtdata, this, d->cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
|
ctxtdata, this, d->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]) : 0;
|
||||||
signal->takeExpression(expression);
|
signal->takeExpression(expression);
|
||||||
d->boundsignals += signal;
|
d->boundsignals += signal;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -99,7 +99,7 @@ class QQmlConnectionsParser : public QQmlCustomParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
|
virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
|
||||||
virtual void applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings);
|
virtual void applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2401,7 +2401,7 @@ bool QQmlListModelParser::verifyProperty(const QV4::CompiledData::Unit *qmlUnit,
|
||||||
listElementTypeName = objName; // cache right name for next time
|
listElementTypeName = objName; // cache right name for next time
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qmlUnit->stringAt(target->idIndex).isEmpty()) {
|
if (!qmlUnit->stringAt(target->idNameIndex).isEmpty()) {
|
||||||
error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
|
error(target->locationOfIdProperty, QQmlListModel::tr("ListElement: cannot use reserved \"id\" property"));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2508,13 +2508,13 @@ void QQmlListModelParser::verifyBindings(const QV4::CompiledData::Unit *qmlUnit,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQmlListModelParser::applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
|
void QQmlListModelParser::applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
|
||||||
{
|
{
|
||||||
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
|
QQmlListModel *rv = static_cast<QQmlListModel *>(obj);
|
||||||
|
|
||||||
rv->m_engine = QV8Engine::getV4(qmlEngine(rv));
|
rv->m_engine = QV8Engine::getV4(qmlEngine(rv));
|
||||||
|
|
||||||
const QV4::CompiledData::Unit *qmlUnit = cdata->compilationUnit->data;
|
const QV4::CompiledData::Unit *qmlUnit = compilationUnit->data;
|
||||||
|
|
||||||
bool setRoles = false;
|
bool setRoles = false;
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ public:
|
||||||
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
|
QQmlListModelParser() : QQmlCustomParser(QQmlCustomParser::AcceptsSignalHandlers) {}
|
||||||
|
|
||||||
void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
|
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;
|
void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
|
bool verifyProperty(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
|
||||||
|
|
|
@ -70,7 +70,7 @@ void QQmlProfilerClient::sendRecordingStatus(bool record, int engineId, quint32
|
||||||
Q_D(const QQmlProfilerClient);
|
Q_D(const QQmlProfilerClient);
|
||||||
|
|
||||||
QPacket stream(d->connection->currentDataStreamVersion());
|
QPacket stream(d->connection->currentDataStreamVersion());
|
||||||
stream << record << engineId << d->features << flushInterval;
|
stream << record << engineId << d->features << flushInterval << true;
|
||||||
sendMessage(stream.data());
|
sendMessage(stream.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ inline QQmlProfilerDefinitions::ProfileFeature featureFromRangeType(
|
||||||
|
|
||||||
void QQmlProfilerClient::messageReceived(const QByteArray &data)
|
void QQmlProfilerClient::messageReceived(const QByteArray &data)
|
||||||
{
|
{
|
||||||
Q_D(const QQmlProfilerClient);
|
Q_D(QQmlProfilerClient);
|
||||||
|
|
||||||
QPacket stream(d->connection->currentDataStreamVersion(), data);
|
QPacket stream(d->connection->currentDataStreamVersion(), data);
|
||||||
|
|
||||||
|
@ -333,12 +333,25 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
|
||||||
!(d->features & one << featureFromRangeType(rangeType)))
|
!(d->features & one << featureFromRangeType(rangeType)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
qint64 typeId = 0;
|
||||||
if (messageType == QQmlProfilerDefinitions::RangeStart) {
|
if (messageType == QQmlProfilerDefinitions::RangeStart) {
|
||||||
rangeStart(rangeType, time);
|
rangeStart(rangeType, time);
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> typeId;
|
||||||
|
auto i = d->types.constFind(typeId);
|
||||||
|
if (i != d->types.constEnd()) {
|
||||||
|
rangeLocation(rangeType, time, i->location);
|
||||||
|
rangeData(rangeType, time, i->name);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (messageType == QQmlProfilerDefinitions::RangeData) {
|
} else if (messageType == QQmlProfilerDefinitions::RangeData) {
|
||||||
QString data;
|
QString data;
|
||||||
stream >> data;
|
stream >> data;
|
||||||
rangeData(rangeType, time, data);
|
rangeData(rangeType, time, data);
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> typeId;
|
||||||
|
d->types[typeId].name = data;
|
||||||
|
}
|
||||||
} else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
|
} else if (messageType == QQmlProfilerDefinitions::RangeLocation) {
|
||||||
QQmlEventLocation location;
|
QQmlEventLocation location;
|
||||||
stream >> location.filename >> location.line;
|
stream >> location.filename >> location.line;
|
||||||
|
@ -347,6 +360,10 @@ void QQmlProfilerClient::messageReceived(const QByteArray &data)
|
||||||
stream >> location.column;
|
stream >> location.column;
|
||||||
|
|
||||||
rangeLocation(rangeType, time, location);
|
rangeLocation(rangeType, time, location);
|
||||||
|
if (!stream.atEnd()) {
|
||||||
|
stream >> typeId;
|
||||||
|
d->types[typeId].location = location;
|
||||||
|
}
|
||||||
} else if (messageType == QQmlProfilerDefinitions::RangeEnd) {
|
} else if (messageType == QQmlProfilerDefinitions::RangeEnd) {
|
||||||
rangeEnd(rangeType, time);
|
rangeEnd(rangeType, time);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -56,12 +56,20 @@
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
struct QQmlProfilerRangeType
|
||||||
|
{
|
||||||
|
QQmlEventLocation location;
|
||||||
|
QString name;
|
||||||
|
};
|
||||||
|
|
||||||
class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
|
class QQmlProfilerClientPrivate : public QQmlDebugClientPrivate
|
||||||
{
|
{
|
||||||
Q_DECLARE_PUBLIC(QQmlProfilerClient)
|
Q_DECLARE_PUBLIC(QQmlProfilerClient)
|
||||||
public:
|
public:
|
||||||
QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
|
QQmlProfilerClientPrivate(QQmlDebugConnection *connection);
|
||||||
quint64 features;
|
quint64 features;
|
||||||
|
|
||||||
|
QHash<qint64, QQmlProfilerRangeType> types;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
@ -415,4 +415,26 @@ Item {
|
||||||
\endqml
|
\endqml
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\qmlproperty int QtQuick::WheelEvent::inverted
|
||||||
|
|
||||||
|
Returns whether the delta values delivered with the event are inverted.
|
||||||
|
|
||||||
|
Normally, a vertical wheel will produce a WheelEvent with positive delta
|
||||||
|
values if the top of the wheel is rotating away from the hand operating it.
|
||||||
|
Similarly, a horizontal wheel movement will produce a QWheelEvent with
|
||||||
|
positive delta values if the top of the wheel is moved to the left.
|
||||||
|
|
||||||
|
However, on some platforms this is configurable, so that the same
|
||||||
|
operations described above will produce negative delta values (but with the
|
||||||
|
same magnitude). For instance, in a QML component (such as a tumbler or a
|
||||||
|
slider) where it is appropriate to synchronize the movement or rotation of
|
||||||
|
an item with the direction of the wheel, regardless of the system settings,
|
||||||
|
the wheel event handler can use the inverted property to decide whether to
|
||||||
|
negate the angleDelta or pixelDelta values.
|
||||||
|
|
||||||
|
\note Many platforms provide no such information. On such platforms
|
||||||
|
\l inverted always returns false.
|
||||||
|
*/
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
@ -73,10 +73,22 @@ class QQuickKeyEvent : public QObject
|
||||||
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QQuickKeyEvent(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers, const QString &text=QString(), bool autorep=false, ushort count=1)
|
QQuickKeyEvent()
|
||||||
: event(type, key, modifiers, text, autorep, count) { event.setAccepted(false); }
|
: event(QEvent::None, 0, 0)
|
||||||
QQuickKeyEvent(const QKeyEvent &ke)
|
{}
|
||||||
: event(ke) { event.setAccepted(false); }
|
|
||||||
|
void reset(QEvent::Type type, int key, Qt::KeyboardModifiers modifiers,
|
||||||
|
const QString &text = QString(), bool autorep = false, ushort count = 1)
|
||||||
|
{
|
||||||
|
event = QKeyEvent(type, key, modifiers, text, autorep, count);
|
||||||
|
event.setAccepted(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset(const QKeyEvent &ke)
|
||||||
|
{
|
||||||
|
event = ke;
|
||||||
|
event.setAccepted(false);
|
||||||
|
}
|
||||||
|
|
||||||
int key() const { return event.key(); }
|
int key() const { return event.key(); }
|
||||||
QString text() const { return event.text(); }
|
QString text() const { return event.text(); }
|
||||||
|
@ -109,10 +121,21 @@ class Q_QUICK_PRIVATE_EXPORT QQuickMouseEvent : public QObject
|
||||||
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QQuickMouseEvent(qreal x, qreal y, Qt::MouseButton button, Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers
|
QQuickMouseEvent() {}
|
||||||
, bool isClick=false, bool wasHeld=false)
|
|
||||||
: _x(x), _y(y), _button(button), _buttons(buttons), _modifiers(modifiers)
|
void reset(qreal x, qreal y, Qt::MouseButton button, Qt::MouseButtons buttons,
|
||||||
, _source(Qt::MouseEventNotSynthesized), _wasHeld(wasHeld), _isClick(isClick), _accepted(true) {}
|
Qt::KeyboardModifiers modifiers, bool isClick = false, bool wasHeld = false)
|
||||||
|
{
|
||||||
|
_x = x;
|
||||||
|
_y = y;
|
||||||
|
_button = button;
|
||||||
|
_buttons = buttons;
|
||||||
|
_modifiers = modifiers;
|
||||||
|
_source = Qt::MouseEventNotSynthesized;
|
||||||
|
_wasHeld = wasHeld;
|
||||||
|
_isClick = isClick;
|
||||||
|
_accepted = true;
|
||||||
|
}
|
||||||
|
|
||||||
qreal x() const { return _x; }
|
qreal x() const { return _x; }
|
||||||
qreal y() const { return _y; }
|
qreal y() const { return _y; }
|
||||||
|
@ -139,9 +162,9 @@ private:
|
||||||
Qt::MouseButtons _buttons;
|
Qt::MouseButtons _buttons;
|
||||||
Qt::KeyboardModifiers _modifiers;
|
Qt::KeyboardModifiers _modifiers;
|
||||||
Qt::MouseEventSource _source;
|
Qt::MouseEventSource _source;
|
||||||
bool _wasHeld;
|
bool _wasHeld : 1;
|
||||||
bool _isClick;
|
bool _isClick : 1;
|
||||||
bool _accepted;
|
bool _accepted : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QQuickWheelEvent : public QObject
|
class QQuickWheelEvent : public QObject
|
||||||
|
@ -153,13 +176,24 @@ class QQuickWheelEvent : public QObject
|
||||||
Q_PROPERTY(QPoint pixelDelta READ pixelDelta)
|
Q_PROPERTY(QPoint pixelDelta READ pixelDelta)
|
||||||
Q_PROPERTY(int buttons READ buttons)
|
Q_PROPERTY(int buttons READ buttons)
|
||||||
Q_PROPERTY(int modifiers READ modifiers)
|
Q_PROPERTY(int modifiers READ modifiers)
|
||||||
|
Q_PROPERTY(bool inverted READ inverted)
|
||||||
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
Q_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QQuickWheelEvent(qreal x, qreal y, const QPoint& angleDelta, const QPoint& pixelDelta,
|
QQuickWheelEvent() {}
|
||||||
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers)
|
|
||||||
: _x(x), _y(y), _angleDelta(angleDelta), _pixelDelta(pixelDelta), _buttons(buttons),
|
void reset(qreal x, qreal y, const QPoint &angleDelta, const QPoint &pixelDelta,
|
||||||
_modifiers(modifiers), _accepted(true) {}
|
Qt::MouseButtons buttons, Qt::KeyboardModifiers modifiers, bool inverted)
|
||||||
|
{
|
||||||
|
_x = x;
|
||||||
|
_y = y;
|
||||||
|
_angleDelta = angleDelta;
|
||||||
|
_pixelDelta = pixelDelta;
|
||||||
|
_buttons = buttons;
|
||||||
|
_modifiers = modifiers;
|
||||||
|
_accepted = true;
|
||||||
|
_inverted = inverted;
|
||||||
|
}
|
||||||
|
|
||||||
qreal x() const { return _x; }
|
qreal x() const { return _x; }
|
||||||
qreal y() const { return _y; }
|
qreal y() const { return _y; }
|
||||||
|
@ -167,7 +201,7 @@ public:
|
||||||
QPoint pixelDelta() const { return _pixelDelta; }
|
QPoint pixelDelta() const { return _pixelDelta; }
|
||||||
int buttons() const { return _buttons; }
|
int buttons() const { return _buttons; }
|
||||||
int modifiers() const { return _modifiers; }
|
int modifiers() const { return _modifiers; }
|
||||||
|
bool inverted() const { return _inverted; }
|
||||||
bool isAccepted() { return _accepted; }
|
bool isAccepted() { return _accepted; }
|
||||||
void setAccepted(bool accepted) { _accepted = accepted; }
|
void setAccepted(bool accepted) { _accepted = accepted; }
|
||||||
|
|
||||||
|
@ -178,6 +212,7 @@ private:
|
||||||
QPoint _pixelDelta;
|
QPoint _pixelDelta;
|
||||||
Qt::MouseButtons _buttons;
|
Qt::MouseButtons _buttons;
|
||||||
Qt::KeyboardModifiers _modifiers;
|
Qt::KeyboardModifiers _modifiers;
|
||||||
|
bool _inverted;
|
||||||
bool _accepted;
|
bool _accepted;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1355,7 +1355,8 @@ void QQuickKeysAttached::keyPressed(QKeyEvent *event, bool post)
|
||||||
d->inPress = false;
|
d->inPress = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickKeyEvent ke(*event);
|
QQuickKeyEvent &ke = d->theKeyEvent;
|
||||||
|
ke.reset(*event);
|
||||||
QByteArray keySignal = keyToSignal(event->key());
|
QByteArray keySignal = keyToSignal(event->key());
|
||||||
if (!keySignal.isEmpty()) {
|
if (!keySignal.isEmpty()) {
|
||||||
keySignal += "(QQuickKeyEvent*)";
|
keySignal += "(QQuickKeyEvent*)";
|
||||||
|
@ -1398,7 +1399,8 @@ void QQuickKeysAttached::keyReleased(QKeyEvent *event, bool post)
|
||||||
d->inRelease = false;
|
d->inRelease = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickKeyEvent ke(*event);
|
QQuickKeyEvent &ke = d->theKeyEvent;
|
||||||
|
ke.reset(*event);
|
||||||
emit released(&ke);
|
emit released(&ke);
|
||||||
event->setAccepted(ke.isAccepted());
|
event->setAccepted(ke.isAccepted());
|
||||||
|
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#include "qquickanchors_p.h"
|
#include "qquickanchors_p.h"
|
||||||
#include "qquickanchors_p_p.h"
|
#include "qquickanchors_p_p.h"
|
||||||
#include "qquickitemchangelistener_p.h"
|
#include "qquickitemchangelistener_p.h"
|
||||||
|
#include "qquickevents_p_p.h"
|
||||||
|
|
||||||
#include "qquickwindow_p.h"
|
#include "qquickwindow_p.h"
|
||||||
|
|
||||||
|
@ -777,6 +778,7 @@ public:
|
||||||
QQuickItem *imeItem;
|
QQuickItem *imeItem;
|
||||||
QList<QQuickItem *> targets;
|
QList<QQuickItem *> targets;
|
||||||
QQuickItem *item;
|
QQuickItem *item;
|
||||||
|
QQuickKeyEvent theKeyEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
|
class QQuickKeysAttached : public QObject, public QQuickItemKeyFilter
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "qquickmousearea_p.h"
|
#include "qquickmousearea_p.h"
|
||||||
#include "qquickmousearea_p_p.h"
|
#include "qquickmousearea_p_p.h"
|
||||||
#include "qquickwindow.h"
|
#include "qquickwindow.h"
|
||||||
#include "qquickevents_p_p.h"
|
|
||||||
#include "qquickdrag_p.h"
|
#include "qquickdrag_p.h"
|
||||||
|
|
||||||
#include <private/qqmldata_p.h>
|
#include <private/qqmldata_p.h>
|
||||||
|
@ -761,7 +760,8 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
|
QQuickMouseEvent &me = d->quickMouseEvent;
|
||||||
|
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
|
||||||
me.setSource(event->source());
|
me.setSource(event->source());
|
||||||
emit mouseXChanged(&me);
|
emit mouseXChanged(&me);
|
||||||
me.setPosition(d->lastPos);
|
me.setPosition(d->lastPos);
|
||||||
|
@ -802,7 +802,8 @@ void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
|
||||||
Q_D(QQuickMouseArea);
|
Q_D(QQuickMouseArea);
|
||||||
if (d->enabled) {
|
if (d->enabled) {
|
||||||
d->saveEvent(event);
|
d->saveEvent(event);
|
||||||
QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
|
QQuickMouseEvent &me = d->quickMouseEvent;
|
||||||
|
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, true, false);
|
||||||
me.setSource(event->source());
|
me.setSource(event->source());
|
||||||
me.setAccepted(d->isDoubleClickConnected());
|
me.setAccepted(d->isDoubleClickConnected());
|
||||||
emit this->doubleClicked(&me);
|
emit this->doubleClicked(&me);
|
||||||
|
@ -822,7 +823,8 @@ void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
|
||||||
d->lastPos = event->posF();
|
d->lastPos = event->posF();
|
||||||
d->lastModifiers = event->modifiers();
|
d->lastModifiers = event->modifiers();
|
||||||
setHovered(true);
|
setHovered(true);
|
||||||
QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
|
QQuickMouseEvent &me = d->quickMouseEvent;
|
||||||
|
me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
|
||||||
emit mouseXChanged(&me);
|
emit mouseXChanged(&me);
|
||||||
me.setPosition(d->lastPos);
|
me.setPosition(d->lastPos);
|
||||||
emit mouseYChanged(&me);
|
emit mouseYChanged(&me);
|
||||||
|
@ -835,10 +837,11 @@ void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
|
||||||
Q_D(QQuickMouseArea);
|
Q_D(QQuickMouseArea);
|
||||||
if (!d->enabled && !d->pressed) {
|
if (!d->enabled && !d->pressed) {
|
||||||
QQuickItem::hoverMoveEvent(event);
|
QQuickItem::hoverMoveEvent(event);
|
||||||
} else {
|
} else if (d->lastPos != event->posF()) {
|
||||||
d->lastPos = event->posF();
|
d->lastPos = event->posF();
|
||||||
d->lastModifiers = event->modifiers();
|
d->lastModifiers = event->modifiers();
|
||||||
QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
|
QQuickMouseEvent &me = d->quickMouseEvent;
|
||||||
|
me.reset(d->lastPos.x(), d->lastPos.y(), Qt::NoButton, Qt::NoButton, d->lastModifiers, false, false);
|
||||||
emit mouseXChanged(&me);
|
emit mouseXChanged(&me);
|
||||||
me.setPosition(d->lastPos);
|
me.setPosition(d->lastPos);
|
||||||
emit mouseYChanged(&me);
|
emit mouseYChanged(&me);
|
||||||
|
@ -865,8 +868,9 @@ void QQuickMouseArea::wheelEvent(QWheelEvent *event)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickWheelEvent we(event->posF().x(), event->posF().y(), event->angleDelta(),
|
QQuickWheelEvent &we = d->quickWheelEvent;
|
||||||
event->pixelDelta(), event->buttons(), event->modifiers());
|
we.reset(event->posF().x(), event->posF().y(), event->angleDelta(), event->pixelDelta(),
|
||||||
|
event->buttons(), event->modifiers(), event->inverted());
|
||||||
we.setAccepted(d->isWheelConnected());
|
we.setAccepted(d->isWheelConnected());
|
||||||
emit wheel(&we);
|
emit wheel(&we);
|
||||||
if (!we.isAccepted())
|
if (!we.isAccepted())
|
||||||
|
@ -997,7 +1001,8 @@ void QQuickMouseArea::timerEvent(QTimerEvent *event)
|
||||||
#endif
|
#endif
|
||||||
if (d->pressed && dragged == false && d->hovered == true) {
|
if (d->pressed && dragged == false && d->hovered == true) {
|
||||||
d->longPress = true;
|
d->longPress = true;
|
||||||
QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
|
QQuickMouseEvent &me = d->quickMouseEvent;
|
||||||
|
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, false, d->longPress);
|
||||||
me.setSource(Qt::MouseEventSynthesizedByQt);
|
me.setSource(Qt::MouseEventSynthesizedByQt);
|
||||||
me.setAccepted(d->isPressAndHoldConnected());
|
me.setAccepted(d->isPressAndHoldConnected());
|
||||||
emit pressAndHold(&me);
|
emit pressAndHold(&me);
|
||||||
|
@ -1078,8 +1083,7 @@ void QQuickMouseArea::setHoverEnabled(bool h)
|
||||||
\qmlproperty bool QtQuick::MouseArea::containsMouse
|
\qmlproperty bool QtQuick::MouseArea::containsMouse
|
||||||
This property holds whether the mouse is currently inside the mouse area.
|
This property holds whether the mouse is currently inside the mouse area.
|
||||||
|
|
||||||
\warning This property is not updated if the area moves under the mouse: \e containsMouse will not change.
|
\warning If hoverEnabled is false, containsMouse will only be valid
|
||||||
In addition, if hoverEnabled is false, containsMouse will only be valid
|
|
||||||
when the mouse is pressed while the mouse cursor is inside the MouseArea.
|
when the mouse is pressed while the mouse cursor is inside the MouseArea.
|
||||||
*/
|
*/
|
||||||
bool QQuickMouseArea::hovered() const
|
bool QQuickMouseArea::hovered() const
|
||||||
|
@ -1175,7 +1179,8 @@ bool QQuickMouseArea::setPressed(Qt::MouseButton button, bool p, Qt::MouseEventS
|
||||||
Qt::MouseButtons oldPressed = d->pressed;
|
Qt::MouseButtons oldPressed = d->pressed;
|
||||||
|
|
||||||
if (wasPressed != p) {
|
if (wasPressed != p) {
|
||||||
QQuickMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
|
QQuickMouseEvent &me = d->quickMouseEvent;
|
||||||
|
me.reset(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
|
||||||
me.setSource(source);
|
me.setSource(source);
|
||||||
if (p) {
|
if (p) {
|
||||||
d->pressed |= button;
|
d->pressed |= button;
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "qquickitem_p.h"
|
#include "qquickitem_p.h"
|
||||||
|
#include "qquickevents_p_p.h"
|
||||||
|
|
||||||
#include <QtGui/qevent.h>
|
#include <QtGui/qevent.h>
|
||||||
#include <QtCore/qbasictimer.h>
|
#include <QtCore/qbasictimer.h>
|
||||||
|
@ -107,6 +108,8 @@ public:
|
||||||
#ifndef QT_NO_CURSOR
|
#ifndef QT_NO_CURSOR
|
||||||
QCursor *cursor;
|
QCursor *cursor;
|
||||||
#endif
|
#endif
|
||||||
|
QQuickMouseEvent quickMouseEvent;
|
||||||
|
QQuickWheelEvent quickWheelEvent;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
|
@ -456,7 +456,7 @@ void QQuickOpenGLShaderEffectMaterial::cleanupMaterialCache()
|
||||||
{
|
{
|
||||||
QQuickOpenGLShaderEffectMaterialCache *cache = QQuickOpenGLShaderEffectMaterialCache::get(false);
|
QQuickOpenGLShaderEffectMaterialCache *cache = QQuickOpenGLShaderEffectMaterialCache::get(false);
|
||||||
if (cache) {
|
if (cache) {
|
||||||
qDeleteAll(cache->cache.values());
|
qDeleteAll(cache->cache);
|
||||||
delete cache;
|
delete cache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -254,7 +254,7 @@ void QQuickRenderControl::polishItems()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
|
QQuickWindowPrivate *cd = QQuickWindowPrivate::get(d->window);
|
||||||
cd->flushDelayedTouchEvent();
|
cd->flushFrameSynchronousEvents();
|
||||||
if (!d->window)
|
if (!d->window)
|
||||||
return;
|
return;
|
||||||
cd->polishItems();
|
cd->polishItems();
|
||||||
|
|
|
@ -2028,7 +2028,7 @@ void QQuickWindowPrivate::deliverTouchEvent(QTouchEvent *event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQuickWindowPrivate::flushDelayedTouchEvent()
|
void QQuickWindowPrivate::flushFrameSynchronousEvents()
|
||||||
{
|
{
|
||||||
if (delayedTouch) {
|
if (delayedTouch) {
|
||||||
deliverDelayedTouchEvent();
|
deliverDelayedTouchEvent();
|
||||||
|
@ -2039,6 +2039,17 @@ void QQuickWindowPrivate::flushDelayedTouchEvent()
|
||||||
if (ut && ut->hasStartAnimationPending())
|
if (ut && ut->hasStartAnimationPending())
|
||||||
ut->startAnimations();
|
ut->startAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Once per frame, send a synthetic hover, in case items have changed position.
|
||||||
|
// For instance, during animation (including the case of a ListView
|
||||||
|
// whose delegates contain MouseAreas), a MouseArea needs to know
|
||||||
|
// whether it has moved into a position where it is now under the cursor.
|
||||||
|
if (!mouseGrabberItem && !lastMousePosition.isNull()) {
|
||||||
|
bool accepted = false;
|
||||||
|
bool delivered = deliverHoverEvent(contentItem, lastMousePosition, lastMousePosition, QGuiApplication::keyboardModifiers(), accepted);
|
||||||
|
if (!delivered)
|
||||||
|
clearHover(); // take care of any exits
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQuickWindowPrivate::reallyDeliverTouchEvent(QTouchEvent *event)
|
void QQuickWindowPrivate::reallyDeliverTouchEvent(QTouchEvent *event)
|
||||||
|
|
|
@ -160,7 +160,7 @@ public:
|
||||||
void reallyDeliverTouchEvent(QTouchEvent *);
|
void reallyDeliverTouchEvent(QTouchEvent *);
|
||||||
bool deliverTouchCancelEvent(QTouchEvent *);
|
bool deliverTouchCancelEvent(QTouchEvent *);
|
||||||
void deliverDelayedTouchEvent();
|
void deliverDelayedTouchEvent();
|
||||||
void flushDelayedTouchEvent();
|
void flushFrameSynchronousEvents();
|
||||||
bool deliverHoverEvent(QQuickItem *, const QPointF &scenePos, const QPointF &lastScenePos, Qt::KeyboardModifiers modifiers, bool &accepted);
|
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);
|
bool deliverMatchingPointsToItem(QQuickItem *item, QTouchEvent *event, QSet<int> *acceptedNewPoints, const QSet<int> &matchingNewPoints, const QList<QTouchEvent::TouchPoint> &matchingPoints, QSet<QQuickItem*> *filtered);
|
||||||
static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
|
static QTouchEvent *touchEventForItem(QQuickItem *target, const QTouchEvent &originalEvent, bool alwaysCheckBounds = false);
|
||||||
|
|
|
@ -126,7 +126,7 @@ void QSGSoftwareRenderLoop::renderWindow(QQuickWindow *window)
|
||||||
data.updatePending = false;
|
data.updatePending = false;
|
||||||
|
|
||||||
if (!data.grabOnly) {
|
if (!data.grabOnly) {
|
||||||
cd->flushDelayedTouchEvent();
|
cd->flushFrameSynchronousEvents();
|
||||||
// Event delivery/processing triggered the window to be deleted or stop rendering.
|
// Event delivery/processing triggered the window to be deleted or stop rendering.
|
||||||
if (!m_windows.contains(window))
|
if (!m_windows.contains(window))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -846,7 +846,7 @@ Renderer::~Renderer()
|
||||||
for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this);
|
for (int i=0; i<m_batchPool.size(); ++i) qsg_wipeBatch(m_batchPool.at(i), this);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (Node *n, m_nodes.values())
|
for (Node *n : qAsConst(m_nodes))
|
||||||
m_nodeAllocator.release(n);
|
m_nodeAllocator.release(n);
|
||||||
|
|
||||||
// Remaining elements...
|
// Remaining elements...
|
||||||
|
|
|
@ -382,7 +382,7 @@ void QSGGuiThreadRenderLoop::renderWindow(QQuickWindow *window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!data.grabOnly) {
|
if (!data.grabOnly) {
|
||||||
cd->flushDelayedTouchEvent();
|
cd->flushFrameSynchronousEvents();
|
||||||
// Event delivery/processing triggered the window to be deleted or stop rendering.
|
// Event delivery/processing triggered the window to be deleted or stop rendering.
|
||||||
if (!m_windows.contains(window))
|
if (!m_windows.contains(window))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1142,7 +1142,7 @@ void QSGThreadedRenderLoop::polishAndSync(Window *w, bool inExpose)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush pending touch events.
|
// Flush pending touch events.
|
||||||
QQuickWindowPrivate::get(window)->flushDelayedTouchEvent();
|
QQuickWindowPrivate::get(window)->flushFrameSynchronousEvents();
|
||||||
// The delivery of the event might have caused the window to stop rendering
|
// The delivery of the event might have caused the window to stop rendering
|
||||||
w = windowFor(m_windows, window);
|
w = windowFor(m_windows, window);
|
||||||
if (!w || !w->thread || !w->thread->window) {
|
if (!w || !w->thread || !w->thread->window) {
|
||||||
|
|
|
@ -445,7 +445,7 @@ void QSGWindowsRenderLoop::renderWindow(QQuickWindow *window)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d->flushDelayedTouchEvent();
|
d->flushFrameSynchronousEvents();
|
||||||
// Event delivery or processing has caused the window to stop rendering.
|
// Event delivery or processing has caused the window to stop rendering.
|
||||||
if (!windowData(window))
|
if (!windowData(window))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -922,15 +922,13 @@ QQuickPixmapStore::~QQuickPixmapStore()
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
int leakedPixmaps = 0;
|
int leakedPixmaps = 0;
|
||||||
#endif
|
#endif
|
||||||
QList<QQuickPixmapData*> cachedData = m_cache.values();
|
|
||||||
|
|
||||||
// Prevent unreferencePixmap() from assuming it needs to kick
|
// Prevent unreferencePixmap() from assuming it needs to kick
|
||||||
// off the cache expiry timer, as we're shrinking the cache
|
// off the cache expiry timer, as we're shrinking the cache
|
||||||
// manually below after releasing all the pixmaps.
|
// manually below after releasing all the pixmaps.
|
||||||
m_timerId = -2;
|
m_timerId = -2;
|
||||||
|
|
||||||
// unreference all (leaked) pixmaps
|
// unreference all (leaked) pixmaps
|
||||||
foreach (QQuickPixmapData* pixmap, cachedData) {
|
for (auto *pixmap : qAsConst(m_cache)) {
|
||||||
int currRefCount = pixmap->refCount;
|
int currRefCount = pixmap->refCount;
|
||||||
if (currRefCount) {
|
if (currRefCount) {
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
|
|
|
@ -110,8 +110,9 @@ void QQuickProfiler::stopProfilingImpl()
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQuickProfiler::reportDataImpl()
|
void QQuickProfiler::reportDataImpl(bool trackLocations)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(trackLocations);
|
||||||
QMutexLocker lock(&m_dataMutex);
|
QMutexLocker lock(&m_dataMutex);
|
||||||
emit dataReady(m_data);
|
emit dataReady(m_data);
|
||||||
m_data.clear();
|
m_data.clear();
|
||||||
|
|
|
@ -353,7 +353,7 @@ signals:
|
||||||
protected slots:
|
protected slots:
|
||||||
void startProfilingImpl(quint64 features);
|
void startProfilingImpl(quint64 features);
|
||||||
void stopProfilingImpl();
|
void stopProfilingImpl();
|
||||||
void reportDataImpl();
|
void reportDataImpl(bool trackLocations);
|
||||||
void setTimer(const QElapsedTimer &t);
|
void setTimer(const QElapsedTimer &t);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,7 @@ public:
|
||||||
|
|
||||||
QPointer<QObject> object;
|
QPointer<QObject> object;
|
||||||
QList<const QV4::CompiledData::Binding *> bindings;
|
QList<const QV4::CompiledData::Binding *> bindings;
|
||||||
QQmlRefPointer<QQmlCompiledData> cdata;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
||||||
|
|
||||||
bool decoded : 1;
|
bool decoded : 1;
|
||||||
bool restore : 1;
|
bool restore : 1;
|
||||||
|
@ -258,7 +258,7 @@ void QQuickPropertyChangesPrivate::decode()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (const QV4::CompiledData::Binding *binding, bindings)
|
foreach (const QV4::CompiledData::Binding *binding, bindings)
|
||||||
decodeBinding(QString(), cdata->compilationUnit->data, binding);
|
decodeBinding(QString(), compilationUnit->data, binding);
|
||||||
|
|
||||||
bindings.clear();
|
bindings.clear();
|
||||||
|
|
||||||
|
@ -288,7 +288,7 @@ void QQuickPropertyChangesPrivate::decodeBinding(const QString &propertyPrefix,
|
||||||
QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
|
QQuickReplaceSignalHandler *handler = new QQuickReplaceSignalHandler;
|
||||||
handler->property = prop;
|
handler->property = prop;
|
||||||
handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(),
|
handler->expression.take(new QQmlBoundSignalExpression(object, QQmlPropertyPrivate::get(prop)->signalIndex(),
|
||||||
QQmlContextData::get(qmlContext(q)), object, cdata->compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]));
|
QQmlContextData::get(qmlContext(q)), object, compilationUnit->runtimeFunctions[binding->value.compiledScriptIndex]));
|
||||||
signalReplacements << handler;
|
signalReplacements << handler;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -338,12 +338,12 @@ void QQuickPropertyChangesParser::verifyBindings(const QV4::CompiledData::Unit *
|
||||||
verifyList(qmlUnit, props.at(ii));
|
verifyList(qmlUnit, props.at(ii));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QQuickPropertyChangesParser::applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
|
void QQuickPropertyChangesParser::applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
|
||||||
{
|
{
|
||||||
QQuickPropertyChangesPrivate *p =
|
QQuickPropertyChangesPrivate *p =
|
||||||
static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj));
|
static_cast<QQuickPropertyChangesPrivate *>(QObjectPrivate::get(obj));
|
||||||
p->bindings = bindings;
|
p->bindings = bindings;
|
||||||
p->cdata = cdata;
|
p->compilationUnit = compilationUnit;
|
||||||
p->decoded = false;
|
p->decoded = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ QQuickPropertyChanges::ActionList QQuickPropertyChanges::actions()
|
||||||
QQmlBinding *newBinding = 0;
|
QQmlBinding *newBinding = 0;
|
||||||
if (e.id != QQmlBinding::Invalid) {
|
if (e.id != QQmlBinding::Invalid) {
|
||||||
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
|
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
|
||||||
QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->cdata->compilationUnit->runtimeFunctions[e.id]));
|
QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, object(), d->compilationUnit->runtimeFunctions[e.id]));
|
||||||
newBinding = new QQmlBinding(function, object(), context);
|
newBinding = new QQmlBinding(function, object(), context);
|
||||||
}
|
}
|
||||||
// QQmlBinding *newBinding = e.id != QQmlBinding::Invalid ? QQmlBinding::createBinding(e.id, object(), qmlContext(this)) : 0;
|
// QQmlBinding *newBinding = e.id != QQmlBinding::Invalid ? QQmlBinding::createBinding(e.id, object(), qmlContext(this)) : 0;
|
||||||
|
|
|
@ -104,7 +104,7 @@ public:
|
||||||
void verifyList(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
|
void verifyList(const QV4::CompiledData::Unit *qmlUnit, const QV4::CompiledData::Binding *binding);
|
||||||
|
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
|
virtual void verifyBindings(const QV4::CompiledData::Unit *qmlUnit, const QList<const QV4::CompiledData::Binding *> &props);
|
||||||
virtual void applyBindings(QObject *obj, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings);
|
virtual void applyBindings(QObject *obj, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -392,7 +392,7 @@ QQuickSmoothedAnimationPrivate::~QQuickSmoothedAnimationPrivate()
|
||||||
|
|
||||||
void QQuickSmoothedAnimationPrivate::updateRunningAnimations()
|
void QQuickSmoothedAnimationPrivate::updateRunningAnimations()
|
||||||
{
|
{
|
||||||
foreach(QSmoothedAnimation* ease, activeAnimations.values()){
|
for (QSmoothedAnimation *ease : qAsConst(activeAnimations)) {
|
||||||
ease->maximumEasingTime = anim->maximumEasingTime;
|
ease->maximumEasingTime = anim->maximumEasingTime;
|
||||||
ease->reversingMode = anim->reversingMode;
|
ease->reversingMode = anim->reversingMode;
|
||||||
ease->velocity = anim->velocity;
|
ease->velocity = anim->velocity;
|
||||||
|
@ -444,7 +444,8 @@ QAbstractAnimationJob* QQuickSmoothedAnimation::transition(QQuickStateActions &a
|
||||||
anims.insert(ease);
|
anims.insert(ease);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (QSmoothedAnimation *ease, d->activeAnimations.values()){
|
const auto copy = d->activeAnimations;
|
||||||
|
for (QSmoothedAnimation *ease : copy) {
|
||||||
if (!anims.contains(ease)) {
|
if (!anims.contains(ease)) {
|
||||||
ease->clearTemplate();
|
ease->clearTemplate();
|
||||||
d->activeAnimations.remove(ease->target);
|
d->activeAnimations.remove(ease->target);
|
||||||
|
|
|
@ -585,7 +585,8 @@ QAbstractAnimationJob* QQuickSpringAnimation::transition(QQuickStateActions &act
|
||||||
animation->restart();
|
animation->restart();
|
||||||
anims.insert(animation);
|
anims.insert(animation);
|
||||||
}
|
}
|
||||||
foreach (QSpringAnimation *anim, d->activeAnimations.values()){
|
const auto copy = d->activeAnimations;
|
||||||
|
for (QSpringAnimation *anim : copy) {
|
||||||
if (!anims.contains(anim)) {
|
if (!anims.contains(anim)) {
|
||||||
anim->clearTemplate();
|
anim->clearTemplate();
|
||||||
d->activeAnimations.remove(anim->target);
|
d->activeAnimations.remove(anim->target);
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import QtQml 2.0
|
||||||
|
Component {
|
||||||
|
QtObject {
|
||||||
|
id: blah
|
||||||
|
}
|
||||||
|
}
|
|
@ -110,11 +110,11 @@ QVariant myCustomVariantTypeConverter(const QString &data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CustomBindingParser::applyBindings(QObject *object, QQmlCompiledData *cdata, const QList<const QV4::CompiledData::Binding *> &bindings)
|
void CustomBindingParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *compilationUnit, const QList<const QV4::CompiledData::Binding *> &bindings)
|
||||||
{
|
{
|
||||||
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
|
CustomBinding *customBinding = qobject_cast<CustomBinding*>(object);
|
||||||
Q_ASSERT(customBinding);
|
Q_ASSERT(customBinding);
|
||||||
customBinding->cdata = cdata;
|
customBinding->compilationUnit = compilationUnit;
|
||||||
customBinding->bindings = bindings;
|
customBinding->bindings = bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,14 +123,14 @@ void CustomBinding::componentComplete()
|
||||||
Q_ASSERT(m_target);
|
Q_ASSERT(m_target);
|
||||||
|
|
||||||
foreach (const QV4::CompiledData::Binding *binding, bindings) {
|
foreach (const QV4::CompiledData::Binding *binding, bindings) {
|
||||||
QString name = cdata->compilationUnit->data->stringAt(binding->propertyNameIndex);
|
QString name = compilationUnit->data->stringAt(binding->propertyNameIndex);
|
||||||
|
|
||||||
int bindingId = binding->value.compiledScriptIndex;
|
int bindingId = binding->value.compiledScriptIndex;
|
||||||
|
|
||||||
QQmlContextData *context = QQmlContextData::get(qmlContext(this));
|
QQmlContextData *context = QQmlContextData::get(qmlContext(this));
|
||||||
|
|
||||||
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
|
QV4::Scope scope(QQmlEnginePrivate::getV4Engine(qmlEngine(this)));
|
||||||
QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, cdata->compilationUnit->runtimeFunctions[bindingId]));
|
QV4::ScopedValue function(scope, QV4::FunctionObject::createQmlFunction(context, m_target, compilationUnit->runtimeFunctions[bindingId]));
|
||||||
QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context);
|
QQmlBinding *qmlBinding = new QQmlBinding(function, m_target, context);
|
||||||
|
|
||||||
QQmlProperty property(m_target, name, qmlContext(this));
|
QQmlProperty property(m_target, name, qmlContext(this));
|
||||||
|
@ -169,7 +169,7 @@ void EnumSupportingCustomParser::verifyBindings(const QV4::CompiledData::Unit *q
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SimpleObjectCustomParser::applyBindings(QObject *object, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &bindings)
|
void SimpleObjectCustomParser::applyBindings(QObject *object, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &bindings)
|
||||||
{
|
{
|
||||||
SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
|
SimpleObjectWithCustomParser *o = qobject_cast<SimpleObjectWithCustomParser*>(object);
|
||||||
Q_ASSERT(o);
|
Q_ASSERT(o);
|
||||||
|
|
|
@ -733,14 +733,14 @@ class MyCustomParserTypeParser : public QQmlCustomParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
||||||
virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
|
virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class EnumSupportingCustomParser : public QQmlCustomParser
|
class EnumSupportingCustomParser : public QQmlCustomParser
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &);
|
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &);
|
||||||
virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &) {}
|
virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyParserStatus : public QObject, public QQmlParserStatus
|
class MyParserStatus : public QObject, public QQmlParserStatus
|
||||||
|
@ -1170,7 +1170,7 @@ public:
|
||||||
void setTarget(QObject *newTarget) { m_target = newTarget; }
|
void setTarget(QObject *newTarget) { m_target = newTarget; }
|
||||||
|
|
||||||
QPointer<QObject> m_target;
|
QPointer<QObject> m_target;
|
||||||
QQmlRefPointer<QQmlCompiledData> cdata;
|
QQmlRefPointer<QV4::CompiledData::CompilationUnit> compilationUnit;
|
||||||
QList<const QV4::CompiledData::Binding*> bindings;
|
QList<const QV4::CompiledData::Binding*> bindings;
|
||||||
QByteArray m_bindingData;
|
QByteArray m_bindingData;
|
||||||
};
|
};
|
||||||
|
@ -1178,7 +1178,7 @@ public:
|
||||||
class CustomBindingParser : public QQmlCustomParser
|
class CustomBindingParser : public QQmlCustomParser
|
||||||
{
|
{
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
||||||
virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
|
virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SimpleObjectWithCustomParser : public QObject
|
class SimpleObjectWithCustomParser : public QObject
|
||||||
|
@ -1224,7 +1224,7 @@ private:
|
||||||
class SimpleObjectCustomParser : public QQmlCustomParser
|
class SimpleObjectCustomParser : public QQmlCustomParser
|
||||||
{
|
{
|
||||||
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
virtual void verifyBindings(const QV4::CompiledData::Unit *, const QList<const QV4::CompiledData::Binding *> &) {}
|
||||||
virtual void applyBindings(QObject *, QQmlCompiledData *, const QList<const QV4::CompiledData::Binding *> &);
|
virtual void applyBindings(QObject *, QV4::CompiledData::CompilationUnit *, const QList<const QV4::CompiledData::Binding *> &);
|
||||||
};
|
};
|
||||||
|
|
||||||
class RootObjectInCreationTester : public QObject
|
class RootObjectInCreationTester : public QObject
|
||||||
|
|
|
@ -108,6 +108,7 @@ private slots:
|
||||||
void bindTypeToJSValue();
|
void bindTypeToJSValue();
|
||||||
void customParserTypes();
|
void customParserTypes();
|
||||||
void rootAsQmlComponent();
|
void rootAsQmlComponent();
|
||||||
|
void rootItemIsComponent();
|
||||||
void inlineQmlComponents();
|
void inlineQmlComponents();
|
||||||
void idProperty();
|
void idProperty();
|
||||||
void autoNotifyConnection();
|
void autoNotifyConnection();
|
||||||
|
@ -1195,6 +1196,19 @@ void tst_qqmllanguage::rootAsQmlComponent()
|
||||||
QCOMPARE(object->getChildren()->count(), 2);
|
QCOMPARE(object->getChildren()->count(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_qqmllanguage::rootItemIsComponent()
|
||||||
|
{
|
||||||
|
QQmlComponent component(&engine, testFileUrl("rootItemIsComponent.qml"));
|
||||||
|
VERIFY_ERRORS(0);
|
||||||
|
QScopedPointer<QObject> root(component.create());
|
||||||
|
QVERIFY(qobject_cast<QQmlComponent*>(root.data()));
|
||||||
|
QScopedPointer<QObject> other(qobject_cast<QQmlComponent*>(root.data())->create());
|
||||||
|
QVERIFY(!other.isNull());
|
||||||
|
QQmlContext *context = qmlContext(other.data());
|
||||||
|
QVERIFY(context);
|
||||||
|
QCOMPARE(context->nameForObject(other.data()), QStringLiteral("blah"));
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that components can be specified inline
|
// Tests that components can be specified inline
|
||||||
void tst_qqmllanguage::inlineQmlComponents()
|
void tst_qqmllanguage::inlineQmlComponents()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 9741ac4655808ac46c127e3d1d8ba3d27ada618e
|
Subproject commit 0b5af3dcec772bb06b4d685a20b2859cda59d189
|
Loading…
Reference in New Issue