aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/v8/qv8bindings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/v8/qv8bindings.cpp')
-rw-r--r--src/declarative/qml/v8/qv8bindings.cpp235
1 files changed, 235 insertions, 0 deletions
diff --git a/src/declarative/qml/v8/qv8bindings.cpp b/src/declarative/qml/v8/qv8bindings.cpp
new file mode 100644
index 0000000000..424d06f083
--- /dev/null
+++ b/src/declarative/qml/v8/qv8bindings.cpp
@@ -0,0 +1,235 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qv8bindings_p.h"
+
+#include <private/qv8_p.h>
+#include <private/qdeclarativebinding_p.h>
+#include <private/qdeclarativecompiler_p.h>
+#include <private/qdeclarativebinding_p_p.h>
+#include <private/qdeclarativeexpression_p.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8BindingsPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QV8Bindings)
+public:
+ QV8BindingsPrivate();
+
+ struct Binding : public QDeclarativeJavaScriptExpression,
+ public QDeclarativeAbstractBinding {
+ Binding();
+
+ // Inherited from QDeclarativeAbstractBinding
+ virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
+ virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
+ virtual void destroy();
+
+ int index:30;
+ bool enabled:1;
+ bool updating:1;
+ int line;
+ QDeclarativeProperty property;
+ QV8BindingsPrivate *parent;
+ };
+
+ QUrl url;
+ int bindingsCount;
+ Binding *bindings;
+ v8::Persistent<v8::Array> functions;
+};
+
+QV8BindingsPrivate::QV8BindingsPrivate()
+: bindingsCount(0), bindings(0)
+{
+}
+
+QV8BindingsPrivate::Binding::Binding()
+: index(-1), enabled(false), updating(false), line(-1), parent(0)
+{
+}
+
+void QV8BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
+{
+ if (enabled != e) {
+ enabled = e;
+
+ if (e) update(flags);
+ }
+}
+
+void QV8BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
+{
+ if (!enabled)
+ return;
+
+ QDeclarativeContextData *context = QDeclarativeAbstractExpression::context();
+ if (!context || !context->isValid())
+ return;
+
+ if (!updating) {
+ updating = true;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
+
+ bool isUndefined = false;
+
+ QDeclarativeDeleteWatcher watcher(this);
+ ep->referenceScarceResources();
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(ep->v8engine.context());
+ v8::Local<v8::Value> result = evaluate(v8::Handle<v8::Function>::Cast(parent->functions->Get(index)),
+ &isUndefined);
+
+ bool needsErrorData = false;
+ if (!watcher.wasDeleted() && !error.isValid())
+ needsErrorData = !QDeclarativeBindingPrivate::writeBindingResult(this, property, result,
+ isUndefined, flags);
+
+ if (!watcher.wasDeleted()) {
+
+ if (needsErrorData) {
+ QUrl url = QUrl(parent->url);
+ if (url.isEmpty()) url = QUrl(QLatin1String("<Unknown File>"));
+
+ error.setUrl(url);
+ error.setLine(line);
+ error.setColumn(-1);
+ }
+
+ if (error.isValid()) {
+ if (!addError(ep)) ep->warning(error);
+ } else {
+ removeError();
+ }
+
+ updating = false;
+ }
+
+ ep->dereferenceScarceResources();
+
+ } else {
+ QDeclarativeBindingPrivate::printBindingLoopError(property);
+ }
+}
+
+void QV8BindingsPrivate::Binding::destroy()
+{
+ enabled = false;
+ removeFromObject();
+ clear();
+ removeError();
+ parent->q_func()->release();
+}
+
+QV8Bindings::QV8Bindings(const QString &program, int line,
+ QDeclarativeCompiledData *compiled,
+ QDeclarativeContextData *context)
+: QObject(*(new QV8BindingsPrivate))
+{
+ Q_D(QV8Bindings);
+
+ QV8Engine *engine = QDeclarativeEnginePrivate::getV8Engine(context->engine);
+
+ if (compiled->v8bindings.IsEmpty()) {
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
+
+ v8::Local<v8::Script> script = engine->qmlModeCompile(program, compiled->name, line);
+ v8::Local<v8::Value> result = script->Run(engine->contextWrapper()->sharedContext());
+
+ if (result->IsArray())
+ compiled->v8bindings = qPersistentNew(v8::Local<v8::Array>::Cast(result));
+ }
+
+ d->url = compiled->url;
+ d->functions = qPersistentNew(compiled->v8bindings);
+ d->bindingsCount = d->functions->Length();
+ d->bindings = new QV8BindingsPrivate::Binding[d->bindingsCount];
+
+ setContext(context);
+}
+
+QV8Bindings::~QV8Bindings()
+{
+ Q_D(QV8Bindings);
+ qPersistentDispose(d->functions);
+
+ delete [] d->bindings;
+ d->bindings = 0;
+ d->bindingsCount = 0;
+}
+
+QDeclarativeAbstractBinding *QV8Bindings::configBinding(int index, QObject *target, QObject *scope,
+ const QDeclarativeProperty &property, int line)
+{
+ Q_D(QV8Bindings);
+ QV8BindingsPrivate::Binding *rv = d->bindings + index;
+
+ rv->line = line;
+ rv->index = index;
+ rv->property = property;
+ rv->setContext(context());
+ rv->setScopeObject(scope);
+ rv->setUseSharedContext(true);
+ rv->setNotifyOnValueChanged(true);
+ rv->setNotifyObject(this, index);
+ rv->parent = d;
+
+ addref(); // This is decremented in Binding::destroy()
+
+ return rv;
+}
+
+int QV8Bindings::qt_metacall(QMetaObject::Call c, int id, void **)
+{
+ Q_D(QV8Bindings);
+
+ if (c == QMetaObject::InvokeMetaMethod) {
+ QV8BindingsPrivate::Binding *binding = d->bindings + id;
+ binding->update(QDeclarativePropertyPrivate::DontRemoveBinding);
+ }
+ return -1;
+}
+
+QT_END_NAMESPACE