diff options
-rw-r--r-- | src/declarative/qml/qmlcontext.cpp | 11 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontext_p.h | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontextscriptclass.cpp | 57 | ||||
-rw-r--r-- | src/declarative/qml/qmlcontextscriptclass_p.h | 6 | ||||
-rw-r--r-- | src/declarative/qml/qmlexpression.cpp | 10 | ||||
-rw-r--r-- | tests/auto/declarative/qmlecmascript/data/scope.2.qml | 42 | ||||
-rw-r--r-- | tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp | 41 |
7 files changed, 119 insertions, 50 deletions
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp index 3f61867..43a4741 100644 --- a/src/declarative/qml/qmlcontext.cpp +++ b/src/declarative/qml/qmlcontext.cpp @@ -64,6 +64,8 @@ QmlContextPrivate::QmlContextPrivate() void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, const QString &fileName, int lineNumber) { + Q_Q(QmlContext); + if (!engine) return; @@ -71,11 +73,8 @@ void QmlContextPrivate::addScript(const QString &script, QObject *scopeObject, QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(scriptValue); + scriptContext->pushScope(enginePriv->contextClass->newContext(q, scopeObject)); - if (scopeObject) - scriptContext->pushScope(enginePriv->objectClass->newQObject(scopeObject)); - QScriptValue scope = scriptEngine->newObject(); scriptContext->setActivationObject(scope); @@ -129,10 +128,6 @@ void QmlContextPrivate::init() if (parent) parent->d_func()->childContexts.insert(q); - - //set scope chain - QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - scriptValue = QmlEnginePrivate::get(engine)->contextClass->newContext(q); } void QmlContextPrivate::addDefaultObject(QObject *object, Priority priority) diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h index fe74e28..9a77e94 100644 --- a/src/declarative/qml/qmlcontext_p.h +++ b/src/declarative/qml/qmlcontext_p.h @@ -91,8 +91,6 @@ public: QObjectList defaultObjects; int highPriorityCount; - QScriptValue scriptValue; - QList<QScriptValue> scripts; void addScript(const QString &script, QObject *scope, const QString &fileName = QString(), int lineNumber = 1); diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp index 6d2c58c..939d008 100644 --- a/src/declarative/qml/qmlcontextscriptclass.cpp +++ b/src/declarative/qml/qmlcontextscriptclass.cpp @@ -47,8 +47,9 @@ QT_BEGIN_NAMESPACE struct ContextData : public QScriptDeclarativeClass::Object { - ContextData(QmlContext *c) : context(c) {} + ContextData(QmlContext *c, QObject *o) : context(c), scopeObject(o) {} QGuard<QmlContext> context; + QGuard<QObject> scopeObject; }; /* @@ -57,7 +58,7 @@ struct ContextData : public QScriptDeclarativeClass::Object { */ QmlContextScriptClass::QmlContextScriptClass(QmlEngine *bindEngine) : QScriptDeclarativeClass(QmlEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine), - lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) + lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1), lastDefaultObject(-1) { } @@ -65,11 +66,11 @@ QmlContextScriptClass::~QmlContextScriptClass() { } -QScriptValue QmlContextScriptClass::newContext(QmlContext *context) +QScriptValue QmlContextScriptClass::newContext(QmlContext *context, QObject *scopeObject) { QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine); - return newObject(scriptEngine, this, new ContextData(context)); + return newObject(scriptEngine, this, new ContextData(context, scopeObject)); } QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) @@ -81,24 +82,27 @@ QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v) return data->context; } -#include <QDebug> QScriptClass::QueryFlags QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, QScriptClass::QueryFlags flags) { Q_UNUSED(flags); + lastScopeObject = 0; lastContext = 0; lastData = 0; lastPropertyIndex = -1; lastDefaultObject = -1; QmlContext *bindContext = ((ContextData *)object)->context.data(); + QObject *scopeObject = ((ContextData *)object)->scopeObject.data(); if (!bindContext) return 0; while (bindContext) { - QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags); + QScriptClass::QueryFlags rv = + queryProperty(bindContext, scopeObject, name, flags); + scopeObject = 0; // Only applies to the first context if (rv) return rv; bindContext = bindContext->parentContext(); } @@ -107,7 +111,8 @@ QmlContextScriptClass::queryProperty(Object *object, const Identifier &name, } QScriptClass::QueryFlags -QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name, +QmlContextScriptClass::queryProperty(QmlContext *bindContext, QObject *scopeObject, + const Identifier &name, QScriptClass::QueryFlags flags) { QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); @@ -129,6 +134,24 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } + for (int ii = 0; ii < cp->scripts.count(); ++ii) { + lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); + if (lastFunction.isValid()) { + lastContext = bindContext; + return QScriptClass::HandlesReadAccess; + } + } + + if (scopeObject) { + QScriptClass::QueryFlags rv = + ep->objectClass->queryProperty(scopeObject, name, flags, 0); + if (rv) { + lastScopeObject = scopeObject; + lastContext = bindContext; + return rv; + } + } + for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) { QScriptClass::QueryFlags rv = ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0); @@ -140,13 +163,6 @@ QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier & } } - for (int ii = 0; ii < cp->scripts.count(); ++ii) { - lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name); - if (lastFunction.isValid()) { - lastContext = bindContext; - return QScriptClass::HandlesReadAccess; - } - } return 0; } @@ -160,8 +176,11 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); + if (lastScopeObject) { - if (lastData) { + return ep->objectClass->property(lastScopeObject, name); + + } else if (lastData) { if (lastData->type) return ep->typeNameClass->newObject(cp->defaultObjects.at(0), lastData->type); @@ -197,7 +216,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, const QScriptValue &value) { - Q_ASSERT(lastDefaultObject != -1); + Q_ASSERT(lastScopeObject || lastDefaultObject != -1); QmlContext *bindContext = lastContext; Q_ASSERT(bindContext); @@ -205,7 +224,11 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name, QmlEnginePrivate *ep = QmlEnginePrivate::get(engine); QmlContextPrivate *cp = QmlContextPrivate::get(bindContext); - ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + if (lastScopeObject) { + ep->objectClass->setProperty(lastScopeObject, name, value); + } else { + ep->objectClass->setProperty(cp->defaultObjects.at(lastDefaultObject), name, value); + } } QT_END_NAMESPACE diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h index 761a115..126c8fe 100644 --- a/src/declarative/qml/qmlcontextscriptclass_p.h +++ b/src/declarative/qml/qmlcontextscriptclass_p.h @@ -67,7 +67,7 @@ public: QmlContextScriptClass(QmlEngine *); ~QmlContextScriptClass(); - QScriptValue newContext(QmlContext *); + QScriptValue newContext(QmlContext *, QObject * = 0); QmlContext *contextFromValue(const QScriptValue &); @@ -78,11 +78,13 @@ protected: virtual void setProperty(Object *, const Identifier &name, const QScriptValue &); private: - QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &, + QScriptClass::QueryFlags queryProperty(QmlContext *, QObject *scopeObject, + const Identifier &, QScriptClass::QueryFlags flags); QmlEngine *engine; + QObject *lastScopeObject; QmlContext *lastContext; QmlTypeNameCache::Data *lastData; int lastPropertyIndex; diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp index 6a6ef5d..0de64d9 100644 --- a/src/declarative/qml/qmlexpression.cpp +++ b/src/declarative/qml/qmlexpression.cpp @@ -114,11 +114,8 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc, new QScriptProgram(scriptEngine->compile(data->expression, data->fileName, data->line)); } - QmlContextPrivate *ctxtPriv = ctxt->d_func(); QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - if (me) - scriptContext->pushScope(ep->objectClass->newQObject(me)); + scriptContext->pushScope(ep->contextClass->newContext(ctxt, me)); data->expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]); @@ -297,10 +294,7 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope) if (!data->expressionFunctionValid) { QScriptContext *scriptContext = scriptEngine->pushCleanContext(); - scriptContext->pushScope(ctxtPriv->scriptValue); - - if (data->me) - scriptContext->pushScope(ep->objectClass->newQObject(data->me)); + scriptContext->pushScope(ep->contextClass->newContext(data->context(), data->me)); if (data->expressionRewritten) { data->expressionFunction = scriptEngine->evaluate(data->expression, diff --git a/tests/auto/declarative/qmlecmascript/data/scope.2.qml b/tests/auto/declarative/qmlecmascript/data/scope.2.qml new file mode 100644 index 0000000..433a22e --- /dev/null +++ b/tests/auto/declarative/qmlecmascript/data/scope.2.qml @@ -0,0 +1,42 @@ +import Qt 4.6 + +Item { + property int a: 0 + property int b: 0 + + Script { + function b() { return 11; } + function c() { return 33; } + } + + Object { + id: a + property int value: 19 + } + + Object { + id: c + property int value: 24 + } + + Object { + id: nested + property int a: 1 + property int test: a.value + property int test2: b() + property int test3: c.value + } + + + // id takes precedence over local, and root properties + property int test1: a.value + property alias test2: nested.test + + // methods takes precedence over local, and root properties + property int test3: b() + property alias test4: nested.test2 + + // id takes precedence over methods + property int test5: c.value + property alias test6: nested.test3 +} diff --git a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp index 673be35..5e04f7c 100644 --- a/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp +++ b/tests/auto/declarative/qmlecmascript/tst_qmlecmascript.cpp @@ -538,20 +538,35 @@ void tst_qmlecmascript::nonExistantAttachedObject() void tst_qmlecmascript::scope() { - QmlComponent component(&engine, TEST_FILE("scope.qml")); - QObject *object = component.create(); - QVERIFY(object != 0); + { + QmlComponent component(&engine, TEST_FILE("scope.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); + + QCOMPARE(object->property("test1").toInt(), 1); + QCOMPARE(object->property("test2").toInt(), 2); + QCOMPARE(object->property("test3").toString(), QString("1Test")); + QCOMPARE(object->property("test4").toString(), QString("2Test")); + QCOMPARE(object->property("test5").toInt(), 1); + QCOMPARE(object->property("test6").toInt(), 1); + QCOMPARE(object->property("test7").toInt(), 2); + QCOMPARE(object->property("test8").toInt(), 2); + QCOMPARE(object->property("test9").toInt(), 1); + QCOMPARE(object->property("test10").toInt(), 3); + } + + { + QmlComponent component(&engine, TEST_FILE("scope.2.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); - QCOMPARE(object->property("test1").toInt(), 1); - QCOMPARE(object->property("test2").toInt(), 2); - QCOMPARE(object->property("test3").toString(), QString("1Test")); - QCOMPARE(object->property("test4").toString(), QString("2Test")); - QCOMPARE(object->property("test5").toInt(), 1); - QCOMPARE(object->property("test6").toInt(), 1); - QCOMPARE(object->property("test7").toInt(), 2); - QCOMPARE(object->property("test8").toInt(), 2); - QCOMPARE(object->property("test9").toInt(), 1); - QCOMPARE(object->property("test10").toInt(), 3); + QCOMPARE(object->property("test1").toInt(), 19); + QCOMPARE(object->property("test2").toInt(), 19); + QCOMPARE(object->property("test3").toInt(), 11); + QCOMPARE(object->property("test4").toInt(), 11); + QCOMPARE(object->property("test5").toInt(), 24); + QCOMPARE(object->property("test6").toInt(), 24); + } } /* |