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 "qqmldebug.h"
5#include "qqmldebugconnector_p.h"
6#include "qqmldebugserviceinterfaces_p.h"
7
8#include <private/qqmlengine_p.h>
9#include <private/qv4compileddata_p.h>
10
11#include <atomic>
12#include <cstdio>
13
14QT_REQUIRE_CONFIG(qml_debug);
15
16QT_BEGIN_NAMESPACE
17
18#if __cplusplus >= 202002L
19# define Q_ATOMIC_FLAG_INIT {}
20#else
21# define Q_ATOMIC_FLAG_INIT ATOMIC_FLAG_INIT // deprecated in C++20
22#endif
23
24Q_CONSTINIT static std::atomic_flag s_printedWarning = Q_ATOMIC_FLAG_INIT;
25
26void QQmlDebuggingEnabler::enableDebugging(bool printWarning)
27{
28 if (printWarning && !s_printedWarning.test_and_set(m: std::memory_order_relaxed)) {
29 fprintf(stderr, format: "QML debugging is enabled. Only use this in a safe environment.\n");
30 fflush(stderr); // We really want to print this warning, even if stderr is buffered
31 }
32 QQmlEnginePrivate::qml_debugging_enabled.store(i: true, m: std::memory_order_relaxed);
33}
34
35#if QT_DEPRECATED_SINCE(6, 4)
36QQmlDebuggingEnabler::QQmlDebuggingEnabler(bool printWarning)
37{
38 enableDebugging(printWarning);
39};
40#endif // QT_DEPRECATED_SINCE(6, 4)
41
42/*!
43 * Retrieves the plugin keys of the debugger services provided by default. The debugger services
44 * enable a debug client to use a Qml/JavaScript debugger, in order to set breakpoints, pause
45 * execution, evaluate expressions and similar debugging tasks.
46 * \return List of plugin keys of default debugger services.
47 */
48QStringList QQmlDebuggingEnabler::debuggerServices()
49{
50 return {QV4DebugService::s_key, QQmlEngineDebugService::s_key, QDebugMessageService::s_key};
51}
52
53/*!
54 * Retrieves the plugin keys of the inspector services provided by default. The inspector services
55 * enable a debug client to use a visual inspector tool for Qt Quick.
56 * \return List of plugin keys of default inspector services.
57 */
58QStringList QQmlDebuggingEnabler::inspectorServices()
59{
60 return {QQmlInspectorService::s_key};
61}
62
63/*!
64 * Retrieves the names of the profiler services provided by default. The profiler services enable a
65 * debug client to use a profiler and track the time taken by various QML and JavaScript constructs,
66 * as well as the QtQuick SceneGraph.
67 * \return List of plugin keys of default profiler services.
68 */
69QStringList QQmlDebuggingEnabler::profilerServices()
70{
71 return {QQmlProfilerService::s_key, QQmlEngineControlService::s_key, QDebugMessageService::s_key};
72}
73
74/*!
75 * Retrieves the plugin keys of the debug services designed to be used with a native debugger. The
76 * native debugger will communicate with these services by directly reading and writing the
77 * application's memory.
78 * \return List of plugin keys of debug services designed to be used with a native debugger.
79 */
80QStringList QQmlDebuggingEnabler::nativeDebuggerServices()
81{
82 return {QQmlNativeDebugService::s_key};
83}
84
85/*!
86 * Restricts the services available from the debug connector. The connector will scan plugins in the
87 * "qmltooling" subdirectory of the default plugin path. If this function is not called before the
88 * debug connector is enabled, all services found that way will be available to any client. If this
89 * function is called, only the services with plugin keys given in \a services will be available.
90 *
91 * Use this method to disable debugger and inspector services when profiling to get better
92 * performance and more realistic profiles. The debugger service will put any JavaScript engine it
93 * connects to into interpreted mode, disabling the JIT compiler.
94 *
95 * \sa debuggerServices(), profilerServices(), inspectorServices()
96 */
97void QQmlDebuggingEnabler::setServices(const QStringList &services)
98{
99 QQmlDebugConnector::setServices(services);
100}
101
102/*!
103 * \enum QQmlDebuggingEnabler::StartMode
104 *
105 * Defines the debug connector's start behavior. You can interrupt QML engines starting while a
106 * debug client is connecting, in order to set breakpoints in or profile startup code.
107 *
108 * \value DoNotWaitForClient Run any QML engines as usual while the debug services are connecting.
109 * \value WaitForClient If a QML engine starts while the debug services are connecting,
110 * interrupt it until they are done.
111 */
112
113/*!
114 * Enables debugging for QML engines created after calling this function. The debug connector will
115 * listen on \a port at \a hostName and block the QML engine until it receives a connection if
116 * \a mode is \c WaitForClient. If \a mode is not specified it won't block and if \a hostName is not
117 * specified it will listen on all available interfaces. You can only start one debug connector at a
118 * time. A debug connector may have already been started if the -qmljsdebugger= command line
119 * argument was given. This method returns \c true if a new debug connector was successfully
120 * started, or \c false otherwise.
121 */
122bool QQmlDebuggingEnabler::startTcpDebugServer(int port, StartMode mode, const QString &hostName)
123{
124 QVariantHash configuration;
125 configuration[QLatin1String("portFrom")] = configuration[QLatin1String("portTo")] = port;
126 configuration[QLatin1String("block")] = (mode == WaitForClient);
127 configuration[QLatin1String("hostAddress")] = hostName;
128 return startDebugConnector(pluginName: QLatin1String("QQmlDebugServer"), configuration);
129}
130
131/*!
132 * \since 5.6
133 *
134 * Enables debugging for QML engines created after calling this function. The debug connector will
135 * connect to a debugger waiting on a local socket at the given \a socketFileName and block the QML
136 * engine until the connection is established if \a mode is \c WaitForClient. If \a mode is not
137 * specified it will not block. You can only start one debug connector at a time. A debug connector
138 * may have already been started if the -qmljsdebugger= command line argument was given. This method
139 * returns \c true if a new debug connector was successfully started, or \c false otherwise.
140 */
141bool QQmlDebuggingEnabler::connectToLocalDebugger(const QString &socketFileName, StartMode mode)
142{
143 QVariantHash configuration;
144 configuration[QLatin1String("fileName")] = socketFileName;
145 configuration[QLatin1String("block")] = (mode == WaitForClient);
146 return startDebugConnector(pluginName: QLatin1String("QQmlDebugServer"), configuration);
147}
148
149/*!
150 * \since 5.7
151 *
152 * Enables debugging for QML engines created after calling this function. A debug connector plugin
153 * specified by \a pluginName will be loaded and started using the given \a configuration. Supported
154 * configuration entries and their semantics depend on the plugin being loaded. You can only start
155 * one debug connector at a time. A debug connector may have already been started if the
156 * -qmljsdebugger= command line argument was given. This method returns \c true if a new debug
157 * connector was successfully started, or \c false otherwise.
158 */
159bool QQmlDebuggingEnabler::startDebugConnector(const QString &pluginName,
160 const QVariantHash &configuration)
161{
162 QQmlDebugConnector::setPluginKey(pluginName);
163 QQmlDebugConnector *connector = QQmlDebugConnector::instance();
164 return connector ? connector->open(configuration) : false;
165}
166
167enum { HookCount = 4 };
168
169// Only add to the end, and bump version if you do.
170quintptr Q_QML_EXPORT qtDeclarativeHookData[] = {
171 // Version of this Array. Bump if you add to end.
172 2,
173
174 // Number of entries in this array.
175 HookCount,
176
177 // TypeInformationVersion, an integral value, bumped whenever private
178 // object sizes or member offsets that are used in Qt Creator's
179 // data structure "pretty printing" change.
180 4,
181
182 // Version of the cache data.
183 QV4_DATA_STRUCTURE_VERSION
184};
185
186Q_STATIC_ASSERT(HookCount == sizeof(qtDeclarativeHookData) / sizeof(qtDeclarativeHookData[0]));
187
188QT_END_NAMESPACE
189

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/qml/debugger/qqmldebug.cpp