diff options
author | Kent Hansen <kent.hansen@nokia.com> | 2012-03-19 12:29:32 +0100 |
---|---|---|
committer | Kent Hansen <kent.hansen@nokia.com> | 2012-03-19 12:37:03 +0100 |
commit | 4821058f10118be55a541ad39e25ec9165cca3b3 (patch) | |
tree | 167973e3c68fc442b0e37d6f628f3fdbe759f15a /src/qml/qml/qqmlexpression.cpp | |
parent | 83f11e33745180e9370d484cbcedd0bac020c9dd (diff) | |
parent | 26d5f2e833f0e3686aaa27e695bbfab5fbd808ad (diff) |
Merge master into api_changes
Conflicts:
src/qml/debugger/qqmlenginedebugservice.cpp
src/qml/qml/v8/qv8qobjectwrapper.cpp
src/quick/util/qquickimageprovider.cpp
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
Change-Id: Ie78ba2fabd32f4812bcae9dbdd66ed289dc11dcb
Diffstat (limited to 'src/qml/qml/qqmlexpression.cpp')
-rw-r--r-- | src/qml/qml/qqmlexpression.cpp | 425 |
1 files changed, 9 insertions, 416 deletions
diff --git a/src/qml/qml/qqmlexpression.cpp b/src/qml/qml/qqmlexpression.cpp index ecdbf21d4b..60a0fe1c89 100644 --- a/src/qml/qml/qqmlexpression.cpp +++ b/src/qml/qml/qqmlexpression.cpp @@ -52,32 +52,6 @@ QT_BEGIN_NAMESPACE -bool QQmlDelayedError::addError(QQmlEnginePrivate *e) -{ - if (!e) return false; - - if (e->inProgressCreations == 0) return false; // Not in construction - - if (prevError) return true; // Already in error chain - - prevError = &e->erroredBindings; - nextError = e->erroredBindings; - e->erroredBindings = this; - if (nextError) nextError->prevError = &nextError; - - return true; -} - -QQmlJavaScriptExpression::QQmlJavaScriptExpression(VTable *v) -: m_vtable(v) -{ -} - -QQmlJavaScriptExpression::~QQmlJavaScriptExpression() -{ - clearGuards(); -} - static QQmlJavaScriptExpression::VTable QQmlExpressionPrivate_jsvtable = { QQmlExpressionPrivate::expressionIdentifier, QQmlExpressionPrivate::expressionChanged @@ -98,8 +72,7 @@ QQmlExpressionPrivate::~QQmlExpressionPrivate() dataRef = 0; } -void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, - QObject *me) +void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, QObject *me) { expression = expr; @@ -109,22 +82,9 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, expressionFunctionRewritten = false; } -void QQmlExpressionPrivate::init(QQmlContextData *ctxt, v8::Handle<v8::Function> func, - QObject *me) -{ - QQmlAbstractExpression::setContext(ctxt); - setScopeObject(me); - - v8function = qPersistentNew<v8::Function>(func); - setUseSharedContext(false); - expressionFunctionValid = true; - expressionFunctionRewritten = false; - extractExpressionFromFunction = true; -} - void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, - bool isRewritten, QObject *me, const QString &srcUrl, - int lineNumber, int columnNumber) + bool isRewritten, QObject *me, const QString &srcUrl, + int lineNumber, int columnNumber) { url = srcUrl; line = lineNumber; @@ -140,8 +100,8 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QString &expr, } void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, - bool isRewritten, QObject *me, const QString &srcUrl, - int lineNumber, int columnNumber) + bool isRewritten, QObject *me, const QString &srcUrl, + int lineNumber, int columnNumber) { url = srcUrl; line = lineNumber; @@ -166,97 +126,13 @@ void QQmlExpressionPrivate::init(QQmlContextData *ctxt, const QByteArray &expr, setScopeObject(me); } -// Callee owns the persistent handle -v8::Persistent<v8::Function> -QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, - const char *code, int codeLength, - const QString &filename, int line, - v8::Persistent<v8::Object> *qmlscope) -{ - QQmlEngine *engine = ctxt->engine; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - - v8::HandleScope handle_scope; - v8::Context::Scope ctxtscope(ep->v8engine()->context()); - - v8::TryCatch tc; - v8::Local<v8::Object> scopeobject = ep->v8engine()->qmlScope(ctxt, scope); - v8::Local<v8::Script> script = ep->v8engine()->qmlModeCompile(code, codeLength, filename, line); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function compilation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local<v8::Message> message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent<v8::Function>(); - } - v8::Local<v8::Value> result = script->Run(scopeobject); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function evaluation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local<v8::Message> message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent<v8::Function>(); - } - if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject); - return qPersistentNew<v8::Function>(v8::Local<v8::Function>::Cast(result)); -} - -// Callee owns the persistent handle -v8::Persistent<v8::Function> -QQmlExpressionPrivate::evalFunction(QQmlContextData *ctxt, QObject *scope, - const QString &code, const QString &filename, int line, - v8::Persistent<v8::Object> *qmlscope) -{ - QQmlEngine *engine = ctxt->engine; - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine); - - v8::HandleScope handle_scope; - v8::Context::Scope ctxtscope(ep->v8engine()->context()); - - 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()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function compilation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local<v8::Message> message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent<v8::Function>(); - } - v8::Local<v8::Value> result = script->Run(scopeobject); - if (tc.HasCaught()) { - QQmlError error; - error.setDescription(QLatin1String("Exception occurred during function evaluation")); - error.setLine(line); - error.setUrl(QUrl::fromLocalFile(filename)); - v8::Local<v8::Message> message = tc.Message(); - if (!message.IsEmpty()) - QQmlExpressionPrivate::exceptionToError(message, error); - ep->warning(error); - return v8::Persistent<v8::Function>(); - } - if (qmlscope) *qmlscope = qPersistentNew<v8::Object>(scopeobject); - return qPersistentNew<v8::Function>(v8::Local<v8::Function>::Cast(result)); -} - QQmlExpression * QQmlExpressionPrivate::create(QQmlContextData *ctxt, QObject *object, - const QString &expr, bool isRewritten, - const QString &url, int lineNumber, int columnNumber) + const QString &expr, bool isRewritten, + const QString &url, int lineNumber, int columnNumber) { - return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, *new QQmlExpressionPrivate); + return new QQmlExpression(ctxt, object, expr, isRewritten, url, lineNumber, columnNumber, + *new QQmlExpressionPrivate); } /*! @@ -408,24 +284,6 @@ QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, d->init(ctxt, expression, scope); } -/*! - \internal - - To avoid exposing v8 in the public API, functionPtr must be a pointer to a v8::Handle<v8::Function>. - For example: - v8::Handle<v8::Function> function; - new QQmlExpression(ctxt, scope, &function, ...); - */ -QQmlExpression::QQmlExpression(QQmlContextData *ctxt, QObject *scope, void *functionPtr, - QQmlExpressionPrivate &dd) -: QObject(dd, 0) -{ - v8::Handle<v8::Function> function = *(v8::Handle<v8::Function> *)functionPtr; - - Q_D(QQmlExpression); - d->init(ctxt, function, scope); -} - /*! Destroy the QQmlExpression instance. */ @@ -489,217 +347,6 @@ void QQmlExpression::setExpression(const QString &expression) qPersistentDispose(d->v8qmlscope); } -void QQmlExpressionPrivate::exceptionToError(v8::Handle<v8::Message> message, - QQmlError &error) -{ - Q_ASSERT(!message.IsEmpty()); - - v8::Handle<v8::Value> name = message->GetScriptResourceName(); - v8::Handle<v8::String> description = message->Get(); - int lineNumber = message->GetLineNumber(); - - v8::Local<v8::String> file = name->IsString()?name->ToString():v8::Local<v8::String>(); - if (file.IsEmpty() || file->Length() == 0) - error.setUrl(QUrl(QLatin1String("<Unknown File>"))); - else - error.setUrl(QUrl(QV8Engine::toStringStatic(file))); - - error.setLine(lineNumber); - error.setColumn(-1); - - QString qDescription = QV8Engine::toStringStatic(description); - if (qDescription.startsWith(QLatin1String("Uncaught "))) - qDescription = qDescription.mid(9 /* strlen("Uncaught ") */); - - error.setDescription(qDescription); -} - -void QQmlJavaScriptExpression::setNotifyOnValueChanged(bool v) -{ - activeGuards.setFlagValue(v); - if (!v) clearGuards(); -} - -void QQmlJavaScriptExpression::resetNotifyOnValueChanged() -{ - clearGuards(); -} - -v8::Local<v8::Value> -QQmlJavaScriptExpression::evaluate(QQmlContextData *context, - v8::Handle<v8::Function> function, bool *isUndefined) -{ - Q_ASSERT(context && context->engine); - - if (function.IsEmpty() || function->IsUndefined()) { - if (isUndefined) *isUndefined = true; - return v8::Local<v8::Value>(); - } - - QQmlEnginePrivate *ep = QQmlEnginePrivate::get(context->engine); - - Q_ASSERT(notifyOnValueChanged() || activeGuards.isEmpty()); - GuardCapture capture(context->engine, this); - - QQmlEnginePrivate::PropertyCapture *lastPropertyCapture = ep->propertyCapture; - ep->propertyCapture = notifyOnValueChanged()?&capture:0; - - - if (notifyOnValueChanged()) - capture.guards.copyAndClearPrepend(activeGuards); - - QQmlContextData *lastSharedContext = 0; - QObject *lastSharedScope = 0; - - bool sharedContext = useSharedContext(); - - // All code that follows must check with watcher before it accesses data members - // incase we have been deleted. - DeleteWatcher watcher(this); - - if (sharedContext) { - lastSharedContext = ep->sharedContext; - lastSharedScope = ep->sharedScope; - ep->sharedContext = context; - ep->sharedScope = scopeObject(); - } - - 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); - } - - result = function->Call(This, 0, 0); - - 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()) { - QQmlExpressionPrivate::exceptionToError(message, delayedError()->error); - } else { - if (hasDelayedError()) delayedError()->error = QQmlError(); - } - } else { - if (hasDelayedError()) delayedError()->error = QQmlError(); - } - } - - if (sharedContext) { - ep->sharedContext = lastSharedContext; - ep->sharedScope = lastSharedScope; - } - - 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; - } - - while (Guard *g = capture.guards.takeFirst()) - g->Delete(); - - ep->propertyCapture = lastPropertyCapture; - - return result; -} - -void QQmlJavaScriptExpression::GuardCapture::captureProperty(QQmlNotifier *n) -{ - if (expression) { - - // Try and find a matching guard - while (!guards.isEmpty() && !guards.first()->isConnected(n)) - guards.takeFirst()->Delete(); - - Guard *g = 0; - if (!guards.isEmpty()) { - g = guards.takeFirst(); - g->cancelNotify(); - Q_ASSERT(g->isConnected(n)); - } else { - g = Guard::New(expression, engine); - g->connect(n); - } - - expression->activeGuards.prepend(g); - } -} - -void QQmlJavaScriptExpression::GuardCapture::captureProperty(QObject *o, int c, int n) -{ - if (expression) { - if (n == -1) { - if (!errorString) { - errorString = new QStringList; - QString preamble = QLatin1String("QQmlExpression: Expression ") + - expression->m_vtable->expressionIdentifier(expression) + - QLatin1String(" depends on non-NOTIFYable properties:"); - errorString->append(preamble); - } - - 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 { - - // 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, engine); - g->connect(o, n); - } - - expression->activeGuards.prepend(g); - } - } -} - -void QQmlJavaScriptExpression::clearError() -{ - if (m_vtable.hasValue()) { - m_vtable.value().error = QQmlError(); - m_vtable.value().removeError(); - } -} - -QQmlError QQmlJavaScriptExpression::error() const -{ - if (m_vtable.hasValue()) return m_vtable.constValue()->error; - else return QQmlError(); -} - -QQmlDelayedError *QQmlJavaScriptExpression::delayedError() -{ - return &m_vtable.value(); -} - -void QQmlJavaScriptExpression::clearGuards() -{ - while (Guard *g = activeGuards.takeFirst()) - g->Delete(); -} - // Must be called with a valid handle scope v8::Local<v8::Value> QQmlExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined) { @@ -923,60 +570,6 @@ QString QQmlExpressionPrivate::expressionIdentifier(QQmlJavaScriptExpression *e) return QLatin1String("\"") + This->expression + QLatin1String("\""); } -QQmlAbstractExpression::QQmlAbstractExpression() -: m_prevExpression(0), m_nextExpression(0) -{ -} - -QQmlAbstractExpression::~QQmlAbstractExpression() -{ - if (m_prevExpression) { - *m_prevExpression = m_nextExpression; - if (m_nextExpression) - m_nextExpression->m_prevExpression = m_prevExpression; - } - - if (m_context.isT2()) - m_context.asT2()->_s = 0; -} - -QQmlContextData *QQmlAbstractExpression::context() const -{ - if (m_context.isT1()) return m_context.asT1(); - else return m_context.asT2()->_c; -} - -void QQmlAbstractExpression::setContext(QQmlContextData *context) -{ - if (m_prevExpression) { - *m_prevExpression = m_nextExpression; - if (m_nextExpression) - m_nextExpression->m_prevExpression = m_prevExpression; - m_prevExpression = 0; - m_nextExpression = 0; - } - - if (m_context.isT1()) m_context = context; - else m_context.asT2()->_c = context; - - if (context) { - m_nextExpression = context->expressions; - if (m_nextExpression) - m_nextExpression->m_prevExpression = &m_nextExpression; - m_prevExpression = &context->expressions; - context->expressions = this; - } -} - -void QQmlAbstractExpression::refresh() -{ -} - -bool QQmlAbstractExpression::isValid() const -{ - return context() != 0; -} - QT_END_NAMESPACE #include <moc_qqmlexpression.cpp> |