diff options
| -rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 46 | ||||
| -rw-r--r-- | tests/auto/qml/qqmllanguage/data/jsFunctionOverridesImport.qml | 6 | ||||
| -rw-r--r-- | tests/auto/qml/qqmllanguage/data/overrideImport.js | 7 | ||||
| -rw-r--r-- | tests/auto/qml/qqmllanguage/tst_qqmllanguage.cpp | 10 |
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" |
