Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmljslinterpasses.cpp
Go to the documentation of this file.
1// Copyright (C) 2026 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
3// Qt-Security score:significant
4
7
8#include <private/qqmlsa_p.h>
9#include <private/qqmljsscope_p.h>
10
11#include <QtCore/qstring.h>
12
14
16
17using namespace Qt::StringLiterals;
18void registerDefaultPasses(QQmlSA::PassManager *passMan)
19{
20 passMan->registerPropertyPass(std::make_unique<QQmlJSLiteralBindingCheck>(passMan), QString(),
21 QString(), QString());
22
23 QQmlSA::PropertyPassBuilder(passMan)
24 .withOnCall([](QQmlSA::PropertyPass *self, const QQmlSA::Element &, const QString &,
25 const QQmlSA::Element &, QQmlSA::SourceLocation location) {
26 self->emitWarning("Do not use 'eval'", qmlEval, location);
27 })
28 .registerOnBuiltin("GlobalObject", "eval");
29
30 QQmlSA::PropertyPassBuilder(passMan)
31 .withOnRead([](QQmlSA::PropertyPass *self, const QQmlSA::Element &element,
32 const QString &propName, const QQmlSA::Element &readScope_,
33 QQmlSA::SourceLocation location) {
34 const auto &elementScope = QQmlJSScope::scope(element);
35 const auto &owner = QQmlJSScope::ownerOfProperty(elementScope, propName).scope;
36 if (!owner || owner->isComposite() || owner->isValueType())
37 return;
38 const auto &prop = QQmlSA::PropertyPrivate::property(element.property(propName));
39 if (prop.index() != -1 && !prop.isPropertyConstant() && prop.notify().isEmpty()
40 && prop.bindable().isEmpty()) {
41 const QQmlJSScope::ConstPtr &readScope = QQmlJSScope::scope(readScope_);
42 // FIXME: we currently get the closest QML Scope as readScope, instead of
43 // the innermost scope. We try locate it here via source location
44 Q_ASSERT(readScope->scopeType() == QQmlJSScope::ScopeType::QMLScope);
45 for (auto it = readScope->childScopesBegin(); it != readScope->childScopesEnd();
46 ++it) {
47 QQmlJS::SourceLocation childLocation = (*it)->sourceLocation();
48 if (childLocation.offset <= location.offset()
49 && (childLocation.offset + childLocation.length
50 <= location.offset() + location.length())) {
51 if ((*it)->scopeType() != QQmlSA::ScopeType::BindingFunctionScope)
52 return;
53 }
54 }
55 const QString msg =
56 "Reading non-constant and non-notifiable property %1. "_L1
57 "Binding might not update when the property changes."_L1.arg(propName);
58 self->emitWarning(msg, qmlStalePropertyRead, location);
59 }
60 })
61 .registerOn({}, {}, {});
62}
63} // namespace QQmlJSLinterPasses
64QT_END_NAMESPACE
void registerDefaultPasses(QQmlSA::PassManager *passMan)
Combined button and popup list for selecting options.