aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/declarative.pro9
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp76
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.h5
-rw-r--r--src/declarative/items/qsgitem.cpp74
-rw-r--r--src/declarative/items/qsgitem.h4
-rw-r--r--src/declarative/qml/qdeclarativebinding.cpp32
-rw-r--r--src/declarative/qml/qdeclarativebinding_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeboundsignal.cpp1
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp13
-rw-r--r--src/declarative/qml/qdeclarativecomponent.cpp119
-rw-r--r--src/declarative/qml/qdeclarativecomponent.h4
-rw-r--r--src/declarative/qml/qdeclarativecomponent_p.h2
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp24
-rw-r--r--src/declarative/qml/qdeclarativecontext.h2
-rw-r--r--src/declarative/qml/qdeclarativecontext_p.h12
-rw-r--r--src/declarative/qml/qdeclarativecontextscriptclass.cpp335
-rw-r--r--src/declarative/qml/qdeclarativedata_p.h11
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp1022
-rw-r--r--src/declarative/qml/qdeclarativeengine.h2
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h93
-rw-r--r--src/declarative/qml/qdeclarativeexpression.cpp245
-rw-r--r--src/declarative/qml/qdeclarativeexpression.h3
-rw-r--r--src/declarative/qml/qdeclarativeexpression_p.h19
-rw-r--r--src/declarative/qml/qdeclarativeglobalscriptclass.cpp147
-rw-r--r--src/declarative/qml/qdeclarativeinclude.cpp310
-rw-r--r--src/declarative/qml/qdeclarativeintegercache.cpp29
-rw-r--r--src/declarative/qml/qdeclarativeintegercache_p.h36
-rw-r--r--src/declarative/qml/qdeclarativelistscriptclass.cpp149
-rw-r--r--src/declarative/qml/qdeclarativemetatype.cpp9
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass.cpp1226
-rw-r--r--src/declarative/qml/qdeclarativeobjectscriptclass_p.h166
-rw-r--r--src/declarative/qml/qdeclarativeproperty.cpp2
-rw-r--r--src/declarative/qml/qdeclarativepropertycache.cpp68
-rw-r--r--src/declarative/qml/qdeclarativepropertycache_p.h52
-rw-r--r--src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp219
-rw-r--r--src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h163
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase.cpp585
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase_p.h8
-rw-r--r--src/declarative/qml/qdeclarativetypeloader.cpp11
-rw-r--r--src/declarative/qml/qdeclarativetypeloader_p.h8
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache.cpp29
-rw-r--r--src/declarative/qml/qdeclarativetypenamecache_p.h38
-rw-r--r--src/declarative/qml/qdeclarativetypenamescriptclass.cpp195
-rw-r--r--src/declarative/qml/qdeclarativevaluetypescriptclass.cpp242
-rw-r--r--src/declarative/qml/qdeclarativevme.cpp84
-rw-r--r--src/declarative/qml/qdeclarativevme_p.h5
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp71
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject_p.h13
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp409
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript_p.h8
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest.cpp1392
-rw-r--r--src/declarative/qml/qdeclarativexmlhttprequest_p.h6
-rw-r--r--src/declarative/qml/qintrusivelist_p.h7
-rw-r--r--src/declarative/qml/qml.pri17
-rw-r--r--src/declarative/qml/v4/qdeclarativev4bindings.cpp3
-rw-r--r--src/declarative/qml/v4/qdeclarativev4irbuilder.cpp3
-rw-r--r--src/declarative/qml/v8/notes.txt4
-rw-r--r--src/declarative/qml/v8/qhashedstring.cpp103
-rw-r--r--src/declarative/qml/v8/qhashedstring_p.h572
-rw-r--r--src/declarative/qml/v8/qv8_p.h1
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper.cpp425
-rw-r--r--src/declarative/qml/v8/qv8contextwrapper_p.h (renamed from src/declarative/qml/qdeclarativecontextscriptclass_p.h)73
-rw-r--r--src/declarative/qml/v8/qv8engine.cpp1423
-rw-r--r--src/declarative/qml/v8/qv8engine_p.h348
-rw-r--r--src/declarative/qml/v8/qv8include.cpp243
-rw-r--r--src/declarative/qml/v8/qv8include_p.h (renamed from src/declarative/qml/qdeclarativeinclude_p.h)48
-rw-r--r--src/declarative/qml/v8/qv8listwrapper.cpp178
-rw-r--r--src/declarative/qml/v8/qv8listwrapper_p.h96
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper.cpp1714
-rw-r--r--src/declarative/qml/v8/qv8qobjectwrapper_p.h121
-rw-r--r--src/declarative/qml/v8/qv8stringwrapper.cpp94
-rw-r--r--src/declarative/qml/v8/qv8stringwrapper_p.h (renamed from src/declarative/qml/qdeclarativeglobalscriptclass_p.h)34
-rw-r--r--src/declarative/qml/v8/qv8typewrapper.cpp211
-rw-r--r--src/declarative/qml/v8/qv8typewrapper_p.h (renamed from src/declarative/qml/qdeclarativetypenamescriptclass_p.h)47
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper.cpp289
-rw-r--r--src/declarative/qml/v8/qv8valuetypewrapper_p.h (renamed from src/declarative/qml/qdeclarativevaluetypescriptclass_p.h)46
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper.cpp190
-rw-r--r--src/declarative/qml/v8/qv8variantwrapper_p.h101
-rw-r--r--src/declarative/qml/v8/qv8worker.cpp322
-rw-r--r--src/declarative/qml/v8/qv8worker_p.h (renamed from src/declarative/qml/qdeclarativelistscriptclass_p.h)34
-rw-r--r--src/declarative/qml/v8/v8.pri32
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp2
82 files changed, 8601 insertions, 5969 deletions
diff --git a/src/declarative/declarative.pro b/src/declarative/declarative.pro
index 0a1f76a251..354b5b6577 100644
--- a/src/declarative/declarative.pro
+++ b/src/declarative/declarative.pro
@@ -49,3 +49,12 @@ linux-g++-maemo:DEFINES += QDECLARATIVEVIEW_NOBACKGROUND
DEFINES += QT_NO_OPENTYPE
INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src
+
+macx:CONFIG(debug, debug|release) {
+ LIBS += -L../v8/ -lv8_debug
+} else {
+ LIBS += -L../v8/ -lv8
+}
+
+# Prevent qmake adding v8 as a dependency
+CONFIG -= explicitlib
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index d3132deced..97014032e0 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -63,6 +63,8 @@
#include <QtGui/qgraphicstransform.h>
#include <qlistmodelinterface_p.h>
+#include <private/qv8engine_p.h>
+
#include <float.h>
QT_BEGIN_NAMESPACE
@@ -2653,20 +2655,33 @@ void QDeclarativeItem::setKeepMouseGrab(bool keep)
If \a item is a \c null value, this maps the point from the coordinate
system of the root QML view.
*/
-QScriptValue QDeclarativeItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const
+void QDeclarativeItem::mapFromItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
- // If QGraphicsItem::mapFromItem() is called with 0, behaves the same as mapFromScene()
- QPointF p = qobject_cast<QGraphicsItem*>(this)->mapFromItem(itemObj, x, y);
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QDeclarativeItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QDeclarativeItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
+
+ QPointF p = QGraphicsItem::mapFromItem(itemObj, x, y);
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
/*!
@@ -2679,20 +2694,33 @@ QScriptValue QDeclarativeItem::mapFromItem(const QScriptValue &item, qreal x, qr
If \a item is a \c null value, this maps \a x and \a y to the coordinate
system of the root QML view.
*/
-QScriptValue QDeclarativeItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const
+void QDeclarativeItem::mapToItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QDeclarativeItem *itemObj = qobject_cast<QDeclarativeItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QDeclarativeItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QDeclarativeItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
- // If QGraphicsItem::mapToItem() is called with 0, behaves the same as mapToScene()
- QPointF p = qobject_cast<QGraphicsItem*>(this)->mapToItem(itemObj, x, y);
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QPointF p = QGraphicsItem::mapToItem(itemObj, x, y);
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
/*!
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h
index 839b934903..90328fef24 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.h
+++ b/src/declarative/graphicsitems/qdeclarativeitem.h
@@ -64,6 +64,7 @@ class QDeclarativeTransition;
class QDeclarativeKeyEvent;
class QDeclarativeAnchors;
class QDeclarativeItemPrivate;
+class QDeclarativeV8Function;
class Q_DECLARATIVE_EXPORT QDeclarativeItem : public QGraphicsObject, public QDeclarativeParserStatus
{
Q_OBJECT
@@ -149,8 +150,8 @@ public:
bool keepMouseGrab() const;
void setKeepMouseGrab(bool);
- Q_INVOKABLE QScriptValue mapFromItem(const QScriptValue &item, qreal x, qreal y) const;
- Q_INVOKABLE QScriptValue mapToItem(const QScriptValue &item, qreal x, qreal y) const;
+ Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
Q_INVOKABLE void forceActiveFocus();
Q_INVOKABLE QDeclarativeItem *childAt(qreal x, qreal y) const;
diff --git a/src/declarative/items/qsgitem.cpp b/src/declarative/items/qsgitem.cpp
index f2d26955aa..bb3ad8a2ca 100644
--- a/src/declarative/items/qsgitem.cpp
+++ b/src/declarative/items/qsgitem.cpp
@@ -1817,20 +1817,33 @@ void QSGItem::polish()
}
}
-QScriptValue QSGItem::mapFromItem(const QScriptValue &item, qreal x, qreal y) const
+void QSGItem::mapFromItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QSGItem *itemObj = qobject_cast<QSGItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapFromItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QSGItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QSGItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapFromItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
- // If QSGItem::mapFromItem() is called with 0, behaves the same as mapFromScene()
- QPointF p = mapFromItem(itemObj, QPointF(x, y));
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QPointF p = mapFromItem(itemObj, QPointF(x, y));
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
@@ -1847,20 +1860,33 @@ QTransform QSGItem::itemTransform(QSGItem *other, bool *ok) const
return t;
}
-QScriptValue QSGItem::mapToItem(const QScriptValue &item, qreal x, qreal y) const
+void QSGItem::mapToItem(QDeclarativeV8Function *args) const
{
- QScriptValue sv = QDeclarativeEnginePrivate::getScriptEngine(qmlEngine(this))->newObject();
- QSGItem *itemObj = qobject_cast<QSGItem*>(item.toQObject());
- if (!itemObj && !item.isNull()) {
- qmlInfo(this) << "mapToItem() given argument \"" << item.toString() << "\" which is neither null nor an Item";
- return 0;
- }
+ if (args->Length() != 0) {
+ v8::Local<v8::Value> item = (*args)[0];
+ QV8Engine *engine = args->engine();
+
+ QSGItem *itemObj = 0;
+ if (!item->IsNull())
+ itemObj = qobject_cast<QSGItem*>(engine->toQObject(item));
+
+ if (!itemObj && !item->IsNull()) {
+ qmlInfo(this) << "mapToItem() given argument \"" << engine->toString(item->ToString())
+ << "\" which is neither null nor an Item";
+ return;
+ }
+
+ v8::Local<v8::Object> rv = v8::Object::New();
+ args->returnValue(rv);
+
+ qreal x = (args->Length() > 1)?(*args)[1]->NumberValue():0;
+ qreal y = (args->Length() > 2)?(*args)[2]->NumberValue():0;
- // If QSGItem::mapToItem() is called with 0, behaves the same as mapToScene()
- QPointF p = mapToItem(itemObj, QPointF(x, y));
- sv.setProperty(QLatin1String("x"), p.x());
- sv.setProperty(QLatin1String("y"), p.y());
- return sv;
+ QPointF p = mapToItem(itemObj, QPointF(x, y));
+
+ rv->Set(v8::String::New("x"), v8::Number::New(p.x()));
+ rv->Set(v8::String::New("y"), v8::Number::New(p.y()));
+ }
}
void QSGItem::forceActiveFocus()
diff --git a/src/declarative/items/qsgitem.h b/src/declarative/items/qsgitem.h
index 564d819000..a4420b2af5 100644
--- a/src/declarative/items/qsgitem.h
+++ b/src/declarative/items/qsgitem.h
@@ -287,8 +287,8 @@ public:
void polish();
- Q_INVOKABLE QScriptValue mapFromItem(const QScriptValue &item, qreal x, qreal y) const;
- Q_INVOKABLE QScriptValue mapToItem(const QScriptValue &item, qreal x, qreal y) const;
+ Q_INVOKABLE void mapFromItem(QDeclarativeV8Function*) const;
+ Q_INVOKABLE void mapToItem(QDeclarativeV8Function*) const;
Q_INVOKABLE void forceActiveFocus();
Q_INVOKABLE QSGItem *childAt(qreal x, qreal y) const;
diff --git a/src/declarative/qml/qdeclarativebinding.cpp b/src/declarative/qml/qdeclarativebinding.cpp
index 3e93ce7266..02cdb2eb47 100644
--- a/src/declarative/qml/qdeclarativebinding.cpp
+++ b/src/declarative/qml/qdeclarativebinding.cpp
@@ -274,8 +274,17 @@ QDeclarativeBinding::QDeclarativeBinding(const QString &str, QObject *obj, QDecl
setNotifyOnValueChanged(true);
}
-QDeclarativeBinding::QDeclarativeBinding(const QScriptValue &func, QObject *obj, QDeclarativeContextData *ctxt, QObject *parent)
-: QDeclarativeExpression(ctxt, obj, func, *new QDeclarativeBindingPrivate)
+/*!
+ \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 QDeclarativeBInding(&function, scope, ctxt);
+ */
+QDeclarativeBinding::QDeclarativeBinding(void *functionPtr, QObject *obj, QDeclarativeContextData *ctxt,
+ QObject *parent)
+: QDeclarativeExpression(ctxt, obj, functionPtr, *new QDeclarativeBindingPrivate)
{
setParent(parent);
setNotifyOnValueChanged(true);
@@ -362,25 +371,28 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
bool isUndefined = false;
QVariant value;
- QScriptValue scriptValue = d->scriptValue(0, &isUndefined);
+ v8::HandleScope handle_scope;
+ v8::Local<v8::Value> result = d->v8value(0, &isUndefined);
if (wasDeleted) {
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
return;
}
- if (d->property.propertyTypeCategory() == QDeclarativeProperty::List) {
- value = ep->scriptValueToVariant(scriptValue, qMetaTypeId<QList<QObject *> >());
- } else if (scriptValue.isNull() &&
- d->property.propertyTypeCategory() == QDeclarativeProperty::Object) {
+ 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->scriptValueToVariant(scriptValue, d->property.propertyType());
+ value = ep->v8engine.toVariant(result, d->property.propertyType());
if (value.userType() == QMetaType::QObjectStar && !qvariant_cast<QObject*>(value)) {
// If the object is null, we extract the predicted type. While this isn't
// 100% reliable, in many cases it gives us better error messages if we
// assign this null-object to an incompatible property
- int type = ep->objectClass->objectType(scriptValue);
+ // XXX aakenned
+ // int type = ep->objectClass->objectType(scriptValue);
+ int type = QMetaType::QObjectStar;
QObject *o = 0;
value = QVariant(type, (void *)&o);
}
@@ -410,7 +422,7 @@ void QDeclarativeBinding::update(QDeclarativePropertyPrivate::WriteFlags flags)
QLatin1String(QMetaType::typeName(d->property.propertyType())) +
QLatin1String(" ") + d->property.name());
- } else if (!scriptValue.isRegExp() && scriptValue.isFunction()) {
+ } else if (result->IsFunction()) {
QUrl url = QUrl(d->url);
int line = d->line;
diff --git a/src/declarative/qml/qdeclarativebinding_p.h b/src/declarative/qml/qdeclarativebinding_p.h
index 0260b95fb8..d723ade7b7 100644
--- a/src/declarative/qml/qdeclarativebinding_p.h
+++ b/src/declarative/qml/qdeclarativebinding_p.h
@@ -154,7 +154,7 @@ public:
QDeclarativeBinding(const QString &, QObject *, QDeclarativeContextData *, QObject *parent=0);
QDeclarativeBinding(void *, QDeclarativeRefCount *, QObject *, QDeclarativeContextData *,
const QString &, int, QObject *parent);
- QDeclarativeBinding(const QScriptValue &, QObject *, QDeclarativeContextData *, QObject *parent=0);
+ QDeclarativeBinding(void *, QObject *, QDeclarativeContextData *, QObject *parent=0);
void setTarget(const QDeclarativeProperty &);
QDeclarativeProperty property() const;
diff --git a/src/declarative/qml/qdeclarativeboundsignal.cpp b/src/declarative/qml/qdeclarativeboundsignal.cpp
index 47a15cb0ce..cedc5d55fa 100644
--- a/src/declarative/qml/qdeclarativeboundsignal.cpp
+++ b/src/declarative/qml/qdeclarativeboundsignal.cpp
@@ -227,7 +227,6 @@ QDeclarativeBoundSignalParameters::QDeclarativeBoundSignalParameters(const QMeta
} else {
QByteArray propType = type;
if (t >= QVariant::UserType || t == QVariant::Invalid) {
- //copy of QDeclarativeObjectScriptClass::enumType()
QByteArray scope;
QByteArray name;
int scopeIdx = propType.lastIndexOf("::");
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index 3a686be9ec..21343b6567 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -64,7 +64,6 @@
#include "private/qdeclarativescriptparser_p.h"
#include "private/qdeclarativebinding_p.h"
#include "private/qdeclarativev4compiler_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include <QColor>
#include <QDebug>
@@ -2253,7 +2252,7 @@ bool QDeclarativeCompiler::testQualifiedEnumAssignment(const QMetaProperty &prop
}
} else {
// Otherwise we have to search the whole type
- // This matches the logic in QDeclarativeTypeNameScriptClass
+ // This matches the logic in QV8TypeWrapper
QByteArray enumName = enumValue.toUtf8();
const QMetaObject *metaObject = type->baseMetaObject();
for (int ii = metaObject->enumeratorCount() - 1; value == -1 && ii >= 0; --ii) {
@@ -2358,7 +2357,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
if (propName.at(0).isUpper())
COMPILE_EXCEPTION(&prop, tr("Property names cannot begin with an upper case letter"));
- if (enginePrivate->globalClass->illegalNames().contains(propName))
+ if (enginePrivate->v8engine.illegalNames().contains(propName))
COMPILE_EXCEPTION(&prop, tr("Illegal property name"));
propNames.insert(prop.name);
@@ -2371,7 +2370,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
COMPILE_EXCEPTION(obj, tr("Signal names cannot begin with an upper case letter"));
- if (enginePrivate->globalClass->illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine.illegalNames().contains(nameStr))
COMPILE_EXCEPTION(obj, tr("Illegal signal name"));
methodNames.insert(name);
}
@@ -2382,7 +2381,7 @@ bool QDeclarativeCompiler::checkDynamicMeta(QDeclarativeParser::Object *obj)
QString nameStr = QString::fromUtf8(name);
if (nameStr.at(0).isUpper())
COMPILE_EXCEPTION(obj, tr("Method names cannot begin with an upper case letter"));
- if (enginePrivate->globalClass->illegalNames().contains(nameStr))
+ if (enginePrivate->v8engine.illegalNames().contains(nameStr))
COMPILE_EXCEPTION(obj, tr("Illegal method name"));
methodNames.insert(name);
}
@@ -2676,7 +2675,7 @@ bool QDeclarativeCompiler::checkValidId(QDeclarativeParser::Value *v, const QStr
}
- if (enginePrivate->globalClass->illegalNames().contains(val))
+ if (enginePrivate->v8engine.illegalNames().contains(val))
COMPILE_EXCEPTION(v, tr( "ID illegally masks global JavaScript property"));
return true;
@@ -2877,7 +2876,7 @@ int QDeclarativeCompiler::genContextCache()
if (compileState.ids.count() == 0)
return -1;
- QDeclarativeIntegerCache *cache = new QDeclarativeIntegerCache(engine);
+ QDeclarativeIntegerCache *cache = new QDeclarativeIntegerCache();
for (QHash<QString, QDeclarativeParser::Object *>::ConstIterator iter = compileState.ids.begin();
iter != compileState.ids.end();
diff --git a/src/declarative/qml/qdeclarativecomponent.cpp b/src/declarative/qml/qdeclarativecomponent.cpp
index 7126746078..b5704d17c7 100644
--- a/src/declarative/qml/qdeclarativecomponent.cpp
+++ b/src/declarative/qml/qdeclarativecomponent.cpp
@@ -660,49 +660,50 @@ QDeclarativeComponent::QDeclarativeComponent(QDeclarativeComponentPrivate &dd, Q
Sets graphics object parent because forgetting to do this is a frequent
and serious problem.
*/
-QScriptValue QDeclarativeComponent::createObject(QObject* parent)
+void QDeclarativeComponent::createObject(QDeclarativeV8Function *args)
{
- Q_D(QDeclarativeComponent);
- return d->createObject(parent, QScriptValue(QScriptValue::NullValue));
-}
+ Q_ASSERT(args);
+
+#define RETURN(result) { args->returnValue((result)); return; }
-/*!
- \internal
- Overloadable method allows properties to be set during creation
-*/
-QScriptValue QDeclarativeComponent::createObject(QObject* parent, const QScriptValue& valuemap)
-{
Q_D(QDeclarativeComponent);
- if (!valuemap.isObject() || valuemap.isArray()) {
- qmlInfo(this) << tr("createObject: value is not an object");
- return QScriptValue(QScriptValue::NullValue);
+ Q_ASSERT(d->engine);
+
+ QDeclarativeEngine *engine = d->engine;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
+ QV8Engine *v8engine = &ep->v8engine;
+
+ QDeclarativeContext *ctxt = creationContext();
+ if (!ctxt) ctxt = engine->rootContext();
+
+ v8::Local<v8::Object> valuemap;
+ if (args->Length() >= 2) {
+ v8::Local<v8::Value> v = (*args)[1];
+ if (!v->IsObject() || v->IsArray()) {
+ qmlInfo(this) << tr("createObject: value is not an object");
+ RETURN(v8::Null());
+ }
+ valuemap = v8::Local<v8::Object>::Cast(v);
}
- return d->createObject(parent, valuemap);
-}
-QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, const QScriptValue valuemap)
-{
- Q_Q(QDeclarativeComponent);
- QDeclarativeContext* ctxt = q->creationContext();
- if(!ctxt && engine)
- ctxt = engine->rootContext();
- if (!ctxt)
- return QScriptValue(QScriptValue::NullValue);
- QObject* ret = q->beginCreate(ctxt);
+ QObject *parent = args->Length()?v8engine->toQObject((*args)[0]):0;
+
+ QObject *ret = beginCreate(ctxt);
if (!ret) {
- q->completeCreate();
- return QScriptValue(QScriptValue::NullValue);
+ completeCreate();
+ RETURN(v8::Null());
}
- if (publicParent) {
- ret->setParent(publicParent);
+ if (parent) {
+ ret->setParent(parent);
+
QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
bool needParent = false;
for (int ii = 0; ii < functions.count(); ++ii) {
- QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, publicParent);
+ QDeclarativePrivate::AutoParentResult res = functions.at(ii)(ret, parent);
if (res == QDeclarativePrivate::Parented) {
needParent = false;
break;
@@ -715,37 +716,41 @@ QScriptValue QDeclarativeComponentPrivate::createObject(QObject *publicParent, c
qWarning("QDeclarativeComponent: Created graphical object was not placed in the graphics scene.");
}
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
- QDeclarativeData::get(ret, true)->setImplicitDestructible();
- QScriptValue newObject = priv->objectClass->newQObject(ret, QMetaType::QObjectStar);
-
- if (valuemap.isObject() && !valuemap.isArray()) {
- //Iterate through and assign properties
- QScriptValueIterator it(valuemap);
- while (it.hasNext()) {
- it.next();
- QScriptValue prop = newObject;
- QString propName = it.name();
- int index = propName.indexOf(QLatin1Char('.'));
- if (index > 0) {
- QString subProp = propName;
- int lastIndex = 0;
- while (index > 0) {
- subProp = propName.mid(lastIndex, index - lastIndex);
- prop = prop.property(subProp);
- lastIndex = index + 1;
- index = propName.indexOf(QLatin1Char('.'), index + 1);
- }
- prop.setProperty(propName.mid(propName.lastIndexOf(QLatin1Char('.')) + 1), it.value());
- } else {
- newObject.setProperty(propName, it.value());
- }
- }
+ v8::Handle<v8::Value> ov = v8engine->newQObject(ret);
+ Q_ASSERT(ov->IsObject());
+ v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(ov);
+
+ if (!valuemap.IsEmpty()) {
+
+#define SET_ARGS_SOURCE \
+ "(function(object, values) {"\
+ "try {"\
+ "for(var property in values) {"\
+ "try {"\
+ "var properties = property.split(\".\");"\
+ "var o = object;"\
+ "for (var ii = 0; ii < properties.length - 1; ++ii) {"\
+ "o = o[properties[ii]];"\
+ "}"\
+ "o[properties[properties.length - 1]] = values[property];"\
+ "} catch(e) {}"\
+ "}"\
+ "} catch(e) {}"\
+ "})"
+
+ v8::Local<v8::Script> script = v8engine->qmlModeCompile(SET_ARGS_SOURCE);
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(script->Run(args->qmlGlobal()));
+
+ // Try catch isn't needed as the function itself is loaded with try/catch
+ v8::Handle<v8::Value> args[] = { object, valuemap };
+ function->Call(v8engine->global(), 2, args);
}
- q->completeCreate();
+ completeCreate();
+
+ RETURN(object);
- return newObject;
+#undef RETURN
}
/*!
diff --git a/src/declarative/qml/qdeclarativecomponent.h b/src/declarative/qml/qdeclarativecomponent.h
index 6c05881f52..b9cc74d37c 100644
--- a/src/declarative/qml/qdeclarativecomponent.h
+++ b/src/declarative/qml/qdeclarativecomponent.h
@@ -60,6 +60,7 @@ class QByteArray;
class QDeclarativeComponentPrivate;
class QDeclarativeEngine;
class QDeclarativeComponentAttached;
+class QDeclarativeV8Function;
class Q_DECLARATIVE_EXPORT QDeclarativeComponent : public QObject
{
Q_OBJECT
@@ -110,8 +111,7 @@ Q_SIGNALS:
protected:
QDeclarativeComponent(QDeclarativeComponentPrivate &dd, QObject* parent);
- Q_INVOKABLE QScriptValue createObject(QObject* parent);
- Q_INVOKABLE Q_REVISION(1) QScriptValue createObject(QObject* parent, const QScriptValue& valuemap); //XXX Versioning
+ Q_INVOKABLE void createObject(QDeclarativeV8Function *);
private:
QDeclarativeComponent(QDeclarativeEngine *, QDeclarativeCompiledData *, int, QObject *parent);
diff --git a/src/declarative/qml/qdeclarativecomponent_p.h b/src/declarative/qml/qdeclarativecomponent_p.h
index 9bfbba94e2..f5bbd20ef3 100644
--- a/src/declarative/qml/qdeclarativecomponent_p.h
+++ b/src/declarative/qml/qdeclarativecomponent_p.h
@@ -115,8 +115,6 @@ public:
ConstructionState *state);
static void complete(QDeclarativeEnginePrivate *enginePriv, ConstructionState *state);
- QScriptValue createObject(QObject *publicParent, const QScriptValue valuemap);
-
QDeclarativeEngine *engine;
QDeclarativeGuardedContextData creationContext;
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index 4f0d704d95..1083409511 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -47,7 +47,6 @@
#include "private/qdeclarativeengine_p.h"
#include "qdeclarativeengine.h"
#include "qdeclarativeinfo.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include "private/qdeclarativev4bindings_p.h"
#include <qscriptengine.h>
@@ -313,7 +312,7 @@ void QDeclarativeContext::setContextProperty(const QString &name, const QVariant
}
}
- if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
+ if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache();
int idx = data->propertyNames->value(name);
if (idx == -1) {
@@ -350,7 +349,7 @@ void QDeclarativeContext::setContextProperty(const QString &name, QObject *value
return;
}
- if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache(data->engine);
+ if (!data->propertyNames) data->propertyNames = new QDeclarativeIntegerCache();
int idx = data->propertyNames->value(name);
if (idx == -1) {
@@ -498,18 +497,18 @@ QObject *QDeclarativeContextPrivate::context_at(QDeclarativeListProperty<QObject
QDeclarativeContextData::QDeclarativeContextData()
-: parent(0), engine(0), isInternal(false), ownedByParent(false), publicContext(0), propertyNames(0), contextObject(0),
- imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
- contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
- componentAttached(0)
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), publicContext(0),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0),
+ linkedContext(0), componentAttached(0)
{
}
QDeclarativeContextData::QDeclarativeContextData(QDeclarativeContext *ctxt)
-: parent(0), engine(0), isInternal(false), ownedByParent(false), publicContext(ctxt), propertyNames(0), contextObject(0),
- imports(0), childContexts(0), nextChild(0), prevChild(0), expressions(0), contextObjects(0),
- contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0), linkedContext(0),
- componentAttached(0)
+: parent(0), engine(0), isInternal(false), ownedByParent(false), isJSContext(false), publicContext(ctxt),
+ propertyNames(0), contextObject(0), imports(0), childContexts(0), nextChild(0), prevChild(0),
+ expressions(0), contextObjects(0), contextGuards(0), idValues(0), idValueCount(0), optimizedBindings(0),
+ linkedContext(0), componentAttached(0)
{
}
@@ -611,6 +610,9 @@ void QDeclarativeContextData::destroy()
if (optimizedBindings)
optimizedBindings->release();
+ for (int ii = 0; ii < importedScripts.count(); ++ii)
+ importedScripts[ii].Dispose();
+
delete [] idValues;
if (isInternal)
diff --git a/src/declarative/qml/qdeclarativecontext.h b/src/declarative/qml/qdeclarativecontext.h
index 66daca959d..21e1fc30de 100644
--- a/src/declarative/qml/qdeclarativecontext.h
+++ b/src/declarative/qml/qdeclarativecontext.h
@@ -94,8 +94,6 @@ private:
friend class QDeclarativeEnginePrivate;
friend class QDeclarativeExpression;
friend class QDeclarativeExpressionPrivate;
- friend class QDeclarativeContextScriptClass;
- friend class QDeclarativeObjectScriptClass;
friend class QDeclarativeComponent;
friend class QDeclarativeComponentPrivate;
friend class QDeclarativeScriptPrivate;
diff --git a/src/declarative/qml/qdeclarativecontext_p.h b/src/declarative/qml/qdeclarativecontext_p.h
index 29ca091fc2..11a4f1407b 100644
--- a/src/declarative/qml/qdeclarativecontext_p.h
+++ b/src/declarative/qml/qdeclarativecontext_p.h
@@ -69,6 +69,8 @@
#include <private/qobject_p.h>
#include "private/qdeclarativeguard_p.h"
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeContext;
@@ -137,7 +139,8 @@ public:
QDeclarativeContextPrivate *asQDeclarativeContextPrivate();
quint32 isInternal:1;
quint32 ownedByParent:1; // unrelated to isInternal; parent context deletes children if true.
- quint32 dummy:30;
+ quint32 isJSContext:1;
+ quint32 dummy:29;
QDeclarativeContext *publicContext;
// Property name cache
@@ -147,7 +150,9 @@ public:
QObject *contextObject;
// Any script blocks that exist on this context
- QList<QScriptValue> importedScripts;
+ // XXX aakenned
+ QList<v8::Persistent<v8::Object> > importedScripts;
+// QList<QScriptValue> importedScripts;
// Context base url
QUrl url;
@@ -216,9 +221,10 @@ public:
inline QDeclarativeGuardedContextData(QDeclarativeContextData *);
inline ~QDeclarativeGuardedContextData();
+ inline QDeclarativeContextData *contextData();
inline void setContextData(QDeclarativeContextData *);
- inline QDeclarativeContextData *contextData();
+ inline bool isNull() const { return !m_contextData; }
inline operator QDeclarativeContextData*() const { return m_contextData; }
inline QDeclarativeContextData* operator->() const { return m_contextData; }
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass.cpp b/src/declarative/qml/qdeclarativecontextscriptclass.cpp
deleted file mode 100644
index 3abd78794a..0000000000
--- a/src/declarative/qml/qdeclarativecontextscriptclass.cpp
+++ /dev/null
@@ -1,335 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativecontextscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativeguard_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct ContextData : public QScriptDeclarativeClass::Object {
- ContextData() : overrideObject(0), isSharedContext(true) {}
- ContextData(QDeclarativeContextData *c, QObject *o)
- : context(c), scopeObject(o), overrideObject(0), isSharedContext(false), isUrlContext(false) {}
- QDeclarativeGuardedContextData context;
- QDeclarativeGuard<QObject> scopeObject;
- QObject *overrideObject;
- bool isSharedContext:1;
- bool isUrlContext:1;
-
- QDeclarativeContextData *getContext(QDeclarativeEngine *engine) {
- if (isSharedContext) {
- return QDeclarativeEnginePrivate::get(engine)->sharedContext;
- } else {
- return context.contextData();
- }
- }
-
- QObject *getScope(QDeclarativeEngine *engine) {
- if (isSharedContext) {
- return QDeclarativeEnginePrivate::get(engine)->sharedScope;
- } else {
- return scopeObject.data();
- }
- }
-};
-
-struct UrlContextData : public ContextData {
- UrlContextData(QDeclarativeContextData *c, QObject *o, const QString &u)
- : ContextData(c, o), url(u) {
- isUrlContext = true;
- }
- UrlContextData(const QString &u)
- : ContextData(0, 0), url(u) {
- isUrlContext = true;
- }
- QString url;
-};
-
-/*
- The QDeclarativeContextScriptClass handles property access for a QDeclarativeContext
- via QtScript.
- */
-QDeclarativeContextScriptClass::QDeclarativeContextScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine),
- lastScopeObject(0), lastContext(0), lastData(0), lastPropertyIndex(-1)
-{
-}
-
-QDeclarativeContextScriptClass::~QDeclarativeContextScriptClass()
-{
-}
-
-QScriptValue QDeclarativeContextScriptClass::newContext(QDeclarativeContextData *context, QObject *scopeObject)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new ContextData(context, scopeObject));
-}
-
-QScriptValue QDeclarativeContextScriptClass::newUrlContext(QDeclarativeContextData *context, QObject *scopeObject,
- const QString &url)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new UrlContextData(context, scopeObject, url));
-}
-
-QScriptValue QDeclarativeContextScriptClass::newUrlContext(const QString &url)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new UrlContextData(url));
-}
-
-QScriptValue QDeclarativeContextScriptClass::newSharedContext()
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new ContextData());
-}
-
-QDeclarativeContextData *QDeclarativeContextScriptClass::contextFromValue(const QScriptValue &v)
-{
- if (scriptClass(v) != this)
- return 0;
-
- ContextData *data = (ContextData *)object(v);
- return data->getContext(engine);
-}
-
-QUrl QDeclarativeContextScriptClass::urlFromValue(const QScriptValue &v)
-{
- if (scriptClass(v) != this)
- return QUrl();
-
- ContextData *data = (ContextData *)object(v);
- if (data->isUrlContext) {
- return QUrl(static_cast<UrlContextData *>(data)->url);
- } else {
- return QUrl();
- }
-}
-
-QObject *QDeclarativeContextScriptClass::setOverrideObject(QScriptValue &v, QObject *override)
-{
- if (scriptClass(v) != this)
- return 0;
-
- ContextData *data = (ContextData *)object(v);
- QObject *rv = data->overrideObject;
- data->overrideObject = override;
- return rv;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeContextScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
-
- lastScopeObject = 0;
- lastContext = 0;
- lastData = 0;
- lastPropertyIndex = -1;
-
- QDeclarativeContextData *bindContext = ((ContextData *)object)->getContext(engine);
- QObject *scopeObject = ((ContextData *)object)->getScope(engine);
- if (!bindContext)
- return 0;
-
- QObject *overrideObject = ((ContextData *)object)->overrideObject;
- if (overrideObject) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(overrideObject, name, flags, bindContext,
- QDeclarativeObjectScriptClass::ImplicitObject |
- QDeclarativeObjectScriptClass::SkipAttachedProperties);
- if (rv) {
- lastScopeObject = overrideObject;
- lastContext = bindContext;
- return rv;
- }
- }
-
- bool includeTypes = true;
- while (bindContext) {
- QScriptClass::QueryFlags rv =
- queryProperty(bindContext, scopeObject, name, flags, includeTypes);
- scopeObject = 0; // Only applies to the first context
- includeTypes = false; // Only applies to the first context
- if (rv) return rv;
- bindContext = bindContext->parent;
- }
-
- return 0;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeContextScriptClass::queryProperty(QDeclarativeContextData *bindContext, QObject *scopeObject,
- const Identifier &name,
- QScriptClass::QueryFlags flags,
- bool includeTypes)
-{
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- lastPropertyIndex = bindContext->propertyNames?bindContext->propertyNames->value(name):-1;
- if (lastPropertyIndex != -1) {
- lastContext = bindContext;
- return QScriptClass::HandlesReadAccess;
- }
-
- if (includeTypes && bindContext->imports) {
- QDeclarativeTypeNameCache::Data *data = bindContext->imports->data(name);
-
- if (data) {
- lastData = data;
- lastContext = bindContext;
- lastScopeObject = scopeObject;
- return QScriptClass::HandlesReadAccess;
- }
- }
-
- if (scopeObject) {
- QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(scopeObject, name, flags, bindContext,
- QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
- if (rv) {
- lastScopeObject = scopeObject;
- lastContext = bindContext;
- return rv;
- }
- }
-
- if (bindContext->contextObject) {
- QScriptClass::QueryFlags rv =
- ep->objectClass->queryProperty(bindContext->contextObject, name, flags, bindContext,
- QDeclarativeObjectScriptClass::ImplicitObject | QDeclarativeObjectScriptClass::SkipAttachedProperties);
-
- if (rv) {
- lastScopeObject = bindContext->contextObject;
- lastContext = bindContext;
- return rv;
- }
- }
-
- return 0;
-}
-
-QDeclarativeContextScriptClass::Value
-QDeclarativeContextScriptClass::property(Object *object, const Identifier &name)
-{
- Q_UNUSED(object);
-
- QDeclarativeContextData *bindContext = lastContext;
- Q_ASSERT(bindContext);
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (lastData) {
-
- if (lastData->type) {
- return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->type));
- } else if (lastData->typeNamespace) {
- return Value(scriptEngine, ep->typeNameClass->newObject(lastScopeObject, lastData->typeNamespace));
- } else {
- int index = lastData->importedScriptIndex;
- if (index < bindContext->importedScripts.count()) {
- return Value(scriptEngine, bindContext->importedScripts.at(index));
- } else {
- return Value();
- }
- }
-
- } else if (lastScopeObject) {
-
- return ep->objectClass->property(lastScopeObject, name);
-
- } else if (lastPropertyIndex != -1) {
-
- QScriptValue rv;
- if (lastPropertyIndex < bindContext->idValueCount) {
- rv = ep->objectClass->newQObject(bindContext->idValues[lastPropertyIndex].data());
-
- if (ep->captureProperties)
- ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(&bindContext->idValues[lastPropertyIndex].bindings);
- } else {
- QDeclarativeContextPrivate *cp = bindContext->asQDeclarativeContextPrivate();
- const QVariant &value = cp->propertyValues.at(lastPropertyIndex);
- if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
- rv = ep->listClass->newList(QDeclarativeListProperty<QObject>(bindContext->asQDeclarativeContext(), (void*)lastPropertyIndex, 0, QDeclarativeContextPrivate::context_count, QDeclarativeContextPrivate::context_at), qMetaTypeId<QDeclarativeListProperty<QObject> >());
- } else {
- rv = ep->scriptValueFromVariant(value);
- }
-
- if (ep->captureProperties)
- ep->capturedProperties << QDeclarativeEnginePrivate::CapturedProperty(bindContext->asQDeclarativeContext(), -1, lastPropertyIndex + cp->notifyIndex);
- }
-
- return Value(scriptEngine, rv);
-
- } else {
-
- return Value(scriptEngine, lastFunction);
-
- }
-}
-
-void QDeclarativeContextScriptClass::setProperty(Object *object, const Identifier &name,
- const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_ASSERT(lastScopeObject);
-
- QDeclarativeContextData *bindContext = lastContext;
- Q_ASSERT(bindContext);
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- ep->objectClass->setProperty(lastScopeObject, name, value, context(), bindContext);
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativedata_p.h b/src/declarative/qml/qdeclarativedata_p.h
index 33458dc2f4..2516f4a8e1 100644
--- a/src/declarative/qml/qdeclarativedata_p.h
+++ b/src/declarative/qml/qdeclarativedata_p.h
@@ -57,6 +57,8 @@
#include <private/qobject_p.h>
#include "private/qdeclarativeguard_p.h"
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeCompiledData;
@@ -76,8 +78,8 @@ public:
QDeclarativeData()
: ownMemory(true), ownContext(false), indestructible(true), explicitIndestructibleSet(false),
context(0), outerContext(0), bindings(0), nextContextObject(0), prevContextObject(0), bindingBitsSize(0),
- bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0),
- scriptValue(0), objectDataRefCount(0), propertyCache(0), guards(0), extendedData(0) {
+ bindingBits(0), lineNumber(0), columnNumber(0), deferredComponent(0), deferredIdx(0), propertyCache(0),
+ guards(0), extendedData(0) {
init();
}
@@ -128,10 +130,7 @@ public:
QDeclarativeCompiledData *deferredComponent; // Can't this be found from the context?
unsigned int deferredIdx;
- // ### Can we make this QScriptValuePrivate so we incur no additional allocation
- // cost?
- QScriptValue *scriptValue;
- quint32 objectDataRefCount;
+ v8::Persistent<v8::Object> v8object;
QDeclarativePropertyCache *propertyCache;
QDeclarativeGuard<QObject> *guards;
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 073e1d4119..c4e9d0e432 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -44,7 +44,6 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativecompiler_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include "qdeclarative.h"
#include "qdeclarativecontext.h"
#include "qdeclarativeexpression.h"
@@ -55,9 +54,6 @@
#include "private/qdeclarativestringconverters_p.h"
#include "private/qdeclarativexmlhttprequest_p.h"
#include "private/qdeclarativesqldatabase_p.h"
-#include "private/qdeclarativescarceresourcescriptclass_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
#include "qdeclarativescriptstring.h"
#include "private/qdeclarativeglobal_p.h"
#include "private/qdeclarativeworkerscript_p.h"
@@ -68,13 +64,11 @@
#include "qdeclarativeextensioninterface.h"
#include "private/qdeclarativelist_p.h"
#include "private/qdeclarativetypenamecache_p.h"
-#include "private/qdeclarativeinclude_p.h"
#include "private/qdeclarativenotifier_p.h"
#include "private/qdeclarativedebugtrace_p.h"
#include "private/qdeclarativeapplication_p.h"
#include <QtCore/qmetaobject.h>
-#include <QScriptClass>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
@@ -343,16 +337,16 @@ The \c status property will be updated as the operation progresses.
If provided, \a callback is invoked when the operation completes. The callback is passed
the same object as is returned from the Qt.include() call.
*/
-// Qt.include() is implemented in qdeclarativeinclude.cpp
+// Qt.include() is implemented in qv8include.cpp
QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
: captureProperties(false), rootContext(0), isDebugging(false),
- outputWarningsToStdErr(true), contextClass(0), sharedContext(0), sharedScope(0),
- objectClass(0), valueTypeClass(0), globalClass(0), cleanup(0), erroredBindings(0),
- inProgressCreations(0), scriptEngine(this), workerScriptEngine(0), componentAttached(0),
- inBeginCreate(false), networkAccessManager(0), networkAccessManagerFactory(0),
- scarceResources(0), scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
+ outputWarningsToStdErr(true), sharedContext(0), sharedScope(0),
+ cleanup(0), erroredBindings(0), inProgressCreations(0), scriptEngine(this),
+ workerScriptEngine(0), componentAttached(0), inBeginCreate(false),
+ networkAccessManager(0), networkAccessManagerFactory(0),
+ scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1),
sgContext(0)
{
if (!qt_QmlQtModule_registered) {
@@ -363,102 +357,18 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
QSGItemsModule::defineModule();
QDeclarativeValueTypeFactory::registerValueTypes();
}
- globalClass = new QDeclarativeGlobalScriptClass(&scriptEngine);
-}
-
-/*!
- \qmlmethod url Qt::resolvedUrl(url url)
- Returns \a url resolved relative to the URL of the caller.
-*/
-QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
-{
- if (p) {
- QDeclarativeContextData *ctxt = p->getContext(context);
- if (ctxt)
- return ctxt->resolvedUrl(url);
- else
- return p->getUrl(context).resolved(url);
- }
- return baseUrl.resolved(url);
}
QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *priv)
-: p(priv), sqlQueryClass(0), namedNodeMapClass(0), nodeListClass(0)
+: p(priv)
{
// Note that all documentation for stuff put on the global object goes in
// doc/src/declarative/globalobject.qdoc
- bool mainthread = priv != 0;
-
QScriptValue qtObject =
newQMetaObject(StaticQtMetaObject::get());
globalObject().setProperty(QLatin1String("Qt"), qtObject);
-#ifndef QT_NO_DESKTOPSERVICES
- offlineStoragePath = QDesktopServices::storageLocation(QDesktopServices::DataLocation).replace(QLatin1Char('/'), QDir::separator())
- + QDir::separator() + QLatin1String("QML")
- + QDir::separator() + QLatin1String("OfflineStorage");
-#endif
-
-#ifndef QT_NO_XMLSTREAMREADER
- qt_add_qmlxmlhttprequest(this);
-#endif
- qt_add_qmlsqldatabase(this);
- // XXX A Multimedia "Qt.Sound" class also needs to be made available,
- // XXX but we don't want a dependency in that cirection.
- // XXX When the above a done some better way, that way should also be
- // XXX used to add Qt.Sound class.
-
- //types
- if (mainthread)
- qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::include, 2));
- else
- qtObject.setProperty(QLatin1String("include"), newFunction(QDeclarativeInclude::worker_include, 2));
-
- qtObject.setProperty(QLatin1String("isQtObject"), newFunction(QDeclarativeEnginePrivate::isQtObject, 1));
- qtObject.setProperty(QLatin1String("rgba"), newFunction(QDeclarativeEnginePrivate::rgba, 4));
- qtObject.setProperty(QLatin1String("hsla"), newFunction(QDeclarativeEnginePrivate::hsla, 4));
- qtObject.setProperty(QLatin1String("rect"), newFunction(QDeclarativeEnginePrivate::rect, 4));
- qtObject.setProperty(QLatin1String("point"), newFunction(QDeclarativeEnginePrivate::point, 2));
- qtObject.setProperty(QLatin1String("size"), newFunction(QDeclarativeEnginePrivate::size, 2));
- qtObject.setProperty(QLatin1String("vector3d"), newFunction(QDeclarativeEnginePrivate::vector3d, 3));
-
- if (mainthread) {
- //color helpers
- qtObject.setProperty(QLatin1String("lighter"), newFunction(QDeclarativeEnginePrivate::lighter, 1));
- qtObject.setProperty(QLatin1String("darker"), newFunction(QDeclarativeEnginePrivate::darker, 1));
- qtObject.setProperty(QLatin1String("tint"), newFunction(QDeclarativeEnginePrivate::tint, 2));
- }
-
-#ifndef QT_NO_DATESTRING
- //date/time formatting
- qtObject.setProperty(QLatin1String("formatDate"),newFunction(QDeclarativeEnginePrivate::formatDate, 2));
- qtObject.setProperty(QLatin1String("formatTime"),newFunction(QDeclarativeEnginePrivate::formatTime, 2));
- qtObject.setProperty(QLatin1String("formatDateTime"),newFunction(QDeclarativeEnginePrivate::formatDateTime, 2));
-#endif
-
- //misc methods
- qtObject.setProperty(QLatin1String("openUrlExternally"),newFunction(QDeclarativeEnginePrivate::desktopOpenUrl, 1));
- qtObject.setProperty(QLatin1String("fontFamilies"),newFunction(QDeclarativeEnginePrivate::fontFamilies, 0));
- qtObject.setProperty(QLatin1String("md5"),newFunction(QDeclarativeEnginePrivate::md5, 1));
- qtObject.setProperty(QLatin1String("btoa"),newFunction(QDeclarativeEnginePrivate::btoa, 1));
- qtObject.setProperty(QLatin1String("atob"),newFunction(QDeclarativeEnginePrivate::atob, 1));
- qtObject.setProperty(QLatin1String("quit"), newFunction(QDeclarativeEnginePrivate::quit, 0));
- qtObject.setProperty(QLatin1String("resolvedUrl"),newFunction(QDeclarativeScriptEngine::resolvedUrl, 1));
-
- if (mainthread) {
- qtObject.setProperty(QLatin1String("createQmlObject"),
- newFunction(QDeclarativeEnginePrivate::createQmlObject, 1));
- qtObject.setProperty(QLatin1String("createComponent"),
- newFunction(QDeclarativeEnginePrivate::createComponent, 1));
- }
-
- //firebug/webkit compat
- QScriptValue consoleObject = newObject();
- consoleObject.setProperty(QLatin1String("log"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1));
- consoleObject.setProperty(QLatin1String("debug"),newFunction(QDeclarativeEnginePrivate::consoleLog, 1));
- globalObject().setProperty(QLatin1String("console"), consoleObject);
-
// translation functions need to be installed
// before the global script class is constructed (QTBUG-6437)
installTranslatorFunctions();
@@ -466,16 +376,6 @@ QDeclarativeScriptEngine::QDeclarativeScriptEngine(QDeclarativeEnginePrivate *pr
QDeclarativeScriptEngine::~QDeclarativeScriptEngine()
{
- delete sqlQueryClass;
- delete nodeListClass;
- delete namedNodeMapClass;
-}
-
-QScriptValue QDeclarativeScriptEngine::resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine)
-{
- QString arg = ctxt->argument(0).toString();
- QUrl r = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt,QUrl(arg));
- return QScriptValue(r.toString());
}
QNetworkAccessManager *QDeclarativeScriptEngine::networkAccessManager()
@@ -500,20 +400,6 @@ QDeclarativeEnginePrivate::~QDeclarativeEnginePrivate()
delete rootContext;
rootContext = 0;
- delete contextClass;
- contextClass = 0;
- delete objectClass;
- objectClass = 0;
- delete scarceResourceClass;
- scarceResourceClass = 0;
- delete valueTypeClass;
- valueTypeClass = 0;
- delete typeNameClass;
- typeNameClass = 0;
- delete listClass;
- listClass = 0;
- delete globalClass;
- globalClass = 0;
for(QHash<int, QDeclarativeCompiledData*>::ConstIterator iter = m_compositeTypes.constBegin(); iter != m_compositeTypes.constEnd(); ++iter)
(*iter)->release();
@@ -579,16 +465,10 @@ void QDeclarativeEnginePrivate::init()
QDeclarativeData::init();
- contextClass = new QDeclarativeContextScriptClass(q);
- objectClass = new QDeclarativeObjectScriptClass(q);
- scarceResourceClass = new QDeclarativeScarceResourceScriptClass(q);
- valueTypeClass = new QDeclarativeValueTypeScriptClass(q);
- typeNameClass = new QDeclarativeTypeNameScriptClass(q);
- listClass = new QDeclarativeListScriptClass(q);
- rootContext = new QDeclarativeContext(q,true);
+ // Init V8 data
+ v8engine.init(q);
- QScriptValue applicationObject = objectClass->newQObject(new QDeclarativeApplication(q));
- scriptEngine.globalObject().property(QLatin1String("Qt")).setProperty(QLatin1String("application"), applicationObject);
+ rootContext = new QDeclarativeContext(q,true);
if (QCoreApplication::instance()->thread() == q->thread() &&
QDeclarativeEngineDebugServer::isDebuggingEnabled()) {
@@ -938,6 +818,15 @@ void QDeclarativeEngine::setOutputWarningsToStandardError(bool enabled)
}
/*!
+ Attempt to free unused memory.
+*/
+void QDeclarativeEngine::collectGarbage()
+{
+ v8::V8::LowMemoryNotification();
+ while (!v8::V8::IdleNotification()) {}
+}
+
+/*!
Returns the QDeclarativeContext for the \a object, or 0 if no
context has been set.
@@ -1186,19 +1075,19 @@ void QDeclarativeData::destroyed(QObject *object)
guard->objectDestroyed(object);
}
- if (scriptValue)
- delete scriptValue;
-
if (extendedData)
delete extendedData;
+ v8object.Dispose();
+
if (ownMemory)
delete this;
}
void QDeclarativeData::parentChanged(QObject *, QObject *parent)
{
- if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }
+ // XXX aakenned
+// if (!parent && scriptValue) { delete scriptValue; scriptValue = 0; }
}
void QDeclarativeData::objectNameChanged(QObject *)
@@ -1242,44 +1131,6 @@ void QDeclarativeData::setBindingBit(QObject *obj, int bit)
bindingBits[bit / 32] |= (1 << (bit % 32));
}
-/*!
- Creates a QScriptValue allowing you to use \a object in QML script.
- \a engine is the QDeclarativeEngine it is to be created in.
-
- The QScriptValue returned is a QtScript Object, not a QtScript QObject, due
- to the special needs of QML requiring more functionality than a standard
- QtScript QObject.
-*/
-QScriptValue QDeclarativeEnginePrivate::qmlScriptObject(QObject* object,
- QDeclarativeEngine* engine)
-{
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
- return enginePriv->objectClass->newQObject(object);
-}
-
-/*!
- Returns the QDeclarativeContext for the executing QScript \a ctxt.
-*/
-QDeclarativeContextData *QDeclarativeEnginePrivate::getContext(QScriptContext *ctxt)
-{
- QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
- Q_ASSERT(scopeNode.isValid());
- Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
- return contextClass->contextFromValue(scopeNode);
-}
-
-/*!
- Returns the QUrl associated with the script \a ctxt for the case that there is
- no QDeclarativeContext.
-*/
-QUrl QDeclarativeEnginePrivate::getUrl(QScriptContext *ctxt)
-{
- QScriptValue scopeNode = QScriptDeclarativeClass::scopeChainValue(ctxt, -3);
- Q_ASSERT(scopeNode.isValid());
- Q_ASSERT(QScriptDeclarativeClass::scriptClass(scopeNode) == contextClass);
- return contextClass->urlFromValue(scopeNode);
-}
-
QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
{
if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) {
@@ -1290,651 +1141,6 @@ QString QDeclarativeEnginePrivate::urlToLocalFileOrQrc(const QUrl& url)
return url.toLocalFile();
}
-/*!
-\qmlmethod object Qt::createComponent(url)
-
-Returns a \l Component object created using the QML file at the specified \a url,
-or \c null if an empty string was given.
-
-The returned component's \l Component::status property indicates whether the
-component was successfully created. If the status is \c Component.Error,
-see \l Component::errorString() for an error description.
-
-Call \l {Component::createObject()}{Component.createObject()} on the returned
-component to create an object instance of the component.
-
-For example:
-
-\snippet doc/src/snippets/declarative/createComponent-simple.qml 0
-
-See \l {Dynamic Object Management in QML} for more information on using this function.
-
-To create a QML object from an arbitrary string of QML (instead of a file),
-use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::createComponent(QScriptContext *ctxt, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *activeEnginePriv =
- static_cast<QDeclarativeScriptEngine*>(engine)->p;
- QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
-
- if(ctxt->argumentCount() != 1) {
- return ctxt->throwError(QLatin1String("Qt.createComponent(): Invalid arguments"));
- } else {
-
- QString arg = ctxt->argument(0).toString();
- if (arg.isEmpty())
- return engine->nullValue();
- QUrl url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(ctxt, QUrl(arg));
- QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
- QDeclarativeComponent *c = new QDeclarativeComponent(activeEngine, url, activeEngine);
- QDeclarativeComponentPrivate::get(c)->creationContext = context;
- QDeclarativeData::get(c, true)->setImplicitDestructible();
- return activeEnginePriv->objectClass->newQObject(c, qMetaTypeId<QDeclarativeComponent*>());
- }
-}
-
-/*!
-\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
-
-Returns a new object created from the given \a string of QML which will have the specified \a parent,
-or \c null if there was an error in creating the object.
-
-If \a filepath is specified, it will be used for error reporting for the created object.
-
-Example (where \c parentItem is the id of an existing QML item):
-
-\snippet doc/src/snippets/declarative/createQmlObject.qml 0
-
-In the case of an error, a QtScript Error object is thrown. This object has an additional property,
-\c qmlErrors, which is an array of the errors encountered.
-Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
-For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
-{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
-
-Note that this function returns immediately, and therefore may not work if
-the \a qml string loads new components (that is, external QML files that have not yet been loaded).
-If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
-
-See \l {Dynamic Object Management in QML} for more information on using this function.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::createQmlObject(QScriptContext *ctxt, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *activeEnginePriv =
- static_cast<QDeclarativeScriptEngine*>(engine)->p;
- QDeclarativeEngine* activeEngine = activeEnginePriv->q_func();
-
- if(ctxt->argumentCount() < 2 || ctxt->argumentCount() > 3)
- return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Invalid arguments"));
-
- QDeclarativeContextData* context = activeEnginePriv->getContext(ctxt);
- Q_ASSERT(context);
-
- QString qml = ctxt->argument(0).toString();
- if (qml.isEmpty())
- return engine->nullValue();
-
- QUrl url;
- if(ctxt->argumentCount() > 2)
- url = QUrl(ctxt->argument(2).toString());
- else
- url = QUrl(QLatin1String("inline"));
-
- if (url.isValid() && url.isRelative())
- url = context->resolvedUrl(url);
-
- QObject *parentArg = activeEnginePriv->objectClass->toQObject(ctxt->argument(1));
- if(!parentArg)
- return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Missing parent object"));
-
- QDeclarativeComponent component(activeEngine);
- component.setData(qml.toUtf8(), url);
-
- if(component.isError()) {
- QList<QDeclarativeError> errors = component.errors();
- QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
- QScriptValue arr = ctxt->engine()->newArray(errors.length());
- int i = 0;
- foreach (const QDeclarativeError &error, errors){
- errstr += QLatin1String("\n ") + error.toString();
- QScriptValue qmlErrObject = ctxt->engine()->newObject();
- qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
- qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
- qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
- qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
- arr.setProperty(i++, qmlErrObject);
- }
- QScriptValue err = ctxt->throwError(errstr);
- err.setProperty(QLatin1String("qmlErrors"),arr);
- return err;
- }
-
- if (!component.isReady())
- return ctxt->throwError(QLatin1String("Qt.createQmlObject(): Component is not ready"));
-
- QObject *obj = component.beginCreate(context->asQDeclarativeContext());
- if(obj)
- QDeclarativeData::get(obj, true)->setImplicitDestructible();
- component.completeCreate();
-
- if(component.isError()) {
- QList<QDeclarativeError> errors = component.errors();
- QString errstr = QLatin1String("Qt.createQmlObject() failed to create object: ");
- QScriptValue arr = ctxt->engine()->newArray(errors.length());
- int i = 0;
- foreach (const QDeclarativeError &error, errors){
- errstr += QLatin1String("\n ") + error.toString();
- QScriptValue qmlErrObject = ctxt->engine()->newObject();
- qmlErrObject.setProperty(QLatin1String("lineNumber"), QScriptValue(error.line()));
- qmlErrObject.setProperty(QLatin1String("columnNumber"), QScriptValue(error.column()));
- qmlErrObject.setProperty(QLatin1String("fileName"), QScriptValue(error.url().toString()));
- qmlErrObject.setProperty(QLatin1String("message"), QScriptValue(error.description()));
- arr.setProperty(i++, qmlErrObject);
- }
- QScriptValue err = ctxt->throwError(errstr);
- err.setProperty(QLatin1String("qmlErrors"),arr);
- return err;
- }
-
- Q_ASSERT(obj);
-
- obj->setParent(parentArg);
-
- QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
- for (int ii = 0; ii < functions.count(); ++ii) {
- if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
- break;
- }
-
- QDeclarativeData::get(obj, true)->setImplicitDestructible();
- return activeEnginePriv->objectClass->newQObject(obj, QMetaType::QObjectStar);
-}
-
-/*!
-\qmlmethod bool Qt::isQtObject(object)
-Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
-*/
-QScriptValue QDeclarativeEnginePrivate::isQtObject(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() == 0)
- return QScriptValue(engine, false);
-
- return QScriptValue(engine, 0 != ctxt->argument(0).toQObject());
-}
-
-/*!
-\qmlmethod Qt::vector3d(real x, real y, real z)
-Returns a Vector3D with the specified \c x, \c y and \c z.
-*/
-QScriptValue QDeclarativeEnginePrivate::vector3d(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 3)
- return ctxt->throwError(QLatin1String("Qt.vector(): Invalid arguments"));
- qsreal x = ctxt->argument(0).toNumber();
- qsreal y = ctxt->argument(1).toNumber();
- qsreal z = ctxt->argument(2).toNumber();
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QVector3D(x, y, z)));
-}
-
-/*!
-\qmlmethod string Qt::formatDate(datetime date, variant format)
-
-Returns a string representation of \c date, optionally formatted according
-to \c format.
-
-The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
-property, a QDate, or QDateTime value. The \a format parameter may be any of
-the possible format values as described for
-\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
-
-If \a format is not specified, \a date is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
-*/
-#ifndef QT_NO_DATESTRING
-QScriptValue QDeclarativeEnginePrivate::formatDate(QScriptContext*ctxt, QScriptEngine*engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount == 0 || argCount > 2)
- return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid arguments"));
-
- QDate date = ctxt->argument(0).toDateTime().date();
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- if (argCount == 2) {
- QScriptValue formatArg = ctxt->argument(1);
- if (formatArg.isString()) {
- QString format = formatArg.toString();
- return engine->newVariant(QVariant::fromValue(date.toString(format)));
- } else if (formatArg.isNumber()) {
- enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
- return ctxt->throwError(QLatin1String("Qt.formatDate(): Invalid date format"));
- }
- }
- return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
-}
-
-/*!
-\qmlmethod string Qt::formatTime(datetime time, variant format)
-
-Returns a string representation of \c time, optionally formatted according to
-\c format.
-
-The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
-value. The \a format parameter may be any of the possible format values as
-described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
-
-If \a format is not specified, \a time is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
-*/
-QScriptValue QDeclarativeEnginePrivate::formatTime(QScriptContext*ctxt, QScriptEngine*engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount == 0 || argCount > 2)
- return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid arguments"));
-
- QTime time;
- QScriptValue sv = ctxt->argument(0);
- if (sv.isDate())
- time = sv.toDateTime().time();
- else if (sv.toVariant().type() == QVariant::Time)
- time = sv.toVariant().toTime();
-
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- if (argCount == 2) {
- QScriptValue formatArg = ctxt->argument(1);
- if (formatArg.isString()) {
- QString format = formatArg.toString();
- return engine->newVariant(QVariant::fromValue(time.toString(format)));
- } else if (formatArg.isNumber()) {
- enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
- return ctxt->throwError(QLatin1String("Qt.formatTime(): Invalid time format"));
- }
- }
- return engine->newVariant(QVariant::fromValue(time.toString(enumFormat)));
-}
-
-/*!
-\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
-
-Returns a string representation of \c datetime, optionally formatted according to
-\c format.
-
-The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
-property, a QDate, QTime, or QDateTime value.
-
-If \a format is not provided, \a dateTime is formatted using
-\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
-\a format should be either.
-
-\list
-\o One of the Qt::DateFormat enumeration values, such as
- \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
-\o A string that specifies the format of the returned string, as detailed below.
-\endlist
-
-If \a format specifies a format string, it should use the following expressions
-to specify the date:
-
- \table
- \header \i Expression \i Output
- \row \i d \i the day as number without a leading zero (1 to 31)
- \row \i dd \i the day as number with a leading zero (01 to 31)
- \row \i ddd
- \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
- Uses QDate::shortDayName().
- \row \i dddd
- \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
- Uses QDate::longDayName().
- \row \i M \i the month as number without a leading zero (1-12)
- \row \i MM \i the month as number with a leading zero (01-12)
- \row \i MMM
- \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
- Uses QDate::shortMonthName().
- \row \i MMMM
- \i the long localized month name (e.g. 'January' to 'December').
- Uses QDate::longMonthName().
- \row \i yy \i the year as two digit number (00-99)
- \row \i yyyy \i the year as four digit number
- \endtable
-
-In addition the following expressions can be used to specify the time:
-
- \table
- \header \i Expression \i Output
- \row \i h
- \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
- \row \i hh
- \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
- \row \i m \i the minute without a leading zero (0 to 59)
- \row \i mm \i the minute with a leading zero (00 to 59)
- \row \i s \i the second without a leading zero (0 to 59)
- \row \i ss \i the second with a leading zero (00 to 59)
- \row \i z \i the milliseconds without leading zeroes (0 to 999)
- \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
- \row \i AP
- \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
- \row \i ap
- \i use am/pm display. \e ap will be replaced by either "am" or "pm".
- \endtable
-
- All other input characters will be ignored. Any sequence of characters that
- are enclosed in single quotes will be treated as text and not be used as an
- expression. Two consecutive single quotes ("''") are replaced by a single quote
- in the output.
-
-For example, if the following date/time value was specified:
-
- \code
- // 21 May 2001 14:13:09
- var dateTime = new Date(2001, 5, 21, 14, 13, 09)
- \endcode
-
-This \a dateTime value could be passed to \c Qt.formatDateTime(),
-\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
-with the \a format values below to produce the following results:
-
- \table
- \header \i Format \i Result
- \row \i "dd.MM.yyyy" \i 21.05.2001
- \row \i "ddd MMMM d yy" \i Tue May 21 01
- \row \i "hh:mm:ss.zzz" \i 14:13:09.042
- \row \i "h:m:s ap" \i 2:13:9 pm
- \endtable
-*/
-QScriptValue QDeclarativeEnginePrivate::formatDateTime(QScriptContext*ctxt, QScriptEngine*engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount == 0 || argCount > 2)
- return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid arguments"));
-
- QDateTime date = ctxt->argument(0).toDateTime();
- Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
- if (argCount == 2) {
- QScriptValue formatArg = ctxt->argument(1);
- if (formatArg.isString()) {
- QString format = formatArg.toString();
- return engine->newVariant(QVariant::fromValue(date.toString(format)));
- } else if (formatArg.isNumber()) {
- enumFormat = Qt::DateFormat(formatArg.toUInt32());
- } else {
- return ctxt->throwError(QLatin1String("Qt.formatDateTime(): Invalid datetime format"));
- }
- }
- return engine->newVariant(QVariant::fromValue(date.toString(enumFormat)));
-}
-#endif // QT_NO_DATESTRING
-
-/*!
-\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
-
-Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
-All components should be in the range 0-1 inclusive.
-*/
-QScriptValue QDeclarativeEnginePrivate::rgba(QScriptContext *ctxt, QScriptEngine *engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount < 3 || argCount > 4)
- return ctxt->throwError(QLatin1String("Qt.rgba(): Invalid arguments"));
- qsreal r = ctxt->argument(0).toNumber();
- qsreal g = ctxt->argument(1).toNumber();
- qsreal b = ctxt->argument(2).toNumber();
- qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
-
- if (r < 0.0) r=0.0;
- if (r > 1.0) r=1.0;
- if (g < 0.0) g=0.0;
- if (g > 1.0) g=1.0;
- if (b < 0.0) b=0.0;
- if (b > 1.0) b=1.0;
- if (a < 0.0) a=0.0;
- if (a > 1.0) a=1.0;
-
- return engine->toScriptValue(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
-}
-
-/*!
-\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
-
-Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
-All components should be in the range 0-1 inclusive.
-*/
-QScriptValue QDeclarativeEnginePrivate::hsla(QScriptContext *ctxt, QScriptEngine *engine)
-{
- int argCount = ctxt->argumentCount();
- if(argCount < 3 || argCount > 4)
- return ctxt->throwError(QLatin1String("Qt.hsla(): Invalid arguments"));
- qsreal h = ctxt->argument(0).toNumber();
- qsreal s = ctxt->argument(1).toNumber();
- qsreal l = ctxt->argument(2).toNumber();
- qsreal a = (argCount == 4) ? ctxt->argument(3).toNumber() : 1;
-
- if (h < 0.0) h=0.0;
- if (h > 1.0) h=1.0;
- if (s < 0.0) s=0.0;
- if (s > 1.0) s=1.0;
- if (l < 0.0) l=0.0;
- if (l > 1.0) l=1.0;
- if (a < 0.0) a=0.0;
- if (a > 1.0) a=1.0;
-
- return engine->toScriptValue(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
-}
-
-/*!
-\qmlmethod rect Qt::rect(int x, int y, int width, int height)
-
-Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
-
-The returned object has \c x, \c y, \c width and \c height attributes with the given values.
-*/
-QScriptValue QDeclarativeEnginePrivate::rect(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 4)
- return ctxt->throwError(QLatin1String("Qt.rect(): Invalid arguments"));
-
- qsreal x = ctxt->argument(0).toNumber();
- qsreal y = ctxt->argument(1).toNumber();
- qsreal w = ctxt->argument(2).toNumber();
- qsreal h = ctxt->argument(3).toNumber();
-
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
-}
-
-/*!
-\qmlmethod point Qt::point(int x, int y)
-Returns a Point with the specified \c x and \c y coordinates.
-*/
-QScriptValue QDeclarativeEnginePrivate::point(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.point(): Invalid arguments"));
- qsreal x = ctxt->argument(0).toNumber();
- qsreal y = ctxt->argument(1).toNumber();
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QPointF(x, y)));
-}
-
-/*!
-\qmlmethod Qt::size(int width, int height)
-Returns a Size with the specified \c width and \c height.
-*/
-QScriptValue QDeclarativeEnginePrivate::size(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.size(): Invalid arguments"));
- qsreal w = ctxt->argument(0).toNumber();
- qsreal h = ctxt->argument(1).toNumber();
- return QDeclarativeEnginePrivate::get(engine)->scriptValueFromVariant(QVariant::fromValue(QSizeF(w, h)));
-}
-
-/*!
-\qmlmethod color Qt::lighter(color baseColor, real factor)
-Returns a color lighter than \c baseColor by the \c factor provided.
-
-If the factor is greater than 1.0, this functions returns a lighter color.
-Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
-the return color is darker, but we recommend using the Qt.darker() function for this purpose.
-If the factor is 0 or negative, the return value is unspecified.
-
-The function converts the current RGB color to HSV, multiplies the value (V) component
-by factor and converts the color back to RGB.
-
-If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
-*/
-QScriptValue QDeclarativeEnginePrivate::lighter(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.lighter(): Invalid arguments"));
- QVariant v = ctxt->argument(0).toVariant();
- QColor color;
- if (v.userType() == QVariant::Color)
- color = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
- qsreal factor = 1.5;
- if (ctxt->argumentCount() == 2)
- factor = ctxt->argument(1).toNumber();
- color = color.lighter(int(qRound(factor*100.)));
- return engine->toScriptValue(QVariant::fromValue(color));
-}
-
-/*!
-\qmlmethod color Qt::darker(color baseColor, real factor)
-Returns a color darker than \c baseColor by the \c factor provided.
-
-If the factor is greater than 1.0, this function returns a darker color.
-Setting factor to 3.0 returns a color that has one-third the brightness.
-If the factor is less than 1.0, the return color is lighter, but we recommend using
-the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
-value is unspecified.
-
-The function converts the current RGB color to HSV, divides the value (V) component
-by factor and converts the color back to RGB.
-
-If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
-*/
-QScriptValue QDeclarativeEnginePrivate::darker(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 1 && ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.darker(): Invalid arguments"));
- QVariant v = ctxt->argument(0).toVariant();
- QColor color;
- if (v.userType() == QVariant::Color)
- color = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
- qsreal factor = 2.0;
- if (ctxt->argumentCount() == 2)
- factor = ctxt->argument(1).toNumber();
- color = color.darker(int(qRound(factor*100.)));
- return engine->toScriptValue(QVariant::fromValue(color));
-}
-
-/*!
-\qmlmethod bool Qt::openUrlExternally(url target)
-Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
-*/
-QScriptValue QDeclarativeEnginePrivate::desktopOpenUrl(QScriptContext *ctxt, QScriptEngine *e)
-{
- if(ctxt->argumentCount() < 1)
- return QScriptValue(e, false);
- bool ret = false;
-#ifndef QT_NO_DESKTOPSERVICES
- ret = QDesktopServices::openUrl(QDeclarativeScriptEngine::get(e)->resolvedUrl(ctxt, QUrl(ctxt->argument(0).toString())));
-#endif
- return QScriptValue(e, ret);
-}
-
-/*!
-\qmlmethod list<string> Qt::fontFamilies()
-Returns a list of the font families available to the application.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::fontFamilies(QScriptContext *ctxt, QScriptEngine *e)
-{
- if(ctxt->argumentCount() != 0)
- return ctxt->throwError(QLatin1String("Qt.fontFamilies(): Invalid arguments"));
-
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(e);
- QFontDatabase database;
- return p->scriptValueFromVariant(database.families());
-}
-
-/*!
-\qmlmethod string Qt::md5(data)
-Returns a hex string of the md5 hash of \c data.
-*/
-QScriptValue QDeclarativeEnginePrivate::md5(QScriptContext *ctxt, QScriptEngine *)
-{
- if (ctxt->argumentCount() != 1)
- return ctxt->throwError(QLatin1String("Qt.md5(): Invalid arguments"));
-
- QByteArray data = ctxt->argument(0).toString().toUtf8();
- QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
-
- return QScriptValue(QLatin1String(result.toHex()));
-}
-
-/*!
-\qmlmethod string Qt::btoa(data)
-Binary to ASCII - this function returns a base64 encoding of \c data.
-*/
-QScriptValue QDeclarativeEnginePrivate::btoa(QScriptContext *ctxt, QScriptEngine *)
-{
- if (ctxt->argumentCount() != 1)
- return ctxt->throwError(QLatin1String("Qt.btoa(): Invalid arguments"));
-
- QByteArray data = ctxt->argument(0).toString().toUtf8();
-
- return QScriptValue(QLatin1String(data.toBase64()));
-}
-
-/*!
-\qmlmethod string Qt::atob(data)
-ASCII to binary - this function returns a base64 decoding of \c data.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::atob(QScriptContext *ctxt, QScriptEngine *)
-{
- if (ctxt->argumentCount() != 1)
- return ctxt->throwError(QLatin1String("Qt.atob(): Invalid arguments"));
-
- QByteArray data = ctxt->argument(0).toString().toUtf8();
-
- return QScriptValue(QLatin1String(QByteArray::fromBase64(data)));
-}
-
-QScriptValue QDeclarativeEnginePrivate::consoleLog(QScriptContext *ctxt, QScriptEngine *e)
-{
- if(ctxt->argumentCount() < 1)
- return e->newVariant(QVariant(false));
-
- QByteArray msg;
-
- for (int i=0; i<ctxt->argumentCount(); ++i) {
- if (!msg.isEmpty()) msg += ' ';
- msg += ctxt->argument(i).toString().toLocal8Bit();
- // does not support firebug "%[a-z]" formatting, since firebug really
- // does just ignore the format letter, which makes it pointless.
- }
-
- qDebug("%s",msg.constData());
-
- return e->newVariant(QVariant(true));
-}
-
void QDeclarativeEnginePrivate::sendQuit()
{
Q_Q(QDeclarativeEngine);
@@ -2003,145 +1209,6 @@ void QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate *engine, const
dumpwarning(error);
}
-/*!
-\qmlmethod Qt::quit()
-This function causes the QDeclarativeEngine::quit() signal to be emitted.
-Within the \l {QML Viewer}, this causes the launcher application to exit;
-to quit a C++ application when this method is called, connect the
-QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
-*/
-
-QScriptValue QDeclarativeEnginePrivate::quit(QScriptContext * /*ctxt*/, QScriptEngine *e)
-{
- QDeclarativeEnginePrivate *qe = get (e);
- qe->sendQuit();
- return QScriptValue();
-}
-
-/*!
- \qmlmethod color Qt::tint(color baseColor, color tintColor)
- This function allows tinting one color with another.
-
- The tint color should usually be mostly transparent, or you will not be
- able to see the underlying color. The below example provides a slight red
- tint by having the tint color be pure red which is only 1/16th opaque.
-
- \qml
- Item {
- Rectangle {
- x: 0; width: 80; height: 80
- color: "lightsteelblue"
- }
- Rectangle {
- x: 100; width: 80; height: 80
- color: Qt.tint("lightsteelblue", "#10FF0000")
- }
- }
- \endqml
- \image declarative-rect_tint.png
-
- Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
-*/
-QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if(ctxt->argumentCount() != 2)
- return ctxt->throwError(QLatin1String("Qt.tint(): Invalid arguments"));
- //get color
- QVariant v = ctxt->argument(0).toVariant();
- QColor color;
- if (v.userType() == QVariant::Color)
- color = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
-
- //get tint color
- v = ctxt->argument(1).toVariant();
- QColor tintColor;
- if (v.userType() == QVariant::Color)
- tintColor = v.value<QColor>();
- else if (v.userType() == QVariant::String) {
- bool ok;
- tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
- if (!ok)
- return engine->nullValue();
- } else
- return engine->nullValue();
-
- //tint
- QColor finalColor;
- int a = tintColor.alpha();
- if (a == 0xFF)
- finalColor = tintColor;
- else if (a == 0x00)
- finalColor = color;
- else {
- qreal a = tintColor.alphaF();
- qreal inv_a = 1.0 - a;
-
- finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
- tintColor.greenF() * a + color.greenF() * inv_a,
- tintColor.blueF() * a + color.blueF() * inv_a,
- a + inv_a * color.alphaF());
- }
-
- return engine->toScriptValue(QVariant::fromValue(finalColor));
-}
-
-QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
-{
- if (variantIsScarceResource(val)) {
- return scarceResourceClass->newScarceResource(val);
- } else if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
- QDeclarativeListReferencePrivate *p =
- QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
- if (p->object) {
- return listClass->newList(p->property, p->propertyType);
- } else {
- return scriptEngine.nullValue();
- }
- } else if (val.userType() == qMetaTypeId<QList<QObject *> >()) {
- const QList<QObject *> &list = *(QList<QObject *>*)val.constData();
- QScriptValue rv = scriptEngine.newArray(list.count());
- for (int ii = 0; ii < list.count(); ++ii) {
- QObject *object = list.at(ii);
- rv.setProperty(ii, objectClass->newQObject(object));
- }
- return rv;
- } else if (QDeclarativeValueType *vt = valueTypes[val.userType()]) {
- return valueTypeClass->newObject(val, vt);
- }
-
- bool objOk;
- QObject *obj = QDeclarativeMetaType::toQObject(val, &objOk);
- if (objOk) {
- return objectClass->newQObject(obj);
- } else {
- return scriptEngine.toScriptValue(val);
- }
-}
-
-/*
- If the variant is a scarce resource (consumes a large amount of memory, or
- only a limited number of them can be held in memory at any given time without
- exhausting supply for future use) we need to release the scarce resource
- after evaluation of the javascript binding is complete.
- */
-bool QDeclarativeEnginePrivate::variantIsScarceResource(const QVariant& val)
-{
- if (val.type() == QVariant::Pixmap) {
- return true;
- } else if (val.type() == QVariant::Image) {
- return true;
- }
-
- return false;
-}
-
/*
This function should be called prior to evaluation of any js expression,
so that scarce resources are not freed prematurely (eg, if there is a
@@ -2169,45 +1236,13 @@ void QDeclarativeEnginePrivate::dereferenceScarceResources()
// note that the actual SRD is owned by the JS engine,
// so we cannot delete the SRD; but we can free the
// memory used by the variant in the SRD.
- ScarceResourceData *srd = 0;
- while (scarceResources) {
- srd = scarceResources; // srd points to the "old" (current) head of the list
- scarceResources = srd->next; // srd->next is the "new" head of the list
- if (srd->next) srd->next->prev = &scarceResources; // newHead->prev = listptr.
- srd->next = 0;
- srd->prev = 0;
- srd->releaseResource(); // release the old head node.
+ while (ScarceResourceData *sr = scarceResources.first()) {
+ sr->data = QVariant();
+ scarceResources.remove(sr);
}
}
}
-QVariant QDeclarativeEnginePrivate::scriptValueToVariant(const QScriptValue &val, int hint)
-{
- QScriptDeclarativeClass *dc = QScriptDeclarativeClass::scriptClass(val);
- if (dc == objectClass)
- return QVariant::fromValue(objectClass->toQObject(val));
- else if (dc == scarceResourceClass)
- return scarceResourceClass->toVariant(val);
- else if (dc == valueTypeClass)
- return valueTypeClass->toVariant(val);
- else if (dc == contextClass)
- return QVariant();
-
- // Convert to a QList<QObject*> only if val is an array and we were explicitly hinted
- if (hint == qMetaTypeId<QList<QObject *> >() && val.isArray()) {
- QList<QObject *> list;
- int length = val.property(QLatin1String("length")).toInt32();
- for (int ii = 0; ii < length; ++ii) {
- QScriptValue arrayItem = val.property(ii);
- QObject *d = arrayItem.toQObject();
- list << d;
- }
- return QVariant::fromValue(list);
- }
-
- return val.toVariant();
-}
-
/*!
Adds \a path as a directory where the engine searches for
installed modules in a URL-based directory structure.
@@ -2311,7 +1346,6 @@ void QDeclarativeEngine::setPluginPathList(const QStringList &paths)
d->importDatabase.setPluginPathList(paths);
}
-
/*!
Imports the plugin named \a filePath with the \a uri provided.
Returns true if the plugin was successfully imported; otherwise returns false.
@@ -2371,13 +1405,13 @@ bool QDeclarativeEngine::importPlugin(const QString &filePath, const QString &ur
void QDeclarativeEngine::setOfflineStoragePath(const QString& dir)
{
Q_D(QDeclarativeEngine);
- d->scriptEngine.offlineStoragePath = dir;
+ qt_qmlsqldatabase_setOfflineStoragePath(&d->v8engine, dir);
}
QString QDeclarativeEngine::offlineStoragePath() const
{
Q_D(const QDeclarativeEngine);
- return d->scriptEngine.offlineStoragePath;
+ return qt_qmlsqldatabase_getOfflineStoragePath(&d->v8engine);
}
static void voidptr_destructor(void *v)
diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h
index 8db3db8096..4f1ecdc8f1 100644
--- a/src/declarative/qml/qdeclarativeengine.h
+++ b/src/declarative/qml/qdeclarativeengine.h
@@ -107,6 +107,8 @@ public:
bool outputWarningsToStandardError() const;
void setOutputWarningsToStandardError(bool);
+ void collectGarbage();
+
static QDeclarativeContext *contextForObject(const QObject *);
static void setContextForObject(QObject *, QDeclarativeContext *);
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index fadedf41dd..f3943db454 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -66,14 +66,10 @@
#include "qdeclarativeimageprovider.h"
#include "private/qdeclarativeproperty_p.h"
#include "private/qdeclarativepropertycache_p.h"
-#include "private/qdeclarativeobjectscriptclass_p.h"
-#include "private/qdeclarativescarceresourcescriptclass_p.h"
-#include "private/qdeclarativecontextscriptclass_p.h"
-#include "private/qdeclarativevaluetypescriptclass_p.h"
#include "private/qdeclarativemetatype_p.h"
#include "private/qdeclarativedirparser_p.h"
+#include "private/qintrusivelist_p.h"
-#include <QtScript/QScriptClass>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptString>
#include <QtCore/qstring.h>
@@ -85,33 +81,27 @@
#include <private/qobject_p.h>
+#include <private/qv8engine_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeContext;
class QDeclarativeEngine;
class QDeclarativeContextPrivate;
class QDeclarativeExpression;
-class QDeclarativeContextScriptClass;
class QDeclarativeImportDatabase;
-class QDeclarativeObjectScriptClass;
-class QDeclarativeScarceResourceScriptClass;
class ScarceResourceData;
-class QDeclarativeTypeNameScriptClass;
-class QDeclarativeValueTypeScriptClass;
class QScriptEngineDebugger;
class QNetworkReply;
class QNetworkAccessManager;
class QDeclarativeNetworkAccessManagerFactory;
class QDeclarativeAbstractBinding;
class QScriptDeclarativeClass;
-class QDeclarativeTypeNameScriptClass;
class QDeclarativeTypeNameCache;
class QDeclarativeComponentAttached;
-class QDeclarativeListScriptClass;
class QDeclarativeCleanup;
class QDeclarativeDelayedError;
class QDeclarativeWorkerScriptEngine;
-class QDeclarativeGlobalScriptClass;
class QDir;
class QSGTexture;
class QSGContext;
@@ -122,21 +112,10 @@ public:
QDeclarativeScriptEngine(QDeclarativeEnginePrivate *priv);
virtual ~QDeclarativeScriptEngine();
- QUrl resolvedUrl(QScriptContext *context, const QUrl& url); // resolved against p's context, or baseUrl if no p
- static QScriptValue resolvedUrl(QScriptContext *ctxt, QScriptEngine *engine);
-
static QDeclarativeScriptEngine *get(QScriptEngine* e) { return static_cast<QDeclarativeScriptEngine*>(e); }
QDeclarativeEnginePrivate *p;
- // User by SQL API
- QScriptClass *sqlQueryClass;
- QString offlineStoragePath;
-
- // Used by DOM Core 3 API
- QScriptClass *namedNodeMapClass;
- QScriptClass *nodeListClass;
-
QUrl baseUrl;
virtual QNetworkAccessManager *networkAccessManager();
@@ -170,16 +149,8 @@ public:
bool outputWarningsToStdErr;
- QDeclarativeContextScriptClass *contextClass;
QDeclarativeContextData *sharedContext;
QObject *sharedScope;
- QDeclarativeObjectScriptClass *objectClass;
- QDeclarativeScarceResourceScriptClass *scarceResourceClass;
- QDeclarativeValueTypeScriptClass *valueTypeClass;
- QDeclarativeTypeNameScriptClass *typeNameClass;
- QDeclarativeListScriptClass *listClass;
- // Global script class
- QDeclarativeGlobalScriptClass *globalClass;
// Registered cleanup handlers
QDeclarativeCleanup *cleanup;
@@ -188,6 +159,9 @@ public:
QDeclarativeDelayedError *erroredBindings;
int inProgressCreations;
+ // V8 Engine
+ QV8Engine v8engine;
+
QDeclarativeScriptEngine scriptEngine;
QDeclarativeWorkerScriptEngine *getWorkerScriptEngine();
@@ -243,15 +217,20 @@ public:
QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
- /*
- A scarce resource (like a large pixmap or texture) will be cached in a
- JavaScript wrapper object when accessed in a binding or other js expression.
- We need some way to automatically release that scarce resource prior to normal
- garbage collection (unless the user explicitly preserves the resource).
- */
- ScarceResourceData* scarceResources;
+ // Scarce resources are "exceptionally high cost" QVariant types where allowing the
+ // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
+ // out-of-resource situations. When such a resource is passed into JavaScript we
+ // add it to the scarceResources list and it is destroyed when we return from the
+ // JavaScript execution that created it. The user can prevent this behavior by
+ // calling preserve() on the object which removes it from this scarceResource list.
+ class ScarceResourceData {
+ public:
+ ScarceResourceData(const QVariant &data) : data(data) {}
+ QVariant data;
+ QIntrusiveListNode node;
+ };
+ QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
int scarceResourcesRefCount;
- static bool variantIsScarceResource(const QVariant& val);
void referenceScarceResources();
void dereferenceScarceResources();
@@ -291,9 +270,6 @@ public:
QHash<int, int> m_qmlLists;
QHash<int, QDeclarativeCompiledData *> m_compositeTypes;
- QScriptValue scriptValueFromVariant(const QVariant &);
- QVariant scriptValueToVariant(const QScriptValue &, int hint = QVariant::Invalid);
-
void sendQuit();
void warning(const QDeclarativeError &);
void warning(const QList<QDeclarativeError> &);
@@ -302,35 +278,6 @@ public:
static void warning(QDeclarativeEnginePrivate *, const QDeclarativeError &);
static void warning(QDeclarativeEnginePrivate *, const QList<QDeclarativeError> &);
- static QScriptValue qmlScriptObject(QObject*, QDeclarativeEngine*);
-
- static QScriptValue createComponent(QScriptContext*, QScriptEngine*);
- static QScriptValue createQmlObject(QScriptContext*, QScriptEngine*);
- static QScriptValue isQtObject(QScriptContext*, QScriptEngine*);
- static QScriptValue vector3d(QScriptContext*, QScriptEngine*);
- static QScriptValue rgba(QScriptContext*, QScriptEngine*);
- static QScriptValue hsla(QScriptContext*, QScriptEngine*);
- static QScriptValue point(QScriptContext*, QScriptEngine*);
- static QScriptValue size(QScriptContext*, QScriptEngine*);
- static QScriptValue rect(QScriptContext*, QScriptEngine*);
-
- static QScriptValue lighter(QScriptContext*, QScriptEngine*);
- static QScriptValue darker(QScriptContext*, QScriptEngine*);
- static QScriptValue tint(QScriptContext*, QScriptEngine*);
-
- static QScriptValue desktopOpenUrl(QScriptContext*, QScriptEngine*);
- static QScriptValue fontFamilies(QScriptContext*, QScriptEngine*);
- static QScriptValue md5(QScriptContext*, QScriptEngine*);
- static QScriptValue btoa(QScriptContext*, QScriptEngine*);
- static QScriptValue atob(QScriptContext*, QScriptEngine*);
- static QScriptValue consoleLog(QScriptContext*, QScriptEngine*);
- static QScriptValue quit(QScriptContext*, QScriptEngine*);
-
-#ifndef QT_NO_DATESTRING
- static QScriptValue formatDate(QScriptContext*, QScriptEngine*);
- static QScriptValue formatTime(QScriptContext*, QScriptEngine*);
- static QScriptValue formatDateTime(QScriptContext*, QScriptEngine*);
-#endif
static QScriptEngine *getScriptEngine(QDeclarativeEngine *e) { return &e->d_func()->scriptEngine; }
static QDeclarativeEngine *getEngine(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p->q_func(); }
static QDeclarativeEnginePrivate *get(QDeclarativeEngine *e) { return e->d_func(); }
@@ -338,8 +285,6 @@ public:
static QDeclarativeEnginePrivate *get(QDeclarativeContextData *c) { return (c && c->engine) ? QDeclarativeEnginePrivate::get(c->engine) : 0; }
static QDeclarativeEnginePrivate *get(QScriptEngine *e) { return static_cast<QDeclarativeScriptEngine*>(e)->p; }
static QDeclarativeEngine *get(QDeclarativeEnginePrivate *p) { return p->q_func(); }
- QDeclarativeContextData *getContext(QScriptContext *);
- QUrl getUrl(QScriptContext *);
static QString urlToLocalFileOrQrc(const QUrl& url);
diff --git a/src/declarative/qml/qdeclarativeexpression.cpp b/src/declarative/qml/qdeclarativeexpression.cpp
index afd1be1025..a210e4e1d7 100644
--- a/src/declarative/qml/qdeclarativeexpression.cpp
+++ b/src/declarative/qml/qdeclarativeexpression.cpp
@@ -46,7 +46,6 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativerewrite_p.h"
#include "private/qdeclarativecompiler_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include <QtCore/qdebug.h>
#include <QtScript/qscriptprogram.h>
@@ -79,6 +78,11 @@ QDeclarativeQtScriptExpression::QDeclarativeQtScriptExpression()
QDeclarativeQtScriptExpression::~QDeclarativeQtScriptExpression()
{
+ v8function.Dispose();
+ v8qmlscope.Dispose();
+ v8function = v8::Persistent<v8::Function>();
+ v8qmlscope = v8::Persistent<v8::Function>();
+
if (guardList) { delete [] guardList; guardList = 0; }
if (dataRef) dataRef->release();
if (deleted) *deleted = true;
@@ -103,15 +107,16 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QS
expressionFunctionValid = false;
}
-void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, const QScriptValue &func,
+void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, v8::Handle<v8::Function> func,
QObject *me)
{
- expression = func.toString();
+ // XXX aakenned
+ // expression = func.toString();
QDeclarativeAbstractExpression::setContext(ctxt);
scopeObject = me;
- expressionFunction = func;
+ v8function = v8::Persistent<v8::Function>::New(func);
expressionFunctionMode = ExplicitContext;
expressionFunctionValid = true;
}
@@ -123,7 +128,8 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex
url = srcUrl;
line = lineNumber;
- if (dataRef) dataRef->release();
+ Q_ASSERT(!dataRef);
+
dataRef = rc;
if (dataRef) dataRef->addref();
@@ -136,45 +142,42 @@ void QDeclarativeExpressionPrivate::init(QDeclarativeContextData *ctxt, void *ex
bool isSharedProgram = progIdx & 0x80000000;
progIdx &= 0x7FFFFFFF;
- QDeclarativeEngine *engine = ctxt->engine;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (isSharedProgram) {
-
- if (!dd->cachedClosures.at(progIdx)) {
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- scriptContext->pushScope(ep->contextClass->newSharedContext());
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
- dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(expression, url, line));
- scriptEngine->popContext();
- }
-
- expressionFunction = *dd->cachedClosures.at(progIdx);
- expressionFunctionMode = SharedContext;
- expressionFunctionValid = true;
+ v8function = evalFunction(ctxt, me, expression, url, line, &v8qmlscope);
- } else {
+ expressionFunctionMode = ExplicitContext;
+ expressionFunctionValid = true;
- if (!dd->cachedPrograms.at(progIdx)) {
- dd->cachedPrograms[progIdx] = new QScriptProgram(expression, url, line);
- }
+ QDeclarativeAbstractExpression::setContext(ctxt);
+ scopeObject = me;
+}
- expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx),
- &expressionContext);
+// Callee owns the persistent handle
+v8::Persistent<v8::Function>
+QDeclarativeExpressionPrivate::evalFunction(QDeclarativeContextData *ctxt, QObject *scope,
+ const QString &code, const QString &filename, int line,
+ v8::Persistent<v8::Object> *qmlscope)
+{
+ QDeclarativeEngine *engine = ctxt->engine;
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- expressionFunctionMode = ExplicitContext;
- expressionFunctionValid = true;
- }
+ // XXX aakenned optimize
+ v8::HandleScope handle_scope;
+ v8::Context::Scope ctxtscope(ep->v8engine.context());
+
+ // XXX try/catch?
- QDeclarativeAbstractExpression::setContext(ctxt);
- scopeObject = me;
+ v8::Local<v8::Object> scopeobject = ep->v8engine.qmlScope(ctxt, scope);
+ v8::Local<v8::Script> script = ep->v8engine.qmlModeCompile(code, filename, line);
+ v8::Local<v8::Value> result = script->Run(scopeobject);
+ if (qmlscope) *qmlscope = v8::Persistent<v8::Object>::New(scopeobject);
+ return v8::Persistent<v8::Function>::New(v8::Local<v8::Function>::Cast(result));
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
const QString &program, const QString &fileName,
int lineNumber, QScriptValue *contextObject)
{
+#if 0
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
if (contextObject) {
@@ -187,12 +190,16 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex
QScriptValue rv = ep->scriptEngine.evaluate(program, fileName, lineNumber);
ep->scriptEngine.popContext();
return rv;
+#else
+ qFatal("Not impl");
+#endif
}
QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContextData *context, QObject *object,
const QScriptProgram &program,
QScriptValue *contextObject)
{
+#if 0
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(&ep->scriptEngine);
if (contextObject) {
@@ -205,6 +212,9 @@ QScriptValue QDeclarativeExpressionPrivate::evalInObjectScope(QDeclarativeContex
QScriptValue rv = ep->scriptEngine.evaluate(program);
ep->scriptEngine.popContext();
return rv;
+#else
+ qFatal("Not impl");
+#endif
}
/*!
@@ -317,16 +327,26 @@ QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QO
d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
-/*! \internal */
-QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, const QScriptValue &func,
+/*!
+ \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 QDeclarativeExpression(ctxt, scope, &function, ...);
+ */
+QDeclarativeExpression::QDeclarativeExpression(QDeclarativeContextData *ctxt, QObject *scope, void *functionPtr,
QDeclarativeExpressionPrivate &dd)
: QObject(dd, 0)
{
+ v8::Handle<v8::Function> function = *(v8::Handle<v8::Function> *)functionPtr;
+
Q_D(QDeclarativeExpression);
- d->init(ctxt, func, scope);
+ d->init(ctxt, function, scope);
if (QDeclarativeExpression_notifyIdx == -1)
QDeclarativeExpression_notifyIdx = QDeclarativeExpression::staticMetaObject.indexOfMethod("_q_notify()");
+
d->setNotifyObject(this, QDeclarativeExpression_notifyIdx);
}
@@ -377,34 +397,43 @@ void QDeclarativeExpression::setExpression(const QString &expression)
d->resetNotifyOnChange();
d->expression = expression;
d->expressionFunctionValid = false;
- d->expressionFunction = QScriptValue();
+ d->v8function.Dispose();
+ d->v8qmlscope.Dispose();
+ d->v8function = v8::Persistent<v8::Function>();
+ d->v8qmlscope = v8::Persistent<v8::Function>();
}
-void QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
- QDeclarativeError &error)
+void QDeclarativeExpressionPrivate::exceptionToError(v8::Handle<v8::Message> message,
+ QDeclarativeError &error)
{
- if (scriptEngine->hasUncaughtException() &&
- scriptEngine->uncaughtException().isError()) {
+ Q_ASSERT(!message.IsEmpty());
- QString fileName;
- int lineNumber = scriptEngine->uncaughtExceptionLineNumber();
+ v8::Handle<v8::Value> name = message->GetScriptResourceName();
+ v8::Handle<v8::String> description = message->Get();
+ int lineNumber = message->GetLineNumber();
- QScriptValue exception = scriptEngine->uncaughtException();
- QLatin1String fileNameProp("fileName");
+ Q_ASSERT(name->IsString());
- if (!exception.property(fileNameProp).toString().isEmpty()){
- fileName = exception.property(fileNameProp).toString();
- } else {
- fileName = QLatin1String("<Unknown File>");
- }
+ v8::Local<v8::String> file = name->ToString();
+ if (file->Length() == 0)
+ error.setUrl(QUrl(QLatin1String("<Unknown File>")));
+ else
+ error.setUrl(QUrl(QV8Engine::toStringStatic(file)));
- error.setUrl(QUrl(fileName));
- error.setLine(lineNumber);
- error.setColumn(-1);
- error.setDescription(exception.toString());
- } else {
- error = QDeclarativeError();
- }
+ 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 QDeclarativeExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
+ QDeclarativeError &error)
+{
+ qFatal("Not implemented - we use v8 now");
}
bool QDeclarativeQtScriptExpression::notifyOnValueChange() const
@@ -448,14 +477,14 @@ QDeclarativeQtScriptExpression::EvaluateFlags QDeclarativeQtScriptExpression::ev
return evalFlags;
}
-QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope, bool *isUndefined)
+v8::Local<v8::Value> QDeclarativeQtScriptExpression::v8value(QObject *secondaryScope, bool *isUndefined)
{
Q_ASSERT(context() && context()->engine);
Q_ASSERT(!trackChange || (guardObject && guardObjectNotifyIndex != -1));
- if (!expressionFunction.isValid()) {
+ if (v8function.IsEmpty() || v8function->IsUndefined()) {
if (isUndefined) *isUndefined = true;
- return QScriptValue();
+ return v8::Local<v8::Value>();
}
DeleteWatcher watcher(this);
@@ -467,7 +496,7 @@ QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope
ep->captureProperties = trackChange;
ep->capturedProperties.copyAndClear(lastCapturedProperties);
- QScriptValue value = eval(secondaryScope, isUndefined);
+ v8::Local<v8::Value> value = eval(secondaryScope, isUndefined);
if (!watcher.wasDeleted() && trackChange) {
if (ep->capturedProperties.count() == 0) {
@@ -487,59 +516,52 @@ QScriptValue QDeclarativeQtScriptExpression::scriptValue(QObject *secondaryScope
return value;
}
-QScriptValue QDeclarativeQtScriptExpression::eval(QObject *secondaryScope, bool *isUndefined)
+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);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
+ QObject *restoreSecondaryScope = 0;
+ if (secondaryScope)
+ restoreSecondaryScope = ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, secondaryScope);
- QDeclarativeContextData *oldSharedContext = 0;
- QObject *oldSharedScope = 0;
- QObject *oldOverride = 0;
- bool isShared = (expressionFunctionMode == SharedContext);
+ v8::TryCatch try_catch;
+ v8::Context::Scope scope(ep->v8engine.context()); // XXX is this needed?
- if (isShared) {
- oldSharedContext = ep->sharedContext;
- oldSharedScope = ep->sharedScope;
- ep->sharedContext = context();
- ep->sharedScope = scopeObject;
- } else {
- oldOverride = ep->contextClass->setOverrideObject(expressionContext, secondaryScope);
+ 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();
}
- QScriptValue thisObject;
- if (evalFlags & RequiresThisObject)
- thisObject = ep->objectClass->newQObject(scopeObject);
- QScriptValue svalue = expressionFunction.call(thisObject); // This could cause this c++ object to be deleted
+ v8::Local<v8::Value> result = v8function->Call(This, 0, 0);
- if (isShared) {
- ep->sharedContext = oldSharedContext;
- ep->sharedScope = oldSharedScope;
- } else if (!watcher.wasDeleted()) {
- ep->contextClass->setOverrideObject(expressionContext, oldOverride);
- }
+ if (secondaryScope)
+ ep->v8engine.contextWrapper()->setSecondaryScope(v8qmlscope, restoreSecondaryScope);
if (isUndefined)
- *isUndefined = svalue.isUndefined() || scriptEngine->hasUncaughtException();
+ *isUndefined = try_catch.HasCaught() || result->IsUndefined();
- // Handle exception
- if (scriptEngine->hasUncaughtException()) {
- if (!watcher.wasDeleted())
- QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
-
- scriptEngine->clearExceptions();
- return QScriptValue();
- } else {
- if (!watcher.wasDeleted())
+ if (watcher.wasDeleted()) {
+ } else if (try_catch.HasCaught()) {
+ v8::Local<v8::Message> message = try_catch.Message();
+ if (!message.IsEmpty()) {
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ } else {
error = QDeclarativeError();
-
- return svalue;
+ }
+ } else {
+ error = QDeclarativeError();
}
+
+ return result;
}
void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties)
@@ -625,31 +647,23 @@ void QDeclarativeQtScriptExpression::updateGuards(const QPODVector<QDeclarativeE
}
}
-QScriptValue QDeclarativeExpressionPrivate::scriptValue(QObject *secondaryScope, bool *isUndefined)
+// Must be called with a valid handle scope
+v8::Local<v8::Value> QDeclarativeExpressionPrivate::v8value(QObject *secondaryScope, bool *isUndefined)
{
if (!expressionFunctionValid) {
QDeclarativeEngine *engine = context()->engine;
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- expressionContext = ep->contextClass->newContext(context(), scopeObject);
- scriptContext->pushScope(expressionContext);
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
QDeclarativeRewrite::RewriteBinding rewriteBinding;
rewriteBinding.setName(name);
bool ok = true;
const QString code = rewriteBinding(expression, &ok);
- if (ok)
- expressionFunction = scriptEngine->evaluate(code, url, line);
-
- scriptEngine->popContext();
+ if (ok) v8function = evalFunction(context(), scopeObject, code, url, line, &v8qmlscope);
expressionFunctionMode = ExplicitContext;
expressionFunctionValid = true;
}
- return QDeclarativeQtScriptExpression::scriptValue(secondaryScope, isUndefined);
+ return QDeclarativeQtScriptExpression::v8value(secondaryScope, isUndefined);
}
QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
@@ -662,10 +676,19 @@ QVariant QDeclarativeExpressionPrivate::value(QObject *secondaryScope, bool *isU
}
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(q->engine());
+ QVariant rv;
+
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QVariant retn(ep->scriptValueToVariant(scriptValue(secondaryScope, isUndefined), qMetaTypeId<QList<QObject*> >()));
+
+ {
+ v8::HandleScope handle_scope;
+ v8::Local<v8::Value> result = v8value(secondaryScope, isUndefined);
+ rv = ep->v8engine.toVariant(result, qMetaTypeId<QList<QObject*> >());
+ }
+
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
- return retn;
+
+ return rv;
}
/*!
diff --git a/src/declarative/qml/qdeclarativeexpression.h b/src/declarative/qml/qdeclarativeexpression.h
index d40094b669..ae0aba6a4b 100644
--- a/src/declarative/qml/qdeclarativeexpression.h
+++ b/src/declarative/qml/qdeclarativeexpression.h
@@ -59,7 +59,6 @@ class QDeclarativeEngine;
class QDeclarativeContext;
class QDeclarativeExpressionPrivate;
class QDeclarativeContextData;
-class QScriptValue;
class Q_DECLARATIVE_EXPORT QDeclarativeExpression : public QObject
{
Q_OBJECT
@@ -95,7 +94,7 @@ Q_SIGNALS:
protected:
QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QString &,
QDeclarativeExpressionPrivate &dd);
- QDeclarativeExpression(QDeclarativeContextData *, QObject *, const QScriptValue &,
+ QDeclarativeExpression(QDeclarativeContextData *, QObject *, void *,
QDeclarativeExpressionPrivate &dd);
QDeclarativeExpression(QDeclarativeContextData *, void *, QDeclarativeRefCount *rc,
QObject *me, const QString &, int, QDeclarativeExpressionPrivate &dd);
diff --git a/src/declarative/qml/qdeclarativeexpression_p.h b/src/declarative/qml/qdeclarativeexpression_p.h
index 51cae0f9d4..04cbdad415 100644
--- a/src/declarative/qml/qdeclarativeexpression_p.h
+++ b/src/declarative/qml/qdeclarativeexpression_p.h
@@ -60,6 +60,8 @@
#include <QtScript/qscriptvalue.h>
+#include <private/qv8engine_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeAbstractExpression
@@ -124,7 +126,8 @@ public:
QString expression;
Mode expressionFunctionMode;
- QScriptValue expressionFunction;
+ v8::Persistent<v8::Function> v8function;
+ v8::Persistent<v8::Object> v8qmlscope;
QScriptValue expressionContext; // Only used in ExplicitContext
QObject *scopeObject; // Only used in SharedContext
@@ -137,7 +140,7 @@ public:
void setEvaluateFlags(EvaluateFlags flags);
EvaluateFlags evaluateFlags() const;
- QScriptValue scriptValue(QObject *secondaryScope, bool *isUndefined);
+ v8::Local<v8::Value> v8value(QObject *secondaryScope, bool *isUndefined);
class DeleteWatcher {
public:
@@ -152,7 +155,7 @@ public:
private:
void clearGuards();
- QScriptValue eval(QObject *secondaryScope, bool *isUndefined);
+ v8::Local<v8::Value> eval(QObject *secondaryScope, bool *isUndefined);
void updateGuards(const QPODVector<QDeclarativeEnginePrivate::CapturedProperty> &properties);
bool trackChange;
@@ -180,11 +183,12 @@ public:
~QDeclarativeExpressionPrivate();
void init(QDeclarativeContextData *, const QString &, QObject *);
- void init(QDeclarativeContextData *, const QScriptValue &, QObject *);
+ void init(QDeclarativeContextData *, v8::Handle<v8::Function>, QObject *);
void init(QDeclarativeContextData *, void *, QDeclarativeRefCount *, QObject *, const QString &, int);
QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
- QScriptValue scriptValue(QObject *secondaryScope = 0, bool *isUndefined = 0);
+
+ v8::Local<v8::Value> v8value(QObject *secondaryScope = 0, bool *isUndefined = 0);
static QDeclarativeExpressionPrivate *get(QDeclarativeExpression *expr) {
return static_cast<QDeclarativeExpressionPrivate *>(QObjectPrivate::get(expr));
@@ -197,11 +201,16 @@ public:
virtual void emitValueChanged();
static void exceptionToError(QScriptEngine *, QDeclarativeError &);
+ static void exceptionToError(v8::Handle<v8::Message>, QDeclarativeError &);
static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QString &, const QString &,
int, QScriptValue *);
static QScriptValue evalInObjectScope(QDeclarativeContextData *, QObject *, const QScriptProgram &,
QScriptValue *);
+ static v8::Persistent<v8::Function> evalFunction(QDeclarativeContextData *ctxt, QObject *scope,
+ const QString &code, const QString &filename, int line,
+ v8::Persistent<v8::Object> *qmlscope = 0);
+
bool expressionFunctionValid:1;
QString url; // This is a QString for a reason. QUrls are slooooooow...
diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp b/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
deleted file mode 100644
index 4bdfdd9b9e..0000000000
--- a/src/declarative/qml/qdeclarativeglobalscriptclass.cpp
+++ /dev/null
@@ -1,147 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativeglobalscriptclass_p.h"
-
-#include <QtCore/qstringlist.h>
-#include <QtCore/qvector.h>
-#include <QtScript/qscriptstring.h>
-#include <QtScript/qscriptengine.h>
-#include <QtScript/qscriptvalueiterator.h>
-
-#include <private/qscriptdeclarativeclass_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/*
- Used to prevent any writes to the global object.
-*/
-QDeclarativeGlobalScriptClass::QDeclarativeGlobalScriptClass(QScriptEngine *engine)
-: QScriptClass(engine)
-{
- QString eval = QLatin1String("eval");
- QString version = QLatin1String("version");
-
- QScriptValue originalGlobalObject = engine->globalObject();
-
- QScriptValue newGlobalObject = engine->newObject();
-
- {
- QScriptValueIterator iter(originalGlobalObject);
- QVector<QString> names;
- QVector<QScriptValue> values;
- QVector<QScriptValue::PropertyFlags> flags;
- while (iter.hasNext()) {
- iter.next();
-
- QString name = iter.name();
-
- if (name == version)
- continue;
-
- if (name != eval) {
- names.append(name);
- values.append(iter.value());
- flags.append(iter.flags() | QScriptValue::Undeletable);
- }
- newGlobalObject.setProperty(iter.scriptName(), iter.value());
-
- m_illegalNames.insert(name);
- }
- m_staticGlobalObject = QScriptDeclarativeClass::newStaticScopeObject(
- engine, names.size(), names.constData(), values.constData(), flags.constData());
- }
-
- newGlobalObject.setScriptClass(this);
- engine->setGlobalObject(newGlobalObject);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeGlobalScriptClass::queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id)
-{
- Q_UNUSED(object);
- Q_UNUSED(name);
- Q_UNUSED(flags);
- Q_UNUSED(id);
- return HandlesWriteAccess;
-}
-
-void QDeclarativeGlobalScriptClass::setProperty(QScriptValue &object,
- const QScriptString &name,
- uint id, const QScriptValue &value)
-{
- Q_UNUSED(object);
- Q_UNUSED(id);
- Q_UNUSED(value);
- QString error = QLatin1String("Invalid write to global property \"") +
- name.toString() + QLatin1Char('\"');
- engine()->currentContext()->throwError(error);
-}
-
-/* This method is for the use of tst_qdeclarativeecmascript::callQtInvokables() only */
-void QDeclarativeGlobalScriptClass::explicitSetProperty(const QStringList &names, const QList<QScriptValue> &values)
-{
- Q_ASSERT(names.count() == values.count());
- QScriptValue globalObject = engine()->globalObject();
-
- QScriptValue v = engine()->newObject();
-
- QScriptValueIterator iter(v);
- while (iter.hasNext()) {
- iter.next();
- v.setProperty(iter.scriptName(), iter.value());
- }
-
- for (int ii = 0; ii < names.count(); ++ii) {
- const QString &name = names.at(ii);
- const QScriptValue &value = values.at(ii);
- v.setProperty(name, value);
- }
-
- v.setScriptClass(this);
-
- engine()->setGlobalObject(v);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativeinclude.cpp b/src/declarative/qml/qdeclarativeinclude.cpp
deleted file mode 100644
index 7102209126..0000000000
--- a/src/declarative/qml/qdeclarativeinclude.cpp
+++ /dev/null
@@ -1,310 +0,0 @@
-/****************************************************************************
-**
-** 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 "qdeclarativeinclude_p.h"
-
-#include <QtScript/qscriptengine.h>
-#include <QtNetwork/qnetworkrequest.h>
-#include <QtNetwork/qnetworkreply.h>
-#include <QtCore/qfile.h>
-
-#include <private/qdeclarativeengine_p.h>
-#include <private/qdeclarativeglobalscriptclass_p.h>
-
-QT_BEGIN_NAMESPACE
-
-QDeclarativeInclude::QDeclarativeInclude(const QUrl &url,
- QDeclarativeEngine *engine,
- QScriptContext *ctxt)
-: QObject(engine), m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0)
-{
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- m_context = ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
-
- m_scope[0] = QScriptDeclarativeClass::scopeChainValue(ctxt, -4);
- m_scope[1] = QScriptDeclarativeClass::scopeChainValue(ctxt, -5);
-
- m_scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- m_network = QDeclarativeScriptEngine::get(m_scriptEngine)->networkAccessManager();
-
- m_result = resultValue(m_scriptEngine);
-
- QNetworkRequest request;
- request.setUrl(url);
-
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
-}
-
-QDeclarativeInclude::~QDeclarativeInclude()
-{
- delete m_reply;
-}
-
-QScriptValue QDeclarativeInclude::resultValue(QScriptEngine *engine, Status status)
-{
- QScriptValue result = engine->newObject();
- result.setProperty(QLatin1String("OK"), QScriptValue(engine, Ok));
- result.setProperty(QLatin1String("LOADING"), QScriptValue(engine, Loading));
- result.setProperty(QLatin1String("NETWORK_ERROR"), QScriptValue(engine, NetworkError));
- result.setProperty(QLatin1String("EXCEPTION"), QScriptValue(engine, Exception));
-
- result.setProperty(QLatin1String("status"), QScriptValue(engine, status));
- return result;
-}
-
-QScriptValue QDeclarativeInclude::result() const
-{
- return m_result;
-}
-
-void QDeclarativeInclude::setCallback(const QScriptValue &c)
-{
- m_callback = c;
-}
-
-QScriptValue QDeclarativeInclude::callback() const
-{
- return m_callback;
-}
-
-#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
-void QDeclarativeInclude::finished()
-{
- m_redirectCount++;
-
- if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
- QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
- if (redirect.isValid()) {
- m_url = m_url.resolved(redirect.toUrl());
- delete m_reply;
-
- QNetworkRequest request;
- request.setUrl(m_url);
-
- m_reply = m_network->get(request);
- QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
- return;
- }
- }
-
- if (m_reply->error() == QNetworkReply::NoError) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine);
-
- QByteArray data = m_reply->readAll();
-
- QString code = QString::fromUtf8(data);
-
- QString urlString = m_url.toString();
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(m_scriptEngine);
- scriptContext->pushScope(ep->contextClass->newUrlContext(m_context, 0, urlString));
- scriptContext->pushScope(m_scope[0]);
-
- scriptContext->pushScope(m_scope[1]);
- scriptContext->setActivationObject(m_scope[1]);
- QDeclarativeScriptParser::extractPragmas(code);
-
- m_scriptEngine->evaluate(code, urlString, 1);
-
- m_scriptEngine->popContext();
-
- if (m_scriptEngine->hasUncaughtException()) {
- m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Exception));
- m_result.setProperty(QLatin1String("exception"), m_scriptEngine->uncaughtException());
- m_scriptEngine->clearExceptions();
- } else {
- m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, Ok));
- }
- } else {
- m_result.setProperty(QLatin1String("status"), QScriptValue(m_scriptEngine, NetworkError));
- }
-
- callback(m_scriptEngine, m_callback, m_result);
-
- disconnect();
- deleteLater();
-}
-
-void QDeclarativeInclude::callback(QScriptEngine *engine, QScriptValue &callback, QScriptValue &status)
-{
- if (callback.isValid()) {
- QScriptValue args = engine->newArray(1);
- args.setProperty(0, status);
- callback.call(QScriptValue(), args);
- }
-}
-
-/*
- Documented in qdeclarativeengine.cpp
-*/
-QScriptValue QDeclarativeInclude::include(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() == 0)
- return engine->undefinedValue();
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- QUrl contextUrl = ep->contextClass->urlFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
- if (contextUrl.isEmpty())
- return ctxt->throwError(QLatin1String("Qt.include(): Can only be called from JavaScript files"));
-
- QString urlString = ctxt->argument(0).toString();
- QUrl url(urlString);
- if (url.isRelative()) {
- url = QUrl(contextUrl).resolved(url);
- urlString = url.toString();
- }
-
- QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
-
- QScriptValue func = ctxt->argument(1);
- if (!func.isFunction())
- func = QScriptValue();
-
- QScriptValue result;
- if (localFile.isEmpty()) {
- QDeclarativeInclude *i =
- new QDeclarativeInclude(url, QDeclarativeEnginePrivate::getEngine(engine), ctxt);
-
- if (func.isValid())
- i->setCallback(func);
-
- result = i->result();
- } else {
-
- QFile f(localFile);
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray data = f.readAll();
- QString code = QString::fromUtf8(data);
-
- QDeclarativeContextData *context =
- ep->contextClass->contextFromValue(QScriptDeclarativeClass::scopeChainValue(ctxt, -3));
-
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine);
- scriptContext->pushScope(ep->contextClass->newUrlContext(context, 0, urlString));
- scriptContext->pushScope(ep->globalClass->staticGlobalObject());
- QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -5);
- scriptContext->pushScope(scope);
- scriptContext->setActivationObject(scope);
- QDeclarativeScriptParser::extractPragmas(code);
-
- engine->evaluate(code, urlString, 1);
-
- engine->popContext();
-
- if (engine->hasUncaughtException()) {
- result = resultValue(engine, Exception);
- result.setProperty(QLatin1String("exception"), engine->uncaughtException());
- engine->clearExceptions();
- } else {
- result = resultValue(engine, Ok);
- }
- callback(engine, func, result);
- } else {
- result = resultValue(engine, NetworkError);
- callback(engine, func, result);
- }
- }
-
- return result;
-}
-
-QScriptValue QDeclarativeInclude::worker_include(QScriptContext *ctxt, QScriptEngine *engine)
-{
- if (ctxt->argumentCount() == 0)
- return engine->undefinedValue();
-
- QString urlString = ctxt->argument(0).toString();
- QUrl url(ctxt->argument(0).toString());
- if (url.isRelative()) {
- QString contextUrl = QScriptDeclarativeClass::scopeChainValue(ctxt, -3).data().toString();
- Q_ASSERT(!contextUrl.isEmpty());
-
- url = QUrl(contextUrl).resolved(url);
- urlString = url.toString();
- }
-
- QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
-
- QScriptValue func = ctxt->argument(1);
- if (!func.isFunction())
- func = QScriptValue();
-
- QScriptValue result;
- if (!localFile.isEmpty()) {
-
- QFile f(localFile);
- if (f.open(QIODevice::ReadOnly)) {
- QByteArray data = f.readAll();
- QString code = QString::fromUtf8(data);
-
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(engine);
- QScriptValue urlContext = engine->newObject();
- urlContext.setData(QScriptValue(engine, urlString));
- scriptContext->pushScope(urlContext);
-
- QScriptValue scope = QScriptDeclarativeClass::scopeChainValue(ctxt, -4);
- scriptContext->pushScope(scope);
- scriptContext->setActivationObject(scope);
- QDeclarativeScriptParser::extractPragmas(code);
-
- engine->evaluate(code, urlString, 1);
-
- engine->popContext();
-
- if (engine->hasUncaughtException()) {
- result = resultValue(engine, Exception);
- result.setProperty(QLatin1String("exception"), engine->uncaughtException());
- engine->clearExceptions();
- } else {
- result = resultValue(engine, Ok);
- }
- callback(engine, func, result);
- } else {
- result = resultValue(engine, NetworkError);
- callback(engine, func, result);
- }
- }
-
- return result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeintegercache.cpp b/src/declarative/qml/qdeclarativeintegercache.cpp
index cbeb16842f..ae2fbfca87 100644
--- a/src/declarative/qml/qdeclarativeintegercache.cpp
+++ b/src/declarative/qml/qdeclarativeintegercache.cpp
@@ -41,34 +41,21 @@
#include "private/qdeclarativeintegercache_p.h"
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativemetatype_p.h"
-
QT_BEGIN_NAMESPACE
-QDeclarativeIntegerCache::QDeclarativeIntegerCache(QDeclarativeEngine *e)
-: QDeclarativeCleanup(e), engine(e)
+QDeclarativeIntegerCache::QDeclarativeIntegerCache()
{
}
QDeclarativeIntegerCache::~QDeclarativeIntegerCache()
{
- clear();
-}
-
-void QDeclarativeIntegerCache::clear()
-{
- qDeleteAll(stringCache);
- stringCache.clear();
- identifierCache.clear();
- engine = 0;
}
QString QDeclarativeIntegerCache::findId(int value) const
{
for (StringCache::ConstIterator iter = stringCache.begin();
iter != stringCache.end(); ++iter) {
- if (iter.value() && iter.value()->value == value)
+ if (iter.value() == value)
return iter.key();
}
return QString();
@@ -78,19 +65,13 @@ void QDeclarativeIntegerCache::add(const QString &id, int value)
{
Q_ASSERT(!stringCache.contains(id));
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- // ### use contextClass
- Data *d = new Data(enginePriv->objectClass->createPersistentIdentifier(id), value);
-
- stringCache.insert(id, d);
- identifierCache.insert(d->identifier, d);
+ stringCache.insert(id, value);
}
int QDeclarativeIntegerCache::value(const QString &id)
{
- Data *d = stringCache.value(id);
- return d?d->value:-1;
+ int *rv = stringCache.value(id);
+ return rv?*rv:-1;
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeintegercache_p.h b/src/declarative/qml/qdeclarativeintegercache_p.h
index 686880e0d7..33dd2485ff 100644
--- a/src/declarative/qml/qdeclarativeintegercache_p.h
+++ b/src/declarative/qml/qdeclarativeintegercache_p.h
@@ -54,51 +54,35 @@
//
#include "private/qdeclarativerefcount_p.h"
-#include "private/qdeclarativecleanup_p.h"
-
-#include <QtCore/qhash.h>
-
-#include <private/qscriptdeclarativeclass_p.h>
+#include "private/qhashedstring_p.h"
QT_BEGIN_NAMESPACE
class QDeclarativeType;
class QDeclarativeEngine;
-class QDeclarativeIntegerCache : public QDeclarativeRefCount, public QDeclarativeCleanup
+class QDeclarativeIntegerCache : public QDeclarativeRefCount
{
public:
- QDeclarativeIntegerCache(QDeclarativeEngine *);
+ QDeclarativeIntegerCache();
virtual ~QDeclarativeIntegerCache();
inline int count() const;
void add(const QString &, int);
+
int value(const QString &);
- QString findId(int value) const;
- inline int value(const QScriptDeclarativeClass::Identifier &id) const;
+ inline int value(v8::Handle<v8::String>);
-protected:
- virtual void clear();
+ QString findId(int value) const;
private:
- struct Data : public QScriptDeclarativeClass::PersistentIdentifier {
- Data(const QScriptDeclarativeClass::PersistentIdentifier &i, int v)
- : QScriptDeclarativeClass::PersistentIdentifier(i), value(v) {}
-
- int value;
- };
-
- typedef QHash<QString, Data *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, Data *> IdentifierCache;
-
+ typedef QStringHash<int> StringCache;
StringCache stringCache;
- IdentifierCache identifierCache;
- QDeclarativeEngine *engine;
};
-int QDeclarativeIntegerCache::value(const QScriptDeclarativeClass::Identifier &id) const
+int QDeclarativeIntegerCache::value(v8::Handle<v8::String> name)
{
- Data *d = identifierCache.value(id);
- return d?d->value:-1;
+ int *result = stringCache.value(name);
+ return result?*result:-1;
}
int QDeclarativeIntegerCache::count() const
diff --git a/src/declarative/qml/qdeclarativelistscriptclass.cpp b/src/declarative/qml/qdeclarativelistscriptclass.cpp
deleted file mode 100644
index ace777e6ff..0000000000
--- a/src/declarative/qml/qdeclarativelistscriptclass.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativelistscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativelist_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct ListData : public QScriptDeclarativeClass::Object {
- QDeclarativeGuard<QObject> object;
- QDeclarativeListProperty<QObject> property;
- int propertyType;
-};
-
-QDeclarativeListScriptClass::QDeclarativeListScriptClass(QDeclarativeEngine *e)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(e)), engine(e)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- Q_UNUSED(scriptEngine);
-
- m_lengthId = createPersistentIdentifier(QLatin1String("length"));
-}
-
-QDeclarativeListScriptClass::~QDeclarativeListScriptClass()
-{
-}
-
-QScriptValue QDeclarativeListScriptClass::newList(QObject *object, int propId, int propType)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (!object || propId == -1)
- return scriptEngine->nullValue();
-
- ListData *data = new ListData;
- data->object = object;
- data->propertyType = propType;
- void *args[] = { &data->property, 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
-
- return newObject(scriptEngine, this, data);
-}
-
-QScriptValue QDeclarativeListScriptClass::newList(const QDeclarativeListProperty<QObject> &prop, int propType)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- ListData *data = new ListData;
- data->object = prop.object;
- data->property = prop;
- data->propertyType = propType;
-
- return newObject(scriptEngine, this, data);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeListScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(object);
- Q_UNUSED(flags);
- if (name == m_lengthId.identifier)
- return QScriptClass::HandlesReadAccess;
-
- bool ok = false;
- quint32 idx = toArrayIndex(name, &ok);
-
- if (ok) {
- lastIndex = idx;
- return QScriptClass::HandlesReadAccess;
- } else {
- return 0;
- }
-}
-
-QDeclarativeListScriptClass::Value QDeclarativeListScriptClass::property(Object *obj, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- ListData *data = (ListData *)obj;
- if (!data->object)
- return Value();
-
- quint32 count = data->property.count?data->property.count(&data->property):0;
-
- if (name == m_lengthId.identifier)
- return Value(scriptEngine, count);
- else if (lastIndex < count && data->property.at)
- return Value(scriptEngine, enginePriv->objectClass->newQObject(data->property.at(&data->property, lastIndex)));
- else
- return Value();
-}
-
-QVariant QDeclarativeListScriptClass::toVariant(Object *obj, bool *ok)
-{
- ListData *data = (ListData *)obj;
-
- if (!data->object) {
- if (ok) *ok = false;
- return QVariant();
- }
-
- return QVariant::fromValue(QDeclarativeListReferencePrivate::init(data->property, data->propertyType, engine));
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativemetatype.cpp b/src/declarative/qml/qdeclarativemetatype.cpp
index ede02e9f30..d00a28eb2d 100644
--- a/src/declarative/qml/qdeclarativemetatype.cpp
+++ b/src/declarative/qml/qdeclarativemetatype.cpp
@@ -1099,8 +1099,10 @@ QT_END_NAMESPACE
#include <QtGui/qvector3d.h>
#include <QtGui/qvector4d.h>
#include <QtGui/qquaternion.h>
+#include <private/qv8engine_p.h>
Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
@@ -1181,6 +1183,7 @@ bool QDeclarativeMetaType::canCopy(int type)
default:
if (type == qMetaTypeId<QVariant>() ||
type == qMetaTypeId<QScriptValue>() ||
+ type == qMetaTypeId<QDeclarativeV8Handle>() ||
typeCategory(type) != Unknown) {
return true;
}
@@ -1403,6 +1406,9 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
} else if (type == qMetaTypeId<QScriptValue>()) {
*static_cast<NS(QScriptValue) *>(data) = *static_cast<const NS(QScriptValue)*>(copy);
return true;
+ } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
+ *static_cast<NS(QDeclarativeV8Handle) *>(data) = *static_cast<const NS(QDeclarativeV8Handle)*>(copy);
+ return true;
} else if (typeCategory(type) != Unknown) {
*static_cast<void **>(data) = *static_cast<void* const *>(copy);
return true;
@@ -1610,6 +1616,9 @@ bool QDeclarativeMetaType::copy(int type, void *data, const void *copy)
} else if (type == qMetaTypeId<QScriptValue>()) {
*static_cast<NS(QScriptValue) *>(data) = NS(QScriptValue)();
return true;
+ } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
+ *static_cast<NS(QDeclarativeV8Handle) *>(data) = NS(QDeclarativeV8Handle)();
+ return true;
} else if (typeCategory(type) != Unknown) {
*static_cast<void **>(data) = 0;
return true;
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
deleted file mode 100644
index edc1755a72..0000000000
--- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp
+++ /dev/null
@@ -1,1226 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativeobjectscriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativedata_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativevmemetaobject_p.h"
-
-#include <QtCore/qtimer.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtScript/qscriptcontextinfo.h>
-
-Q_DECLARE_METATYPE(QScriptValue)
-
-#if defined(__GNUC__)
-# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
-// The code in this file does not violate strict aliasing, but GCC thinks it does
-// so turn off the warnings for us to have a clean build
-# pragma GCC diagnostic ignored "-Wstrict-aliasing"
-# endif
-#endif
-
-QT_BEGIN_NAMESPACE
-
-struct ObjectData : public QScriptDeclarativeClass::Object {
- ObjectData(QObject *o, int t) : object(o), type(t) {
- if (o) {
- QDeclarativeData *ddata = QDeclarativeData::get(object, true);
- if (ddata) ddata->objectDataRefCount++;
- }
- }
-
- virtual ~ObjectData() {
- if (object && !object->parent()) {
- QDeclarativeData *ddata = QDeclarativeData::get(object, false);
- if (ddata && !ddata->indestructible && 0 == --ddata->objectDataRefCount)
- object->deleteLater();
- }
- }
-
- QDeclarativeGuard<QObject> object;
- int type;
-};
-
-/*
- The QDeclarativeObjectScriptClass handles property access for QObjects
- via QtScript. It is also used to provide a more useful API in
- QtScript for QML.
- */
-QDeclarativeObjectScriptClass::QDeclarativeObjectScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- methods(bindEngine), lastData(0), engine(bindEngine)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- m_destroy = scriptEngine->newFunction(destroy);
- m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
- m_toString = scriptEngine->newFunction(tostring);
- m_toStringId = createPersistentIdentifier(QLatin1String("toString"));
-}
-
-QDeclarativeObjectScriptClass::~QDeclarativeObjectScriptClass()
-{
-}
-
-QScriptValue QDeclarativeObjectScriptClass::newQObject(QObject *object, int type)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (!object)
- return scriptEngine->nullValue();
-// return newObject(scriptEngine, this, new ObjectData(object, type));
-
- if (QObjectPrivate::get(object)->wasDeleted)
- return scriptEngine->undefinedValue();
-
- QDeclarativeData *ddata = QDeclarativeData::get(object, true);
-
- if (!ddata) {
- return scriptEngine->undefinedValue();
- } else if (!ddata->indestructible && !object->parent()) {
- return newObject(scriptEngine, this, new ObjectData(object, type));
- } else if (!ddata->scriptValue) {
- ddata->scriptValue = new QScriptValue(newObject(scriptEngine, this, new ObjectData(object, type)));
- return *ddata->scriptValue;
- } else if (ddata->scriptValue->engine() == QDeclarativeEnginePrivate::getScriptEngine(engine)) {
- return *ddata->scriptValue;
- } else {
- return newObject(scriptEngine, this, new ObjectData(object, type));
- }
-}
-
-QObject *QDeclarativeObjectScriptClass::toQObject(const QScriptValue &value) const
-{
- return value.toQObject();
-}
-
-int QDeclarativeObjectScriptClass::objectType(const QScriptValue &value) const
-{
- if (scriptClass(value) != this)
- return QVariant::Invalid;
-
- Object *o = object(value);
- return ((ObjectData*)(o))->type;
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- return queryProperty(toQObject(object), name, flags, 0);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectScriptClass::queryProperty(QObject *obj, const Identifier &name,
- QScriptClass::QueryFlags flags, QDeclarativeContextData *evalContext,
- QueryHints hints)
-{
- Q_UNUSED(flags);
- lastData = 0;
- lastTNData = 0;
-
- if (name == m_destroyId.identifier ||
- name == m_toStringId.identifier)
- return QScriptClass::HandlesReadAccess;
-
- if (!obj)
- return 0;
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
- lastData = QDeclarativePropertyCache::property(engine, obj, name, local);
- if ((hints & ImplicitObject) && lastData && lastData->revision != 0) {
-
- QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(lastData))
- return 0;
- }
-
- if (lastData)
- return QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
-
- if (!(hints & SkipAttachedProperties)) {
- if (!evalContext && context()) {
- // Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context(), -3);
- if (scopeNode.isValid()) {
- Q_ASSERT(scriptClass(scopeNode) == enginePrivate->contextClass);
-
- evalContext = enginePrivate->contextClass->contextFromValue(scopeNode);
- }
- }
-
- if (evalContext && evalContext->imports) {
- QDeclarativeTypeNameCache::Data *data = evalContext->imports->data(name);
- if (data) {
- lastTNData = data;
- return QScriptClass::HandlesReadAccess;
- }
- }
- }
-
- if (!(hints & ImplicitObject)) {
- local.coreIndex = -1;
- lastData = &local;
- return QScriptClass::HandlesWriteAccess;
- }
-
- return 0;
-}
-
-QDeclarativeObjectScriptClass::Value
-QDeclarativeObjectScriptClass::property(Object *object, const Identifier &name)
-{
- return property(toQObject(object), name);
-}
-
-QDeclarativeObjectScriptClass::Value
-QDeclarativeObjectScriptClass::property(QObject *obj, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (name == m_destroyId.identifier)
- return Value(scriptEngine, m_destroy);
- else if (name == m_toStringId.identifier)
- return Value(scriptEngine, m_toString);
-
- if (lastData && !lastData->isValid())
- return Value();
-
- Q_ASSERT(obj);
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- if (lastTNData) {
-
- if (lastTNData->type)
- return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->type));
- else
- return Value(scriptEngine, enginePriv->typeNameClass->newObject(obj, lastTNData->typeNamespace));
-
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsFunction) {
- if (lastData->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
- return Value(scriptEngine, ((QDeclarativeVMEMetaObject *)(obj->metaObject()))->vmeMethod(lastData->coreIndex));
- } else {
- // Uncomment to use QtScript method call logic
- // QScriptValue sobj = scriptEngine->newQObject(obj);
- // return Value(scriptEngine, sobj.property(toString(name)));
- return Value(scriptEngine, methods.newMethod(obj, lastData));
- }
- } else {
- if (enginePriv->captureProperties && !(lastData->flags & QDeclarativePropertyCache::Data::IsConstant)) {
- if (lastData->coreIndex == 0) {
- enginePriv->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(QDeclarativeData::get(obj, true)->objectNameNotifier());
- } else {
- enginePriv->capturedProperties <<
- QDeclarativeEnginePrivate::CapturedProperty(obj, lastData->coreIndex, lastData->notifyIndex);
- }
- }
-
- if (QDeclarativeValueTypeFactory::isValueType((uint)lastData->propType)) {
- QDeclarativeValueType *valueType = enginePriv->valueTypes[lastData->propType];
- if (valueType)
- return Value(scriptEngine, enginePriv->valueTypeClass->newObject(obj, lastData->coreIndex, valueType));
- }
-
- if (lastData->flags & QDeclarativePropertyCache::Data::IsQList) {
- return Value(scriptEngine, enginePriv->listClass->newList(obj, lastData->coreIndex, lastData->propType));
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- QObject *rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, newQObject(rv, lastData->propType));
- } else if (lastData->flags & QDeclarativePropertyCache::Data::IsQScriptValue) {
- QScriptValue rv = scriptEngine->nullValue();
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::QReal) {
- qreal rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Int || lastData->flags & QDeclarativePropertyCache::Data::IsEnumType) {
- int rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Bool) {
- bool rv = false;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::QString) {
- QString rv;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::UInt) {
- uint rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Float) {
- float rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else if (lastData->propType == QMetaType::Double) {
- double rv = 0;
- void *args[] = { &rv, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, lastData->coreIndex, args);
- return Value(scriptEngine, rv);
- } else {
- QVariant var = obj->metaObject()->property(lastData->coreIndex).read(obj);
- return Value(scriptEngine, enginePriv->scriptValueFromVariant(var));
- }
- }
-}
-
-void QDeclarativeObjectScriptClass::setProperty(Object *object,
- const Identifier &name,
- const QScriptValue &value)
-{
- return setProperty(toQObject(object), name, value, context());
-}
-
-void QDeclarativeObjectScriptClass::setProperty(QObject *obj,
- const Identifier &name,
- const QScriptValue &value,
- QScriptContext *context,
- QDeclarativeContextData *evalContext)
-{
- Q_UNUSED(name);
-
- Q_ASSERT(obj);
- Q_ASSERT(lastData);
- Q_ASSERT(context);
-
- if (!lastData->isValid()) {
- QString error = QLatin1String("Cannot assign to non-existent property \"") +
- toString(name) + QLatin1Char('\"');
- context->throwError(error);
- return;
- }
-
- if (!(lastData->flags & QDeclarativePropertyCache::Data::IsWritable) &&
- !(lastData->flags & QDeclarativePropertyCache::Data::IsQList)) {
- QString error = QLatin1String("Cannot assign to read-only property \"") +
- toString(name) + QLatin1Char('\"');
- context->throwError(error);
- return;
- }
-
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
-
- if (!evalContext) {
- // Global object, QScriptContext activation object, QDeclarativeContext object
- QScriptValue scopeNode = scopeChainValue(context, -3);
- if (scopeNode.isValid()) {
- Q_ASSERT(scriptClass(scopeNode) == enginePriv->contextClass);
-
- evalContext = enginePriv->contextClass->contextFromValue(scopeNode);
- }
- }
-
- QDeclarativeBinding *newBinding = 0;
- if (value.isFunction() && !value.isRegExp()) {
- QScriptContextInfo ctxtInfo(context);
- QDeclarativePropertyCache::ValueTypeData valueTypeData;
-
- newBinding = new QDeclarativeBinding(value, obj, evalContext);
- newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
- newBinding->setTarget(QDeclarativePropertyPrivate::restore(*lastData, valueTypeData, obj, evalContext));
- if (newBinding->expression().contains(QLatin1String("this")))
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
- }
-
- QDeclarativeAbstractBinding *delBinding =
- QDeclarativePropertyPrivate::setBinding(obj, lastData->coreIndex, -1, newBinding);
- if (delBinding)
- delBinding->destroy();
-
- if (value.isNull() && lastData->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- QObject *o = 0;
- int status = -1;
- int flags = 0;
- void *argv[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty, lastData->coreIndex, argv);
- } else if (value.isUndefined() && lastData->flags & QDeclarativePropertyCache::Data::IsResettable) {
- void *a[] = { 0 };
- QMetaObject::metacall(obj, QMetaObject::ResetProperty, lastData->coreIndex, a);
- } else if (value.isUndefined() && lastData->propType == qMetaTypeId<QVariant>()) {
- QDeclarativePropertyPrivate::write(obj, *lastData, QVariant(), evalContext);
- } else if (value.isUndefined()) {
- QString error = QLatin1String("Cannot assign [undefined] to ") +
- QLatin1String(QMetaType::typeName(lastData->propType));
- context->throwError(error);
- } else if (value.isFunction() && !value.isRegExp()) {
- // this is handled by the binding creation above
- } else {
- //### expand optimization for other known types
- if (lastData->propType == QMetaType::Int && value.isNumber()) {
- int rawValue = qRound(value.toNumber());
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- } else if (lastData->propType == QMetaType::QReal && value.isNumber()) {
- qreal rawValue = qreal(value.toNumber());
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- } else if (lastData->propType == QMetaType::QString && value.isString()) {
- const QString &rawValue = value.toString();
- int status = -1;
- int flags = 0;
- void *a[] = { (void *)&rawValue, 0, &status, &flags };
- QMetaObject::metacall(obj, QMetaObject::WriteProperty,
- lastData->coreIndex, a);
- return;
- }
-
- QVariant v;
- if (lastData->flags & QDeclarativePropertyCache::Data::IsQList)
- v = enginePriv->scriptValueToVariant(value, qMetaTypeId<QList<QObject *> >());
- else
- v = enginePriv->scriptValueToVariant(value, lastData->propType);
-
- if (!QDeclarativePropertyPrivate::write(obj, *lastData, v, evalContext)) {
- const char *valueType = 0;
- if (v.userType() == QVariant::Invalid) valueType = "null";
- else valueType = QMetaType::typeName(v.userType());
-
- QString error = QLatin1String("Cannot assign ") +
- QLatin1String(valueType) +
- QLatin1String(" to ") +
- QLatin1String(QMetaType::typeName(lastData->propType));
- context->throwError(error);
- }
- }
-}
-
-bool QDeclarativeObjectScriptClass::isQObject() const
-{
- return true;
-}
-
-QObject *QDeclarativeObjectScriptClass::toQObject(Object *object, bool *ok)
-{
- if (ok) *ok = true;
-
- ObjectData *data = (ObjectData*)object;
- return data->object.data();
-}
-
-QScriptValue QDeclarativeObjectScriptClass::tostring(QScriptContext *context, QScriptEngine *)
-{
- QObject* obj = context->thisObject().toQObject();
-
- QString ret;
- if(obj){
- QString objectName = obj->objectName();
-
- ret += QString::fromUtf8(obj->metaObject()->className());
- ret += QLatin1String("(0x");
- ret += QString::number((quintptr)obj,16);
-
- if (!objectName.isEmpty()) {
- ret += QLatin1String(", \"");
- ret += objectName;
- ret += QLatin1Char('\"');
- }
-
- ret += QLatin1Char(')');
- }else{
- ret += QLatin1String("null");
- }
- return QScriptValue(ret);
-}
-
-QScriptValue QDeclarativeObjectScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->objectClass)
- return engine->undefinedValue();
-
- ObjectData *data = (ObjectData *)p->objectClass->object(that);
- if (!data->object)
- return engine->undefinedValue();
-
- QDeclarativeData *ddata = QDeclarativeData::get(data->object, false);
- if (!ddata || ddata->indestructible)
- return engine->currentContext()->throwError(QLatin1String("Invalid attempt to destroy() an indestructible object"));
-
- QObject *obj = data->object;
- int delay = 0;
- if (context->argumentCount() > 0)
- delay = context->argument(0).toInt32();
- if (delay > 0)
- QTimer::singleShot(delay, obj, SLOT(deleteLater()));
- else
- obj->deleteLater();
-
- return engine->undefinedValue();
-}
-
-QStringList QDeclarativeObjectScriptClass::propertyNames(Object *object)
-{
- QObject *obj = toQObject(object);
- if (!obj)
- return QStringList();
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
-
- QDeclarativePropertyCache *cache = 0;
- QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata)
- cache = ddata->propertyCache;
- if (!cache) {
- cache = enginePrivate->cache(obj);
- if (cache) {
- if (ddata) { cache->addref(); ddata->propertyCache = cache; }
- } else {
- // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
- // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal.
- // XXX This is a workaround for QTBUG-9420.
- const QMetaObject *mo = obj->metaObject();
- QStringList r;
- int pc = mo->propertyCount();
- int po = mo->propertyOffset();
- for (int i=po; i<pc; ++i)
- r += QString::fromUtf8(mo->property(i).name());
- return r;
- }
- }
- return cache->propertyNames();
-}
-
-bool QDeclarativeObjectScriptClass::compare(Object *o1, Object *o2)
-{
- ObjectData *d1 = (ObjectData *)o1;
- ObjectData *d2 = (ObjectData *)o2;
-
- return d1 == d2 || d1->object == d2->object;
-}
-
-struct MethodData : public QScriptDeclarativeClass::Object {
- MethodData(QObject *o, const QDeclarativePropertyCache::Data &d) : object(o), data(d) {}
-
- QDeclarativeGuard<QObject> object;
- QDeclarativePropertyCache::Data data;
-};
-
-QDeclarativeObjectMethodScriptClass::QDeclarativeObjectMethodScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- engine(bindEngine)
-{
- qRegisterMetaType<QList<QObject *> >("QList<QObject *>");
-
- setSupportsCall(true);
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- m_connect = scriptEngine->newFunction(connect);
- m_connectId = createPersistentIdentifier(QLatin1String("connect"));
- m_disconnect = scriptEngine->newFunction(disconnect);
- m_disconnectId = createPersistentIdentifier(QLatin1String("disconnect"));
-}
-
-QDeclarativeObjectMethodScriptClass::~QDeclarativeObjectMethodScriptClass()
-{
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::newMethod(QObject *object, const QDeclarativePropertyCache::Data *method)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return newObject(scriptEngine, this, new MethodData(object, *method));
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::connect(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
-
- QScriptValue that = context->thisObject();
- if (&p->objectClass->methods != scriptClass(that))
- return engine->undefinedValue();
-
- MethodData *data = (MethodData *)object(that);
-
- if (!data->object || context->argumentCount() == 0)
- return engine->undefinedValue();
-
- QByteArray signal("2");
- signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
-
- if (context->argumentCount() == 1) {
- qScriptConnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
- } else {
- qScriptConnect(data->object, signal.constData(), context->argument(0), context->argument(1));
- }
-
- return engine->undefinedValue();
-}
-
-QScriptValue QDeclarativeObjectMethodScriptClass::disconnect(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
-
- QScriptValue that = context->thisObject();
- if (&p->objectClass->methods != scriptClass(that))
- return engine->undefinedValue();
-
- MethodData *data = (MethodData *)object(that);
-
- if (!data->object || context->argumentCount() == 0)
- return engine->undefinedValue();
-
- QByteArray signal("2");
- signal.append(data->object->metaObject()->method(data->data.coreIndex).signature());
-
- if (context->argumentCount() == 1) {
- qScriptDisconnect(data->object, signal.constData(), QScriptValue(), context->argument(0));
- } else {
- qScriptDisconnect(data->object, signal.constData(), context->argument(0), context->argument(1));
- }
-
- return engine->undefinedValue();
-}
-
-QScriptClass::QueryFlags
-QDeclarativeObjectMethodScriptClass::queryProperty(Object *, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
- if (name == m_connectId.identifier || name == m_disconnectId.identifier)
- return QScriptClass::HandlesReadAccess;
- else
- return 0;
-
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::property(Object *, const Identifier &name)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- if (name == m_connectId.identifier)
- return Value(scriptEngine, m_connect);
- else if (name == m_disconnectId.identifier)
- return Value(scriptEngine, m_disconnect);
- else
- return Value();
-}
-
-namespace {
-struct MetaCallArgument {
- inline MetaCallArgument();
- inline ~MetaCallArgument();
- inline void *dataPtr();
-
- inline void initAsType(int type, QDeclarativeEngine *);
- void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &);
- inline QScriptDeclarativeClass::Value toValue(QDeclarativeEngine *);
-
-private:
- MetaCallArgument(const MetaCallArgument &);
-
- inline void cleanup();
-
- char data[4 * sizeof(void *)];
- int type;
- bool isObjectType;
-};
-}
-
-MetaCallArgument::MetaCallArgument()
-: type(QVariant::Invalid), isObjectType(false)
-{
-}
-
-MetaCallArgument::~MetaCallArgument()
-{
- cleanup();
-}
-
-void MetaCallArgument::cleanup()
-{
- if (type == QMetaType::QString) {
- ((QString *)&data)->~QString();
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- ((QVariant *)&data)->~QVariant();
- } else if (type == qMetaTypeId<QScriptValue>()) {
- ((QScriptValue *)&data)->~QScriptValue();
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- ((QList<QObject *> *)&data)->~QList<QObject *>();
- }
-}
-
-void *MetaCallArgument::dataPtr()
-{
- if (type == -1)
- return ((QVariant *)data)->data();
- else
- return (void *)&data;
-}
-
-void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e)
-{
- if (type != 0) { cleanup(); type = 0; }
- if (callType == 0) return;
-
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);
-
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue(engine->undefinedValue());
- type = callType;
- } else if (callType == QMetaType::Int ||
- callType == QMetaType::UInt ||
- callType == QMetaType::Bool ||
- callType == QMetaType::Double ||
- callType == QMetaType::Float) {
- type = callType;
- } else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = 0;
- type = callType;
- } else if (callType == QMetaType::QString) {
- new (&data) QString();
- type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
- type = callType;
- new (&data) QVariant();
- } else if (callType == qMetaTypeId<QList<QObject *> >()) {
- type = callType;
- new (&data) QList<QObject *>();
- } else {
- type = -1;
- new (&data) QVariant(callType, (void *)0);
- }
-}
-
-void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, const QScriptValue &value)
-{
- if (type != 0) { cleanup(); type = 0; }
-
- if (callType == qMetaTypeId<QScriptValue>()) {
- new (&data) QScriptValue(value);
- type = qMetaTypeId<QScriptValue>();
- } else if (callType == QMetaType::Int) {
- *((int *)&data) = int(value.toInt32());
- type = callType;
- } else if (callType == QMetaType::UInt) {
- *((uint *)&data) = uint(value.toUInt32());
- type = callType;
- } else if (callType == QMetaType::Bool) {
- *((bool *)&data) = value.toBool();
- type = callType;
- } else if (callType == QMetaType::Double) {
- *((double *)&data) = double(value.toNumber());
- type = callType;
- } else if (callType == QMetaType::Float) {
- *((float *)&data) = float(value.toNumber());
- type = callType;
- } else if (callType == QMetaType::QString) {
- if (value.isNull() || value.isUndefined())
- new (&data) QString();
- else
- new (&data) QString(value.toString());
- type = callType;
- } else if (callType == QMetaType::QObjectStar) {
- *((QObject **)&data) = value.toQObject();
- type = callType;
- } else if (callType == qMetaTypeId<QVariant>()) {
- new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value));
- type = callType;
- } else if (callType == qMetaTypeId<QList<QObject*> >()) {
- QList<QObject *> *list = new (&data) QList<QObject *>();
- if (value.isArray()) {
- int length = value.property(QLatin1String("length")).toInt32();
- for (int ii = 0; ii < length; ++ii) {
- QScriptValue arrayItem = value.property(ii);
- QObject *d = arrayItem.toQObject();
- list->append(d);
- }
- } else if (QObject *d = value.toQObject()) {
- list->append(d);
- }
- type = callType;
- } else {
- new (&data) QVariant();
- type = -1;
-
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine);
- QVariant v = priv->scriptValueToVariant(value);
- if (v.userType() == callType) {
- *((QVariant *)&data) = v;
- } else if (v.canConvert((QVariant::Type)callType)) {
- *((QVariant *)&data) = v;
- ((QVariant *)&data)->convert((QVariant::Type)callType);
- } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) {
- QObject *obj = priv->toQObject(v);
-
- if (obj) {
- const QMetaObject *objMo = obj->metaObject();
- while (objMo && objMo != mo) objMo = objMo->superClass();
- if (!objMo) obj = 0;
- }
-
- *((QVariant *)&data) = QVariant(callType, &obj);
- } else {
- *((QVariant *)&data) = QVariant(callType, (void *)0);
- }
- }
-}
-
-QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e)
-{
- QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e);
-
- if (type == qMetaTypeId<QScriptValue>()) {
- return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)&data));
- } else if (type == QMetaType::Int) {
- return QScriptDeclarativeClass::Value(engine, *((int *)&data));
- } else if (type == QMetaType::UInt) {
- return QScriptDeclarativeClass::Value(engine, *((uint *)&data));
- } else if (type == QMetaType::Bool) {
- return QScriptDeclarativeClass::Value(engine, *((bool *)&data));
- } else if (type == QMetaType::Double) {
- return QScriptDeclarativeClass::Value(engine, *((double *)&data));
- } else if (type == QMetaType::Float) {
- return QScriptDeclarativeClass::Value(engine, *((float *)&data));
- } else if (type == QMetaType::QString) {
- return QScriptDeclarativeClass::Value(engine, *((QString *)&data));
- } else if (type == QMetaType::QObjectStar) {
- QObject *object = *((QObject **)&data);
- if (object)
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
- return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(object));
- } else if (type == qMetaTypeId<QList<QObject *> >()) {
- QList<QObject *> &list = *(QList<QObject *>*)&data;
- QScriptValue rv = engine->newArray(list.count());
- QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e);
- for (int ii = 0; ii < list.count(); ++ii) {
- QObject *object = list.at(ii);
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- rv.setProperty(ii, priv->objectClass->newQObject(object));
- }
- return QScriptDeclarativeClass::Value(engine, rv);
- } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(e);
- QScriptValue rv = ep->scriptValueFromVariant(*((QVariant *)&data));
- if (rv.isQObject()) {
- QObject *object = rv.toQObject();
- if (object)
- QDeclarativeData::get(object, true)->setImplicitDestructible();
- }
- return QScriptDeclarativeClass::Value(engine, rv);
- } else {
- return QScriptDeclarativeClass::Value();
- }
-}
-
-int QDeclarativeObjectMethodScriptClass::enumType(const QMetaObject *meta, const QString &strname)
-{
- QByteArray str = strname.toUtf8();
- QByteArray scope;
- QByteArray name;
- int scopeIdx = str.lastIndexOf("::");
- if (scopeIdx != -1) {
- scope = str.left(scopeIdx);
- name = str.mid(scopeIdx + 2);
- } else {
- name = str;
- }
- for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
- QMetaEnum m = meta->enumerator(i);
- if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
- return QVariant::Int;
- }
- return QVariant::Invalid;
-}
-
-QDeclarativeObjectMethodScriptClass::Value QDeclarativeObjectMethodScriptClass::call(Object *o, QScriptContext *ctxt)
-{
- MethodData *method = static_cast<MethodData *>(o);
-
- if (method->data.relatedIndex == -1)
- return callPrecise(method->object, method->data, ctxt);
- else
- return callOverloaded(method, ctxt);
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
- QScriptContext *ctxt)
-{
- if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
-
- QMetaMethod m = object->metaObject()->method(data.coreIndex);
- QList<QByteArray> argTypeNames = m.parameterTypes();
- QVarLengthArray<int, 9> argTypes(argTypeNames.count());
-
- // ### Cache
- for (int ii = 0; ii < argTypeNames.count(); ++ii) {
- argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
- if (argTypes[ii] == QVariant::Invalid)
- argTypes[ii] = enumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
- if (argTypes[ii] == QVariant::Invalid)
- return Value(ctxt, ctxt->throwError(QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)))));
- }
-
- if (argTypes.count() > ctxt->argumentCount())
- return Value(ctxt, ctxt->throwError(QLatin1String("Insufficient arguments")));
-
- return callMethod(object, data.coreIndex, data.propType, argTypes.count(), argTypes.data(), ctxt);
-
- } else {
-
- return callMethod(object, data.coreIndex, data.propType, 0, 0, ctxt);
-
- }
-}
-
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index,
- int returnType, int argCount, int *argTypes,
- QScriptContext *ctxt)
-{
- if (argCount > 0) {
-
- QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
- args[0].initAsType(returnType, engine);
-
- for (int ii = 0; ii < argCount; ++ii)
- args[ii + 1].fromScriptValue(argTypes[ii], engine, ctxt->argument(ii));
-
- QVarLengthArray<void *, 9> argData(args.count());
- for (int ii = 0; ii < args.count(); ++ii)
- argData[ii] = args[ii].dataPtr();
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
-
- return args[0].toValue(engine);
-
- } else if (returnType != 0) {
-
- MetaCallArgument arg;
- arg.initAsType(returnType, engine);
-
- void *args[] = { arg.dataPtr() };
-
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
-
- return arg.toValue(engine);
-
- } else {
-
- void *args[] = { 0 };
- QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
- return Value();
-
- }
-}
-
-/*!
-Resolve the overloaded method to call. The algorithm works conceptually like this:
- 1. Resolve the set of overloads it is *possible* to call.
- Impossible overloads include those that have too many parameters or have parameters
- of unknown type.
- 2. Filter the set of overloads to only contain those with the closest number of
- parameters.
- For example, if we are called with 3 parameters and there are 2 overloads that
- take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
- 3. Find the best remaining overload based on its match score.
- If two or more overloads have the same match score, call the last one. The match
- score is constructed by adding the matchScore() result for each of the parameters.
-*/
-QDeclarativeObjectMethodScriptClass::Value
-QDeclarativeObjectMethodScriptClass::callOverloaded(MethodData *method, QScriptContext *ctxt)
-{
- int argumentCount = ctxt->argumentCount();
-
- QDeclarativePropertyCache::Data *best = 0;
- int bestParameterScore = INT_MAX;
- int bestMatchScore = INT_MAX;
-
- QDeclarativePropertyCache::Data dummy;
- QDeclarativePropertyCache::Data *attempt = &method->data;
-
- do {
- QList<QByteArray> methodArgTypeNames;
-
- if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
- methodArgTypeNames = method->object->metaObject()->method(attempt->coreIndex).parameterTypes();
-
- int methodArgumentCount = methodArgTypeNames.count();
-
- if (methodArgumentCount > argumentCount)
- continue; // We don't have sufficient arguments to call this method
-
- int methodParameterScore = argumentCount - methodArgumentCount;
- if (methodParameterScore > bestParameterScore)
- continue; // We already have a better option
-
- int methodMatchScore = 0;
- QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
-
- bool unknownArgument = false;
- for (int ii = 0; ii < methodArgumentCount; ++ii) {
- methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
- if (methodArgTypes[ii] == QVariant::Invalid)
- methodArgTypes[ii] = enumType(method->object->metaObject(),
- QString::fromLatin1(methodArgTypeNames.at(ii)));
- if (methodArgTypes[ii] == QVariant::Invalid) {
- unknownArgument = true;
- break;
- }
- methodMatchScore += matchScore(ctxt->argument(ii), methodArgTypes[ii], methodArgTypeNames.at(ii));
- }
- if (unknownArgument)
- continue; // We don't understand all the parameters
-
- if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
- best = attempt;
- bestParameterScore = methodParameterScore;
- bestMatchScore = methodMatchScore;
- }
-
- if (bestParameterScore == 0 && bestMatchScore == 0)
- break; // We can't get better than that
-
- } while((attempt = relatedMethod(method->object, attempt, dummy)) != 0);
-
- if (best) {
- return callPrecise(method->object, *best, ctxt);
- } else {
- QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
- QDeclarativePropertyCache::Data *candidate = &method->data;
- while (candidate) {
- error += QLatin1String("\n ") + QString::fromUtf8(method->object->metaObject()->method(candidate->coreIndex).signature());
- candidate = relatedMethod(method->object, candidate, dummy);
- }
- return Value(ctxt, ctxt->throwError(error));
- }
-}
-
-/*!
- Returns the match score for converting \a actual to be of type \a conversionType. A
- zero score means "perfect match" whereas a higher score is worse.
-
- The conversion table is copied out of the QtScript callQtMethod() function.
-*/
-int QDeclarativeObjectMethodScriptClass::matchScore(const QScriptValue &actual, int conversionType,
- const QByteArray &conversionTypeName)
-{
- if (actual.isNumber()) {
- switch (conversionType) {
- case QMetaType::Double:
- return 0;
- case QMetaType::Float:
- return 1;
- case QMetaType::LongLong:
- case QMetaType::ULongLong:
- return 2;
- case QMetaType::Long:
- case QMetaType::ULong:
- return 3;
- case QMetaType::Int:
- case QMetaType::UInt:
- return 4;
- case QMetaType::Short:
- case QMetaType::UShort:
- return 5;
- break;
- case QMetaType::Char:
- case QMetaType::UChar:
- return 6;
- default:
- return 10;
- }
- } else if (actual.isString()) {
- switch (conversionType) {
- case QMetaType::QString:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isBoolean()) {
- switch (conversionType) {
- case QMetaType::Bool:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isDate()) {
- switch (conversionType) {
- case QMetaType::QDateTime:
- return 0;
- case QMetaType::QDate:
- return 1;
- case QMetaType::QTime:
- return 2;
- default:
- return 10;
- }
- } else if (actual.isRegExp()) {
- switch (conversionType) {
- case QMetaType::QRegExp:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isVariant()) {
- if (conversionType == qMetaTypeId<QVariant>())
- return 0;
- else if (actual.toVariant().userType() == conversionType)
- return 0;
- else
- return 10;
- } else if (actual.isArray()) {
- switch (conversionType) {
- case QMetaType::QStringList:
- case QMetaType::QVariantList:
- return 5;
- default:
- return 10;
- }
- } else if (actual.isQObject()) {
- switch (conversionType) {
- case QMetaType::QObjectStar:
- return 0;
- default:
- return 10;
- }
- } else if (actual.isNull()) {
- switch (conversionType) {
- case QMetaType::VoidStar:
- case QMetaType::QObjectStar:
- return 0;
- default:
- if (!conversionTypeName.endsWith('*'))
- return 10;
- else
- return 0;
- }
- } else {
- return 10;
- }
-}
-
-static inline int QMetaObject_methods(const QMetaObject *metaObject)
-{
- struct Private
- {
- int revision;
- int className;
- int classInfoCount, classInfoData;
- int methodCount, methodData;
- };
-
- return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
-}
-
-static QByteArray QMetaMethod_name(const QMetaMethod &m)
-{
- QByteArray sig = m.signature();
- int paren = sig.indexOf('(');
- if (paren == -1)
- return sig;
- else
- return sig.left(paren);
-}
-
-/*!
-Returns the next related method, if one, or 0.
-*/
-QDeclarativePropertyCache::Data *
-QDeclarativeObjectMethodScriptClass::relatedMethod(QObject *object, QDeclarativePropertyCache::Data *current,
- QDeclarativePropertyCache::Data &dummy)
-{
- QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
- if (current->relatedIndex == -1)
- return 0;
-
- if (cache) {
- return cache->method(current->relatedIndex);
- } else {
- const QMetaObject *mo = object->metaObject();
- int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
-
- while (methodOffset > current->relatedIndex) {
- mo = mo->superClass();
- methodOffset -= QMetaObject_methods(mo);
- }
-
- QMetaMethod method = mo->method(current->relatedIndex);
- dummy.load(method);
-
- // Look for overloaded methods
- QByteArray methodName = QMetaMethod_name(method);
- for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
- if (methodName == QMetaMethod_name(mo->method(ii))) {
- dummy.relatedIndex = ii;
- return &dummy;
- }
- }
-
- return &dummy;
- }
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h b/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
deleted file mode 100644
index 850a94f364..0000000000
--- a/src/declarative/qml/qdeclarativeobjectscriptclass_p.h
+++ /dev/null
@@ -1,166 +0,0 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-#ifndef QDECLARATIVEOBJECTSCRIPTCLASS_P_H
-#define QDECLARATIVEOBJECTSCRIPTCLASS_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "private/qdeclarativepropertycache_p.h"
-#include "private/qdeclarativetypenamecache_p.h"
-
-#include <private/qscriptdeclarativeclass_p.h>
-#include <QtScript/qscriptengine.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDeclarativeEngine;
-class QScriptContext;
-class QScriptEngine;
-class QDeclarativeContextData;
-class MethodData;
-
-class Q_AUTOTEST_EXPORT QDeclarativeObjectMethodScriptClass : public QScriptDeclarativeClass
-{
-public:
- QDeclarativeObjectMethodScriptClass(QDeclarativeEngine *);
- ~QDeclarativeObjectMethodScriptClass();
-
- QScriptValue newMethod(QObject *, const QDeclarativePropertyCache::Data *);
-
-protected:
- virtual Value call(Object *, QScriptContext *);
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &, QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
-
-private:
- int enumType(const QMetaObject *, const QString &);
-
- Value callPrecise(QObject *, const QDeclarativePropertyCache::Data &, QScriptContext *);
- Value callOverloaded(MethodData *, QScriptContext *);
- Value callMethod(QObject *, int index, int returnType, int argCount, int *argTypes, QScriptContext *ctxt);
-
- int matchScore(const QScriptValue &, int, const QByteArray &);
- QDeclarativePropertyCache::Data *relatedMethod(QObject *, QDeclarativePropertyCache::Data *current,
- QDeclarativePropertyCache::Data &dummy);
-
- PersistentIdentifier m_connectId;
- PersistentIdentifier m_disconnectId;
- QScriptValue m_connect;
- QScriptValue m_disconnect;
-
- static QScriptValue connect(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue disconnect(QScriptContext *context, QScriptEngine *engine);
-
- QDeclarativeEngine *engine;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeObjectScriptClass : public QScriptDeclarativeClass
-{
-public:
- QDeclarativeObjectScriptClass(QDeclarativeEngine *);
- ~QDeclarativeObjectScriptClass();
-
- QScriptValue newQObject(QObject *, int type = QMetaType::QObjectStar);
-
- QObject *toQObject(const QScriptValue &) const;
- int objectType(const QScriptValue &) const;
-
- enum QueryHint {
- ImplicitObject = 0x01,
- SkipAttachedProperties = 0x02
- };
- Q_DECLARE_FLAGS(QueryHints, QueryHint)
-
- QScriptClass::QueryFlags queryProperty(QObject *, const Identifier &,
- QScriptClass::QueryFlags flags,
- QDeclarativeContextData *evalContext,
- QueryHints hints = 0);
-
- Value property(QObject *, const Identifier &);
-
- void setProperty(QObject *, const Identifier &name, const QScriptValue &,
- QScriptContext *context, QDeclarativeContextData *evalContext = 0);
- virtual QStringList propertyNames(Object *);
- virtual bool compare(Object *, Object *);
-
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
-
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
- virtual bool isQObject() const;
- virtual QObject *toQObject(Object *, bool *ok = 0);
-
-private:
- friend class QDeclarativeObjectMethodScriptClass;
- QDeclarativeObjectMethodScriptClass methods;
-
- QDeclarativeTypeNameCache::Data *lastTNData;
- QDeclarativePropertyCache::Data *lastData;
- QDeclarativePropertyCache::Data local;
-
- PersistentIdentifier m_destroyId;
- PersistentIdentifier m_toStringId;
- QScriptValue m_destroy;
- QScriptValue m_toString;
-
- static QScriptValue tostring(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
-
- QDeclarativeEngine *engine;
-};
-Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativeObjectScriptClass::QueryHints);
-
-QT_END_NAMESPACE
-
-#endif // QDECLARATIVEOBJECTSCRIPTCLASS_P_H
-
diff --git a/src/declarative/qml/qdeclarativeproperty.cpp b/src/declarative/qml/qdeclarativeproperty.cpp
index b91b820e0f..427e00e8fb 100644
--- a/src/declarative/qml/qdeclarativeproperty.cpp
+++ b/src/declarative/qml/qdeclarativeproperty.cpp
@@ -1503,7 +1503,7 @@ QDeclarativePropertyPrivate::restore(const QDeclarativePropertyCache::Data &data
prop.d = new QDeclarativePropertyPrivate;
prop.d->object = object;
prop.d->context = ctxt;
- prop.d->engine = ctxt->engine;
+ prop.d->engine = ctxt?ctxt->engine:0;
prop.d->core = data;
prop.d->valueType = valueType;
diff --git a/src/declarative/qml/qdeclarativepropertycache.cpp b/src/declarative/qml/qdeclarativepropertycache.cpp
index 9cbb4fa8cc..7e6f130c27 100644
--- a/src/declarative/qml/qdeclarativepropertycache.cpp
+++ b/src/declarative/qml/qdeclarativepropertycache.cpp
@@ -43,9 +43,11 @@
#include "private/qdeclarativeengine_p.h"
#include "private/qdeclarativebinding_p.h"
+#include "private/qv8engine_p.h"
#include <QtCore/qdebug.h>
Q_DECLARE_METATYPE(QScriptValue)
+Q_DECLARE_METATYPE(QDeclarativeV8Handle);
QT_BEGIN_NAMESPACE
@@ -68,6 +70,8 @@ QDeclarativePropertyCache::Data::Flags QDeclarativePropertyCache::Data::flagsFor
flags |= Data::IsQmlBinding;
} else if (propType == qMetaTypeId<QScriptValue>()) {
flags |= Data::IsQScriptValue;
+ } else if (propType == qMetaTypeId<QDeclarativeV8Handle>()) {
+ flags |= Data::IsV8Handle;
} else if (p.isEnumType()) {
flags |= Data::IsEnumType;
} else {
@@ -107,8 +111,13 @@ void QDeclarativePropertyCache::Data::load(const QMetaMethod &m)
propType = QMetaType::type(returnType);
QList<QByteArray> params = m.parameterTypes();
- if (!params.isEmpty())
+ if (!params.isEmpty()) {
flags |= Data::HasArguments;
+ if (params.at(0).length() == 23 &&
+ 0 == qstrcmp(params.at(0).constData(), "QDeclarativeV8Function*")) {
+ flags |= Data::IsV8Function;
+ }
+ }
revision = m.revision();
}
@@ -156,16 +165,11 @@ void QDeclarativePropertyCache::clear()
data->release();
}
- for (IdentifierCache::ConstIterator iter = identifierCache.begin();
- iter != identifierCache.end(); ++iter) {
- RData *data = (*iter);
- data->release();
- }
-
indexCache.clear();
methodIndexCache.clear();
stringCache.clear();
- identifierCache.clear();
+ constructor.Dispose();
+ constructor = v8::Persistent<v8::Function>();
}
QDeclarativePropertyCache::Data QDeclarativePropertyCache::create(const QMetaObject *metaObject,
@@ -219,7 +223,6 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const
cache->indexCache = indexCache;
cache->methodIndexCache = methodIndexCache;
cache->stringCache = stringCache;
- cache->identifierCache = identifierCache;
cache->allowedRevisionCache = allowedRevisionCache;
for (int ii = 0; ii < indexCache.count(); ++ii) {
@@ -230,8 +233,8 @@ QDeclarativePropertyCache *QDeclarativePropertyCache::copy() const
}
for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
(*iter)->addref();
- for (IdentifierCache::ConstIterator iter = identifierCache.begin(); iter != identifierCache.end(); ++iter)
- (*iter)->addref();
+
+ // We specifically do *NOT* copy the constructor
return cache;
}
@@ -248,6 +251,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
{
Q_UNUSED(revision);
+ constructor.Dispose(); // Now invalid
+ constructor = v8::Persistent<v8::Function>();
+
allowedRevisionCache.append(0);
QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(engine);
@@ -267,7 +273,6 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
methodName = methodName.left(parenIdx);
RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(methodName);
methodIndexCache[ii] = data;
data->load(m);
@@ -286,12 +291,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
data->overrideIndex = old->coreIndex;
stringCache[methodName]->release();
- identifierCache[data->identifier.identifier]->release();
}
stringCache.insert(methodName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
data->addref();
}
@@ -307,7 +309,6 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
QString propName = QString::fromUtf8(p.name());
RData *data = new RData;
- data->identifier = enginePriv->objectClass->createPersistentIdentifier(propName);
indexCache[ii] = data;
data->load(p, engine);
@@ -320,12 +321,9 @@ void QDeclarativePropertyCache::append(QDeclarativeEngine *engine, const QMetaOb
data->overrideIndexIsProperty = !bool(old->flags & Data::IsFunction);
data->overrideIndex = old->coreIndex;
stringCache[propName]->release();
- identifierCache[data->identifier.identifier]->release();
}
stringCache.insert(propName, data);
- identifierCache.insert(data->identifier.identifier, data);
- data->addref();
data->addref();
}
}
@@ -375,7 +373,8 @@ QDeclarativePropertyCache::method(int index) const
QDeclarativePropertyCache::Data *
QDeclarativePropertyCache::property(const QString &str) const
{
- return stringCache.value(str);
+ QDeclarativePropertyCache::RData **rv = stringCache.value(str);
+ return rv?*rv:0;
}
QString QDeclarativePropertyCache::Data::name(QObject *object)
@@ -407,29 +406,35 @@ QString QDeclarativePropertyCache::Data::name(const QMetaObject *metaObject)
QStringList QDeclarativePropertyCache::propertyNames() const
{
- return stringCache.keys();
+ QStringList keys;
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter)
+ keys.append(iter.key());
+ return keys;
}
-QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
- const QScriptDeclarativeClass::Identifier &name, Data &local)
+QDeclarativePropertyCache::Data *
+QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
+ v8::Handle<v8::String> name, Data &local)
{
- QDeclarativePropertyCache::Data *rv = 0;
-
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
+ Q_ASSERT(engine);
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
QDeclarativePropertyCache *cache = 0;
QDeclarativeData *ddata = QDeclarativeData::get(obj);
- if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine)
+ if (ddata && ddata->propertyCache && ddata->propertyCache->qmlEngine() == engine) // XXX aakenend
cache = ddata->propertyCache;
if (!cache) {
- cache = enginePrivate->cache(obj);
+ cache = ep->cache(obj);
if (cache && ddata && !ddata->propertyCache) { cache->addref(); ddata->propertyCache = cache; }
}
+ QDeclarativePropertyCache::Data *rv = 0;
+
if (cache) {
rv = cache->property(name);
} else {
- local = QDeclarativePropertyCache::create(obj->metaObject(), enginePrivate->objectClass->toString(name));
+ QString strname = ep->v8engine.toString(name);
+ local = QDeclarativePropertyCache::create(obj->metaObject(), strname);
if (local.isValid())
rv = &local;
}
@@ -437,8 +442,9 @@ QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativ
return rv;
}
-QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
- const QString &name, Data &local)
+QDeclarativePropertyCache::Data *
+QDeclarativePropertyCache::property(QDeclarativeEngine *engine, QObject *obj,
+ const QString &name, Data &local)
{
QDeclarativePropertyCache::Data *rv = 0;
diff --git a/src/declarative/qml/qdeclarativepropertycache_p.h b/src/declarative/qml/qdeclarativepropertycache_p.h
index 65a8725b8f..968ea51dda 100644
--- a/src/declarative/qml/qdeclarativepropertycache_p.h
+++ b/src/declarative/qml/qdeclarativepropertycache_p.h
@@ -57,6 +57,7 @@
#include "private/qdeclarativecleanup_p.h"
#include "private/qdeclarativenotifier_p.h"
+#include "private/qhashedstring_p.h"
#include <QtCore/qvector.h>
#include <QtScript/private/qscriptdeclarativeclass_p.h>
@@ -64,6 +65,8 @@ QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
class QMetaProperty;
+class QV8Engine;
+class QV8QObjectWrapper;
class Q_AUTOTEST_EXPORT QDeclarativePropertyCache : public QDeclarativeRefCount, public QDeclarativeCleanup
{
@@ -93,16 +96,30 @@ public:
IsQList = 0x00000100,
IsQmlBinding = 0x00000200,
IsQScriptValue = 0x00000400,
+ IsV8Handle = 0x00000800,
// Apply only to IsFunctions
- IsVMEFunction = 0x00000800,
- HasArguments = 0x00001000,
- IsSignal = 0x00002000,
- IsVMESignal = 0x00004000
+ IsVMEFunction = 0x00001000,
+ HasArguments = 0x00002000,
+ IsSignal = 0x00004000,
+ IsVMESignal = 0x00008000,
+ IsV8Function = 0x00010000
};
Q_DECLARE_FLAGS(Flags, Flag)
bool isValid() const { return coreIndex != -1; }
+ bool isConstant() const { return flags & IsConstant; }
+ bool isWritable() const { return flags & IsWritable; }
+ bool isResettable() const { return flags & IsResettable; }
+ bool isAlias() const { return flags & IsAlias; }
+ bool isFinal() const { return flags & IsFinal; }
+ bool isFunction() const { return flags & IsFunction; }
+ bool isQObject() const { return flags & IsQObjectDerived; }
+ bool isEnum() const { return flags & IsEnumType; }
+ bool isQList() const { return flags & IsQList; }
+ bool isQmlBinding() const { return flags & IsQmlBinding; }
+ bool isQScriptValue() const { return flags & IsQScriptValue; }
+ bool isV8Handle() const { return flags & IsV8Handle; }
Flags flags;
int propType;
@@ -141,7 +158,7 @@ public:
static Data create(const QMetaObject *, const QString &);
- inline Data *property(const QScriptDeclarativeClass::Identifier &id) const;
+ inline Data *property(v8::Handle<v8::String>) const;
Data *property(const QString &) const;
Data *property(int) const;
Data *method(int) const;
@@ -151,22 +168,25 @@ public:
inline bool isAllowedInRevision(Data *) const;
inline QDeclarativeEngine *qmlEngine() const;
- static Data *property(QDeclarativeEngine *, QObject *, const QScriptDeclarativeClass::Identifier &, Data &);
static Data *property(QDeclarativeEngine *, QObject *, const QString &, Data &);
+ static Data *property(QDeclarativeEngine *, QObject *, v8::Handle<v8::String>, Data &);
protected:
virtual void clear();
private:
friend class QDeclarativeEnginePrivate;
+ friend class QV8QObjectWrapper;
+ // Implemented in v8/qv8qobjectwrapper.cpp
+ v8::Local<v8::Object> newQObject(QObject *, QV8Engine *);
+
+ // XXX is this worth it anymore?
struct RData : public Data, public QDeclarativeRefCount {
- QScriptDeclarativeClass::PersistentIdentifier identifier;
};
typedef QVector<RData *> IndexCache;
- typedef QHash<QString, RData *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ typedef QStringHash<RData *> StringCache;
typedef QVector<int> AllowedRevisionCache;
void updateRecur(QDeclarativeEngine *, const QMetaObject *);
@@ -175,8 +195,8 @@ private:
IndexCache indexCache;
IndexCache methodIndexCache;
StringCache stringCache;
- IdentifierCache identifierCache;
AllowedRevisionCache allowedRevisionCache;
+ v8::Persistent<v8::Function> constructor;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QDeclarativePropertyCache::Data::Flags);
@@ -207,12 +227,6 @@ QDeclarativePropertyCache::overrideData(Data *data) const
return methodIndexCache.at(data->overrideIndex);
}
-QDeclarativePropertyCache::Data *
-QDeclarativePropertyCache::property(const QScriptDeclarativeClass::Identifier &id) const
-{
- return identifierCache.value(id);
-}
-
QDeclarativePropertyCache::ValueTypeData::ValueTypeData()
: flags(QDeclarativePropertyCache::Data::NoFlags), valueTypeCoreIdx(-1), valueTypePropType(0)
{
@@ -236,6 +250,12 @@ QDeclarativeEngine *QDeclarativePropertyCache::qmlEngine() const
return engine;
}
+QDeclarativePropertyCache::Data *QDeclarativePropertyCache::property(v8::Handle<v8::String> str) const
+{
+ QDeclarativePropertyCache::RData **rv = stringCache.value(str);
+ return rv?*rv:0;
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVEPROPERTYCACHE_P_H
diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp b/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp
deleted file mode 100644
index d94e2d9332..0000000000
--- a/src/declarative/qml/qdeclarativescarceresourcescriptclass.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativescarceresourcescriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativecontext_p.h"
-#include "private/qdeclarativedata_p.h"
-#include "private/qdeclarativetypenamescriptclass_p.h"
-#include "private/qdeclarativelistscriptclass_p.h"
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeguard_p.h"
-#include "private/qdeclarativevmemetaobject_p.h"
-
-#include <QtCore/qtimer.h>
-#include <QtCore/qvarlengtharray.h>
-#include <QtScript/qscriptcontextinfo.h>
-
-Q_DECLARE_METATYPE(QScriptValue);
-
-QT_BEGIN_NAMESPACE
-
-QDeclarativeScarceResourceScriptClass::QDeclarativeScarceResourceScriptClass(QDeclarativeEngine *bindEngine)
- : QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- // Properties of this type can be explicitly preserved by clients,
- // which prevents the scarce resource from being automatically
- // released after the binding has been evaluated.
- m_preserve = scriptEngine->newFunction(preserve);
- m_preserveId = createPersistentIdentifier(QLatin1String("preserve"));
-
- // Similarly, they can be explicitly destroyed by clients,
- // which releases the scarce resource.
- m_destroy = scriptEngine->newFunction(destroy);
- m_destroyId = createPersistentIdentifier(QLatin1String("destroy"));
-}
-
-QDeclarativeScarceResourceScriptClass::~QDeclarativeScarceResourceScriptClass()
-{
-}
-
-/*
- Returns a JavaScript object whose instance data is a new scarce resource data.
- The scarce resource is added to the doubly-linked-list of scarce resources in the engine
- so that the scarce resource can be released after evaluation completes.
- */
-QScriptValue QDeclarativeScarceResourceScriptClass::newScarceResource(const QVariant &v)
-{
- // create the scarce resource
- ScarceResourceData *srd = new ScarceResourceData(v);
-
- // insert into the linked list
- QDeclarativeEnginePrivate *enginePrivate = QDeclarativeEnginePrivate::get(engine);
- srd->insertInto(&enginePrivate->scarceResources);
- Q_ASSERT(enginePrivate->scarceResourcesRefCount > 0);
-
- // return the javascript object with the scarce resource instance data
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return QScriptDeclarativeClass::newObject(scriptEngine, this, srd); // JSC takes ownership of srd.
-}
-
-QVariant QDeclarativeScarceResourceScriptClass::toVariant(Object *object, bool *ok)
-{
- ScarceResourceData *obj = static_cast<ScarceResourceData*>(object);
- if (ok) *ok = true;
- return obj->resource;
-}
-
-QVariant QDeclarativeScarceResourceScriptClass::toVariant(const QScriptValue &value)
-{
- Q_ASSERT(scriptClass(value) == this);
-
- return toVariant(object(value), 0);
-}
-
-// The destroy() and preserve() function properties are readable.
-QScriptClass::QueryFlags
-QDeclarativeScarceResourceScriptClass::queryProperty(Object *object, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(object)
- Q_UNUSED(flags)
-
- if (name == m_destroyId.identifier || name == m_preserveId.identifier)
- return (QScriptClass::HandlesReadAccess);
- return 0;
-}
-
-// Return the (function) values which may be evaluated by clients.
-QDeclarativeScarceResourceScriptClass::Value
-QDeclarativeScarceResourceScriptClass::property(Object *object, const Identifier &name)
-{
- Q_UNUSED(object)
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- // functions
- if (name == m_preserveId.identifier)
- return Value(scriptEngine, m_preserve);
- else if (name == m_destroyId.identifier)
- return Value(scriptEngine, m_destroy);
-
- return Value();
-}
-
-/*
- This method is called when the user explicitly calls the "preserve" method of a scarce resource in JavaScript
- within the specified evaluation context \a context of the script engine \a engine.
- Calling this function signifies that the user explicitly wants to preserve the resource rather than let it
- be automatically released once evaluation of the expression is complete.
- This function removes the internal scarce resource from the declarative engine's linked list of scarce resources
- to release after evaluation of the expression completes. This means that the resource will only be truly
- released when the JavaScript engine's garbage collector is run.
-
- Example:
- \qml
- function getIcon(model) {
- var icon = model.avatar; // a pixmap property
- icon.preserve(); // explicitly preserves the resource
- return icon; // a valid variant will be returned
- }
- \endqml
- */
-QScriptValue QDeclarativeScarceResourceScriptClass::preserve(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->scarceResourceClass)
- return engine->undefinedValue();
-
- // The client wishes to preserve the resource in this SRD.
- ScarceResourceData *data = static_cast<ScarceResourceData *>(p->scarceResourceClass->object(that));
- if (!data)
- return engine->undefinedValue();
-
- // remove node from list, without releasing the resource.
- data->removeNode();
-
- return engine->undefinedValue();
-}
-
-/*
- This method is called when the user explicitly calls the "destroy" method of a scarce resource in JavaScript
- within the specified evaluation context \a context of the script engine \a engine.
- Calling this function signifies that the user explicitly wants to release the resource.
- This function sets the internal scarce resource variant to the invalid variant, in order to release the original resource,
- and then removes the resource from the declarative engine's linked-list of scarce resources to
- to release after evaluation of the expression completes, as it has already been released.
-
- Example:
- \qml
- function getIcon(model) {
- var icon = model.avatar; // a pixmap property
- icon.destroy(); // explicitly releases the resource
- return icon; // an invalid variant will be returned
- }
- \endqml
- */
-QScriptValue QDeclarativeScarceResourceScriptClass::destroy(QScriptContext *context, QScriptEngine *engine)
-{
- QDeclarativeEnginePrivate *p = QDeclarativeEnginePrivate::get(engine);
- QScriptValue that = context->thisObject();
-
- if (scriptClass(that) != p->scarceResourceClass)
- return engine->undefinedValue();
-
- // the client wishes to release the resource in this SRD.
- ScarceResourceData *data = static_cast<ScarceResourceData *>(p->scarceResourceClass->object(that));
- if (!data)
- return engine->undefinedValue();
-
- // release the resource and remove the node from the list.
- data->releaseResource();
-
- return engine->undefinedValue();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h b/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h
deleted file mode 100644
index 2a1390a230..0000000000
--- a/src/declarative/qml/qdeclarativescarceresourcescriptclass_p.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/****************************************************************************
-**
-** 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$
-**
-****************************************************************************/
-
-#ifndef QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H
-#define QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "private/qdeclarativepropertycache_p.h"
-#include "private/qdeclarativetypenamecache_p.h"
-
-#include <private/qscriptdeclarativeclass_p.h>
-#include <QtScript/qscriptengine.h>
-
-QT_BEGIN_NAMESPACE
-
-class QDeclarativeEngine;
-
-/*
- Scarce resources (like pixmaps and textures) are managed manually
- in that the variant will be set to the invalid variant once the
- JavaScript engine has finished using the JavaScript object whose
- instance data is the ScarceResourceData (but before the garbage
- collector frees the JavaScript object itself).
-
- The engine stores a doubly-linked-list of scarce resources which
- will to be cleaned up after a binding is successfully evaluated
- (unless the user explicitly preserves the scarce resource).
-
- A ScarceResourceData pointer should not be deleted manually, as
- all instances of a ScarceResourceData should be owned by the
- JavaScript engine.
- */
-struct ScarceResourceData : public QScriptDeclarativeClass::Object {
- ScarceResourceData(const QVariant &v) : resource(v), prev(0), next(0)
- {
- }
-
- virtual ~ScarceResourceData()
- {
- releaseResource();
- }
-
- // Insert this resource into the given list of resources.
- void insertInto(ScarceResourceData **list)
- {
- // This node becomes the head of the list.
- next = *list; // so our next = old list head
- *list = this; // list now points to us (we're the head)
- prev = list; // as we're the head, our prev ptr becomes the list ptr.
-
- // and the next node's prev pointer must contain a ptr to our next ptr,
- // since per definition, prev always contains a pointer to the previous node's "next" ptr,
- // and the "this" node is the "this->next" node's "prev" node.
- if (next) next->prev = &next;
- }
-
- // Remove this resource from the list of resources, without releasing the resource.
- void removeNode()
- {
- // whatever previously pointed to this node (ie, as that node's "next" node)
- // should now point to our next node (since we no longer exist in the list).
- // and the next node's prev ptr should point to our prev node.
- if (prev) *prev = next;
- if (next) next->prev = prev;
- prev = 0;
- next = 0;
- }
-
- // Release this resource, and remove from the list.
- void releaseResource()
- {
- resource = QVariant();
- removeNode();
- }
-
- QVariant resource;
-
- // prev always contains a pointer to the previous node's "next" ptr.
- // :. for the head node, [*prev] will be engine->scarceResources
- // :. for every other node, [*prev] will be the previous node's "next" ptr.
- ScarceResourceData **prev;
- ScarceResourceData *next;
-};
-
-class Q_AUTOTEST_EXPORT QDeclarativeScarceResourceScriptClass : public QScriptDeclarativeClass
-{
-public:
- QDeclarativeScarceResourceScriptClass(QDeclarativeEngine *);
- ~QDeclarativeScarceResourceScriptClass();
-
- // Creates a new JavaScript object whose instance data is the scarce resource v
- QScriptValue newScarceResource(const QVariant &v);
-
- // inherited from QScriptDeclarativeClass
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual QVariant toVariant(Object *, bool *ok = 0);
- QVariant toVariant(const QScriptValue &value);
-
-private:
- PersistentIdentifier m_preserveId;
- PersistentIdentifier m_destroyId;
- QScriptValue m_preserve;
- QScriptValue m_destroy;
-
- static QScriptValue preserve(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue destroy(QScriptContext *context, QScriptEngine *engine);
-
- QDeclarativeEngine *engine;
-};
-
-QT_END_NAMESPACE
-
-#endif // QDECLARATIVESCARCERESOURCESCRIPTCLASS_P_H
diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp
index 4ed2bba525..d4452e766d 100644
--- a/src/declarative/qml/qdeclarativesqldatabase.cpp
+++ b/src/declarative/qml/qdeclarativesqldatabase.cpp
@@ -47,101 +47,21 @@
#include "private/qdeclarativeengine_p.h"
#include <QtCore/qobject.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptvalueiterator.h>
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptengine.h>
-#include <QtScript/qscriptclasspropertyiterator.h>
#include <QtSql/qsqldatabase.h>
#include <QtSql/qsqlquery.h>
#include <QtSql/qsqlerror.h>
#include <QtSql/qsqlrecord.h>
+#include <QtGui/qdesktopservices.h>
#include <QtCore/qstack.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qsettings.h>
#include <QtCore/qdir.h>
#include <QtCore/qdebug.h>
-Q_DECLARE_METATYPE(QSqlDatabase)
-Q_DECLARE_METATYPE(QSqlQuery)
+#include <private/qv8engine_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeSqlQueryScriptClass: public QScriptClass {
-public:
- QDeclarativeSqlQueryScriptClass(QScriptEngine *engine) : QScriptClass(engine)
- {
- str_length = engine->toStringHandle(QLatin1String("length"));
- str_forwardOnly = engine->toStringHandle(QLatin1String("forwardOnly")); // not in HTML5 (an optimization)
- }
-
- QueryFlags queryProperty(const QScriptValue &,
- const QScriptString &name,
- QueryFlags flags, uint *)
- {
- if (flags & HandlesReadAccess) {
- if (name == str_length) {
- return HandlesReadAccess;
- } else if (name == str_forwardOnly) {
- return flags;
- }
- }
- if (flags & HandlesWriteAccess)
- if (name == str_forwardOnly)
- return flags;
- return 0;
- }
-
- QScriptValue property(const QScriptValue &object,
- const QScriptString &name, uint)
- {
- QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
- if (name == str_length) {
- int s = query.size();
- if (s<0) {
- // Inefficient.
- if (query.last()) {
- return query.at()+1;
- } else {
- return 0;
- }
- } else {
- return s;
- }
- } else if (name == str_forwardOnly) {
- return query.isForwardOnly();
- }
- return engine()->undefinedValue();
- }
-
- void setProperty(QScriptValue &object,
- const QScriptString &name, uint, const QScriptValue & value)
- {
- if (name == str_forwardOnly) {
- QSqlQuery query = qscriptvalue_cast<QSqlQuery>(object.data());
- query.setForwardOnly(value.toBool());
- }
- }
-
- QScriptValue::PropertyFlags propertyFlags(const QScriptValue &/*object*/, const QScriptString &name, uint /*id*/)
- {
- if (name == str_length) {
- return QScriptValue::Undeletable
- | QScriptValue::SkipInEnumeration;
- }
- return QScriptValue::Undeletable;
- }
-
-private:
- QScriptString str_length;
- QScriptString str_forwardOnly;
-};
-
-// If the spec changes to allow iteration, check git history...
-// class QDeclarativeSqlQueryScriptClassPropertyIterator : public QScriptClassPropertyIterator
-
-
-
enum SqlException {
UNKNOWN_ERR,
DATABASE_ERR,
@@ -165,90 +85,227 @@ static const char* sqlerror[] = {
0
};
-#define THROW_SQL(error, desc) \
+#define THROW_SQL(error, desc)
+
+#define V8THROW_SQL(error, desc) \
{ \
- QScriptValue errorValue = context->throwError(desc); \
- errorValue.setProperty(QLatin1String("code"), error); \
- return errorValue; \
+ v8::Local<v8::Value> v = v8::Exception::Error(engine->toString(desc)); \
+ v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \
+ v8::ThrowException(v); \
+ return v8::Handle<v8::Value>(); \
+}
+
+#define V8THROW_REFERENCE(string) { \
+ v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
+ return v8::Handle<v8::Value>(); \
+}
+
+#define V8THROW_REFERENCE_VOID(string) { \
+ v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
+ return; \
}
-static QString qmlsqldatabase_databasesPath(QScriptEngine *engine)
+struct QDeclarativeSqlDatabaseData {
+ QDeclarativeSqlDatabaseData(QV8Engine *engine);
+ ~QDeclarativeSqlDatabaseData();
+
+ QString offlineStoragePath;
+ v8::Persistent<v8::Function> constructor;
+ v8::Persistent<v8::Function> queryConstructor;
+ v8::Persistent<v8::Function> rowsConstructor;
+
+ static inline QDeclarativeSqlDatabaseData *data(QV8Engine *e) {
+ return (QDeclarativeSqlDatabaseData *)e->sqlDatabaseData();
+ }
+ static inline QDeclarativeSqlDatabaseData *data(void *d) {
+ return (QDeclarativeSqlDatabaseData *)d;
+ }
+};
+
+class QV8SqlDatabaseResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(SQLDatabaseType)
+
+public:
+ enum Type { Database, Query, Rows };
+
+ QV8SqlDatabaseResource(QV8Engine *e)
+ : QV8ObjectResource(e), type(Database), inTransaction(false), readonly(false), forwardOnly(false) {}
+
+ Type type;
+ QSqlDatabase database;
+
+ QString version; // type == Database
+
+ bool inTransaction; // type == Query
+ bool readonly; // type == Query
+
+ QSqlQuery query; // type == Rows
+ bool forwardOnly; // type == Rows
+};
+
+static v8::Handle<v8::Value> qmlsqldatabase_version(v8::Local<v8::String> property, const v8::AccessorInfo& info)
{
- QDeclarativeScriptEngine *qmlengine = static_cast<QDeclarativeScriptEngine*>(engine);
- return qmlengine->offlineStoragePath
- + QDir::separator() + QLatin1String("Databases");
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Database)
+ V8THROW_REFERENCE("Not a SQLDatabase object");
+
+ return r->engine->toString(r->version);
}
-static void qmlsqldatabase_initDatabasesPath(QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_length(v8::Local<v8::String> property, const v8::AccessorInfo& info)
{
- QDir().mkpath(qmlsqldatabase_databasesPath(engine));
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ int s = r->query.size();
+ if (s < 0) {
+ // Inefficient
+ if (r->query.last()) {
+ s = r->query.at() + 1;
+ } else {
+ s = 0;
+ }
+ }
+ return v8::Integer::New(s);
}
-static QString qmlsqldatabase_databaseFile(const QString& connectionName, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_forwardOnly(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- return qmlsqldatabase_databasesPath(engine) + QDir::separator()
- + connectionName;
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ return v8::Boolean::New(r->query.isForwardOnly());
}
+static void qmlsqldatabase_rows_setForwardOnly(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info)
+{
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE_VOID("Not a SQLDatabase::Rows object");
+
+ r->query.setForwardOnly(value->BooleanValue());
+}
-static QScriptValue qmlsqldatabase_item(QScriptContext *context, QScriptEngine *engine)
+QDeclarativeSqlDatabaseData::~QDeclarativeSqlDatabaseData()
{
- QSqlQuery query = qscriptvalue_cast<QSqlQuery>(context->thisObject().data());
- int i = context->argument(0).toNumber();
- if (query.at() == i || query.seek(i)) { // Qt 4.6 doesn't optimize seek(at())
- QSqlRecord r = query.record();
- QScriptValue row = engine->newObject();
- for (int j=0; j<r.count(); ++j) {
- row.setProperty(r.fieldName(j), QScriptValue(engine,r.value(j).toString()));
+ constructor.Dispose(); constructor = v8::Persistent<v8::Function>();
+ queryConstructor.Dispose(); queryConstructor = v8::Persistent<v8::Function>();
+}
+
+static QString qmlsqldatabase_databasesPath(QV8Engine *engine)
+{
+ return QDeclarativeSqlDatabaseData::data(engine)->offlineStoragePath +
+ QDir::separator() + QLatin1String("Databases");
+}
+
+static void qmlsqldatabase_initDatabasesPath(QV8Engine *engine)
+{
+ QDir().mkpath(qmlsqldatabase_databasesPath(engine));
+}
+
+static QString qmlsqldatabase_databaseFile(const QString& connectionName, QV8Engine *engine)
+{
+ return qmlsqldatabase_databasesPath(engine) + QDir::separator() + connectionName;
+}
+
+static v8::Handle<v8::Value> qmlsqldatabase_rows_index(QV8SqlDatabaseResource *r, uint32_t index)
+{
+ if (r->query.at() == index || r->query.seek(index)) {
+
+ QSqlRecord record = r->query.record();
+ // XXX optimize
+ v8::Local<v8::Object> row = v8::Object::New();
+ for (int ii = 0; ii < record.count(); ++ii) {
+ row->Set(r->engine->toString(record.fieldName(ii)),
+ r->engine->toString(record.value(ii).toString()));
}
return row;
+ } else {
+ return v8::Undefined();
}
- return engine->undefinedValue();
}
-static QScriptValue qmlsqldatabase_executeSql_outsidetransaction(QScriptContext *context, QScriptEngine * /*engine*/)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_index(uint32_t index, const v8::AccessorInfo& info)
{
- THROW_SQL(DATABASE_ERR,QDeclarativeEngine::tr("executeSql called outside transaction()"));
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(info.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ return qmlsqldatabase_rows_index(r, index);
}
-static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_rows_item(const v8::Arguments& args)
{
- QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
- QString sql = context->argument(0).toString();
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Rows)
+ V8THROW_REFERENCE("Not a SQLDatabase::Rows object");
+
+ return qmlsqldatabase_rows_index(r, args.Length()?args[0]->Uint32Value():0);
+}
+
+static v8::Handle<v8::Value> qmlsqldatabase_executeSql(const v8::Arguments& args)
+{
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Query)
+ V8THROW_REFERENCE("Not a SQLDatabase::Query object");
+
+ QV8Engine *engine = r->engine;
+
+ if (!r->inTransaction)
+ V8THROW_SQL(DATABASE_ERR,QDeclarativeEngine::tr("executeSql called outside transaction()"));
+
+ QSqlDatabase db = r->database;
+
+ QString sql = engine->toString(args[0]);
+
+ if (r->readonly && !sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
+ V8THROW_SQL(SYNTAX_ERR, QDeclarativeEngine::tr("Read-only Transaction"));
+ }
+
QSqlQuery query(db);
bool err = false;
- QScriptValue result;
+ v8::Handle<v8::Value> result = v8::Undefined();
if (query.prepare(sql)) {
- if (context->argumentCount() > 1) {
- QScriptValue values = context->argument(1);
- if (values.isObject()) {
- if (values.isArray()) {
- int size = values.property(QLatin1String("length")).toInt32();
- for (int i = 0; i < size; ++i)
- query.bindValue(i, values.property(i).toVariant());
- } else {
- for (QScriptValueIterator it(values); it.hasNext();) {
- it.next();
- query.bindValue(it.name(),it.value().toVariant());
- }
- }
+ if (args.Length() > 1) {
+ v8::Local<v8::Value> values = args[1];
+ if (values->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(values);
+ uint32_t size = array->Length();
+ for (uint32_t ii = 0; ii < size; ++ii)
+ query.bindValue(ii, engine->toVariant(array->Get(ii), -1));
+ } else if (values->IsObject() && !values->ToObject()->GetExternalResource()) {
+ v8::Local<v8::Object> object = values->ToObject();
+ v8::Local<v8::Array> names = object->GetPropertyNames();
+ uint32_t size = names->Length();
+ for (uint32_t ii = 0; ii < size; ++ii)
+ query.bindValue(engine->toString(names->Get(ii)),
+ engine->toVariant(object->Get(names->Get(ii)), -1));
} else {
- query.bindValue(0,values.toVariant());
+ query.bindValue(0, engine->toVariant(values, -1));
}
}
if (query.exec()) {
- result = engine->newObject();
- QDeclarativeScriptEngine *qmlengine = static_cast<QDeclarativeScriptEngine*>(engine);
- if (!qmlengine->sqlQueryClass)
- qmlengine->sqlQueryClass = new QDeclarativeSqlQueryScriptClass(engine);
- QScriptValue rows = engine->newObject(qmlengine->sqlQueryClass);
- rows.setData(engine->newVariant(QVariant::fromValue(query)));
- rows.setProperty(QLatin1String("item"), engine->newFunction(qmlsqldatabase_item,1), QScriptValue::SkipInEnumeration);
- result.setProperty(QLatin1String("rows"),rows);
- result.setProperty(QLatin1String("rowsAffected"),query.numRowsAffected());
- result.setProperty(QLatin1String("insertId"),query.lastInsertId().toString());
+ v8::Handle<v8::Object> rows = QDeclarativeSqlDatabaseData::data(engine)->rowsConstructor->NewInstance();
+ QV8SqlDatabaseResource *r = new QV8SqlDatabaseResource(engine);
+ r->type = QV8SqlDatabaseResource::Rows;
+ r->database = db;
+ r->query = query;
+ rows->SetExternalResource(r);
+
+ v8::Local<v8::Object> resultObject = v8::Object::New();
+ result = resultObject;
+ // XXX optimize
+ resultObject->Set(v8::String::New("rowsAffected"), v8::Integer::New(query.numRowsAffected()));
+ resultObject->Set(v8::String::New("insertId"), engine->toString(query.lastInsertId().toString()));
+ resultObject->Set(v8::String::New("rows"), rows);
} else {
err = true;
}
@@ -256,117 +313,138 @@ static QScriptValue qmlsqldatabase_executeSql(QScriptContext *context, QScriptEn
err = true;
}
if (err)
- THROW_SQL(DATABASE_ERR,query.lastError().text());
+ V8THROW_SQL(DATABASE_ERR,query.lastError().text());
+
return result;
}
-static QScriptValue qmlsqldatabase_executeSql_readonly(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_changeVersion(const v8::Arguments& args)
{
- QString sql = context->argument(0).toString();
- if (sql.startsWith(QLatin1String("SELECT"),Qt::CaseInsensitive)) {
- return qmlsqldatabase_executeSql(context,engine);
- } else {
- THROW_SQL(SYNTAX_ERR,QDeclarativeEngine::tr("Read-only Transaction"))
- }
-}
+ if (args.Length() < 2)
+ return v8::Undefined();
-static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScriptEngine *engine)
-{
- if (context->argumentCount() < 2)
- return engine->undefinedValue();
-
- QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
- QString from_version = context->argument(0).toString();
- QString to_version = context->argument(1).toString();
- QScriptValue callback = context->argument(2);
-
- QScriptValue instance = engine->newObject();
- instance.setProperty(QLatin1String("executeSql"), engine->newFunction(qmlsqldatabase_executeSql,1));
- QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db));
-
- QString foundvers = context->thisObject().property(QLatin1String("version")).toString();
- if (from_version!=foundvers) {
- THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(foundvers));
- return engine->undefinedValue();
- }
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Database)
+ V8THROW_REFERENCE("Not a SQLDatabase object");
+
+ QV8Engine *engine = r->engine;
+
+ QSqlDatabase db = r->database;
+ QString from_version = engine->toString(args[0]);
+ QString to_version = engine->toString(args[1]);
+ v8::Handle<v8::Value> callback = args[2];
+
+ if (from_version != r->version)
+ V8THROW_SQL(VERSION_ERR, QDeclarativeEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(r->version));
+
+ v8::Local<v8::Object> instance = QDeclarativeSqlDatabaseData::data(engine)->queryConstructor->NewInstance();
+ QV8SqlDatabaseResource *r2 = new QV8SqlDatabaseResource(engine);
+ r2->type = QV8SqlDatabaseResource::Query;
+ r2->database = db;
+ r2->version = r->version;
+ r2->inTransaction = true;
+ instance->SetExternalResource(r2);
bool ok = true;
- if (callback.isFunction()) {
+ if (callback->IsFunction()) {
ok = false;
db.transaction();
- callback.call(QScriptValue(), QScriptValueList() << tx);
- if (engine->hasUncaughtException()) {
+
+ v8::TryCatch tc;
+ v8::Handle<v8::Value> callbackArgs[] = { instance };
+ v8::Handle<v8::Function>::Cast(callback)->Call(engine->global(), 1, callbackArgs);
+
+ if (tc.HasCaught()) {
+ db.rollback();
+ tc.ReThrow();
+ return v8::Handle<v8::Value>();
+ } else if (!db.commit()) {
db.rollback();
+ V8THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("SQL transaction failed"));
} else {
- if (!db.commit()) {
- db.rollback();
- THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("SQL transaction failed"));
- } else {
- ok = true;
- }
+ ok = true;
}
}
+ r2->inTransaction = false;
+
if (ok) {
- context->thisObject().setProperty(QLatin1String("version"), to_version, QScriptValue::ReadOnly);
+ r2->version = to_version;
#ifndef QT_NO_SETTINGS
QSettings ini(qmlsqldatabase_databaseFile(db.connectionName(),engine) + QLatin1String(".ini"), QSettings::IniFormat);
ini.setValue(QLatin1String("Version"), to_version);
#endif
}
- return engine->undefinedValue();
+ return v8::Undefined();
}
-static QScriptValue qmlsqldatabase_transaction_shared(QScriptContext *context, QScriptEngine *engine, bool readOnly)
+static v8::Handle<v8::Value> qmlsqldatabase_transaction_shared(const v8::Arguments& args, bool readOnly)
{
- QSqlDatabase db = qscriptvalue_cast<QSqlDatabase>(context->thisObject());
- QScriptValue callback = context->argument(0);
- if (!callback.isFunction())
- THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("transaction: missing callback"));
-
- QScriptValue instance = engine->newObject();
- instance.setProperty(QLatin1String("executeSql"),
- engine->newFunction(readOnly ? qmlsqldatabase_executeSql_readonly : qmlsqldatabase_executeSql,1));
- QScriptValue tx = engine->newVariant(instance,QVariant::fromValue(db));
+ QV8SqlDatabaseResource *r = v8_resource_cast<QV8SqlDatabaseResource>(args.This());
+ if (!r || r->type != QV8SqlDatabaseResource::Database)
+ V8THROW_REFERENCE("Not a SQLDatabase object");
+
+ QV8Engine *engine = r->engine;
+
+ if (args.Length() == 0 || !args[0]->IsFunction())
+ V8THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("transaction: missing callback"));
+
+ QSqlDatabase db = r->database;
+ v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(args[0]);
+
+ v8::Local<v8::Object> instance = QDeclarativeSqlDatabaseData::data(engine)->queryConstructor->NewInstance();
+ QV8SqlDatabaseResource *q = new QV8SqlDatabaseResource(engine);
+ q->type = QV8SqlDatabaseResource::Query;
+ q->database = db;
+ q->readonly = readOnly;
+ q->inTransaction = true;
+ instance->SetExternalResource(q);
db.transaction();
- callback.call(QScriptValue(), QScriptValueList() << tx);
- instance.setProperty(QLatin1String("executeSql"),
- engine->newFunction(qmlsqldatabase_executeSql_outsidetransaction));
- if (engine->hasUncaughtException()) {
+ v8::TryCatch tc;
+ v8::Handle<v8::Value> callbackArgs[] = { instance };
+ callback->Call(engine->global(), 1, callbackArgs);
+
+ q->inTransaction = false;
+
+ if (tc.HasCaught()) {
+ db.rollback();
+ tc.ReThrow();
+ return v8::Handle<v8::Value>();
+ } else if (!db.commit()) {
db.rollback();
- } else {
- if (!db.commit())
- db.rollback();
}
- return engine->undefinedValue();
+
+ return v8::Undefined();
}
-static QScriptValue qmlsqldatabase_transaction(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_transaction(const v8::Arguments& args)
{
- return qmlsqldatabase_transaction_shared(context,engine,false);
+ return qmlsqldatabase_transaction_shared(args, false);
}
-static QScriptValue qmlsqldatabase_read_transaction(QScriptContext *context, QScriptEngine *engine)
+
+static v8::Handle<v8::Value> qmlsqldatabase_read_transaction(const v8::Arguments& args)
{
- return qmlsqldatabase_transaction_shared(context,engine,true);
+ return qmlsqldatabase_transaction_shared(args, true);
}
/*
Currently documented in doc/src/declarative/globalobject.qdoc
*/
-static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlsqldatabase_open_sync(const v8::Arguments& args)
{
#ifndef QT_NO_SETTINGS
+ QV8Engine *engine = V8ENGINE();
qmlsqldatabase_initDatabasesPath(engine);
QSqlDatabase database;
- QString dbname = context->argument(0).toString();
- QString dbversion = context->argument(1).toString();
- QString dbdescription = context->argument(2).toString();
- int dbestimatedsize = context->argument(3).toNumber();
- QScriptValue dbcreationCallback = context->argument(4);
+ QString dbname = engine->toString(args[0]);
+ QString dbversion = engine->toString(args[1]);
+ QString dbdescription = engine->toString(args[2]);
+ int dbestimatedsize = args[3]->Int32Value();
+ v8::Handle<v8::Value> dbcreationCallback = args[4];
QCryptographicHash md5(QCryptographicHash::Md5);
md5.addData(dbname.toUtf8());
@@ -383,13 +461,13 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng
database = QSqlDatabase::database(dbid);
version = ini.value(QLatin1String("Version")).toString();
if (version != dbversion && !dbversion.isEmpty() && !version.isEmpty())
- THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("SQL: database version mismatch"));
+ V8THROW_SQL(VERSION_ERR, QDeclarativeEngine::tr("SQL: database version mismatch"));
} else {
created = !QFile::exists(basename+QLatin1String(".sqlite"));
database = QSqlDatabase::addDatabase(QLatin1String("QSQLITE"), dbid);
if (created) {
ini.setValue(QLatin1String("Name"), dbname);
- if (dbcreationCallback.isFunction())
+ if (dbcreationCallback->IsFunction())
version = QString();
ini.setValue(QLatin1String("Version"), version);
ini.setValue(QLatin1String("Description"), dbdescription);
@@ -398,7 +476,7 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng
} else {
if (!dbversion.isEmpty() && ini.value(QLatin1String("Version")) != dbversion) {
// Incompatible
- THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("SQL: database version mismatch"));
+ V8THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("SQL: database version mismatch"));
}
version = ini.value(QLatin1String("Version")).toString();
}
@@ -408,35 +486,96 @@ static QScriptValue qmlsqldatabase_open_sync(QScriptContext *context, QScriptEng
database.open();
}
- QScriptValue instance = engine->newObject();
- instance.setProperty(QLatin1String("transaction"), engine->newFunction(qmlsqldatabase_transaction,1));
- instance.setProperty(QLatin1String("readTransaction"), engine->newFunction(qmlsqldatabase_read_transaction,1));
- instance.setProperty(QLatin1String("version"), version, QScriptValue::ReadOnly);
- instance.setProperty(QLatin1String("changeVersion"), engine->newFunction(qmlsqldatabase_change_version,3));
-
- QScriptValue result = engine->newVariant(instance,QVariant::fromValue(database));
-
- if (created && dbcreationCallback.isFunction()) {
- dbcreationCallback.call(QScriptValue(), QScriptValueList() << result);
+ v8::Local<v8::Object> instance = QDeclarativeSqlDatabaseData::data(engine)->constructor->NewInstance();
+ QV8SqlDatabaseResource *r = new QV8SqlDatabaseResource(engine);
+ r->database = database;
+ r->version = version;
+ instance->SetExternalResource(r);
+
+ if (created && dbcreationCallback->IsFunction()) {
+ v8::TryCatch tc;
+ v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(dbcreationCallback);
+ v8::Handle<v8::Value> args[] = { instance };
+ callback->Call(engine->global(), 1, args);
+ if (tc.HasCaught()) {
+ tc.ReThrow();
+ return v8::Handle<v8::Value>();
+ }
}
- return result;
+ return instance;
#else
- return engine->undefinedValue();
+ return v8::Undefined();
#endif // QT_NO_SETTINGS
}
-void qt_add_qmlsqldatabase(QScriptEngine *engine)
+QDeclarativeSqlDatabaseData::QDeclarativeSqlDatabaseData(QV8Engine *engine)
{
- QScriptValue openDatabase = engine->newFunction(qmlsqldatabase_open_sync, 4);
- engine->globalObject().setProperty(QLatin1String("openDatabaseSync"), openDatabase);
+ QString dataLocation = QDesktopServices::storageLocation(QDesktopServices::DataLocation);
+ offlineStoragePath = dataLocation.replace(QLatin1Char('/'), QDir::separator()) +
+ QDir::separator() + QLatin1String("QML") +
+ QDir::separator() + QLatin1String("OfflineStorage");
- QScriptValue sqlExceptionPrototype = engine->newObject();
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("transaction"),
+ V8FUNCTION(qmlsqldatabase_transaction, engine));
+ ft->PrototypeTemplate()->Set(v8::String::New("readTransaction"),
+ V8FUNCTION(qmlsqldatabase_read_transaction, engine));
+ ft->PrototypeTemplate()->SetAccessor(v8::String::New("version"), qmlsqldatabase_version);
+ ft->PrototypeTemplate()->Set(v8::String::New("changeVersion"),
+ V8FUNCTION(qmlsqldatabase_changeVersion, engine));
+ constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("executeSql"),
+ V8FUNCTION(qmlsqldatabase_executeSql, engine));
+ queryConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->PrototypeTemplate()->Set(v8::String::New("item"), V8FUNCTION(qmlsqldatabase_rows_item, engine));
+ ft->PrototypeTemplate()->SetAccessor(v8::String::New("length"), qmlsqldatabase_rows_length);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("forwardOnly"), qmlsqldatabase_rows_forwardOnly,
+ qmlsqldatabase_rows_setForwardOnly);
+ ft->InstanceTemplate()->SetIndexedPropertyHandler(qmlsqldatabase_rows_index);
+ rowsConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+}
+
+void *qt_add_qmlsqldatabase(QV8Engine *engine)
+{
+ v8::Local<v8::Function> openDatabase = V8FUNCTION(qmlsqldatabase_open_sync, engine);
+ engine->global()->Set(v8::String::New("openDatabaseSync"), openDatabase);
+
+ v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
+ v8::Local<v8::Object> sqlExceptionPrototype = v8::Object::New();
for (int i=0; sqlerror[i]; ++i)
- sqlExceptionPrototype.setProperty(QLatin1String(sqlerror[i]),
- i,QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ sqlExceptionPrototype->Set(v8::String::New(sqlerror[i]), v8::Integer::New(i), attributes);
+ engine->global()->Set(v8::String::New("SQLException"), sqlExceptionPrototype);
+
+ return (void *)new QDeclarativeSqlDatabaseData(engine);
+}
+
+void qt_rem_qmlsqldatabase(QV8Engine *engine, void *d)
+{
+ QDeclarativeSqlDatabaseData *data = (QDeclarativeSqlDatabaseData *)d;
+ delete data;
+}
- engine->globalObject().setProperty(QLatin1String("SQLException"), sqlExceptionPrototype);
+void qt_qmlsqldatabase_setOfflineStoragePath(QV8Engine *engine, const QString &path)
+{
+ QDeclarativeSqlDatabaseData::data(engine)->offlineStoragePath = path;
+}
+
+QString qt_qmlsqldatabase_getOfflineStoragePath(const QV8Engine *engine)
+{
+ return QDeclarativeSqlDatabaseData::data(const_cast<QV8Engine *>(engine))->offlineStoragePath;
}
/*
diff --git a/src/declarative/qml/qdeclarativesqldatabase_p.h b/src/declarative/qml/qdeclarativesqldatabase_p.h
index 671bd3062c..85b2b111e2 100644
--- a/src/declarative/qml/qdeclarativesqldatabase_p.h
+++ b/src/declarative/qml/qdeclarativesqldatabase_p.h
@@ -58,8 +58,12 @@
QT_BEGIN_NAMESPACE
-class QScriptEngine;
-void qt_add_qmlsqldatabase(QScriptEngine *engine);
+class QV8Engine;
+
+void *qt_add_qmlsqldatabase(QV8Engine *engine);
+void qt_rem_qmlsqldatabase(QV8Engine *engine, void *);
+void qt_qmlsqldatabase_setOfflineStoragePath(QV8Engine *engine, const QString &);
+QString qt_qmlsqldatabase_getOfflineStoragePath(const QV8Engine *);
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativetypeloader.cpp b/src/declarative/qml/qdeclarativetypeloader.cpp
index 1c1eeee2cf..27d0fc6e67 100644
--- a/src/declarative/qml/qdeclarativetypeloader.cpp
+++ b/src/declarative/qml/qdeclarativetypeloader.cpp
@@ -1090,6 +1090,9 @@ void QDeclarativeScriptData::clear()
for (int ii = 0; ii < scripts.count(); ++ii)
scripts.at(ii)->release();
scripts.clear();
+
+ m_program.Dispose();
+ m_value.Dispose();
}
QDeclarativeScriptBlob::QDeclarativeScriptBlob(const QUrl &url, QDeclarativeTypeLoader *loader)
@@ -1218,7 +1221,13 @@ void QDeclarativeScriptBlob::done()
m_imports.populateCache(m_scriptData->importCache, engine);
m_scriptData->pragmas = m_pragmas;
- m_scriptData->m_program = QScriptProgram(m_source, finalUrl().toString());
+
+ // XXX aakenned - what about error handling?
+ QV8Engine *v8engine = &QDeclarativeEnginePrivate::get(engine)->v8engine;
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(v8engine->context());
+ v8::Local<v8::Script> program = v8engine->qmlModeCompile(m_source, finalUrl().toString(), 1);
+ m_scriptData->m_program = v8::Persistent<v8::Script>::New(program);
}
QDeclarativeQmldirData::QDeclarativeQmldirData(const QUrl &url)
diff --git a/src/declarative/qml/qdeclarativetypeloader_p.h b/src/declarative/qml/qdeclarativetypeloader_p.h
index 1c0798d67b..9bda579b45 100644
--- a/src/declarative/qml/qdeclarativetypeloader_p.h
+++ b/src/declarative/qml/qdeclarativetypeloader_p.h
@@ -64,6 +64,8 @@
#include <private/qdeclarativedirparser_p.h>
#include <private/qdeclarativeimport_p.h>
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeScriptData;
@@ -307,8 +309,10 @@ private:
friend class QDeclarativeScriptBlob;
bool m_loaded;
- QScriptProgram m_program;
- QScriptValue m_value;
+ v8::Persistent<v8::Script> m_program;
+ v8::Persistent<v8::Object> m_value;
+// QScriptProgram m_program;
+// QScriptValue m_value;
};
class Q_AUTOTEST_EXPORT QDeclarativeScriptBlob : public QDeclarativeDataBlob
diff --git a/src/declarative/qml/qdeclarativetypenamecache.cpp b/src/declarative/qml/qdeclarativetypenamecache.cpp
index b9577c17fa..214cb4d9d1 100644
--- a/src/declarative/qml/qdeclarativetypenamecache.cpp
+++ b/src/declarative/qml/qdeclarativetypenamecache.cpp
@@ -57,9 +57,7 @@ QDeclarativeTypeNameCache::~QDeclarativeTypeNameCache()
void QDeclarativeTypeNameCache::clear()
{
- qDeleteAll(stringCache);
stringCache.clear();
- identifierCache.clear();
m_moduleApi = 0;
engine = 0;
}
@@ -69,14 +67,9 @@ void QDeclarativeTypeNameCache::add(const QString &name, int importedScriptIndex
if (stringCache.contains(name))
return;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- RData *data = new RData;
- // ### Use typename class
- data->identifier = ep->objectClass->createPersistentIdentifier(name);
- data->importedScriptIndex = importedScriptIndex;
+ Data data;
+ data.importedScriptIndex = importedScriptIndex;
stringCache.insert(name, data);
- identifierCache.insert(data->identifier.identifier, data);
}
void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type)
@@ -84,14 +77,9 @@ void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeType *type)
if (stringCache.contains(name))
return;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- RData *data = new RData;
- // ### Use typename class
- data->identifier = ep->objectClass->createPersistentIdentifier(name);
- data->type = type;
+ Data data;
+ data.type = type;
stringCache.insert(name, data);
- identifierCache.insert(data->identifier.identifier, data);
}
void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCache *typeNamespace)
@@ -101,13 +89,10 @@ void QDeclarativeTypeNameCache::add(const QString &name, QDeclarativeTypeNameCac
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- RData *data = new RData;
- // ### Use typename class
- data->identifier = ep->objectClass->createPersistentIdentifier(name);
- data->typeNamespace = typeNamespace;
- stringCache.insert(name, data);
- identifierCache.insert(data->identifier.identifier, data);
+ Data data;
typeNamespace->addref();
+ data.typeNamespace = typeNamespace;
+ stringCache.insert(name, data);
}
QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QString &id) const
diff --git a/src/declarative/qml/qdeclarativetypenamecache_p.h b/src/declarative/qml/qdeclarativetypenamecache_p.h
index bcca41f4d5..7d2c1a604d 100644
--- a/src/declarative/qml/qdeclarativetypenamecache_p.h
+++ b/src/declarative/qml/qdeclarativetypenamecache_p.h
@@ -59,6 +59,8 @@
#include <private/qscriptdeclarativeclass_p.h>
+#include <private/qhashedstring_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeType;
@@ -71,7 +73,9 @@ public:
struct Data {
inline Data();
+ inline Data(const Data &);
inline ~Data();
+ inline Data &operator=(const Data &);
QDeclarativeType *type;
QDeclarativeTypeNameCache *typeNamespace;
int importedScriptIndex;
@@ -82,7 +86,7 @@ public:
void add(const QString &, QDeclarativeTypeNameCache *);
Data *data(const QString &) const;
- inline Data *data(const QScriptDeclarativeClass::Identifier &id) const;
+ inline Data *data(v8::Handle<v8::String>) const;
inline bool isEmpty() const;
inline QDeclarativeMetaType::ModuleApiInstance *moduleApi() const;
@@ -92,14 +96,10 @@ protected:
virtual void clear();
private:
- struct RData : public Data {
- QScriptDeclarativeClass::PersistentIdentifier identifier;
- };
- typedef QHash<QString, RData *> StringCache;
- typedef QHash<QScriptDeclarativeClass::Identifier, RData *> IdentifierCache;
+ typedef QStringHash<Data> StringCache;
StringCache stringCache;
- IdentifierCache identifierCache;
+
QDeclarativeEngine *engine;
QDeclarativeMetaType::ModuleApiInstance *m_moduleApi;
};
@@ -114,14 +114,25 @@ QDeclarativeTypeNameCache::Data::~Data()
if (typeNamespace) typeNamespace->release();
}
-QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(const QScriptDeclarativeClass::Identifier &id) const
+bool QDeclarativeTypeNameCache::isEmpty() const
{
- return identifierCache.value(id);
+ return stringCache.isEmpty();
}
-bool QDeclarativeTypeNameCache::isEmpty() const
+QDeclarativeTypeNameCache::Data::Data(const QDeclarativeTypeNameCache::Data &o)
+: type(o.type), typeNamespace(o.typeNamespace), importedScriptIndex(o.importedScriptIndex)
+{
+ if (typeNamespace) typeNamespace->addref();
+}
+
+QDeclarativeTypeNameCache::Data &QDeclarativeTypeNameCache::Data::operator=(const QDeclarativeTypeNameCache::Data &o)
{
- return identifierCache.isEmpty();
+ if (o.typeNamespace) o.typeNamespace->addref();
+ if (typeNamespace) typeNamespace->release();
+ type = o.type;
+ typeNamespace = o.typeNamespace;
+ importedScriptIndex = o.importedScriptIndex;
+ return *this;
}
QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi() const
@@ -129,6 +140,11 @@ QDeclarativeMetaType::ModuleApiInstance *QDeclarativeTypeNameCache::moduleApi()
return m_moduleApi;
}
+QDeclarativeTypeNameCache::Data *QDeclarativeTypeNameCache::data(v8::Handle<v8::String> name) const
+{
+ return stringCache.value(name);
+}
+
QT_END_NAMESPACE
#endif // QDECLARATIVETYPENAMECACHE_P_H
diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp b/src/declarative/qml/qdeclarativetypenamescriptclass.cpp
deleted file mode 100644
index d628b7065a..0000000000
--- a/src/declarative/qml/qdeclarativetypenamescriptclass.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativetypenamescriptclass_p.h"
-
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativetypenamecache_p.h"
-
-QT_BEGIN_NAMESPACE
-
-struct TypeNameData : public QScriptDeclarativeClass::Object {
- TypeNameData(QObject *o, QDeclarativeType *t, QDeclarativeTypeNameScriptClass::TypeNameMode m) : object(o), type(t), typeNamespace(0), mode(m) {}
- TypeNameData(QObject *o, QDeclarativeTypeNameCache *n, QDeclarativeTypeNameScriptClass::TypeNameMode m) : object(o), type(0), typeNamespace(n), mode(m) {
- if (typeNamespace) typeNamespace->addref();
- }
- ~TypeNameData() {
- if (typeNamespace) typeNamespace->release();
- }
-
- QObject *object;
- QDeclarativeType *type;
- QDeclarativeTypeNameCache *typeNamespace;
- QDeclarativeTypeNameScriptClass::TypeNameMode mode;
-};
-
-QDeclarativeTypeNameScriptClass::QDeclarativeTypeNameScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)),
- engine(bindEngine), object(0), type(0), api(0)
-{
-}
-
-QDeclarativeTypeNameScriptClass::~QDeclarativeTypeNameScriptClass()
-{
-}
-
-QScriptValue QDeclarativeTypeNameScriptClass::newObject(QObject *object, QDeclarativeType *type, TypeNameMode mode)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, type, mode));
-}
-
-QScriptValue QDeclarativeTypeNameScriptClass::newObject(QObject *object, QDeclarativeTypeNameCache *ns, TypeNameMode mode)
-{
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
-
- return QScriptDeclarativeClass::newObject(scriptEngine, this, new TypeNameData(object, ns, mode));
-}
-
-QScriptClass::QueryFlags
-QDeclarativeTypeNameScriptClass::queryProperty(Object *obj, const Identifier &name,
- QScriptClass::QueryFlags flags)
-{
- Q_UNUSED(flags);
-
- TypeNameData *data = (TypeNameData *)obj;
-
- object = 0;
- type = 0;
- api = 0;
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
-
- if (data->typeNamespace) {
- QDeclarativeTypeNameCache::Data *d = data->typeNamespace->data(name);
- if (d && d->type) {
- type = d->type;
- return QScriptClass::HandlesReadAccess;
- } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = data->typeNamespace->moduleApi()) {
- if (moduleApi->scriptCallback) {
- moduleApi->scriptApi = moduleApi->scriptCallback(engine, &ep->scriptEngine);
- moduleApi->scriptCallback = 0;
- moduleApi->qobjectCallback = 0;
- } else if (moduleApi->qobjectCallback) {
- moduleApi->qobjectApi = moduleApi->qobjectCallback(engine, &ep->scriptEngine);
- moduleApi->scriptCallback = 0;
- moduleApi->qobjectCallback = 0;
- }
-
- api = moduleApi;
- if (api->qobjectApi) {
- return ep->objectClass->queryProperty(api->qobjectApi, name, flags, 0,
- QDeclarativeObjectScriptClass::SkipAttachedProperties);
- } else {
- return QScriptClass::HandlesReadAccess;
- }
-
- return 0;
-
- } else {
- return 0;
- }
-
- } else if (data->type) {
-
- if (startsWithUpper(name)) {
- QString strName = toString(name);
- // Must be an enum
- if (data->mode == IncludeEnums) {
- // ### Optimize
- QByteArray enumName = strName.toUtf8();
- const QMetaObject *metaObject = data->type->baseMetaObject();
- for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
- QMetaEnum e = metaObject->enumerator(ii);
- int value = e.keyToValue(enumName.constData());
- if (value != -1) {
- enumValue = value;
- return QScriptClass::HandlesReadAccess;
- }
- }
- }
- return 0;
- } else if (data->object) {
- // Must be an attached property
- object = qmlAttachedPropertiesObjectById(data->type->attachedPropertiesId(), data->object);
- if (!object) return 0;
- return ep->objectClass->queryProperty(object, name, flags, 0);
- }
-
- }
-
- return 0;
-}
-
-QDeclarativeTypeNameScriptClass::Value
-QDeclarativeTypeNameScriptClass::property(Object *obj, const Identifier &name)
-{
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- if (type) {
- return Value(scriptEngine, newObject(((TypeNameData *)obj)->object, type, ((TypeNameData *)obj)->mode));
- } else if (object) {
- return ep->objectClass->property(object, name);
- } else if (api && api->qobjectApi) {
- return ep->objectClass->property(api->qobjectApi, name);
- } else if (api) {
- return propertyValue(api->scriptApi, name);
- } else {
- return Value(scriptEngine, enumValue);
- }
-}
-
-void QDeclarativeTypeNameScriptClass::setProperty(Object *, const Identifier &n, const QScriptValue &v)
-{
- Q_ASSERT(!type);
-
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine);
- if (api) {
- Q_ASSERT(api->qobjectApi);
- ep->objectClass->setProperty(api->qobjectApi, n, v, context());
- } else {
- Q_ASSERT(object);
- ep->objectClass->setProperty(object, n, v, context());
- }
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp b/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp
deleted file mode 100644
index 4c312b52a8..0000000000
--- a/src/declarative/qml/qdeclarativevaluetypescriptclass.cpp
+++ /dev/null
@@ -1,242 +0,0 @@
-/****************************************************************************
-**
-** 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 "private/qdeclarativevaluetypescriptclass_p.h"
-
-#include "private/qdeclarativebinding_p.h"
-#include "private/qdeclarativeproperty_p.h"
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativeguard_p.h"
-
-#include <QtScript/qscriptcontextinfo.h>
-
-QT_BEGIN_NAMESPACE
-
-struct QDeclarativeValueTypeObject : public QScriptDeclarativeClass::Object {
- enum Type { Reference, Copy };
- QDeclarativeValueTypeObject(Type t) : objectType(t) {}
- Type objectType;
- QDeclarativeValueType *type;
-};
-
-struct QDeclarativeValueTypeReference : public QDeclarativeValueTypeObject {
- QDeclarativeValueTypeReference() : QDeclarativeValueTypeObject(Reference) {}
- QDeclarativeGuard<QObject> object;
- int property;
-};
-
-struct QDeclarativeValueTypeCopy : public QDeclarativeValueTypeObject {
- QDeclarativeValueTypeCopy() : QDeclarativeValueTypeObject(Copy) {}
- QVariant value;
-};
-
-QDeclarativeValueTypeScriptClass::QDeclarativeValueTypeScriptClass(QDeclarativeEngine *bindEngine)
-: QScriptDeclarativeClass(QDeclarativeEnginePrivate::getScriptEngine(bindEngine)), engine(bindEngine)
-{
-}
-
-QDeclarativeValueTypeScriptClass::~QDeclarativeValueTypeScriptClass()
-{
-}
-
-QScriptValue QDeclarativeValueTypeScriptClass::newObject(QObject *object, int coreIndex, QDeclarativeValueType *type)
-{
- QDeclarativeValueTypeReference *ref = new QDeclarativeValueTypeReference;
- ref->type = type;
- ref->object = object;
- ref->property = coreIndex;
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return QScriptDeclarativeClass::newObject(scriptEngine, this, ref);
-}
-
-QScriptValue QDeclarativeValueTypeScriptClass::newObject(const QVariant &v, QDeclarativeValueType *type)
-{
- QDeclarativeValueTypeCopy *copy = new QDeclarativeValueTypeCopy;
- copy->type = type;
- copy->value = v;
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return QScriptDeclarativeClass::newObject(scriptEngine, this, copy);
-}
-
-QScriptClass::QueryFlags
-QDeclarativeValueTypeScriptClass::queryProperty(Object *obj, const Identifier &name,
- QScriptClass::QueryFlags)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- m_lastIndex = -1;
-
- QByteArray propName = toString(name).toUtf8();
-
- m_lastIndex = o->type->metaObject()->indexOfProperty(propName.constData());
- if (m_lastIndex == -1)
- return 0;
-
- QScriptClass::QueryFlags rv = 0;
-
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(o);
-
- if (!ref->object)
- return 0;
-
- QMetaProperty prop = ref->object->metaObject()->property(m_lastIndex);
-
- rv = QScriptClass::HandlesReadAccess;
- if (prop.isWritable())
- rv |= QScriptClass::HandlesWriteAccess;
- } else {
- rv = QScriptClass::HandlesReadAccess | QScriptClass::HandlesWriteAccess;
- }
-
- return rv;
-}
-
-QDeclarativeValueTypeScriptClass::Value QDeclarativeValueTypeScriptClass::property(Object *obj, const Identifier &)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- QVariant rv;
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
-
- QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
- ref->type->read(ref->object, ref->property);
- rv = p.read(ref->type);
- } else {
- QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
-
- QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
- copy->type->setValue(copy->value);
- rv = p.read(copy->type);
- }
-
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
- return Value(scriptEngine, static_cast<QDeclarativeEnginePrivate *>(QObjectPrivate::get(engine))->scriptValueFromVariant(rv));
-}
-
-void QDeclarativeValueTypeScriptClass::setProperty(Object *obj, const Identifier &,
- const QScriptValue &value)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- QVariant v = QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value);
-
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
-
- ref->type->read(ref->object, ref->property);
- QMetaProperty p = ref->type->metaObject()->property(m_lastIndex);
-
- QDeclarativeBinding *newBinding = 0;
- if (value.isFunction() && !value.isRegExp()) {
- QDeclarativeContextData *ctxt = QDeclarativeEnginePrivate::get(engine)->getContext(context());
-
- QDeclarativePropertyCache::Data cacheData;
- cacheData.flags = QDeclarativePropertyCache::Data::IsWritable;
- cacheData.propType = ref->object->metaObject()->property(ref->property).userType();
- cacheData.coreIndex = ref->property;
-
- QDeclarativePropertyCache::ValueTypeData valueTypeData;
- valueTypeData.valueTypeCoreIdx = m_lastIndex;
- valueTypeData.valueTypePropType = p.userType();
-
- newBinding = new QDeclarativeBinding(value, ref->object, ctxt);
- QScriptContextInfo ctxtInfo(context());
- newBinding->setSourceLocation(ctxtInfo.fileName(), ctxtInfo.functionStartLineNumber());
- QDeclarativeProperty prop = QDeclarativePropertyPrivate::restore(cacheData, valueTypeData, ref->object, ctxt);
- newBinding->setTarget(prop);
- if (newBinding->expression().contains(QLatin1String("this")))
- newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
- }
-
- QDeclarativeAbstractBinding *delBinding =
- QDeclarativePropertyPrivate::setBinding(ref->object, ref->property, m_lastIndex, newBinding);
- if (delBinding)
- delBinding->destroy();
-
- if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
- v = v.toInt();
- p.write(ref->type, v);
- ref->type->write(ref->object, ref->property, 0);
-
- } else {
- QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
- copy->type->setValue(copy->value);
- QMetaProperty p = copy->type->metaObject()->property(m_lastIndex);
- p.write(copy->type, v);
- copy->value = copy->type->value();
- }
-}
-
-QVariant QDeclarativeValueTypeScriptClass::toVariant(Object *obj, bool *ok)
-{
- QDeclarativeValueTypeObject *o = static_cast<QDeclarativeValueTypeObject *>(obj);
-
- if (o->objectType == QDeclarativeValueTypeObject::Reference) {
- QDeclarativeValueTypeReference *ref = static_cast<QDeclarativeValueTypeReference *>(obj);
-
- if (ok) *ok = true;
-
- if (ref->object) {
- ref->type->read(ref->object, ref->property);
- return ref->type->value();
- }
- } else {
- QDeclarativeValueTypeCopy *copy = static_cast<QDeclarativeValueTypeCopy *>(obj);
-
- if (ok) *ok = true;
-
- return copy->value;
- }
-
- return QVariant();
-}
-
-QVariant QDeclarativeValueTypeScriptClass::toVariant(const QScriptValue &value)
-{
- Q_ASSERT(scriptClass(value) == this);
-
- return toVariant(object(value), 0);
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/qdeclarativevme.cpp b/src/declarative/qml/qdeclarativevme.cpp
index 13539a0f1f..5e35f6020b 100644
--- a/src/declarative/qml/qdeclarativevme.cpp
+++ b/src/declarative/qml/qdeclarativevme.cpp
@@ -59,7 +59,6 @@
#include "private/qdeclarativecontext_p.h"
#include "private/qdeclarativev4bindings_p.h"
#include "private/qdeclarativeglobal_p.h"
-#include "private/qdeclarativeglobalscriptclass_p.h"
#include "qdeclarativescriptstring.h"
#include <QStack>
@@ -962,68 +961,67 @@ QDeclarativeCompiledData::TypeReference::createInstance(QDeclarativeContextData
}
}
-QScriptValue QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
+v8::Persistent<v8::Object> QDeclarativeVME::run(QDeclarativeContextData *parentCtxt, QDeclarativeScriptData *script)
{
if (script->m_loaded)
- return script->m_value;
+ return v8::Persistent<v8::Object>::New(script->m_value);
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(parentCtxt->engine);
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(parentCtxt->engine);
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(parentCtxt->engine);
+ QV8Engine *v8engine = &ep->v8engine;
bool shared = script->pragmas & QDeclarativeParser::Object::ScriptBlock::Shared;
// Create the script context if required
- QDeclarativeContextData *ctxt = 0;
- if (!shared) {
- ctxt = new QDeclarativeContextData;
- ctxt->isInternal = true;
- ctxt->url = script->url;
-
- // For backward compatibility, if there are no imports, we need to use the
- // imports from the parent context. See QTBUG-17518.
- if (!script->importCache->isEmpty()) {
- ctxt->imports = script->importCache;
- } else {
- ctxt->imports = parentCtxt->imports;
- }
-
- if (ctxt->imports) {
- ctxt->imports->addref();
- }
-
- ctxt->setParent(parentCtxt, true);
+ QDeclarativeContextData *ctxt = new QDeclarativeContextData;
+ ctxt->isInternal = true;
+ ctxt->isJSContext = true;
+ ctxt->url = script->url;
+
+ // For backward compatibility, if there are no imports, we need to use the
+ // imports from the parent context. See QTBUG-17518.
+ if (!script->importCache->isEmpty()) {
+ ctxt->imports = script->importCache;
+ } else {
+ ctxt->imports = parentCtxt->imports;
+ }
- for (int ii = 0; ii < script->scripts.count(); ++ii)
- ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
+ if (ctxt->imports) {
+ ctxt->imports->addref();
}
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- if (shared) {
- scriptContext->pushScope(enginePriv->contextClass->newUrlContext(script->url.toString())); // XXX toString()?
- } else {
- scriptContext->pushScope(enginePriv->contextClass->newUrlContext(ctxt, 0, script->url.toString()));
+ ctxt->setParent(parentCtxt, true);
+
+ for (int ii = 0; ii < script->scripts.count(); ++ii) {
+ ctxt->importedScripts << run(ctxt, script->scripts.at(ii)->scriptData());
}
- scriptContext->pushScope(enginePriv->globalClass->staticGlobalObject());
- QScriptValue scope = QScriptDeclarativeClass::newStaticScopeObject(scriptEngine);
- scriptContext->pushScope(scope);
+ // XXX aakenned optimize
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(v8engine->context());
- scriptEngine->evaluate(script->m_program);
+ v8::Local<v8::Object> qmlglobal = v8engine->qmlScope(ctxt, 0);
- if (scriptEngine->hasUncaughtException()) {
- QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(scriptEngine, error);
- enginePriv->warning(error);
- }
+ v8::TryCatch try_catch;
+ script->m_program->Run(qmlglobal);
- scriptEngine->popContext();
+ v8::Persistent<v8::Object> rv;
+
+ if (try_catch.HasCaught()) {
+ v8::Local<v8::Message> message = try_catch.Message();
+ if (!message.IsEmpty()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ ep->warning(error);
+ }
+ }
+ rv = v8::Persistent<v8::Object>::New(qmlglobal);
if (shared) {
+ script->m_value = v8::Persistent<v8::Object>::New(qmlglobal);
script->m_loaded = true;
- script->m_value = scope;
}
- return scope;
+ return rv;
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevme_p.h b/src/declarative/qml/qdeclarativevme_p.h
index 40343b2f19..14f85e57a3 100644
--- a/src/declarative/qml/qdeclarativevme_p.h
+++ b/src/declarative/qml/qdeclarativevme_p.h
@@ -59,6 +59,8 @@
#include <QtCore/QString>
#include <QtCore/QStack>
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QObject;
@@ -103,7 +105,6 @@ public:
QObject *run(QDeclarativeContextData *, QDeclarativeCompiledData *,
int start = -1, const QBitField & = QBitField());
- QScriptValue run(QDeclarativeContextData *, QDeclarativeScriptData *);
void runDeferred(QObject *);
@@ -111,6 +112,8 @@ public:
QList<QDeclarativeError> errors() const;
private:
+ v8::Persistent<v8::Object> run(QDeclarativeContextData *, QDeclarativeScriptData *);
+
QObject *run(QDeclarativeVMEStack<QObject *> &,
QDeclarativeContextData *, QDeclarativeCompiledData *,
int start, const QBitField &);
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index 6eb74b3bad..a272c180c2 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -383,7 +383,7 @@ QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
const QDeclarativeVMEMetaData *meta,
QDeclarativeCompiledData *cdata)
: object(obj), compiledData(cdata), ctxt(QDeclarativeData::get(obj, true)->outerContext),
- metaData(meta), data(0), methods(0), parent(0)
+ metaData(meta), data(0), v8methods(0), parent(0)
{
compiledData->addref();
@@ -418,7 +418,9 @@ QDeclarativeVMEMetaObject::~QDeclarativeVMEMetaObject()
compiledData->release();
delete parent;
delete [] data;
- delete [] methods;
+
+ for (int ii = 0; v8methods && ii < metaData->methodCount; ++ii)
+ v8methods[ii].Dispose();
}
int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
@@ -649,27 +651,35 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(ctxt->engine);
ep->referenceScarceResources(); // "hold" scarce resources in memory during evaluation.
- QScriptValue function = method(id);
-
- QScriptValueList args;
+ // XXX aakenned
+ v8::Handle<v8::Function> function = method(id);
QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + id;
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(ep->v8engine.context());
+ v8::Handle<v8::Value> *args = 0;
+
if (data->parameterCount) {
- for (int ii = 0; ii < data->parameterCount; ++ii) {
- args << ep->scriptValueFromVariant(*(QVariant *)a[ii + 1]);
- }
+ args = new v8::Handle<v8::Value>[data->parameterCount];
+ for (int ii = 0; ii < data->parameterCount; ++ii)
+ args[ii] = ep->v8engine.fromVariant(*(QVariant *)a[ii + 1]);
}
- QScriptValue rv = function.call(ep->objectClass->newQObject(object), args);
- if (ep->scriptEngine.hasUncaughtException()) {
+ v8::TryCatch try_catch;
+
+ v8::Local<v8::Value> result = function->Call(ep->v8engine.global(), data->parameterCount, args);
+
+ QVariant rv;
+ if (try_catch.HasCaught()) {
QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(&ep->scriptEngine, error);
- if (error.isValid()) {
+ QDeclarativeExpressionPrivate::exceptionToError(try_catch.Message(), error);
+ if (error.isValid())
ep->warning(error);
- }
+ if (a[0]) *(QVariant *)a[0] = QVariant();
+ } else {
+ if (a[0]) *(QVariant *)a[0] = ep->v8engine.toVariant(result, 0);
}
- if (a[0]) *reinterpret_cast<QVariant *>(a[0]) = ep->scriptValueToVariant(rv);
-
ep->dereferenceScarceResources(); // "release" scarce resources if top-level expression evaluation is complete.
return -1;
}
@@ -683,12 +693,12 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
return object->qt_metacall(c, _id, a);
}
-QScriptValue QDeclarativeVMEMetaObject::method(int index)
+v8::Handle<v8::Function> QDeclarativeVMEMetaObject::method(int index)
{
- if (!methods)
- methods = new QScriptValue[metaData->methodCount];
+ if (!v8methods)
+ v8methods = new v8::Persistent<v8::Function>[metaData->methodCount];
- if (!methods[index].isValid()) {
+ if (v8methods[index].IsEmpty()) {
QDeclarativeVMEMetaData::MethodData *data = metaData->methodData() + index;
const QChar *body =
@@ -696,17 +706,17 @@ QScriptValue QDeclarativeVMEMetaObject::method(int index)
QString code = QString::fromRawData(body, data->bodyLength);
- // XXX Use QScriptProgram
// XXX We should evaluate all methods in a single big script block to
// improve the call time between dynamic methods defined on the same
// object
- methods[index] = QDeclarativeExpressionPrivate::evalInObjectScope(ctxt, object, code, ctxt->url.toString(),
- data->lineNumber, 0);
+ v8methods[index] = QDeclarativeExpressionPrivate::evalFunction(ctxt, object, code, ctxt->url.toString(),
+ data->lineNumber);
}
- return methods[index];
+ return v8methods[index];
}
+#if 0
QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
{
if (data[id].dataType() == qMetaTypeId<QScriptValue>())
@@ -716,22 +726,28 @@ QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
else
return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueFromVariant(data[id].asQVariant());
}
+#endif
QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id)
{
+#if 0
if (data[id].dataType() == qMetaTypeId<QScriptValue>())
return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQScriptValue());
- else if (data[id].dataType() == QMetaType::QObjectStar)
+ else
+#endif
+ if (data[id].dataType() == QMetaType::QObjectStar)
return QVariant::fromValue(data[id].asQObject());
else
return data[id].asQVariant();
}
+#if 0
void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &value)
{
data[id].setValue(value);
activate(object, methodOffset + id, 0);
}
+#endif
void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QVariant &value)
{
@@ -803,7 +819,7 @@ int QDeclarativeVMEMetaObject::vmeMethodLineNumber(int index)
return data->lineNumber;
}
-QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
+v8::Handle<v8::Function> QDeclarativeVMEMetaObject::vmeMethod(int index)
{
if (index < methodOffset) {
Q_ASSERT(parent);
@@ -814,6 +830,7 @@ QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
return method(index - methodOffset - plainSignals);
}
+// Used by debugger
void QDeclarativeVMEMetaObject::setVmeMethod(int index, const QScriptValue &value)
{
if (index < methodOffset) {
@@ -823,11 +840,14 @@ void QDeclarativeVMEMetaObject::setVmeMethod(int index, const QScriptValue &valu
int plainSignals = metaData->signalCount + metaData->propertyCount + metaData->aliasCount;
Q_ASSERT(index >= (methodOffset + plainSignals) && index < (methodOffset + plainSignals + metaData->methodCount));
+#if 0
if (!methods)
methods = new QScriptValue[metaData->methodCount];
methods[index - methodOffset - plainSignals] = value;
+#endif
}
+#if 0
QScriptValue QDeclarativeVMEMetaObject::vmeProperty(int index)
{
if (index < propOffset) {
@@ -845,6 +865,7 @@ void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v)
}
return writeVarProperty(index - propOffset, v);
}
+#endif
bool QDeclarativeVMEMetaObject::aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const
{
diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h
index 318ac4aa77..7e8b38df4c 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject_p.h
+++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h
@@ -69,6 +69,8 @@
#include "private/qdeclarativecompiler_p.h"
#include "private/qdeclarativecontext_p.h"
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
#define QML_ALIAS_FLAG_PTR 0x00000001
@@ -140,11 +142,13 @@ public:
bool aliasTarget(int index, QObject **target, int *coreIndex, int *valueTypeIndex) const;
void registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor);
- QScriptValue vmeMethod(int index);
+ v8::Handle<v8::Function> vmeMethod(int index);
int vmeMethodLineNumber(int index);
void setVmeMethod(int index, const QScriptValue &);
+#if 0
QScriptValue vmeProperty(int index);
void setVMEProperty(int index, const QScriptValue &);
+#endif
void connectAliasSignal(int index);
@@ -168,11 +172,14 @@ private:
QHash<int, QPair<int, QDeclarativePropertyValueInterceptor*> > interceptors;
QScriptValue *methods;
- QScriptValue method(int);
+ v8::Persistent<v8::Function> *v8methods;
+ v8::Handle<v8::Function> method(int);
+#if 0
QScriptValue readVarProperty(int);
- QVariant readVarPropertyAsVariant(int);
void writeVarProperty(int, const QScriptValue &);
+#endif
+ QVariant readVarPropertyAsVariant(int);
void writeVarProperty(int, const QVariant &);
QAbstractDynamicMetaObject *parent;
diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp
index db8a2ae81b..0d5582f11e 100644
--- a/src/declarative/qml/qdeclarativeworkerscript.cpp
+++ b/src/declarative/qml/qdeclarativeworkerscript.cpp
@@ -58,6 +58,8 @@
#include <QtDeclarative/qdeclarativeinfo.h>
#include "qdeclarativenetworkaccessmanagerfactory.h"
+#include <private/qv8engine_p.h>
+#include <private/qv8worker_p.h>
QT_BEGIN_NAMESPACE
@@ -66,15 +68,15 @@ class WorkerDataEvent : public QEvent
public:
enum Type { WorkerData = QEvent::User };
- WorkerDataEvent(int workerId, const QVariant &data);
+ WorkerDataEvent(int workerId, const QByteArray &data);
virtual ~WorkerDataEvent();
int workerId() const;
- QVariant data() const;
+ QByteArray data() const;
private:
int m_id;
- QVariant m_data;
+ QByteArray m_data;
};
class WorkerLoadEvent : public QEvent
@@ -128,27 +130,28 @@ public:
QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *eng);
- struct ScriptEngine : public QDeclarativeScriptEngine
+ class WorkerEngine : public QV8Engine
{
- ScriptEngine(QDeclarativeWorkerScriptEnginePrivate *parent) : QDeclarativeScriptEngine(0), p(parent), accessManager(0) {}
- ~ScriptEngine() { delete accessManager; }
+ public:
+ WorkerEngine(QDeclarativeWorkerScriptEnginePrivate *parent);
+ ~WorkerEngine();
+
+ void init();
+ virtual QNetworkAccessManager *networkAccessManager();
+
QDeclarativeWorkerScriptEnginePrivate *p;
- QNetworkAccessManager *accessManager;
- virtual QNetworkAccessManager *networkAccessManager() {
- if (!accessManager) {
- if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
- accessManager = p->qmlengine->networkAccessManagerFactory()->create(this);
- } else {
- accessManager = new QNetworkAccessManager(this);
- }
- }
- return accessManager;
- }
+ v8::Local<v8::Function> sendFunction(int id);
+ void callOnMessage(v8::Handle<v8::Object> object, v8::Handle<v8::Value> arg);
+ private:
+ v8::Persistent<v8::Function> onmessage;
+ v8::Persistent<v8::Function> createsend;
+ QNetworkAccessManager *accessManager;
};
- ScriptEngine *workerEngine;
- static QDeclarativeWorkerScriptEnginePrivate *get(QScriptEngine *e) {
- return static_cast<ScriptEngine *>(e)->p;
+
+ WorkerEngine *workerEngine;
+ static QDeclarativeWorkerScriptEnginePrivate *get(QV8Engine *e) {
+ return static_cast<WorkerEngine *>(e)->p;
}
QDeclarativeEngine *qmlengine;
@@ -158,26 +161,21 @@ public:
struct WorkerScript {
WorkerScript();
+ ~WorkerScript();
int id;
QUrl source;
bool initialized;
QDeclarativeWorkerScript *owner;
- QScriptValue object;
-
- QScriptValue callback;
+ v8::Persistent<v8::Object> object;
};
QHash<int, WorkerScript *> workers;
- QScriptValue getWorker(int);
+ v8::Handle<v8::Object> getWorker(WorkerScript *);
int m_nextId;
- static QVariant scriptValueToVariant(const QScriptValue &);
- static QScriptValue variantToScriptValue(const QVariant &, QScriptEngine *);
-
- static QScriptValue onMessage(QScriptContext *ctxt, QScriptEngine *engine);
- static QScriptValue sendMessage(QScriptContext *ctxt, QScriptEngine *engine);
+ static v8::Handle<v8::Value> sendMessage(const v8::Arguments &args);
signals:
void stopThread();
@@ -186,75 +184,133 @@ protected:
virtual bool event(QEvent *);
private:
- void processMessage(int, const QVariant &);
+ void processMessage(int, const QByteArray &);
void processLoad(int, const QUrl &);
- void reportScriptException(WorkerScript *);
+ void reportScriptException(WorkerScript *, const QDeclarativeError &error);
};
-QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine)
-: workerEngine(0), qmlengine(engine), m_nextId(0)
+QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QDeclarativeWorkerScriptEnginePrivate *parent)
+: p(parent), accessManager(0)
{
}
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::onMessage(QScriptContext *ctxt, QScriptEngine *engine)
+QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
+{
+ createsend.Dispose(); createsend.Clear();
+ onmessage.Dispose(); onmessage.Clear();
+ delete accessManager;
+}
+
+void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::init()
{
- QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine);
+ QV8Engine::init(0);
- int id = ctxt->thisObject().data().toVariant().toInt();
+#define CALL_ONMESSAGE_SCRIPT \
+ "(function(object, message) { "\
+ "var isfunction = false; "\
+ "try { "\
+ "isfunction = object.WorkerScript.onMessage instanceof Function; "\
+ "} catch (e) {}" \
+ "if (isfunction) "\
+ "object.WorkerScript.onMessage(message); "\
+ "})"
- WorkerScript *script = p->workers.value(id);
- if (!script)
- return engine->undefinedValue();
+#define SEND_MESSAGE_CREATE_SCRIPT \
+ "(function(method, engine) { "\
+ "return (function(id) { "\
+ "return (function(message) { "\
+ "if (arguments.length) method(engine, id, message); "\
+ "}); "\
+ "}); "\
+ "})"
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(context());
- if (ctxt->argumentCount() >= 1)
- script->callback = ctxt->argument(0);
+ {
+ v8::Local<v8::Script> onmessagescript = v8::Script::New(v8::String::New(CALL_ONMESSAGE_SCRIPT));
+ onmessage = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(onmessagescript->Run()));
+ }
+ {
+ v8::Local<v8::Script> createsendscript = v8::Script::New(v8::String::New(SEND_MESSAGE_CREATE_SCRIPT));
+ v8::Local<v8::Function> createsendconstructor = v8::Local<v8::Function>::Cast(createsendscript->Run());
- return script->callback;
+ v8::Handle<v8::Value> args[] = {
+ V8FUNCTION(QDeclarativeWorkerScriptEnginePrivate::sendMessage, this)
+ };
+ v8::Local<v8::Value> createsendvalue = createsendconstructor->Call(global(), 1, args);
+
+ createsend = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(createsendvalue));
+ }
}
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::sendMessage(QScriptContext *ctxt, QScriptEngine *engine)
+// Requires handle and context scope
+v8::Local<v8::Function> QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id)
{
- if (!ctxt->argumentCount())
- return engine->undefinedValue();
+ v8::Handle<v8::Value> args[] = { v8::Integer::New(id) };
+ return v8::Local<v8::Function>::Cast(createsend->Call(global(), 1, args));
+}
- QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine);
+// Requires handle and context scope
+void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::callOnMessage(v8::Handle<v8::Object> object,
+ v8::Handle<v8::Value> arg)
+{
+ v8::Handle<v8::Value> args[] = { object, arg };
+ onmessage->Call(global(), 2, args);
+}
- int id = ctxt->thisObject().data().toVariant().toInt();
+QNetworkAccessManager *QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
+{
+ if (!accessManager) {
+ if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
+ accessManager = p->qmlengine->networkAccessManagerFactory()->create(p);
+ } else {
+ accessManager = new QNetworkAccessManager(p);
+ }
+ }
+ return accessManager;
+}
- WorkerScript *script = p->workers.value(id);
- if (!script)
- return engine->undefinedValue();
+QDeclarativeWorkerScriptEnginePrivate::QDeclarativeWorkerScriptEnginePrivate(QDeclarativeEngine *engine)
+: workerEngine(0), qmlengine(engine), m_nextId(0)
+{
+}
- QMutexLocker(&p->m_lock);
+v8::Handle<v8::Value> QDeclarativeWorkerScriptEnginePrivate::sendMessage(const v8::Arguments &args)
+{
+ WorkerEngine *engine = (WorkerEngine*)V8ENGINE();
+
+ int id = args[1]->Int32Value();
+
+ QByteArray data = QV8Worker::serialize(args[2], engine);
+
+ QMutexLocker(&engine->p->m_lock);
+ WorkerScript *script = engine->p->workers.value(id);
+ if (!script)
+ return v8::Undefined();
if (script->owner)
- QCoreApplication::postEvent(script->owner,
- new WorkerDataEvent(0, scriptValueToVariant(ctxt->argument(0))));
+ QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));
- return engine->undefinedValue();
+ return v8::Undefined();
}
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::getWorker(int id)
+// Requires handle scope and context scope
+v8::Handle<v8::Object> QDeclarativeWorkerScriptEnginePrivate::getWorker(WorkerScript *script)
{
- QHash<int, WorkerScript *>::ConstIterator iter = workers.find(id);
-
- if (iter == workers.end())
- return workerEngine->nullValue();
-
- WorkerScript *script = *iter;
if (!script->initialized) {
-
script->initialized = true;
- script->object = workerEngine->newObject();
- QScriptValue api = workerEngine->newObject();
- api.setData(script->id);
+ script->object = v8::Persistent<v8::Object>::New(workerEngine->contextWrapper()->urlScope(script->source));
- api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage),
- QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- api.setProperty(QLatin1String("sendMessage"), workerEngine->newFunction(sendMessage));
+ workerEngine->contextWrapper()->setReadOnly(script->object, false);
- script->object.setProperty(QLatin1String("WorkerScript"), api);
+ v8::Local<v8::Object> api = v8::Object::New();
+ api->Set(v8::String::New("sendMessage"), workerEngine->sendFunction(script->id));
+
+ script->object->Set(v8::String::New("WorkerScript"), api);
+
+ workerEngine->contextWrapper()->setReadOnly(script->object, true);
}
return script->object;
@@ -262,6 +318,7 @@ QScriptValue QDeclarativeWorkerScriptEnginePrivate::getWorker(int id)
bool QDeclarativeWorkerScriptEnginePrivate::event(QEvent *event)
{
+ // XXX must handle remove request
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
processMessage(workerEvent->workerId(), workerEvent->data());
@@ -278,22 +335,24 @@ bool QDeclarativeWorkerScriptEnginePrivate::event(QEvent *event)
}
}
-void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QVariant &data)
+void QDeclarativeWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data)
{
WorkerScript *script = workers.value(id);
if (!script)
return;
- if (script->callback.isFunction()) {
- QScriptValue args = workerEngine->newArray(1);
- args.setProperty(0, variantToScriptValue(data, workerEngine));
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(workerEngine->context());
- script->callback.call(script->object, args);
+ v8::Handle<v8::Value> value = QV8Worker::deserialize(data, workerEngine);
- if (workerEngine->hasUncaughtException()) {
- reportScriptException(script);
- workerEngine->clearExceptions();
- }
+ v8::TryCatch tc;
+ workerEngine->callOnMessage(script->object, value);
+
+ if (tc.HasCaught()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(tc.Message(), error);
+ reportScriptException(script, error);
}
}
@@ -308,44 +367,41 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
if (f.open(QIODevice::ReadOnly)) {
QByteArray data = f.readAll();
QString sourceCode = QString::fromUtf8(data);
-
- QScriptValue activation = getWorker(id);
-
- QScriptContext *ctxt = QScriptDeclarativeClass::pushCleanContext(workerEngine);
- QScriptValue urlContext = workerEngine->newObject();
- urlContext.setData(QScriptValue(workerEngine, url.toString()));
- ctxt->pushScope(urlContext);
- ctxt->pushScope(activation);
- ctxt->setActivationObject(activation);
QDeclarativeScriptParser::extractPragmas(sourceCode);
- workerEngine->baseUrl = url;
- workerEngine->evaluate(sourceCode);
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(workerEngine->context());
WorkerScript *script = workers.value(id);
- if (script) {
- script->source = url;
- if (workerEngine->hasUncaughtException()) {
- reportScriptException(script);
- workerEngine->clearExceptions();
- }
+ if (!script)
+ return;
+ script->source = url;
+ v8::Handle<v8::Object> activation = getWorker(script);
+ if (activation.IsEmpty())
+ return;
+
+ // XXX ???
+ // workerEngine->baseUrl = url;
+
+ v8::TryCatch tc;
+ v8::Local<v8::Script> program = workerEngine->qmlModeCompile(sourceCode, url.toString());
+
+ if (!tc.HasCaught())
+ program->Run(activation);
+
+ if (tc.HasCaught()) {
+ QDeclarativeError error;
+ QDeclarativeExpressionPrivate::exceptionToError(tc.Message(), error);
+ reportScriptException(script, error);
}
-
- workerEngine->popContext();
} else {
qWarning().nospace() << "WorkerScript: Cannot find source file " << url.toString();
}
}
-void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script)
+void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script,
+ const QDeclarativeError &error)
{
- if (!script || !workerEngine->hasUncaughtException())
- return;
-
- QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(workerEngine, error);
- error.setUrl(script->source);
-
QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(workerEngine);
QMutexLocker(&p->m_lock);
@@ -353,109 +409,7 @@ void QDeclarativeWorkerScriptEnginePrivate::reportScriptException(WorkerScript *
QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error));
}
-QVariant QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(const QScriptValue &value)
-{
- if (value.isBool()) {
- return QVariant(value.toBool());
- } else if (value.isString()) {
- return QVariant(value.toString());
- } else if (value.isNumber()) {
- return QVariant((qreal)value.toNumber());
- } else if (value.isDate()) {
- return QVariant(value.toDateTime());
-#ifndef QT_NO_REGEXP
- } else if (value.isRegExp()) {
- return QVariant(value.toRegExp());
-#endif
- } else if (value.isArray()) {
- QVariantList list;
-
- quint32 length = (quint32)value.property(QLatin1String("length")).toNumber();
-
- for (quint32 ii = 0; ii < length; ++ii) {
- QVariant v = scriptValueToVariant(value.property(ii));
- list << v;
- }
-
- return QVariant(list);
- } else if (value.isQObject()) {
- QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(value.toQObject());
- if (lm) {
- QDeclarativeListModelWorkerAgent *agent = lm->agent();
- if (agent) {
- QDeclarativeListModelWorkerAgent::VariantRef v(agent);
- return QVariant::fromValue(v);
- } else {
- return QVariant();
- }
- } else {
- // No other QObject's are allowed to be sent
- return QVariant();
- }
- } else if (value.isObject()) {
- QVariantHash hash;
-
- QScriptValueIterator iter(value);
-
- while (iter.hasNext()) {
- iter.next();
- hash.insert(iter.name(), scriptValueToVariant(iter.value()));
- }
-
- return QVariant(hash);
- }
-
- return QVariant();
-
-}
-
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(const QVariant &value, QScriptEngine *engine)
-{
- if (value.userType() == QVariant::Bool) {
- return QScriptValue(value.toBool());
- } else if (value.userType() == QVariant::String) {
- return QScriptValue(value.toString());
- } else if (value.userType() == QMetaType::QReal) {
- return QScriptValue(value.toReal());
- } else if (value.userType() == QVariant::DateTime) {
- return engine->newDate(value.toDateTime());
-#ifndef QT_NO_REGEXP
- } else if (value.userType() == QVariant::RegExp) {
- return engine->newRegExp(value.toRegExp());
-#endif
- } else if (value.userType() == qMetaTypeId<QDeclarativeListModelWorkerAgent::VariantRef>()) {
- QDeclarativeListModelWorkerAgent::VariantRef vr = qvariant_cast<QDeclarativeListModelWorkerAgent::VariantRef>(value);
- if (vr.a->scriptEngine() == 0)
- vr.a->setScriptEngine(engine);
- else if (vr.a->scriptEngine() != engine)
- return engine->nullValue();
- QScriptValue o = engine->newQObject(vr.a);
- o.setData(engine->newVariant(value)); // Keeps the agent ref so that it is cleaned up on gc
- return o;
- } else if (value.userType() == QMetaType::QVariantList) {
- QVariantList list = qvariant_cast<QVariantList>(value);
- QScriptValue rv = engine->newArray(list.count());
-
- for (quint32 ii = 0; ii < quint32(list.count()); ++ii)
- rv.setProperty(ii, variantToScriptValue(list.at(ii), engine));
-
- return rv;
- } else if (value.userType() == QMetaType::QVariantHash) {
-
- QVariantHash hash = qvariant_cast<QVariantHash>(value);
-
- QScriptValue rv = engine->newObject();
-
- for (QVariantHash::ConstIterator iter = hash.begin(); iter != hash.end(); ++iter)
- rv.setProperty(iter.key(), variantToScriptValue(iter.value(), engine));
-
- return rv;
- } else {
- return engine->nullValue();
- }
-}
-
-WorkerDataEvent::WorkerDataEvent(int workerId, const QVariant &data)
+WorkerDataEvent::WorkerDataEvent(int workerId, const QByteArray &data)
: QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data)
{
}
@@ -469,7 +423,7 @@ int WorkerDataEvent::workerId() const
return m_id;
}
-QVariant WorkerDataEvent::data() const
+QByteArray WorkerDataEvent::data() const
{
return m_data;
}
@@ -537,9 +491,16 @@ QDeclarativeWorkerScriptEnginePrivate::WorkerScript::WorkerScript()
{
}
+QDeclarativeWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
+{
+ object.Dispose(); object.Clear();
+}
+
int QDeclarativeWorkerScriptEngine::registerWorkerScript(QDeclarativeWorkerScript *owner)
{
- QDeclarativeWorkerScriptEnginePrivate::WorkerScript *script = new QDeclarativeWorkerScriptEnginePrivate::WorkerScript;
+ typedef QDeclarativeWorkerScriptEnginePrivate::WorkerScript WorkerScript;
+ WorkerScript *script = new WorkerScript;
+
script->id = d->m_nextId++;
script->owner = owner;
@@ -560,7 +521,7 @@ void QDeclarativeWorkerScriptEngine::executeUrl(int id, const QUrl &url)
QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url));
}
-void QDeclarativeWorkerScriptEngine::sendMessage(int id, const QVariant &data)
+void QDeclarativeWorkerScriptEngine::sendMessage(int id, const QByteArray &data)
{
QCoreApplication::postEvent(d, new WorkerDataEvent(id, data));
}
@@ -569,7 +530,11 @@ void QDeclarativeWorkerScriptEngine::run()
{
d->m_lock.lock();
- d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::ScriptEngine(d);
+ v8::Isolate *isolate = v8::Isolate::New();
+ isolate->Enter();
+
+ d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::WorkerEngine(d);
+ d->workerEngine->init();
d->m_wait.wakeAll();
@@ -578,6 +543,9 @@ void QDeclarativeWorkerScriptEngine::run()
exec();
delete d->workerEngine; d->workerEngine = 0;
+
+ isolate->Exit();
+ isolate->Dispose();
}
@@ -677,14 +645,18 @@ void QDeclarativeWorkerScript::setSource(const QUrl &source)
of ListModel objects, any modifications by the other thread to an object
passed in \c message will not be reflected in the original object.
*/
-void QDeclarativeWorkerScript::sendMessage(const QScriptValue &message)
+void QDeclarativeWorkerScript::sendMessage(QDeclarativeV8Function *args)
{
if (!engine()) {
qWarning("QDeclarativeWorkerScript: Attempt to send message before WorkerScript establishment");
return;
}
- m_engine->sendMessage(m_scriptId, QDeclarativeWorkerScriptEnginePrivate::scriptValueToVariant(message));
+ v8::Handle<v8::Value> argument = v8::Undefined();
+ if (args->Length() != 0)
+ argument = (*args)[0];
+
+ m_engine->sendMessage(m_scriptId, QV8Worker::serialize(argument, args->engine()));
}
void QDeclarativeWorkerScript::classBegin()
@@ -731,11 +703,12 @@ bool QDeclarativeWorkerScript::event(QEvent *event)
if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
QDeclarativeEngine *engine = qmlEngine(this);
if (engine) {
- QScriptEngine *scriptEngine = QDeclarativeEnginePrivate::getScriptEngine(engine);
WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event);
- QScriptValue value =
- QDeclarativeWorkerScriptEnginePrivate::variantToScriptValue(workerEvent->data(), scriptEngine);
- emit message(value);
+ QV8Engine *v8engine = &QDeclarativeEnginePrivate::get(engine)->v8engine;
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(v8engine->context());
+ v8::Handle<v8::Value> value = QV8Worker::deserialize(workerEvent->data(), v8engine);
+ emit message(QDeclarativeV8Handle::fromHandle(value));
}
return true;
} else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) {
diff --git a/src/declarative/qml/qdeclarativeworkerscript_p.h b/src/declarative/qml/qdeclarativeworkerscript_p.h
index 70fdeb4d0d..54c9644efc 100644
--- a/src/declarative/qml/qdeclarativeworkerscript_p.h
+++ b/src/declarative/qml/qdeclarativeworkerscript_p.h
@@ -78,7 +78,7 @@ public:
int registerWorkerScript(QDeclarativeWorkerScript *);
void removeWorkerScript(int);
void executeUrl(int, const QUrl &);
- void sendMessage(int, const QVariant &);
+ void sendMessage(int, const QByteArray &);
protected:
virtual void run();
@@ -87,6 +87,8 @@ private:
QDeclarativeWorkerScriptEnginePrivate *d;
};
+class QDeclarativeV8Function;
+class QDeclarativeV8Handle;
class Q_AUTOTEST_EXPORT QDeclarativeWorkerScript : public QObject, public QDeclarativeParserStatus
{
Q_OBJECT
@@ -101,11 +103,11 @@ public:
void setSource(const QUrl &);
public slots:
- void sendMessage(const QScriptValue &);
+ void sendMessage(QDeclarativeV8Function*);
signals:
void sourceChanged();
- void message(const QScriptValue &messageObject);
+ void message(const QDeclarativeV8Handle &messageObject);
protected:
virtual void classBegin();
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest.cpp b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
index 930d345285..0a3cbe5c7e 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest.cpp
+++ b/src/declarative/qml/qdeclarativexmlhttprequest.cpp
@@ -41,6 +41,8 @@
#include "private/qdeclarativexmlhttprequest_p.h"
+#include <private/qv8engine_p.h>
+
#include "qdeclarativeengine.h"
#include "private/qdeclarativeengine_p.h"
#include "private/qdeclarativerefcount_p.h"
@@ -82,17 +84,17 @@
#define VALIDATION_ERR 16
#define TYPE_MISMATCH_ERR 17
-#define THROW_DOM(error, desc) \
-{ \
- QScriptValue errorValue = context->throwError(QLatin1String(desc)); \
- errorValue.setProperty(QLatin1String("code"), error); \
- return errorValue; \
-}
+#define V8THROW_DOM(error, string) { \
+ v8::Local<v8::Value> v = v8::Exception::Error(v8::String::New(string)); \
+ v->ToObject()->Set(v8::String::New("code"), v8::Integer::New(error)); \
+ v8::ThrowException(v); \
+ return v8::Handle<v8::Value>(); \
+}
-#define THROW_SYNTAX(desc) \
- return context->throwError(QScriptContext::SyntaxError, QLatin1String(desc));
-#define THROW_REFERENCE(desc) \
- return context->throwError(QScriptContext::ReferenceError, QLatin1String(desc));
+#define V8THROW_REFERENCE(string) { \
+ v8::ThrowException(v8::Exception::ReferenceError(v8::String::New(string))); \
+ return v8::Handle<v8::Value>(); \
+}
#define D(arg) (arg)->release()
#define A(arg) (arg)->addref()
@@ -101,6 +103,59 @@ QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP);
+struct QDeclarativeXMLHttpRequestData {
+ QDeclarativeXMLHttpRequestData();
+ ~QDeclarativeXMLHttpRequestData();
+
+ v8::Persistent<v8::Function> nodeFunction;
+
+ v8::Persistent<v8::Object> namedNodeMapPrototype;
+ v8::Persistent<v8::Object> nodeListPrototype;
+ v8::Persistent<v8::Object> nodePrototype;
+ v8::Persistent<v8::Object> elementPrototype;
+ v8::Persistent<v8::Object> attrPrototype;
+ v8::Persistent<v8::Object> characterDataPrototype;
+ v8::Persistent<v8::Object> textPrototype;
+ v8::Persistent<v8::Object> cdataPrototype;
+ v8::Persistent<v8::Object> documentPrototype;
+
+ v8::Local<v8::Object> newNode();
+};
+
+static inline QDeclarativeXMLHttpRequestData *xhrdata(QV8Engine *engine)
+{
+ return (QDeclarativeXMLHttpRequestData *)engine->xmlHttpRequestData();
+}
+
+QDeclarativeXMLHttpRequestData::QDeclarativeXMLHttpRequestData()
+{
+}
+
+QDeclarativeXMLHttpRequestData::~QDeclarativeXMLHttpRequestData()
+{
+ nodeFunction.Dispose(); nodeFunction.Clear();
+ namedNodeMapPrototype.Dispose(); namedNodeMapPrototype.Clear();
+ nodeListPrototype.Dispose(); nodeListPrototype.Clear();
+ nodePrototype.Dispose(); nodePrototype.Clear();
+ elementPrototype.Dispose(); elementPrototype.Clear();
+ attrPrototype.Dispose(); attrPrototype.Clear();
+ characterDataPrototype.Dispose(); characterDataPrototype.Clear();
+ textPrototype.Dispose(); textPrototype.Clear();
+ cdataPrototype.Dispose(); cdataPrototype.Clear();
+ documentPrototype.Dispose(); documentPrototype.Clear();
+}
+
+v8::Local<v8::Object> QDeclarativeXMLHttpRequestData::newNode()
+{
+ if (nodeFunction.IsEmpty()) {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ nodeFunction = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+
+ return nodeFunction->NewInstance();
+}
+
namespace {
class DocumentImpl;
@@ -169,86 +224,53 @@ class NamedNodeMap
{
public:
// JS API
- static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> length(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> indexed(uint32_t index, const v8::AccessorInfo& info);
+ static v8::Handle<v8::Value> named(v8::Local<v8::String> property, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue create(QScriptEngine *, NodeImpl *, QList<NodeImpl *> *);
-
- NamedNodeMap();
- NamedNodeMap(const NamedNodeMap &);
- ~NamedNodeMap();
- bool isNull();
-
- NodeImpl *d;
- QList<NodeImpl *> *list;
-private:
- NamedNodeMap &operator=(const NamedNodeMap &);
-};
-
-class NamedNodeMapClass : public QScriptClass
-{
-public:
- NamedNodeMapClass(QScriptEngine *engine) : QScriptClass(engine) {}
-
- virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> create(QV8Engine *, NodeImpl *, QList<NodeImpl *> *);
};
class NodeList
{
public:
// JS API
- static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> length(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> indexed(uint32_t index, const v8::AccessorInfo& info);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue create(QScriptEngine *, NodeImpl *);
-
- NodeList();
- NodeList(const NodeList &);
- ~NodeList();
- bool isNull();
-
- NodeImpl *d;
-private:
- NodeList &operator=(const NodeList &);
-};
-
-class NodeListClass : public QScriptClass
-{
-public:
- NodeListClass(QScriptEngine *engine) : QScriptClass(engine) {}
- virtual QueryFlags queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id);
- virtual QScriptValue property(const QScriptValue &object, const QScriptString &name, uint id);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> create(QV8Engine *, NodeImpl *);
};
class Node
{
public:
// JS API
- static QScriptValue nodeName(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue nodeValue(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue nodeType(QScriptContext *context, QScriptEngine *engine);
-
- static QScriptValue parentNode(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue childNodes(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue firstChild(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue lastChild(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue previousSibling(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue nextSibling(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue attributes(QScriptContext *context, QScriptEngine *engine);
-
- //static QScriptValue ownerDocument(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue namespaceURI(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue prefix(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue localName(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue baseURI(QScriptContext *context, QScriptEngine *engine);
- //static QScriptValue textContent(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> nodeName(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> nodeValue(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> nodeType(v8::Local<v8::String>, const v8::AccessorInfo& args);
+
+ static v8::Handle<v8::Value> parentNode(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> childNodes(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> firstChild(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> lastChild(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> previousSibling(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> nextSibling(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> attributes(v8::Local<v8::String>, const v8::AccessorInfo& args);
+
+ //static v8::Handle<v8::Value> ownerDocument(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> namespaceURI(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> prefix(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> localName(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> baseURI(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ //static v8::Handle<v8::Value> textContent(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue create(QScriptEngine *, NodeImpl *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> create(QV8Engine *, NodeImpl *);
Node();
Node(const Node &o);
@@ -265,68 +287,82 @@ class Element : public Node
{
public:
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class Attr : public Node
{
public:
// JS API
- static QScriptValue name(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue specified(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue value(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue ownerElement(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue schemaTypeInfo(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue isId(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> name(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> specified(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> value(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> ownerElement(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> schemaTypeInfo(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> isId(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class CharacterData : public Node
{
public:
// JS API
- static QScriptValue length(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> length(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class Text : public CharacterData
{
public:
// JS API
- static QScriptValue isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue wholeText(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> isElementContentWhitespace(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> wholeText(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class CDATA : public Text
{
public:
// C++ API
- static QScriptValue prototype(QScriptEngine *);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
};
class Document : public Node
{
public:
// JS API
- static QScriptValue xmlVersion(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue xmlEncoding(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue xmlStandalone(QScriptContext *context, QScriptEngine *engine);
- static QScriptValue documentElement(QScriptContext *context, QScriptEngine *engine);
+ static v8::Handle<v8::Value> xmlVersion(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> xmlEncoding(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> xmlStandalone(v8::Local<v8::String>, const v8::AccessorInfo& args);
+ static v8::Handle<v8::Value> documentElement(v8::Local<v8::String>, const v8::AccessorInfo& args);
// C++ API
- static QScriptValue prototype(QScriptEngine *);
- static QScriptValue load(QScriptEngine *engine, const QByteArray &data);
+ static v8::Handle<v8::Object> prototype(QV8Engine *);
+ static v8::Handle<v8::Value> load(QV8Engine *engine, const QByteArray &data);
};
}
+class QDeclarativeDOMNodeResource : public QV8ObjectResource, public Node
+{
+ V8_RESOURCE_TYPE(DOMNodeType);
+public:
+ QDeclarativeDOMNodeResource(QV8Engine *e);
+
+ QList<NodeImpl *> *list; // Only used in NamedNodeMap
+};
+
+QDeclarativeDOMNodeResource::QDeclarativeDOMNodeResource(QV8Engine *e)
+: QV8ObjectResource(e), list(0)
+{
+}
+
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Node)
@@ -345,152 +381,174 @@ void NodeImpl::release()
D(document);
}
-QScriptValue Node::nodeName(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nodeName(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- switch (node.d->type) {
+ switch (r->d->type) {
case NodeImpl::Document:
- return QScriptValue(QLatin1String("#document"));
+ return v8::String::New("#document");
case NodeImpl::CDATA:
- return QScriptValue(QLatin1String("#cdata-section"));
+ return v8::String::New("#cdata-section");
case NodeImpl::Text:
- return QScriptValue(QLatin1String("#text"));
+ return v8::String::New("#text");
default:
- return QScriptValue(node.d->name);
+ return engine->toString(r->d->name);
}
}
-QScriptValue Node::nodeValue(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nodeValue(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->type == NodeImpl::Document ||
- node.d->type == NodeImpl::DocumentFragment ||
- node.d->type == NodeImpl::DocumentType ||
- node.d->type == NodeImpl::Element ||
- node.d->type == NodeImpl::Entity ||
- node.d->type == NodeImpl::EntityReference ||
- node.d->type == NodeImpl::Notation)
- return engine->nullValue();
+ if (r->d->type == NodeImpl::Document ||
+ r->d->type == NodeImpl::DocumentFragment ||
+ r->d->type == NodeImpl::DocumentType ||
+ r->d->type == NodeImpl::Element ||
+ r->d->type == NodeImpl::Entity ||
+ r->d->type == NodeImpl::EntityReference ||
+ r->d->type == NodeImpl::Notation)
+ return v8::Null();
- return QScriptValue(node.d->data);
+ return engine->toString(r->d->data);
}
-QScriptValue Node::nodeType(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nodeType(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
- return QScriptValue(node.d->type);
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ return v8::Integer::New(r->d->type);
}
-QScriptValue Node::parentNode(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::parentNode(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->parent) return Node::create(engine, node.d->parent);
- else return engine->nullValue();
+ if (r->d->parent) return Node::create(engine, r->d->parent);
+ else return v8::Null();
}
-QScriptValue Node::childNodes(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::childNodes(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return NodeList::create(engine, node.d);
+ return NodeList::create(engine, r->d);
}
-QScriptValue Node::firstChild(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::firstChild(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->children.isEmpty()) return engine->nullValue();
- else return Node::create(engine, node.d->children.first());
+ if (r->d->children.isEmpty()) return v8::Null();
+ else return Node::create(engine, r->d->children.first());
}
-QScriptValue Node::lastChild(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::lastChild(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->children.isEmpty()) return engine->nullValue();
- else return Node::create(engine, node.d->children.last());
+ if (r->d->children.isEmpty()) return v8::Null();
+ else return Node::create(engine, r->d->children.last());
}
-QScriptValue Node::previousSibling(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::previousSibling(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (!node.d->parent) return engine->nullValue();
+ if (!r->d->parent) return v8::Null();
- for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
- if (node.d->parent->children.at(ii) == node.d) {
- if (ii == 0) return engine->nullValue();
- else return Node::create(engine, node.d->parent->children.at(ii - 1));
+ for (int ii = 0; ii < r->d->parent->children.count(); ++ii) {
+ if (r->d->parent->children.at(ii) == r->d) {
+ if (ii == 0) return v8::Null();
+ else return Node::create(engine, r->d->parent->children.at(ii - 1));
}
}
- return engine->nullValue();
+ return v8::Null();
}
-QScriptValue Node::nextSibling(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::nextSibling(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (!node.d->parent) return engine->nullValue();
+ if (!r->d->parent) return v8::Null();
- for (int ii = 0; ii < node.d->parent->children.count(); ++ii) {
- if (node.d->parent->children.at(ii) == node.d) {
- if ((ii + 1) == node.d->parent->children.count()) return engine->nullValue();
- else return Node::create(engine, node.d->parent->children.at(ii + 1));
+ for (int ii = 0; ii < r->d->parent->children.count(); ++ii) {
+ if (r->d->parent->children.at(ii) == r->d) {
+ if ((ii + 1) == r->d->parent->children.count()) return v8::Null();
+ else return Node::create(engine, r->d->parent->children.at(ii + 1));
}
}
- return engine->nullValue();
+ return v8::Null();
}
-QScriptValue Node::attributes(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Node::attributes(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- if (node.d->type != NodeImpl::Element)
- return engine->nullValue();
+ if (r->d->type != NodeImpl::Element)
+ return v8::Null();
else
- return NamedNodeMap::create(engine, node.d, &node.d->attributes);
-}
-
-QScriptValue Node::prototype(QScriptEngine *engine)
-{
- QScriptValue proto = engine->newObject();
-
- proto.setProperty(QLatin1String("nodeName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("nodeValue"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("nodeType"), engine->newFunction(nodeType), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("parentNode"), engine->newFunction(parentNode), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("childNodes"), engine->newFunction(childNodes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("firstChild"), engine->newFunction(firstChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("lastChild"), engine->newFunction(lastChild), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("previousSibling"), engine->newFunction(previousSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("nextSibling"), engine->newFunction(nextSibling), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("attributes"), engine->newFunction(attributes), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return NamedNodeMap::create(engine, r->d, &r->d->attributes);
+}
+
+v8::Handle<v8::Object> Node::prototype(QV8Engine *engine)
+{
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->nodePrototype.IsEmpty()) {
+ d->nodePrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->nodePrototype->SetAccessor(v8::String::New("nodeName"), nodeName,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("nodeValue"), nodeValue,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("nodeType"), nodeType,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("parentNode"), parentNode,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("childNodes"), childNodes,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("firstChild"), firstChild,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("lastChild"), lastChild,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("previousSibling"), previousSibling,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("nextSibling"), nextSibling,
+ 0, v8::External::Wrap(engine));
+ d->nodePrototype->SetAccessor(v8::String::New("attributes"), attributes,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->nodePrototype;
}
-QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
+v8::Handle<v8::Value> Node::create(QV8Engine *engine, NodeImpl *data)
{
- QScriptValue instance = engine->newObject();
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ v8::Local<v8::Object> instance = d->newNode();
switch (data->type) {
case NodeImpl::Attr:
- instance.setPrototype(Attr::prototype(engine));
+ instance->SetPrototype(Attr::prototype(engine));
break;
case NodeImpl::Comment:
case NodeImpl::Document:
@@ -500,138 +558,171 @@ QScriptValue Node::create(QScriptEngine *engine, NodeImpl *data)
case NodeImpl::EntityReference:
case NodeImpl::Notation:
case NodeImpl::ProcessingInstruction:
- return QScriptValue();
+ return v8::Undefined();
case NodeImpl::CDATA:
- instance.setPrototype(CDATA::prototype(engine));
+ instance->SetPrototype(CDATA::prototype(engine));
break;
case NodeImpl::Text:
- instance.setPrototype(Text::prototype(engine));
+ instance->SetPrototype(Text::prototype(engine));
break;
case NodeImpl::Element:
- instance.setPrototype(Element::prototype(engine));
+ instance->SetPrototype(Element::prototype(engine));
break;
}
- Node node;
- node.d = data;
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = data;
if (data) A(data);
+ instance->SetExternalResource(r);
- return engine->newVariant(instance, QVariant::fromValue(node));
-}
-
-QScriptValue Element::prototype(QScriptEngine *engine)
-{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
-
- proto.setProperty(QLatin1String("tagName"), engine->newFunction(nodeName), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
-}
-
-QScriptValue Attr::prototype(QScriptEngine *engine)
-{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
-
- proto.setProperty(QLatin1String("name"), engine->newFunction(name), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("value"), engine->newFunction(value), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("ownerElement"), engine->newFunction(ownerElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return instance;
}
-QScriptValue Attr::name(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Object> Element::prototype(QV8Engine *engine)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
-
- return QScriptValue(node.d->name);
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->elementPrototype.IsEmpty()) {
+ d->elementPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->elementPrototype->SetPrototype(Node::prototype(engine));
+ d->elementPrototype->SetAccessor(v8::String::New("tagName"), nodeName,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->elementPrototype;
+}
+
+v8::Handle<v8::Object> Attr::prototype(QV8Engine *engine)
+{
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->attrPrototype.IsEmpty()) {
+ d->attrPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->attrPrototype->SetPrototype(Node::prototype(engine));
+ d->attrPrototype->SetAccessor(v8::String::New("name"), name,
+ 0, v8::External::Wrap(engine));
+ d->attrPrototype->SetAccessor(v8::String::New("value"), value,
+ 0, v8::External::Wrap(engine));
+ d->attrPrototype->SetAccessor(v8::String::New("ownerElement"), ownerElement,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->attrPrototype;
}
-QScriptValue Attr::value(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Attr::name(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(node.d->data);
+ return engine->toString(r->d->name);
}
-QScriptValue Attr::ownerElement(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Attr::value(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return Node::create(engine, node.d->parent);
+ return engine->toString(r->d->data);
}
-QScriptValue CharacterData::length(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Attr::ownerElement(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(node.d->data.length());
+ return Node::create(engine, r->d->parent);
}
-QScriptValue CharacterData::prototype(QScriptEngine *engine)
+v8::Handle<v8::Value> CharacterData::length(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- proto.setProperty(QLatin1String("data"), engine->newFunction(nodeValue), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return v8::Integer::New(r->d->data.length());
}
-QScriptValue Text::isElementContentWhitespace(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Object> CharacterData::prototype(QV8Engine *engine)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
-
- return node.d->data.trimmed().isEmpty();
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->characterDataPrototype.IsEmpty()) {
+ d->characterDataPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->characterDataPrototype->SetPrototype(Node::prototype(engine));
+ d->characterDataPrototype->SetAccessor(v8::String::New("data"), nodeValue,
+ 0, v8::External::Wrap(engine));
+ d->characterDataPrototype->SetAccessor(v8::String::New("length"), length,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->characterDataPrototype;
}
-QScriptValue Text::wholeText(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Text::isElementContentWhitespace(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- Node node = qscriptvalue_cast<Node>(context->thisObject());
- if (node.isNull()) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return node.d->data;
+ return v8::Boolean::New(r->d->data.trimmed().isEmpty());
}
-QScriptValue Text::prototype(QScriptEngine *engine)
+v8::Handle<v8::Value> Text::wholeText(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(CharacterData::prototype(engine));
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- proto.setProperty(QLatin1String("isElementContentWhitespace"), engine->newFunction(isElementContentWhitespace), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- proto.setProperty(QLatin1String("wholeText"), engine->newFunction(wholeText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return engine->toString(r->d->data);
}
-QScriptValue CDATA::prototype(QScriptEngine *engine)
+v8::Handle<v8::Object> Text::prototype(QV8Engine *engine)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Text::prototype(engine));
- return proto;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->textPrototype.IsEmpty()) {
+ d->textPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->textPrototype->SetPrototype(CharacterData::prototype(engine));
+ d->textPrototype->SetAccessor(v8::String::New("isElementContentWhitespace"), isElementContentWhitespace,
+ 0, v8::External::Wrap(engine));
+ d->textPrototype->SetAccessor(v8::String::New("wholeText"), wholeText,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->textPrototype;
}
-QScriptValue Document::prototype(QScriptEngine *engine)
+v8::Handle<v8::Object> CDATA::prototype(QV8Engine *engine)
{
- QScriptValue proto = engine->newObject();
- proto.setPrototype(Node::prototype(engine));
-
- proto.setProperty(QLatin1String("xmlVersion"), engine->newFunction(xmlVersion), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("xmlEncoding"), engine->newFunction(xmlEncoding), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("xmlStandalone"), engine->newFunction(xmlStandalone), QScriptValue::ReadOnly | QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
- proto.setProperty(QLatin1String("documentElement"), engine->newFunction(documentElement), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->cdataPrototype.IsEmpty()) {
+ d->cdataPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->cdataPrototype->SetPrototype(Text::prototype(engine));
+ // XXX freeze
+ }
+ return d->cdataPrototype;
+}
+
+v8::Handle<v8::Object> Document::prototype(QV8Engine *engine)
+{
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->documentPrototype.IsEmpty()) {
+ d->documentPrototype = v8::Persistent<v8::Object>::New(v8::Object::New());
+ d->documentPrototype->SetPrototype(Node::prototype(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("xmlVersion"), xmlVersion,
+ 0, v8::External::Wrap(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("xmlEncoding"), xmlEncoding,
+ 0, v8::External::Wrap(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("xmlStandalone"), xmlStandalone,
+ 0, v8::External::Wrap(engine));
+ d->documentPrototype->SetAccessor(v8::String::New("documentElement"), documentElement,
+ 0, v8::External::Wrap(engine));
+ // XXX freeze
+ }
+ return d->documentPrototype;
}
-QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
+v8::Handle<v8::Value> Document::load(QV8Engine *engine, const QByteArray &data)
{
Q_ASSERT(engine);
@@ -709,14 +800,15 @@ QScriptValue Document::load(QScriptEngine *engine, const QByteArray &data)
if (!document || reader.hasError()) {
if (document) D(document);
- return engine->nullValue();
+ return v8::Null();
}
- QScriptValue instance = engine->newObject();
- instance.setPrototype(Document::prototype(engine));
- Node documentNode;
- documentNode.d = document;
- return engine->newVariant(instance, QVariant::fromValue(documentNode));
+ v8::Local<v8::Object> instance = xhrdata(engine)->newNode();
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = document;
+ instance->SetExternalResource(r);
+ instance->SetPrototype(Document::prototype(engine));
+ return instance;
}
Node::Node()
@@ -740,221 +832,165 @@ bool Node::isNull() const
return d == 0;
}
-QScriptValue NamedNodeMap::length(QScriptContext *context, QScriptEngine *engine)
-{
- NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(context->thisObject().data());
- if (map.isNull()) return engine->undefinedValue();
-
- return QScriptValue(map.list->count());
-}
-
-QScriptValue NamedNodeMap::prototype(QScriptEngine *engine)
+v8::Handle<v8::Value> NamedNodeMap::length(v8::Local<v8::String>, const v8::AccessorInfo &args)
{
- QScriptValue proto = engine->newObject();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ return v8::Integer::New(r->list->count());
}
-QScriptValue NamedNodeMap::create(QScriptEngine *engine, NodeImpl *data, QList<NodeImpl *> *list)
+v8::Handle<v8::Value> NamedNodeMap::indexed(uint32_t index, const v8::AccessorInfo& args)
{
- QScriptValue instance = engine->newObject();
- instance.setPrototype(NamedNodeMap::prototype(engine));
-
- NamedNodeMap map;
- map.d = data;
- map.list = list;
- if (data) A(data);
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || !r->list) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- instance.setData(engine->newVariant(QVariant::fromValue(map)));
-
- if (!QDeclarativeScriptEngine::get(engine)->namedNodeMapClass)
- QDeclarativeScriptEngine::get(engine)->namedNodeMapClass= new NamedNodeMapClass(engine);
-
- instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->namedNodeMapClass);
-
- return instance;
-}
-
-NamedNodeMap::NamedNodeMap()
-: d(0), list(0)
-{
-}
-
-NamedNodeMap::NamedNodeMap(const NamedNodeMap &o)
-: d(o.d), list(o.list)
-{
- if (d) A(d);
-}
-
-NamedNodeMap::~NamedNodeMap()
-{
- if (d) D(d);
+ if (index < r->list->count()) {
+ return Node::create(engine, r->list->at(index));
+ } else {
+ return v8::Undefined();
+ }
}
-bool NamedNodeMap::isNull()
+v8::Handle<v8::Value> NamedNodeMap::named(v8::Local<v8::String> property, const v8::AccessorInfo& args)
{
- return d == 0;
-}
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || !r->list) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
-QScriptValue NodeList::length(QScriptContext *context, QScriptEngine *engine)
-{
- NodeList list = qscriptvalue_cast<NodeList>(context->thisObject().data());
- if (list.isNull()) return engine->undefinedValue();
+ QString str = engine->toString(property);
+ for (int ii = 0; ii < r->list->count(); ++ii) {
+ if (r->list->at(ii)->name == str) {
+ return Node::create(engine, r->list->at(ii));
+ }
+ }
- return QScriptValue(list.d->children.count());
+ return v8::Undefined();
}
-QScriptValue NodeList::prototype(QScriptEngine *engine)
+v8::Handle<v8::Object> NamedNodeMap::prototype(QV8Engine *engine)
{
- QScriptValue proto = engine->newObject();
-
- proto.setProperty(QLatin1String("length"), engine->newFunction(length), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
-
- return proto;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->namedNodeMapPrototype.IsEmpty()) {
+ v8::Local<v8::ObjectTemplate> ot = v8::ObjectTemplate::New();
+ ot->SetAccessor(v8::String::New("length"), length, 0, v8::External::Wrap(engine));
+ ot->SetIndexedPropertyHandler(indexed, 0, 0, 0, 0, v8::External::Wrap(engine));
+ ot->SetFallbackPropertyHandler(named, 0, 0, 0, 0, v8::External::Wrap(engine));
+ d->namedNodeMapPrototype = v8::Persistent<v8::Object>::New(ot->NewInstance());
+ // XXX freeze
+ }
+ return d->namedNodeMapPrototype;
}
-QScriptValue NodeList::create(QScriptEngine *engine, NodeImpl *data)
+v8::Handle<v8::Value> NamedNodeMap::create(QV8Engine *engine, NodeImpl *data, QList<NodeImpl *> *list)
{
- QScriptValue instance = engine->newObject();
- instance.setPrototype(NodeList::prototype(engine));
-
- NodeList list;
- list.d = data;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ v8::Local<v8::Object> instance = d->newNode();
+ instance->SetPrototype(NamedNodeMap::prototype(engine));
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = data;
+ r->list = list;
if (data) A(data);
-
- instance.setData(engine->newVariant(QVariant::fromValue(list)));
-
- if (!QDeclarativeScriptEngine::get(engine)->nodeListClass)
- QDeclarativeScriptEngine::get(engine)->nodeListClass= new NodeListClass(engine);
-
- instance.setScriptClass(QDeclarativeScriptEngine::get(engine)->nodeListClass);
-
+ instance->SetExternalResource(r);
return instance;
}
-NodeList::NodeList()
-: d(0)
-{
-}
-
-NodeList::NodeList(const NodeList &o)
-: d(o.d)
-{
- if (d) A(d);
-}
-
-NodeList::~NodeList()
-{
- if (d) D(d);
-}
-
-bool NodeList::isNull()
+v8::Handle<v8::Value> NodeList::indexed(uint32_t index, const v8::AccessorInfo& args)
{
- return d == 0;
-}
-
-NamedNodeMapClass::QueryFlags NamedNodeMapClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
-{
- if (!(flags & HandlesReadAccess))
- return 0;
-
- NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
- Q_ASSERT(!map.isNull());
-
- bool ok = false;
- QString nameString = name.toString();
- uint index = nameString.toUInt(&ok);
- if (ok) {
- if ((uint)map.list->count() <= index)
- return 0;
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- *id = index;
- return HandlesReadAccess;
+ if (index < r->d->children.count()) {
+ return Node::create(engine, r->d->children.at(index));
} else {
- for (int ii = 0; ii < map.list->count(); ++ii) {
- if (map.list->at(ii) && map.list->at(ii)->name == nameString) {
- *id = ii;
- return HandlesReadAccess;
- }
- }
+ // XXX RangeError exception?
+ return v8::Undefined();
}
-
- return 0;
}
-QScriptValue NamedNodeMapClass::property(const QScriptValue &object, const QScriptString &, uint id)
+v8::Handle<v8::Value> NodeList::length(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- NamedNodeMap map = qscriptvalue_cast<NamedNodeMap>(object.data());
- return Node::create(engine(), map.list->at(id));
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
+
+ return v8::Integer::New(r->d->children.count());
}
-NodeListClass::QueryFlags NodeListClass::queryProperty(const QScriptValue &object, const QScriptString &name, QueryFlags flags, uint *id)
+v8::Handle<v8::Object> NodeList::prototype(QV8Engine *engine)
{
- if (!(flags & HandlesReadAccess))
- return 0;
-
- bool ok = false;
- uint index = name.toString().toUInt(&ok);
- if (!ok)
- return 0;
-
- NodeList list = qscriptvalue_cast<NodeList>(object.data());
- if (list.isNull() || (uint)list.d->children.count() <= index)
- return 0; // ### I think we're meant to raise an exception
-
- *id = index;
- return HandlesReadAccess;
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ if (d->nodeListPrototype.IsEmpty()) {
+ v8::Local<v8::ObjectTemplate> ot = v8::ObjectTemplate::New();
+ ot->SetAccessor(v8::String::New("length"), length, 0, v8::External::Wrap(engine));
+ ot->SetIndexedPropertyHandler(indexed, 0, 0, 0, 0, v8::External::Wrap(engine));
+ d->nodeListPrototype = v8::Persistent<v8::Object>::New(ot->NewInstance());
+ // XXX freeze
+ }
+ return d->nodeListPrototype;
}
-QScriptValue NodeListClass::property(const QScriptValue &object, const QScriptString &, uint id)
+v8::Handle<v8::Value> NodeList::create(QV8Engine *engine, NodeImpl *data)
{
- NodeList list = qscriptvalue_cast<NodeList>(object.data());
- return Node::create(engine(), list.d->children.at(id));
+ QDeclarativeXMLHttpRequestData *d = xhrdata(engine);
+ v8::Local<v8::Object> instance = d->newNode();
+ instance->SetPrototype(NodeList::prototype(engine));
+ QDeclarativeDOMNodeResource *r = new QDeclarativeDOMNodeResource(engine);
+ r->d = data;
+ if (data) A(data);
+ instance->SetExternalResource(r);
+ return instance;
}
-QScriptValue Document::documentElement(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::documentElement(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return Node::create(engine, static_cast<DocumentImpl *>(document.d)->root);
+ return Node::create(engine, static_cast<DocumentImpl *>(r->d)->root);
}
-QScriptValue Document::xmlStandalone(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::xmlStandalone(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(static_cast<DocumentImpl *>(document.d)->isStandalone);
+ return v8::Boolean::New(static_cast<DocumentImpl *>(r->d)->isStandalone);
}
-QScriptValue Document::xmlVersion(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::xmlVersion(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(static_cast<DocumentImpl *>(document.d)->version);
+ return engine->toString(static_cast<DocumentImpl *>(r->d)->version);
}
-QScriptValue Document::xmlEncoding(QScriptContext *context, QScriptEngine *engine)
+v8::Handle<v8::Value> Document::xmlEncoding(v8::Local<v8::String>, const v8::AccessorInfo& args)
{
- Node document = qscriptvalue_cast<Node>(context->thisObject());
- if (document.isNull() || document.d->type != NodeImpl::Document) return engine->undefinedValue();
+ QDeclarativeDOMNodeResource *r = v8_resource_cast<QDeclarativeDOMNodeResource>(args.This());
+ if (!r || r->d->type != NodeImpl::Document) return v8::Undefined();
+ QV8Engine *engine = V8ENGINE();
- return QScriptValue(static_cast<DocumentImpl *>(document.d)->encoding);
+ return engine->toString(static_cast<DocumentImpl *>(r->d)->encoding);
}
-class QDeclarativeXMLHttpRequest : public QObject
+class QDeclarativeXMLHttpRequest : public QObject, public QV8ObjectResource
{
Q_OBJECT
+V8_RESOURCE_TYPE(XMLHttpRequestType)
public:
enum State { Unsent = 0,
Opened = 1, HeadersReceived = 2,
Loading = 3, Done = 4 };
- QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager);
+ QDeclarativeXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager);
virtual ~QDeclarativeXMLHttpRequest();
bool sendFlag() const;
@@ -963,13 +999,14 @@ public:
int replyStatus() const;
QString replyStatusText() const;
- QScriptValue open(QScriptValue *me, const QString &, const QUrl &);
+ v8::Handle<v8::Value> open(v8::Handle<v8::Object> me, const QString &, const QUrl &);
+ v8::Handle<v8::Value> send(v8::Handle<v8::Object> me, const QByteArray &);
+ v8::Handle<v8::Value> abort(v8::Handle<v8::Object> me);
void addHeader(const QString &, const QString &);
QString header(const QString &name);
QString headers();
- QScriptValue send(QScriptValue *me, const QByteArray &);
- QScriptValue abort(QScriptValue *me);
+
QString responseBody();
const QByteArray & rawResponseBody() const;
@@ -1005,10 +1042,12 @@ private:
#endif
void readEncoding();
- QScriptValue m_me; // Set to the data object while a send() is ongoing (to access the callback)
+ v8::Handle<v8::Object> getMe() const;
+ void setMe(v8::Handle<v8::Object> me);
+ v8::Persistent<v8::Object> m_me;
- QScriptValue dispatchCallback(QScriptValue *me);
- void printError(const QScriptValue&);
+ void dispatchCallback(v8::Handle<v8::Object> me);
+ void printError(v8::Handle<v8::Message>);
int m_status;
QString m_statusText;
@@ -1020,8 +1059,8 @@ private:
QNetworkAccessManager *networkAccessManager() { return m_nam; }
};
-QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QNetworkAccessManager *manager)
-: m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
+QDeclarativeXMLHttpRequest::QDeclarativeXMLHttpRequest(QV8Engine *engine, QNetworkAccessManager *manager)
+: QV8ObjectResource(engine), m_state(Unsent), m_errorFlag(false), m_sendFlag(false),
m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager)
{
}
@@ -1056,7 +1095,8 @@ QString QDeclarativeXMLHttpRequest::replyStatusText() const
return m_statusText;
}
-QScriptValue QDeclarativeXMLHttpRequest::open(QScriptValue *me, const QString &method, const QUrl &url)
+v8::Handle<v8::Value> QDeclarativeXMLHttpRequest::open(v8::Handle<v8::Object> me, const QString &method,
+ const QUrl &url)
{
destroyNetwork();
m_sendFlag = false;
@@ -1065,7 +1105,8 @@ QScriptValue QDeclarativeXMLHttpRequest::open(QScriptValue *me, const QString &m
m_method = method;
m_url = url;
m_state = Opened;
- return dispatchCallback(me);
+ dispatchCallback(me);
+ return v8::Undefined();
}
void QDeclarativeXMLHttpRequest::addHeader(const QString &name, const QString &value)
@@ -1176,20 +1217,21 @@ void QDeclarativeXMLHttpRequest::requestFromUrl(const QUrl &url)
this, SLOT(finished()));
}
-QScriptValue QDeclarativeXMLHttpRequest::send(QScriptValue *me, const QByteArray &data)
+v8::Handle<v8::Value> QDeclarativeXMLHttpRequest::send(v8::Handle<v8::Object> me, const QByteArray &data)
{
m_errorFlag = false;
m_sendFlag = true;
m_redirectCount = 0;
m_data = data;
- m_me = *me;
+
+ setMe(me);
requestFromUrl(m_url);
- return QScriptValue();
+ return v8::Undefined();
}
-QScriptValue QDeclarativeXMLHttpRequest::abort(QScriptValue *me)
+v8::Handle<v8::Value> QDeclarativeXMLHttpRequest::abort(v8::Handle<v8::Object> me)
{
destroyNetwork();
m_responseEntityBody = QByteArray();
@@ -1202,16 +1244,32 @@ QScriptValue QDeclarativeXMLHttpRequest::abort(QScriptValue *me)
m_state = Done;
m_sendFlag = false;
- QScriptValue cbv = dispatchCallback(me);
- if (cbv.isError()) return cbv;
+ dispatchCallback(me);
}
m_state = Unsent;
- return QScriptValue();
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Object> QDeclarativeXMLHttpRequest::getMe() const
+{
+ return m_me;
+}
+
+void QDeclarativeXMLHttpRequest::setMe(v8::Handle<v8::Object> me)
+{
+ m_me.Dispose();
+ m_me = v8::Persistent<v8::Object>();
+
+ if (!me.IsEmpty())
+ m_me = v8::Persistent<v8::Object>::New(me);
}
void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes)
{
+ v8::HandleScope handle_scope;
+
Q_UNUSED(bytes)
m_status =
m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -1222,16 +1280,18 @@ void QDeclarativeXMLHttpRequest::downloadProgress(qint64 bytes)
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
bool wasEmpty = m_responseEntityBody.isEmpty();
m_responseEntityBody.append(m_network->readAll());
if (wasEmpty && !m_responseEntityBody.isEmpty()) {
m_state = Loading;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
}
@@ -1249,6 +1309,8 @@ static const char *errorToString(QNetworkReply::NetworkError error)
void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error)
{
+ v8::HandleScope handle_scope;
+
Q_UNUSED(error)
m_status =
m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
@@ -1272,20 +1334,25 @@ void QDeclarativeXMLHttpRequest::error(QNetworkReply::NetworkError error)
error == QNetworkReply::AuthenticationRequiredError ||
error == QNetworkReply::ContentReSendError) {
m_state = Loading;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
} else {
m_errorFlag = true;
}
m_state = Done;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
void QDeclarativeXMLHttpRequest::finished()
{
+ v8::HandleScope handle_scope;
+
m_redirectCount++;
if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute);
@@ -1305,8 +1372,9 @@ void QDeclarativeXMLHttpRequest::finished()
if (m_state < HeadersReceived) {
m_state = HeadersReceived;
fillHeadersList ();
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
m_responseEntityBody.append(m_network->readAll());
readEncoding();
@@ -1324,14 +1392,17 @@ void QDeclarativeXMLHttpRequest::finished()
destroyNetwork();
if (m_state < Loading) {
m_state = Loading;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
}
m_state = Done;
- QScriptValue cbv = dispatchCallback(&m_me);
- if (cbv.isError()) printError(cbv);
- m_me = QScriptValue();
+ v8::TryCatch tc;
+ dispatchCallback(m_me);
+ if (tc.HasCaught()) printError(tc.Message());
+
+ setMe(v8::Handle<v8::Object>());
}
@@ -1409,17 +1480,25 @@ const QByteArray &QDeclarativeXMLHttpRequest::rawResponseBody() const
return m_responseEntityBody;
}
-QScriptValue QDeclarativeXMLHttpRequest::dispatchCallback(QScriptValue *me)
+// Requires a TryCatch scope
+void QDeclarativeXMLHttpRequest::dispatchCallback(v8::Handle<v8::Object> me)
{
- QScriptValue v = me->property(QLatin1String("callback"));
- return v.call();
+ v8::Local<v8::Value> callback = me->Get(v8::String::New("onreadystatechange"));
+ if (callback->IsFunction()) {
+ v8::Local<v8::Function> f = v8::Local<v8::Function>::Cast(callback);
+
+ f->Call(me, 0, 0);
+ }
}
-void QDeclarativeXMLHttpRequest::printError(const QScriptValue& sv)
+// Must have a handle scope
+void QDeclarativeXMLHttpRequest::printError(v8::Handle<v8::Message> message)
{
+ v8::Context::Scope scope(engine->context());
+
QDeclarativeError error;
- QDeclarativeExpressionPrivate::exceptionToError(sv.engine(), error);
- QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(sv.engine()), error);
+ QDeclarativeExpressionPrivate::exceptionToError(message, error);
+ QDeclarativeEnginePrivate::warning(QDeclarativeEnginePrivate::get(engine->engine()), error);
}
void QDeclarativeXMLHttpRequest::destroyNetwork()
@@ -1432,71 +1511,68 @@ void QDeclarativeXMLHttpRequest::destroyNetwork()
}
// XMLHttpRequest methods
-static QScriptValue qmlxmlhttprequest_open(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_open(const v8::Arguments &args)
{
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (context->argumentCount() < 2 || context->argumentCount() > 5)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ if (args.Length() < 2 || args.Length() > 5)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+
+ QV8Engine *engine = r->engine;
// Argument 0 - Method
- QString method = context->argument(0).toString().toUpper();
+ QString method = engine->toString(args[0]).toUpper();
if (method != QLatin1String("GET") &&
method != QLatin1String("PUT") &&
method != QLatin1String("HEAD") &&
method != QLatin1String("POST"))
- THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
-
+ V8THROW_DOM(SYNTAX_ERR, "Unsupported HTTP method type");
// Argument 1 - URL
- QUrl url = QUrl::fromEncoded(context->argument(1).toString().toUtf8());
+ QUrl url = QUrl::fromEncoded(engine->toString(args[1]).toUtf8());
- if (url.isRelative()) {
- url = QDeclarativeScriptEngine::get(engine)->resolvedUrl(context,url);
- }
+ if (url.isRelative())
+ url = engine->callingContext()->resolvedUrl(url);
// Argument 2 - async (optional)
- if (context->argumentCount() > 2 && !context->argument(2).toBoolean())
- THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
-
+ if (args.Length() > 2 && !args[2]->BooleanValue())
+ V8THROW_DOM(NOT_SUPPORTED_ERR, "Synchronous XMLHttpRequest calls are not supported");
// Argument 3/4 - user/pass (optional)
QString username, password;
- if (context->argumentCount() > 3)
- username = context->argument(3).toString();
- if (context->argumentCount() > 4)
- password = context->argument(4).toString();
-
+ if (args.Length() > 3)
+ username = engine->toString(args[3]);
+ if (args.Length() > 4)
+ password = engine->toString(args[4]);
// Clear the fragment (if any)
url.setFragment(QString());
+
// Set username/password
if (!username.isNull()) url.setUserName(username);
if (!password.isNull()) url.setPassword(password);
- return request->open(&dataObject, method, url);
+ return r->open(args.This(), method, url);
}
-static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_setRequestHeader(const v8::Arguments &args)
{
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
-
- if (context->argumentCount() != 2)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
+ if (args.Length() != 2)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
- if (request->readyState() != QDeclarativeXMLHttpRequest::Opened ||
- request->sendFlag())
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Opened || r->sendFlag())
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ QV8Engine *engine = r->engine;
- QString name = context->argument(0).toString();
- QString value = context->argument(1).toString();
+ QString name = engine->toString(args[0]);
+ QString value = engine->toString(args[1]);
// ### Check that name and value are well formed
@@ -1521,237 +1597,243 @@ static QScriptValue qmlxmlhttprequest_setRequestHeader(QScriptContext *context,
nameUpper == QLatin1String("VIA") ||
nameUpper.startsWith(QLatin1String("PROXY-")) ||
nameUpper.startsWith(QLatin1String("SEC-")))
- return engine->undefinedValue();
+ return v8::Undefined();
- request->addHeader(nameUpper, value);
+ r->addHeader(nameUpper, value);
- return engine->undefinedValue();
+ return v8::Undefined();
}
-static QScriptValue qmlxmlhttprequest_send(QScriptContext *context, QScriptEngine *)
+static v8::Handle<v8::Value> qmlxmlhttprequest_send(const v8::Arguments &args)
{
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (request->readyState() != QDeclarativeXMLHttpRequest::Opened)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ QV8Engine *engine = r->engine;
- if (request->sendFlag())
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Opened ||
+ r->sendFlag())
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
QByteArray data;
- if (context->argumentCount() > 0)
- data = context->argument(0).toString().toUtf8();
+ if (args.Length() > 0)
+ data = engine->toString(args[0]).toUtf8();
- return request->send(&dataObject, data);
+ return r->send(args.This(), data);
}
-static QScriptValue qmlxmlhttprequest_abort(QScriptContext *context, QScriptEngine *)
+static v8::Handle<v8::Value> qmlxmlhttprequest_abort(const v8::Arguments &args)
{
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- return request->abort(&dataObject);
+ return r->abort(args.This());
}
-static QScriptValue qmlxmlhttprequest_getResponseHeader(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_getResponseHeader(const v8::Arguments &args)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (context->argumentCount() != 1)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ QV8Engine *engine = r->engine;
- if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done &&
- request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (args.Length() != 1)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
- QString headerName = context->argument(0).toString();
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done &&
+ r->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
- return QScriptValue(request->header(headerName));
+ return engine->toString(r->header(engine->toString(args[0])));
}
-static QScriptValue qmlxmlhttprequest_getAllResponseHeaders(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_getAllResponseHeaders(const v8::Arguments &args)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(args.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ QV8Engine *engine = r->engine;
- if (context->argumentCount() != 0)
- THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
+ if (args.Length() != 0)
+ V8THROW_DOM(SYNTAX_ERR, "Incorrect argument count");
- if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done &&
- request->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done &&
+ r->readyState() != QDeclarativeXMLHttpRequest::HeadersReceived)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
- return QScriptValue(request->headers());
+ return engine->toString(r->headers());
}
// XMLHttpRequest properties
-static QScriptValue qmlxmlhttprequest_readyState(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_readyState(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- return QScriptValue(request->readyState());
+ return v8::Integer::NewFromUnsigned(r->readyState());
}
-static QScriptValue qmlxmlhttprequest_status(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_status(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
- request->readyState() == QDeclarativeXMLHttpRequest::Opened)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ if (r->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
+ r->readyState() == QDeclarativeXMLHttpRequest::Opened)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
- if (request->errorFlag())
- return QScriptValue(0);
+ if (r->errorFlag())
+ return v8::Integer::New(0);
else
- return QScriptValue(request->replyStatus());
+ return v8::Integer::New(r->replyStatus());
}
-static QScriptValue qmlxmlhttprequest_statusText(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_statusText(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (request->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
- request->readyState() == QDeclarativeXMLHttpRequest::Opened)
- THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+ QV8Engine *engine = r->engine;
- if (request->errorFlag())
- return QScriptValue(0);
+ if (r->readyState() == QDeclarativeXMLHttpRequest::Unsent ||
+ r->readyState() == QDeclarativeXMLHttpRequest::Opened)
+ V8THROW_DOM(INVALID_STATE_ERR, "Invalid state");
+
+ if (r->errorFlag())
+ return engine->toString(QString());
else
- return QScriptValue(request->replyStatusText());
+ return engine->toString(r->replyStatusText());
}
-static QScriptValue qmlxmlhttprequest_responseText(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_responseText(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- Q_UNUSED(engine)
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
+
+ QV8Engine *engine = r->engine;
- if (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done)
- return QScriptValue(QString());
+ if (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done)
+ return engine->toString(QString());
else
- return QScriptValue(request->responseBody());
+ return engine->toString(r->responseBody());
}
-static QScriptValue qmlxmlhttprequest_responseXML(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_responseXML(v8::Local<v8::String> property,
+ const v8::AccessorInfo& info)
{
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(context->thisObject().data().toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ QDeclarativeXMLHttpRequest *r = v8_resource_cast<QDeclarativeXMLHttpRequest>(info.This());
+ if (!r)
+ V8THROW_REFERENCE("Not an XMLHttpRequest object");
- if (!request->receivedXml() ||
- (request->readyState() != QDeclarativeXMLHttpRequest::Loading &&
- request->readyState() != QDeclarativeXMLHttpRequest::Done))
- return engine->nullValue();
- else
- return Document::load(engine, request->rawResponseBody());
+ if (!r->receivedXml() ||
+ (r->readyState() != QDeclarativeXMLHttpRequest::Loading &&
+ r->readyState() != QDeclarativeXMLHttpRequest::Done)) {
+ return v8::Null();
+ } else {
+ return Document::load(r->engine, r->rawResponseBody());
+ }
}
-static QScriptValue qmlxmlhttprequest_onreadystatechange(QScriptContext *context, QScriptEngine *engine)
+static v8::Handle<v8::Value> qmlxmlhttprequest_new(const v8::Arguments &args)
{
- Q_UNUSED(engine);
- QScriptValue dataObject = context->thisObject().data();
- QDeclarativeXMLHttpRequest *request = qobject_cast<QDeclarativeXMLHttpRequest *>(dataObject.toQObject());
- if (!request)
- THROW_REFERENCE("Not an XMLHttpRequest object");
+ if (args.IsConstructCall()) {
+ QV8Engine *engine = V8ENGINE();
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+
+ QDeclarativeXMLHttpRequest *r = new QDeclarativeXMLHttpRequest(engine, engine->networkAccessManager());
+ args.This()->SetExternalResource(r);
- if (context->argumentCount()) {
- QScriptValue v = context->argument(0);
- dataObject.setProperty(QLatin1String("callback"), v);
- return v;
+ return args.This();
} else {
- return dataObject.property(QLatin1String("callback"));
+ return v8::Undefined();
}
}
-// Constructor
-static QScriptValue qmlxmlhttprequest_new(QScriptContext *context, QScriptEngine *engine)
+#define NEWFUNCTION(function) v8::FunctionTemplate::New(function)->GetFunction()
+
+void qt_rem_qmlxmlhttprequest(QV8Engine *engine, void *d)
{
- if (context->isCalledAsConstructor()) {
- context->thisObject().setData(engine->newQObject(new QDeclarativeXMLHttpRequest(QDeclarativeScriptEngine::get(engine)->networkAccessManager()), QScriptEngine::ScriptOwnership));
- }
- return engine->undefinedValue();
+ QDeclarativeXMLHttpRequestData *data = (QDeclarativeXMLHttpRequestData *)d;
+ delete data;
}
-void qt_add_qmlxmlhttprequest(QScriptEngine *engine)
+void *qt_add_qmlxmlhttprequest(QV8Engine *engine)
{
- QScriptValue prototype = engine->newObject();
+ v8::PropertyAttribute attributes = (v8::PropertyAttribute)(v8::ReadOnly | v8::DontEnum | v8::DontDelete);
+
+ // XMLHttpRequest
+ v8::Local<v8::FunctionTemplate> xmlhttprequest = v8::FunctionTemplate::New(qmlxmlhttprequest_new,
+ v8::External::Wrap(engine));
+ xmlhttprequest->InstanceTemplate()->SetHasExternalResource(true);
// Methods
- prototype.setProperty(QLatin1String("open"), engine->newFunction(qmlxmlhttprequest_open, 2));
- prototype.setProperty(QLatin1String("setRequestHeader"), engine->newFunction(qmlxmlhttprequest_setRequestHeader, 2));
- prototype.setProperty(QLatin1String("send"), engine->newFunction(qmlxmlhttprequest_send));
- prototype.setProperty(QLatin1String("abort"), engine->newFunction(qmlxmlhttprequest_abort));
- prototype.setProperty(QLatin1String("getResponseHeader"), engine->newFunction(qmlxmlhttprequest_getResponseHeader, 1));
- prototype.setProperty(QLatin1String("getAllResponseHeaders"), engine->newFunction(qmlxmlhttprequest_getAllResponseHeaders));
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("open"), NEWFUNCTION(qmlxmlhttprequest_open), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("setRequestHeader"), NEWFUNCTION(qmlxmlhttprequest_setRequestHeader), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("send"), NEWFUNCTION(qmlxmlhttprequest_send), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("abort"), NEWFUNCTION(qmlxmlhttprequest_abort), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("getResponseHeader"), NEWFUNCTION(qmlxmlhttprequest_getResponseHeader), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("getAllResponseHeaders"), NEWFUNCTION(qmlxmlhttprequest_getAllResponseHeaders), attributes);
// Read-only properties
- prototype.setProperty(QLatin1String("readyState"), engine->newFunction(qmlxmlhttprequest_readyState), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("status"), engine->newFunction(qmlxmlhttprequest_status), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("statusText"), engine->newFunction(qmlxmlhttprequest_statusText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("responseText"), engine->newFunction(qmlxmlhttprequest_responseText), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("responseXML"), engine->newFunction(qmlxmlhttprequest_responseXML), QScriptValue::ReadOnly | QScriptValue::PropertyGetter);
- prototype.setProperty(QLatin1String("onreadystatechange"), engine->newFunction(qmlxmlhttprequest_onreadystatechange), QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("readyState"), qmlxmlhttprequest_readyState, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("status"),qmlxmlhttprequest_status, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("statusText"),qmlxmlhttprequest_statusText, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("responseText"),qmlxmlhttprequest_responseText, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
+ xmlhttprequest->PrototypeTemplate()->SetAccessor(v8::String::New("responseXML"),qmlxmlhttprequest_responseXML, 0, v8::Handle<v8::Value>(), v8::DEFAULT, attributes);
// State values
- prototype.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- prototype.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("UNSENT"), v8::Integer::New(0), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("OPENED"), v8::Integer::New(1), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("HEADERS_RECEIVED"), v8::Integer::New(2), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("LOADING"), v8::Integer::New(3), attributes);
+ xmlhttprequest->PrototypeTemplate()->Set(v8::String::New("DONE"), v8::Integer::New(4), attributes);
// Constructor
- QScriptValue constructor = engine->newFunction(qmlxmlhttprequest_new, prototype);
- constructor.setProperty(QLatin1String("UNSENT"), 0, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("OPENED"), 1, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("HEADERS_RECEIVED"), 2, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("LOADING"), 3, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- constructor.setProperty(QLatin1String("DONE"), 4, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- engine->globalObject().setProperty(QLatin1String("XMLHttpRequest"), constructor);
+ xmlhttprequest->Set(v8::String::New("UNSENT"), v8::Integer::New(0), attributes);
+ xmlhttprequest->Set(v8::String::New("OPENED"), v8::Integer::New(1), attributes);
+ xmlhttprequest->Set(v8::String::New("HEADERS_RECEIVED"), v8::Integer::New(2), attributes);
+ xmlhttprequest->Set(v8::String::New("LOADING"), v8::Integer::New(3), attributes);
+ xmlhttprequest->Set(v8::String::New("DONE"), v8::Integer::New(4), attributes);
+ engine->global()->Set(v8::String::New("XMLHttpRequest"), xmlhttprequest->GetFunction());
// DOM Exception
- QScriptValue domExceptionPrototype = engine->newObject();
- domExceptionPrototype.setProperty(QLatin1String("INDEX_SIZE_ERR"), INDEX_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("DOMSTRING_SIZE_ERR"), DOMSTRING_SIZE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("HIERARCHY_REQUEST_ERR"), HIERARCHY_REQUEST_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("WRONG_DOCUMENT_ERR"), WRONG_DOCUMENT_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_CHARACTER_ERR"), INVALID_CHARACTER_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NO_DATA_ALLOWED_ERR"), NO_DATA_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NO_MODIFICATION_ALLOWED_ERR"), NO_MODIFICATION_ALLOWED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NOT_FOUND_ERR"), NOT_FOUND_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NOT_SUPPORTED_ERR"), NOT_SUPPORTED_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INUSE_ATTRIBUTE_ERR"), INUSE_ATTRIBUTE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_STATE_ERR"), INVALID_STATE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("SYNTAX_ERR"), SYNTAX_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_MODIFICATION_ERR"), INVALID_MODIFICATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("NAMESPACE_ERR"), NAMESPACE_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("INVALID_ACCESS_ERR"), INVALID_ACCESS_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("VALIDATION_ERR"), VALIDATION_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
- domExceptionPrototype.setProperty(QLatin1String("TYPE_MISMATCH_ERR"), TYPE_MISMATCH_ERR, QScriptValue::ReadOnly | QScriptValue::Undeletable | QScriptValue::SkipInEnumeration);
-
- engine->globalObject().setProperty(QLatin1String("DOMException"), domExceptionPrototype);
+ v8::Local<v8::Object> domexception = v8::Object::New();
+ domexception->Set(v8::String::New("INDEX_SIZE_ERR"), v8::Integer::New(INDEX_SIZE_ERR), attributes);
+ domexception->Set(v8::String::New("DOMSTRING_SIZE_ERR"), v8::Integer::New(DOMSTRING_SIZE_ERR), attributes);
+ domexception->Set(v8::String::New("HIERARCHY_REQUEST_ERR"), v8::Integer::New(HIERARCHY_REQUEST_ERR), attributes);
+ domexception->Set(v8::String::New("WRONG_DOCUMENT_ERR"), v8::Integer::New(WRONG_DOCUMENT_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_CHARACTER_ERR"), v8::Integer::New(INVALID_CHARACTER_ERR), attributes);
+ domexception->Set(v8::String::New("NO_DATA_ALLOWED_ERR"), v8::Integer::New(NO_DATA_ALLOWED_ERR), attributes);
+ domexception->Set(v8::String::New("NO_MODIFICATION_ALLOWED_ERR"), v8::Integer::New(NO_MODIFICATION_ALLOWED_ERR), attributes);
+ domexception->Set(v8::String::New("NOT_FOUND_ERR"), v8::Integer::New(NOT_FOUND_ERR), attributes);
+ domexception->Set(v8::String::New("NOT_SUPPORTED_ERR"), v8::Integer::New(NOT_SUPPORTED_ERR), attributes);
+ domexception->Set(v8::String::New("INUSE_ATTRIBUTE_ERR"), v8::Integer::New(INUSE_ATTRIBUTE_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_STATE_ERR"), v8::Integer::New(INVALID_STATE_ERR), attributes);
+ domexception->Set(v8::String::New("SYNTAX_ERR"), v8::Integer::New(SYNTAX_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_MODIFICATION_ERR"), v8::Integer::New(INVALID_MODIFICATION_ERR), attributes);
+ domexception->Set(v8::String::New("NAMESPACE_ERR"), v8::Integer::New(NAMESPACE_ERR), attributes);
+ domexception->Set(v8::String::New("INVALID_ACCESS_ERR"), v8::Integer::New(INVALID_ACCESS_ERR), attributes);
+ domexception->Set(v8::String::New("VALIDATION_ERR"), v8::Integer::New(VALIDATION_ERR), attributes);
+ domexception->Set(v8::String::New("TYPE_MISMATCH_ERR"), v8::Integer::New(TYPE_MISMATCH_ERR), attributes);
+ engine->global()->Set(v8::String::New("DOMException"), domexception);
+
+ QDeclarativeXMLHttpRequestData *data = new QDeclarativeXMLHttpRequestData;
+ return data;
}
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativexmlhttprequest_p.h b/src/declarative/qml/qdeclarativexmlhttprequest_p.h
index 7863035842..ab2d9207e6 100644
--- a/src/declarative/qml/qdeclarativexmlhttprequest_p.h
+++ b/src/declarative/qml/qdeclarativexmlhttprequest_p.h
@@ -60,8 +60,10 @@
QT_BEGIN_NAMESPACE
-class QScriptEngine;
-void qt_add_qmlxmlhttprequest(QScriptEngine *engine);
+class QV8Engine;
+
+void *qt_add_qmlxmlhttprequest(QV8Engine *engine);
+void qt_rem_qmlxmlhttprequest(QV8Engine *engine, void *);
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qintrusivelist_p.h b/src/declarative/qml/qintrusivelist_p.h
index 459d051d07..b2a15a0a52 100644
--- a/src/declarative/qml/qintrusivelist_p.h
+++ b/src/declarative/qml/qintrusivelist_p.h
@@ -65,6 +65,7 @@ public:
inline QIntrusiveList();
inline ~QIntrusiveList();
+ inline bool isEmpty() const;
inline void insert(N *n);
inline void remove(N *n);
@@ -176,6 +177,12 @@ QIntrusiveList<N, member>::~QIntrusiveList()
}
template<class N, QIntrusiveListNode N::*member>
+bool QIntrusiveList<N, member>::isEmpty() const
+{
+ return __first == 0;
+}
+
+template<class N, QIntrusiveListNode N::*member>
void QIntrusiveList<N, member>::insert(N *n)
{
QIntrusiveListNode *nnode = &(n->*member);
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 62c1f97d60..1baa21f3ae 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -9,7 +9,6 @@ SOURCES += \
$$PWD/qdeclarativeproperty.cpp \
$$PWD/qdeclarativecomponent.cpp \
$$PWD/qdeclarativecontext.cpp \
- $$PWD/qdeclarativeinclude.cpp \
$$PWD/qdeclarativecustomparser.cpp \
$$PWD/qdeclarativepropertyvaluesource.cpp \
$$PWD/qdeclarativepropertyvalueinterceptor.cpp \
@@ -41,13 +40,6 @@ SOURCES += \
$$PWD/qdeclarativetypenotavailable.cpp \
$$PWD/qdeclarativetypenamecache.cpp \
$$PWD/qdeclarativescriptstring.cpp \
- $$PWD/qdeclarativeobjectscriptclass.cpp \
- $$PWD/qdeclarativescarceresourcescriptclass.cpp \
- $$PWD/qdeclarativecontextscriptclass.cpp \
- $$PWD/qdeclarativeglobalscriptclass.cpp \
- $$PWD/qdeclarativevaluetypescriptclass.cpp \
- $$PWD/qdeclarativetypenamescriptclass.cpp \
- $$PWD/qdeclarativelistscriptclass.cpp \
$$PWD/qdeclarativeworkerscript.cpp \
$$PWD/qdeclarativeimageprovider.cpp \
$$PWD/qdeclarativenetworkaccessmanagerfactory.cpp \
@@ -90,7 +82,6 @@ HEADERS += \
$$PWD/qdeclarativeinfo.h \
$$PWD/qdeclarativeproperty_p.h \
$$PWD/qdeclarativecontext_p.h \
- $$PWD/qdeclarativeinclude_p.h \
$$PWD/qdeclarativetypeloader_p.h \
$$PWD/qdeclarativelist.h \
$$PWD/qdeclarativelist_p.h \
@@ -114,13 +105,6 @@ HEADERS += \
$$PWD/qdeclarativetypenotavailable_p.h \
$$PWD/qdeclarativetypenamecache_p.h \
$$PWD/qdeclarativescriptstring.h \
- $$PWD/qdeclarativeobjectscriptclass_p.h \
- $$PWD/qdeclarativescarceresourcescriptclass_p.h \
- $$PWD/qdeclarativecontextscriptclass_p.h \
- $$PWD/qdeclarativeglobalscriptclass_p.h \
- $$PWD/qdeclarativevaluetypescriptclass_p.h \
- $$PWD/qdeclarativetypenamescriptclass_p.h \
- $$PWD/qdeclarativelistscriptclass_p.h \
$$PWD/qdeclarativeworkerscript_p.h \
$$PWD/qdeclarativeguard_p.h \
$$PWD/qdeclarativeimageprovider.h \
@@ -136,6 +120,7 @@ QT += sql
include(parser/parser.pri)
include(rewriter/rewriter.pri)
include(v4/v4.pri)
+include(v8/v8.pri)
# mirrors logic in corelib/kernel/kernel.pri
unix:!symbian: contains(QT_CONFIG, clock-gettime):include($$QT_SOURCE_TREE/config.tests/unix/clock-gettime/clock-gettime.pri)
diff --git a/src/declarative/qml/v4/qdeclarativev4bindings.cpp b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
index 5ef293de89..0ee7d4dc7d 100644
--- a/src/declarative/qml/v4/qdeclarativev4bindings.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4bindings.cpp
@@ -1492,7 +1492,8 @@ void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
QString str = QString::fromRawData(strdata, len);
- identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
+ // XXX not applicable in v8
+ // identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
}
QML_V4_END_INSTR(InitString, initstring)
diff --git a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
index 103d5ba0df..928fea4487 100644
--- a/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
+++ b/src/declarative/qml/v4/qdeclarativev4irbuilder.cpp
@@ -41,7 +41,6 @@
#include "qdeclarativev4irbuilder_p.h"
-#include <private/qdeclarativeglobalscriptclass_p.h> // For illegalNames
#include <private/qdeclarativeanchors_p_p.h> // For AnchorLine
#include <private/qsganchors_p_p.h> // For AnchorLine
#include <private/qdeclarativetypenamecache_p.h>
@@ -437,7 +436,7 @@ bool QDeclarativeV4IRBuilder::visit(AST::IdentifierExpression *ast)
if (name.at(0) == QLatin1Char('u') && name.length() == 9 && name == QLatin1String("undefined")) {
_expr.code = _block->CONST(IR::UndefinedType, 0); // ### undefined value
- } else if(m_engine->globalClass->illegalNames().contains(name) ) {
+ } else if(m_engine->v8engine.illegalNames().contains(name) ) {
if (qmlVerboseCompiler()) qWarning() << "*** illegal symbol:" << name;
return false;
} else if (const QDeclarativeParser::Object *obj = m_expression->ids.value(name)) {
diff --git a/src/declarative/qml/v8/notes.txt b/src/declarative/qml/v8/notes.txt
new file mode 100644
index 0000000000..ff5a289b7c
--- /dev/null
+++ b/src/declarative/qml/v8/notes.txt
@@ -0,0 +1,4 @@
+Removed backwards compatible imports - QTBUG-17518
+
+autotest print() taking objects that don't ToString()
+autotest QDeclarativeV8Function
diff --git a/src/declarative/qml/v8/qhashedstring.cpp b/src/declarative/qml/v8/qhashedstring.cpp
new file mode 100644
index 0000000000..4a23e3b7dd
--- /dev/null
+++ b/src/declarative/qml/v8/qhashedstring.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** 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 "qhashedstring_p.h"
+
+inline unsigned stringHash(const QChar* data, unsigned length)
+{
+ return v8::String::ComputeHash((uint16_t *)data, length);
+}
+
+void QHashedString::computeHash() const
+{
+ m_hash = stringHash(constData(), length());
+}
+
+void QHashedStringRef::computeHash() const
+{
+ m_hash = stringHash(m_data, m_length);
+}
+
+/*
+ A QHash has initially around pow(2, MinNumBits) buckets. For
+ example, if MinNumBits is 4, it has 17 buckets.
+*/
+const int MinNumBits = 4;
+
+/*
+ The prime_deltas array is a table of selected prime values, even
+ though it doesn't look like one. The primes we are using are 1,
+ 2, 5, 11, 17, 37, 67, 131, 257, ..., i.e. primes in the immediate
+ surrounding of a power of two.
+
+ The primeForNumBits() function returns the prime associated to a
+ power of two. For example, primeForNumBits(8) returns 257.
+*/
+
+static const uchar prime_deltas[] = {
+ 0, 0, 1, 3, 1, 5, 3, 3, 1, 9, 7, 5, 3, 9, 25, 3,
+ 1, 21, 3, 21, 7, 15, 9, 5, 3, 29, 15, 0, 0, 0, 0, 0
+};
+
+static inline int primeForNumBits(int numBits)
+{
+ return (1 << numBits) + prime_deltas[numBits];
+}
+
+void QStringHashData::rehash()
+{
+ numBits = qMax(MinNumBits, numBits + 1);
+ numBuckets = primeForNumBits(numBits);
+
+ delete [] buckets;
+ buckets = new QStringHashNode *[numBuckets];
+ ::memset(buckets, 0, sizeof(QStringHashNode *) * numBuckets);
+
+ QStringHashNode *nodeList = nodes;
+ while (nodeList) {
+ int bucket = nodeList->key.hash() % numBuckets;
+ nodeList->next = buckets[bucket];
+ buckets[bucket] = nodeList;
+
+ nodeList = nodeList->nlist;
+ }
+}
+
diff --git a/src/declarative/qml/v8/qhashedstring_p.h b/src/declarative/qml/v8/qhashedstring_p.h
new file mode 100644
index 0000000000..acee03a9b5
--- /dev/null
+++ b/src/declarative/qml/v8/qhashedstring_p.h
@@ -0,0 +1,572 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QHASHEDSTRING_P_H
+#define QHASHEDSTRING_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qstring.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHashedStringRef;
+class QHashedString : public QString
+{
+public:
+ inline QHashedString();
+ inline QHashedString(const QString &string);
+ inline QHashedString(const QString &string, quint32);
+ inline QHashedString(const QHashedString &string);
+
+ inline QHashedString &operator=(const QHashedString &string);
+ inline bool operator==(const QHashedString &string) const;
+ inline bool operator==(const QHashedStringRef &string) const;
+
+ inline quint32 hash() const;
+ inline quint32 existingHash() const;
+
+ static inline bool isUpper(const QChar &);
+private:
+ friend class QHashedStringRef;
+
+ void computeHash() const;
+ mutable quint32 m_hash;
+};
+
+class QHashedStringRef
+{
+public:
+ inline QHashedStringRef();
+ inline QHashedStringRef(const QString &);
+ inline QHashedStringRef(const QChar *, int);
+ inline QHashedStringRef(const QChar *, int, quint32);
+ inline QHashedStringRef(const QHashedString &);
+ inline QHashedStringRef(const QHashedStringRef &);
+
+ inline bool operator==(const QHashedString &string) const;
+ inline bool operator==(const QHashedStringRef &string) const;
+
+ inline quint32 hash() const;
+
+ inline const QChar *constData() const;
+ inline quint32 length() const;
+ inline bool startsWithUpper() const;
+
+private:
+ friend class QHashedString;
+
+ void computeHash() const;
+
+ const QChar *m_data;
+ quint32 m_length;
+ mutable quint32 m_hash;
+};
+
+class QStringHashData;
+class QStringHashNode
+{
+public:
+ QStringHashNode(const QHashedString &key)
+ : nlist(0), next(0), key(key) {}
+
+ QStringHashNode *nlist;
+ QStringHashNode *next;
+ QHashedString key;
+};
+
+struct QStringHashData
+{
+public:
+ QStringHashData()
+ : nodes(0), buckets(0), numBuckets(0), size(0), numBits(0) {}
+
+ QStringHashNode *nodes;
+ QStringHashNode **buckets;
+ int numBuckets;
+ int size;
+ short numBits;
+
+ void rehash();
+};
+
+template<class T>
+class QStringHash
+{
+private:
+ struct Node : public QStringHashNode {
+ Node(const QHashedString &key, const T &value) : QStringHashNode(key), value(value) {}
+ T value;
+ };
+
+ QStringHashData data;
+
+ inline Node *findNode(const QHashedStringRef &) const;
+ inline Node *findNode(v8::Handle<v8::String> &, quint32) const;
+ Node *createNode(const QHashedString &, const T &);
+
+public:
+ inline QStringHash();
+ inline QStringHash(const QStringHash &);
+ inline ~QStringHash();
+
+ QStringHash &operator=(const QStringHash<T> &);
+
+ inline bool isEmpty() const;
+ inline void clear();
+ inline int count() const;
+
+ inline void insert(const QString &, const T &);
+ inline void insert(const QHashedString &, const T &);
+ inline void insert(const QHashedStringRef &, const T &);
+
+ inline T *value(const QString &) const;
+ inline T *value(const QHashedString &) const;
+ inline T *value(const QHashedStringRef &) const;
+ inline T *value(v8::Handle<v8::String> &) const;
+ inline T *value(v8::Handle<v8::String> &, quint32 hash) const;
+
+ inline bool contains(const QString &) const;
+ inline bool contains(const QHashedString &) const;
+ inline bool contains(const QHashedStringRef &) const;
+
+ T &operator[](const QString &);
+ T &operator[](const QHashedString &);
+ T &operator[](const QHashedStringRef &);
+
+ class ConstIterator {
+ public:
+ ConstIterator() : n(0) {}
+ ConstIterator(Node *n) : n(n) {}
+
+ ConstIterator &operator++() { n = (Node *)n->nlist; return *this; }
+ bool operator==(const ConstIterator &o) const { return n == o.n; }
+ bool operator!=(const ConstIterator &o) const { return n != o.n; }
+
+ const QHashedString &key() const { return n->key; }
+ const T &value() const { return n->value; }
+ const T &operator*() const { return n->value; }
+ private:
+ Node *n;
+ };
+
+ ConstIterator begin() const { return ConstIterator((Node *)data.nodes); }
+ ConstIterator end() const { return ConstIterator(); }
+};
+
+template<class T>
+QStringHash<T>::QStringHash()
+{
+}
+
+template<class T>
+QStringHash<T>::QStringHash(const QStringHash<T> &other)
+: data(other.data)
+{
+ data.nodes = 0;
+ data.buckets = 0;
+
+ QStringHashNode *n = other.data.nodes;
+ while (n) {
+ Node *o = (Node *)n;
+ Node *mynode = new Node(o->key, o->value);
+ mynode->nlist = data.nodes;
+ data.nodes = mynode;
+ n = o->nlist;
+ }
+
+ data.rehash();
+}
+
+template<class T>
+QStringHash<T> &QStringHash<T>::operator=(const QStringHash<T> &other)
+{
+ if (&other == this)
+ return *this;
+
+ clear();
+ data = other.data;
+ data.nodes = 0;
+ data.buckets = 0;
+
+ QStringHashNode *n = other.data.nodes;
+ while (n) {
+ Node *o = (Node *)n;
+ Node *mynode = new Node(o->key, o->value);
+ mynode->nlist = data.nodes;
+ data.nodes = mynode;
+ n = o->nlist;
+ }
+
+ data.rehash();
+
+ return *this;
+}
+
+template<class T>
+QStringHash<T>::~QStringHash()
+{
+ clear();
+}
+
+template<class T>
+void QStringHash<T>::clear()
+{
+ QStringHashNode *n = data.nodes;
+ while (n) {
+ Node *o = (Node *)n;
+ n = n->nlist;
+ delete o;
+ }
+
+ delete [] data.buckets;
+
+ data = QStringHashData();
+}
+
+template<class T>
+bool QStringHash<T>::isEmpty() const
+{
+ return data.nodes == 0;
+}
+
+template<class T>
+int QStringHash<T>::count() const
+{
+ return data.size;
+}
+
+template<class T>
+typename QStringHash<T>::Node *QStringHash<T>::createNode(const QHashedString &key, const T &value)
+{
+ if (data.size == data.numBuckets)
+ data.rehash();
+
+ Node *n = new Node(key, value);
+ n->nlist = data.nodes;
+ data.nodes = n;
+
+ int bucket = key.hash() % data.numBuckets;
+ n->next = data.buckets[bucket];
+ data.buckets[bucket] = n;
+
+ data.size++;
+
+ return n;
+}
+
+template<class T>
+void QStringHash<T>::insert(const QString &key, const T &value)
+{
+ QHashedStringRef ch(key);
+ Node *n = findNode(key);
+ if (n) n->value = value;
+ else createNode(QHashedString(key, ch.hash()), value);
+}
+
+template<class T>
+void QStringHash<T>::insert(const QHashedString &key, const T &value)
+{
+ Node *n = findNode(key);
+ if (n) n->value = value;
+ else createNode(key, value);
+}
+
+template<class T>
+void QStringHash<T>::insert(const QHashedStringRef &key, const T &value)
+{
+ Node *n = findNode(key);
+ if (n) n->value = value;
+ else createNode(key, value);
+}
+
+template<class T>
+typename QStringHash<T>::Node *QStringHash<T>::findNode(const QHashedStringRef &string) const
+{
+ QStringHashNode *node = 0;
+ if (data.numBuckets) {
+ node = data.buckets[string.hash() % data.numBuckets];
+ while (node && !(node->key == string))
+ node = node->next;
+ }
+
+ return (Node *)node;
+}
+
+template<class T>
+typename QStringHash<T>::Node *QStringHash<T>::findNode(v8::Handle<v8::String> &string, quint32 hash) const
+{
+ QStringHashNode *node = 0;
+ if (data.numBuckets) {
+ node = data.buckets[hash % data.numBuckets];
+ int length = string->Length();
+ while (node && (length != node->key.length() || !string->Equals((uint16_t*)node->key.constData(), length)))
+ node = node->next;
+ }
+
+ return (Node *)node;
+}
+
+template<class T>
+T *QStringHash<T>::value(const QString &key) const
+{
+ Node *n = findNode(key);
+ return n?&n->value:0;
+}
+
+template<class T>
+T *QStringHash<T>::value(const QHashedString &key) const
+{
+ Node *n = findNode(key);
+ return n?&n->value:0;
+}
+
+template<class T>
+T *QStringHash<T>::value(const QHashedStringRef &key) const
+{
+ Node *n = findNode(key);
+ return n?&n->value:0;
+}
+
+template<class T>
+T *QStringHash<T>::value(v8::Handle<v8::String> &key) const
+{
+ return value(key, (quint32)key->Hash());
+}
+
+template<class T>
+T *QStringHash<T>::value(v8::Handle<v8::String> &key, quint32 hash) const
+{
+ Node *n = findNode(key, hash);
+ return n?&n->value:0;
+}
+
+template<class T>
+bool QStringHash<T>::contains(const QString &s) const
+{
+ return 0 != value(s);
+}
+
+template<class T>
+bool QStringHash<T>::contains(const QHashedString &s) const
+{
+ return 0 != value(s);
+}
+template<class T>
+bool QStringHash<T>::contains(const QHashedStringRef &s) const
+{
+ return 0 != value(s);
+}
+
+template<class T>
+T &QStringHash<T>::operator[](const QString &key)
+{
+ QHashedStringRef cs(key);
+ Node *n = findNode(cs);
+ if (n) return n->value;
+ else return createNode(QHashedString(key, cs.hash()), T())->value;
+}
+
+template<class T>
+T &QStringHash<T>::operator[](const QHashedString &key)
+{
+ Node *n = findNode(key);
+ if (n) return n->value;
+ else return createNode(key)->value;
+}
+
+template<class T>
+T &QStringHash<T>::operator[](const QHashedStringRef &key)
+{
+ Node *n = findNode(key);
+ if (n) return n->value;
+ else return createNode(key)->value;
+}
+
+inline uint qHash(const QHashedString &string)
+{
+ return uint(string.hash());
+}
+
+inline uint qHash(const QHashedStringRef &string)
+{
+ return uint(string.hash());
+}
+
+QHashedString::QHashedString()
+: QString(), m_hash(0)
+{
+}
+
+QHashedString::QHashedString(const QString &string)
+: QString(string), m_hash(0)
+{
+}
+
+QHashedString::QHashedString(const QString &string, quint32 hash)
+: QString(string), m_hash(hash)
+{
+}
+
+QHashedString::QHashedString(const QHashedString &string)
+: QString(string), m_hash(string.m_hash)
+{
+}
+
+QHashedString &QHashedString::operator=(const QHashedString &string)
+{
+ static_cast<QString &>(*this) = string;
+ m_hash = string.m_hash;
+ return *this;
+}
+
+bool QHashedString::operator==(const QHashedString &string) const
+{
+ return (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
+ static_cast<const QString &>(*this) == static_cast<const QString &>(string);
+}
+
+bool QHashedString::operator==(const QHashedStringRef &string) const
+{
+ return (uint)length() == string.m_length &&
+ (string.m_hash == m_hash || !string.m_hash || !m_hash) &&
+ 0 == ::memcmp(constData(), string.m_data, string.m_length * sizeof(QChar));
+}
+
+quint32 QHashedString::hash() const
+{
+ if (!m_hash) computeHash();
+ return m_hash;
+}
+
+quint32 QHashedString::existingHash() const
+{
+ return m_hash;
+}
+
+bool QHashedString::isUpper(const QChar &qc)
+{
+ ushort c = qc.unicode();
+ // Optimize for _, a-z and A-Z.
+ return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) &&
+ ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
+}
+
+QHashedStringRef::QHashedStringRef()
+: m_data(0), m_length(0), m_hash(0)
+{
+}
+
+QHashedStringRef::QHashedStringRef(const QString &str)
+: m_data(str.constData()), m_length(str.length()), m_hash(0)
+{
+}
+
+QHashedStringRef::QHashedStringRef(const QChar *data, int length)
+: m_data(data), m_length(length), m_hash(0)
+{
+}
+
+QHashedStringRef::QHashedStringRef(const QChar *data, int length, quint32 hash)
+: m_data(data), m_length(length), m_hash(hash)
+{
+}
+
+QHashedStringRef::QHashedStringRef(const QHashedString &string)
+: m_data(string.constData()), m_length(string.length()), m_hash(string.m_hash)
+{
+}
+
+QHashedStringRef::QHashedStringRef(const QHashedStringRef &string)
+: m_data(string.m_data), m_length(string.m_length), m_hash(string.m_hash)
+{
+}
+
+bool QHashedStringRef::operator==(const QHashedString &string) const
+{
+ return m_length == (uint)string.length() &&
+ (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
+ 0 == ::memcmp(string.constData(), m_data, m_length * sizeof(QChar));
+}
+
+bool QHashedStringRef::operator==(const QHashedStringRef &string) const
+{
+ return m_length == string.m_length &&
+ (m_hash == string.m_hash || !m_hash || !string.m_hash) &&
+ 0 == ::memcmp(string.m_data, m_data, m_length * sizeof(QChar));
+}
+
+const QChar *QHashedStringRef::constData() const
+{
+ return m_data;
+}
+
+quint32 QHashedStringRef::length() const
+{
+ return m_length;
+}
+
+bool QHashedStringRef::startsWithUpper() const
+{
+ if (m_length < 1) return false;
+ return QHashedString::isUpper(m_data[0]);
+}
+
+quint32 QHashedStringRef::hash() const
+{
+ if (!m_hash) computeHash();
+ return m_hash;
+}
+
+QT_END_NAMESPACE
+
+#endif // QHASHEDSTRING_P_H
diff --git a/src/declarative/qml/v8/qv8_p.h b/src/declarative/qml/v8/qv8_p.h
new file mode 100644
index 0000000000..6aeb6f6458
--- /dev/null
+++ b/src/declarative/qml/v8/qv8_p.h
@@ -0,0 +1 @@
+#include "../../../3rdparty/v8/include/v8.h"
diff --git a/src/declarative/qml/v8/qv8contextwrapper.cpp b/src/declarative/qml/v8/qv8contextwrapper.cpp
new file mode 100644
index 0000000000..1af4b4c883
--- /dev/null
+++ b/src/declarative/qml/v8/qv8contextwrapper.cpp
@@ -0,0 +1,425 @@
+/****************************************************************************
+**
+** 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 "qv8contextwrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativecontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+static QString internal(QLatin1String("You've stumbled onto an internal implementation detail "
+ "that should never have been exposed."));
+
+class QV8ContextResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(ContextType);
+
+public:
+ QV8ContextResource(QV8Engine *engine, QDeclarativeContextData *context, QObject *scopeObject);
+ ~QV8ContextResource();
+
+ inline QDeclarativeContextData *getContext() const;
+
+ QDeclarativeGuard<QObject> scopeObject;
+
+ quint32 hasSubContexts:1;
+ quint32 ownsContext:1;
+ quint32 readOnly:1;
+ quint32 dummy:29;
+
+ QObject *secondaryScope;
+
+ // XXX aakenned - this is somewhat of a horrible abuse of external strings :)
+ struct SubContext : public v8::String::ExternalStringResource {
+ SubContext(QDeclarativeContextData *context) : context(context) {}
+ QDeclarativeGuardedContextData context;
+
+ virtual const uint16_t* data() const { return (const uint16_t *)internal.constData(); }
+ virtual size_t length() const { return internal.length(); }
+ };
+
+private:
+ QDeclarativeGuardedContextData context;
+};
+
+QV8ContextResource::QV8ContextResource(QV8Engine *engine, QDeclarativeContextData *context, QObject *scopeObject)
+: QV8ObjectResource(engine), scopeObject(scopeObject), hasSubContexts(false), ownsContext(false),
+ readOnly(true), secondaryScope(0), context(context)
+{
+}
+
+QV8ContextResource::~QV8ContextResource()
+{
+ if (ownsContext && context)
+ context->destroy();
+}
+
+// Returns the context, including resolving a subcontext
+QDeclarativeContextData *QV8ContextResource::getContext() const
+{
+ if (!hasSubContexts)
+ return context;
+
+ v8::Local<v8::Value> callingdata = v8::Context::GetCallingScriptData();
+ if (callingdata.IsEmpty() || !callingdata->IsString())
+ return context;
+
+ v8::Local<v8::String> callingstring = callingdata->ToString();
+ Q_ASSERT(callingstring->IsExternal());
+ Q_ASSERT(callingstring->GetExternalStringResource());
+
+ SubContext *sc = static_cast<SubContext *>(callingstring->GetExternalStringResource());
+ return sc->context;
+}
+
+QV8ContextWrapper::QV8ContextWrapper()
+: m_engine(0)
+{
+}
+
+QV8ContextWrapper::~QV8ContextWrapper()
+{
+}
+
+void QV8ContextWrapper::destroy()
+{
+ m_urlConstructor.Dispose(); m_urlConstructor.Clear();
+ m_constructor.Dispose(); m_constructor.Clear();
+}
+
+void QV8ContextWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(NullGetter, NullSetter);
+ m_urlConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+}
+
+v8::Local<v8::Object> QV8ContextWrapper::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ContextResource *r = new QV8ContextResource(m_engine, ctxt, scope);
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Local<v8::Object> QV8ContextWrapper::urlScope(const QUrl &url)
+{
+ QDeclarativeContextData *context = new QDeclarativeContextData;
+ context->url = url;
+ context->isInternal = true;
+ context->isJSContext = true;
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_urlConstructor->NewInstance();
+ QV8ContextResource *r = new QV8ContextResource(m_engine, context, 0);
+ r->ownsContext = true;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+void QV8ContextWrapper::setReadOnly(v8::Handle<v8::Object> qmlglobal, bool readOnly)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ Q_ASSERT(resource);
+ resource->readOnly = readOnly;
+}
+
+void QV8ContextWrapper::addSubContext(v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Script> script,
+ QDeclarativeContextData *ctxt)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ Q_ASSERT(resource);
+ resource->hasSubContexts = true;
+ script->SetData(v8::String::NewExternal(new QV8ContextResource::SubContext(ctxt)));
+}
+
+QObject *QV8ContextWrapper::setSecondaryScope(v8::Handle<v8::Object> ctxt, QObject *scope)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(ctxt);
+ if (!resource) return 0;
+
+ QObject *rv = resource->secondaryScope;
+ resource->secondaryScope = scope;
+ return rv;
+}
+
+QDeclarativeContextData *QV8ContextWrapper::callingContext()
+{
+ v8::Local<v8::Object> qmlglobal = v8::Context::GetCallingQmlGlobal();
+ if (qmlglobal.IsEmpty()) return 0;
+
+ QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ return r?r->getContext():0;
+}
+
+QDeclarativeContextData *QV8ContextWrapper::context(v8::Handle<v8::Value> value)
+{
+ if (!value->IsObject())
+ return 0;
+
+ v8::Handle<v8::Object> qmlglobal = v8::Handle<v8::Object>::Cast(value);
+ QV8ContextResource *r = v8_resource_cast<QV8ContextResource>(qmlglobal);
+ return r?r->getContext():0;
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::NullGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ QV8Engine *engine = resource->engine;
+
+ QString error = QLatin1String("Can't find variable: ") + engine->toString(property);
+ v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // XXX aakenned too agressive
+ QDeclarativeContextData *context = resource->getContext();
+
+ if (!context)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // Search type (attached property/enum/imported scripts) names
+ // Secondary scope object
+ // while (context) {
+ // Search context properties
+ // Search scope object
+ // Search context object
+ // context = context->parent
+ // }
+
+ QV8Engine *engine = resource->engine;
+ QObject *scopeObject = resource->scopeObject;
+
+ if (context->imports && QV8Engine::startsWithUpper(property)) {
+ // Search for attached properties, enums and imported scripts
+ QDeclarativeTypeNameCache::Data *data = context->imports->data(property);
+
+ if (data) {
+ if (data->importedScriptIndex != -1) {
+ int index = data->importedScriptIndex;
+ if (index < context->importedScripts.count())
+ return context->importedScripts.at(index);
+ else
+ return v8::Undefined();
+ } else if (data->type) {
+ return engine->typeWrapper()->newObject(scopeObject, data->type);
+ } else if (data->typeNamespace) {
+ return engine->typeWrapper()->newObject(scopeObject, data->typeNamespace);
+ }
+ Q_ASSERT(!"Unreachable");
+ }
+
+ // Fall through
+ }
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+
+ if (resource->secondaryScope) {
+ v8::Handle<v8::Value> result = qobjectWrapper->getProperty(resource->secondaryScope, property,
+ QV8QObjectWrapper::IgnoreRevision);
+ if (!result.IsEmpty()) return result;
+ }
+
+ while (context) {
+ // Search context properties
+ if (context->propertyNames) {
+ int propertyIdx = context->propertyNames->value(property);
+
+ if (propertyIdx != -1) {
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
+
+ if (propertyIdx < context->idValueCount) {
+
+ if (ep->captureProperties)
+ ep->capturedProperties << CapturedProperty(&context->idValues[propertyIdx].bindings);
+
+ return engine->newQObject(context->idValues[propertyIdx]);
+ } else {
+
+ QDeclarativeContextPrivate *cp = context->asQDeclarativeContextPrivate();
+
+ if (ep->captureProperties)
+ ep->capturedProperties << CapturedProperty(context->asQDeclarativeContext(), -1,
+ propertyIdx + cp->notifyIndex);
+
+ const QVariant &value = cp->propertyValues.at(propertyIdx);
+ if (value.userType() == qMetaTypeId<QList<QObject*> >()) {
+ QDeclarativeListProperty<QObject> prop(context->asQDeclarativeContext(), (void*)propertyIdx,
+ 0,
+ QDeclarativeContextPrivate::context_count,
+ QDeclarativeContextPrivate::context_at);
+ return engine->listWrapper()->newList(prop, qMetaTypeId<QDeclarativeListProperty<QObject> >());
+ } else {
+ return engine->fromVariant(cp->propertyValues.at(propertyIdx));
+ }
+ }
+ }
+ }
+
+ // Search scope object
+ if (scopeObject) {
+ v8::Handle<v8::Value> result = qobjectWrapper->getProperty(scopeObject, property,
+ QV8QObjectWrapper::CheckRevision);
+ if (!result.IsEmpty()) return result;
+ }
+ scopeObject = 0;
+
+
+ // Search context object
+ if (context->contextObject) {
+ v8::Handle<v8::Value> result = qobjectWrapper->getProperty(context->contextObject, property,
+ QV8QObjectWrapper::CheckRevision);
+ if (!result.IsEmpty()) return result;
+ }
+
+ context = context->parent;
+ }
+
+ QString error = QLatin1String("Can't find variable: ") + engine->toString(property);
+ v8::ThrowException(v8::Exception::ReferenceError(engine->toString(error)));
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::NullSetter(v8::Local<v8::String> property,
+ v8::Local<v8::Value>,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ QV8Engine *engine = resource->engine;
+
+ if (!resource->readOnly) {
+ return v8::Handle<v8::Value>();
+ } else {
+ QString error = QLatin1String("Invalid write to global property \"") + engine->toString(property) +
+ QLatin1String("\"");
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Undefined();
+ }
+}
+
+v8::Handle<v8::Value> QV8ContextWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ QV8ContextResource *resource = v8_resource_cast<QV8ContextResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // XXX aakenned too agressive
+ QDeclarativeContextData *context = resource->getContext();
+
+ if (!context)
+ return v8::Undefined(); // XXX Should we throw here?
+
+ // See QV8ContextWrapper::Getter for resolution order
+
+ QV8Engine *engine = resource->engine;
+ QObject *scopeObject = resource->scopeObject;
+
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+
+ // Search scope object
+ if (resource->secondaryScope && qobjectWrapper->setProperty(resource->secondaryScope, property, value,
+ QV8QObjectWrapper::IgnoreRevision))
+ return value;
+
+ while (context) {
+ // Search context properties
+ if (context->propertyNames && -1 != context->propertyNames->value(property))
+ return value;
+
+ // Search scope object
+ if (scopeObject &&
+ qobjectWrapper->setProperty(scopeObject, property, value, QV8QObjectWrapper::CheckRevision))
+ return value;
+ scopeObject = 0;
+
+ // Search context object
+ if (context->contextObject &&
+ qobjectWrapper->setProperty(context->contextObject, property, value, QV8QObjectWrapper::CheckRevision))
+ return value;
+
+ context = context->parent;
+ }
+
+ if (!resource->readOnly) {
+ return v8::Handle<v8::Value>();
+ } else {
+ QString error = QLatin1String("Invalid write to global property \"") + engine->toString(property) +
+ QLatin1String("\"");
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Undefined();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativecontextscriptclass_p.h b/src/declarative/qml/v8/qv8contextwrapper_p.h
index 26d82724f3..cc0705995b 100644
--- a/src/declarative/qml/qdeclarativecontextscriptclass_p.h
+++ b/src/declarative/qml/v8/qv8contextwrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVECONTEXTSCRIPTCLASS_P_H
-#define QDECLARATIVECONTEXTSCRIPTCLASS_P_H
+#ifndef QV8CONTEXTWRAPPER_P_H
+#define QV8CONTEXTWRAPPER_P_H
//
// W A R N I N G
@@ -53,54 +53,55 @@
// We mean it.
//
-#include "private/qdeclarativetypenamecache_p.h"
-#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qglobal.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
-class QDeclarativeContext;
+class QUrl;
+class QObject;
+class QV8Engine;
class QDeclarativeContextData;
-class QDeclarativeContextScriptClass : public QScriptDeclarativeClass
+class QV8ContextWrapper
{
public:
- QDeclarativeContextScriptClass(QDeclarativeEngine *);
- ~QDeclarativeContextScriptClass();
+ QV8ContextWrapper();
+ ~QV8ContextWrapper();
- QScriptValue newContext(QDeclarativeContextData *, QObject * = 0);
- QScriptValue newUrlContext(QDeclarativeContextData *, QObject *, const QString &);
- QScriptValue newUrlContext(const QString &);
- QScriptValue newSharedContext();
+ void init(QV8Engine *);
+ void destroy();
- QDeclarativeContextData *contextFromValue(const QScriptValue &);
- QUrl urlFromValue(const QScriptValue &);
+ v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
+ v8::Local<v8::Object> urlScope(const QUrl &);
- QObject *setOverrideObject(QScriptValue &, QObject *);
+ void setReadOnly(v8::Handle<v8::Object>, bool);
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ void addSubContext(v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Script>,
+ QDeclarativeContextData *ctxt);
-private:
- QScriptClass::QueryFlags queryProperty(QDeclarativeContextData *, QObject *scopeObject,
- const Identifier &,
- QScriptClass::QueryFlags flags,
- bool includeTypes);
-
- QDeclarativeEngine *engine;
+ // XXX aakenned - remove this abomination
+ QObject *setSecondaryScope(v8::Handle<v8::Object>, QObject *);
- QObject *lastScopeObject;
- QDeclarativeContextData *lastContext;
- QDeclarativeTypeNameCache::Data *lastData;
- int lastPropertyIndex;
- QScriptValue lastFunction;
-
- uint m_id;
+ QDeclarativeContextData *callingContext();
+ QDeclarativeContextData *context(v8::Handle<v8::Value>);
+private:
+ static v8::Handle<v8::Value> NullGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> NullSetter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_urlConstructor;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVECONTEXTSCRIPTCLASS_P_H
+#endif // QV8CONTEXTWRAPPER_P_H
diff --git a/src/declarative/qml/v8/qv8engine.cpp b/src/declarative/qml/v8/qv8engine.cpp
new file mode 100644
index 0000000000..ced07e142f
--- /dev/null
+++ b/src/declarative/qml/v8/qv8engine.cpp
@@ -0,0 +1,1423 @@
+/****************************************************************************
+**
+** 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 "qv8engine_p.h"
+
+#include "qv8contextwrapper_p.h"
+#include "qv8include_p.h"
+#include "../../../3rdparty/javascriptcore/DateMath.h"
+
+#include <private/qdeclarativelist_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativecomponent_p.h>
+#include <private/qdeclarativestringconverters_p.h>
+
+#include <QtDeclarative/qdeclarativecomponent.h>
+
+#include <QtCore/qstring.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qcryptographichash.h>
+#include <QtCore/qnumeric.h>
+#include <QtGui/qdesktopservices.h>
+#include <QtGui/qfontdatabase.h>
+#include <private/qdeclarativeapplication_p.h>
+#include <private/qdeclarativexmlhttprequest_p.h>
+#include <private/qdeclarativesqldatabase_p.h>
+
+// XXX Need to check all the global functions will also work in a worker script where the QDeclarativeEngine
+// is not available
+QT_BEGIN_NAMESPACE
+
+QV8Engine::QV8Engine()
+: m_xmlHttpRequestData(0), m_sqlDatabaseData(0)
+{
+}
+
+QV8Engine::~QV8Engine()
+{
+ qt_rem_qmlsqldatabase(this, m_sqlDatabaseData);
+ m_sqlDatabaseData = 0;
+ qt_rem_qmlxmlhttprequest(this, m_xmlHttpRequestData);
+ m_xmlHttpRequestData = 0;
+
+ m_getOwnPropertyNames.Dispose(); m_getOwnPropertyNames.Clear();
+
+ m_valueTypeWrapper.destroy();
+ m_variantWrapper.destroy();
+ m_listWrapper.destroy();
+ m_typeWrapper.destroy();
+ m_qobjectWrapper.destroy();
+ m_contextWrapper.destroy();
+ m_stringWrapper.destroy();
+ m_context.Dispose();
+}
+
+void QV8Engine::init(QDeclarativeEngine *engine)
+{
+ m_engine = engine;
+
+ QByteArray v8args = qgetenv("V8ARGS");
+ if (!v8args.isEmpty())
+ v8::V8::SetFlagsFromString(v8args.constData(), v8args.length());
+
+ v8::HandleScope handle_scope;
+ m_context = v8::Context::New();
+ v8::Context::Scope context_scope(m_context);
+
+ m_stringWrapper.init();
+ m_contextWrapper.init(this);
+ m_qobjectWrapper.init(this);
+ m_typeWrapper.init(this);
+ m_listWrapper.init(this);
+ m_variantWrapper.init(this);
+ m_valueTypeWrapper.init(this);
+
+ {
+ v8::Handle<v8::Value> v = global()->Get(v8::String::New("Object"))->ToObject()->Get(v8::String::New("getOwnPropertyNames"));
+ m_getOwnPropertyNames = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(v));
+ }
+
+ initializeGlobal(m_context->Global());
+ freezeGlobal();
+}
+
+QString QV8Engine::toStringStatic(v8::Handle<v8::Value> jsstr)
+{
+ return toStringStatic(jsstr->ToString());
+}
+
+QString QV8Engine::toStringStatic(v8::Handle<v8::String> jsstr)
+{
+ QString qstr;
+ qstr.resize(jsstr->Length());
+ jsstr->Write((uint16_t*)qstr.data());
+ return qstr;
+}
+
+QVariant QV8Engine::toVariant(v8::Handle<v8::Value> value, int typeHint)
+{
+ if (value.IsEmpty())
+ return QVariant();
+
+ if (value->IsObject()) {
+ QV8ObjectResource *r = (QV8ObjectResource *)value->ToObject()->GetExternalResource();
+ if (r) {
+ switch (r->resourceType()) {
+ case QV8ObjectResource::ContextType:
+ case QV8ObjectResource::TypeType:
+ case QV8ObjectResource::XMLHttpRequestType:
+ case QV8ObjectResource::DOMNodeType:
+ case QV8ObjectResource::SQLDatabaseType:
+ return QVariant();
+ case QV8ObjectResource::QObjectType:
+ return qVariantFromValue<QObject *>(m_qobjectWrapper.toQObject(r));
+ case QV8ObjectResource::ListType:
+ return m_listWrapper.toVariant(r);
+ case QV8ObjectResource::VariantType:
+ return m_variantWrapper.toVariant(r);
+ case QV8ObjectResource::ValueTypeType:
+ return m_valueTypeWrapper.toVariant(r);
+ }
+ }
+ }
+
+ if (typeHint == qMetaTypeId<QList<QObject *> >() && value->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+
+ QList<QObject *> list;
+ uint32_t length = array->Length();
+ for (uint32_t ii = 0; ii < length; ++ii) {
+ v8::Local<v8::Value> arrayItem = array->Get(ii);
+ if (arrayItem->IsObject()) {
+ list << toQObject(arrayItem->ToObject());
+ } else {
+ list << 0;
+ }
+ }
+
+ return qVariantFromValue<QList<QObject*> >(list);
+ }
+
+ return toBasicVariant(value);
+}
+
+static v8::Handle<v8::Array> arrayFromStringList(QV8Engine *engine, const QStringList &list)
+{
+ v8::Context::Scope scope(engine->context());
+ v8::Local<v8::Array> result = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ result->Set(ii, engine->toString(list.at(ii)));
+ return result;
+}
+
+static v8::Handle<v8::Array> arrayFromVariantList(QV8Engine *engine, const QVariantList &list)
+{
+ v8::Context::Scope scope(engine->context());
+ v8::Local<v8::Array> result = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ result->Set(ii, engine->fromVariant(list.at(ii)));
+ return result;
+}
+
+static v8::Handle<v8::Object> objectFromVariantMap(QV8Engine *engine, const QVariantMap &map)
+{
+ v8::Context::Scope scope(engine->context());
+ v8::Local<v8::Object> object = v8::Object::New();
+ for (QVariantMap::ConstIterator iter = map.begin(); iter != map.end(); ++iter)
+ object->Set(engine->toString(iter.key()), engine->fromVariant(iter.value()));
+ return object;
+}
+
+Q_CORE_EXPORT QString qt_regexp_toCanonical(const QString &, QRegExp::PatternSyntax);
+
+// Converts a QRegExp to a JS RegExp.
+// The conversion is not 100% exact since ECMA regexp and QRegExp
+// have different semantics/flags, but we try to do our best.
+static v8::Handle<v8::RegExp> regexpFromQRegExp(QV8Engine *engine, const QRegExp &re)
+{
+ // Convert the pattern to a ECMAScript pattern.
+ QString pattern = qt_regexp_toCanonical(re.pattern(), re.patternSyntax());
+ if (re.isMinimal()) {
+ QString ecmaPattern;
+ int len = pattern.length();
+ ecmaPattern.reserve(len);
+ int i = 0;
+ const QChar *wc = pattern.unicode();
+ bool inBracket = false;
+ while (i < len) {
+ QChar c = wc[i++];
+ ecmaPattern += c;
+ switch (c.unicode()) {
+ case '?':
+ case '+':
+ case '*':
+ case '}':
+ if (!inBracket)
+ ecmaPattern += QLatin1Char('?');
+ break;
+ case '\\':
+ if (i < len)
+ ecmaPattern += wc[i++];
+ break;
+ case '[':
+ inBracket = true;
+ break;
+ case ']':
+ inBracket = false;
+ break;
+ default:
+ break;
+ }
+ }
+ pattern = ecmaPattern;
+ }
+
+ int flags = v8::RegExp::kNone;
+ if (re.caseSensitivity() == Qt::CaseInsensitive)
+ flags |= v8::RegExp::kIgnoreCase;
+
+ return v8::RegExp::New(engine->toString(pattern), static_cast<v8::RegExp::Flags>(flags));
+}
+
+v8::Handle<v8::Value> QV8Engine::fromVariant(const QVariant &variant)
+{
+ int type = variant.userType();
+ const void *ptr = variant.constData();
+
+ if (type < QMetaType::User) {
+ switch (QMetaType::Type(type)) {
+ case QMetaType::Void:
+ return v8::Undefined();
+ case QMetaType::Bool:
+ return v8::Boolean::New(*reinterpret_cast<const bool*>(ptr));
+ case QMetaType::Int:
+ return v8::Integer::New(*reinterpret_cast<const int*>(ptr));
+ case QMetaType::UInt:
+ return v8::Integer::NewFromUnsigned(*reinterpret_cast<const uint*>(ptr));
+ case QMetaType::LongLong:
+ return v8::Number::New(*reinterpret_cast<const qlonglong*>(ptr));
+ case QMetaType::ULongLong:
+ return v8::Number::New(*reinterpret_cast<const qulonglong*>(ptr));
+ case QMetaType::Double:
+ return v8::Number::New(*reinterpret_cast<const double*>(ptr));
+ case QMetaType::QString:
+ return m_stringWrapper.toString(*reinterpret_cast<const QString*>(ptr));
+ case QMetaType::Float:
+ return v8::Number::New(*reinterpret_cast<const float*>(ptr));
+ case QMetaType::Short:
+ return v8::Integer::New(*reinterpret_cast<const short*>(ptr));
+ case QMetaType::UShort:
+ return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned short*>(ptr));
+ case QMetaType::Char:
+ return v8::Integer::New(*reinterpret_cast<const char*>(ptr));
+ case QMetaType::UChar:
+ return v8::Integer::NewFromUnsigned(*reinterpret_cast<const unsigned char*>(ptr));
+ case QMetaType::QChar:
+ return v8::Integer::New((*reinterpret_cast<const QChar*>(ptr)).unicode());
+ case QMetaType::QDateTime:
+ return v8::Date::New(qtDateTimeToJsDate(*reinterpret_cast<const QDateTime *>(ptr)));
+ case QMetaType::QDate:
+ return v8::Date::New(qtDateTimeToJsDate(QDateTime(*reinterpret_cast<const QDate *>(ptr))));
+ case QMetaType::QTime:
+ return v8::Date::New(qtDateTimeToJsDate(QDateTime(QDate(1970,1,1), *reinterpret_cast<const QTime *>(ptr))));
+ case QMetaType::QRegExp:
+ return regexpFromQRegExp(this, *reinterpret_cast<const QRegExp *>(ptr));
+ case QMetaType::QObjectStar:
+ case QMetaType::QWidgetStar:
+ return newQObject(*reinterpret_cast<QObject* const *>(ptr));
+ case QMetaType::QStringList:
+ return arrayFromStringList(this, *reinterpret_cast<const QStringList *>(ptr));
+ case QMetaType::QVariantList:
+ return arrayFromVariantList(this, *reinterpret_cast<const QVariantList *>(ptr));
+ case QMetaType::QVariantMap:
+ return objectFromVariantMap(this, *reinterpret_cast<const QVariantMap *>(ptr));
+
+ default:
+ break;
+ }
+
+ if (QDeclarativeValueType *vt = QDeclarativeEnginePrivate::get(m_engine)->valueTypes[type])
+ return m_valueTypeWrapper.newValueType(variant, vt);
+
+ } else {
+ if (type == qMetaTypeId<QDeclarativeListReference>()) {
+ typedef QDeclarativeListReferencePrivate QDLRP;
+ QDLRP *p = QDLRP::get((QDeclarativeListReference*)ptr);
+ if (p->object) {
+ return m_listWrapper.newList(p->property, p->propertyType);
+ } else {
+ return v8::Null();
+ }
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ // XXX aakenned Can this be more optimal? Just use Array as a prototype and
+ // implement directly against QList<QObject*>?
+ const QList<QObject *> &list = *(QList<QObject *>*)ptr;
+ v8::Local<v8::Array> array = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ array->Set(ii, newQObject(list.at(ii)));
+ return array;
+ }
+
+ bool objOk;
+ QObject *obj = QDeclarativeMetaType::toQObject(variant, &objOk);
+ if (objOk)
+ return newQObject(obj);
+ }
+
+ return m_variantWrapper.newVariant(variant);
+
+ // XXX aakenned
+#if 0
+#ifndef QT_NO_REGEXP
+ case QMetaType::QRegExp:
+ result = newRegExp(exec, *reinterpret_cast<const QRegExp *>(ptr));
+ break;
+#endif
+#ifndef QT_NO_QOBJECT
+#endif
+ case QMetaType::QVariant:
+ result = eng->newVariant(*reinterpret_cast<const QVariant*>(ptr));
+ break;
+ default:
+ if (type == qMetaTypeId<QScriptValue>()) {
+ result = eng->scriptValueToJSCValue(*reinterpret_cast<const QScriptValue*>(ptr));
+ if (!result)
+ return JSC::jsUndefined();
+ }
+
+#ifndef QT_NO_QOBJECT
+ // lazy registration of some common list types
+ else if (type == qMetaTypeId<QObjectList>()) {
+ qScriptRegisterSequenceMetaType<QObjectList>(eng->q_func());
+ return create(exec, type, ptr);
+ }
+#endif
+ else if (type == qMetaTypeId<QList<int> >()) {
+ qScriptRegisterSequenceMetaType<QList<int> >(eng->q_func());
+ return create(exec, type, ptr);
+ }
+
+ else {
+ QByteArray typeName = QMetaType::typeName(type);
+ if (typeName.endsWith('*') && !*reinterpret_cast<void* const *>(ptr))
+ return JSC::jsNull();
+ else
+ result = eng->newVariant(QVariant(type, ptr));
+ }
+ }
+ }
+#endif
+}
+
+// A handle scope and context must be entered
+v8::Local<v8::Script> QV8Engine::qmlModeCompile(const QString &source, const QString &fileName, int lineNumber)
+{
+ v8::Local<v8::String> v8source = m_stringWrapper.toString(source);
+ v8::Local<v8::String> v8fileName = m_stringWrapper.toString(fileName);
+
+ v8::ScriptOrigin origin(v8fileName, v8::Integer::New(lineNumber - 1));
+
+ v8::Local<v8::Script> script = v8::Script::Compile(v8source, &origin, 0, v8::Handle<v8::String>(),
+ v8::Script::QmlMode);
+
+ return script;
+}
+
+QNetworkAccessManager *QV8Engine::networkAccessManager()
+{
+ return QDeclarativeEnginePrivate::get(m_engine)->getNetworkAccessManager();
+}
+
+const QSet<QString> &QV8Engine::illegalNames() const
+{
+ return m_illegalNames;
+}
+
+// Requires a handle scope
+v8::Local<v8::Array> QV8Engine::getOwnPropertyNames(v8::Handle<v8::Object> o)
+{
+ v8::TryCatch tc;
+ v8::Handle<v8::Value> args[] = { o };
+ v8::Local<v8::Value> r = m_getOwnPropertyNames->Call(global(), 1, args);
+ if (tc.HasCaught())
+ return v8::Array::New();
+ else
+ return v8::Local<v8::Array>::Cast(r);
+}
+
+QDeclarativeContextData *QV8Engine::callingContext()
+{
+ return m_contextWrapper.callingContext();
+}
+
+// Converts a JS value to a QVariant.
+// Null, Undefined -> QVariant() (invalid)
+// Boolean -> QVariant(bool)
+// Number -> QVariant(double)
+// String -> QVariant(QString)
+// Array -> QVariantList(...)
+// Date -> QVariant(QDateTime)
+// RegExp -> QVariant(QRegExp)
+// [Any other object] -> QVariantMap(...)
+QVariant QV8Engine::toBasicVariant(v8::Handle<v8::Value> value)
+{
+ if (value->IsNull() || value->IsUndefined())
+ return QVariant();
+ else if (value->IsBoolean())
+ return value->ToBoolean()->Value();
+ else if (value->IsInt32())
+ return value->ToInt32()->Value();
+ else if (value->IsNumber())
+ return value->ToNumber()->Value();
+ else if (value->IsString())
+ return m_stringWrapper.toString(value->ToString());
+ if (value->IsDate())
+ return qtDateTimeFromJsDate(v8::Handle<v8::Date>::Cast(value)->NumberValue());
+ // NOTE: since we convert QTime to JS Date, round trip will change the variant type (to QDateTime)!
+
+ Q_ASSERT(value->IsObject());
+
+ if (value->IsRegExp()) {
+ v8::Context::Scope scope(context());
+ v8::Handle<v8::RegExp> jsRegExp = v8::Handle<v8::RegExp>::Cast(value);
+ // Copied from QtScript
+ // Converts a JS RegExp to a QRegExp.
+ // The conversion is not 100% exact since ECMA regexp and QRegExp
+ // have different semantics/flags, but we try to do our best.
+ QString pattern = toString(jsRegExp->GetSource());
+ Qt::CaseSensitivity caseSensitivity = Qt::CaseSensitive;
+ if (jsRegExp->GetFlags() & v8::RegExp::kIgnoreCase)
+ caseSensitivity = Qt::CaseInsensitive;
+ return QRegExp(pattern, caseSensitivity, QRegExp::RegExp2);
+ } else if (value->IsArray()) {
+ v8::Context::Scope scope(context());
+ QVariantList rv;
+
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+ int length = array->Length();
+ for (int ii = 0; ii < length; ++ii)
+ rv << toVariant(array->Get(ii), -1);
+
+ return rv;
+ } else if (!value->IsFunction()) {
+ v8::Context::Scope scope(context());
+ v8::Handle<v8::Object> object = value->ToObject();
+ v8::Local<v8::Array> properties = object->GetPropertyNames();
+ int length = properties->Length();
+ if (length == 0)
+ return QVariant();
+
+ QVariantMap map;
+ for (int ii = 0; ii < length; ++ii) {
+ v8::Handle<v8::Value> property = properties->Get(ii);
+ map.insert(toString(property), toVariant(object->Get(property), -1));
+ }
+ return map;
+ }
+
+ return QVariant();
+}
+
+
+
+#include <QtGui/qvector3d.h>
+
+struct StaticQtMetaObject : public QObject
+{
+ static const QMetaObject *get()
+ { return &static_cast<StaticQtMetaObject*> (0)->staticQtMetaObject; }
+};
+
+void QV8Engine::initializeGlobal(v8::Handle<v8::Object> global)
+{
+ v8::Local<v8::Function> printFn = V8FUNCTION(print, this);
+
+ v8::Local<v8::Object> console = v8::Object::New();
+ console->Set(v8::String::New("log"), printFn);
+ console->Set(v8::String::New("debug"), printFn);
+
+ // XXX - Qt global object properties
+
+ v8::Local<v8::Object> qt = v8::Object::New();
+
+ // Set all the enums from the "Qt" namespace
+ const QMetaObject *qtMetaObject = StaticQtMetaObject::get();
+ for (int ii = 0; ii < qtMetaObject->enumeratorCount(); ++ii) {
+ QMetaEnum enumerator = qtMetaObject->enumerator(ii);
+ for (int jj = 0; jj < enumerator.keyCount(); ++jj) {
+ qt->Set(v8::String::New(enumerator.key(jj)), v8::Integer::New(enumerator.value(jj)));
+ }
+ }
+
+ if (m_engine)
+ qt->Set(v8::String::New("application"), newQObject(new QDeclarativeApplication(m_engine)));
+
+ qt->Set(v8::String::New("include"), V8FUNCTION(QV8Include::include, this));
+ qt->Set(v8::String::New("isQtObject"), V8FUNCTION(isQtObject, this));
+ qt->Set(v8::String::New("rgba"), V8FUNCTION(rgba, this));
+ qt->Set(v8::String::New("hsla"), V8FUNCTION(hsla, this));
+ qt->Set(v8::String::New("rect"), V8FUNCTION(rect, this));
+ qt->Set(v8::String::New("point"), V8FUNCTION(point, this));
+ qt->Set(v8::String::New("size"), V8FUNCTION(size, this));
+ qt->Set(v8::String::New("vector3d"), V8FUNCTION(vector3d, this));
+
+ if (m_engine) {
+ qt->Set(v8::String::New("lighter"), V8FUNCTION(lighter, this));
+ qt->Set(v8::String::New("darker"), V8FUNCTION(darker, this));
+ qt->Set(v8::String::New("tint"), V8FUNCTION(tint, this));
+ }
+
+ qt->Set(v8::String::New("formatDate"), V8FUNCTION(formatDate, this));
+ qt->Set(v8::String::New("formatTime"), V8FUNCTION(formatTime, this));
+ qt->Set(v8::String::New("formatDateTime"), V8FUNCTION(formatDateTime, this));
+
+ qt->Set(v8::String::New("openUrlExternally"), V8FUNCTION(openUrlExternally, this));
+ qt->Set(v8::String::New("fontFamilies"), V8FUNCTION(fontFamilies, this));
+ qt->Set(v8::String::New("md5"), V8FUNCTION(md5, this));
+ qt->Set(v8::String::New("btoa"), V8FUNCTION(btoa, this));
+ qt->Set(v8::String::New("atob"), V8FUNCTION(atob, this));
+ qt->Set(v8::String::New("quit"), V8FUNCTION(quit, this));
+ qt->Set(v8::String::New("resolvedUrl"), V8FUNCTION(resolvedUrl, this));
+
+ if (m_engine) {
+ qt->Set(v8::String::New("createQmlObject"), V8FUNCTION(createQmlObject, this));
+ qt->Set(v8::String::New("createComponent"), V8FUNCTION(createComponent, this));
+ }
+
+ // XXX translator functions
+
+ global->Set(v8::String::New("print"), printFn);
+ global->Set(v8::String::New("console"), console);
+ global->Set(v8::String::New("Qt"), qt);
+
+ // XXX mainthread only
+ m_xmlHttpRequestData = qt_add_qmlxmlhttprequest(this);
+ m_sqlDatabaseData = qt_add_qmlsqldatabase(this);
+
+ {
+ v8::Handle<v8::Value> args[] = { global };
+ v8::Local<v8::Value> names = m_getOwnPropertyNames->Call(global, 1, args);
+ v8::Local<v8::Array> namesArray = v8::Local<v8::Array>::Cast(names);
+ for (quint32 ii = 0; ii < namesArray->Length(); ++ii)
+ m_illegalNames.insert(toString(namesArray->Get(ii)));
+ }
+}
+
+void QV8Engine::freezeGlobal()
+{
+ // Freeze the global object
+ // XXX I don't think this is sufficient as it misses non-enumerable properties
+#define FREEZE "(function freeze_recur(obj) { "\
+ " if (Qt.isQtObject(obj)) return;"\
+ " for (var prop in obj) { " \
+ " if (prop == \"connect\" || prop == \"disconnect\") {" \
+ " Object.freeze(obj[prop]); "\
+ " continue;" \
+ " }" \
+ " freeze_recur(obj[prop]);" \
+ " }" \
+ " if (obj instanceof Object) {" \
+ " Object.freeze(obj);" \
+ " }"\
+ "})(this);"
+ v8::Local<v8::Script> test = v8::Script::New(v8::String::New(FREEZE));
+#undef FREEZE
+
+ test->Run();
+}
+
+v8::Handle<v8::Value> QV8Engine::print(const v8::Arguments &args)
+{
+ QString result;
+ for (int i = 0; i < args.Length(); ++i) {
+ if (i != 0)
+ result.append(QLatin1Char(' '));
+
+ v8::Local<v8::String> jsstr = args[i]->ToString();
+ if (!jsstr.IsEmpty()) {
+ QString qstr;
+ qstr.resize(jsstr->Length());
+ jsstr->Write((uint16_t*)qstr.data());
+ result.append(qstr);
+ }
+ }
+ qDebug("%s", qPrintable(result));
+ return v8::Undefined();
+}
+
+/*!
+\qmlmethod bool Qt::isQtObject(object)
+Returns true if \c object is a valid reference to a Qt or QML object, otherwise false.
+*/
+v8::Handle<v8::Value> QV8Engine::isQtObject(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ return v8::Boolean::New(false);
+
+ return v8::Boolean::New(0 != V8ENGINE()->toQObject(args[0]));
+}
+
+/*!
+\qmlmethod color Qt::rgba(real red, real green, real blue, real alpha)
+
+Returns a color with the specified \c red, \c green, \c blue and \c alpha components.
+All components should be in the range 0-1 inclusive.
+*/
+v8::Handle<v8::Value> QV8Engine::rgba(const v8::Arguments &args)
+{
+ int argCount = args.Length();
+ if (argCount < 3 || argCount > 4)
+ V8THROW_ERROR("Qt.rgba(): Invalid arguments");
+
+ double r = args[0]->NumberValue();
+ double g = args[1]->NumberValue();
+ double b = args[2]->NumberValue();
+ double a = (argCount == 4) ? args[3]->NumberValue() : 1;
+
+ if (r < 0.0) r=0.0;
+ if (r > 1.0) r=1.0;
+ if (g < 0.0) g=0.0;
+ if (g > 1.0) g=1.0;
+ if (b < 0.0) b=0.0;
+ if (b > 1.0) b=1.0;
+ if (a < 0.0) a=0.0;
+ if (a > 1.0) a=1.0;
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromRgbF(r, g, b, a)));
+}
+
+/*!
+\qmlmethod color Qt::hsla(real hue, real saturation, real lightness, real alpha)
+
+Returns a color with the specified \c hue, \c saturation, \c lightness and \c alpha components.
+All components should be in the range 0-1 inclusive.
+*/
+v8::Handle<v8::Value> QV8Engine::hsla(const v8::Arguments &args)
+{
+ int argCount = args.Length();
+ if (argCount < 3 || argCount > 4)
+ V8THROW_ERROR("Qt.hsla(): Invalid arguments");
+
+ double h = args[0]->NumberValue();
+ double s = args[1]->NumberValue();
+ double l = args[2]->NumberValue();
+ double a = (argCount == 4) ? args[3]->NumberValue() : 1;
+
+ if (h < 0.0) h=0.0;
+ if (h > 1.0) h=1.0;
+ if (s < 0.0) s=0.0;
+ if (s > 1.0) s=1.0;
+ if (l < 0.0) l=0.0;
+ if (l > 1.0) l=1.0;
+ if (a < 0.0) a=0.0;
+ if (a > 1.0) a=1.0;
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QColor::fromHslF(h, s, l, a)));
+}
+
+/*!
+\qmlmethod rect Qt::rect(int x, int y, int width, int height)
+
+Returns a \c rect with the top-left corner at \c x, \c y and the specified \c width and \c height.
+
+The returned object has \c x, \c y, \c width and \c height attributes with the given values.
+*/
+v8::Handle<v8::Value> QV8Engine::rect(const v8::Arguments &args)
+{
+ if (args.Length() != 4)
+ V8THROW_ERROR("Qt.rect(): Invalid arguments");
+
+ double x = args[0]->NumberValue();
+ double y = args[1]->NumberValue();
+ double w = args[2]->NumberValue();
+ double h = args[3]->NumberValue();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QRectF(x, y, w, h)));
+}
+
+/*!
+\qmlmethod point Qt::point(int x, int y)
+Returns a Point with the specified \c x and \c y coordinates.
+*/
+v8::Handle<v8::Value> QV8Engine::point(const v8::Arguments &args)
+{
+ if (args.Length() != 2)
+ V8THROW_ERROR("Qt.point(): Invalid arguments");
+
+ double x = args[0]->ToNumber()->Value();
+ double y = args[1]->ToNumber()->Value();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QPointF(x, y)));
+}
+
+/*!
+\qmlmethod Qt::size(int width, int height)
+Returns a Size with the specified \c width and \c height.
+*/
+v8::Handle<v8::Value> QV8Engine::size(const v8::Arguments &args)
+{
+ if (args.Length() != 2)
+ V8THROW_ERROR("Qt.size(): Invalid arguments");
+
+ double w = args[0]->ToNumber()->Value();
+ double h = args[1]->ToNumber()->Value();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QSizeF(w, h)));
+}
+
+/*!
+\qmlmethod Qt::vector3d(real x, real y, real z)
+Returns a Vector3D with the specified \c x, \c y and \c z.
+*/
+v8::Handle<v8::Value> QV8Engine::vector3d(const v8::Arguments &args)
+{
+ if (args.Length() != 3)
+ V8THROW_ERROR("Qt.vector(): Invalid arguments");
+
+ double x = args[0]->ToNumber()->Value();
+ double y = args[1]->ToNumber()->Value();
+ double z = args[2]->ToNumber()->Value();
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(QVector3D(x, y, z)));
+}
+
+/*!
+\qmlmethod color Qt::lighter(color baseColor, real factor)
+Returns a color lighter than \c baseColor by the \c factor provided.
+
+If the factor is greater than 1.0, this functions returns a lighter color.
+Setting factor to 1.5 returns a color that is 50% brighter. If the factor is less than 1.0,
+the return color is darker, but we recommend using the Qt.darker() function for this purpose.
+If the factor is 0 or negative, the return value is unspecified.
+
+The function converts the current RGB color to HSV, multiplies the value (V) component
+by factor and converts the color back to RGB.
+
+If \c factor is not supplied, returns a color 50% lighter than \c baseColor (factor 1.5).
+*/
+v8::Handle<v8::Value> QV8Engine::lighter(const v8::Arguments &args)
+{
+ if (args.Length() != 1 && args.Length() != 2)
+ V8THROW_ERROR("Qt.lighter(): Invalid arguments");
+
+ QColor color;
+ QVariant v = V8ENGINE()->toVariant(args[0], -1);
+ if (v.userType() == QVariant::Color) {
+ color = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ qreal factor = 1.5;
+ if (args.Length() == 2)
+ factor = args[1]->ToNumber()->Value();
+
+ color = color.lighter(int(qRound(factor*100.)));
+ return V8ENGINE()->fromVariant(QVariant::fromValue(color));
+}
+
+/*!
+\qmlmethod color Qt::darker(color baseColor, real factor)
+Returns a color darker than \c baseColor by the \c factor provided.
+
+If the factor is greater than 1.0, this function returns a darker color.
+Setting factor to 3.0 returns a color that has one-third the brightness.
+If the factor is less than 1.0, the return color is lighter, but we recommend using
+the Qt.lighter() function for this purpose. If the factor is 0 or negative, the return
+value is unspecified.
+
+The function converts the current RGB color to HSV, divides the value (V) component
+by factor and converts the color back to RGB.
+
+If \c factor is not supplied, returns a color 50% darker than \c baseColor (factor 2.0).
+*/
+v8::Handle<v8::Value> QV8Engine::darker(const v8::Arguments &args)
+{
+ if (args.Length() != 1 && args.Length() != 2)
+ V8THROW_ERROR("Qt.darker(): Invalid arguments");
+
+ QColor color;
+ QVariant v = V8ENGINE()->toVariant(args[0], -1);
+ if (v.userType() == QVariant::Color) {
+ color = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ qreal factor = 2.0;
+ if (args.Length() == 2)
+ factor = args[1]->ToNumber()->Value();
+
+ color = color.darker(int(qRound(factor*100.)));
+ return V8ENGINE()->fromVariant(QVariant::fromValue(color));
+}
+
+/*!
+ \qmlmethod color Qt::tint(color baseColor, color tintColor)
+ This function allows tinting one color with another.
+
+ The tint color should usually be mostly transparent, or you will not be
+ able to see the underlying color. The below example provides a slight red
+ tint by having the tint color be pure red which is only 1/16th opaque.
+
+ \qml
+ Item {
+ Rectangle {
+ x: 0; width: 80; height: 80
+ color: "lightsteelblue"
+ }
+ Rectangle {
+ x: 100; width: 80; height: 80
+ color: Qt.tint("lightsteelblue", "#10FF0000")
+ }
+ }
+ \endqml
+ \image declarative-rect_tint.png
+
+ Tint is most useful when a subtle change is intended to be conveyed due to some event; you can then use tinting to more effectively tune the visible color.
+*/
+v8::Handle<v8::Value> QV8Engine::tint(const v8::Arguments &args)
+{
+ if (args.Length() != 2)
+ V8THROW_ERROR("Qt.tint(): Invalid arguments");
+
+ // base color
+ QColor color;
+ QVariant v = V8ENGINE()->toVariant(args[0], -1);
+ if (v.userType() == QVariant::Color) {
+ color = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ color = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ // tint color
+ QColor tintColor;
+ v = V8ENGINE()->toVariant(args[1], -1);
+ if (v.userType() == QVariant::Color) {
+ tintColor = v.value<QColor>();
+ } else if (v.userType() == QVariant::String) {
+ bool ok = false;
+ tintColor = QDeclarativeStringConverters::colorFromString(v.toString(), &ok);
+ if (!ok) {
+ return v8::Null();
+ }
+ } else {
+ return v8::Null();
+ }
+
+ // tint the base color and return the final color
+ QColor finalColor;
+ int a = tintColor.alpha();
+ if (a == 0xFF)
+ finalColor = tintColor;
+ else if (a == 0x00)
+ finalColor = color;
+ else {
+ qreal a = tintColor.alphaF();
+ qreal inv_a = 1.0 - a;
+
+ finalColor.setRgbF(tintColor.redF() * a + color.redF() * inv_a,
+ tintColor.greenF() * a + color.greenF() * inv_a,
+ tintColor.blueF() * a + color.blueF() * inv_a,
+ a + inv_a * color.alphaF());
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(finalColor));
+}
+
+/*!
+\qmlmethod string Qt::formatDate(datetime date, variant format)
+
+Returns a string representation of \c date, optionally formatted according
+to \c format.
+
+The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
+property, a QDate, or QDateTime value. The \a format parameter may be any of
+the possible format values as described for
+\l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
+
+If \a format is not specified, \a date is formatted using
+\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+*/
+v8::Handle<v8::Value> QV8Engine::formatDate(const v8::Arguments &args)
+{
+ if (args.Length() < 1 || args.Length() > 2)
+ V8THROW_ERROR("Qt.formatDate(): Invalid arguments");
+
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ QDate date = V8ENGINE()->toVariant(args[0], -1).toDateTime().date();
+ QString formattedDate;
+ if (args.Length() == 2) {
+ if (args[1]->IsString()) {
+ QString format = V8ENGINE()->toVariant(args[1], -1).toString();
+ formattedDate = date.toString(format);
+ } else if (args[1]->IsNumber()) {
+ quint32 intFormat = args[1]->ToNumber()->Value();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formattedDate = date.toString(format);
+ } else {
+ V8THROW_ERROR("Qt.formatDate(): Invalid date format");
+ }
+ } else {
+ formattedDate = date.toString(enumFormat);
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDate));
+}
+
+/*!
+\qmlmethod string Qt::formatTime(datetime time, variant format)
+
+Returns a string representation of \c time, optionally formatted according to
+\c format.
+
+The \a time parameter may be a JavaScript \c Date object, a QTime, or QDateTime
+value. The \a format parameter may be any of the possible format values as
+described for \l{QML:Qt::formatDateTime()}{Qt.formatDateTime()}.
+
+If \a format is not specified, \a time is formatted using
+\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}.
+*/
+v8::Handle<v8::Value> QV8Engine::formatTime(const v8::Arguments &args)
+{
+ if (args.Length() < 1 || args.Length() > 2)
+ V8THROW_ERROR("Qt.formatTime(): Invalid arguments");
+
+ QVariant argVariant = V8ENGINE()->toVariant(args[0], -1);
+ QTime time;
+ if (args[0]->IsDate() || (argVariant.type() == QVariant::String))
+ time = argVariant.toDateTime().time();
+ else // if (argVariant.type() == QVariant::Time), or invalid.
+ time = argVariant.toTime();
+
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ QString formattedTime;
+ if (args.Length() == 2) {
+ if (args[1]->IsString()) {
+ QString format = V8ENGINE()->toVariant(args[1], -1).toString();
+ formattedTime = time.toString(format);
+ } else if (args[1]->IsNumber()) {
+ quint32 intFormat = args[1]->ToNumber()->Value();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formattedTime = time.toString(format);
+ } else {
+ V8THROW_ERROR("Qt.formatTime(): Invalid time format");
+ }
+ } else {
+ formattedTime = time.toString(enumFormat);
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(formattedTime));
+}
+
+/*!
+\qmlmethod string Qt::formatDateTime(datetime dateTime, variant format)
+
+Returns a string representation of \c datetime, optionally formatted according to
+\c format.
+
+The \a date parameter may be a JavaScript \c Date object, a \l{date}{date}
+property, a QDate, QTime, or QDateTime value.
+
+If \a format is not provided, \a dateTime is formatted using
+\l {Qt::DefaultLocaleShortDate}{Qt.DefaultLocaleShortDate}. Otherwise,
+\a format should be either:
+
+\list
+\o One of the Qt::DateFormat enumeration values, such as
+ \c Qt.DefaultLocaleShortDate or \c Qt.ISODate
+\o A string that specifies the format of the returned string, as detailed below.
+\endlist
+
+If \a format specifies a format string, it should use the following expressions
+to specify the date:
+
+ \table
+ \header \i Expression \i Output
+ \row \i d \i the day as number without a leading zero (1 to 31)
+ \row \i dd \i the day as number with a leading zero (01 to 31)
+ \row \i ddd
+ \i the abbreviated localized day name (e.g. 'Mon' to 'Sun').
+ Uses QDate::shortDayName().
+ \row \i dddd
+ \i the long localized day name (e.g. 'Monday' to 'Qt::Sunday').
+ Uses QDate::longDayName().
+ \row \i M \i the month as number without a leading zero (1-12)
+ \row \i MM \i the month as number with a leading zero (01-12)
+ \row \i MMM
+ \i the abbreviated localized month name (e.g. 'Jan' to 'Dec').
+ Uses QDate::shortMonthName().
+ \row \i MMMM
+ \i the long localized month name (e.g. 'January' to 'December').
+ Uses QDate::longMonthName().
+ \row \i yy \i the year as two digit number (00-99)
+ \row \i yyyy \i the year as four digit number
+ \endtable
+
+In addition the following expressions can be used to specify the time:
+
+ \table
+ \header \i Expression \i Output
+ \row \i h
+ \i the hour without a leading zero (0 to 23 or 1 to 12 if AM/PM display)
+ \row \i hh
+ \i the hour with a leading zero (00 to 23 or 01 to 12 if AM/PM display)
+ \row \i m \i the minute without a leading zero (0 to 59)
+ \row \i mm \i the minute with a leading zero (00 to 59)
+ \row \i s \i the second without a leading zero (0 to 59)
+ \row \i ss \i the second with a leading zero (00 to 59)
+ \row \i z \i the milliseconds without leading zeroes (0 to 999)
+ \row \i zzz \i the milliseconds with leading zeroes (000 to 999)
+ \row \i AP
+ \i use AM/PM display. \e AP will be replaced by either "AM" or "PM".
+ \row \i ap
+ \i use am/pm display. \e ap will be replaced by either "am" or "pm".
+ \endtable
+
+ All other input characters will be ignored. Any sequence of characters that
+ are enclosed in single quotes will be treated as text and not be used as an
+ expression. Two consecutive single quotes ("''") are replaced by a single quote
+ in the output.
+
+For example, if the following date/time value was specified:
+
+ \code
+ // 21 May 2001 14:13:09
+ var dateTime = new Date(2001, 5, 21, 14, 13, 09)
+ \endcode
+
+This \a dateTime value could be passed to \c Qt.formatDateTime(),
+\l {QML:Qt::formatDate()}{Qt.formatDate()} or \l {QML:Qt::formatTime()}{Qt.formatTime()}
+with the \a format values below to produce the following results:
+
+ \table
+ \header \i Format \i Result
+ \row \i "dd.MM.yyyy" \i 21.05.2001
+ \row \i "ddd MMMM d yy" \i Tue May 21 01
+ \row \i "hh:mm:ss.zzz" \i 14:13:09.042
+ \row \i "h:m:s ap" \i 2:13:9 pm
+ \endtable
+*/
+v8::Handle<v8::Value> QV8Engine::formatDateTime(const v8::Arguments &args)
+{
+ if (args.Length() < 1 || args.Length() > 2)
+ V8THROW_ERROR("Qt.formatDateTime(): Invalid arguments");
+
+ Qt::DateFormat enumFormat = Qt::DefaultLocaleShortDate;
+ QDateTime dt = V8ENGINE()->toVariant(args[0], -1).toDateTime();
+ QString formattedDt;
+ if (args.Length() == 2) {
+ if (args[1]->IsString()) {
+ QString format = V8ENGINE()->toVariant(args[1], -1).toString();
+ formattedDt = dt.toString(format);
+ } else if (args[1]->IsNumber()) {
+ quint32 intFormat = args[1]->ToNumber()->Value();
+ Qt::DateFormat format = Qt::DateFormat(intFormat);
+ formattedDt = dt.toString(format);
+ } else {
+ V8THROW_ERROR("Qt.formatDateTime(): Invalid datetime format");
+ }
+ } else {
+ formattedDt = dt.toString(enumFormat);
+ }
+
+ return V8ENGINE()->fromVariant(QVariant::fromValue(formattedDt));
+}
+
+double QV8Engine::qtDateTimeToJsDate(const QDateTime &dt)
+{
+ // from QScriptEngine::DateTimeToMs()
+ if (!dt.isValid()) {
+ return qSNaN();
+ }
+ QDateTime utc = dt.toUTC();
+ QDate date = utc.date();
+ QTime time = utc.time();
+ QV8DateConverter::JSC::GregorianDateTime tm;
+ tm.year = date.year() - 1900;
+ tm.month = date.month() - 1;
+ tm.monthDay = date.day();
+ tm.weekDay = date.dayOfWeek();
+ tm.yearDay = date.dayOfYear();
+ tm.hour = time.hour();
+ tm.minute = time.minute();
+ tm.second = time.second();
+ return QV8DateConverter::JSC::gregorianDateTimeToMS(tm, time.msec());
+}
+
+QDateTime QV8Engine::qtDateTimeFromJsDate(double jsDate)
+{
+ // from QScriptEngine::MsToDateTime()
+ if (qIsNaN(jsDate))
+ return QDateTime();
+ QV8DateConverter::JSC::GregorianDateTime tm;
+ QV8DateConverter::JSC::msToGregorianDateTime(jsDate, tm);
+
+ // from QScriptEngine::MsFromTime()
+ int ms = int(::fmod(jsDate, 1000.0));
+ if (ms < 0)
+ ms += int(1000.0);
+
+ QDateTime convertedUTC = QDateTime(QDate(tm.year + 1900, tm.month + 1, tm.monthDay),
+ QTime(tm.hour, tm.minute, tm.second, ms), Qt::UTC);
+ return convertedUTC.toLocalTime();
+}
+
+/*!
+\qmlmethod bool Qt::openUrlExternally(url target)
+Attempts to open the specified \c target url in an external application, based on the user's desktop preferences. Returns true if it succeeds, and false otherwise.
+*/
+v8::Handle<v8::Value> QV8Engine::openUrlExternally(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ return V8ENGINE()->fromVariant(false);
+
+ bool ret = false;
+#ifndef QT_NO_DESKTOPSERVICES
+ ret = QDesktopServices::openUrl(V8ENGINE()->toVariant(resolvedUrl(args), -1).toUrl());
+#endif
+ return V8ENGINE()->fromVariant(ret);
+}
+
+/*!
+ \qmlmethod url Qt::resolvedUrl(url url)
+ Returns \a url resolved relative to the URL of the caller.
+*/
+v8::Handle<v8::Value> QV8Engine::resolvedUrl(const v8::Arguments &args)
+{
+ QUrl url = V8ENGINE()->toVariant(args[0], -1).toUrl();
+ // XXX uses QDeclarativeEngine which means it wont work in worker script?
+ QDeclarativeEngine *e = V8ENGINE()->engine();
+ QDeclarativeEnginePrivate *p = 0;
+ if (e) p = QDeclarativeEnginePrivate::get(e);
+ if (p) {
+ QDeclarativeContextData *ctxt = V8ENGINE()->callingContext();
+ if (ctxt)
+ return V8ENGINE()->fromVariant(ctxt->resolvedUrl(url));
+ else
+ return V8ENGINE()->fromVariant(url);
+ }
+
+ return V8ENGINE()->fromVariant(e->baseUrl().resolved(url));
+}
+
+/*!
+\qmlmethod list<string> Qt::fontFamilies()
+Returns a list of the font families available to the application.
+*/
+v8::Handle<v8::Value> QV8Engine::fontFamilies(const v8::Arguments &args)
+{
+ if (args.Length() != 0)
+ V8THROW_ERROR("Qt.fontFamilies(): Invalid arguments");
+
+ QFontDatabase database;
+ return V8ENGINE()->fromVariant(database.families());
+}
+
+/*!
+\qmlmethod string Qt::md5(data)
+Returns a hex string of the md5 hash of \c data.
+*/
+v8::Handle<v8::Value> QV8Engine::md5(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.md5(): Invalid arguments");
+
+ QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
+ QByteArray result = QCryptographicHash::hash(data, QCryptographicHash::Md5);
+ return V8ENGINE()->toString(QLatin1String(result.toHex()));
+}
+
+/*!
+\qmlmethod string Qt::btoa(data)
+Binary to ASCII - this function returns a base64 encoding of \c data.
+*/
+v8::Handle<v8::Value> QV8Engine::btoa(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.btoa(): Invalid arguments");
+
+ QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
+
+ return V8ENGINE()->toString(QLatin1String(data.toBase64()));
+}
+
+/*!
+\qmlmethod string Qt::atob(data)
+ASCII to binary - this function returns a base64 decoding of \c data.
+*/
+v8::Handle<v8::Value> QV8Engine::atob(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.atob(): Invalid arguments");
+
+ QByteArray data = V8ENGINE()->toString(args[0]->ToString()).toUtf8();
+
+ return V8ENGINE()->toString(QLatin1String(QByteArray::fromBase64(data)));
+}
+
+/*!
+\qmlmethod Qt::quit()
+This function causes the QDeclarativeEngine::quit() signal to be emitted.
+Within the \l {QML Viewer}, this causes the launcher application to exit;
+to quit a C++ application when this method is called, connect the
+QDeclarativeEngine::quit() signal to the QCoreApplication::quit() slot.
+*/
+v8::Handle<v8::Value> QV8Engine::quit(const v8::Arguments &args)
+{
+ // XXX worker script?
+ QDeclarativeEnginePrivate::get(V8ENGINE()->engine())->sendQuit();
+ return v8::Undefined();
+}
+
+/*!
+\qmlmethod object Qt::createQmlObject(string qml, object parent, string filepath)
+
+Returns a new object created from the given \a string of QML which will have the specified \a parent,
+or \c null if there was an error in creating the object.
+
+If \a filepath is specified, it will be used for error reporting for the created object.
+
+Example (where \c parentItem is the id of an existing QML item):
+
+\snippet doc/src/snippets/declarative/createQmlObject.qml 0
+
+In the case of an error, a QtScript Error object is thrown. This object has an additional property,
+\c qmlErrors, which is an array of the errors encountered.
+Each object in this array has the members \c lineNumber, \c columnNumber, \c fileName and \c message.
+For example, if the above snippet had misspelled color as 'colro' then the array would contain an object like the following:
+{ "lineNumber" : 1, "columnNumber" : 32, "fileName" : "dynamicSnippet1", "message" : "Cannot assign to non-existent property \"colro\""}.
+
+Note that this function returns immediately, and therefore may not work if
+the \a qml string loads new components (that is, external QML files that have not yet been loaded).
+If this is the case, consider using \l{QML:Qt::createComponent()}{Qt.createComponent()} instead.
+
+See \l {Dynamic Object Management in QML} for more information on using this function.
+*/
+v8::Handle<v8::Value> QV8Engine::createQmlObject(const v8::Arguments &args)
+{
+ if (args.Length() < 2 || args.Length() > 3)
+ V8THROW_ERROR("Qt.createQmlObject(): Invalid arguments");
+
+ struct Error {
+ static v8::Local<v8::Value> create(QV8Engine *engine, const QList<QDeclarativeError> &errors) {
+ QString errorstr = QLatin1String("Qt.createQmlObject(): failed to create object: ");
+
+ v8::Local<v8::Array> qmlerrors = v8::Array::New(errors.count());
+ for (int ii = 0; ii < errors.count(); ++ii) {
+ const QDeclarativeError &error = errors.at(ii);
+ errorstr += QLatin1String("\n ") + error.toString();
+ v8::Local<v8::Object> qmlerror = v8::Object::New();
+ qmlerror->Set(v8::String::New("lineNumber"), v8::Integer::New(error.line()));
+ qmlerror->Set(v8::String::New("columnNumber"), v8::Integer::New(error.line()));
+ qmlerror->Set(v8::String::New("fileName"), engine->toString(error.url().toString()));
+ qmlerror->Set(v8::String::New("message"), engine->toString(error.description()));
+ qmlerrors->Set(ii, qmlerror);
+ }
+
+ v8::Local<v8::Value> error = v8::Exception::Error(engine->toString(errorstr));
+ v8::Local<v8::Object> errorObject = error->ToObject();
+ errorObject->Set(v8::String::New("qmlErrors"), qmlerrors);
+ return error;
+ }
+ };
+
+ QV8Engine *v8engine = V8ENGINE();
+ QDeclarativeEngine *engine = v8engine->engine();
+
+ QDeclarativeContextData *context = v8engine->callingContext();
+ Q_ASSERT(context);
+
+ QString qml = v8engine->toString(args[0]->ToString());
+ if (qml.isEmpty())
+ return v8::Null();
+
+ QUrl url;
+ if(args.Length() > 2)
+ url = QUrl(v8engine->toString(args[2]->ToString()));
+ else
+ url = QUrl(QLatin1String("inline"));
+
+ if (url.isValid() && url.isRelative())
+ url = context->resolvedUrl(url);
+
+ QObject *parentArg = v8engine->toQObject(args[1]);
+ if(!parentArg)
+ V8THROW_ERROR("Qt.createQmlObject(): Missing parent object");
+
+ QDeclarativeComponent component(engine);
+ component.setData(qml.toUtf8(), url);
+
+ if(component.isError()) {
+ v8::ThrowException(Error::create(v8engine, component.errors()));
+ return v8::Undefined();
+ }
+
+ if (!component.isReady())
+ V8THROW_ERROR("Qt.createQmlObject(): Component is not ready");
+
+ QObject *obj = component.beginCreate(context->asQDeclarativeContext());
+ if(obj)
+ QDeclarativeData::get(obj, true)->setImplicitDestructible();
+ component.completeCreate();
+
+ if(component.isError()) {
+ v8::ThrowException(Error::create(v8engine, component.errors()));
+ return v8::Undefined();
+ }
+
+ Q_ASSERT(obj);
+
+ obj->setParent(parentArg);
+
+ QList<QDeclarativePrivate::AutoParentFunction> functions = QDeclarativeMetaType::parentFunctions();
+ for (int ii = 0; ii < functions.count(); ++ii) {
+ if (QDeclarativePrivate::Parented == functions.at(ii)(obj, parentArg))
+ break;
+ }
+
+ return v8engine->newQObject(obj);
+}
+
+/*!
+\qmlmethod object Qt::createComponent(url)
+
+Returns a \l Component object created using the QML file at the specified \a url,
+or \c null if an empty string was given.
+
+The returned component's \l Component::status property indicates whether the
+component was successfully created. If the status is \c Component.Error,
+see \l Component::errorString() for an error description.
+
+Call \l {Component::createObject()}{Component.createObject()} on the returned
+component to create an object instance of the component.
+
+For example:
+
+\snippet doc/src/snippets/declarative/createComponent-simple.qml 0
+
+See \l {Dynamic Object Management in QML} for more information on using this function.
+
+To create a QML object from an arbitrary string of QML (instead of a file),
+use \l{QML:Qt::createQmlObject()}{Qt.createQmlObject()}.
+*/
+v8::Handle<v8::Value> QV8Engine::createComponent(const v8::Arguments &args)
+{
+ if (args.Length() != 1)
+ V8THROW_ERROR("Qt.createComponent(): Invalid arguments");
+
+ QV8Engine *v8engine = V8ENGINE();
+ QDeclarativeEngine *engine = v8engine->engine();
+
+ QDeclarativeContextData *context = v8engine->callingContext();
+ Q_ASSERT(context);
+
+ QString arg = v8engine->toString(args[0]->ToString());
+ if (arg.isEmpty())
+ return v8::Null();
+
+ QUrl url = context->resolvedUrl(QUrl(arg));
+ QDeclarativeComponent *c = new QDeclarativeComponent(engine, url, engine);
+ QDeclarativeComponentPrivate::get(c)->creationContext = context;
+ QDeclarativeData::get(c, true)->setImplicitDestructible();
+ return v8engine->newQObject(c);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/v8/qv8engine_p.h b/src/declarative/qml/v8/qv8engine_p.h
new file mode 100644
index 0000000000..d4b8730dc7
--- /dev/null
+++ b/src/declarative/qml/v8/qv8engine_p.h
@@ -0,0 +1,348 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEV8ENGINE_P_H
+#define QDECLARATIVEV8ENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qset.h>
+#include <private/qv8_p.h>
+
+#include <private/qdeclarativepropertycache_p.h>
+
+#include "qv8contextwrapper_p.h"
+#include "qv8qobjectwrapper_p.h"
+#include "qv8stringwrapper_p.h"
+#include "qv8typewrapper_p.h"
+#include "qv8listwrapper_p.h"
+#include "qv8variantwrapper_p.h"
+#include "qv8valuetypewrapper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#define V8_RESOURCE_TYPE(resourcetype) \
+public: \
+ enum { V8ResourceType = QV8ObjectResource:: resourcetype }; \
+ virtual QV8ObjectResource::ResourceType resourceType() const { return QV8ObjectResource:: resourcetype; } \
+private:
+
+#define V8ENGINE() ((QV8Engine *)v8::External::Unwrap(args.Data()))
+#define V8FUNCTION(function, engine) v8::FunctionTemplate::New(function, v8::External::Wrap((QV8Engine*)engine))->GetFunction()
+// XXX Are we mean to return a value here, or is an empty handle ok?
+#define V8THROW_ERROR(string) { \
+ v8::ThrowException(v8::Exception::Error(v8::String::New(string))); \
+ return v8::Handle<v8::Value>(); \
+}
+
+class QV8Engine;
+class QV8ObjectResource : public v8::Object::ExternalResource
+{
+public:
+ QV8ObjectResource(QV8Engine *engine) : engine(engine) { Q_ASSERT(engine); }
+ enum ResourceType { ContextType, QObjectType, TypeType, ListType, VariantType,
+ ValueTypeType, XMLHttpRequestType, DOMNodeType, SQLDatabaseType };
+ virtual ResourceType resourceType() const = 0;
+
+ QV8Engine *engine;
+};
+
+template<class T>
+T *v8_resource_cast(v8::Handle<v8::Object> object) {
+ QV8ObjectResource *resource = static_cast<QV8ObjectResource *>(object->GetExternalResource());
+ return (resource && (quint32)resource->resourceType() == (quint32)T::V8ResourceType)?static_cast<T *>(resource):0;
+}
+
+// Used to allow a QObject method take and return raw V8 handles without having to expose
+// v8 in the public API.
+// Use like this:
+// class MyClass : public QObject {
+// Q_OBJECT
+// ...
+// Q_INVOKABLE void myMethod(QDeclarativeV8Function*);
+// };
+// The QDeclarativeV8Function - and consequently the arguments and return value - only remains
+// valid during the call. If the return value isn't set within myMethod(), the will return
+// undefined.
+class QV8Engine;
+class QDeclarativeV8Function
+{
+public:
+ int Length() const { return _ac; }
+ v8::Local<v8::Value> operator[](int idx) { return (*_a)->Get(idx); }
+ QDeclarativeContextData *context() { return _c; }
+ v8::Handle<v8::Object> qmlGlobal() { return *_g; }
+ void returnValue(v8::Handle<v8::Value> rv) { *_r = rv; }
+ QV8Engine *engine() const { return _e; }
+private:
+ friend class QV8QObjectWrapper;
+ QDeclarativeV8Function();
+ QDeclarativeV8Function(const QDeclarativeV8Function &);
+ QDeclarativeV8Function &operator=(const QDeclarativeV8Function &);
+
+ QDeclarativeV8Function(int length, v8::Handle<v8::Object> &args,
+ v8::Handle<v8::Value> &rv, v8::Handle<v8::Object> &global,
+ QDeclarativeContextData *c, QV8Engine *e)
+ : _ac(length), _a(&args), _r(&rv), _g(&global), _c(c), _e(e) {}
+
+ int _ac;
+ v8::Handle<v8::Object> *_a;
+ v8::Handle<v8::Value> *_r;
+ v8::Handle<v8::Object> *_g;
+ QDeclarativeContextData *_c;
+ QV8Engine *_e;
+};
+
+class QDeclarativeV8Handle
+{
+public:
+ QDeclarativeV8Handle() : d(0) {}
+ QDeclarativeV8Handle(const QDeclarativeV8Handle &other) : d(other.d) {}
+ QDeclarativeV8Handle &operator=(const QDeclarativeV8Handle &other) { d = other.d; return *this; }
+
+ static QDeclarativeV8Handle fromHandle(v8::Handle<v8::Value> h) {
+ return reinterpret_cast<QDeclarativeV8Handle &>(h);
+ }
+ v8::Handle<v8::Value> toHandle() const {
+ return reinterpret_cast<const v8::Handle<v8::Value> &>(*this);
+ }
+private:
+ void *d;
+};
+
+class QObject;
+class QDeclarativeEngine;
+class QDeclarativeValueType;
+class QNetworkAccessManager;
+class QDeclarativeContextData;
+class Q_AUTOTEST_EXPORT QV8Engine
+{
+public:
+ QV8Engine();
+ ~QV8Engine();
+
+ void init(QDeclarativeEngine *);
+
+ QDeclarativeEngine *engine() { return m_engine; }
+ v8::Local<v8::Object> global() { return m_context->Global(); }
+ v8::Handle<v8::Context> context() { return m_context; }
+ QV8ContextWrapper *contextWrapper() { return &m_contextWrapper; }
+ QV8QObjectWrapper *qobjectWrapper() { return &m_qobjectWrapper; }
+ QV8TypeWrapper *typeWrapper() { return &m_typeWrapper; }
+ QV8ListWrapper *listWrapper() { return &m_listWrapper; }
+ QV8VariantWrapper *variantWrapper() { return &m_variantWrapper; }
+
+ void *xmlHttpRequestData() { return m_xmlHttpRequestData; }
+ void *sqlDatabaseData() { return m_sqlDatabaseData; }
+
+ QDeclarativeContextData *callingContext();
+
+ v8::Local<v8::Array> getOwnPropertyNames(v8::Handle<v8::Object>);
+
+ inline QString toString(v8::Handle<v8::Value> string);
+ inline QString toString(v8::Handle<v8::String> string);
+ static QString toStringStatic(v8::Handle<v8::Value>);
+ static QString toStringStatic(v8::Handle<v8::String>);
+ static inline bool startsWithUpper(v8::Handle<v8::String>);
+
+ QVariant toVariant(v8::Handle<v8::Value>, int typeHint);
+ v8::Handle<v8::Value> fromVariant(const QVariant &);
+ inline bool isVariant(v8::Handle<v8::Value>);
+
+ // Compile \a source (from \a fileName at \a lineNumber) in QML mode
+ v8::Local<v8::Script> qmlModeCompile(const QString &source,
+ const QString &fileName = QString(),
+ int lineNumber = 1);
+
+ // Return the QML global "scope" object for the \a ctxt context and \a scope object.
+ inline v8::Local<v8::Object> qmlScope(QDeclarativeContextData *ctxt, QObject *scope);
+
+ // Return a JS wrapper for the given QObject \a object
+ inline v8::Handle<v8::Value> newQObject(QObject *object);
+ inline bool isQObject(v8::Handle<v8::Value>);
+ inline QObject *toQObject(v8::Handle<v8::Value>);
+
+ // Return a JS string for the given QString \a string
+ inline v8::Local<v8::String> toString(const QString &string);
+
+ // Create a new value type object
+ inline v8::Handle<v8::Value> newValueType(QObject *, int coreIndex, QDeclarativeValueType *);
+ inline v8::Handle<v8::Value> newValueType(const QVariant &, QDeclarativeValueType *);
+
+ // Create a new QVariant object. This doesn't examine the type of the variant, but always returns
+ // a QVariant wrapper
+ inline v8::Handle<v8::Value> newQVariant(const QVariant &);
+
+ // Return the network access manager for this engine. By default this returns the network
+ // access manager of the QDeclarativeEngine. It is overridden in the case of a threaded v8
+ // instance (like in WorkerScript).
+ virtual QNetworkAccessManager *networkAccessManager();
+
+ // Return the list of illegal id names (the names of the properties on the global object)
+ const QSet<QString> &illegalNames() const;
+
+private:
+ QDeclarativeEngine *m_engine;
+ v8::Persistent<v8::Context> m_context;
+
+ QV8StringWrapper m_stringWrapper;
+ QV8ContextWrapper m_contextWrapper;
+ QV8QObjectWrapper m_qobjectWrapper;
+ QV8TypeWrapper m_typeWrapper;
+ QV8ListWrapper m_listWrapper;
+ QV8VariantWrapper m_variantWrapper;
+ QV8ValueTypeWrapper m_valueTypeWrapper;
+
+ v8::Persistent<v8::Function> m_getOwnPropertyNames;
+
+ void *m_xmlHttpRequestData;
+ void *m_sqlDatabaseData;
+
+ QSet<QString> m_illegalNames;
+
+ QVariant toBasicVariant(v8::Handle<v8::Value>);
+
+ void initializeGlobal(v8::Handle<v8::Object>);
+ void freezeGlobal();
+
+ static v8::Handle<v8::Value> print(const v8::Arguments &args);
+ static v8::Handle<v8::Value> isQtObject(const v8::Arguments &args);
+ static v8::Handle<v8::Value> rgba(const v8::Arguments &args);
+ static v8::Handle<v8::Value> hsla(const v8::Arguments &args);
+ static v8::Handle<v8::Value> rect(const v8::Arguments &args);
+ static v8::Handle<v8::Value> point(const v8::Arguments &args);
+ static v8::Handle<v8::Value> size(const v8::Arguments &args);
+ static v8::Handle<v8::Value> vector3d(const v8::Arguments &args);
+ static v8::Handle<v8::Value> lighter(const v8::Arguments &args);
+ static v8::Handle<v8::Value> darker(const v8::Arguments &args);
+ static v8::Handle<v8::Value> tint(const v8::Arguments &args);
+ static v8::Handle<v8::Value> formatDate(const v8::Arguments &args);
+ static v8::Handle<v8::Value> formatTime(const v8::Arguments &args);
+ static v8::Handle<v8::Value> formatDateTime(const v8::Arguments &args);
+ static v8::Handle<v8::Value> openUrlExternally(const v8::Arguments &args);
+ static v8::Handle<v8::Value> fontFamilies(const v8::Arguments &args);
+ static v8::Handle<v8::Value> md5(const v8::Arguments &args);
+ static v8::Handle<v8::Value> btoa(const v8::Arguments &args);
+ static v8::Handle<v8::Value> atob(const v8::Arguments &args);
+ static v8::Handle<v8::Value> quit(const v8::Arguments &args);
+ static v8::Handle<v8::Value> resolvedUrl(const v8::Arguments &args);
+ static v8::Handle<v8::Value> createQmlObject(const v8::Arguments &args);
+ static v8::Handle<v8::Value> createComponent(const v8::Arguments &args);
+
+ double qtDateTimeToJsDate(const QDateTime &dt);
+ QDateTime qtDateTimeFromJsDate(double jsDate);
+};
+
+QString QV8Engine::toString(v8::Handle<v8::Value> string)
+{
+ return m_stringWrapper.toString(string->ToString());
+}
+
+QString QV8Engine::toString(v8::Handle<v8::String> string)
+{
+ return m_stringWrapper.toString(string);
+}
+
+bool QV8Engine::isVariant(v8::Handle<v8::Value> value)
+{
+ return m_variantWrapper.isVariant(value);
+}
+
+v8::Local<v8::Object> QV8Engine::qmlScope(QDeclarativeContextData *ctxt, QObject *scope)
+{
+ return m_contextWrapper.qmlScope(ctxt, scope);
+}
+
+bool QV8Engine::isQObject(v8::Handle<v8::Value> obj)
+{
+ return obj->IsObject()?m_qobjectWrapper.isQObject(v8::Handle<v8::Object>::Cast(obj)):false;
+}
+
+QObject *QV8Engine::toQObject(v8::Handle<v8::Value> obj)
+{
+ return obj->IsObject()?m_qobjectWrapper.toQObject(v8::Handle<v8::Object>::Cast(obj)):0;
+}
+
+v8::Handle<v8::Value> QV8Engine::newQObject(QObject *object)
+{
+ return m_qobjectWrapper.newQObject(object);
+}
+
+v8::Local<v8::String> QV8Engine::toString(const QString &string)
+{
+ return m_stringWrapper.toString(string);
+}
+
+v8::Handle<v8::Value> QV8Engine::newValueType(QObject *object, int property, QDeclarativeValueType *type)
+{
+ return m_valueTypeWrapper.newValueType(object, property, type);
+}
+
+v8::Handle<v8::Value> QV8Engine::newValueType(const QVariant &value, QDeclarativeValueType *type)
+{
+ return m_valueTypeWrapper.newValueType(value, type);
+}
+
+// XXX perf?
+bool QV8Engine::startsWithUpper(v8::Handle<v8::String> string)
+{
+ uint16_t buffer[2];
+ int written = string->Write(buffer, 0, 1);
+ if (written == 0) return false;
+ uint16_t c = buffer[0];
+ return ((c != '_' ) && (!(c >= 'a' && c <= 'z')) &&
+ ((c >= 'A' && c <= 'Z') || QChar::category(c) == QChar::Letter_Uppercase));
+}
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEV8ENGINE_P_H
diff --git a/src/declarative/qml/v8/qv8include.cpp b/src/declarative/qml/v8/qv8include.cpp
new file mode 100644
index 0000000000..f2b25e0a92
--- /dev/null
+++ b/src/declarative/qml/v8/qv8include.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** 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 "qv8include_p.h"
+
+#include <QtScript/qscriptengine.h>
+#include <QtNetwork/qnetworkrequest.h>
+#include <QtNetwork/qnetworkreply.h>
+#include <QtCore/qfile.h>
+
+#include <private/qdeclarativeengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+QV8Include::QV8Include(const QUrl &url, QV8Engine *engine, QDeclarativeContextData *context,
+ v8::Handle<v8::Object> qmlglobal, v8::Handle<v8::Function> callback)
+: m_engine(engine), m_network(0), m_reply(0), m_url(url), m_redirectCount(0), m_context(context)
+{
+ m_qmlglobal = v8::Persistent<v8::Object>::New(qmlglobal);
+ if (!callback.IsEmpty())
+ m_callbackFunction = v8::Persistent<v8::Function>::New(callback);
+
+ m_resultObject = v8::Persistent<v8::Object>::New(resultValue());
+
+ m_network = engine->networkAccessManager();
+
+ QNetworkRequest request;
+ request.setUrl(url);
+
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+}
+
+QV8Include::~QV8Include()
+{
+ delete m_reply; m_reply = 0;
+ m_callbackFunction.Dispose();
+ m_resultObject.Dispose();
+}
+
+v8::Local<v8::Object> QV8Include::resultValue(Status status)
+{
+ // XXX aakenned inefficient
+ v8::Local<v8::Object> result = v8::Object::New();
+ result->Set(v8::String::New("OK"), v8::Integer::New(Ok));
+ result->Set(v8::String::New("LOADING"), v8::Integer::New(Loading));
+ result->Set(v8::String::New("NETWORK_ERROR"), v8::Integer::New(NetworkError));
+ result->Set(v8::String::New("EXCEPTION"), v8::Integer::New(Exception));
+
+ result->Set(v8::String::New("status"), v8::Integer::New(status));
+
+ return result;
+}
+
+void QV8Include::callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status)
+{
+ if (!callback.IsEmpty()) {
+ v8::Handle<v8::Value> args[] = { status };
+ // XXX TryCatch?
+ callback->Call(engine->global(), 1, args);
+ }
+}
+
+v8::Handle<v8::Object> QV8Include::result()
+{
+ return m_resultObject;
+}
+
+#define INCLUDE_MAXIMUM_REDIRECT_RECURSION 15
+void QV8Include::finished()
+{
+ m_redirectCount++;
+
+ if (m_redirectCount < INCLUDE_MAXIMUM_REDIRECT_RECURSION) {
+ QVariant redirect = m_reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
+ if (redirect.isValid()) {
+ m_url = m_url.resolved(redirect.toUrl());
+ delete m_reply;
+
+ QNetworkRequest request;
+ request.setUrl(m_url);
+
+ m_reply = m_network->get(request);
+ QObject::connect(m_reply, SIGNAL(finished()), this, SLOT(finished()));
+ return;
+ }
+ }
+
+ v8::HandleScope handle_scope;
+
+ if (m_reply->error() == QNetworkReply::NoError) {
+ QByteArray data = m_reply->readAll();
+
+ QString code = QString::fromUtf8(data);
+ QDeclarativeScriptParser::extractPragmas(code);
+
+ QDeclarativeContextData *importContext = new QDeclarativeContextData;
+ importContext->isInternal = true;
+ importContext->isJSContext = true;
+ importContext->url = m_url;
+ importContext->setParent(m_context, true);
+
+ v8::Context::Scope ctxtscope(m_engine->context());
+ v8::TryCatch try_catch;
+
+ v8::Local<v8::Script> script = m_engine->qmlModeCompile(code, m_url.toString());
+
+ if (!try_catch.HasCaught()) {
+ m_engine->contextWrapper()->addSubContext(m_qmlglobal, script, importContext);
+ script->Run(m_qmlglobal);
+ }
+
+ if (try_catch.HasCaught()) {
+ m_resultObject->Set(v8::String::New("status"), v8::Integer::New(Exception));
+ m_resultObject->Set(v8::String::New("exception"), try_catch.Exception());
+ } else {
+ m_resultObject->Set(v8::String::New("status"), v8::Integer::New(Ok));
+ }
+ } else {
+ m_resultObject->Set(v8::String::New("status"), v8::Integer::New(NetworkError));
+ }
+
+ callback(m_engine, m_callbackFunction, m_resultObject);
+
+ disconnect();
+ deleteLater();
+}
+
+/*
+ Documented in qv8engine.cpp
+*/
+v8::Handle<v8::Value> QV8Include::include(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ return v8::Undefined();
+
+ QV8Engine *engine = V8ENGINE();
+ QDeclarativeContextData *context = engine->callingContext();
+
+ if (!context || !context->isJSContext)
+ V8THROW_ERROR("Qt.include(): Can only be called from JavaScript files");
+
+ QUrl url(context->resolvedUrl(QUrl(engine->toString(args[0]->ToString()))));
+
+ v8::Local<v8::Function> callbackFunction;
+ if (args.Length() >= 2 && args[1]->IsFunction())
+ callbackFunction = v8::Local<v8::Function>::Cast(args[1]);
+
+ QString localFile = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(url);
+
+ v8::Local<v8::Object> result;
+
+ if (localFile.isEmpty()) {
+
+ QV8Include *i = new QV8Include(url, engine, context,
+ v8::Context::GetCallingQmlGlobal(),
+ callbackFunction);
+ result = v8::Local<v8::Object>::New(i->result());
+
+ } else {
+
+ QFile f(localFile);
+
+ if (f.open(QIODevice::ReadOnly)) {
+ QByteArray data = f.readAll();
+ QString code = QString::fromUtf8(data);
+ QDeclarativeScriptParser::extractPragmas(code);
+
+ QDeclarativeContextData *importContext = new QDeclarativeContextData;
+ importContext->isInternal = true;
+ importContext->isJSContext = true;
+ importContext->url = url;
+ importContext->setParent(context, true);
+
+ v8::TryCatch try_catch;
+
+ v8::Local<v8::Script> script = engine->qmlModeCompile(code, url.toString());
+
+ if (!try_catch.HasCaught()) {
+ v8::Local<v8::Object> qmlglobal = v8::Context::GetCallingQmlGlobal();
+ engine->contextWrapper()->addSubContext(qmlglobal, script, importContext);
+ script->Run(qmlglobal);
+ }
+
+ if (try_catch.HasCaught()) {
+ result = resultValue(Exception);
+ result->Set(v8::String::New("exception"), try_catch.Exception());
+ } else {
+ result = resultValue(Ok);
+ }
+
+ } else {
+ result = resultValue(NetworkError);
+ }
+
+ callback(engine, callbackFunction, result);
+ }
+
+ if (result.IsEmpty())
+ return v8::Undefined();
+ else
+ return result;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeinclude_p.h b/src/declarative/qml/v8/qv8include_p.h
index e56de79058..76997ba649 100644
--- a/src/declarative/qml/qdeclarativeinclude_p.h
+++ b/src/declarative/qml/v8/qv8include_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEINCLUDE_P_H
-#define QDECLARATIVEINCLUDE_P_H
+#ifndef QV8INCLUDE_P_H
+#define QV8INCLUDE_P_H
//
// W A R N I N G
@@ -55,19 +55,19 @@
#include <QtCore/qobject.h>
#include <QtCore/qurl.h>
-#include <QtScript/qscriptvalue.h>
#include <private/qdeclarativecontext_p.h>
#include <private/qdeclarativeguard_p.h>
+#include <private/qv8_p.h>
+
QT_BEGIN_NAMESPACE
class QDeclarativeEngine;
-class QScriptContext;
-class QScriptEngine;
class QNetworkAccessManager;
class QNetworkReply;
-class QDeclarativeInclude : public QObject
+class QV8Engine;
+class QV8Include : public QObject
{
Q_OBJECT
public:
@@ -78,38 +78,36 @@ public:
Exception = 3
};
- QDeclarativeInclude(const QUrl &, QDeclarativeEngine *, QScriptContext *ctxt);
- ~QDeclarativeInclude();
-
- void setCallback(const QScriptValue &);
- QScriptValue callback() const;
+ static v8::Handle<v8::Value> include(const v8::Arguments &args);
- QScriptValue result() const;
+private slots:
+ void finished();
- static QScriptValue resultValue(QScriptEngine *, Status status = Loading);
- static void callback(QScriptEngine *, QScriptValue &callback, QScriptValue &status);
+private:
+ QV8Include(const QUrl &, QV8Engine *, QDeclarativeContextData *,
+ v8::Handle<v8::Object>, v8::Handle<v8::Function>);
+ ~QV8Include();
- static QScriptValue include(QScriptContext *ctxt, QScriptEngine *engine);
- static QScriptValue worker_include(QScriptContext *ctxt, QScriptEngine *engine);
+ v8::Handle<v8::Object> result();
-public slots:
- void finished();
+ static v8::Local<v8::Object> resultValue(Status status = Loading);
+ static void callback(QV8Engine *engine, v8::Handle<v8::Function> callback, v8::Handle<v8::Object> status);
-private:
- QDeclarativeEngine *m_engine;
- QScriptEngine *m_scriptEngine;
+ QV8Engine *m_engine;
QNetworkAccessManager *m_network;
QDeclarativeGuard<QNetworkReply> m_reply;
QUrl m_url;
int m_redirectCount;
- QScriptValue m_callback;
- QScriptValue m_result;
+
+ v8::Persistent<v8::Function> m_callbackFunction;
+ v8::Persistent<v8::Object> m_resultObject;
+
QDeclarativeGuardedContextData m_context;
- QScriptValue m_scope[2];
+ v8::Persistent<v8::Object> m_qmlglobal;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVEINCLUDE_P_H
+#endif // QV8INCLUDE_P_H
diff --git a/src/declarative/qml/v8/qv8listwrapper.cpp b/src/declarative/qml/v8/qv8listwrapper.cpp
new file mode 100644
index 0000000000..9e1110fd85
--- /dev/null
+++ b/src/declarative/qml/v8/qv8listwrapper.cpp
@@ -0,0 +1,178 @@
+/****************************************************************************
+**
+** 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 "qv8listwrapper_p.h"
+#include "qv8engine_p.h"
+#include <private/qdeclarativelist_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8ListResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(ListType);
+public:
+ QV8ListResource(QV8Engine *engine) : QV8ObjectResource(engine) {}
+
+ QDeclarativeGuard<QObject> object;
+ QDeclarativeListProperty<QObject> property;
+ int propertyType;
+};
+
+QV8ListWrapper::QV8ListWrapper()
+: m_engine(0)
+{
+}
+
+QV8ListWrapper::~QV8ListWrapper()
+{
+}
+
+void QV8ListWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetIndexedPropertyHandler(IndexedGetter);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("length"), LengthGetter, 0,
+ v8::Handle<v8::Value>(), v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+}
+
+void QV8ListWrapper::destroy()
+{
+ m_constructor.Dispose();
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::newList(QObject *object, int propId, int propType)
+{
+ if (!object || propId == -1)
+ return v8::Null();
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ListResource *r = new QV8ListResource(m_engine);
+ r->object = object;
+ r->propertyType = propType;
+ void *args[] = { &r->property, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, propId, args);
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::newList(const QDeclarativeListProperty<QObject> &prop, int propType)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ListResource *r = new QV8ListResource(m_engine);
+ r->object = prop.object;
+ r->property = prop;
+ r->propertyType = propType;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+QVariant QV8ListWrapper::toVariant(v8::Handle<v8::Object> obj)
+{
+ QV8ListResource *resource = v8_resource_cast<QV8ListResource>(obj);
+ if (resource) return toVariant(resource);
+ else return QVariant();
+}
+
+QVariant QV8ListWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::ListType);
+ QV8ListResource *resource = static_cast<QV8ListResource *>(r);
+
+ if (!resource->object)
+ return QVariant();
+
+ return QVariant::fromValue(QDeclarativeListReferencePrivate::init(resource->property, resource->propertyType,
+ m_engine->engine()));
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ Q_UNUSED(info);
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ Q_UNUSED(info);
+ return value;
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::IndexedGetter(uint32_t index, const v8::AccessorInfo &info)
+{
+ QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This());
+
+ if (!resource || resource->object.isNull()) return v8::Undefined();
+
+ quint32 count = resource->property.count?resource->property.count(&resource->property):0;
+ if (index < count && resource->property.at) {
+ return resource->engine->newQObject(resource->property.at(&resource->property, index));
+ } else {
+ return v8::Undefined();
+ }
+}
+
+v8::Handle<v8::Value> QV8ListWrapper::LengthGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+
+ QV8ListResource *resource = v8_resource_cast<QV8ListResource>(info.This());
+
+ if (!resource || resource->object.isNull()) return v8::Undefined();
+
+ quint32 count = resource->property.count?resource->property.count(&resource->property):0;
+
+ return v8::Integer::NewFromUnsigned(count);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8listwrapper_p.h b/src/declarative/qml/v8/qv8listwrapper_p.h
new file mode 100644
index 0000000000..82fdaa7271
--- /dev/null
+++ b/src/declarative/qml/v8/qv8listwrapper_p.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QV8LISTWRAPPER_P_H
+#define QV8LISTWRAPPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtDeclarative/qdeclarativelist.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8Engine;
+class QV8ObjectResource;
+class QV8ListWrapper
+{
+public:
+ QV8ListWrapper();
+ ~QV8ListWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
+
+ v8::Handle<v8::Value> newList(QObject *, int, int);
+ v8::Handle<v8::Value> newList(const QDeclarativeListProperty<QObject> &, int);
+ QVariant toVariant(v8::Handle<v8::Object>);
+ QVariant toVariant(QV8ObjectResource *);
+
+private:
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> IndexedGetter(uint32_t index,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> LengthGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8LISTWRAPPER_P_H
+
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper.cpp b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
new file mode 100644
index 0000000000..99cede2072
--- /dev/null
+++ b/src/declarative/qml/v8/qv8qobjectwrapper.cpp
@@ -0,0 +1,1714 @@
+/****************************************************************************
+**
+** 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 "qv8qobjectwrapper_p.h"
+#include "qv8contextwrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativeguard_p.h>
+#include <private/qdeclarativepropertycache_p.h>
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativevmemetaobject_p.h>
+#include <private/qdeclarativebinding_p.h>
+
+#include <QtScript/qscriptvalue.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_METATYPE(QScriptValue);
+Q_DECLARE_METATYPE(QDeclarativeV8Handle);
+
+#if defined(__GNUC__)
+# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 405
+// The code in this file does not violate strict aliasing, but GCC thinks it does
+// so turn off the warnings for us to have a clean build
+# pragma GCC diagnostic ignored "-Wstrict-aliasing"
+# endif
+#endif
+
+#define QOBJECT_TOSTRING_INDEX -2
+#define QOBJECT_DESTROY_INDEX -3
+
+class QV8QObjectResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(QObjectType);
+
+public:
+ QV8QObjectResource(QV8Engine *engine, QObject *object);
+
+ QDeclarativeGuard<QObject> object;
+};
+
+namespace {
+struct MetaCallArgument {
+ inline MetaCallArgument();
+ inline ~MetaCallArgument();
+ inline void *dataPtr();
+
+ inline void initAsType(int type);
+ inline void fromValue(int type, QV8Engine *, v8::Handle<v8::Value>);
+ inline v8::Handle<v8::Value> toValue(QV8Engine *);
+
+private:
+ MetaCallArgument(const MetaCallArgument &);
+
+ inline void cleanup();
+
+ char data[4 * sizeof(void *)];
+ int type;
+ bool isObjectType;
+};
+}
+
+QV8QObjectResource::QV8QObjectResource(QV8Engine *engine, QObject *object)
+: QV8ObjectResource(engine), object(object)
+{
+}
+
+QV8QObjectWrapper::QV8QObjectWrapper()
+: m_engine(0)
+{
+}
+
+QV8QObjectWrapper::~QV8QObjectWrapper()
+{
+}
+
+void QV8QObjectWrapper::destroy()
+{
+ qDeleteAll(m_connections);
+ m_connections.clear();
+
+ m_hiddenObject.Dispose();
+ m_destroySymbol.Dispose();
+ m_toStringSymbol.Dispose();
+ m_methodConstructor.Dispose();
+ m_constructor.Dispose();
+}
+
+#define FAST_VALUE_GETTER(name, cpptype, defaultvalue, constructor) \
+static v8::Handle<v8::Value> name ## ValueGetter(v8::Local<v8::String>, const v8::AccessorInfo &info) \
+{ \
+ v8::Handle<v8::Object> This = info.This(); \
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(This); \
+ \
+ if (!resource || resource->object.isNull()) return v8::Undefined(); \
+ \
+ QObject *object = resource->object; \
+ \
+ uint32_t data = info.Data()->Uint32Value(); \
+ int index = data & 0x7FFF; \
+ int notify = (data & 0x7FFF0000) >> 16; \
+ if (notify == 0x7FFF) notify = -1; \
+ \
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine()); \
+ if (notify /* 0 means constant */ && ep->captureProperties) { \
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty; \
+ ep->capturedProperties << CapturedProperty(object, index, notify); \
+ } \
+ \
+ cpptype value = defaultvalue; \
+ void *args[] = { &value, 0 }; \
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, index, args); \
+ \
+ return constructor(value); \
+}
+
+#define CREATE_FUNCTION \
+ "(function(method) { "\
+ "return (function(object, data, qmlglobal) { "\
+ "return (function() { "\
+ "return method(object, data, qmlglobal, arguments.length, arguments); "\
+ "});"\
+ "});"\
+ "})"
+
+void QV8QObjectWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+
+ m_toStringSymbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("toString"));
+ m_destroySymbol = v8::Persistent<v8::String>::New(v8::String::NewSymbol("destroy"));
+ m_hiddenObject = v8::Persistent<v8::Object>::New(v8::Object::New());
+
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter, Query, 0, Enumerator);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ v8::ScriptOrigin origin(m_hiddenObject); // Hack to allow us to identify these functions
+ v8::Local<v8::Script> script = v8::Script::New(v8::String::New(CREATE_FUNCTION), &origin);
+ v8::Local<v8::Function> fn = v8::Local<v8::Function>::Cast(script->Run());
+ v8::Handle<v8::Value> invokeFn = v8::FunctionTemplate::New(Invoke)->GetFunction();
+ v8::Handle<v8::Value> args[] = { invokeFn };
+ v8::Local<v8::Function> createFn = v8::Local<v8::Function>::Cast(fn->Call(engine->global(), 1, args));
+ m_methodConstructor = v8::Persistent<v8::Function>::New(createFn);
+ }
+
+ {
+ v8::Local<v8::Object> prototype = engine->global()->Get(v8::String::New("Function"))->ToObject()->Get(v8::String::New("prototype"))->ToObject();
+ prototype->Set(v8::String::New("connect"), V8FUNCTION(Connect, engine));
+ prototype->Set(v8::String::New("disconnect"), V8FUNCTION(Disconnect, engine));
+ }
+}
+
+bool QV8QObjectWrapper::isQObject(v8::Handle<v8::Object> obj)
+{
+ return v8_resource_cast<QV8QObjectResource>(obj) != 0;
+}
+
+QObject *QV8QObjectWrapper::toQObject(v8::Handle<v8::Object> obj)
+{
+ QV8QObjectResource *r = v8_resource_cast<QV8QObjectResource>(obj);
+ return r?r->object:0;
+}
+
+// r *MUST* be a QV8ObjectResource (r->type() == QV8ObjectResource::QObjectType)
+QObject *QV8QObjectWrapper::QV8QObjectWrapper::toQObject(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::QObjectType);
+ return static_cast<QV8QObjectResource *>(r)->object;
+}
+
+// Load value properties
+static v8::Handle<v8::Value> LoadProperty(QV8Engine *engine, QObject *object,
+ const QDeclarativePropertyCache::Data &property)
+{
+ Q_ASSERT(!property.isFunction());
+
+#define PROPERTY_LOAD(metatype, cpptype, constructor) \
+ if (property.propType == QMetaType:: metatype) { \
+ cpptype type = cpptype(); \
+ void *args[] = { &type, 0 }; \
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args); \
+ return constructor(type); \
+ }
+
+ if (property.isQObject()) {
+ QObject *rv = 0;
+ void *args[] = { &rv, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+ return engine->newQObject(rv);
+ } else if (property.isQList()) {
+ return engine->listWrapper()->newList(object, property.coreIndex, property.propType);
+ } else PROPERTY_LOAD(QReal, qreal, v8::Number::New)
+ else PROPERTY_LOAD(Int || property.isEnum(), int, v8::Number::New)
+ else PROPERTY_LOAD(Bool, bool, v8::Boolean::New)
+ else PROPERTY_LOAD(QString, QString, engine->toString)
+ else PROPERTY_LOAD(UInt, uint, v8::Integer::NewFromUnsigned)
+ else PROPERTY_LOAD(Float, float, v8::Number::New)
+ else PROPERTY_LOAD(Double, double, v8::Number::New)
+ else if(property.isV8Handle()) {
+ QDeclarativeV8Handle handle;
+ void *args[] = { &handle, 0 };
+ QMetaObject::metacall(object, QMetaObject::ReadProperty, property.coreIndex, args);
+ return reinterpret_cast<v8::Handle<v8::Value> &>(handle);
+ } else if (QDeclarativeValueTypeFactory::isValueType((uint)property.propType)) {
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QDeclarativeValueType *valueType = ep->valueTypes[property.propType];
+ if (valueType)
+ return engine->newValueType(object, property.coreIndex, valueType);
+ }
+
+ QVariant var = object->metaObject()->property(property.coreIndex).read(object);
+ return engine->fromVariant(var);
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::GetProperty(QV8Engine *engine, QObject *object,
+ v8::Handle<v8::Value> *objectHandle,
+ v8::Handle<v8::String> property,
+ QV8QObjectWrapper::RevisionMode revisionMode)
+{
+ // XXX aakenned This can't possibly be the best solution!!!
+ struct MethodClosure {
+ static v8::Handle<v8::Value> create(QV8Engine *engine, QObject *object,
+ v8::Handle<v8::Value> *objectHandle,
+ int index) {
+ v8::Handle<v8::Value> argv[] = {
+ objectHandle?*objectHandle:engine->newQObject(object),
+ v8::Integer::New(index)
+ };
+ return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 2, argv);
+ }
+ static v8::Handle<v8::Value> createWithGlobal(QV8Engine *engine, QObject *object,
+ v8::Handle<v8::Value> *objectHandle,
+ int index) {
+ v8::Handle<v8::Value> argv[] = {
+ objectHandle?*objectHandle:engine->newQObject(object),
+ v8::Integer::New(index),
+ v8::Context::GetCallingQmlGlobal()
+ };
+ return engine->qobjectWrapper()->m_methodConstructor->Call(engine->global(), 3, argv);
+ }
+ };
+
+ if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property)) {
+ return MethodClosure::create(engine, object, objectHandle, QOBJECT_TOSTRING_INDEX);
+ } else if (engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property)) {
+ return MethodClosure::create(engine, object, objectHandle, QOBJECT_DESTROY_INDEX);
+ }
+
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+
+ if (!result)
+ return v8::Handle<v8::Value>();
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+
+ if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
+ return v8::Handle<v8::Value>();
+ }
+
+ typedef QDeclarativeEnginePrivate::CapturedProperty CapturedProperty;
+
+ if (result->isFunction()) {
+ if (result->flags & QDeclarativePropertyCache::Data::IsVMEFunction) {
+ return ((QDeclarativeVMEMetaObject *)(object->metaObject()))->vmeMethod(result->coreIndex);
+ } else if (result->flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ return MethodClosure::createWithGlobal(engine, object, objectHandle, result->coreIndex);
+ } else {
+ return MethodClosure::create(engine, object, objectHandle, result->coreIndex);
+ }
+ }
+
+ if (ep->captureProperties && !result->isConstant()) {
+ if (result->coreIndex == 0)
+ ep->capturedProperties << CapturedProperty(QDeclarativeData::get(object, true)->objectNameNotifier());
+ else
+ ep->capturedProperties << CapturedProperty(object, result->coreIndex, result->notifyIndex);
+ }
+
+ return LoadProperty(engine, object, *result);
+}
+
+// Setter for writable properties. Shared between the interceptor and fast property accessor
+static inline void StoreProperty(QV8Engine *engine, QObject *object, QDeclarativePropertyCache::Data *property,
+ v8::Handle<v8::Value> value)
+{
+ QDeclarativeBinding *newBinding = 0;
+
+ if (value->IsFunction()) {
+ QDeclarativeContextData *context = engine->callingContext();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+ v8::Local<v8::StackTrace> trace =
+ v8::StackTrace::CurrentStackTrace(1, (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+ v8::StackTrace::kScriptName));
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+ int lineNumber = frame->GetLineNumber();
+ QString url = engine->toString(frame->GetScriptName());
+
+ QDeclarativePropertyCache::ValueTypeData valueTypeData;
+ newBinding = new QDeclarativeBinding(&function, object, context);
+ newBinding->setSourceLocation(url, lineNumber);
+ newBinding->setTarget(QDeclarativePropertyPrivate::restore(*property, valueTypeData, object, context));
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
+ }
+
+ QDeclarativeAbstractBinding *oldBinding =
+ QDeclarativePropertyPrivate::setBinding(object, property->coreIndex, -1, newBinding);
+ if (oldBinding)
+ oldBinding->destroy();
+
+#define PROPERTY_STORE(cpptype, value) \
+ cpptype o = value; \
+ int status = -1; \
+ int flags = 0; \
+ void *argv[] = { &o, 0, &status, &flags }; \
+ QMetaObject::metacall(object, QMetaObject::WriteProperty, property->coreIndex, argv);
+
+
+ if (value->IsNull() && property->isQObject()) {
+ PROPERTY_STORE(QObject*, 0);
+ } else if (value->IsUndefined() && property->isResettable()) {
+ void *a[] = { 0 };
+ QMetaObject::metacall(object, QMetaObject::ResetProperty, property->coreIndex, a);
+ } else if (value->IsUndefined() && property->propType == qMetaTypeId<QVariant>()) {
+ PROPERTY_STORE(QVariant, QVariant());
+ } else if (value->IsUndefined()) {
+ QString error = QLatin1String("Cannot assign [undefined] to ") +
+ QLatin1String(QMetaType::typeName(property->propType));
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ } else if (value->IsFunction()) {
+ // this is handled by the binding creation above
+ } else if (property->propType == QMetaType::Int && value->IsNumber()) {
+ PROPERTY_STORE(int, qRound(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::QReal && value->IsNumber()) {
+ PROPERTY_STORE(qreal, qreal(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::Float && value->IsNumber()) {
+ PROPERTY_STORE(float, float(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::Double && value->IsNumber()) {
+ PROPERTY_STORE(double, double(value->ToNumber()->Value()));
+ } else if (property->propType == QMetaType::QString && value->IsString()) {
+ PROPERTY_STORE(QString, engine->toString(value->ToString()));
+ } else {
+ QVariant v;
+ if (property->isQList())
+ v = engine->toVariant(value, qMetaTypeId<QList<QObject *> >());
+ else
+ v = engine->toVariant(value, property->propType);
+
+ QDeclarativeContextData *context = engine->callingContext();
+
+ if (!QDeclarativePropertyPrivate::write(object, *property, v, context)) {
+ const char *valueType = 0;
+ if (v.userType() == QVariant::Invalid) valueType = "null";
+ else valueType = QMetaType::typeName(v.userType());
+
+ QString error = QLatin1String("Cannot assign ") +
+ QLatin1String(valueType) +
+ QLatin1String(" to ") +
+ QLatin1String(QMetaType::typeName(property->propType));
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ }
+ }
+}
+
+bool QV8QObjectWrapper::SetProperty(QV8Engine *engine, QObject *object, v8::Handle<v8::String> property,
+ v8::Handle<v8::Value> value, QV8QObjectWrapper::RevisionMode revisionMode)
+{
+ if (engine->qobjectWrapper()->m_toStringSymbol->StrictEquals(property) ||
+ engine->qobjectWrapper()->m_destroySymbol->StrictEquals(property))
+ return true;
+
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+
+ if (!result)
+ return false;
+
+ if (revisionMode == QV8QObjectWrapper::CheckRevision && result->revision != 0) {
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ if (ddata && ddata->propertyCache && !ddata->propertyCache->isAllowedInRevision(result))
+ return false;
+ }
+
+ if (!result->isWritable() && !result->isQList()) {
+ QString error = QLatin1String("Cannot assign to read-only property \"") +
+ engine->toString(property) + QLatin1Char('\"');
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return true;
+ }
+
+ StoreProperty(engine, object, result, value);
+
+ return true;
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+ v8::Handle<v8::Value> This = info.This();
+
+ if (!resource || resource->object.isNull()) return v8::Undefined();
+
+ QObject *object = resource->object;
+
+ QV8Engine *v8engine = resource->engine;
+ v8::Handle<v8::Value> result = GetProperty(v8engine, object, &This, property, QV8QObjectWrapper::IgnoreRevision);
+ if (!result.IsEmpty())
+ return result;
+
+ if (QV8Engine::startsWithUpper(property)) {
+ // Check for attached properties
+ QDeclarativeContextData *context = v8engine->callingContext();
+ QDeclarativeTypeNameCache::Data *data = context && (context->imports)?context->imports->data(property):0;
+
+ if (data) {
+ if (data->type) {
+ return v8engine->typeWrapper()->newObject(object, data->type, QV8TypeWrapper::ExcludeEnums);
+ } else if (data->typeNamespace) {
+ return v8engine->typeWrapper()->newObject(object, data->typeNamespace, QV8TypeWrapper::ExcludeEnums);
+ }
+ }
+
+ return v8::Undefined();
+ } else {
+ // XXX throw?
+ return v8::Undefined();
+ }
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return value;
+
+ QObject *object = resource->object;
+
+ QV8Engine *v8engine = resource->engine;
+ bool result = SetProperty(v8engine, object, property, value, QV8QObjectWrapper::IgnoreRevision);
+
+ if (!result) {
+ QString error = QLatin1String("Cannot assign to non-existent property \"") +
+ v8engine->toString(property) + QLatin1Char('\"');
+ v8::ThrowException(v8::Exception::Error(v8engine->toString(error)));
+ return value;
+ }
+
+ return value;
+}
+
+v8::Handle<v8::Integer> QV8QObjectWrapper::Query(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return v8::Handle<v8::Integer>();
+
+ QV8Engine *engine = resource->engine;
+ QObject *object = resource->object;
+
+ QDeclarativePropertyCache::Data local;
+ QDeclarativePropertyCache::Data *result = 0;
+ result = QDeclarativePropertyCache::property(engine->engine(), object, property, local);
+
+ if (!result)
+ return v8::Handle<v8::Integer>();
+ else if (!result->isWritable() && !result->isQList())
+ return v8::Integer::New(v8::ReadOnly | v8::DontDelete);
+ else
+ return v8::Integer::New(v8::DontDelete);
+}
+
+v8::Handle<v8::Array> QV8QObjectWrapper::Enumerator(const v8::AccessorInfo &info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return v8::Array::New();
+
+ QObject *object = resource->object;
+
+ QStringList result;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(resource->engine->engine());
+
+ QDeclarativePropertyCache *cache = 0;
+ QDeclarativeData *ddata = QDeclarativeData::get(object);
+ if (ddata)
+ cache = ddata->propertyCache;
+
+ if (!cache) {
+ cache = ep->cache(object);
+ if (cache) {
+ if (ddata) { cache->addref(); ddata->propertyCache = cache; }
+ } else {
+ // Not cachable - fall back to QMetaObject (eg. dynamic meta object)
+ // XXX QDeclarativeOpenMetaObject has a cache, so this is suboptimal.
+ // XXX This is a workaround for QTBUG-9420.
+ const QMetaObject *mo = object->metaObject();
+ int pc = mo->propertyCount();
+ int po = mo->propertyOffset();
+ for (int i=po; i<pc; ++i)
+ result << QString::fromUtf8(mo->property(i).name());
+ }
+ } else {
+ result = cache->propertyNames();
+ }
+
+ v8::Local<v8::Array> rv = v8::Array::New(result.count());
+
+ for (int ii = 0; ii < result.count(); ++ii)
+ rv->Set(ii, resource->engine->toString(result.at(ii)));
+
+ return rv;
+}
+
+FAST_VALUE_GETTER(QObject, QObject*, 0, resource->engine->newQObject);
+FAST_VALUE_GETTER(Int, int, 0, v8::Integer::New);
+FAST_VALUE_GETTER(Bool, bool, false, v8::Boolean::New);
+FAST_VALUE_GETTER(QString, QString, QString(), resource->engine->toString);
+FAST_VALUE_GETTER(UInt, uint, 0, v8::Integer::NewFromUnsigned);
+FAST_VALUE_GETTER(Float, float, 0, v8::Number::New);
+FAST_VALUE_GETTER(Double, double, 0, v8::Number::New);
+
+static void FastValueSetter(v8::Local<v8::String>, v8::Local<v8::Value> value,
+ const v8::AccessorInfo& info)
+{
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(info.This());
+
+ if (!resource || resource->object.isNull())
+ return;
+
+ QObject *object = resource->object;
+
+ uint32_t data = info.Data()->Uint32Value();
+ int index = data & 0x7FFF; // So that we can use the same data for Setter and Getter
+
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ Q_ASSERT(ddata);
+ Q_ASSERT(ddata->propertyCache);
+
+ QDeclarativePropertyCache::Data *pdata = ddata->propertyCache->property(index);
+ Q_ASSERT(pdata);
+
+ Q_ASSERT(pdata->isWritable() || pdata->isQList());
+
+ StoreProperty(resource->engine, object, pdata, value);
+}
+
+static void WeakQObjectReferenceCallback(v8::Persistent<v8::Value> handle, void *)
+{
+ Q_ASSERT(handle->IsObject());
+
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(handle->ToObject());
+
+ Q_ASSERT(resource);
+
+ QObject *object = resource->object;
+ if (object) {
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ if (ddata) {
+ ddata->v8object.Clear();
+ if (!object->parent() && !ddata->indestructible)
+ object->deleteLater();
+ }
+ }
+
+ // XXX do we want to use the objectDataRefCount to support multiple concurrent engines?
+
+ handle.Dispose();
+}
+
+v8::Local<v8::Object> QDeclarativePropertyCache::newQObject(QObject *object, QV8Engine *engine)
+{
+ Q_ASSERT(object);
+
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+
+ Q_ASSERT(ddata && ddata->propertyCache && ddata->propertyCache == this);
+ Q_ASSERT(ddata->v8object.IsEmpty());
+
+ // Setup constructor
+ if (constructor.IsEmpty()) {
+ v8::Local<v8::FunctionTemplate> ft;
+
+ QString toString = QLatin1String("toString");
+ QString destroy = QLatin1String("destroy");
+
+ // XXX Enables fast property accessors. These more than double the property access
+ // performance, but the cost of setting up this structure hasn't been measured so
+ // its not guarenteed that this is a win overall
+ for (StringCache::ConstIterator iter = stringCache.begin(); iter != stringCache.end(); ++iter) {
+ Data *property = *iter;
+ if (property->isFunction() || !property->isWritable() ||
+ property->coreIndex >= 0x7FFF || property->notifyIndex >= 0x7FFF ||
+ property->coreIndex == 0)
+ continue;
+
+ v8::AccessorGetter fastgetter = 0;
+
+
+ if (property->isQObject())
+ fastgetter = QObjectValueGetter;
+ else if (property->propType == QMetaType::Int || property->isEnum())
+ fastgetter = IntValueGetter;
+ else if (property->propType == QMetaType::Bool)
+ fastgetter = BoolValueGetter;
+ else if (property->propType == QMetaType::QString)
+ fastgetter = QStringValueGetter;
+ else if (property->propType == QMetaType::UInt)
+ fastgetter = UIntValueGetter;
+ else if (property->propType == QMetaType::Float)
+ fastgetter = FloatValueGetter;
+ else if (property->propType == QMetaType::Double)
+ fastgetter = DoubleValueGetter;
+
+ if (fastgetter) {
+ int notifyIndex = property->notifyIndex;
+ if (property->isConstant()) notifyIndex = 0;
+ else if (notifyIndex == -1) notifyIndex = 0x7FFF;
+ uint32_t data = (property->notifyIndex & 0x7FFF) << 16 | property->coreIndex;
+
+ QString name = iter.key();
+ if (name == toString || name == destroy)
+ continue;
+
+ if (ft.IsEmpty()) {
+ ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter,
+ QV8QObjectWrapper::Setter,
+ QV8QObjectWrapper::Query,
+ 0,
+ QV8QObjectWrapper::Enumerator);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ }
+
+ ft->InstanceTemplate()->SetAccessor(engine->toString(name), fastgetter, FastValueSetter,
+ v8::Integer::NewFromUnsigned(data));
+ }
+ }
+
+ if (ft.IsEmpty()) {
+ constructor = v8::Persistent<v8::Function>::New(engine->qobjectWrapper()->m_constructor);
+ } else {
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(QV8QObjectWrapper::Getter,
+ QV8QObjectWrapper::Setter,
+ QV8QObjectWrapper::Query,
+ 0,
+ QV8QObjectWrapper::Enumerator);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ }
+
+ v8::Local<v8::Object> result = constructor->NewInstance();
+ QV8QObjectResource *r = new QV8QObjectResource(engine, object);
+ result->SetExternalResource(r);
+
+ ddata->v8object = v8::Persistent<v8::Object>::New(result);
+ ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ return result;
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::newQObject(QObject *object)
+{
+ // XXX aakenned QDeclarativeObjectScriptClass::newQObject() does a lot more
+
+ if (!object)
+ return v8::Null();
+
+ if (QObjectPrivate::get(object)->wasDeleted)
+ return v8::Undefined();
+
+ QDeclarativeData *ddata = QDeclarativeData::get(object, true);
+
+ if (!ddata)
+ return v8::Undefined();
+
+ if (ddata->v8object.IsEmpty()) {
+
+ if (ddata->propertyCache) {
+ return ddata->propertyCache->newQObject(object, m_engine);
+ }
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8QObjectResource *r = new QV8QObjectResource(m_engine, object);
+ rv->SetExternalResource(r);
+ ddata->v8object = v8::Persistent<v8::Object>::New(rv);
+ }
+
+ // XXX do we have to check that the v8object isn't "owned" by another engine?
+
+ ddata->v8object.MakeWeak(0, WeakQObjectReferenceCallback);
+ return v8::Local<v8::Object>::New(ddata->v8object);
+}
+
+QPair<QObject *, int> QV8QObjectWrapper::ExtractQtMethod(QV8Engine *engine, v8::Handle<v8::Function> function)
+{
+ v8::ScriptOrigin origin = function->GetScriptOrigin();
+ if (origin.ResourceName()->StrictEquals(engine->qobjectWrapper()->m_hiddenObject)) {
+
+ // This is one of our special QObject method wrappers
+ v8::Handle<v8::Value> args[] = { engine->qobjectWrapper()->m_hiddenObject };
+ v8::Local<v8::Value> data = function->Call(engine->global(), 1, args);
+
+ if (data->IsArray()) {
+ v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(data);
+ return qMakePair(engine->toQObject(array->Get(0)), array->Get(1)->Int32Value());
+ }
+
+ // In theory this can't fall through, but I suppose V8 might run out of memory or something
+ }
+
+ return qMakePair((QObject *)0, -1);
+}
+
+struct QV8QObjectConnectionList : public QObject, public QDeclarativeGuard<QObject>
+{
+ QV8QObjectConnectionList(QObject *object, QV8Engine *engine);
+ ~QV8QObjectConnectionList();
+
+ struct Connection {
+ v8::Persistent<v8::Object> thisObject;
+ v8::Persistent<v8::Function> function;
+ };
+
+ QV8Engine *engine;
+
+ typedef QHash<int, QList<Connection> > SlotHash;
+ SlotHash slotHash;
+
+ virtual void objectDestroyed(QObject *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **);
+};
+
+QV8QObjectConnectionList::QV8QObjectConnectionList(QObject *object, QV8Engine *engine)
+: QDeclarativeGuard<QObject>(object), engine(engine)
+{
+}
+
+QV8QObjectConnectionList::~QV8QObjectConnectionList()
+{
+ for (SlotHash::Iterator iter = slotHash.begin(); iter != slotHash.end(); ++iter) {
+ QList<Connection> &connections = *iter;
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ connections[ii].thisObject.Dispose();
+ connections[ii].function.Dispose();
+ }
+ }
+ slotHash.clear();
+}
+
+void QV8QObjectConnectionList::objectDestroyed(QObject *object)
+{
+ engine->qobjectWrapper()->m_connections.remove(object);
+ delete this;
+}
+
+int QV8QObjectConnectionList::qt_metacall(QMetaObject::Call method, int index, void **metaArgs)
+{
+ if (method == QMetaObject::InvokeMetaMethod) {
+ SlotHash::Iterator iter = slotHash.find(index);
+ if (iter == slotHash.end())
+ return -1;
+ QList<Connection> &connections = *iter;
+ if (connections.isEmpty())
+ return -1;
+
+ // XXX optimize
+ QMetaMethod method = data()->metaObject()->method(index);
+ Q_ASSERT(method.methodType() == QMetaMethod::Signal);
+ QList<QByteArray> params = method.parameterTypes();
+
+ v8::HandleScope handle_scope;
+ v8::Context::Scope scope(engine->context());
+
+ QVarLengthArray<v8::Handle<v8::Value> > args(params.count());
+ int argCount = params.count();
+
+ for (int ii = 0; ii < argCount; ++ii) {
+ int type = QMetaType::type(params.at(ii).constData());
+ if (type == qMetaTypeId<QVariant>()) {
+ args[ii] = engine->fromVariant(*((QVariant *)metaArgs[ii + 1]));
+ } else {
+ args[ii] = engine->fromVariant(QVariant(type, metaArgs[ii + 1]));
+ }
+ }
+
+ // XXX what if this list changes or this object is deleted during the calls?
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ Connection &connection = connections[ii];
+ if (connection.thisObject.IsEmpty()) {
+ connection.function->Call(engine->global(), argCount, args.data());
+ } else {
+ connection.function->Call(connection.thisObject, argCount, args.data());
+ }
+ }
+ }
+
+ return -1;
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Connect(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ V8THROW_ERROR("Function.prototype.connect: no arguments given");
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (!args.This()->IsFunction())
+ V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
+
+ QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QObject *signalObject = signalInfo.first;
+ int signalIndex = signalInfo.second;
+
+ if (signalIndex == -1)
+ V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
+
+ if (!signalObject)
+ V8THROW_ERROR("Function.prototype.connect: cannot connect to deleted QObject");
+
+ if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
+ V8THROW_ERROR("Function.prototype.connect: this object is not a signal");
+
+ v8::Local<v8::Value> functionValue;
+ v8::Local<v8::Value> functionThisValue;
+
+ if (args.Length() == 1) {
+ functionValue = args[0];
+ } else {
+ functionThisValue = args[0];
+ functionValue = args[1];
+ }
+
+ if (!functionValue->IsFunction())
+ V8THROW_ERROR("Function.prototype.connect: target is not a function");
+
+ if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
+ V8THROW_ERROR("Function.prototype.connect: target this is not an object");
+
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+ QHash<QObject *, QV8QObjectConnectionList *> &connections = qobjectWrapper->m_connections;
+ QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connections.find(signalObject);
+ if (iter == connections.end())
+ iter = connections.insert(signalObject, new QV8QObjectConnectionList(signalObject, engine));
+
+ QV8QObjectConnectionList *connectionList = *iter;
+ QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex);
+ if (slotIter == connectionList->slotHash.end()) {
+ slotIter = connectionList->slotHash.insert(signalIndex, QList<QV8QObjectConnectionList::Connection>());
+ QMetaObject::connect(signalObject, signalIndex, connectionList, signalIndex);
+ }
+
+ QV8QObjectConnectionList::Connection connection;
+ if (!functionThisValue.IsEmpty())
+ connection.thisObject = v8::Persistent<v8::Object>::New(functionThisValue->ToObject());
+ connection.function = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(functionValue));
+
+ slotIter->append(connection);
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Disconnect(const v8::Arguments &args)
+{
+ if (args.Length() == 0)
+ V8THROW_ERROR("Function.prototype.disconnect: no arguments given");
+
+ QV8Engine *engine = V8ENGINE();
+
+ if (!args.This()->IsFunction())
+ V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+
+ QPair<QObject *, int> signalInfo = ExtractQtMethod(engine, v8::Handle<v8::Function>::Cast(args.This()));
+ QObject *signalObject = signalInfo.first;
+ int signalIndex = signalInfo.second;
+
+ if (signalIndex == -1)
+ V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+
+ if (!signalObject)
+ V8THROW_ERROR("Function.prototype.disconnect: cannot disconnect from deleted QObject");
+
+ if (signalIndex < 0 || signalObject->metaObject()->method(signalIndex).methodType() != QMetaMethod::Signal)
+ V8THROW_ERROR("Function.prototype.disconnect: this object is not a signal");
+
+ v8::Local<v8::Value> functionValue;
+ v8::Local<v8::Value> functionThisValue;
+
+ if (args.Length() == 1) {
+ functionValue = args[0];
+ } else {
+ functionThisValue = args[0];
+ functionValue = args[1];
+ }
+
+ if (!functionValue->IsFunction())
+ V8THROW_ERROR("Function.prototype.disconnect: target is not a function");
+
+ if (!functionThisValue.IsEmpty() && !functionThisValue->IsObject())
+ V8THROW_ERROR("Function.prototype.disconnect: target this is not an object");
+
+ QV8QObjectWrapper *qobjectWrapper = engine->qobjectWrapper();
+ QHash<QObject *, QV8QObjectConnectionList *> &connectionsList = qobjectWrapper->m_connections;
+ QHash<QObject *, QV8QObjectConnectionList *>::Iterator iter = connectionsList.find(signalObject);
+ if (iter == connectionsList.end())
+ return v8::Undefined(); // Nothing to disconnect from
+
+ QV8QObjectConnectionList *connectionList = *iter;
+ QV8QObjectConnectionList::SlotHash::Iterator slotIter = connectionList->slotHash.find(signalIndex);
+ if (slotIter == connectionList->slotHash.end())
+ return v8::Undefined(); // Nothing to disconnect from
+
+ QList<QV8QObjectConnectionList::Connection> &connections = *slotIter;
+
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(functionValue);
+ QPair<QObject *, int> functionData = ExtractQtMethod(engine, function);
+
+ if (functionData.second != -1) {
+ // This is a QObject function wrapper
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ QV8QObjectConnectionList::Connection &connection = connections[ii];
+
+ if (connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() &&
+ (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) {
+
+ QPair<QObject *, int> connectedFunctionData = ExtractQtMethod(engine, connection.function);
+ if (connectedFunctionData == functionData) {
+ // Match!
+ connection.thisObject.Dispose();
+ connection.function.Dispose();
+ connections.removeAt(ii);
+ return v8::Undefined();
+ }
+ }
+ }
+
+ } else {
+ // This is a normal JS function
+ for (int ii = 0; ii < connections.count(); ++ii) {
+ QV8QObjectConnectionList::Connection &connection = connections[ii];
+ if (connection.function->StrictEquals(function) &&
+ connection.thisObject.IsEmpty() == functionThisValue.IsEmpty() &&
+ (connection.thisObject.IsEmpty() || connection.thisObject->StrictEquals(functionThisValue))) {
+ // Match!
+ connection.thisObject.Dispose();
+ connection.function.Dispose();
+ connections.removeAt(ii);
+ return v8::Undefined();
+ }
+ }
+ }
+
+ return v8::Undefined();
+}
+
+/*!
+ Get the \a property of \a object. Returns an empty handle if the property doesn't exist.
+
+ Only searches for real properties of \a object (including methods), not attached properties etc.
+*/
+v8::Handle<v8::Value> QV8QObjectWrapper::getProperty(QObject *object, v8::Handle<v8::String> property,
+ QV8QObjectWrapper::RevisionMode revisionMode)
+{
+ return GetProperty(m_engine, object, 0, property, revisionMode);
+}
+
+/*
+ Set the \a property of \a object to \a value.
+
+ Returns true if the property was "set" - even if this results in an exception being thrown -
+ and false if the object has no such property.
+
+ Only searches for real properties of \a object (including methods), not attached properties etc.
+*/
+bool QV8QObjectWrapper::setProperty(QObject *object, v8::Handle<v8::String> property,
+ v8::Handle<v8::Value> value, RevisionMode revisionMode)
+{
+ return SetProperty(m_engine, object, property, value, revisionMode);
+}
+
+namespace {
+struct CallArgs
+{
+ CallArgs(int length, v8::Handle<v8::Object> *args) : _length(length), _args(args) {}
+ int Length() const { return _length; }
+ v8::Local<v8::Value> operator[](int idx) { return (*_args)->Get(idx); }
+
+private:
+ int _length;
+ v8::Handle<v8::Object> *_args;
+};
+}
+
+static v8::Handle<v8::Value> CallMethod(QObject *object, int index, int returnType, int argCount,
+ int *argTypes, QV8Engine *engine, CallArgs &callArgs)
+{
+ if (argCount > 0) {
+
+ QVarLengthArray<MetaCallArgument, 9> args(argCount + 1);
+ args[0].initAsType(returnType);
+
+ for (int ii = 0; ii < argCount; ++ii)
+ args[ii + 1].fromValue(argTypes[ii], engine, callArgs[ii]);
+
+ QVarLengthArray<void *, 9> argData(args.count());
+ for (int ii = 0; ii < args.count(); ++ii)
+ argData[ii] = args[ii].dataPtr();
+
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, argData.data());
+
+ return args[0].toValue(engine);
+
+ } else if (returnType != 0) {
+
+ MetaCallArgument arg;
+ arg.initAsType(returnType);
+
+ void *args[] = { arg.dataPtr() };
+
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
+
+ return arg.toValue(engine);
+
+ } else {
+
+ void *args[] = { 0 };
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, index, args);
+ return v8::Undefined();
+
+ }
+}
+
+static int EnumType(const QMetaObject *meta, const QString &strname)
+{
+ QByteArray str = strname.toUtf8();
+ QByteArray scope;
+ QByteArray name;
+ int scopeIdx = str.lastIndexOf("::");
+ if (scopeIdx != -1) {
+ scope = str.left(scopeIdx);
+ name = str.mid(scopeIdx + 2);
+ } else {
+ name = str;
+ }
+ for (int i = meta->enumeratorCount() - 1; i >= 0; --i) {
+ QMetaEnum m = meta->enumerator(i);
+ if ((m.name() == name) && (scope.isEmpty() || (m.scope() == scope)))
+ return QVariant::Int;
+ }
+ return QVariant::Invalid;
+}
+
+/*!
+ Returns the match score for converting \a actual to be of type \a conversionType. A
+ zero score means "perfect match" whereas a higher score is worse.
+
+ The conversion table is copied out of the QtScript callQtMethod() function.
+*/
+static int MatchScore(v8::Handle<v8::Value> actual, int conversionType,
+ const QByteArray &conversionTypeName)
+{
+ if (actual->IsNumber()) {
+ switch (conversionType) {
+ case QMetaType::Double:
+ return 0;
+ case QMetaType::Float:
+ return 1;
+ case QMetaType::LongLong:
+ case QMetaType::ULongLong:
+ return 2;
+ case QMetaType::Long:
+ case QMetaType::ULong:
+ return 3;
+ case QMetaType::Int:
+ case QMetaType::UInt:
+ return 4;
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ return 5;
+ break;
+ case QMetaType::Char:
+ case QMetaType::UChar:
+ return 6;
+ default:
+ return 10;
+ }
+ } else if (actual->IsString()) {
+ switch (conversionType) {
+ case QMetaType::QString:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual->IsBoolean()) {
+ switch (conversionType) {
+ case QMetaType::Bool:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual->IsDate()) {
+ switch (conversionType) {
+ case QMetaType::QDateTime:
+ return 0;
+ case QMetaType::QDate:
+ return 1;
+ case QMetaType::QTime:
+ return 2;
+ default:
+ return 10;
+ }
+ } else if (actual->IsRegExp()) {
+ switch (conversionType) {
+ case QMetaType::QRegExp:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (actual->IsArray()) {
+ switch (conversionType) {
+ case QMetaType::QStringList:
+ case QMetaType::QVariantList:
+ return 5;
+ default:
+ return 10;
+ }
+ } else if (actual->IsNull()) {
+ switch (conversionType) {
+ case QMetaType::VoidStar:
+ case QMetaType::QObjectStar:
+ return 0;
+ default:
+ if (!conversionTypeName.endsWith('*'))
+ return 10;
+ else
+ return 0;
+ }
+ } else if (actual->IsObject()) {
+ v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(actual);
+
+ QV8ObjectResource *r = static_cast<QV8ObjectResource *>(obj->GetExternalResource());
+ if (r && r->resourceType() == QV8ObjectResource::QObjectType) {
+ switch (conversionType) {
+ case QMetaType::QObjectStar:
+ return 0;
+ default:
+ return 10;
+ }
+ } else if (r && r->resourceType() == QV8ObjectResource::VariantType) {
+ if (conversionType == qMetaTypeId<QVariant>())
+ return 0;
+ else if (r->engine->toVariant(actual, -1).userType() == conversionType)
+ return 0;
+ else
+ return 10;
+ } else {
+ return 10;
+ }
+
+ } else {
+ return 10;
+ }
+}
+
+static inline int QMetaObject_methods(const QMetaObject *metaObject)
+{
+ struct Private
+ {
+ int revision;
+ int className;
+ int classInfoCount, classInfoData;
+ int methodCount, methodData;
+ };
+
+ return reinterpret_cast<const Private *>(metaObject->d.data)->methodCount;
+}
+
+static QByteArray QMetaMethod_name(const QMetaMethod &m)
+{
+ QByteArray sig = m.signature();
+ int paren = sig.indexOf('(');
+ if (paren == -1)
+ return sig;
+ else
+ return sig.left(paren);
+}
+
+/*!
+Returns the next related method, if one, or 0.
+*/
+static const QDeclarativePropertyCache::Data * RelatedMethod(QObject *object,
+ const QDeclarativePropertyCache::Data *current,
+ QDeclarativePropertyCache::Data &dummy)
+{
+ QDeclarativePropertyCache *cache = QDeclarativeData::get(object)->propertyCache;
+ if (current->relatedIndex == -1)
+ return 0;
+
+ if (cache) {
+ return cache->method(current->relatedIndex);
+ } else {
+ const QMetaObject *mo = object->metaObject();
+ int methodOffset = mo->methodCount() - QMetaObject_methods(mo);
+
+ while (methodOffset > current->relatedIndex) {
+ mo = mo->superClass();
+ methodOffset -= QMetaObject_methods(mo);
+ }
+
+ QMetaMethod method = mo->method(current->relatedIndex);
+ dummy.load(method);
+
+ // Look for overloaded methods
+ QByteArray methodName = QMetaMethod_name(method);
+ for (int ii = current->relatedIndex - 1; ii >= methodOffset; --ii) {
+ if (methodName == QMetaMethod_name(mo->method(ii))) {
+ dummy.relatedIndex = ii;
+ return &dummy;
+ }
+ }
+
+ return &dummy;
+ }
+}
+
+static v8::Handle<v8::Value> CallPrecise(QObject *object, const QDeclarativePropertyCache::Data &data,
+ QV8Engine *engine, CallArgs &callArgs)
+{
+ if (data.flags & QDeclarativePropertyCache::Data::HasArguments) {
+
+ QMetaMethod m = object->metaObject()->method(data.coreIndex);
+ QList<QByteArray> argTypeNames = m.parameterTypes();
+ QVarLengthArray<int, 9> argTypes(argTypeNames.count());
+
+ // ### Cache
+ for (int ii = 0; ii < argTypeNames.count(); ++ii) {
+ argTypes[ii] = QMetaType::type(argTypeNames.at(ii));
+ if (argTypes[ii] == QVariant::Invalid)
+ argTypes[ii] = EnumType(object->metaObject(), QString::fromLatin1(argTypeNames.at(ii)));
+ if (argTypes[ii] == QVariant::Invalid) {
+ QString error = QString::fromLatin1("Unknown method parameter type: %1").arg(QLatin1String(argTypeNames.at(ii)));
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
+ }
+ }
+
+ if (argTypes.count() > callArgs.Length()) {
+ QString error = QLatin1String("Insufficient arguments");
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
+ }
+
+ return CallMethod(object, data.coreIndex, data.propType, argTypes.count(),
+ argTypes.data(), engine, callArgs);
+
+ } else {
+
+ return CallMethod(object, data.coreIndex, data.propType, 0, 0, engine, callArgs);
+
+ }
+}
+
+/*!
+Resolve the overloaded method to call. The algorithm works conceptually like this:
+ 1. Resolve the set of overloads it is *possible* to call.
+ Impossible overloads include those that have too many parameters or have parameters
+ of unknown type.
+ 2. Filter the set of overloads to only contain those with the closest number of
+ parameters.
+ For example, if we are called with 3 parameters and there are 2 overloads that
+ take 2 parameters and one that takes 3, eliminate the 2 parameter overloads.
+ 3. Find the best remaining overload based on its match score.
+ If two or more overloads have the same match score, call the last one. The match
+ score is constructed by adding the matchScore() result for each of the parameters.
+*/
+static v8::Handle<v8::Value> CallOverloaded(QObject *object, const QDeclarativePropertyCache::Data &data,
+ QV8Engine *engine, CallArgs &callArgs)
+{
+ int argumentCount = callArgs.Length();
+
+ const QDeclarativePropertyCache::Data *best = 0;
+ int bestParameterScore = INT_MAX;
+ int bestMatchScore = INT_MAX;
+
+ QDeclarativePropertyCache::Data dummy;
+ const QDeclarativePropertyCache::Data *attempt = &data;
+
+ do {
+ QList<QByteArray> methodArgTypeNames;
+
+ if (attempt->flags & QDeclarativePropertyCache::Data::HasArguments)
+ methodArgTypeNames = object->metaObject()->method(attempt->coreIndex).parameterTypes();
+
+ int methodArgumentCount = methodArgTypeNames.count();
+
+ if (methodArgumentCount > argumentCount)
+ continue; // We don't have sufficient arguments to call this method
+
+ int methodParameterScore = argumentCount - methodArgumentCount;
+ if (methodParameterScore > bestParameterScore)
+ continue; // We already have a better option
+
+ int methodMatchScore = 0;
+ QVarLengthArray<int, 9> methodArgTypes(methodArgumentCount);
+
+ bool unknownArgument = false;
+ for (int ii = 0; ii < methodArgumentCount; ++ii) {
+ methodArgTypes[ii] = QMetaType::type(methodArgTypeNames.at(ii));
+ if (methodArgTypes[ii] == QVariant::Invalid)
+ methodArgTypes[ii] = EnumType(object->metaObject(),
+ QString::fromLatin1(methodArgTypeNames.at(ii)));
+ if (methodArgTypes[ii] == QVariant::Invalid) {
+ unknownArgument = true;
+ break;
+ }
+ methodMatchScore += MatchScore(callArgs[ii], methodArgTypes[ii], methodArgTypeNames.at(ii));
+ }
+ if (unknownArgument)
+ continue; // We don't understand all the parameters
+
+ if (bestParameterScore > methodParameterScore || bestMatchScore > methodMatchScore) {
+ best = attempt;
+ bestParameterScore = methodParameterScore;
+ bestMatchScore = methodMatchScore;
+ }
+
+ if (bestParameterScore == 0 && bestMatchScore == 0)
+ break; // We can't get better than that
+
+ } while((attempt = RelatedMethod(object, attempt, dummy)) != 0);
+
+ if (best) {
+ return CallPrecise(object, *best, engine, callArgs);
+ } else {
+ QString error = QLatin1String("Unable to determine callable overload. Candidates are:");
+ const QDeclarativePropertyCache::Data *candidate = &data;
+ while (candidate) {
+ error += QLatin1String("\n ") +
+ QString::fromUtf8(object->metaObject()->method(candidate->coreIndex).signature());
+ candidate = RelatedMethod(object, candidate, dummy);
+ }
+
+ v8::ThrowException(v8::Exception::Error(engine->toString(error)));
+ return v8::Handle<v8::Value>();
+ }
+}
+
+static v8::Handle<v8::Value> ToString(QV8Engine *engine, QObject *object, int, v8::Handle<v8::Object>)
+{
+ QString result;
+ if (object) {
+ QString objectName = object->objectName();
+
+ result += QString::fromUtf8(object->metaObject()->className());
+ result += QLatin1String("(0x");
+ result += QString::number((quintptr)object,16);
+
+ if (!objectName.isEmpty()) {
+ result += QLatin1String(", \"");
+ result += objectName;
+ result += QLatin1Char('\"');
+ }
+
+ result += QLatin1Char(')');
+ } else {
+ result = QLatin1String("null");
+ }
+
+ return engine->toString(result);
+}
+
+static v8::Handle<v8::Value> Destroy(QV8Engine *, QObject *object, int argCount, v8::Handle<v8::Object> args)
+{
+ QDeclarativeData *ddata = QDeclarativeData::get(object, false);
+ if (!ddata || ddata->indestructible) {
+ const char *error = "Invalid attempt to destroy() an indestructible object";
+ v8::ThrowException(v8::Exception::Error(v8::String::New(error)));
+ return v8::Undefined();
+ }
+
+ int delay = 0;
+ if (argCount > 0)
+ delay = args->Get(0)->Uint32Value();
+
+ if (delay > 0)
+ QTimer::singleShot(delay, object, SLOT(deleteLater()));
+ else
+ object->deleteLater();
+
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8QObjectWrapper::Invoke(const v8::Arguments &args)
+{
+ // object, index, qmlglobal, argCount, args
+ Q_ASSERT(args.Length() == 5);
+ Q_ASSERT(args[0]->IsObject());
+
+ QV8QObjectResource *resource = v8_resource_cast<QV8QObjectResource>(args[0]->ToObject());
+
+ if (!resource)
+ return v8::Undefined();
+
+ int argCount = args[3]->Int32Value();
+ v8::Handle<v8::Object> arguments = v8::Handle<v8::Object>::Cast(args[4]);
+
+ // Special hack to return info about this closure.
+ if (argCount == 1 && arguments->Get(0)->StrictEquals(resource->engine->qobjectWrapper()->m_hiddenObject)) {
+ v8::Local<v8::Array> data = v8::Array::New(2);
+ data->Set(0, args[0]);
+ data->Set(1, args[1]);
+ return data;
+ }
+
+ QObject *object = resource->object;
+ int index = args[1]->Int32Value();
+
+ if (!object)
+ return v8::Undefined();
+
+ if (index < 0) {
+ // Builtin functions
+ if (index == QOBJECT_TOSTRING_INDEX) {
+ return ToString(resource->engine, object, argCount, arguments);
+ } else if (index == QOBJECT_DESTROY_INDEX) {
+ return Destroy(resource->engine, object, argCount, arguments);
+ } else {
+ return v8::Undefined();
+ }
+ }
+
+ QDeclarativePropertyCache::Data method;
+
+ if (QDeclarativeData *ddata = static_cast<QDeclarativeData *>(QObjectPrivate::get(object)->declarativeData)) {
+ if (ddata->propertyCache) {
+ QDeclarativePropertyCache::Data *d = ddata->propertyCache->method(index);
+ if (!d)
+ return v8::Undefined();
+ method = *d;
+ }
+ }
+
+ if (method.coreIndex == -1) {
+ QMetaMethod mm = object->metaObject()->method(index);
+ method.load(object->metaObject()->method(index));
+
+ if (method.coreIndex == -1)
+ return v8::Undefined();
+ }
+
+ if (method.flags & QDeclarativePropertyCache::Data::IsV8Function) {
+ v8::Handle<v8::Value> rv;
+ v8::Handle<v8::Object> qmlglobal = args[2]->ToObject();
+
+ QDeclarativeV8Function func(argCount, arguments, rv, qmlglobal,
+ resource->engine->contextWrapper()->context(qmlglobal),
+ resource->engine);
+ QDeclarativeV8Function *funcptr = &func;
+
+ void *args[] = { 0, &funcptr };
+ QMetaObject::metacall(object, QMetaObject::InvokeMetaMethod, method.coreIndex, args);
+
+ if (rv.IsEmpty()) return v8::Undefined();
+ return rv;
+ }
+
+ CallArgs callArgs(argCount, &arguments);
+ if (method.relatedIndex == -1) {
+ return CallPrecise(object, method, resource->engine, callArgs);
+ } else {
+ return CallOverloaded(object, method, resource->engine, callArgs);
+ }
+}
+
+MetaCallArgument::MetaCallArgument()
+: type(QVariant::Invalid), isObjectType(false)
+{
+}
+
+MetaCallArgument::~MetaCallArgument()
+{
+ cleanup();
+}
+
+void MetaCallArgument::cleanup()
+{
+ if (type == QMetaType::QString) {
+ ((QString *)&data)->~QString();
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ ((QVariant *)&data)->~QVariant();
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ ((QScriptValue *)&data)->~QScriptValue();
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ ((QList<QObject *> *)&data)->~QList<QObject *>();
+ }
+}
+
+void *MetaCallArgument::dataPtr()
+{
+ if (type == -1)
+ return ((QVariant *)data)->data();
+ else
+ return (void *)&data;
+}
+
+void MetaCallArgument::initAsType(int callType)
+{
+ if (type != 0) { cleanup(); type = 0; }
+ if (callType == 0) return;
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (&data) QScriptValue();
+ type = callType;
+ } else if (callType == QMetaType::Int ||
+ callType == QMetaType::UInt ||
+ callType == QMetaType::Bool ||
+ callType == QMetaType::Double ||
+ callType == QMetaType::Float) {
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)&data) = 0;
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ new (&data) QString();
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ type = callType;
+ new (&data) QVariant();
+ } else if (callType == qMetaTypeId<QList<QObject *> >()) {
+ type = callType;
+ new (&data) QList<QObject *>();
+ } else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
+ type = callType;
+ new (&data) v8::Handle<v8::Value>();
+ } else {
+ type = -1;
+ new (&data) QVariant(callType, (void *)0);
+ }
+}
+
+void MetaCallArgument::fromValue(int callType, QV8Engine *engine, v8::Handle<v8::Value> value)
+{
+ if (type != 0) { cleanup(); type = 0; }
+
+ if (callType == qMetaTypeId<QScriptValue>()) {
+ new (&data) QScriptValue();
+ type = qMetaTypeId<QScriptValue>();
+ } else if (callType == QMetaType::Int) {
+ *((int *)&data) = int(value->Int32Value());
+ type = callType;
+ } else if (callType == QMetaType::UInt) {
+ *((uint *)&data) = uint(value->Uint32Value());
+ type = callType;
+ } else if (callType == QMetaType::Bool) {
+ *((bool *)&data) = value->BooleanValue();
+ type = callType;
+ } else if (callType == QMetaType::Double) {
+ *((double *)&data) = double(value->NumberValue());
+ type = callType;
+ } else if (callType == QMetaType::Float) {
+ *((float *)&data) = float(value->NumberValue());
+ type = callType;
+ } else if (callType == QMetaType::QString) {
+ if (value->IsNull() || value->IsUndefined())
+ new (&data) QString();
+ else
+ new (&data) QString(engine->toString(value->ToString()));
+ type = callType;
+ } else if (callType == QMetaType::QObjectStar) {
+ *((QObject **)&data) = engine->toQObject(value);
+ type = callType;
+ } else if (callType == qMetaTypeId<QVariant>()) {
+ new (&data) QVariant(engine->toVariant(value, -1));
+ type = callType;
+ } else if (callType == qMetaTypeId<QList<QObject*> >()) {
+ QList<QObject *> *list = new (&data) QList<QObject *>();
+ if (value->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value);
+ uint32_t length = array->Length();
+ for (uint32_t ii = 0; ii < length; ++ii)
+ list->append(engine->toQObject(array->Get(ii)));
+ } else {
+ list->append(engine->toQObject(value));
+ }
+ type = callType;
+ } else if (callType == qMetaTypeId<QDeclarativeV8Handle>()) {
+ new (&data) v8::Handle<v8::Value>(value);
+ type = callType;
+ } else {
+ new (&data) QVariant();
+ type = -1;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(engine->engine());
+ QVariant v = engine->toVariant(value, -1);
+
+ if (v.userType() == callType) {
+ *((QVariant *)&data) = v;
+ } else if (v.canConvert((QVariant::Type)callType)) {
+ *((QVariant *)&data) = v;
+ ((QVariant *)&data)->convert((QVariant::Type)callType);
+ } else if (const QMetaObject *mo = ep->rawMetaObjectForType(callType)) {
+ QObject *obj = ep->toQObject(v);
+
+ if (obj) {
+ const QMetaObject *objMo = obj->metaObject();
+ while (objMo && objMo != mo) objMo = objMo->superClass();
+ if (!objMo) obj = 0;
+ }
+
+ *((QVariant *)&data) = QVariant(callType, &obj);
+ } else {
+ *((QVariant *)&data) = QVariant(callType, (void *)0);
+ }
+ }
+}
+
+v8::Handle<v8::Value> MetaCallArgument::toValue(QV8Engine *engine)
+{
+ if (type == qMetaTypeId<QScriptValue>()) {
+ return v8::Undefined();
+ } else if (type == QMetaType::Int) {
+ return v8::Integer::New(*((int *)&data));
+ } else if (type == QMetaType::UInt) {
+ return v8::Integer::NewFromUnsigned(*((uint *)&data));
+ } else if (type == QMetaType::Bool) {
+ return v8::Boolean::New(*((bool *)&data));
+ } else if (type == QMetaType::Double) {
+ return v8::Number::New(*((double *)&data));
+ } else if (type == QMetaType::Float) {
+ return v8::Number::New(*((float *)&data));
+ } else if (type == QMetaType::QString) {
+ return engine->toString(*((QString *)&data));
+ } else if (type == QMetaType::QObjectStar) {
+ QObject *object = *((QObject **)&data);
+ if (object)
+ QDeclarativeData::get(object, true)->setImplicitDestructible();
+ return engine->newQObject(object);
+ } else if (type == qMetaTypeId<QList<QObject *> >()) {
+ // XXX aakenned Can this be more optimal? Just use Array as a prototype and
+ // implement directly against QList<QObject*>?
+ QList<QObject *> &list = *(QList<QObject *>*)&data;
+ v8::Local<v8::Array> array = v8::Array::New(list.count());
+ for (int ii = 0; ii < list.count(); ++ii)
+ array->Set(ii, engine->newQObject(list.at(ii)));
+ return array;
+ } else if (type == qMetaTypeId<QDeclarativeV8Handle>()) {
+ return *(v8::Handle<v8::Value>*)&data;
+ } else if (type == -1 || type == qMetaTypeId<QVariant>()) {
+ QVariant value = *((QVariant *)&data);
+ v8::Handle<v8::Value> rv = engine->fromVariant(value);
+ if (QObject *object = engine->toQObject(rv))
+ QDeclarativeData::get(object, true)->setImplicitDestructible();
+ return rv;
+ } else {
+ return v8::Undefined();
+ }
+}
diff --git a/src/declarative/qml/v8/qv8qobjectwrapper_p.h b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
new file mode 100644
index 0000000000..f63396945e
--- /dev/null
+++ b/src/declarative/qml/v8/qv8qobjectwrapper_p.h
@@ -0,0 +1,121 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QV8QOBJECTWRAPPER_P_H
+#define QV8QOBJECTWRAPPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qmetatype.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qhash.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QV8Engine;
+class QV8ObjectResource;
+class QDeclarativePropertyCache;
+class QV8QObjectConnectionList;
+class Q_AUTOTEST_EXPORT QV8QObjectWrapper
+{
+public:
+ QV8QObjectWrapper();
+ ~QV8QObjectWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
+
+ v8::Handle<v8::Value> newQObject(QObject *object);
+ bool isQObject(v8::Handle<v8::Object>);
+ QObject *toQObject(v8::Handle<v8::Object>);
+ QObject *toQObject(QV8ObjectResource *);
+
+ enum RevisionMode { IgnoreRevision, CheckRevision };
+ v8::Handle<v8::Value> getProperty(QObject *, v8::Handle<v8::String>, RevisionMode);
+ bool setProperty(QObject *, v8::Handle<v8::String>, v8::Handle<v8::Value>, RevisionMode);
+
+private:
+ friend class QDeclarativePropertyCache;
+ friend class QV8QObjectConnectionList;
+
+ static v8::Handle<v8::Value> GetProperty(QV8Engine *, QObject *, v8::Handle<v8::Value> *,
+ v8::Handle<v8::String>, QV8QObjectWrapper::RevisionMode);
+ static bool SetProperty(QV8Engine *, QObject *, v8::Handle<v8::String>,
+ v8::Handle<v8::Value>, QV8QObjectWrapper::RevisionMode);
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Integer> Query(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Array> Enumerator(const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Connect(const v8::Arguments &args);
+ static v8::Handle<v8::Value> Disconnect(const v8::Arguments &args);
+ static v8::Handle<v8::Value> Invoke(const v8::Arguments &args);
+ static QPair<QObject *, int> ExtractQtMethod(QV8Engine *, v8::Handle<v8::Function>);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_methodConstructor;
+ v8::Persistent<v8::String> m_toStringSymbol;
+ v8::Persistent<v8::String> m_destroySymbol;
+ v8::Persistent<v8::Object> m_hiddenObject;
+ QHash<QObject *, QV8QObjectConnectionList *> m_connections;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8QOBJECTWRAPPER_P_H
+
+
diff --git a/src/declarative/qml/v8/qv8stringwrapper.cpp b/src/declarative/qml/v8/qv8stringwrapper.cpp
new file mode 100644
index 0000000000..883c4826c5
--- /dev/null
+++ b/src/declarative/qml/v8/qv8stringwrapper.cpp
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** 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 "qv8stringwrapper_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QV8StringResource : public v8::String::ExternalStringResource
+{
+public:
+ QV8StringResource(const QString &str) : str(str) {}
+ virtual const uint16_t* data() const { return (uint16_t*)str.constData(); }
+ virtual size_t length() const { return str.length(); }
+ virtual void Dispose() { delete this; }
+
+ QString str;
+};
+
+QV8StringWrapper::QV8StringWrapper()
+{
+}
+
+QV8StringWrapper::~QV8StringWrapper()
+{
+}
+
+void QV8StringWrapper::init()
+{
+}
+
+void QV8StringWrapper::destroy()
+{
+}
+
+v8::Local<v8::String> QV8StringWrapper::toString(const QString &qstr)
+{
+// return v8::String::NewExternal(new QV8StringResource(qstr));
+ return v8::String::New((uint16_t*)qstr.constData(), qstr.length());
+}
+
+QString QV8StringWrapper::toString(v8::Handle<v8::String> jsstr)
+{
+ if (jsstr.IsEmpty()) {
+ return QString();
+ } else if (jsstr->IsExternal()) {
+ QV8StringResource *r = (QV8StringResource *)jsstr->GetExternalStringResource();
+ return r->str;
+ } else {
+ QString qstr;
+ qstr.resize(jsstr->Length());
+ jsstr->Write((uint16_t*)qstr.data());
+ return qstr;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h b/src/declarative/qml/v8/qv8stringwrapper_p.h
index 01cfb6ecac..8dde5c8c44 100644
--- a/src/declarative/qml/qdeclarativeglobalscriptclass_p.h
+++ b/src/declarative/qml/v8/qv8stringwrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEGLOBALSCRIPTCLASS_P_H
-#define QDECLARATIVEGLOBALSCRIPTCLASS_P_H
+#ifndef QDECLARATIVEV8STRINGWRAPPER_P_H
+#define QDECLARATIVEV8STRINGWRAPPER_P_H
//
// W A R N I N G
@@ -53,34 +53,24 @@
// We mean it.
//
-#include <QtScript/qscriptclass.h>
-#include <QtCore/qset.h>
+#include <QtCore/qstring.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class Q_AUTOTEST_EXPORT QDeclarativeGlobalScriptClass : public QScriptClass
+class Q_AUTOTEST_EXPORT QV8StringWrapper
{
public:
- QDeclarativeGlobalScriptClass(QScriptEngine *);
+ QV8StringWrapper();
+ ~QV8StringWrapper();
- virtual QueryFlags queryProperty(const QScriptValue &object,
- const QScriptString &name,
- QueryFlags flags, uint *id);
+ void init();
+ void destroy();
- virtual void setProperty(QScriptValue &object, const QScriptString &name,
- uint id, const QScriptValue &value);
-
- void explicitSetProperty(const QStringList &, const QList<QScriptValue> &);
-
- const QScriptValue &staticGlobalObject() const { return m_staticGlobalObject; }
-
- const QSet<QString> &illegalNames() const { return m_illegalNames; }
-
-private:
- QSet<QString> m_illegalNames;
- QScriptValue m_staticGlobalObject;
+ v8::Local<v8::String> toString(const QString &);
+ QString toString(v8::Handle<v8::String>);
};
QT_END_NAMESPACE
-#endif // QDECLARATIVEGLOBALSCRIPTCLASS_P_H
+#endif // QDECLARATIVEV8STRINGWRAPPER_P_H
diff --git a/src/declarative/qml/v8/qv8typewrapper.cpp b/src/declarative/qml/v8/qv8typewrapper.cpp
new file mode 100644
index 0000000000..2067f73fae
--- /dev/null
+++ b/src/declarative/qml/v8/qv8typewrapper.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** 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 "qv8contextwrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativeengine_p.h>
+#include <private/qdeclarativecontext_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8TypeResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(TypeType);
+
+public:
+ QV8TypeResource(QV8Engine *engine);
+ virtual ~QV8TypeResource();
+
+ QV8TypeWrapper::TypeNameMode mode;
+
+ QDeclarativeGuard<QObject> object;
+ QDeclarativeType *type;
+ QDeclarativeTypeNameCache *typeNamespace;
+};
+
+QV8TypeResource::QV8TypeResource(QV8Engine *engine)
+: QV8ObjectResource(engine), mode(QV8TypeWrapper::IncludeEnums), type(0), typeNamespace(0)
+{
+}
+
+QV8TypeResource::~QV8TypeResource()
+{
+ if (typeNamespace) typeNamespace->release();
+}
+
+QV8TypeWrapper::QV8TypeWrapper()
+: m_engine(0)
+{
+}
+
+QV8TypeWrapper::~QV8TypeWrapper()
+{
+}
+
+void QV8TypeWrapper::destroy()
+{
+ m_constructor.Dispose();
+}
+
+void QV8TypeWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+}
+
+v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeType *t, TypeNameMode mode)
+{
+ Q_ASSERT(t);
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8TypeResource *r = new QV8TypeResource(m_engine);
+ r->mode = mode; r->object = o; r->type = t;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Local<v8::Object> QV8TypeWrapper::newObject(QObject *o, QDeclarativeTypeNameCache *t, TypeNameMode mode)
+{
+ Q_ASSERT(t);
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8TypeResource *r = new QV8TypeResource(m_engine);
+ t->addref();
+ r->mode = mode; r->object = o; r->typeNamespace = t;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Handle<v8::Value> QV8TypeWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ v8::Object::ExternalResource *r = info.This()->GetExternalResource();
+ QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
+
+ if (!resource)
+ return v8::Undefined();
+
+ QV8Engine *v8engine = resource->engine;
+ QObject *object = resource->object;
+
+ if (resource->type) {
+ QDeclarativeType *type = resource->type;
+
+ if (QV8Engine::startsWithUpper(property)) {
+ if (resource->mode == IncludeEnums) {
+ QString name = v8engine->toString(property);
+
+ // ### Optimize
+ QByteArray enumName = name.toUtf8();
+ const QMetaObject *metaObject = type->baseMetaObject();
+ for (int ii = metaObject->enumeratorCount() - 1; ii >= 0; --ii) {
+ QMetaEnum e = metaObject->enumerator(ii);
+ int value = e.keyToValue(enumName.constData());
+ if (value != -1)
+ return v8::Integer::New(value);
+ }
+ }
+
+ // Fall through to undefined
+
+ } else if (resource->object) {
+ QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
+ if (ao)
+ return v8engine->qobjectWrapper()->getProperty(ao, property, QV8QObjectWrapper::IgnoreRevision);
+
+ // Fall through to undefined
+ }
+
+ // Fall through to undefined
+
+ } else if (resource->typeNamespace) {
+
+ QDeclarativeTypeNameCache *typeNamespace = resource->typeNamespace;
+ QDeclarativeTypeNameCache::Data *d = typeNamespace->data(property);
+ Q_ASSERT(!d || !d->typeNamespace); // Nested namespaces not supported
+
+ if (d && d->type) {
+ return v8engine->typeWrapper()->newObject(object, d->type, resource->mode);
+ } else if (QDeclarativeMetaType::ModuleApiInstance *moduleApi = typeNamespace->moduleApi()) {
+
+ // XXX QtScript/JSC required
+ return v8::Undefined();
+
+ }
+
+ // Fall through to undefined
+
+ } else {
+ Q_ASSERT(!"Unreachable");
+ }
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8TypeWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ v8::Object::ExternalResource *r = info.This()->GetExternalResource();
+ QV8TypeResource *resource = v8_resource_cast<QV8TypeResource>(info.This());
+
+ if (!resource)
+ return value;
+
+ QV8Engine *v8engine = resource->engine;
+
+ // XXX module api
+
+ if (resource->type && resource->object) {
+ QDeclarativeType *type = resource->type;
+ QObject *object = resource->object;
+ QObject *ao = qmlAttachedPropertiesObjectById(type->attachedPropertiesId(), object);
+ if (ao)
+ v8engine->qobjectWrapper()->setProperty(ao, property, value, QV8QObjectWrapper::IgnoreRevision);
+ }
+
+ return value;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h b/src/declarative/qml/v8/qv8typewrapper_p.h
index 49e1ae809e..166bf3b7fa 100644
--- a/src/declarative/qml/qdeclarativetypenamescriptclass_p.h
+++ b/src/declarative/qml/v8/qv8typewrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVETYPENAMESCRIPTCLASS_P_H
-#define QDECLARATIVETYPENAMESCRIPTCLASS_P_H
+#ifndef QV8TYPEWRAPPER_P_H
+#define QV8TYPEWRAPPER_P_H
//
// W A R N I N G
@@ -52,42 +52,41 @@
//
// We mean it.
//
-#include "private/qdeclarativeengine_p.h"
-#include <private/qscriptdeclarativeclass_p.h>
-#include <QtScript/qscriptclass.h>
+#include <QtCore/qglobal.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
+class QObject;
+class QV8Engine;
class QDeclarativeType;
class QDeclarativeTypeNameCache;
-class QDeclarativeTypeNameScriptClass : public QScriptDeclarativeClass
+class QV8TypeWrapper
{
public:
- QDeclarativeTypeNameScriptClass(QDeclarativeEngine *);
- ~QDeclarativeTypeNameScriptClass();
+ QV8TypeWrapper();
+ ~QV8TypeWrapper();
- enum TypeNameMode { IncludeEnums, ExcludeEnums };
- QScriptValue newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
- QScriptValue newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums);
-
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
+ void init(QV8Engine *);
+ void destroy();
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ enum TypeNameMode { IncludeEnums, ExcludeEnums };
+ v8::Local<v8::Object> newObject(QObject *, QDeclarativeType *, TypeNameMode = IncludeEnums);
+ v8::Local<v8::Object> newObject(QObject *, QDeclarativeTypeNameCache *, TypeNameMode = IncludeEnums);
private:
- QDeclarativeEngine *engine;
- QObject *object;
- QDeclarativeType *type;
- QDeclarativeMetaType::ModuleApiInstance *api;
- quint32 enumValue;
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVETYPENAMESCRIPTCLASS_P_H
+#endif // QV8TYPEWRAPPER_P_H
diff --git a/src/declarative/qml/v8/qv8valuetypewrapper.cpp b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
new file mode 100644
index 0000000000..6dfb4312bc
--- /dev/null
+++ b/src/declarative/qml/v8/qv8valuetypewrapper.cpp
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** 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 "qv8valuetypewrapper_p.h"
+#include "qv8engine_p.h"
+
+#include <private/qdeclarativevaluetype_p.h>
+#include <private/qdeclarativebinding_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8ValueTypeResource : public QV8ObjectResource
+{
+ V8_RESOURCE_TYPE(ValueTypeType);
+
+public:
+ enum ObjectType { Reference, Copy };
+
+ QV8ValueTypeResource(QV8Engine *engine, ObjectType objectType);
+
+ ObjectType objectType;
+ QDeclarativeValueType *type;
+};
+
+class QV8ValueTypeReferenceResource : public QV8ValueTypeResource
+{
+public:
+ QV8ValueTypeReferenceResource(QV8Engine *engine);
+
+ QDeclarativeGuard<QObject> object;
+ int property;
+};
+
+class QV8ValueTypeCopyResource : public QV8ValueTypeResource
+{
+public:
+ QV8ValueTypeCopyResource(QV8Engine *engine);
+
+ QVariant value;
+};
+
+QV8ValueTypeResource::QV8ValueTypeResource(QV8Engine *engine, ObjectType objectType)
+: QV8ObjectResource(engine), objectType(objectType)
+{
+}
+
+QV8ValueTypeReferenceResource::QV8ValueTypeReferenceResource(QV8Engine *engine)
+: QV8ValueTypeResource(engine, Reference)
+{
+}
+
+QV8ValueTypeCopyResource::QV8ValueTypeCopyResource(QV8Engine *engine)
+: QV8ValueTypeResource(engine, Copy)
+{
+}
+
+QV8ValueTypeWrapper::QV8ValueTypeWrapper()
+: m_engine(0)
+{
+}
+
+QV8ValueTypeWrapper::~QV8ValueTypeWrapper()
+{
+}
+
+void QV8ValueTypeWrapper::destroy()
+{
+ m_constructor.Dispose();
+}
+
+void QV8ValueTypeWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+}
+
+v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(QObject *object, int property, QDeclarativeValueType *type)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ValueTypeReferenceResource *r = new QV8ValueTypeReferenceResource(m_engine);
+ r->type = type; r->object = object; r->property = property;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+v8::Local<v8::Object> QV8ValueTypeWrapper::newValueType(const QVariant &value, QDeclarativeValueType *type)
+{
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv = m_constructor->NewInstance();
+ QV8ValueTypeCopyResource *r = new QV8ValueTypeCopyResource(m_engine);
+ r->type = type; r->value = value;
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+QVariant QV8ValueTypeWrapper::toVariant(v8::Handle<v8::Object> obj)
+{
+ QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(obj);
+ if (r) return toVariant(r);
+ else return QVariant();
+}
+
+QVariant QV8ValueTypeWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::ValueTypeType);
+ QV8ValueTypeResource *resource = static_cast<QV8ValueTypeResource *>(r);
+
+ if (resource->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(resource);
+
+ if (reference->object) {
+ reference->type->read(reference->object, reference->property);
+ return reference->type->value();
+ } else {
+ return QVariant();
+ }
+
+ } else {
+ Q_ASSERT(resource->objectType == QV8ValueTypeResource::Copy);
+
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(resource);
+
+ return copy->value;
+ }
+}
+
+v8::Handle<v8::Value> QV8ValueTypeWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This());
+ if (!r) return v8::Undefined();
+
+ // XXX aakenned - this is horribly inefficient. People seem to have taken a
+ // liking to value type properties, so we should probably try and optimize it
+ // a little.
+
+ QByteArray propName = r->engine->toString(property).toUtf8();
+ int index = r->type->metaObject()->indexOfProperty(propName.constData());
+ if (index == -1)
+ return v8::Undefined();
+
+ if (r->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r);
+
+ if (!reference->object)
+ return v8::Undefined();
+
+ r->type->read(reference->object, reference->property);
+ } else {
+ Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy);
+
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(r);
+
+ r->type->setValue(copy->value);
+ }
+
+ QMetaProperty prop = r->type->metaObject()->property(index);
+ QVariant result = prop.read(r->type);
+
+ return r->engine->fromVariant(result);
+}
+
+v8::Handle<v8::Value> QV8ValueTypeWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ QV8ValueTypeResource *r = v8_resource_cast<QV8ValueTypeResource>(info.This());
+ if (!r) return value;
+
+ QByteArray propName = r->engine->toString(property).toUtf8();
+ int index = r->type->metaObject()->indexOfProperty(propName.constData());
+ if (index == -1)
+ return value;
+
+ if (r->objectType == QV8ValueTypeResource::Reference) {
+ QV8ValueTypeReferenceResource *reference = static_cast<QV8ValueTypeReferenceResource *>(r);
+
+ if (!reference->object ||
+ !reference->object->metaObject()->property(reference->property).isWritable())
+ return value;
+
+ r->type->read(reference->object, reference->property);
+ QMetaProperty p = r->type->metaObject()->property(index);
+
+ QDeclarativeBinding *newBinding = 0;
+
+ if (value->IsFunction()) {
+ QDeclarativeContextData *context = r->engine->callingContext();
+ v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(value);
+
+ QDeclarativePropertyCache::Data cacheData;
+ cacheData.flags = QDeclarativePropertyCache::Data::IsWritable;
+ cacheData.propType = reference->object->metaObject()->property(reference->property).userType();
+ cacheData.coreIndex = reference->property;
+
+ QDeclarativePropertyCache::ValueTypeData valueTypeData;
+ valueTypeData.valueTypeCoreIdx = index;
+ valueTypeData.valueTypePropType = p.userType();
+
+ v8::Local<v8::StackTrace> trace =
+ v8::StackTrace::CurrentStackTrace(1,
+ (v8::StackTrace::StackTraceOptions)(v8::StackTrace::kLineNumber |
+ v8::StackTrace::kScriptName));
+ v8::Local<v8::StackFrame> frame = trace->GetFrame(0);
+ int lineNumber = frame->GetLineNumber();
+ QString url = r->engine->toString(frame->GetScriptName());
+
+ newBinding = new QDeclarativeBinding(&function, reference->object, context);
+ newBinding->setSourceLocation(url, lineNumber);
+ newBinding->setTarget(QDeclarativePropertyPrivate::restore(cacheData, valueTypeData,
+ reference->object, context));
+ newBinding->setEvaluateFlags(newBinding->evaluateFlags() | QDeclarativeBinding::RequiresThisObject);
+ }
+
+ QDeclarativeAbstractBinding *oldBinding =
+ QDeclarativePropertyPrivate::setBinding(reference->object, reference->property, index, newBinding);
+ if (oldBinding)
+ oldBinding->destroy();
+
+ if (!value->IsFunction()) {
+ QVariant v = r->engine->toVariant(value, -1);
+
+ if (p.isEnumType() && (QMetaType::Type)v.type() == QMetaType::Double)
+ v = v.toInt();
+
+ p.write(reference->type, v);
+
+ reference->type->write(reference->object, reference->property, 0);
+ }
+
+ } else {
+ Q_ASSERT(r->objectType == QV8ValueTypeResource::Copy);
+
+ QV8ValueTypeCopyResource *copy = static_cast<QV8ValueTypeCopyResource *>(r);
+
+ QVariant v = r->engine->toVariant(value, -1);
+
+ r->type->setValue(copy->value);
+ QMetaProperty p = r->type->metaObject()->property(index);
+ p.write(r->type, v);
+ copy->value = r->type->value();
+ }
+
+ return value;
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h b/src/declarative/qml/v8/qv8valuetypewrapper_p.h
index 8988c0be6a..b4bc90cfec 100644
--- a/src/declarative/qml/qdeclarativevaluetypescriptclass_p.h
+++ b/src/declarative/qml/v8/qv8valuetypewrapper_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEVALUETYPESCRIPTCLASS_P_H
-#define QDECLARATIVEVALUETYPESCRIPTCLASS_P_H
+#ifndef QV8VALUETYPEWRAPPER_P_H
+#define QV8VALUETYPEWRAPPER_P_H
//
// W A R N I N G
@@ -53,35 +53,43 @@
// We mean it.
//
-
-#include <private/qscriptdeclarativeclass_p.h>
+#include <QtCore/qglobal.h>
+#include <QtDeclarative/qdeclarativelist.h>
+#include <private/qv8_p.h>
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
+class QV8Engine;
+class QV8ObjectResource;
class QDeclarativeValueType;
-class QDeclarativeValueTypeScriptClass : public QScriptDeclarativeClass
+class QV8ValueTypeWrapper
{
public:
- QDeclarativeValueTypeScriptClass(QDeclarativeEngine *);
- ~QDeclarativeValueTypeScriptClass();
+ QV8ValueTypeWrapper();
+ ~QV8ValueTypeWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
- QScriptValue newObject(QObject *object, int coreIndex, QDeclarativeValueType *);
- QScriptValue newObject(const QVariant &, QDeclarativeValueType *);
+ v8::Local<v8::Object> newValueType(QObject *, int, QDeclarativeValueType *);
+ v8::Local<v8::Object> newValueType(const QVariant &, QDeclarativeValueType *);
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual void setProperty(Object *, const Identifier &name, const QScriptValue &);
+ QVariant toVariant(v8::Handle<v8::Object>);
+ QVariant toVariant(QV8ObjectResource *);
- virtual QVariant toVariant(Object *, bool *ok = 0);
- QVariant toVariant(const QScriptValue &);
private:
- QDeclarativeEngine *engine;
- int m_lastIndex;
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
};
QT_END_NAMESPACE
-#endif // QDECLARATIVEVALUETYPESCRIPTCLASS_P_H
+#endif // QV8VALUETYPEWRAPPER_P_H
+
diff --git a/src/declarative/qml/v8/qv8variantwrapper.cpp b/src/declarative/qml/v8/qv8variantwrapper.cpp
new file mode 100644
index 0000000000..2d91a335b2
--- /dev/null
+++ b/src/declarative/qml/v8/qv8variantwrapper.cpp
@@ -0,0 +1,190 @@
+/****************************************************************************
+**
+** 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 "qv8variantwrapper_p.h"
+#include "qv8engine_p.h"
+#include "qdeclarativeengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QV8VariantResource : public QV8ObjectResource,
+ public QDeclarativeEnginePrivate::ScarceResourceData
+{
+ V8_RESOURCE_TYPE(VariantType);
+public:
+ QV8VariantResource(QV8Engine *engine, const QVariant &data);
+};
+
+QV8VariantResource::QV8VariantResource(QV8Engine *engine, const QVariant &data)
+: QV8ObjectResource(engine), QDeclarativeEnginePrivate::ScarceResourceData(data)
+{
+}
+
+QV8VariantWrapper::QV8VariantWrapper()
+: m_engine(0)
+{
+}
+
+QV8VariantWrapper::~QV8VariantWrapper()
+{
+}
+
+void QV8VariantWrapper::init(QV8Engine *engine)
+{
+ m_engine = engine;
+ {
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetNamedPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ m_constructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+ {
+ m_preserve = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(Preserve)->GetFunction());
+ m_destroy = v8::Persistent<v8::Function>::New(v8::FunctionTemplate::New(Destroy)->GetFunction());
+ v8::Local<v8::FunctionTemplate> ft = v8::FunctionTemplate::New();
+ ft->InstanceTemplate()->SetFallbackPropertyHandler(Getter, Setter);
+ ft->InstanceTemplate()->SetHasExternalResource(true);
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("preserve"), PreserveGetter, 0,
+ m_preserve, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ ft->InstanceTemplate()->SetAccessor(v8::String::New("destroy"), DestroyGetter, 0,
+ m_destroy, v8::DEFAULT,
+ v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+ m_scarceConstructor = v8::Persistent<v8::Function>::New(ft->GetFunction());
+ }
+
+}
+
+void QV8VariantWrapper::destroy()
+{
+ m_destroy.Dispose();
+ m_preserve.Dispose();
+ m_scarceConstructor.Dispose();
+ m_constructor.Dispose();
+}
+
+v8::Local<v8::Object> QV8VariantWrapper::newVariant(const QVariant &value)
+{
+ bool scarceResource = value.type() == QVariant::Pixmap ||
+ value.type() == QVariant::Image;
+
+ QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(m_engine->engine());
+
+ // XXX aakenned - NewInstance() is slow for our case
+ v8::Local<v8::Object> rv;
+ QV8VariantResource *r = new QV8VariantResource(m_engine, value);
+
+ if (scarceResource) {
+ Q_ASSERT(ep->scarceResourcesRefCount);
+ rv = m_scarceConstructor->NewInstance();
+ ep->scarceResources.insert(r);
+ } else {
+ rv = m_constructor->NewInstance();
+ }
+
+ rv->SetExternalResource(r);
+ return rv;
+}
+
+bool QV8VariantWrapper::isVariant(v8::Handle<v8::Value> value)
+{
+ return value->IsObject() && v8_resource_cast<QV8VariantResource>(value->ToObject());
+}
+
+QVariant QV8VariantWrapper::toVariant(v8::Handle<v8::Object> obj)
+{
+ QV8VariantResource *r = v8_resource_cast<QV8VariantResource>(obj);
+ return r?r->data:QVariant();
+}
+
+QVariant QV8VariantWrapper::toVariant(QV8ObjectResource *r)
+{
+ Q_ASSERT(r->resourceType() == QV8ObjectResource::VariantType);
+ return static_cast<QV8VariantResource *>(r)->data;
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info)
+{
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::PreserveGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ return info.Data();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::DestroyGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info)
+{
+ Q_UNUSED(property);
+ return info.Data();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Preserve(const v8::Arguments &args)
+{
+ QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
+ if (resource) {
+ resource->node.remove();
+ }
+ return v8::Undefined();
+}
+
+v8::Handle<v8::Value> QV8VariantWrapper::Destroy(const v8::Arguments &args)
+{
+ QV8VariantResource *resource = v8_resource_cast<QV8VariantResource>(args.This());
+ if (resource) {
+ resource->data = QVariant();
+ resource->node.remove();
+ }
+ return v8::Undefined();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/v8/qv8variantwrapper_p.h b/src/declarative/qml/v8/qv8variantwrapper_p.h
new file mode 100644
index 0000000000..391ec4c21a
--- /dev/null
+++ b/src/declarative/qml/v8/qv8variantwrapper_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** 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$
+**
+****************************************************************************/
+
+#ifndef QV8VARIANTWRAPPER_P_H
+#define QV8VARIANTWRAPPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+#include <QtDeclarative/qdeclarativelist.h>
+#include <private/qv8_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QV8Engine;
+class QV8ObjectResource;
+class QV8VariantWrapper
+{
+public:
+ QV8VariantWrapper();
+ ~QV8VariantWrapper();
+
+ void init(QV8Engine *);
+ void destroy();
+
+ v8::Local<v8::Object> newVariant(const QVariant &);
+ bool isVariant(v8::Handle<v8::Value>);
+ QVariant toVariant(v8::Handle<v8::Object>);
+ QVariant toVariant(QV8ObjectResource *);
+
+private:
+ static v8::Handle<v8::Value> Getter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Setter(v8::Local<v8::String> property,
+ v8::Local<v8::Value> value,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> PreserveGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> DestroyGetter(v8::Local<v8::String> property,
+ const v8::AccessorInfo &info);
+ static v8::Handle<v8::Value> Preserve(const v8::Arguments &args);
+ static v8::Handle<v8::Value> Destroy(const v8::Arguments &args);
+
+ QV8Engine *m_engine;
+ v8::Persistent<v8::Function> m_constructor;
+ v8::Persistent<v8::Function> m_scarceConstructor;
+ v8::Persistent<v8::Function> m_preserve;
+ v8::Persistent<v8::Function> m_destroy;
+};
+
+QT_END_NAMESPACE
+
+#endif // QV8VARIANTWRAPPER_P_H
+
diff --git a/src/declarative/qml/v8/qv8worker.cpp b/src/declarative/qml/v8/qv8worker.cpp
new file mode 100644
index 0000000000..6b6ecd8c2a
--- /dev/null
+++ b/src/declarative/qml/v8/qv8worker.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** 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 "qv8worker_p.h"
+
+QT_BEGIN_NAMESPACE
+
+// We allow the following JavaScript types to be passed between the main and
+// the secondary thread:
+// + undefined
+// + null
+// + Boolean
+// + String
+// + Function
+// + Array
+// + "Simple" Objects
+// + Number
+// + Date
+// + RegExp
+// <quint8 type><quint24 size><data>
+
+enum Type {
+ WorkerUndefined,
+ WorkerNull,
+ WorkerTrue,
+ WorkerFalse,
+ WorkerString,
+ WorkerFunction,
+ WorkerArray,
+ WorkerObject,
+ WorkerInt32,
+ WorkerUint32,
+ WorkerNumber,
+ WorkerDate,
+ WorkerRegexp
+};
+
+static inline quint32 valueheader(Type type, quint32 size = 0)
+{
+ return quint8(type) << 24 | (size & 0xFFFFFF);
+}
+
+static inline Type headertype(quint32 header)
+{
+ return (Type)(header >> 24);
+}
+
+static inline quint32 headersize(quint32 header)
+{
+ return header & 0xFFFFFF;
+}
+
+static inline void push(QByteArray &data, quint32 value)
+{
+ data.append((const char *)&value, sizeof(quint32));
+}
+
+static inline void push(QByteArray &data, double value)
+{
+ data.append((const char *)&value, sizeof(double));
+}
+
+static inline void reserve(QByteArray &data, int extra)
+{
+ data.reserve(data.size() + extra);
+}
+
+static inline quint32 popUint32(const char *&data)
+{
+ quint32 rv = *((quint32 *)data);
+ data += sizeof(quint32);
+ return rv;
+}
+
+static inline double popDouble(const char *&data)
+{
+ double rv = *((double *)data);
+ data += sizeof(double);
+ return rv;
+}
+
+// XXX double check exception safety
+
+#include <QDebug>
+#define ALIGN(size) (((size) + 3) & ~3)
+void QV8Worker::serialize(QByteArray &data, v8::Handle<v8::Value> v, QV8Engine *engine)
+{
+ if (v.IsEmpty()) {
+ } else if (v->IsUndefined()) {
+ push(data, valueheader(WorkerUndefined));
+ } else if (v->IsNull()) {
+ push(data, valueheader(WorkerNull));
+ } else if (v->IsTrue()) {
+ push(data, valueheader(WorkerTrue));
+ } else if (v->IsFalse()) {
+ push(data, valueheader(WorkerFalse));
+ } else if (v->IsString()) {
+ v8::Handle<v8::String> string = v->ToString();
+ int length = string->Length() + 1;
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ int utf16size = ALIGN(length * sizeof(uint16_t));
+
+ reserve(data, utf16size + sizeof(quint32));
+ push(data, valueheader(WorkerString, length));
+
+ int offset = data.size();
+ data.resize(data.size() + utf16size);
+ char *buffer = data.data() + offset;
+
+ string->Write((uint16_t*)buffer);
+ } else if (v->IsFunction()) {
+ // XXX
+ push(data, valueheader(WorkerUndefined));
+ } else if (v->IsArray()) {
+ v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(v);
+ uint32_t length = array->Length();
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ reserve(data, sizeof(quint32) + length * sizeof(quint32));
+ push(data, valueheader(WorkerArray, length));
+ for (uint32_t ii = 0; ii < length; ++ii)
+ serialize(data, array->Get(ii), engine);
+ } else if (v->IsInt32()) {
+ reserve(data, 2 * sizeof(quint32));
+ push(data, valueheader(WorkerInt32));
+ push(data, (quint32)v->Int32Value());
+ } else if (v->IsUint32()) {
+ reserve(data, 2 * sizeof(quint32));
+ push(data, valueheader(WorkerUint32));
+ push(data, v->Uint32Value());
+ } else if (v->IsNumber()) {
+ reserve(data, sizeof(quint32) + sizeof(double));
+ push(data, valueheader(WorkerNumber));
+ push(data, v->NumberValue());
+ } else if (v->IsDate()) {
+ reserve(data, sizeof(quint32) + sizeof(double));
+ push(data, valueheader(WorkerDate));
+ push(data, v8::Handle<v8::Date>::Cast(v)->NumberValue());
+ } else if (v->IsRegExp()) {
+ v8::Handle<v8::RegExp> regexp = v8::Handle<v8::RegExp>::Cast(v);
+ quint32 flags = regexp->GetFlags();
+ v8::Local<v8::String> source = regexp->GetSource();
+
+ int length = source->Length() + 1;
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ int utf16size = ALIGN(length * sizeof(uint16_t));
+
+ reserve(data, sizeof(quint32) + utf16size);
+ push(data, valueheader(WorkerRegexp, flags));
+ push(data, (quint32)length);
+ int offset = data.size();
+ data.resize(data.size() + utf16size);
+ char *buffer = data.data() + offset;
+
+ source->Write((uint16_t*)buffer);
+ } else if (v->IsObject() && !v->ToObject()->GetExternalResource()) {
+ v8::Handle<v8::Object> object = v->ToObject();
+ v8::Local<v8::Array> properties = engine->getOwnPropertyNames(object);
+ quint32 length = properties->Length();
+ if (length > 0xFFFFFF) {
+ push(data, valueheader(WorkerUndefined));
+ return;
+ }
+ push(data, valueheader(WorkerObject, length));
+ v8::TryCatch tc;
+ for (quint32 ii = 0; ii < length; ++ii) {
+ v8::Local<v8::String> str = properties->Get(ii)->ToString();
+ serialize(data, str, engine);
+
+ v8::Local<v8::Value> val = object->Get(str);
+ if (tc.HasCaught()) {
+ serialize(data, v8::Undefined(), engine);
+ tc.Reset();
+ } else {
+ serialize(data, val, engine);
+ }
+ }
+ } else {
+ push(data, valueheader(WorkerUndefined));
+ }
+
+ // XXX Need to serialize QDeclarativeListModel
+ /*
+ QDeclarativeListModel *lm = qobject_cast<QDeclarativeListModel *>(value.toQObject());
+ if (lm) {
+ QDeclarativeListModelWorkerAgent *agent = lm->agent();
+ if (agent) {
+ QDeclarativeListModelWorkerAgent::VariantRef v(agent);
+ return QVariant::fromValue(v);
+ } else {
+ return QVariant();
+ }
+ }
+ */
+}
+
+v8::Handle<v8::Value> QV8Worker::deserialize(const char *&data, QV8Engine *engine)
+{
+ quint32 header = popUint32(data);
+ Type type = headertype(header);
+
+ switch (type) {
+ case WorkerUndefined:
+ return v8::Undefined();
+ case WorkerNull:
+ return v8::Null();
+ case WorkerTrue:
+ return v8::True();
+ case WorkerFalse:
+ return v8::False();
+ case WorkerString:
+ {
+ quint32 size = headersize(header);
+ v8::Local<v8::String> string = v8::String::New((uint16_t*)data, size - 1);
+ data += ALIGN(size * sizeof(uint16_t));
+ return string;
+ }
+ case WorkerFunction:
+ Q_ASSERT(!"Unreachable");
+ break;
+ case WorkerArray:
+ {
+ quint32 size = headersize(header);
+ v8::Local<v8::Array> array = v8::Array::New(size);
+ for (quint32 ii = 0; ii < size; ++ii) {
+ array->Set(ii, deserialize(data, engine));
+ }
+ return array;
+ }
+ case WorkerObject:
+ {
+ quint32 size = headersize(header);
+ v8::Local<v8::Object> o = v8::Object::New();
+ for (quint32 ii = 0; ii < size; ++ii) {
+ v8::Handle<v8::Value> name = deserialize(data, engine);
+ v8::Handle<v8::Value> value = deserialize(data, engine);
+ o->Set(name, value);
+ }
+ return o;
+ }
+ case WorkerInt32:
+ return v8::Integer::New((qint32)popUint32(data));
+ case WorkerUint32:
+ return v8::Integer::NewFromUnsigned(popUint32(data));
+ case WorkerNumber:
+ return v8::Number::New(popDouble(data));
+ case WorkerDate:
+ return v8::Date::New(popDouble(data));
+ case WorkerRegexp:
+ {
+ quint32 flags = headersize(header);
+ quint32 length = popUint32(data);
+ v8::Local<v8::String> source = v8::String::New((uint16_t*)data, length - 1);
+ data += ALIGN(length * sizeof(uint16_t));
+ return v8::RegExp::New(source, (v8::RegExp::Flags)flags);
+ }
+ }
+ Q_ASSERT(!"Unreachable");
+ return v8::Undefined();
+}
+
+QByteArray QV8Worker::serialize(v8::Handle<v8::Value> value, QV8Engine *engine)
+{
+ QByteArray rv;
+ serialize(rv, value, engine);
+ return rv;
+}
+
+v8::Handle<v8::Value> QV8Worker::deserialize(const QByteArray &data, QV8Engine *engine)
+{
+ const char *stream = data.constData();
+ return deserialize(stream, engine);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/declarative/qml/qdeclarativelistscriptclass_p.h b/src/declarative/qml/v8/qv8worker_p.h
index 005380b92c..086e18e7e0 100644
--- a/src/declarative/qml/qdeclarativelistscriptclass_p.h
+++ b/src/declarative/qml/v8/qv8worker_p.h
@@ -39,8 +39,8 @@
**
****************************************************************************/
-#ifndef QDECLARATIVELISTSCRIPTCLASS_P_H
-#define QDECLARATIVELISTSCRIPTCLASS_P_H
+#ifndef QV8WORKER_P_H
+#define QV8WORKER_P_H
//
// W A R N I N G
@@ -53,35 +53,23 @@
// We mean it.
//
-#include <private/qscriptdeclarativeclass_p.h>
-#include "qdeclarativelist.h"
+#include "qv8engine_p.h"
QT_BEGIN_NAMESPACE
-class QDeclarativeEngine;
-class QDeclarativeListScriptClass : public QScriptDeclarativeClass
-{
+class QV8Worker {
public:
- QDeclarativeListScriptClass(QDeclarativeEngine *);
- ~QDeclarativeListScriptClass();
+ struct SavedData {
+ };
- QScriptValue newList(QObject *, int, int);
- QScriptValue newList(const QDeclarativeListProperty<QObject> &, int);
-
-protected:
- virtual QScriptClass::QueryFlags queryProperty(Object *, const Identifier &,
- QScriptClass::QueryFlags flags);
- virtual Value property(Object *, const Identifier &);
- virtual QVariant toVariant(Object *, bool *ok);
+ static QByteArray serialize(v8::Handle<v8::Value>, QV8Engine *);
+ static v8::Handle<v8::Value> deserialize(const QByteArray &, QV8Engine *);
private:
- PersistentIdentifier m_lengthId;
- QDeclarativeEngine *engine;
-
- quint32 lastIndex;
+ static void serialize(QByteArray &, v8::Handle<v8::Value>, QV8Engine *);
+ static v8::Handle<v8::Value> deserialize(const char *&, QV8Engine *);
};
QT_END_NAMESPACE
-#endif // QDECLARATIVELISTSCRIPTCLASS_P_H
-
+#endif // QV8WORKER_P_H
diff --git a/src/declarative/qml/v8/v8.pri b/src/declarative/qml/v8/v8.pri
new file mode 100644
index 0000000000..d91acd7759
--- /dev/null
+++ b/src/declarative/qml/v8/v8.pri
@@ -0,0 +1,32 @@
+INCLUDEPATH += $$PWD/../../../3rdparty/javascriptcore
+INCLUDEPATH += $$PWD
+
+HEADERS += \
+ $$PWD/qv8_p.h \
+ $$PWD/qv8stringwrapper_p.h \
+ $$PWD/qv8engine_p.h \
+ $$PWD/qhashedstring_p.h \
+ $$PWD/qv8contextwrapper_p.h \
+ $$PWD/qv8qobjectwrapper_p.h \
+ $$PWD/qv8typewrapper_p.h \
+ $$PWD/qv8listwrapper_p.h \
+ $$PWD/qv8variantwrapper_p.h \
+ $$PWD/qv8valuetypewrapper_p.h \
+ $$PWD/qv8include_p.h \
+ $$PWD/qv8worker_p.h \
+ $$PWD/../../../3rdparty/javascriptcore/DateMath.h \
+
+SOURCES += \
+ $$PWD/qv8stringwrapper.cpp \
+ $$PWD/qv8engine.cpp \
+ $$PWD/qhashedstring.cpp \
+ $$PWD/qv8contextwrapper.cpp \
+ $$PWD/qv8qobjectwrapper.cpp \
+ $$PWD/qv8typewrapper.cpp \
+ $$PWD/qv8listwrapper.cpp \
+ $$PWD/qv8variantwrapper.cpp \
+ $$PWD/qv8valuetypewrapper.cpp \
+ $$PWD/qv8include.cpp \
+ $$PWD/qv8worker.cpp \
+ $$PWD/../../../3rdparty/javascriptcore/DateMath.cpp \
+
diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp
index 61b2d3463a..372b318e7e 100644
--- a/src/declarative/util/qdeclarativelistmodel.cpp
+++ b/src/declarative/util/qdeclarativelistmodel.cpp
@@ -1353,7 +1353,9 @@ QScriptValue NestedListModel::get(int index) const
if (!node)
return 0;
+#if 0
return QDeclarativeEnginePrivate::qmlScriptObject(node->object(this), eng);
+#endif
}
void NestedListModel::set(int index, const QScriptValue& valuemap, QList<int> *roles)