summaryrefslogtreecommitdiff
path: root/src/declarative/qml/qdeclarativeexpression.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativeexpression.cpp')
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp136
1 files changed, 76 insertions, 60 deletions
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index d3ba92ab42..0895ffa1ec 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -70,12 +70,14 @@ bool QDeclarativeDelayedError::addError(QDeclarativeEnginePrivate *e)
QDeclarativeJavaScriptExpression::QDeclarativeJavaScriptExpression()
: m_requiresThisObject(0), m_useSharedContext(0), m_notifyOnValueChanged(0),
- m_scopeObject(0)
+ m_scopeObject(0), guardCapture(0)
{
}
QDeclarativeJavaScriptExpression::~QDeclarativeJavaScriptExpression()
{
+ if (guardCapture) guardCapture->expression = 0;
+ clearGuards();
}
QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate()
@@ -149,6 +151,7 @@ QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObje
v8::TryCatch tc;
v8::Local<v8::Object> scopeobject = ep->v8engine()->qmlScope(ctxt, scope);
v8::Local<v8::Script> script = ep->v8engine()->qmlModeCompile(code, filename, line);
+ if (tc.HasCaught()) return v8::Persistent<v8::Function>();
v8::Local<v8::Value> result = script->Run(scopeobject);
if (tc.HasCaught()) return v8::Persistent<v8::Function>();
if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject);
@@ -396,12 +399,12 @@ void QDeclarativeExpressionPrivate::exceptionToError(v8::Handle<v8::Message> mes
void QDeclarativeJavaScriptExpression::setNotifyOnValueChanged(bool v)
{
m_notifyOnValueChanged = v;
- if (!v) guardList.clear();
+ if (!v) clearGuards();
}
void QDeclarativeJavaScriptExpression::resetNotifyOnValueChanged()
{
- guardList.clear();
+ clearGuards();
}
v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::Function> function, bool *isUndefined)
@@ -415,12 +418,15 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
- bool lastCaptureProperties = ep->captureProperties;
- QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
- ep->captureProperties = notifyOnValueChanged();
+ Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty());
+ GuardCapture capture(this);
+
+ QDeclarativeEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture;
+ ep->propertyCapture = notifyOnValueChanged()?&capture:0;
+
- if (ep->capturedProperties.count())
- ep->capturedProperties.copyAndClear(lastCapturedProperties);
+ if (notifyOnValueChanged())
+ capture.guards.copyAndClear(activeGuards);
QDeclarativeContextData *lastSharedContext = 0;
QObject *lastSharedScope = 0;
@@ -429,7 +435,7 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
// All code that follows must check with watcher before it accesses data members
// incase we have been deleted.
- QDeclarativeDeleteWatcher watcher(this);
+ QDeleteWatcher watcher(this);
if (sharedContext) {
lastSharedContext = ep->sharedContext;
@@ -471,80 +477,90 @@ v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::F
ep->sharedScope = lastSharedScope;
}
- if (!watcher.wasDeleted() && notifyOnValueChanged()) {
- guardList.updateGuards(this, ep->capturedProperties);
+ if (capture.errorString) {
+ for (int ii = 0; ii < capture.errorString->count(); ++ii)
+ qWarning("%s", qPrintable(capture.errorString->at(ii)));
+ delete capture.errorString;
+ capture.errorString = 0;
}
- if (lastCapturedProperties.count())
- lastCapturedProperties.copyAndClear(ep->capturedProperties);
- else
- ep->capturedProperties.clear();
+ while (Guard *g = capture.guards.takeFirst())
+ g->Delete();
- ep->captureProperties = lastCaptureProperties;
+ ep->propertyCapture = lastPropertyCapture;
return result;
}
-void
-QDeclarativeJavaScriptExpression::GuardList::updateGuards(QDeclarativeJavaScriptExpression *expression,
- const CapturedProperties &properties)
+void QDeclarativeJavaScriptExpression::GuardCapture::captureProperty(QDeclarativeNotifier *n)
{
- if (properties.count() == 0) {
- clear();
- return;
- }
+ if (expression) {
- if (properties.count() != length) {
- Endpoint *newGuardList = new Endpoint[properties.count()];
+ // Try and find a matching guard
+ while (!guards.isEmpty() && !guards.first()->isConnected(n))
+ guards.takeFirst()->Delete();
- for (int ii = 0; ii < qMin(length, properties.count()); ++ii)
- endpoints[ii].copyAndClear(newGuardList[ii]);
+ Guard *g = 0;
+ if (!guards.isEmpty()) {
+ g = guards.takeFirst();
+ g->cancelNotify();
+ Q_ASSERT(g->isConnected(n));
+ } else {
+ g = Guard::New(expression);
+ g->connect(n);
+ }
- delete [] endpoints;
- endpoints = newGuardList;
- length = properties.count();
+ expression->activeGuards.append(g);
}
+}
- bool outputWarningHeader = false;
- bool noChanges = true;
- for (int ii = 0; ii < properties.count(); ++ii) {
- Endpoint &guard = endpoints[ii];
- const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
-
- guard.expression = expression;
-
- if (property.notifier != 0) {
-
- if (guard.isConnected(property.notifier)) {
- guard.cancelNotify();
- } else {
- guard.connect(property.notifier);
+void QDeclarativeJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n)
+{
+ if (expression) {
+ if (n == -1) {
+ if (!errorString) {
+ errorString = new QStringList;
+ QString preamble = QLatin1String("QDeclarativeExpression: Expression ") +
+ expression->expressionIdentifier() +
+ QLatin1String(" depends on non-NOTIFYable properties:");
+ errorString->append(preamble);
}
- } else if (property.notifyIndex != -1) {
-
- if (guard.isConnected(property.object, property.notifyIndex)) {
- guard.cancelNotify();
- } else {
- guard.connect(property.object, property.notifyIndex);
- }
+ const QMetaObject *metaObj = o->metaObject();
+ QMetaProperty metaProp = metaObj->property(c);
+ QString error = QLatin1String(" ") +
+ QString::fromUtf8(metaObj->className()) +
+ QLatin1String("::") +
+ QString::fromUtf8(metaProp.name());
+ errorString->append(error);
} else {
- if (!outputWarningHeader) {
- QString e = expression->expressionIdentifier();
- outputWarningHeader = true;
- qWarning() << "QDeclarativeExpression: Expression" << qPrintable(e)
- << "depends on non-NOTIFYable properties:";
- }
- const QMetaObject *metaObj = property.object->metaObject();
- QMetaProperty metaProp = metaObj->property(property.coreIndex);
+ // Try and find a matching guard
+ while (!guards.isEmpty() && !guards.first()->isConnected(o, n))
+ guards.takeFirst()->Delete();
+
+ Guard *g = 0;
+ if (!guards.isEmpty()) {
+ g = guards.takeFirst();
+ g->cancelNotify();
+ Q_ASSERT(g->isConnected(o, n));
+ } else {
+ g = Guard::New(expression);
+ g->connect(o, n);
+ }
- qWarning().nospace() << " " << metaObj->className() << "::" << metaProp.name();
+ expression->activeGuards.append(g);
}
}
}
+void QDeclarativeJavaScriptExpression::clearGuards()
+{
+ while (Guard *g = activeGuards.takeFirst())
+ g->Delete();
+}
+
// Must be called with a valid handle scope
v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
{