| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/qtdeclarative/src/qtdeclarative/src/qml/types/qquickworkerscript.cpp |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /**************************************************************************** | - | ||||||||||||
| 2 | ** | - | ||||||||||||
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | - | ||||||||||||
| 4 | ** Contact: https://www.qt.io/licensing/ | - | ||||||||||||
| 5 | ** | - | ||||||||||||
| 6 | ** This file is part of the QtQml module of the Qt Toolkit. | - | ||||||||||||
| 7 | ** | - | ||||||||||||
| 8 | ** $QT_BEGIN_LICENSE:LGPL$ | - | ||||||||||||
| 9 | ** Commercial License Usage | - | ||||||||||||
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | - | ||||||||||||
| 11 | ** accordance with the commercial license agreement provided with the | - | ||||||||||||
| 12 | ** Software or, alternatively, in accordance with the terms contained in | - | ||||||||||||
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | - | ||||||||||||
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | - | ||||||||||||
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | - | ||||||||||||
| 16 | ** | - | ||||||||||||
| 17 | ** GNU Lesser General Public License Usage | - | ||||||||||||
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | - | ||||||||||||
| 19 | ** General Public License version 3 as published by the Free Software | - | ||||||||||||
| 20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the | - | ||||||||||||
| 21 | ** packaging of this file. Please review the following information to | - | ||||||||||||
| 22 | ** ensure the GNU Lesser General Public License version 3 requirements | - | ||||||||||||
| 23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. | - | ||||||||||||
| 24 | ** | - | ||||||||||||
| 25 | ** GNU General Public License Usage | - | ||||||||||||
| 26 | ** Alternatively, this file may be used under the terms of the GNU | - | ||||||||||||
| 27 | ** General Public License version 2.0 or (at your option) the GNU General | - | ||||||||||||
| 28 | ** Public license version 3 or any later version approved by the KDE Free | - | ||||||||||||
| 29 | ** Qt Foundation. The licenses are as published by the Free Software | - | ||||||||||||
| 30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 | - | ||||||||||||
| 31 | ** included in the packaging of this file. Please review the following | - | ||||||||||||
| 32 | ** information to ensure the GNU General Public License requirements will | - | ||||||||||||
| 33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and | - | ||||||||||||
| 34 | ** https://www.gnu.org/licenses/gpl-3.0.html. | - | ||||||||||||
| 35 | ** | - | ||||||||||||
| 36 | ** $QT_END_LICENSE$ | - | ||||||||||||
| 37 | ** | - | ||||||||||||
| 38 | ****************************************************************************/ | - | ||||||||||||
| 39 | - | |||||||||||||
| 40 | #include "qtqmlglobal_p.h" | - | ||||||||||||
| 41 | #include "qquickworkerscript_p.h" | - | ||||||||||||
| 42 | #if QT_CONFIG(qml_list_model) | - | ||||||||||||
| 43 | #include "qqmllistmodel_p.h" | - | ||||||||||||
| 44 | #include "qqmllistmodelworkeragent_p.h" | - | ||||||||||||
| 45 | #endif | - | ||||||||||||
| 46 | #include <private/qqmlengine_p.h> | - | ||||||||||||
| 47 | #include <private/qqmlexpression_p.h> | - | ||||||||||||
| 48 | - | |||||||||||||
| 49 | #include <QtCore/qcoreevent.h> | - | ||||||||||||
| 50 | #include <QtCore/qcoreapplication.h> | - | ||||||||||||
| 51 | #include <QtCore/qdebug.h> | - | ||||||||||||
| 52 | #include <QtQml/qjsengine.h> | - | ||||||||||||
| 53 | #include <QtCore/qmutex.h> | - | ||||||||||||
| 54 | #include <QtCore/qwaitcondition.h> | - | ||||||||||||
| 55 | #include <QtCore/qfile.h> | - | ||||||||||||
| 56 | #include <QtCore/qdatetime.h> | - | ||||||||||||
| 57 | #include <QtQml/qqmlinfo.h> | - | ||||||||||||
| 58 | #include <QtQml/qqmlfile.h> | - | ||||||||||||
| 59 | #if QT_CONFIG(qml_network) | - | ||||||||||||
| 60 | #include <QtNetwork/qnetworkaccessmanager.h> | - | ||||||||||||
| 61 | #include "qqmlnetworkaccessmanagerfactory.h" | - | ||||||||||||
| 62 | #endif | - | ||||||||||||
| 63 | - | |||||||||||||
| 64 | #include <private/qv8engine_p.h> | - | ||||||||||||
| 65 | #include <private/qv4serialize_p.h> | - | ||||||||||||
| 66 | - | |||||||||||||
| 67 | #include <private/qv4value_p.h> | - | ||||||||||||
| 68 | #include <private/qv4functionobject_p.h> | - | ||||||||||||
| 69 | #include <private/qv4script_p.h> | - | ||||||||||||
| 70 | #include <private/qv4scopedvalue_p.h> | - | ||||||||||||
| 71 | #include <private/qv4jscall_p.h> | - | ||||||||||||
| 72 | - | |||||||||||||
| 73 | QT_BEGIN_NAMESPACE | - | ||||||||||||
| 74 | - | |||||||||||||
| 75 | class WorkerDataEvent : public QEvent | - | ||||||||||||
| 76 | { | - | ||||||||||||
| 77 | public: | - | ||||||||||||
| 78 | enum Type { WorkerData = QEvent::User }; | - | ||||||||||||
| 79 | - | |||||||||||||
| 80 | WorkerDataEvent(int workerId, const QByteArray &data); | - | ||||||||||||
| 81 | virtual ~WorkerDataEvent(); | - | ||||||||||||
| 82 | - | |||||||||||||
| 83 | int workerId() const; | - | ||||||||||||
| 84 | QByteArray data() const; | - | ||||||||||||
| 85 | - | |||||||||||||
| 86 | private: | - | ||||||||||||
| 87 | int m_id; | - | ||||||||||||
| 88 | QByteArray m_data; | - | ||||||||||||
| 89 | }; | - | ||||||||||||
| 90 | - | |||||||||||||
| 91 | class WorkerLoadEvent : public QEvent | - | ||||||||||||
| 92 | { | - | ||||||||||||
| 93 | public: | - | ||||||||||||
| 94 | enum Type { WorkerLoad = WorkerDataEvent::WorkerData + 1 }; | - | ||||||||||||
| 95 | - | |||||||||||||
| 96 | WorkerLoadEvent(int workerId, const QUrl &url); | - | ||||||||||||
| 97 | - | |||||||||||||
| 98 | int workerId() const; | - | ||||||||||||
| 99 | QUrl url() const; | - | ||||||||||||
| 100 | - | |||||||||||||
| 101 | private: | - | ||||||||||||
| 102 | int m_id; | - | ||||||||||||
| 103 | QUrl m_url; | - | ||||||||||||
| 104 | }; | - | ||||||||||||
| 105 | - | |||||||||||||
| 106 | class WorkerRemoveEvent : public QEvent | - | ||||||||||||
| 107 | { | - | ||||||||||||
| 108 | public: | - | ||||||||||||
| 109 | enum Type { WorkerRemove = WorkerLoadEvent::WorkerLoad + 1 }; | - | ||||||||||||
| 110 | - | |||||||||||||
| 111 | WorkerRemoveEvent(int workerId); | - | ||||||||||||
| 112 | - | |||||||||||||
| 113 | int workerId() const; | - | ||||||||||||
| 114 | - | |||||||||||||
| 115 | private: | - | ||||||||||||
| 116 | int m_id; | - | ||||||||||||
| 117 | }; | - | ||||||||||||
| 118 | - | |||||||||||||
| 119 | class WorkerErrorEvent : public QEvent | - | ||||||||||||
| 120 | { | - | ||||||||||||
| 121 | public: | - | ||||||||||||
| 122 | enum Type { WorkerError = WorkerRemoveEvent::WorkerRemove + 1 }; | - | ||||||||||||
| 123 | - | |||||||||||||
| 124 | WorkerErrorEvent(const QQmlError &error); | - | ||||||||||||
| 125 | - | |||||||||||||
| 126 | QQmlError error() const; | - | ||||||||||||
| 127 | - | |||||||||||||
| 128 | private: | - | ||||||||||||
| 129 | QQmlError m_error; | - | ||||||||||||
| 130 | }; | - | ||||||||||||
| 131 | - | |||||||||||||
| 132 | class QQuickWorkerScriptEnginePrivate : public QObject | - | ||||||||||||
| 133 | { | - | ||||||||||||
| 134 | Q_OBJECT | - | ||||||||||||
| 135 | public: | - | ||||||||||||
| 136 | enum WorkerEventTypes { | - | ||||||||||||
| 137 | WorkerDestroyEvent = QEvent::User + 100 | - | ||||||||||||
| 138 | }; | - | ||||||||||||
| 139 | - | |||||||||||||
| 140 | QQuickWorkerScriptEnginePrivate(QQmlEngine *eng); | - | ||||||||||||
| 141 | - | |||||||||||||
| 142 | class WorkerEngine : public QV8Engine | - | ||||||||||||
| 143 | { | - | ||||||||||||
| 144 | public: | - | ||||||||||||
| 145 | WorkerEngine(QQuickWorkerScriptEnginePrivate *parent); | - | ||||||||||||
| 146 | ~WorkerEngine(); | - | ||||||||||||
| 147 | - | |||||||||||||
| 148 | void init(); | - | ||||||||||||
| 149 | - | |||||||||||||
| 150 | #if QT_CONFIG(qml_network) | - | ||||||||||||
| 151 | QNetworkAccessManager *networkAccessManager() override; | - | ||||||||||||
| 152 | #endif | - | ||||||||||||
| 153 | - | |||||||||||||
| 154 | QQuickWorkerScriptEnginePrivate *p; | - | ||||||||||||
| 155 | - | |||||||||||||
| 156 | QV4::ReturnedValue sendFunction(int id); | - | ||||||||||||
| 157 | - | |||||||||||||
| 158 | QV4::PersistentValue onmessage; | - | ||||||||||||
| 159 | private: | - | ||||||||||||
| 160 | QV4::PersistentValue createsend; | - | ||||||||||||
| 161 | #if QT_CONFIG(qml_network) | - | ||||||||||||
| 162 | QNetworkAccessManager *accessManager; | - | ||||||||||||
| 163 | #endif | - | ||||||||||||
| 164 | }; | - | ||||||||||||
| 165 | - | |||||||||||||
| 166 | WorkerEngine *workerEngine; | - | ||||||||||||
| 167 | static QQuickWorkerScriptEnginePrivate *get(QV8Engine *e) { | - | ||||||||||||
| 168 | return static_cast<WorkerEngine *>(e)->p; executed 8 times by 1 test: return static_cast<WorkerEngine *>(e)->p;Executed by:
| 8 | ||||||||||||
| 169 | } | - | ||||||||||||
| 170 | - | |||||||||||||
| 171 | QQmlEngine *qmlengine; | - | ||||||||||||
| 172 | - | |||||||||||||
| 173 | QMutex m_lock; | - | ||||||||||||
| 174 | QWaitCondition m_wait; | - | ||||||||||||
| 175 | - | |||||||||||||
| 176 | struct WorkerScript { | - | ||||||||||||
| 177 | WorkerScript(); | - | ||||||||||||
| 178 | ~WorkerScript(); | - | ||||||||||||
| 179 | - | |||||||||||||
| 180 | int id; | - | ||||||||||||
| 181 | QUrl source; | - | ||||||||||||
| 182 | bool initialized; | - | ||||||||||||
| 183 | QQuickWorkerScript *owner; | - | ||||||||||||
| 184 | QV4::PersistentValue qmlContext; | - | ||||||||||||
| 185 | }; | - | ||||||||||||
| 186 | - | |||||||||||||
| 187 | QHash<int, WorkerScript *> workers; | - | ||||||||||||
| 188 | QV4::ReturnedValue getWorker(WorkerScript *); | - | ||||||||||||
| 189 | - | |||||||||||||
| 190 | int m_nextId; | - | ||||||||||||
| 191 | - | |||||||||||||
| 192 | static QV4::ReturnedValue method_sendMessage(const QV4::FunctionObject *, const QV4::Value *thisObject, const QV4::Value *argv, int argc); | - | ||||||||||||
| 193 | - | |||||||||||||
| 194 | signals: | - | ||||||||||||
| 195 | void stopThread(); | - | ||||||||||||
| 196 | - | |||||||||||||
| 197 | protected: | - | ||||||||||||
| 198 | bool event(QEvent *) override; | - | ||||||||||||
| 199 | - | |||||||||||||
| 200 | private: | - | ||||||||||||
| 201 | void processMessage(int, const QByteArray &); | - | ||||||||||||
| 202 | void processLoad(int, const QUrl &); | - | ||||||||||||
| 203 | void reportScriptException(WorkerScript *, const QQmlError &error); | - | ||||||||||||
| 204 | }; | - | ||||||||||||
| 205 | - | |||||||||||||
| 206 | QQuickWorkerScriptEnginePrivate::WorkerEngine::WorkerEngine(QQuickWorkerScriptEnginePrivate *parent) | - | ||||||||||||
| 207 | : QV8Engine(new QV4::ExecutionEngine), p(parent) | - | ||||||||||||
| 208 | #if QT_CONFIG(qml_network) | - | ||||||||||||
| 209 | , accessManager(nullptr) | - | ||||||||||||
| 210 | #endif | - | ||||||||||||
| 211 | { | - | ||||||||||||
| 212 | m_v4Engine->v8Engine = this; | - | ||||||||||||
| 213 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 214 | - | |||||||||||||
| 215 | QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() | - | ||||||||||||
| 216 | { | - | ||||||||||||
| 217 | #if QT_CONFIG(qml_network) | - | ||||||||||||
| 218 | delete accessManager; | - | ||||||||||||
| 219 | #endif | - | ||||||||||||
| 220 | delete m_v4Engine; | - | ||||||||||||
| 221 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 222 | - | |||||||||||||
| 223 | void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() | - | ||||||||||||
| 224 | { | - | ||||||||||||
| 225 | initQmlGlobalObject(); | - | ||||||||||||
| 226 | #define CALL_ONMESSAGE_SCRIPT \ | - | ||||||||||||
| 227 | "(function(object, message) { "\ | - | ||||||||||||
| 228 | "var isfunction = false; "\ | - | ||||||||||||
| 229 | "try { "\ | - | ||||||||||||
| 230 | "isfunction = object.WorkerScript.onMessage instanceof Function; "\ | - | ||||||||||||
| 231 | "} catch (e) {}" \ | - | ||||||||||||
| 232 | "if (isfunction) "\ | - | ||||||||||||
| 233 | "object.WorkerScript.onMessage(message); "\ | - | ||||||||||||
| 234 | "})" | - | ||||||||||||
| 235 | - | |||||||||||||
| 236 | #define SEND_MESSAGE_CREATE_SCRIPT \ | - | ||||||||||||
| 237 | "(function(method, engine) { "\ | - | ||||||||||||
| 238 | "return (function(id) { "\ | - | ||||||||||||
| 239 | "return (function(message) { "\ | - | ||||||||||||
| 240 | "if (arguments.length) method(engine, id, message); "\ | - | ||||||||||||
| 241 | "}); "\ | - | ||||||||||||
| 242 | "}); "\ | - | ||||||||||||
| 243 | "})" | - | ||||||||||||
| 244 | - | |||||||||||||
| 245 | QV4::Scope scope(m_v4Engine); | - | ||||||||||||
| 246 | QV4::ExecutionContext *globalContext = scope.engine->rootContext(); | - | ||||||||||||
| 247 | 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 | - | ||||||||||||
| 248 | Q_ASSERT(!scope.engine->hasException); | - | ||||||||||||
| 249 | 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 | - | ||||||||||||
| 250 | QV4::ScopedFunctionObject createsendconstructor(scope, createsendscript.run()); | - | ||||||||||||
| 251 | Q_ASSERT(!scope.engine->hasException); | - | ||||||||||||
| 252 | QV4::ScopedString name(scope, m_v4Engine->newString(QStringLiteral("sendMessage"))); executed 1110 times by 5 tests: return qstring_literal_temp;Executed by:
| 1110 | ||||||||||||
| 253 | QV4::ScopedValue function(scope, QV4::FunctionObject::createBuiltinFunction(m_v4Engine, name, method_sendMessage, 1)); | - | ||||||||||||
| 254 | QV4::JSCallData jsCallData(scope, 1); | - | ||||||||||||
| 255 | jsCallData->args[0] = function; | - | ||||||||||||
| 256 | *jsCallData->thisObject = m_v4Engine->global(); | - | ||||||||||||
| 257 | createsend.set(scope.engine, createsendconstructor->call(jsCallData)); | - | ||||||||||||
| 258 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 259 | - | |||||||||||||
| 260 | // Requires handle and context scope | - | ||||||||||||
| 261 | QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::WorkerEngine::sendFunction(int id) | - | ||||||||||||
| 262 | { | - | ||||||||||||
| 263 | QV4::ExecutionEngine *v4 = createsend.engine(); | - | ||||||||||||
| 264 | if (!v4)
| 0-1152 | ||||||||||||
| 265 | return QV4::Encode::undefined(); never executed: return QV4::Encode::undefined(); | 0 | ||||||||||||
| 266 | - | |||||||||||||
| 267 | QV4::Scope scope(v4); | - | ||||||||||||
| 268 | QV4::ScopedFunctionObject f(scope, createsend.value()); | - | ||||||||||||
| 269 | - | |||||||||||||
| 270 | QV4::ScopedValue v(scope); | - | ||||||||||||
| 271 | QV4::JSCallData jsCallData(scope, 1); | - | ||||||||||||
| 272 | jsCallData->args[0] = QV4::Primitive::fromInt32(id); | - | ||||||||||||
| 273 | *jsCallData->thisObject = m_v4Engine->global(); | - | ||||||||||||
| 274 | v = f->call(jsCallData); | - | ||||||||||||
| 275 | if (scope.hasException())
| 0-1152 | ||||||||||||
| 276 | v = scope.engine->catchException(); never executed: v = scope.engine->catchException(); | 0 | ||||||||||||
| 277 | return v->asReturnedValue(); executed 1152 times by 5 tests: return v->asReturnedValue();Executed by:
| 1152 | ||||||||||||
| 278 | } | - | ||||||||||||
| 279 | - | |||||||||||||
| 280 | #if QT_CONFIG(qml_network) | - | ||||||||||||
| 281 | QNetworkAccessManager *QQuickWorkerScriptEnginePrivate::WorkerEngine::networkAccessManager() | - | ||||||||||||
| 282 | { | - | ||||||||||||
| 283 | if (!accessManager) {
| 0 | ||||||||||||
| 284 | if (p->qmlengine && p->qmlengine->networkAccessManagerFactory()) {
| 0 | ||||||||||||
| 285 | accessManager = p->qmlengine->networkAccessManagerFactory()->create(p); | - | ||||||||||||
| 286 | } else { never executed: end of block | 0 | ||||||||||||
| 287 | accessManager = new QNetworkAccessManager(p); | - | ||||||||||||
| 288 | } never executed: end of block | 0 | ||||||||||||
| 289 | } | - | ||||||||||||
| 290 | return accessManager; never executed: return accessManager; | 0 | ||||||||||||
| 291 | } | - | ||||||||||||
| 292 | #endif | - | ||||||||||||
| 293 | - | |||||||||||||
| 294 | QQuickWorkerScriptEnginePrivate::QQuickWorkerScriptEnginePrivate(QQmlEngine *engine) | - | ||||||||||||
| 295 | : workerEngine(nullptr), qmlengine(engine), m_nextId(0) | - | ||||||||||||
| 296 | { | - | ||||||||||||
| 297 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 298 | - | |||||||||||||
| 299 | QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4::FunctionObject *b, | - | ||||||||||||
| 300 | const QV4::Value *, const QV4::Value *argv, int argc) | - | ||||||||||||
| 301 | { | - | ||||||||||||
| 302 | QV4::Scope scope(b); | - | ||||||||||||
| 303 | WorkerEngine *engine = static_cast<WorkerEngine *>(scope.engine->v8Engine); | - | ||||||||||||
| 304 | - | |||||||||||||
| 305 | int id = argc > 1 ? argv[1].toInt32() : 0;
| 0-976 | ||||||||||||
| 306 | - | |||||||||||||
| 307 | QV4::ScopedValue v(scope, argc > 2 ? argv[2] : QV4::Primitive::undefinedValue()); | - | ||||||||||||
| 308 | QByteArray data = QV4::Serialize::serialize(v, scope.engine); | - | ||||||||||||
| 309 | - | |||||||||||||
| 310 | QMutexLocker locker(&engine->p->m_lock); | - | ||||||||||||
| 311 | WorkerScript *script = engine->p->workers.value(id); | - | ||||||||||||
| 312 | if (script && script->owner)
| 0-976 | ||||||||||||
| 313 | QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data)); executed 972 times by 4 tests: QCoreApplication::postEvent(script->owner, new WorkerDataEvent(0, data));Executed by:
| 972 | ||||||||||||
| 314 | - | |||||||||||||
| 315 | return QV4::Encode::undefined(); executed 976 times by 4 tests: return QV4::Encode::undefined();Executed by:
| 976 | ||||||||||||
| 316 | } | - | ||||||||||||
| 317 | - | |||||||||||||
| 318 | QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script) | - | ||||||||||||
| 319 | { | - | ||||||||||||
| 320 | if (!script->initialized) {
| 2-1152 | ||||||||||||
| 321 | script->initialized = true; | - | ||||||||||||
| 322 | - | |||||||||||||
| 323 | QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine); | - | ||||||||||||
| 324 | QV4::Scope scope(v4); | - | ||||||||||||
| 325 | QV4::ScopedValue v(scope, workerEngine->sendFunction(script->id)); | - | ||||||||||||
| 326 | script->qmlContext.set(v4, QV4::QmlContext::createWorkerContext(v4->rootContext(), script->source, v)); | - | ||||||||||||
| 327 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 328 | - | |||||||||||||
| 329 | return script->qmlContext.value(); executed 1154 times by 5 tests: return script->qmlContext.value();Executed by:
| 1154 | ||||||||||||
| 330 | } | - | ||||||||||||
| 331 | - | |||||||||||||
| 332 | bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) | - | ||||||||||||
| 333 | { | - | ||||||||||||
| 334 | if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
| 1182-4526 | ||||||||||||
| 335 | WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event); | - | ||||||||||||
| 336 | processMessage(workerEvent->workerId(), workerEvent->data()); | - | ||||||||||||
| 337 | return true; executed 1182 times by 5 tests: return true;Executed by:
| 1182 | ||||||||||||
| 338 | } else if (event->type() == (QEvent::Type)WorkerLoadEvent::WorkerLoad) {
| 1154-3372 | ||||||||||||
| 339 | WorkerLoadEvent *workerEvent = static_cast<WorkerLoadEvent *>(event); | - | ||||||||||||
| 340 | processLoad(workerEvent->workerId(), workerEvent->url()); | - | ||||||||||||
| 341 | return true; executed 1154 times by 5 tests: return true;Executed by:
| 1154 | ||||||||||||
| 342 | } else if (event->type() == (QEvent::Type)WorkerDestroyEvent) {
| 1110-2262 | ||||||||||||
| 343 | emit stopThread(); | - | ||||||||||||
| 344 | return true; executed 1110 times by 5 tests: return true;Executed by:
| 1110 | ||||||||||||
| 345 | } else if (event->type() == (QEvent::Type)WorkerRemoveEvent::WorkerRemove) {
| 1110-1152 | ||||||||||||
| 346 | WorkerRemoveEvent *workerEvent = static_cast<WorkerRemoveEvent *>(event); | - | ||||||||||||
| 347 | QHash<int, WorkerScript *>::iterator itr = workers.find(workerEvent->workerId()); | - | ||||||||||||
| 348 | if (itr != workers.end()) {
| 0-1152 | ||||||||||||
| 349 | delete itr.value(); | - | ||||||||||||
| 350 | workers.erase(itr); | - | ||||||||||||
| 351 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 352 | return true; executed 1152 times by 5 tests: return true;Executed by:
| 1152 | ||||||||||||
| 353 | } else { | - | ||||||||||||
| 354 | return QObject::event(event); executed 1110 times by 5 tests: return QObject::event(event);Executed by:
| 1110 | ||||||||||||
| 355 | } | - | ||||||||||||
| 356 | } | - | ||||||||||||
| 357 | - | |||||||||||||
| 358 | void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &data) | - | ||||||||||||
| 359 | { | - | ||||||||||||
| 360 | WorkerScript *script = workers.value(id); | - | ||||||||||||
| 361 | if (!script)
| 0-1182 | ||||||||||||
| 362 | return; never executed: return; | 0 | ||||||||||||
| 363 | - | |||||||||||||
| 364 | QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine); | - | ||||||||||||
| 365 | QV4::Scope scope(v4); | - | ||||||||||||
| 366 | QV4::ScopedFunctionObject f(scope, workerEngine->onmessage.value()); | - | ||||||||||||
| 367 | - | |||||||||||||
| 368 | QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4)); | - | ||||||||||||
| 369 | QV4::Scoped<QV4::QmlContext> qmlContext(scope, script->qmlContext.value()); | - | ||||||||||||
| 370 | Q_ASSERT(!!qmlContext); | - | ||||||||||||
| 371 | - | |||||||||||||
| 372 | QV4::JSCallData jsCallData(scope, 2); | - | ||||||||||||
| 373 | *jsCallData->thisObject = v4->global(); | - | ||||||||||||
| 374 | jsCallData->args[0] = qmlContext->d()->qml(); // ### | - | ||||||||||||
| 375 | jsCallData->args[1] = value; | - | ||||||||||||
| 376 | f->call(jsCallData); | - | ||||||||||||
| 377 | if (scope.hasException()) {
| 4-1178 | ||||||||||||
| 378 | QQmlError error = scope.engine->catchExceptionAsQmlError(); | - | ||||||||||||
| 379 | reportScriptException(script, error); | - | ||||||||||||
| 380 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||
| 381 | } executed 1182 times by 5 tests: end of blockExecuted by:
| 1182 | ||||||||||||
| 382 | - | |||||||||||||
| 383 | void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) | - | ||||||||||||
| 384 | { | - | ||||||||||||
| 385 | if (url.isRelative())
| 0-1154 | ||||||||||||
| 386 | return; never executed: return; | 0 | ||||||||||||
| 387 | - | |||||||||||||
| 388 | QString fileName = QQmlFile::urlToLocalFileOrQrc(url); | - | ||||||||||||
| 389 | - | |||||||||||||
| 390 | QV4::ExecutionEngine *v4 = QV8Engine::getV4(workerEngine); | - | ||||||||||||
| 391 | QV4::Scope scope(v4); | - | ||||||||||||
| 392 | QScopedPointer<QV4::Script> program; | - | ||||||||||||
| 393 | - | |||||||||||||
| 394 | WorkerScript *script = workers.value(id); | - | ||||||||||||
| 395 | if (!script)
| 0-1154 | ||||||||||||
| 396 | return; never executed: return; | 0 | ||||||||||||
| 397 | script->source = url; | - | ||||||||||||
| 398 | - | |||||||||||||
| 399 | QV4::Scoped<QV4::QmlContext> qmlContext(scope, getWorker(script)); | - | ||||||||||||
| 400 | Q_ASSERT(!!qmlContext); | - | ||||||||||||
| 401 | - | |||||||||||||
| 402 | QString error; | - | ||||||||||||
| 403 | program.reset(QV4::Script::createFromFileOrCache(v4, qmlContext, fileName, url, &error)); | - | ||||||||||||
| 404 | if (program.isNull()) {
| 0-1154 | ||||||||||||
| 405 | if (!error.isEmpty())
| 0 | ||||||||||||
| 406 | qWarning().nospace() << error; never executed: QMessageLogger(__FILE__, 406, __PRETTY_FUNCTION__).warning().nospace() << error; | 0 | ||||||||||||
| 407 | return; never executed: return; | 0 | ||||||||||||
| 408 | } | - | ||||||||||||
| 409 | - | |||||||||||||
| 410 | if (!v4->hasException)
| 2-1152 | ||||||||||||
| 411 | program->run(); executed 1152 times by 5 tests: program->run();Executed by:
| 1152 | ||||||||||||
| 412 | - | |||||||||||||
| 413 | if (v4->hasException) {
| 4-1150 | ||||||||||||
| 414 | QQmlError error = v4->catchExceptionAsQmlError(); | - | ||||||||||||
| 415 | reportScriptException(script, error); | - | ||||||||||||
| 416 | } executed 4 times by 1 test: end of blockExecuted by:
| 4 | ||||||||||||
| 417 | } executed 1154 times by 5 tests: end of blockExecuted by:
| 1154 | ||||||||||||
| 418 | - | |||||||||||||
| 419 | void QQuickWorkerScriptEnginePrivate::reportScriptException(WorkerScript *script, | - | ||||||||||||
| 420 | const QQmlError &error) | - | ||||||||||||
| 421 | { | - | ||||||||||||
| 422 | QQuickWorkerScriptEnginePrivate *p = QQuickWorkerScriptEnginePrivate::get(workerEngine); | - | ||||||||||||
| 423 | - | |||||||||||||
| 424 | QMutexLocker locker(&p->m_lock); | - | ||||||||||||
| 425 | if (script->owner)
| 0-8 | ||||||||||||
| 426 | QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error)); executed 8 times by 1 test: QCoreApplication::postEvent(script->owner, new WorkerErrorEvent(error));Executed by:
| 8 | ||||||||||||
| 427 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||
| 428 | - | |||||||||||||
| 429 | WorkerDataEvent::WorkerDataEvent(int workerId, const QByteArray &data) | - | ||||||||||||
| 430 | : QEvent((QEvent::Type)WorkerData), m_id(workerId), m_data(data) | - | ||||||||||||
| 431 | { | - | ||||||||||||
| 432 | } executed 2154 times by 5 tests: end of blockExecuted by:
| 2154 | ||||||||||||
| 433 | - | |||||||||||||
| 434 | WorkerDataEvent::~WorkerDataEvent() | - | ||||||||||||
| 435 | { | - | ||||||||||||
| 436 | } | - | ||||||||||||
| 437 | - | |||||||||||||
| 438 | int WorkerDataEvent::workerId() const | - | ||||||||||||
| 439 | { | - | ||||||||||||
| 440 | return m_id; executed 1182 times by 5 tests: return m_id;Executed by:
| 1182 | ||||||||||||
| 441 | } | - | ||||||||||||
| 442 | - | |||||||||||||
| 443 | QByteArray WorkerDataEvent::data() const | - | ||||||||||||
| 444 | { | - | ||||||||||||
| 445 | return m_data; executed 2154 times by 5 tests: return m_data;Executed by:
| 2154 | ||||||||||||
| 446 | } | - | ||||||||||||
| 447 | - | |||||||||||||
| 448 | WorkerLoadEvent::WorkerLoadEvent(int workerId, const QUrl &url) | - | ||||||||||||
| 449 | : QEvent((QEvent::Type)WorkerLoad), m_id(workerId), m_url(url) | - | ||||||||||||
| 450 | { | - | ||||||||||||
| 451 | } executed 1154 times by 5 tests: end of blockExecuted by:
| 1154 | ||||||||||||
| 452 | - | |||||||||||||
| 453 | int WorkerLoadEvent::workerId() const | - | ||||||||||||
| 454 | { | - | ||||||||||||
| 455 | return m_id; executed 1154 times by 5 tests: return m_id;Executed by:
| 1154 | ||||||||||||
| 456 | } | - | ||||||||||||
| 457 | - | |||||||||||||
| 458 | QUrl WorkerLoadEvent::url() const | - | ||||||||||||
| 459 | { | - | ||||||||||||
| 460 | return m_url; executed 1154 times by 5 tests: return m_url;Executed by:
| 1154 | ||||||||||||
| 461 | } | - | ||||||||||||
| 462 | - | |||||||||||||
| 463 | WorkerRemoveEvent::WorkerRemoveEvent(int workerId) | - | ||||||||||||
| 464 | : QEvent((QEvent::Type)WorkerRemove), m_id(workerId) | - | ||||||||||||
| 465 | { | - | ||||||||||||
| 466 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 467 | - | |||||||||||||
| 468 | int WorkerRemoveEvent::workerId() const | - | ||||||||||||
| 469 | { | - | ||||||||||||
| 470 | return m_id; executed 1152 times by 5 tests: return m_id;Executed by:
| 1152 | ||||||||||||
| 471 | } | - | ||||||||||||
| 472 | - | |||||||||||||
| 473 | WorkerErrorEvent::WorkerErrorEvent(const QQmlError &error) | - | ||||||||||||
| 474 | : QEvent((QEvent::Type)WorkerError), m_error(error) | - | ||||||||||||
| 475 | { | - | ||||||||||||
| 476 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||
| 477 | - | |||||||||||||
| 478 | QQmlError WorkerErrorEvent::error() const | - | ||||||||||||
| 479 | { | - | ||||||||||||
| 480 | return m_error; executed 8 times by 1 test: return m_error;Executed by:
| 8 | ||||||||||||
| 481 | } | - | ||||||||||||
| 482 | - | |||||||||||||
| 483 | QQuickWorkerScriptEngine::QQuickWorkerScriptEngine(QQmlEngine *parent) | - | ||||||||||||
| 484 | : QThread(parent), d(new QQuickWorkerScriptEnginePrivate(parent)) | - | ||||||||||||
| 485 | { | - | ||||||||||||
| 486 | d->m_lock.lock(); | - | ||||||||||||
| 487 | connect(d, SIGNAL(stopThread()), this, SLOT(quit()), Qt::DirectConnection); | - | ||||||||||||
| 488 | start(QThread::LowestPriority); | - | ||||||||||||
| 489 | d->m_wait.wait(&d->m_lock); | - | ||||||||||||
| 490 | d->moveToThread(this); | - | ||||||||||||
| 491 | d->m_lock.unlock(); | - | ||||||||||||
| 492 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 493 | - | |||||||||||||
| 494 | QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine() | - | ||||||||||||
| 495 | { | - | ||||||||||||
| 496 | d->m_lock.lock(); | - | ||||||||||||
| 497 | QCoreApplication::postEvent(d, new QEvent((QEvent::Type)QQuickWorkerScriptEnginePrivate::WorkerDestroyEvent)); | - | ||||||||||||
| 498 | d->m_lock.unlock(); | - | ||||||||||||
| 499 | - | |||||||||||||
| 500 | //We have to force to cleanup the main thread's event queue here | - | ||||||||||||
| 501 | //to make sure the main GUI release all pending locks/wait conditions which | - | ||||||||||||
| 502 | //some worker script/agent are waiting for (QQmlListModelWorkerAgent::sync() for example). | - | ||||||||||||
| 503 | while (!isFinished()) {
| 1110-136696 | ||||||||||||
| 504 | // We can't simply wait here, because the worker thread will not terminate | - | ||||||||||||
| 505 | // until the main thread processes the last data event it generates | - | ||||||||||||
| 506 | QCoreApplication::processEvents(); | - | ||||||||||||
| 507 | yieldCurrentThread(); | - | ||||||||||||
| 508 | } executed 136696 times by 5 tests: end of blockExecuted by:
| 136696 | ||||||||||||
| 509 | - | |||||||||||||
| 510 | d->deleteLater(); | - | ||||||||||||
| 511 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 512 | - | |||||||||||||
| 513 | QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript() | - | ||||||||||||
| 514 | : id(-1), initialized(false), owner(nullptr) | - | ||||||||||||
| 515 | { | - | ||||||||||||
| 516 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 517 | - | |||||||||||||
| 518 | QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript() | - | ||||||||||||
| 519 | { | - | ||||||||||||
| 520 | } | - | ||||||||||||
| 521 | - | |||||||||||||
| 522 | int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner) | - | ||||||||||||
| 523 | { | - | ||||||||||||
| 524 | typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript; | - | ||||||||||||
| 525 | WorkerScript *script = new WorkerScript; | - | ||||||||||||
| 526 | - | |||||||||||||
| 527 | script->id = d->m_nextId++; | - | ||||||||||||
| 528 | script->owner = owner; | - | ||||||||||||
| 529 | - | |||||||||||||
| 530 | d->m_lock.lock(); | - | ||||||||||||
| 531 | d->workers.insert(script->id, script); | - | ||||||||||||
| 532 | d->m_lock.unlock(); | - | ||||||||||||
| 533 | - | |||||||||||||
| 534 | return script->id; executed 1152 times by 5 tests: return script->id;Executed by:
| 1152 | ||||||||||||
| 535 | } | - | ||||||||||||
| 536 | - | |||||||||||||
| 537 | void QQuickWorkerScriptEngine::removeWorkerScript(int id) | - | ||||||||||||
| 538 | { | - | ||||||||||||
| 539 | QQuickWorkerScriptEnginePrivate::WorkerScript* script = d->workers.value(id); | - | ||||||||||||
| 540 | if (script) {
| 0-1152 | ||||||||||||
| 541 | script->owner = nullptr; | - | ||||||||||||
| 542 | QCoreApplication::postEvent(d, new WorkerRemoveEvent(id)); | - | ||||||||||||
| 543 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 544 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 545 | - | |||||||||||||
| 546 | void QQuickWorkerScriptEngine::executeUrl(int id, const QUrl &url) | - | ||||||||||||
| 547 | { | - | ||||||||||||
| 548 | QCoreApplication::postEvent(d, new WorkerLoadEvent(id, url)); | - | ||||||||||||
| 549 | } executed 1154 times by 5 tests: end of blockExecuted by:
| 1154 | ||||||||||||
| 550 | - | |||||||||||||
| 551 | void QQuickWorkerScriptEngine::sendMessage(int id, const QByteArray &data) | - | ||||||||||||
| 552 | { | - | ||||||||||||
| 553 | QCoreApplication::postEvent(d, new WorkerDataEvent(id, data)); | - | ||||||||||||
| 554 | } executed 1182 times by 5 tests: end of blockExecuted by:
| 1182 | ||||||||||||
| 555 | - | |||||||||||||
| 556 | void QQuickWorkerScriptEngine::run() | - | ||||||||||||
| 557 | { | - | ||||||||||||
| 558 | d->m_lock.lock(); | - | ||||||||||||
| 559 | - | |||||||||||||
| 560 | d->workerEngine = new QQuickWorkerScriptEnginePrivate::WorkerEngine(d); | - | ||||||||||||
| 561 | d->workerEngine->init(); | - | ||||||||||||
| 562 | - | |||||||||||||
| 563 | d->m_wait.wakeAll(); | - | ||||||||||||
| 564 | - | |||||||||||||
| 565 | d->m_lock.unlock(); | - | ||||||||||||
| 566 | - | |||||||||||||
| 567 | exec(); | - | ||||||||||||
| 568 | - | |||||||||||||
| 569 | qDeleteAll(d->workers); | - | ||||||||||||
| 570 | d->workers.clear(); | - | ||||||||||||
| 571 | - | |||||||||||||
| 572 | delete d->workerEngine; d->workerEngine = nullptr; | - | ||||||||||||
| 573 | } executed 1110 times by 5 tests: end of blockExecuted by:
| 1110 | ||||||||||||
| 574 | - | |||||||||||||
| 575 | - | |||||||||||||
| 576 | /*! | - | ||||||||||||
| 577 | \qmltype WorkerScript | - | ||||||||||||
| 578 | \instantiates QQuickWorkerScript | - | ||||||||||||
| 579 | \ingroup qtquick-threading | - | ||||||||||||
| 580 | \inqmlmodule QtQuick | - | ||||||||||||
| 581 | \brief Enables the use of threads in a Qt Quick application. | - | ||||||||||||
| 582 | - | |||||||||||||
| 583 | Use WorkerScript to run operations in a new thread. | - | ||||||||||||
| 584 | This is useful for running operations in the background so | - | ||||||||||||
| 585 | that the main GUI thread is not blocked. | - | ||||||||||||
| 586 | - | |||||||||||||
| 587 | Messages can be passed between the new thread and the parent thread | - | ||||||||||||
| 588 | using \l sendMessage() and the \c onMessage() handler. | - | ||||||||||||
| 589 | - | |||||||||||||
| 590 | An example: | - | ||||||||||||
| 591 | - | |||||||||||||
| 592 | \snippet qml/workerscript/workerscript.qml 0 | - | ||||||||||||
| 593 | - | |||||||||||||
| 594 | The above worker script specifies a JavaScript file, "script.js", that handles | - | ||||||||||||
| 595 | the operations to be performed in the new thread. Here is \c script.js: | - | ||||||||||||
| 596 | - | |||||||||||||
| 597 | \quotefile qml/workerscript/script.js | - | ||||||||||||
| 598 | - | |||||||||||||
| 599 | When the user clicks anywhere within the rectangle, \c sendMessage() is | - | ||||||||||||
| 600 | called, triggering the \tt WorkerScript.onMessage() handler in | - | ||||||||||||
| 601 | \tt script.js. This in turn sends a reply message that is then received | - | ||||||||||||
| 602 | by the \tt onMessage() handler of \tt myWorker. | - | ||||||||||||
| 603 | - | |||||||||||||
| 604 | - | |||||||||||||
| 605 | \section3 Restrictions | - | ||||||||||||
| 606 | - | |||||||||||||
| 607 | Since the \c WorkerScript.onMessage() function is run in a separate thread, the | - | ||||||||||||
| 608 | JavaScript file is evaluated in a context separate from the main QML engine. This means | - | ||||||||||||
| 609 | that unlike an ordinary JavaScript file that is imported into QML, the \c script.js | - | ||||||||||||
| 610 | in the above example cannot access the properties, methods or other attributes | - | ||||||||||||
| 611 | of the QML item, nor can it access any context properties set on the QML object | - | ||||||||||||
| 612 | through QQmlContext. | - | ||||||||||||
| 613 | - | |||||||||||||
| 614 | Additionally, there are restrictions on the types of values that can be passed to and | - | ||||||||||||
| 615 | from the worker script. See the sendMessage() documentation for details. | - | ||||||||||||
| 616 | - | |||||||||||||
| 617 | Worker script can not use \l {qtqml-javascript-imports.html}{.import} syntax. | - | ||||||||||||
| 618 | - | |||||||||||||
| 619 | \sa {Qt Quick Examples - Threading}, | - | ||||||||||||
| 620 | {Threaded ListModel Example} | - | ||||||||||||
| 621 | */ | - | ||||||||||||
| 622 | QQuickWorkerScript::QQuickWorkerScript(QObject *parent) | - | ||||||||||||
| 623 | : QObject(parent), m_engine(nullptr), m_scriptId(-1), m_componentComplete(true) | - | ||||||||||||
| 624 | { | - | ||||||||||||
| 625 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 626 | - | |||||||||||||
| 627 | QQuickWorkerScript::~QQuickWorkerScript() | - | ||||||||||||
| 628 | { | - | ||||||||||||
| 629 | if (m_scriptId != -1) m_engine->removeWorkerScript(m_scriptId); executed 1152 times by 5 tests: m_engine->removeWorkerScript(m_scriptId);Executed by:
| 0-1152 | ||||||||||||
| 630 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 631 | - | |||||||||||||
| 632 | /*! | - | ||||||||||||
| 633 | \qmlproperty url WorkerScript::source | - | ||||||||||||
| 634 | - | |||||||||||||
| 635 | This holds the url of the JavaScript file that implements the | - | ||||||||||||
| 636 | \tt WorkerScript.onMessage() handler for threaded operations. | - | ||||||||||||
| 637 | */ | - | ||||||||||||
| 638 | QUrl QQuickWorkerScript::source() const | - | ||||||||||||
| 639 | { | - | ||||||||||||
| 640 | return m_source; executed 2 times by 1 test: return m_source;Executed by:
| 2 | ||||||||||||
| 641 | } | - | ||||||||||||
| 642 | - | |||||||||||||
| 643 | void QQuickWorkerScript::setSource(const QUrl &source) | - | ||||||||||||
| 644 | { | - | ||||||||||||
| 645 | if (m_source == source)
| 0-1154 | ||||||||||||
| 646 | return; never executed: return; | 0 | ||||||||||||
| 647 | - | |||||||||||||
| 648 | m_source = source; | - | ||||||||||||
| 649 | - | |||||||||||||
| 650 | if (engine())
| 2-1152 | ||||||||||||
| 651 | m_engine->executeUrl(m_scriptId, m_source); executed 2 times by 1 test: m_engine->executeUrl(m_scriptId, m_source);Executed by:
| 2 | ||||||||||||
| 652 | - | |||||||||||||
| 653 | emit sourceChanged(); | - | ||||||||||||
| 654 | } executed 1154 times by 5 tests: end of blockExecuted by:
| 1154 | ||||||||||||
| 655 | - | |||||||||||||
| 656 | /*! | - | ||||||||||||
| 657 | \qmlmethod WorkerScript::sendMessage(jsobject message) | - | ||||||||||||
| 658 | - | |||||||||||||
| 659 | Sends the given \a message to a worker script handler in another | - | ||||||||||||
| 660 | thread. The other worker script handler can receive this message | - | ||||||||||||
| 661 | through the onMessage() handler. | - | ||||||||||||
| 662 | - | |||||||||||||
| 663 | The \c message object may only contain values of the following | - | ||||||||||||
| 664 | types: | - | ||||||||||||
| 665 | - | |||||||||||||
| 666 | \list | - | ||||||||||||
| 667 | \li boolean, number, string | - | ||||||||||||
| 668 | \li JavaScript objects and arrays | - | ||||||||||||
| 669 | \li ListModel objects (any other type of QObject* is not allowed) | - | ||||||||||||
| 670 | \endlist | - | ||||||||||||
| 671 | - | |||||||||||||
| 672 | All objects and arrays are copied to the \c message. With the exception | - | ||||||||||||
| 673 | of ListModel objects, any modifications by the other thread to an object | - | ||||||||||||
| 674 | passed in \c message will not be reflected in the original object. | - | ||||||||||||
| 675 | */ | - | ||||||||||||
| 676 | void QQuickWorkerScript::sendMessage(QQmlV4Function *args) | - | ||||||||||||
| 677 | { | - | ||||||||||||
| 678 | if (!engine()) {
| 4-1182 | ||||||||||||
| 679 | qWarning("QQuickWorkerScript: Attempt to send message before WorkerScript establishment"); | - | ||||||||||||
| 680 | return; executed 4 times by 1 test: return;Executed by:
| 4 | ||||||||||||
| 681 | } | - | ||||||||||||
| 682 | - | |||||||||||||
| 683 | QV4::Scope scope(args->v4engine()); | - | ||||||||||||
| 684 | QV4::ScopedValue argument(scope, QV4::Primitive::undefinedValue()); | - | ||||||||||||
| 685 | if (args->length() != 0)
| 0-1182 | ||||||||||||
| 686 | argument = (*args)[0]; executed 1182 times by 5 tests: argument = (*args)[0];Executed by:
| 1182 | ||||||||||||
| 687 | - | |||||||||||||
| 688 | m_engine->sendMessage(m_scriptId, QV4::Serialize::serialize(argument, scope.engine)); | - | ||||||||||||
| 689 | } executed 1182 times by 5 tests: end of blockExecuted by:
| 1182 | ||||||||||||
| 690 | - | |||||||||||||
| 691 | void QQuickWorkerScript::classBegin() | - | ||||||||||||
| 692 | { | - | ||||||||||||
| 693 | m_componentComplete = false; | - | ||||||||||||
| 694 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 695 | - | |||||||||||||
| 696 | QQuickWorkerScriptEngine *QQuickWorkerScript::engine() | - | ||||||||||||
| 697 | { | - | ||||||||||||
| 698 | if (m_engine) return m_engine; executed 1184 times by 5 tests: return m_engine;Executed by:
| 1184-2308 | ||||||||||||
| 699 | if (m_componentComplete) {
| 1152-1156 | ||||||||||||
| 700 | QQmlEngine *engine = qmlEngine(this); | - | ||||||||||||
| 701 | if (!engine) {
| 0-1152 | ||||||||||||
| 702 | qWarning("QQuickWorkerScript: engine() called without qmlEngine() set"); | - | ||||||||||||
| 703 | return nullptr; never executed: return nullptr; | 0 | ||||||||||||
| 704 | } | - | ||||||||||||
| 705 | - | |||||||||||||
| 706 | m_engine = QQmlEnginePrivate::get(engine)->getWorkerScriptEngine(); | - | ||||||||||||
| 707 | m_scriptId = m_engine->registerWorkerScript(this); | - | ||||||||||||
| 708 | - | |||||||||||||
| 709 | if (m_source.isValid())
| 0-1152 | ||||||||||||
| 710 | m_engine->executeUrl(m_scriptId, m_source); executed 1152 times by 5 tests: m_engine->executeUrl(m_scriptId, m_source);Executed by:
| 1152 | ||||||||||||
| 711 | - | |||||||||||||
| 712 | return m_engine; executed 1152 times by 5 tests: return m_engine;Executed by:
| 1152 | ||||||||||||
| 713 | } | - | ||||||||||||
| 714 | return nullptr; executed 1156 times by 5 tests: return nullptr;Executed by:
| 1156 | ||||||||||||
| 715 | } | - | ||||||||||||
| 716 | - | |||||||||||||
| 717 | void QQuickWorkerScript::componentComplete() | - | ||||||||||||
| 718 | { | - | ||||||||||||
| 719 | m_componentComplete = true; | - | ||||||||||||
| 720 | engine(); // Get it started now. | - | ||||||||||||
| 721 | } executed 1152 times by 5 tests: end of blockExecuted by:
| 1152 | ||||||||||||
| 722 | - | |||||||||||||
| 723 | /*! | - | ||||||||||||
| 724 | \qmlsignal WorkerScript::message(jsobject msg) | - | ||||||||||||
| 725 | - | |||||||||||||
| 726 | This signal is emitted when a message \a msg is received from a worker | - | ||||||||||||
| 727 | script in another thread through a call to sendMessage(). | - | ||||||||||||
| 728 | - | |||||||||||||
| 729 | The corresponding handler is \c onMessage. | - | ||||||||||||
| 730 | */ | - | ||||||||||||
| 731 | - | |||||||||||||
| 732 | bool QQuickWorkerScript::event(QEvent *event) | - | ||||||||||||
| 733 | { | - | ||||||||||||
| 734 | if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) {
| 8-972 | ||||||||||||
| 735 | QQmlEngine *engine = qmlEngine(this); | - | ||||||||||||
| 736 | if (engine) {
| 0-972 | ||||||||||||
| 737 | WorkerDataEvent *workerEvent = static_cast<WorkerDataEvent *>(event); | - | ||||||||||||
| 738 | QV4::Scope scope(engine->handle()); | - | ||||||||||||
| 739 | QV4::ScopedValue value(scope, QV4::Serialize::deserialize(workerEvent->data(), scope.engine)); | - | ||||||||||||
| 740 | emit message(QQmlV4Handle(value)); | - | ||||||||||||
| 741 | } executed 972 times by 4 tests: end of blockExecuted by:
| 972 | ||||||||||||
| 742 | return true; executed 972 times by 4 tests: return true;Executed by:
| 972 | ||||||||||||
| 743 | } else if (event->type() == (QEvent::Type)WorkerErrorEvent::WorkerError) {
| 0-8 | ||||||||||||
| 744 | WorkerErrorEvent *workerEvent = static_cast<WorkerErrorEvent *>(event); | - | ||||||||||||
| 745 | QQmlEnginePrivate::warning(qmlEngine(this), workerEvent->error()); | - | ||||||||||||
| 746 | return true; executed 8 times by 1 test: return true;Executed by:
| 8 | ||||||||||||
| 747 | } else { | - | ||||||||||||
| 748 | return QObject::event(event); never executed: return QObject::event(event); | 0 | ||||||||||||
| 749 | } | - | ||||||||||||
| 750 | } | - | ||||||||||||
| 751 | - | |||||||||||||
| 752 | QT_END_NAMESPACE | - | ||||||||||||
| 753 | - | |||||||||||||
| 754 | #include <qquickworkerscript.moc> | - | ||||||||||||
| 755 | - | |||||||||||||
| 756 | #include "moc_qquickworkerscript_p.cpp" | - | ||||||||||||
| Source code | Switch to Preprocessed file |