aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp46
-rw-r--r--tests/auto/qml/qqmllanguage/data/jsFunctionOverridesImport.qml6
-rw-r--r--tests/auto/qml/qqmllanguage/data/overrideImport.js7
-rw-r--r--tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp10
4 files changed, 51 insertions, 18 deletions
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 7145fec618..c069bd854c 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -91,6 +91,18 @@ static OptionalReturnedValue searchContextProperties(
return OptionalReturnedValue(v4->fromVariant(cp->propertyValue(propertyIdx)));
}
+template<typename Lookup>
+bool performLookup(ScopedValue *result, bool *hasProperty, const Lookup &lookup) {
+ bool hasProp = false;
+ *result = lookup(&hasProp);
+ if (hasProp) {
+ if (hasProperty)
+ *hasProperty = hasProp;
+ return true;
+ }
+ return false;
+}
+
ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *resource, PropertyKey id, const Value *receiver, bool *hasProperty, Value *base, Lookup *lookup)
{
if (!id.isString())
@@ -139,17 +151,20 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
ScopedString name(scope, id.asStringOrSymbol());
- const auto performGobalLookUp = [&result, v4, &name, hasProperty]() {
- bool hasProp = false;
- result = v4->globalObject->get(name, &hasProp);
- if (hasProp) {
- if (hasProperty)
- *hasProperty = hasProp;
- return true;
- }
- return false;
+ const auto globalLookup = [v4, &name](bool *hasProp) {
+ return v4->globalObject->get(name, hasProp);
+ };
+
+ const auto jsLookup = [resource, &id, receiver](bool *hasProp) {
+ return Object::virtualGet(resource, id, receiver, hasProp);
};
+ const bool isJSContext = context->isJSContext();
+
+ // Do the generic JS lookup early in case of a JavaScript context.
+ if (isJSContext && performLookup(&result, hasProperty, jsLookup))
+ return result->asReturnedValue();
+
// If the scope object is a QAbstractDynamicMetaObject, then QMetaObject::indexOfProperty
// will call createProperty() on the QADMO and implicitly create the property. While that
// is questionable behavior, there are two use-cases that we support in the light of this:
@@ -170,7 +185,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
if (metaObjectPrivate && metaObjectPrivate->flags & DynamicMetaObject) {
// all bets are off, so don't try to optimize any lookups
lookup = nullptr;
- if (performGobalLookUp())
+ if (performLookup(&result, hasProperty, globalLookup))
return result->asReturnedValue();
}
@@ -318,15 +333,10 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
lookup = nullptr;
}
- // Do the generic JS lookup late.
+ // Do the generic JS lookup late in case of a non-JavaScript context.
// The scope, context, types etc should be able to override it.
- bool hasProp = false;
- result = Object::virtualGet(resource, id, receiver, &hasProp);
- if (hasProp) {
- if (hasProperty)
- *hasProperty = hasProp;
+ if (!isJSContext && performLookup(&result, hasProperty, jsLookup))
return result->asReturnedValue();
- }
// Do a lookup in the global object here to avoid expressionContext->unresolvedNames becoming
// true if we access properties of the global object.
@@ -345,7 +355,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
lookup->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
} else {
- if (performGobalLookUp())
+ if (performLookup(&result, hasProperty, globalLookup))
return result->asReturnedValue();
}
diff --git a/tests/auto/qml/qqmllanguage/data/jsFunctionOverridesImport.qml b/tests/auto/qml/qqmllanguage/data/jsFunctionOverridesImport.qml
new file mode 100644
index 0000000000..2fed087d54
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/jsFunctionOverridesImport.qml
@@ -0,0 +1,6 @@
+import QtQml
+import "overrideImport.js" as Override
+
+QtObject {
+ objectName: Override.override()
+}
diff --git a/tests/auto/qml/qqmllanguage/data/overrideImport.js b/tests/auto/qml/qqmllanguage/data/overrideImport.js
new file mode 100644
index 0000000000..a602d72803
--- /dev/null
+++ b/tests/auto/qml/qqmllanguage/data/overrideImport.js
@@ -0,0 +1,7 @@
+function QtObject() {
+ return "foo";
+}
+
+function override() {
+ return QtObject();
+}
diff --git a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
index 8bed8a9880..c39119dc06 100644
--- a/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
+++ b/tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp
@@ -392,6 +392,7 @@ private slots:
void v4SequenceMethods();
void v4SequenceMethodsWithParams_data();
void v4SequenceMethodsWithParams();
+ void jsFunctionOverridesImport();
private:
QQmlEngine engine;
@@ -7573,6 +7574,15 @@ void tst_qqmllanguage::v4SequenceMethodsWithParams()
QCOMPARE(object->property("v4SequenceLastIndexOf"), object->property("jsArrayLastIndexOf"));
}
+void tst_qqmllanguage::jsFunctionOverridesImport()
+{
+ QQmlEngine engine;
+ QQmlComponent component(&engine, testFileUrl("jsFunctionOverridesImport.qml"));
+ QVERIFY2(component.isReady(), qPrintable(component.errorString()));
+ QScopedPointer<QObject> object(component.create());
+ QCOMPARE(object->objectName(), u"foo"_s);
+}
+
QTEST_MAIN(tst_qqmllanguage)
#include "tst_qqmllanguage.moc"