aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/types
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@qt.io>2018-08-20 13:59:08 +0200
committerSimon Hausmann <simon.hausmann@qt.io>2018-08-21 06:33:18 +0000
commit1d769f0c5f76ad06466f873b0421e59e984a263b (patch)
tree5e5490011cce833451e718d6fa301f4c51186ab4 /src/qml/types
parent26e9c07650474a23817487e768bbebbb87bd78e4 (diff)
Clean up QML worker scripts part 3
With one engine per worker script, we can replace the onMessage and sendmessage wrappers with plain properties of the WorkerScript object that we can access. The code is further simplified by merging WorkerEngine into WorkerScript. Change-Id: I25e9fb253b6b0dd1fe63676392b1c760a83215db Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/qml/types')
-rw-r--r--src/qml/types/qquickworkerscript.cpp199
1 files changed, 55 insertions, 144 deletions
diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp
index 706982ba97..c4fc9a0532 100644
--- a/src/qml/types/qquickworkerscript.cpp
+++ b/src/qml/types/qquickworkerscript.cpp
@@ -139,48 +139,26 @@ public:
QQuickWorkerScriptEnginePrivate(QQmlEngine *eng);
- class WorkerEngine : public QV8Engine
- {
- public:
- WorkerEngine(QQuickWorkerScriptEnginePrivate *parent);
- ~WorkerEngine() override;
-
- void init(int id);
-
-#if QT_CONFIG(qml_network)
- QNetworkAccessManager *networkAccessManager() override;
-#endif
-
- QQuickWorkerScriptEnginePrivate *p;
-
- QV4::ReturnedValue sendFunction(int id);
-
- QV4::PersistentValue onmessage;
- private:
- QV4::PersistentValue createsend;
-#if QT_CONFIG(qml_network)
- QNetworkAccessManager *accessManager;
-#endif
- };
-
- static QQuickWorkerScriptEnginePrivate *get(QV8Engine *e) {
- return static_cast<WorkerEngine *>(e)->p;
- }
-
QQmlEngine *qmlengine;
QMutex m_lock;
QWaitCondition m_wait;
- struct WorkerScript {
+ struct WorkerScript : public QV8Engine {
WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent);
- ~WorkerScript();
+ ~WorkerScript() override;
+
+#if QT_CONFIG(qml_network)
+ QNetworkAccessManager *networkAccessManager() override;
+#endif
- QV4::ExecutionEngine *v4() const { return QV8Engine::getV4(workerEngine.data()); }
- QScopedPointer<WorkerEngine> workerEngine;
- int id;
+ QQuickWorkerScriptEnginePrivate *p = nullptr;
QUrl source;
- QQuickWorkerScript *owner;
+ QQuickWorkerScript *owner = nullptr;
+#if QT_CONFIG(qml_network)
+ QScopedPointer<QNetworkAccessManager> accessManager;
+#endif
+ int id = -1;
};
QHash<int, WorkerScript *> workers;
@@ -202,100 +180,6 @@ private:
void reportScriptException(WorkerScript *, const QQmlError &error);
};
-QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent)
- : QV8Engine(new QV4::ExecutionEngine), p(parent)
-#if QT_CONFIG(qml_network)
-, accessManager(nullptr)
-#endif
-{
- m_v4Engine->v8Engine = this;
-}
-
-QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine()
-{
-#if QT_CONFIG(qml_network)
- delete accessManager;
-#endif
- delete m_v4Engine;
-}
-
-void QQuickWorkerScriptEnginePrivate::WorkerEngine::init(int id)
-{
- initQmlGlobalObject();
-#define CALL_ONMESSAGE_SCRIPT \
- "(function(message) { "\
- "var isfunction = false; "\
- "try { "\
- "isfunction = WorkerScript.onMessage instanceof Function; "\
- "} catch (e) {}" \
- "if (isfunction) "\
- "WorkerScript.onMessage(message); "\
- "})"
-
-#define SEND_MESSAGE_CREATE_SCRIPT \
- "(function(method, engine) { "\
- "return (function(id) { "\
- "return (function(message) { "\
- "if (arguments.length) method(engine, id, message); "\
- "}); "\
- "}); "\
- "})"
-
- QV4::Scope scope(m_v4Engine);
- QV4::ExecutionContext *globalContext = scope.engine->rootContext();
- onmessage.set(scope.engine, QV4::Script(globalContext, QV4::Compiler::ContextType::Global, QString::fromUtf8(CALL_ONMESSAGE_SCRIPT)).run()); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
- Q_ASSERT(!scope.engine->hasException);
- QV4::Script createsendscript(globalContext, QV4::Compiler::ContextType::Global, QString::fromUtf8(SEND_MESSAGE_CREATE_SCRIPT)); // do not use QStringLiteral here, MSVC2012 cannot apply this cleanly to the macro
- QV4::ScopedFunctionObject createsendconstructor(scope, createsendscript.run());
- Q_ASSERT(!scope.engine->hasException);
- QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
- QV4::ScopedValue function(scope, QV4::FunctionObject::createBuiltinFunction(m_v4Engine, name, method_sendMessage, 1));
- QV4::JSCallData jsCallData(scope, 1);
- jsCallData->args[0] = function;
- *jsCallData->thisObject = m_v4Engine->global();
- createsend.set(scope.engine, createsendconstructor->call(jsCallData));
-
-
- QV4::ScopedValue v(scope, sendFunction(id));
- QV4::ScopedObject api(scope, scope.engine->newObject());
- api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), v);
- m_v4Engine->globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
-}
-
-// Requires handle and context scope
-QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id)
-{
- QV4::ExecutionEngine *v4 = createsend.engine();
- if (!v4)
- return QV4::Encode::undefined();
-
- QV4::Scope scope(v4);
- QV4::ScopedFunctionObject f(scope, createsend.value());
-
- QV4::ScopedValue v(scope);
- QV4::JSCallData jsCallData(scope, 1);
- jsCallData->args[0] = QV4::Primitive::fromInt32(id);
- *jsCallData->thisObject = m_v4Engine->global();
- v = f->call(jsCallData);
- if (scope.hasException())
- v = scope.engine->catchException();
- return v->asReturnedValue();
-}
-
-#if QT_CONFIG(qml_network)
-QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager()
-{
- if (!accessManager) {
- if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
- accessManager = p->qmlengine->networkAccessManagerFactory()->create(p);
- } else {
- accessManager = new QNetworkAccessManager(p);
- }
- }
- return accessManager;
-}
-#endif
-
QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine)
: qmlengine(engine), m_nextId(0)
{
@@ -305,15 +189,12 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4
const QV4::Value *, const QV4::Value *argv, int argc)
{
QV4::Scope scope(b);
- WorkerEngine *engine = static_cast<WorkerEngine *>(scope.engine->v8Engine);
+ WorkerScript *script = static_cast<WorkerScript *>(scope.engine->v8Engine);
- int id = argc > 1 ? argv[1].toInt32() : 0;
-
- QV4::ScopedValue v(scope, argc > 2 ? argv[2] : QV4::Primitive::undefinedValue());
+ QV4::ScopedValue v(scope, argc > 0 ? argv[0] : QV4::Primitive::undefinedValue());
QByteArray data = QV4::Serialize::serialize(v, scope.engine);
- QMutexLocker locker(&engine->p->m_lock);
- WorkerScript *script = engine->p->workers.value(id);
+ QMutexLocker locker(&script->p->m_lock);
if (script && script->owner)
QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));
@@ -352,16 +233,23 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d
if (!script)
return;
- QV4::ExecutionEngine *v4 = script->v4();
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(script);
QV4::Scope scope(v4);
- QV4::ScopedFunctionObject f(scope, script->workerEngine->onmessage.value());
+ QV4::ScopedString v(scope);
+ QV4::ScopedObject worker(scope, v4->globalObject->get((v = v4->newString(QStringLiteral("WorkerScript")))));
+ QV4::ScopedFunctionObject onmessage(scope);
+ if (worker)
+ onmessage = worker->get((v = v4->newString(QStringLiteral("onMessage"))));
+
+ if (!onmessage)
+ return;
QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4));
QV4::JSCallData jsCallData(scope, 1);
*jsCallData->thisObject = v4->global();
jsCallData->args[0] = value;
- f->call(jsCallData);
+ onmessage->call(jsCallData);
if (scope.hasException()) {
QQmlError error = scope.engine->catchExceptionAsQmlError();
reportScriptException(script, error);
@@ -379,7 +267,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
if (!script)
return;
- QV4::ExecutionEngine *v4 = script->v4();
+ QV4::ExecutionEngine *v4 = QV8Engine::getV4(script);
QV4::Scope scope(v4);
QScopedPointer<QV4::Script> program;
@@ -405,9 +293,7 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url)
void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script,
const QQmlError &error)
{
- QQuickWorkerScriptEnginePrivate *p = QQuickWorkerScriptEnginePrivate::get(script->workerEngine.data());
-
- QMutexLocker locker(&p->m_lock);
+ QMutexLocker locker(&script->p->m_lock);
if (script->owner)
QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error));
}
@@ -497,16 +383,41 @@ QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine()
}
QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
-: id(id), owner(nullptr)
+ : QV8Engine(new QV4::ExecutionEngine)
+ , p(parent)
+ , id(id)
{
- workerEngine.reset(new QQuickWorkerScriptEnginePrivate::WorkerEngine(parent));
- workerEngine->init(id);
+ m_v4Engine->v8Engine = this;
+
+ initQmlGlobalObject();
+
+ QV4::Scope scope(m_v4Engine);
+ QV4::ScopedObject api(scope, scope.engine->newObject());
+ QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage")));
+ QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(m_v4Engine, name, method_sendMessage, 1));
+ api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), sendMessage);
+ m_v4Engine->globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
}
QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript()
{
+ delete m_v4Engine;
}
+#if QT_CONFIG(qml_network)
+QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerScript::networkAccessManager()
+{
+ if (!accessManager) {
+ if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
+ accessManager.reset(p->qmlengine->networkAccessManagerFactory()->create(p));
+ } else {
+ accessManager.reset(new QNetworkAccessManager(p));
+ }
+ }
+ return accessManager.data();
+}
+#endif
+
int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
{
typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript;