Don't optimize global lookups if fast QML lookups are disabled

If fast QML lookups are disabled, we generally want to look up by
string. If the name then happens to be a member of the global JavaScript
object, we still don't want to directly access that, as the name could
have been overridden in a deeper context.

Fixes: QTBUG-73750
Change-Id: Id16110969123d91501064ba46bfad4c2a39e4650
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Ulf Hermann 2019-02-13 09:17:10 +01:00
parent 91a71bce9c
commit 01f9c623ed
5 changed files with 43 additions and 2 deletions

View File

@ -622,6 +622,7 @@ struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen
protected:
void beginFunctionBodyHook() override;
bool canAccelerateGlobalLookups() const override { return !_disableAcceleratedLookups; }
Reference fallbackNameLookup(const QString &name) override;
private:

View File

@ -2404,7 +2404,7 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs, co
Reference r = Reference::fromName(this, name);
r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global);
if (!r.global && m_globalNames.contains(name))
if (!r.global && canAccelerateGlobalLookups() && m_globalNames.contains(name))
r.global = true;
return r;
}

View File

@ -561,8 +561,10 @@ protected:
Reference referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name);
// Hook provided to implement QML lookup semantics
// Hooks provided to implement QML lookup semantics
virtual bool canAccelerateGlobalLookups() const { return true; }
virtual Reference fallbackNameLookup(const QString &name);
virtual void beginFunctionBodyHook() {}
void emitReturn(const Reference &expr);

View File

@ -0,0 +1,13 @@
import QtQml 2.12
import test.proxy 1.0
Proxy {
property int testEnum: 0;
id: proxy
property Connections connections: Connections {
target: proxy
onSomeSignal: testEnum = Proxy.EnumValue;
}
Component.onCompleted: someSignal()
}

View File

@ -55,6 +55,7 @@ private slots:
void disabledAtStart();
void clearImplicitTarget();
void onWithoutASignal();
void noAcceleratedGlobalLookup();
private:
QQmlEngine engine;
@ -407,6 +408,30 @@ void tst_qqmlconnections::onWithoutASignal()
QVERIFY(item == nullptr); // should parse error, and not give us an item (or crash).
}
class Proxy : public QObject
{
Q_OBJECT
public:
enum MyEnum { EnumValue = 20, AnotherEnumValue };
Q_ENUM(MyEnum)
signals:
void someSignal();
};
void tst_qqmlconnections::noAcceleratedGlobalLookup()
{
qRegisterMetaType<Proxy::MyEnum>();
qmlRegisterType<Proxy>("test.proxy", 1, 0, "Proxy");
QQmlEngine engine;
QQmlComponent c(&engine, testFileUrl("override-proxy-type.qml"));
QVERIFY(c.isReady());
QScopedPointer<QObject> object(c.create());
const QVariant val = object->property("testEnum");
QCOMPARE(val.type(), QMetaType::Int);
QCOMPARE(val.toInt(), int(Proxy::EnumValue));
}
QTEST_MAIN(tst_qqmlconnections)
#include "tst_qqmlconnections.moc"