}
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,
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;
}
}
};
+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);
if (!d->updating) {
QDeclarativeBindingProfiler prof(this);
d->updating = true;
- bool wasDeleted = false;
- d->deleted = &wasDeleted;
+
+ QDeclarativeDeleteWatcher watcher(d);
if (d->property.propertyType() == qMetaTypeId<QDeclarativeBinding *>()) {
QMetaObject::WriteProperty,
idx, a);
- if (wasDeleted)
- return;
-
} else {
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(d->context()->engine);
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
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());
}
{
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);
virtual void emitValueChanged();
+ static bool writeBindingResult(QDeclarativeJavaScriptExpression *expression,
+ QDeclarativeProperty &prop, v8::Handle<v8::Value> value, bool isUndefined,
+ QDeclarativePropertyPrivate::WriteFlags flags);
+
protected:
virtual void refresh();
bool updating:1;
bool enabled:1;
QDeclarativeProperty property;
-
- bool *deleted;
};
QT_END_NAMESPACE
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,
expression = expr;
QDeclarativeAbstractExpression::setContext(ctxt);
- scopeObject = me;
+ setScopeObject(me);
expressionFunctionValid = false;
}
QObject *me)
{
QDeclarativeAbstractExpression::setContext(ctxt);
- scopeObject = me;
+ setScopeObject(me);
v8function = qPersistentNew<v8::Function>(func);
- expressionFunctionMode = ExplicitContext;
+ setUseSharedContext(false);
expressionFunctionValid = true;
extractExpressionFromFunction = true;
}
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
{
Q_D(QDeclarativeExpression);
- d->resetNotifyOnChange();
+ d->resetNotifyOnValueChanged();
d->expression = expression;
d->expressionFunctionValid = false;
qPersistentDispose(d->v8function);
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) {
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) {
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) {
}
}
- } else {
+ } else if (!expression.isEmpty()) {
if (!outputWarningHeader) {
outputWarningHeader = true;
qWarning() << "QDeclarativeExpression: Expression" << expression
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)
bool QDeclarativeExpression::notifyOnValueChanged() const
{
Q_D(const QDeclarativeExpression);
- return d->notifyOnValueChange();
+ return d->notifyOnValueChanged();
}
/*!
void QDeclarativeExpression::setNotifyOnValueChanged(bool notifyOnChange)
{
Q_D(QDeclarativeExpression);
- d->setNotifyOnValueChange(notifyOnChange);
+ d->setNotifyOnValueChanged(notifyOnChange);
}
/*!
QObject *QDeclarativeExpression::scopeObject() const
{
Q_D(const QDeclarativeExpression);
- return d->scopeObject;
+ return d->scopeObject();
}
/*!
emitValueChanged();
}
-void QDeclarativeQtScriptExpression::clearGuards()
-{
- delete [] guardList;
- guardList = 0;
- guardListLength = 0;
-}
-
/*!
\fn void QDeclarativeExpression::valueChanged()
#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>
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:
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();
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