aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4lookup_p.h7
-rw-r--r--src/qml/jsruntime/qv4qmlcontext.cpp33
-rw-r--r--src/qml/jsruntime/qv4qmlcontext_p.h1
3 files changed, 39 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4lookup_p.h b/src/qml/jsruntime/qv4lookup_p.h
index 68da224273..ee6da21121 100644
--- a/src/qml/jsruntime/qv4lookup_p.h
+++ b/src/qml/jsruntime/qv4lookup_p.h
@@ -143,6 +143,13 @@ struct Lookup {
quintptr unused2;
int objectId;
} qmlContextIdObjectLookup;
+ struct {
+ // Same as protoLookup, as used for global lookups
+ quintptr reserved1;
+ quintptr reserved2;
+ quintptr reserved3;
+ ReturnedValue (*getterTrampoline)(Lookup *l, ExecutionEngine *engine);
+ } qmlContextGlobalLookup;
};
uint nameIndex;
diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp
index 3d9e1cc0f8..e728cfb457 100644
--- a/src/qml/jsruntime/qv4qmlcontext.cpp
+++ b/src/qml/jsruntime/qv4qmlcontext.cpp
@@ -213,6 +213,7 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
}
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(v4->qmlEngine());
+ Lookup * const originalLookup = lookup;
while (context) {
// Search context properties
@@ -295,8 +296,24 @@ ReturnedValue QQmlContextWrapper::getPropertyAndBase(const QQmlContextWrapper *r
// Do a lookup in the global object here to avoid expressionContext->unresolvedNames becoming
// true if we access properties of the global object.
- if (performGobalLookUp())
- return result->asReturnedValue();
+ if (originalLookup) {
+ // Try a lookup in the global object. It's theoretically possible to first find a property
+ // in the global object and then later a context property with the same name is added, but that
+ // never really worked as we used to detect access to global properties at type compile time anyway.
+ lookup = originalLookup;
+ result = lookup->resolveGlobalGetter(v4);
+ if (lookup->globalGetter != Lookup::globalGetterGeneric) {
+ if (hasProperty)
+ *hasProperty = true;
+ lookup->qmlContextGlobalLookup.getterTrampoline = lookup->globalGetter;
+ lookup->qmlContextPropertyGetter = QQmlContextWrapper::lookupInGlobalObject;
+ return result->asReturnedValue();
+ }
+ lookup->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter;
+ } else {
+ if (performGobalLookUp())
+ return result->asReturnedValue();
+ }
expressionContext->unresolvedNames = true;
@@ -449,6 +466,18 @@ ReturnedValue QQmlContextWrapper::lookupIdObject(Lookup *l, ExecutionEngine *eng
return QV4::QObjectWrapper::wrap(engine, context->idValues[objectId]);
}
+ReturnedValue QQmlContextWrapper::lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base)
+{
+ Q_UNUSED(base);
+ ReturnedValue result = l->qmlContextGlobalLookup.getterTrampoline(l, engine);
+ // In the unlikely event of mutation of the global object, update the trampoline.
+ if (l->qmlContextPropertyGetter != lookupInGlobalObject) {
+ l->qmlContextGlobalLookup.getterTrampoline = l->globalGetter;
+ l->qmlContextPropertyGetter = QQmlContextWrapper::lookupInGlobalObject;
+ }
+ return result;
+}
+
void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml)
{
Heap::ExecutionContext::init(Heap::ExecutionContext::Type_QmlContext);
diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h
index caf9281540..cfcc53c7c9 100644
--- a/src/qml/jsruntime/qv4qmlcontext_p.h
+++ b/src/qml/jsruntime/qv4qmlcontext_p.h
@@ -108,6 +108,7 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object
static ReturnedValue lookupScript(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupSingleton(Lookup *l, ExecutionEngine *engine, Value *base);
static ReturnedValue lookupIdObject(Lookup *l, ExecutionEngine *engine, Value *base);
+ static ReturnedValue lookupInGlobalObject(Lookup *l, ExecutionEngine *engine, Value *base);
};
struct Q_QML_EXPORT QmlContext : public ExecutionContext