diff options
author | Ulf Hermann <[email protected]> | 2022-07-22 10:40:51 +0200 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2022-07-25 12:26:07 +0200 |
commit | aa553318d40a1ca586b11e3209529bd1911cd427 (patch) | |
tree | 49e94be7e071f4578c317f76818b5020927b6c61 /src/qml/jsruntime/qv4qmlcontext.cpp | |
parent | 7f6960efded7e57864066cf831bb0e8446c717f4 (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 <[email protected]>
Reviewed-by: Andrei Golubev <[email protected]>
Diffstat (limited to 'src/qml/jsruntime/qv4qmlcontext.cpp')
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 46 |
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(); } |