aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/jsruntime/qv4qmlcontext.cpp
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2022-07-22 10:40:51 +0200
committerUlf Hermann <ulf.hermann@qt.io>2022-07-25 12:26:07 +0200
commitaa553318d40a1ca586b11e3209529bd1911cd427 (patch)
tree49e94be7e071f4578c317f76818b5020927b6c61 /src/qml/jsruntime/qv4qmlcontext.cpp
parent7f6960efded7e57864066cf831bb0e8446c717f4 (diff)
Fix precedence between JS and QML scopes
In case of a JS context, we need to do the JS lookup early in order to override imports with locally defined functions. [ChangeLog][QtQml][Important Behavior Changes] The precedence between imports and locally defined functions and variables in JavaScript files has been fixed. If you import a JavaScript file from a QML file, the functions inside the JavaScript file should obviously override anything imported from the QML context. This behavior has been restored. Pick-to: 6.4 Task-number: QTBUG-91687 Change-Id: I119e3109f96ffad7455daaf1a5f17bad31fa8e33 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io>
Diffstat (limited to 'src/qml/jsruntime/qv4qmlcontext.cpp')
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp46
1 files changed, 28 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();
}