1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qqmlenginecontrolservice.h"
5#include <private/qqmldebugconnector_p.h>
6#include <private/qversionedpacket_p.h>
7#include <QJSEngine>
8
9QT_BEGIN_NAMESPACE
10
11using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
12
13QQmlEngineControlServiceImpl::QQmlEngineControlServiceImpl(QObject *parent) :
14 QQmlEngineControlService(1, parent)
15{
16 blockingMode = QQmlDebugConnector::instance()->blockingMode();
17}
18
19void QQmlEngineControlServiceImpl::messageReceived(const QByteArray &message)
20{
21 QMutexLocker lock(&dataMutex);
22 QQmlDebugPacket d(message);
23 qint32 command;
24 qint32 engineId;
25 d >> command >> engineId;
26 QJSEngine *engine = qobject_cast<QJSEngine *>(object: objectForId(id: engineId));
27 if (command == StartWaitingEngine && startingEngines.contains(t: engine)) {
28 startingEngines.removeOne(t: engine);
29 emit attachedToEngine(engine);
30 } else if (command == StopWaitingEngine && stoppingEngines.contains(t: engine)) {
31 stoppingEngines.removeOne(t: engine);
32 emit detachedFromEngine(engine);
33 }
34}
35
36void QQmlEngineControlServiceImpl::engineAboutToBeAdded(QJSEngine *engine)
37{
38 QMutexLocker lock(&dataMutex);
39 if (blockingMode && state() == Enabled) {
40 Q_ASSERT(!stoppingEngines.contains(engine));
41 Q_ASSERT(!startingEngines.contains(engine));
42 startingEngines.append(t: engine);
43 sendMessage(type: EngineAboutToBeAdded, engine);
44 } else {
45 emit attachedToEngine(engine);
46 }
47}
48
49void QQmlEngineControlServiceImpl::engineAboutToBeRemoved(QJSEngine *engine)
50{
51 QMutexLocker lock(&dataMutex);
52 if (blockingMode && state() == Enabled) {
53 Q_ASSERT(!stoppingEngines.contains(engine));
54 Q_ASSERT(!startingEngines.contains(engine));
55 stoppingEngines.append(t: engine);
56 sendMessage(type: EngineAboutToBeRemoved, engine);
57 } else {
58 emit detachedFromEngine(engine);
59 }
60}
61
62void QQmlEngineControlServiceImpl::engineAdded(QJSEngine *engine)
63{
64 if (state() == Enabled) {
65 QMutexLocker lock(&dataMutex);
66 Q_ASSERT(!startingEngines.contains(engine));
67 Q_ASSERT(!stoppingEngines.contains(engine));
68 sendMessage(type: EngineAdded, engine);
69 }
70}
71
72void QQmlEngineControlServiceImpl::engineRemoved(QJSEngine *engine)
73{
74 if (state() == Enabled) {
75 QMutexLocker lock(&dataMutex);
76 Q_ASSERT(!startingEngines.contains(engine));
77 Q_ASSERT(!stoppingEngines.contains(engine));
78 sendMessage(type: EngineRemoved, engine);
79 }
80}
81
82void QQmlEngineControlServiceImpl::sendMessage(QQmlEngineControlServiceImpl::MessageType type,
83 QJSEngine *engine)
84{
85 QQmlDebugPacket d;
86 d << static_cast<qint32>(type) << idForObject(engine);
87 emit messageToClient(name: name(), message: d.data());
88}
89
90void QQmlEngineControlServiceImpl::stateChanged(State)
91{
92 // We flush everything for any kind of state change, to avoid complicated timing issues.
93 QMutexLocker lock(&dataMutex);
94 for (QJSEngine *engine : std::as_const(t&: startingEngines))
95 emit attachedToEngine(engine);
96 startingEngines.clear();
97 for (QJSEngine *engine : std::as_const(t&: stoppingEngines))
98 emit detachedFromEngine(engine);
99 stoppingEngines.clear();
100}
101
102QT_END_NAMESPACE
103

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_profiler/qqmlenginecontrolservice.cpp