Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativeworkerscript.cpp
index f887084..b17c026 100644 (file)
@@ -1,8 +1,7 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
 **
 ** This file is part of the QtDeclarative module of the Qt Toolkit.
 **
 **
 **
 **
+**
 ** $QT_END_LICENSE$
 **
 ****************************************************************************/
 
-#include "private/qdeclarativeworkerscript_p.h"
-#include "private/qdeclarativelistmodel_p.h"
-#include "private/qdeclarativelistmodelworkeragent_p.h"
-#include "private/qdeclarativeengine_p.h"
-#include "private/qdeclarativeexpression_p.h"
+#include "qdeclarativeworkerscript_p.h"
+#include "qdeclarativelistmodel_p.h"
+#include "qdeclarativelistmodelworkeragent_p.h"
+#include "qdeclarativeengine_p.h"
+#include "qdeclarativeexpression_p.h"
 
 #include <QtCore/qcoreevent.h>
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qdebug.h>
-#include <QtScript/qscriptengine.h>
+#include <QtDeclarative/qjsengine.h>
 #include <QtCore/qmutex.h>
 #include <QtCore/qwaitcondition.h>
-#include <QtScript/qscriptvalueiterator.h>
 #include <QtCore/qfile.h>
 #include <QtCore/qdatetime.h>
 #include <QtNetwork/qnetworkaccessmanager.h>
 #include <QtDeclarative/qdeclarativeinfo.h>
 #include "qdeclarativenetworkaccessmanagerfactory.h"
 
+#include <private/qv8engine_p.h>
+#include <private/qv8worker_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -66,15 +67,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 +129,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 +160,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 +183,132 @@ 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) 
+: QV8Engine(0), p(parent), accessManager(0)
 {
 }
 
-QScriptValue QDeclarativeWorkerScriptEnginePrivate::onMessage(QScriptContext *ctxt, QScriptEngine *engine)
+QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() 
+{ 
+    qPersistentDispose(createsend);
+    qPersistentDispose(onmessage);
+    delete accessManager; 
+}
+
+void QDeclarativeWorkerScriptEnginePrivate::WorkerEngine::init()
 {
-    QDeclarativeWorkerScriptEnginePrivate *p = QDeclarativeWorkerScriptEnginePrivate::get(engine);
+    initDeclarativeGlobalObject();
+#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); "\
+    "})"
 
-    int id = ctxt->thisObject().data().toVariant().toInt();
+#define SEND_MESSAGE_CREATE_SCRIPT \
+    "(function(method, engine) { "\
+        "return (function(id) { "\
+            "return (function(message) { "\
+                "if (arguments.length) method(engine, id, message); "\
+            "}); "\
+        "}); "\
+    "})"
 
-    WorkerScript *script = p->workers.value(id);
-    if (!script)
-        return engine->undefinedValue();
+    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 = qPersistentNew<v8::Function>(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 = qPersistentNew<v8::Function>(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 = qPersistentNew<v8::Object>(workerEngine->contextWrapper()->urlScope(script->source));
+
+        workerEngine->contextWrapper()->setReadOnly(script->object, false);
+
+        v8::Local<v8::Object> api = v8::Object::New();
+        api->Set(v8::String::New("sendMessage"), workerEngine->sendFunction(script->id));
 
-        api.setProperty(QLatin1String("onMessage"), workerEngine->newFunction(onMessage),
-                        QScriptValue::PropertyGetter | QScriptValue::PropertySetter);
-        api.setProperty(QLatin1String("sendMessage"), workerEngine->newFunction(sendMessage));
+        script->object->Set(v8::String::New("WorkerScript"), api);
 
-        script->object.setProperty(QLatin1String("WorkerScript"), api);
+        workerEngine->contextWrapper()->setReadOnly(script->object, true);
     }
 
     return script->object;
@@ -262,6 +316,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 +333,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 +365,41 @@ void QDeclarativeWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
     if (f.open(QIODevice::ReadOnly)) {
         QByteArray data = f.readAll();
         QString sourceCode = QString::fromUtf8(data);
+        QDeclarativeScript::Parser::extractPragmas(sourceCode);
 
-        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 +407,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 +421,7 @@ int WorkerDataEvent::workerId() const
     return m_id;
 }
 
-QVariant WorkerDataEvent::data() const
+QByteArray WorkerDataEvent::data() const
 {
     return m_data;
 }
@@ -514,7 +466,7 @@ QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngin
 {
     d->m_lock.lock();
     connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection);
-    start(QThread::IdlePriority);
+    start(QThread::LowestPriority);
     d->m_wait.wait(&d->m_lock);
     d->moveToThread(this);
     d->m_lock.unlock();
@@ -523,11 +475,13 @@ QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngin
 QDeclarativeWorkerScriptEngine::~QDeclarativeWorkerScriptEngine()
 {
     d->m_lock.lock();
-    qDeleteAll(d->workers);
-    d->workers.clear();
     QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QDeclarativeWorkerScriptEnginePrivate::WorkerDestroyEvent));
     d->m_lock.unlock();
 
+    //We have to force to cleanup the main thread's event queue here
+    //to make sure the main GUI release all pending locks/wait conditions which
+    //some worker script/agent are waiting for (QDeclarativeListModelWorkerAgent::sync() for example).
+    QCoreApplication::processEvents();
     wait();
     d->deleteLater();
 }
@@ -537,9 +491,16 @@ QDeclarativeWorkerScriptEnginePrivate::WorkerScript::WorkerScript()
 {
 }
 
+QDeclarativeWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
+{
+    qPersistentDispose(object);
+}
+
 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,8 @@ void QDeclarativeWorkerScriptEngine::run()
 {
     d->m_lock.lock();
 
-    d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::ScriptEngine(d);
+    d->workerEngine = new QDeclarativeWorkerScriptEnginePrivate::WorkerEngine(d);
+    d->workerEngine->init();
 
     d->m_wait.wakeAll();
 
@@ -577,6 +539,9 @@ void QDeclarativeWorkerScriptEngine::run()
 
     exec();
 
+    qDeleteAll(d->workers);
+    d->workers.clear();
+
     delete d->workerEngine; d->workerEngine = 0;
 }
 
@@ -677,14 +642,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 +700,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) {