Cleanup
authorAaron Kennedy <aaron.kennedy@nokia.com>
Thu, 16 Jun 2011 05:38:40 +0000 (15:38 +1000)
committerAaron Kennedy <aaron.kennedy@nokia.com>
Thu, 16 Jun 2011 05:38:40 +0000 (15:38 +1000)
src/declarative/qml/qdeclarativebinding.cpp
src/declarative/qml/qdeclarativebinding_p.h
src/declarative/qml/qdeclarativebinding_p_p.h
src/declarative/qml/qdeclarativeexpression.cpp
src/declarative/qml/qdeclarativeexpression_p.h

index 6cca327..d1fdec5 100644 (file)
@@ -218,13 +218,12 @@ void QDeclarativeBindingPrivate::refresh()
 }
 
 QDeclarativeBindingPrivate::QDeclarativeBindingPrivate()
-: updating(false), enabled(false), deleted(0)
+: updating(false), enabled(false)
 {
 }
 
 QDeclarativeBindingPrivate::~QDeclarativeBindingPrivate()
 {
-    if (deleted) *deleted = true;
 }
 
 QDeclarativeBinding::QDeclarativeBinding(void *data, QDeclarativeRefCount *rc, QObject *obj, 
@@ -311,13 +310,13 @@ QDeclarativeProperty QDeclarativeBinding::property() const
 void QDeclarativeBinding::setEvaluateFlags(EvaluateFlags flags)
 {
     Q_D(QDeclarativeBinding);
-    d->setEvaluateFlags(QDeclarativeQtScriptExpression::EvaluateFlags(static_cast<int>(flags)));
+    d->setRequiresThisObject(flags & RequiresThisObject);
 }
 
 QDeclarativeBinding::EvaluateFlags QDeclarativeBinding::evaluateFlags() const
 {
     Q_D(const QDeclarativeBinding);
-    return QDeclarativeBinding::EvaluateFlags(static_cast<int>(d->evaluateFlags()));
+    return d->requiresThisObject()?RequiresThisObject:None;
 }
 
 
@@ -336,6 +335,57 @@ public:
     }
 };
 
+bool QDeclarativeBindingPrivate::writeBindingResult(QDeclarativeJavaScriptExpression *expression,
+                                                    QDeclarativeProperty &prop, v8::Handle<v8::Value> result, 
+                                                    bool isUndefined, QDeclarativePropertyPrivate::WriteFlags flags)
+{
+    QV8Engine *engine = QDeclarativeEnginePrivate::getV8Engine(expression->context()->engine);
+    QDeclarativeDeleteWatcher watcher(expression);
+
+    QVariant value;
+
+    if (isUndefined) {
+    } else if (prop.propertyTypeCategory() == QDeclarativeProperty::List) {
+        value = engine->toVariant(result, qMetaTypeId<QList<QObject *> >());
+    } else if (result->IsNull() && prop.propertyTypeCategory() == QDeclarativeProperty::Object) {
+        value = QVariant::fromValue((QObject *)0);
+    } else {
+        value = engine->toVariant(result, prop.propertyType());
+    }
+
+    if (expression->error.isValid()) {
+        return false;
+    } else if (isUndefined && prop.isResettable()) {
+        prop.reset();
+    } else if (isUndefined && prop.propertyType() == qMetaTypeId<QVariant>()) {
+        QDeclarativePropertyPrivate::write(prop, QVariant(), flags);
+    } else if (isUndefined) {
+        expression->error.setDescription(QLatin1String("Unable to assign [undefined] to ") +
+                                         QLatin1String(QMetaType::typeName(prop.propertyType())) +
+                                         QLatin1String(" ") + prop.name());
+        return false;
+    } else if (result->IsFunction()) {
+        expression->error.setDescription(QLatin1String("Unable to assign a function to a property."));
+        return false;
+    } else if (prop.object() && !QDeclarativePropertyPrivate::write(prop, value, flags)) {
+
+        if (watcher.wasDeleted()) 
+            return true;
+
+        const char *valueType = 0;
+        if (value.userType() == QVariant::Invalid) valueType = "null";
+        else valueType = QMetaType::typeName(value.userType());
+
+        expression->error.setDescription(QLatin1String("Unable to assign ") +
+                                         QLatin1String(valueType) +
+                                         QLatin1String(" to ") +
+                                         QLatin1String(QMetaType::typeName(prop.propertyType())));
+        return false;
+    }
+
+    return true;
+}
+
 void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
 {
     Q_D(QDeclarativeBinding);
@@ -346,8 +396,8 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
     if (!d->updating) {
         QDeclarativeBindingProfiler prof(this);
         d->updating = true;
-        bool wasDeleted = false;
-        d->deleted = &wasDeleted;
+
+        QDeclarativeDeleteWatcher watcher(d);
 
         if (d->property.propertyType() == qMetaTypeId<QDeclarativeBinding *>()) {
 
@@ -361,9 +411,6 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
                                   QMetaObject::WriteProperty,
                                   idx, a);
 
-            if (wasDeleted)
-                return;
-
         } else {
             QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context()->engine);
             ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
@@ -375,99 +422,36 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
             v8::Context::Scope scope(ep->v8engine.context());
             v8::Local<v8::Value> result = d->v8value(0, &isUndefined);
 
-            if (wasDeleted) {
-                ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
-                return;
+            bool needsErrorData = false;
+            if (!watcher.wasDeleted() && !d->error.isValid()) {
+                needsErrorData = !d->writeBindingResult(d, d->property, result, isUndefined, flags);
             }
 
-            if (isUndefined) {
-            } else if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) {
-                value = ep->v8engine.toVariant(result, qMetaTypeId<QList<QObject *> >());
-            } else if (result->IsNull() && d->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
-                value = QVariant::fromValue((QObject *)0);
-            } else {
-                value = ep->v8engine.toVariant(result, d->property.propertyType());
-            }
-
-
-            if (d->error.isValid()) {
+            if (!watcher.wasDeleted()) {
+               
+                if (needsErrorData) {
+                    QUrl url = QUrl(d->url);
+                    int line = d->line;
+                    if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
 
-            } else if (isUndefined && d->property.isResettable()) {
-
-                d->property.reset();
-
-            } else if (isUndefined && d->property.propertyType() == qMetaTypeId<QVariant>()) {
-
-                QDeclarativePropertyPrivate::write(d->property, QVariant(), flags);
-
-            } else if (isUndefined) {
-
-                QUrl url = QUrl(d->url);
-                int line = d->line;
-                if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
-
-                d->error.setUrl(url);
-                d->error.setLine(line);
-                d->error.setColumn(-1);
-                d->error.setDescription(QLatin1String("Unable to assign [undefined] to ") +
-                                        QLatin1String(QMetaType::typeName(d->property.propertyType())) +
-                                        QLatin1String(" ") + d->property.name());
-
-            } else if (result->IsFunction()) {
-
-                QUrl url = QUrl(d->url);
-                int line = d->line;
-                if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
-
-                d->error.setUrl(url);
-                d->error.setLine(line);
-                d->error.setColumn(-1);
-                d->error.setDescription(QLatin1String("Unable to assign a function to a property."));
-
-            } else if (d->property.object() &&
-                       !QDeclarativePropertyPrivate::write(d->property, value, flags)) {
-
-                if (wasDeleted) {
-                    ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
-                    return;
+                    d->error.setUrl(url);
+                    d->error.setLine(line);
+                    d->error.setColumn(-1);
                 }
 
-                QUrl url = QUrl(d->url);
-                int line = d->line;
-                if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
-
-                const char *valueType = 0;
-                if (value.userType() == QVariant::Invalid) valueType = "null";
-                else valueType = QMetaType::typeName(value.userType());
-
-                d->error.setUrl(url);
-                d->error.setLine(line);
-                d->error.setColumn(-1);
-                d->error.setDescription(QLatin1String("Unable to assign ") +
-                                        QLatin1String(valueType) +
-                                        QLatin1String(" to ") +
-                                        QLatin1String(QMetaType::typeName(d->property.propertyType())));
-            }
-
-            if (wasDeleted) {
-                ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
-                return;
-            }
+                if (d->error.isValid()) {
+                    if (!d->addError(ep)) ep->warning(this->error());
+                } else {
+                    d->removeError();
+                }
 
-            if (d->error.isValid()) {
-               if (!d->addError(ep)) ep->warning(this->error());
-            } else {
-                d->removeError();
             }
 
-            // at this point, the binding has been evaluated.  If any scarce
-            // resources were copied during the evaluation of the binding,
-            // we need to release those copies.
-            ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
+            ep->dereferenceScarceResources(); 
         }
 
-        d->updating = false;
-        d->deleted = 0;
+        if (!watcher.wasDeleted())
+            d->updating = false;
     } else {
         qmlInfo(d->property.object()) << tr("Binding loop detected for property \"%1\"").arg(d->property.name());
     }
index f0b3335..e646c86 100644 (file)
@@ -147,7 +147,7 @@ class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeBinding : public QDeclarativeExpr
 {
 Q_OBJECT
 public:
-    enum EvaluateFlag { RequiresThisObject = 0x01 };
+    enum EvaluateFlag { None = 0x00, RequiresThisObject = 0x01 };
     Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag)
 
     QDeclarativeBinding(const QString &, QObject *, QDeclarativeContext *, QObject *parent=0);
index 9e6f75b..1b1b03b 100644 (file)
@@ -69,6 +69,10 @@ public:
 
     virtual void emitValueChanged();
 
+    static bool writeBindingResult(QDeclarativeJavaScriptExpression *expression,
+                                   QDeclarativeProperty &prop, v8::Handle<v8::Value> value, bool isUndefined,
+                                   QDeclarativePropertyPrivate::WriteFlags flags);
+
 protected:
     virtual void refresh();
 
@@ -76,8 +80,6 @@ private:
     bool updating:1;
     bool enabled:1;
     QDeclarativeProperty property; 
-
-    bool *deleted;
 };
 
 QT_END_NAMESPACE
index 7d2803f..d709d5c 100644 (file)
@@ -68,30 +68,27 @@ bool QDeclarativeDelayedError::addError(QDeclarativeEnginePrivate *e)
     return true;
 }
 
-QDeclarativeQtScriptExpression::QDeclarativeQtScriptExpression()
-: dataRef(0), extractExpressionFromFunction(false), expressionFunctionMode(ExplicitContext), 
-  scopeObject(0), trackChange(false), guardList(0), guardListLength(0), guardObject(0), 
-  guardObjectNotifyIndex(-1), deleted(0)
+QDeclarativeJavaScriptExpression::QDeclarativeJavaScriptExpression()
+: m_requiresThisObject(0), m_useSharedContext(0), m_notifyOnValueChanged(0), 
+  m_scopeObject(0), m_notifyObject(0), m_notifyIndex(-1)
 {
 }
 
-QDeclarativeQtScriptExpression::~QDeclarativeQtScriptExpression()
+QDeclarativeJavaScriptExpression::~QDeclarativeJavaScriptExpression()
 {
-    qPersistentDispose(v8function);
-    qPersistentDispose(v8qmlscope);
-
-    if (guardList) { delete [] guardList; guardList = 0; }
-    if (dataRef) dataRef->release();
-    if (deleted) *deleted = true;
 }
 
 QDeclarativeExpressionPrivate::QDeclarativeExpressionPrivate()
-: expressionFunctionValid(true), line(-1)
+: expressionFunctionValid(true), extractExpressionFromFunction(false), line(-1), dataRef(0)
 {
 }
 
 QDeclarativeExpressionPrivate::~QDeclarativeExpressionPrivate()
 {
+    qPersistentDispose(v8qmlscope);
+    qPersistentDispose(v8function);
+    if (dataRef) dataRef->release();
+    dataRef = 0;
 }
 
 void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QString &expr, 
@@ -100,7 +97,7 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QS
     expression = expr;
 
     QDeclarativeAbstractExpression::setContext(ctxt);
-    scopeObject = me;
+    setScopeObject(me);
     expressionFunctionValid = false;
 }
 
@@ -108,10 +105,10 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, v8::Hand
                                          QObject *me)
 {
     QDeclarativeAbstractExpression::setContext(ctxt);
-    scopeObject = me;
+    setScopeObject(me);
 
     v8function = qPersistentNew<v8::Function>(func);
-    expressionFunctionMode = ExplicitContext;
+    setUseSharedContext(false);
     expressionFunctionValid = true;
     extractExpressionFromFunction = true;
 }
@@ -139,11 +136,12 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex
 
     v8function = evalFunction(ctxt, me, expression, url, line, &v8qmlscope);
 
-    expressionFunctionMode = ExplicitContext;
+    setUseSharedContext(false);
+
     expressionFunctionValid = true;
 
     QDeclarativeAbstractExpression::setContext(ctxt);
-    scopeObject = me;
+    setScopeObject(me);
 }
 
 // Callee owns the persistent handle
@@ -405,7 +403,7 @@ void QDeclarativeExpression::setExpression(const QString &expression)
 {
     Q_D(QDeclarativeExpression);
 
-    d->resetNotifyOnChange();
+    d->resetNotifyOnValueChanged();
     d->expression = expression;
     d->expressionFunctionValid = false;
     qPersistentDispose(d->v8function);
@@ -439,158 +437,138 @@ void QDeclarativeExpressionPrivate::exceptionToError(v8::Handle<v8::Message> mes
     error.setDescription(qDescription);
 }
 
-bool QDeclarativeQtScriptExpression::notifyOnValueChange() const
+void QDeclarativeJavaScriptExpression::setNotifyOnValueChanged(bool v)
 {
-    return trackChange;
+    m_notifyOnValueChanged = v;
+    if (!v) guardList.clear();
 }
 
-void QDeclarativeQtScriptExpression::setNotifyOnValueChange(bool notify)
+void QDeclarativeJavaScriptExpression::resetNotifyOnValueChanged()
 {
-    trackChange = notify;
-    if (!notify && guardList) 
-        clearGuards();
+    guardList.clear();
 }
 
-void QDeclarativeQtScriptExpression::resetNotifyOnChange()
+void QDeclarativeJavaScriptExpression::setNotifyObject(QObject *object, int index)
 {
-    clearGuards();
-}
+    guardList.clear();
 
-void QDeclarativeQtScriptExpression::setNotifyObject(QObject *object, int notifyIndex)
-{
-    if (guardList) clearGuards();
-
-    if (!object || notifyIndex == -1) {
-        guardObject = 0;
-        notifyIndex = -1;
-    } else {
-        guardObject = object;
-        guardObjectNotifyIndex = notifyIndex;
+    m_notifyObject = object;
+    m_notifyIndex = index;
 
+    if (!object || index == -1) {
+        m_notifyObject = 0;
+        m_notifyIndex = -1;
     }
 }
 
-void QDeclarativeQtScriptExpression::setEvaluateFlags(EvaluateFlags flags)
-{
-    evalFlags = flags;
-}
-
-QDeclarativeQtScriptExpression::EvaluateFlags QDeclarativeQtScriptExpression::evaluateFlags() const
-{
-    return evalFlags;
-}
-
-v8::Local<v8::Value> QDeclarativeQtScriptExpression::v8value(QObject *secondaryScope, bool *isUndefined)
+v8::Local<v8::Value> QDeclarativeJavaScriptExpression::evaluate(v8::Handle<v8::Function> function, bool *isUndefined)
 {
     Q_ASSERT(context() && context()->engine);
-    Q_ASSERT(!trackChange || (guardObject && guardObjectNotifyIndex != -1));
+    Q_ASSERT(!notifyOnValueChanged() || (m_notifyObject && m_notifyIndex != -1));
 
-    if (v8function.IsEmpty() || v8function->IsUndefined()) {
+    if (function.IsEmpty() || function->IsUndefined()) {
         if (isUndefined) *isUndefined = true;
         return v8::Local<v8::Value>();
     }
 
-    DeleteWatcher watcher(this);
-
     QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
 
     bool lastCaptureProperties = ep->captureProperties;
     QPODVector<QDeclarativeEnginePrivate::CapturedProperty> lastCapturedProperties;
-    ep->captureProperties = trackChange;
+    ep->captureProperties = notifyOnValueChanged();
     ep->capturedProperties.copyAndClear(lastCapturedProperties);
 
-    v8::Local<v8::Value> value = eval(secondaryScope, isUndefined);
-
-    if (!watcher.wasDeleted() && trackChange) {
-        if (ep->capturedProperties.count() == 0) {
-
-            if (guardList) clearGuards();
+    QDeclarativeContextData *lastSharedContext = 0;
+    QObject *lastSharedScope = 0;
 
-        } else {
+    bool sharedContext = useSharedContext();
 
-            updateGuards(ep->capturedProperties);
+    // All code that follows must check with watcher before it accesses data members 
+    // incase we have been deleted.
+    QDeclarativeDeleteWatcher watcher(this);
 
-        }
+    if (sharedContext) {
+        lastSharedContext = ep->sharedContext;
+        lastSharedScope = ep->sharedScope;
+        ep->sharedContext = context();
+        ep->sharedScope = scopeObject();
     }
 
-    lastCapturedProperties.copyAndClear(ep->capturedProperties);
-    ep->captureProperties = lastCaptureProperties;
-
-    return value;
-}
-
-v8::Local<v8::Value> QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined)
-{
-    Q_ASSERT(context() && context()->engine);
-    DeleteWatcher watcher(this);
-
-    QDeclarativeEngine *engine = context()->engine;
-    QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
-    QObject *restoreSecondaryScope = 0;
-    if (secondaryScope) 
-        restoreSecondaryScope = ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
-
-    v8::TryCatch try_catch;
-
-    v8::Handle<v8::Object> This;
-
-    if (evaluateFlags() & RequiresThisObject) {
-        v8::Handle<v8::Value> value = ep->v8engine.newQObject(scopeObject);
-        if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
-    }
-    if (This.IsEmpty()) {
-        This = ep->v8engine.global();
-    }
-
-    v8::Local<v8::Value> result = v8function->Call(This, 0, 0);
+    v8::Local<v8::Value> result;
+    {
+        v8::TryCatch try_catch;
+        v8::Handle<v8::Object> This = ep->v8engine.global();
+        if (scopeObject() && requiresThisObject()) {
+            v8::Handle<v8::Value> value = ep->v8engine.newQObject(scopeObject());
+            if (value->IsObject()) This = v8::Handle<v8::Object>::Cast(value);
+        }
 
-    if (secondaryScope) 
-        ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
+        result = function->Call(This, 0, 0);
 
-    if (isUndefined)
-        *isUndefined = try_catch.HasCaught() || result->IsUndefined();
+        if (isUndefined)
+            *isUndefined = try_catch.HasCaught() || result->IsUndefined();
 
-    if (watcher.wasDeleted()) {
-    } else if (try_catch.HasCaught()) {
-        v8::Context::Scope scope(ep->v8engine.context());
-        v8::Local<v8::Message> message = try_catch.Message();
-        if (!message.IsEmpty()) {
-            QDeclarativeExpressionPrivate::exceptionToError(message, error);
+        if (watcher.wasDeleted()) {
+        } else if (try_catch.HasCaught()) {
+            v8::Context::Scope scope(ep->v8engine.context());
+            v8::Local<v8::Message> message = try_catch.Message();
+            if (!message.IsEmpty()) {
+                QDeclarativeExpressionPrivate::exceptionToError(message, error);
+            } else {
+                error = QDeclarativeError();
+            }
         } else {
             error = QDeclarativeError();
         }
-    } else {
-        error = QDeclarativeError();
     }
 
+    if (sharedContext) {
+        ep->sharedContext = lastSharedContext;
+        ep->sharedScope = lastSharedScope;
+    }
+
+    if (!watcher.wasDeleted() && notifyOnValueChanged()) {
+        guardList.updateGuards(m_notifyObject, m_notifyIndex, expressionString(), 
+                               ep->capturedProperties);
+    }
+
+    lastCapturedProperties.copyAndClear(ep->capturedProperties);
+    ep->captureProperties = lastCaptureProperties;
+
     return result;
 }
 
-void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
+void QDeclarativeJavaScriptExpression::GuardList::updateGuards(QObject *notifyObject, int notifyIndex,
+                                                               const QStringRef &expression,
+                                                               const CapturedProperties &properties)
 {
-    Q_ASSERT(guardObject);
-    Q_ASSERT(guardObjectNotifyIndex != -1);
+    Q_ASSERT(notifyObject);
+    Q_ASSERT(notifyIndex != -1);
 
-    if (properties.count() != guardListLength) {
+    if (properties.count() == 0) {
+        clear();
+        return;
+    }
+
+    if (properties.count() != length) {
         QDeclarativeNotifierEndpoint *newGuardList = new QDeclarativeNotifierEndpoint[properties.count()];
 
-        for (int ii = 0; ii < qMin(guardListLength, properties.count()); ++ii) 
-           guardList[ii].copyAndClear(newGuardList[ii]);
+        for (int ii = 0; ii < qMin(length, properties.count()); ++ii) 
+           endpoints[ii].copyAndClear(newGuardList[ii]);
 
-        delete [] guardList;
-        guardList = newGuardList;
-        guardListLength = properties.count();
+        delete [] endpoints;
+        endpoints = newGuardList;
+        length = properties.count();
     }
 
     bool outputWarningHeader = false;
     bool noChanges = true;
     for (int ii = 0; ii < properties.count(); ++ii) {
-        QDeclarativeNotifierEndpoint &guard = guardList[ii];
+        QDeclarativeNotifierEndpoint &guard = endpoints[ii];
         const QDeclarativeEnginePrivate::CapturedProperty &property = properties.at(ii);
 
-        guard.target = guardObject;
-        guard.targetMethod = guardObjectNotifyIndex;
+        guard.target = notifyObject;
+        guard.targetMethod = notifyIndex;
 
         if (property.notifier != 0) {
 
@@ -602,7 +580,7 @@ void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeE
 
                 bool existing = false;
                 for (int jj = 0; !existing && jj < ii; ++jj) 
-                    if (guardList[jj].isConnected(property.notifier)) 
+                    if (endpoints[jj].isConnected(property.notifier)) 
                         existing = true;
 
                 if (existing) {
@@ -624,7 +602,7 @@ void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeE
 
                 bool existing = false;
                 for (int jj = 0; !existing && jj < ii; ++jj) 
-                    if (guardList[jj].isConnected(property.object, property.notifyIndex)) 
+                    if (endpoints[jj].isConnected(property.object, property.notifyIndex)) 
                         existing = true;
 
                 if (existing) {
@@ -635,7 +613,7 @@ void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeE
                 }
             }
 
-        } else {
+        } else if (!expression.isEmpty()) {
             if (!outputWarningHeader) {
                 outputWarningHeader = true;
                 qWarning() << "QDeclarativeExpression: Expression" << expression
@@ -654,19 +632,27 @@ void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeE
 v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
 {
     if (!expressionFunctionValid) {
-        QDeclarativeEngine *engine = context()->engine;
-        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
         QDeclarativeRewrite::RewriteBinding rewriteBinding;
         rewriteBinding.setName(name);
         bool ok = true;
         const QString code = rewriteBinding(expression, &ok);
-        if (ok) v8function = evalFunction(context(), scopeObject, code, url, line, &v8qmlscope);
-        expressionFunctionMode = ExplicitContext;
+        if (ok) v8function = evalFunction(context(), scopeObject(), code, url, line, &v8qmlscope);
+        setUseSharedContext(false);
         expressionFunctionValid = true;
     }
 
-    return QDeclarativeQtScriptExpression::v8value(secondaryScope, isUndefined);
+
+    if (secondaryScope) {
+        v8::Local<v8::Value> result;
+        QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context()->engine);
+        QObject *restoreSecondaryScope = 0;
+        restoreSecondaryScope = ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
+        result = evaluate(v8function, isUndefined);
+        ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
+        return result;
+    } else {
+        return evaluate(v8function, isUndefined);
+    }
 }
 
 QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
@@ -716,7 +702,7 @@ value changes.
 bool QDeclarativeExpression::notifyOnValueChanged() const
 {
     Q_D(const QDeclarativeExpression);
-    return d->notifyOnValueChange();
+    return d->notifyOnValueChanged();
 }
 
 /*!
@@ -738,7 +724,7 @@ bool QDeclarativeExpression::notifyOnValueChanged() const
 void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
 {
     Q_D(QDeclarativeExpression);
-    d->setNotifyOnValueChange(notifyOnChange);
+    d->setNotifyOnValueChanged(notifyOnChange);
 }
 
 /*!
@@ -781,7 +767,7 @@ void QDeclarativeExpression::setSourceLocation(const QString &url, int line)
 QObject *QDeclarativeExpression::scopeObject() const
 {
     Q_D(const QDeclarativeExpression);
-    return d->scopeObject;
+    return d->scopeObject();
 }
 
 /*!
@@ -827,13 +813,6 @@ void QDeclarativeExpressionPrivate::_q_notify()
     emitValueChanged();
 }
 
-void QDeclarativeQtScriptExpression::clearGuards()
-{
-    delete [] guardList; 
-    guardList = 0; 
-    guardListLength = 0;
-}
-
 /*!
     \fn void QDeclarativeExpression::valueChanged()
 
index b03c709..dcf47c3 100644 (file)
@@ -55,8 +55,8 @@
 
 #include "qdeclarativeexpression.h"
 
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativeguard_p.h"
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativeguard_p.h>
 
 #include <private/qv8engine_p.h>
 
@@ -107,73 +107,84 @@ private:
     QDeclarativeDelayedError **prevError;
 };
 
-class QDeclarativeQtScriptExpression : public QDeclarativeAbstractExpression, 
-                                       public QDeclarativeDelayedError
+class QDeclarativeDeleteWatchable
 {
 public:
-    enum Mode { SharedContext, ExplicitContext };
-
-    enum EvaluateFlag { RequiresThisObject = 0x01 };
-    Q_DECLARE_FLAGS(EvaluateFlags, EvaluateFlag)
-
-    QDeclarativeQtScriptExpression();
-    virtual ~QDeclarativeQtScriptExpression();
+    inline QDeclarativeDeleteWatchable();
+    inline ~QDeclarativeDeleteWatchable();
+private:
+    friend class QDeclarativeDeleteWatcher;
+    bool *m_wasDeleted;
+};
 
-    QDeclarativeRefCount *dataRef;
+class QDeclarativeDeleteWatcher {
+public:
+    inline QDeclarativeDeleteWatcher(QDeclarativeDeleteWatchable *data);
+    inline ~QDeclarativeDeleteWatcher();
+    inline bool wasDeleted() const;
+private:
+    void *operator new(size_t);
+    bool *m_wasDeleted;
+    bool m_wasDeletedStorage;
+    QDeclarativeDeleteWatchable *m_d;
+};
 
-    QString expression;
-    bool extractExpressionFromFunction;
+class QDeclarativeJavaScriptExpression : public QDeclarativeAbstractExpression, 
+                                         public QDeclarativeDelayedError,
+                                         public QDeclarativeDeleteWatchable
+{
+public:
+    QDeclarativeJavaScriptExpression();
+    virtual ~QDeclarativeJavaScriptExpression();
 
-    Mode expressionFunctionMode;
-    v8::Persistent<v8::Function> v8function;
-    v8::Persistent<v8::Object> v8qmlscope;
+    v8::Local<v8::Value> evaluate(v8::Handle<v8::Function>, bool *isUndefined);
 
-    QObject *scopeObject;           // Only used in SharedContext
+    inline bool requiresThisObject() const;
+    inline void setRequiresThisObject(bool v);
+    inline bool useSharedContext() const;
+    inline void setUseSharedContext(bool v);
+    inline bool notifyOnValueChanged() const;
 
-    bool notifyOnValueChange() const;
-    void setNotifyOnValueChange(bool);
-    void resetNotifyOnChange();
+    void setNotifyOnValueChanged(bool v);
+    void resetNotifyOnValueChanged();
     void setNotifyObject(QObject *, int );
 
-    void setEvaluateFlags(EvaluateFlags flags);
-    EvaluateFlags evaluateFlags() const;
+    inline QObject *scopeObject() const;
+    inline void setScopeObject(QObject *v);
 
-    v8::Local<v8::Value> v8value(QObject *secondaryScope, bool *isUndefined);
-
-    class DeleteWatcher {
-    public:
-        inline DeleteWatcher(QDeclarativeQtScriptExpression *data);
-        inline ~DeleteWatcher();
-        inline bool wasDeleted() const;
-    private:
-        bool *m_wasDeleted;
-        bool m_wasDeletedStorage;
-        QDeclarativeQtScriptExpression *m_d;
-    };
+protected:
+    inline virtual QStringRef expressionString();
 
 private:
-    void clearGuards();
-    v8::Local<v8::Value> eval(QObject *secondaryScope, bool *isUndefined);
-    void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties);
+    quint32 m_requiresThisObject:1;
+    quint32 m_useSharedContext:1;
+    quint32 m_notifyOnValueChanged:1;
+    quint32 m_dummy:29;
 
-    bool trackChange;
+    QObject *m_scopeObject;
+    QObject *m_notifyObject;
+    int m_notifyIndex;
 
-    QDeclarativeNotifierEndpoint *guardList;
-    int guardListLength;
+    class GuardList {
+    public:
+        inline GuardList();
+        inline ~GuardList();
+        void inline clear();
 
-    QObject *guardObject;
-    int guardObjectNotifyIndex;
-    bool *deleted;
+        typedef QPODVector<QDeclarativeEnginePrivate::CapturedProperty> CapturedProperties;
+        void updateGuards(QObject *guardObject, int guardObjectNotifyIndex,
+                          const QStringRef &expression, const CapturedProperties &properties);
 
-    EvaluateFlags evalFlags;
+    private:
+        QDeclarativeNotifierEndpoint *endpoints;
+        int length;
+    };
+    GuardList guardList;
 };
 
-Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeQtScriptExpression::EvaluateFlags)
-
-
 class QDeclarativeExpression;
 class QString;
-class QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeQtScriptExpression
+class QDeclarativeExpressionPrivate : public QObjectPrivate, public QDeclarativeJavaScriptExpression
 {
     Q_DECLARE_PUBLIC(QDeclarativeExpression)
 public:
@@ -188,12 +199,8 @@ public:
 
     v8::Local<v8::Value> v8value(QObject *secondaryScope = 0, bool *isUndefined = 0);
 
-    static QDeclarativeExpressionPrivate *get(QDeclarativeExpression *expr) {
-        return static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr));
-    }
-    static QDeclarativeExpression *get(QDeclarativeExpressionPrivate *expr) {
-        return expr->q_func();
-    }
+    static inline QDeclarativeExpressionPrivate *get(QDeclarativeExpression *expr);
+    static inline QDeclarativeExpression *get(QDeclarativeExpressionPrivate *expr);
 
     void _q_notify();
     virtual void emitValueChanged();
@@ -204,31 +211,123 @@ public:
                                                      v8::Persistent<v8::Object> *qmlscope = 0);
 
     bool expressionFunctionValid:1;
+    bool extractExpressionFromFunction:1;
+
+    inline virtual QStringRef expressionString();
+
+    QString expression;
+
+    v8::Persistent<v8::Object> v8qmlscope;
+    v8::Persistent<v8::Function> v8function;
 
     QString url; // This is a QString for a reason.  QUrls are slooooooow...
     int line;
     QByteArray name; //function name, hint for the debugger
+
+    QDeclarativeRefCount *dataRef;
 };
 
-QDeclarativeQtScriptExpression::DeleteWatcher::DeleteWatcher(QDeclarativeQtScriptExpression *data)
+QDeclarativeDeleteWatchable::QDeclarativeDeleteWatchable()
+: m_wasDeleted(0)
+{
+}
+
+QDeclarativeDeleteWatchable::~QDeclarativeDeleteWatchable()
+{
+    if (m_wasDeleted) *m_wasDeleted = true;
+}
+
+QDeclarativeDeleteWatcher::QDeclarativeDeleteWatcher(QDeclarativeDeleteWatchable *data)
 : m_wasDeletedStorage(false), m_d(data) 
 {
-    if (!m_d->deleted) 
-        m_d->deleted = &m_wasDeletedStorage; 
-    m_wasDeleted = m_d->deleted;
+    if (!m_d->m_wasDeleted) 
+        m_d->m_wasDeleted = &m_wasDeletedStorage; 
+    m_wasDeleted = m_d->m_wasDeleted;
 }
 
-QDeclarativeQtScriptExpression::DeleteWatcher::~DeleteWatcher() 
+QDeclarativeDeleteWatcher::~QDeclarativeDeleteWatcher() 
 {
-    if (false == *m_wasDeleted && m_wasDeleted == m_d->deleted)
-        m_d->deleted = 0;
+    if (false == *m_wasDeleted && m_wasDeleted == m_d->m_wasDeleted)
+        m_d->m_wasDeleted = 0;
 }
 
-bool QDeclarativeQtScriptExpression::DeleteWatcher::wasDeleted() const 
+bool QDeclarativeDeleteWatcher::wasDeleted() const 
 { 
     return *m_wasDeleted; 
 }
 
+bool QDeclarativeJavaScriptExpression::requiresThisObject() const 
+{ 
+    return m_requiresThisObject; 
+}
+
+void QDeclarativeJavaScriptExpression::setRequiresThisObject(bool v) 
+{ 
+    m_requiresThisObject = v; 
+}
+
+bool QDeclarativeJavaScriptExpression::useSharedContext() const 
+{ 
+    return m_useSharedContext; 
+}
+
+void QDeclarativeJavaScriptExpression::setUseSharedContext(bool v) 
+{ 
+    m_useSharedContext = v; 
+}
+
+bool QDeclarativeJavaScriptExpression::notifyOnValueChanged() const 
+{ 
+    return m_notifyOnValueChanged; 
+}
+
+QObject *QDeclarativeJavaScriptExpression::scopeObject() const 
+{ 
+    return m_scopeObject; 
+}
+
+void QDeclarativeJavaScriptExpression::setScopeObject(QObject *v) 
+{ 
+    m_scopeObject = v; 
+}
+
+QStringRef QDeclarativeJavaScriptExpression::expressionString() 
+{ 
+    return QStringRef(); 
+}
+
+QDeclarativeJavaScriptExpression::GuardList::GuardList() 
+: endpoints(0), length(0) 
+{
+}
+
+QDeclarativeJavaScriptExpression::GuardList::~GuardList() 
+{ 
+    clear(); 
+}
+
+void QDeclarativeJavaScriptExpression::GuardList::clear() 
+{ 
+    delete [] endpoints; 
+    endpoints = 0; 
+    length = 0; 
+}
+
+QDeclarativeExpressionPrivate *QDeclarativeExpressionPrivate::get(QDeclarativeExpression *expr) 
+{
+    return static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr));
+}
+
+QDeclarativeExpression *QDeclarativeExpressionPrivate::get(QDeclarativeExpressionPrivate *expr) 
+{
+    return expr->q_func();
+}
+
+QStringRef QDeclarativeExpressionPrivate::expressionString()
+{
+    return QStringRef(&expression);
+}
+
 QT_END_NAMESPACE
 
 #endif // QDECLARATIVEEXPRESSION_P_H