summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2009-10-06 05:31:56 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2009-10-06 05:31:56 (GMT)
commit067b419199b369b6c81fa1ae387257aa87cab20c (patch)
tree20ef3dc7c3def67fd74117f50fdae3be054ee836
parent9e4b877430a6811079d209656587ea228334ed34 (diff)
downloadQt-067b419199b369b6c81fa1ae387257aa87cab20c.zip
Qt-067b419199b369b6c81fa1ae387257aa87cab20c.tar.gz
Qt-067b419199b369b6c81fa1ae387257aa87cab20c.tar.bz2
Improve scope handling
-rw-r--r--src/declarative/qml/qmlcontext.cpp11
-rw-r--r--src/declarative/qml/qmlcontext_p.h3
-rw-r--r--src/declarative/qml/qmlcontextscriptclass.cpp45
-rw-r--r--src/declarative/qml/qmlcontextscriptclass_p.h6
-rw-r--r--src/declarative/qml/qmlexpression.cpp22
-rw-r--r--src/declarative/qml/qmlobjectscriptclass.cpp56
-rw-r--r--src/declarative/qml/qmlobjectscriptclass_p.h3
-rw-r--r--src/declarative/qml/qmltypenamescriptclass.cpp3
-rw-r--r--src/declarative/util/qmlscript.cpp6
9 files changed, 96 insertions, 59 deletions
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index 968597c..a1eb5de 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -103,16 +103,7 @@ void QmlContextPrivate::init()
//set scope chain
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- QScriptValue scopeObj = QmlEnginePrivate::get(engine)->contextClass->newContext(q);
-
- //### no longer need to push global object once we switch to JSC (test with objects added to globalObject)
- //if (parent)
- // scopeChain = parent->d_func()->scopeChain;
- if (!parent)
- scopeChain.append(scriptEngine->globalObject());
- else
- scopeChain = parent->d_func()->scopeChain;
- scopeChain.prepend(scopeObj);
+ 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 8fd2e92..22e5895 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -85,14 +85,13 @@ public:
bool isInternal;
QmlIntegerCache *propertyNames;
-// QHash<QString, int> propertyNames;
QList<QVariant> propertyValues;
int notifyIndex;
QObjectList defaultObjects;
int highPriorityCount;
- QScriptValueList scopeChain;
+ QScriptValue scriptValue;
QList<QScriptValue> scripts;
diff --git a/src/declarative/qml/qmlcontextscriptclass.cpp b/src/declarative/qml/qmlcontextscriptclass.cpp
index 226c34c..6d2c58c 100644
--- a/src/declarative/qml/qmlcontextscriptclass.cpp
+++ b/src/declarative/qml/qmlcontextscriptclass.cpp
@@ -72,51 +72,80 @@ QScriptValue QmlContextScriptClass::newContext(QmlContext *context)
return newObject(scriptEngine, this, new ContextData(context));
}
+QmlContext *QmlContextScriptClass::contextFromValue(const QScriptValue &v)
+{
+ if (scriptClass(v) != this)
+ return 0;
+
+ ContextData *data = (ContextData *)object(v);
+ return data->context;
+}
+
+#include <QDebug>
QScriptClass::QueryFlags
QmlContextScriptClass::queryProperty(Object *object, const Identifier &name,
QScriptClass::QueryFlags flags)
{
Q_UNUSED(flags);
+ lastContext = 0;
+ lastData = 0;
lastPropertyIndex = -1;
lastDefaultObject = -1;
- lastData = 0;
QmlContext *bindContext = ((ContextData *)object)->context.data();
if (!bindContext)
return 0;
+ while (bindContext) {
+ QScriptClass::QueryFlags rv = queryProperty(bindContext, name, flags);
+ if (rv) return rv;
+ bindContext = bindContext->parentContext();
+ }
+
+ return 0;
+}
+
+QScriptClass::QueryFlags
+QmlContextScriptClass::queryProperty(QmlContext *bindContext, const Identifier &name,
+ QScriptClass::QueryFlags flags)
+{
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QmlContextPrivate *cp = QmlContextPrivate::get(bindContext);
lastPropertyIndex = cp->propertyNames?cp->propertyNames->value(name):-1;
- if (lastPropertyIndex != -1)
+ if (lastPropertyIndex != -1) {
+ lastContext = bindContext;
return QScriptClass::HandlesReadAccess;
+ }
- if (ep->currentExpression && cp->imports && bindContext == ep->currentExpression->context()) {
+ if (cp->imports) {
QmlTypeNameCache::Data *data = cp->imports->data(name);
if (data) {
lastData = data;
+ lastContext = bindContext;
return QScriptClass::HandlesReadAccess;
}
}
for (int ii = 0; ii < cp->defaultObjects.count(); ++ii) {
QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags,
- QmlObjectScriptClass::SkipAttachedProperties);
+ ep->objectClass->queryProperty(cp->defaultObjects.at(ii), name, flags, 0);
if (rv) {
lastDefaultObject = ii;
+ lastContext = bindContext;
return rv;
}
}
for (int ii = 0; ii < cp->scripts.count(); ++ii) {
lastFunction = QScriptDeclarativeClass::function(cp->scripts.at(ii), name);
- if (lastFunction.isValid())
+ if (lastFunction.isValid()) {
+ lastContext = bindContext;
return QScriptClass::HandlesReadAccess;
+ }
}
return 0;
}
@@ -125,7 +154,7 @@ QScriptValue QmlContextScriptClass::property(Object *object, const Identifier &n
{
Q_UNUSED(object);
- QmlContext *bindContext = ((ContextData *)object)->context.data();
+ QmlContext *bindContext = lastContext;
Q_ASSERT(bindContext);
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
@@ -170,7 +199,7 @@ void QmlContextScriptClass::setProperty(Object *object, const Identifier &name,
{
Q_ASSERT(lastDefaultObject != -1);
- QmlContext *bindContext = ((ContextData *)object)->context.data();
+ QmlContext *bindContext = lastContext;
Q_ASSERT(bindContext);
QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
diff --git a/src/declarative/qml/qmlcontextscriptclass_p.h b/src/declarative/qml/qmlcontextscriptclass_p.h
index acb8926..761a115 100644
--- a/src/declarative/qml/qmlcontextscriptclass_p.h
+++ b/src/declarative/qml/qmlcontextscriptclass_p.h
@@ -69,6 +69,8 @@ public:
QScriptValue newContext(QmlContext *);
+ QmlContext *contextFromValue(const QScriptValue &);
+
protected:
virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
QScriptClass::QueryFlags flags);
@@ -76,8 +78,12 @@ protected:
virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
private:
+ QScriptClass::QueryFlags queryProperty(QmlContext *, const Identifier &,
+ QScriptClass::QueryFlags flags);
+
QmlEngine *engine;
+ QmlContext *lastContext;
QmlTypeNameCache::Data *lastData;
int lastPropertyIndex;
int lastDefaultObject;
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index 61c14a9..e1c7afe 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -82,17 +82,20 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
int progIdx = *(data + 1);
QmlEngine *engine = ctxt->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
if (!dd->programs.at(progIdx)) {
dd->programs[progIdx] = new QScriptProgram(scriptEngine->compile(expression));
}
QmlContextPrivate *ctxtPriv = ctxt->d_func();
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i)
- scriptContext->pushScope(ctxtPriv->scopeChain.at(i));
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ctxtPriv->scriptValue);
+ if (me)
+ scriptContext->pushScope(ep->objectClass->newQObject(me));
expressionFunction = scriptEngine->evaluate(*dd->programs[progIdx]);
+
expressionFunctionValid = true;
scriptEngine->popContext();
}
@@ -239,9 +242,8 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
QmlContextPrivate *ctxtPriv = context()->d_func();
QmlEngine *engine = context()->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- if (me)
- ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount, me);
if (secondaryScope)
ctxtPriv->defaultObjects.insert(ctxtPriv->highPriorityCount,
secondaryScope);
@@ -250,9 +252,11 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
if (!expressionFunctionValid) {
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = ctxtPriv->scopeChain.size() - 1; i > -1; --i)
- scriptContext->pushScope(ctxtPriv->scopeChain.at(i));
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(ctxtPriv->scriptValue);
+
+ if (me)
+ scriptContext->pushScope(ep->objectClass->newQObject(me));
if (expressionRewritten) {
expressionFunction = scriptEngine->evaluate(expression, fileName, line);
@@ -283,8 +287,6 @@ QVariant QmlExpressionPrivate::evalQtScript(QObject *secondaryScope)
}
}
- if (me)
- ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
if (secondaryScope)
ctxtPriv->defaultObjects.removeAt(ctxtPriv->highPriorityCount);
diff --git a/src/declarative/qml/qmlobjectscriptclass.cpp b/src/declarative/qml/qmlobjectscriptclass.cpp
index 330eddd..2d69590 100644
--- a/src/declarative/qml/qmlobjectscriptclass.cpp
+++ b/src/declarative/qml/qmlobjectscriptclass.cpp
@@ -80,6 +80,9 @@ QScriptValue QmlObjectScriptClass::newQObject(QObject *object)
{
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ if (!object)
+ return newObject(scriptEngine, this, new ObjectData(object));
+
QmlDeclarativeData *ddata = QmlDeclarativeData::get(object, true);
if (!ddata->scriptValue.isValid()) {
@@ -101,12 +104,12 @@ QScriptClass::QueryFlags
QmlObjectScriptClass::queryProperty(Object *object, const Identifier &name,
QScriptClass::QueryFlags flags)
{
- return queryProperty(toQObject(object), name, flags);
+ return queryProperty(toQObject(object), name, flags, 0);
}
QScriptClass::QueryFlags
QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
- QScriptClass::QueryFlags flags, QueryMode mode)
+ QScriptClass::QueryFlags flags, QmlContext *evalContext)
{
Q_UNUSED(flags);
lastData = 0;
@@ -120,21 +123,7 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
return 0;
QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(engine);
-
- if (mode == IncludeAttachedProperties) {
- QmlContext *evalContext = enginePrivate->currentExpression->context();
- QmlContextPrivate *cp = QmlContextPrivate::get(evalContext);
- // ### Check for attached properties
-
- if (cp->imports) {
- QmlTypeNameCache::Data *data = cp->imports->data(name);
- if (data) {
- lastTNData = data;
- return QScriptClass::HandlesReadAccess;
- }
- }
-
- }
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
QmlPropertyCache *cache = 0;
QmlDeclarativeData *ddata = QmlDeclarativeData::get(obj);
@@ -153,12 +142,35 @@ QmlObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
lastData = &local;
}
- if (!lastData) return 0;
+ if (lastData) {
+ QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess;
+ if (lastData->flags & QmlPropertyCache::Data::IsWritable)
+ rv |= QScriptClass::HandlesWriteAccess;
+ return rv;
+ }
+
+ if (!evalContext && context) {
+ // Global object, QScriptContext activation object, QmlContext object
+ QScriptValue scopeNode = scopeChainValue(context, 3);
+ Q_ASSERT(scopeNode.isValid());
+ Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
+
+ evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
+ }
+
+ if (evalContext) {
+ QmlContextPrivate *cp = QmlContextPrivate::get(evalContext);
+
+ if (cp->imports) {
+ QmlTypeNameCache::Data *data = cp->imports->data(name);
+ if (data) {
+ lastTNData = data;
+ return QScriptClass::HandlesReadAccess;
+ }
+ }
+ }
- QScriptClass::QueryFlags rv = QScriptClass::HandlesReadAccess;
- if (lastData->flags & QmlPropertyCache::Data::IsWritable)
- rv |= QScriptClass::HandlesWriteAccess;
- return rv;
+ return 0;
}
QScriptValue QmlObjectScriptClass::property(Object *object, const Identifier &name)
diff --git a/src/declarative/qml/qmlobjectscriptclass_p.h b/src/declarative/qml/qmlobjectscriptclass_p.h
index 6de63ca..3fcf009 100644
--- a/src/declarative/qml/qmlobjectscriptclass_p.h
+++ b/src/declarative/qml/qmlobjectscriptclass_p.h
@@ -63,6 +63,7 @@ QT_BEGIN_NAMESPACE
class QmlEngine;
class QScriptContext;
class QScriptEngine;
+class QmlContext;
class QmlObjectScriptClass : public QScriptDeclarativeClass
{
public:
@@ -76,7 +77,7 @@ public:
QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
QScriptClass::QueryFlags flags,
- QueryMode = IncludeAttachedProperties);
+ QmlContext *evalContext);
QScriptValue property(QObject *, const Identifier &);
void setProperty(QObject *, const Identifier &name, const QScriptValue &);
diff --git a/src/declarative/qml/qmltypenamescriptclass.cpp b/src/declarative/qml/qmltypenamescriptclass.cpp
index 4e1ac4b..c0613d1 100644
--- a/src/declarative/qml/qmltypenamescriptclass.cpp
+++ b/src/declarative/qml/qmltypenamescriptclass.cpp
@@ -131,8 +131,7 @@ QmlTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name,
// Must be an attached property
object = qmlAttachedPropertiesObjectById(data->type->index(), data->object);
if (!object) return 0;
- return ep->objectClass->queryProperty(object, name, flags,
- QmlObjectScriptClass::SkipAttachedProperties);
+ return ep->objectClass->queryProperty(object, name, flags, 0);
}
}
diff --git a/src/declarative/util/qmlscript.cpp b/src/declarative/util/qmlscript.cpp
index 2031a54..5d58f64 100644
--- a/src/declarative/util/qmlscript.cpp
+++ b/src/declarative/util/qmlscript.cpp
@@ -178,10 +178,8 @@ void QmlScriptPrivate::addScriptToEngine(const QString &script, const QString &s
QmlContext *context = qmlContext(q);
QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- QScriptContext *scriptContext = scriptEngine->pushContext();
- for (int i = context->d_func()->scopeChain.size() - 1; i >= 0; --i) {
- scriptContext->pushScope(context->d_func()->scopeChain.at(i));
- }
+ QScriptContext *scriptContext = scriptEngine->pushCleanContext();
+ scriptContext->pushScope(QmlContextPrivate::get(context)->scriptValue);
QScriptValue scope = scriptEngine->newObject();
scriptContext->pushScope(scope);