diff options
-rw-r--r-- | src/qml/jsruntime/qv4include.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext.cpp | 53 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qmlcontext_p.h | 5 | ||||
-rw-r--r-- | src/qml/types/qquickworkerscript.cpp | 55 | ||||
-rw-r--r-- | tests/auto/qml/qquickworkerscript/data/script_global.js | 5 | ||||
-rw-r--r-- | tests/auto/qml/qquickworkerscript/data/script_global2.js | 6 | ||||
-rw-r--r-- | tests/auto/qml/qquickworkerscript/data/worker_global.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qquickworkerscript/data/worker_global2.qml | 5 | ||||
-rw-r--r-- | tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp | 42 |
9 files changed, 24 insertions, 154 deletions
diff --git a/src/qml/jsruntime/qv4include.cpp b/src/qml/jsruntime/qv4include.cpp index d0d66c9b9a..e3e16fa070 100644 --- a/src/qml/jsruntime/qv4include.cpp +++ b/src/qml/jsruntime/qv4include.cpp @@ -207,7 +207,7 @@ QV4::ReturnedValue QV4Include::method_include(const QV4::FunctionObject *b, cons QQmlContextData *context = scope.engine->callingQmlContext(); - if (!context || !context->isJSContext) + if ((!context || !context->isJSContext) && scope.engine->qmlEngine()) RETURN_RESULT(scope.engine->throwError(QString::fromUtf8("Qt.include(): Can only be called from JavaScript files"))); QV4::ScopedValue callbackFunction(scope, QV4::Primitive::undefinedValue()); diff --git a/src/qml/jsruntime/qv4qmlcontext.cpp b/src/qml/jsruntime/qv4qmlcontext.cpp index c8ef87b979..b69081d378 100644 --- a/src/qml/jsruntime/qv4qmlcontext.cpp +++ b/src/qml/jsruntime/qv4qmlcontext.cpp @@ -65,8 +65,6 @@ DEFINE_MANAGED_VTABLE(QmlContext); void Heap::QQmlContextWrapper::init(QQmlContextData *context, QObject *scopeObject) { Object::init(); - readOnly = true; - isNullWrapper = false; this->context = new QQmlContextDataRef(context); this->scopeObject.init(scopeObject); } @@ -89,9 +87,6 @@ ReturnedValue QQmlContextWrapper::virtualGet(const Managed *m, PropertyKey id, c QV4::ExecutionEngine *v4 = resource->engine(); QV4::Scope scope(v4); - if (resource->d()->isNullWrapper) - return Object::virtualGet(m, id, receiver, hasProperty); - if (v4->callingQmlContext() != *resource->d()->context) return Object::virtualGet(m, id, receiver, hasProperty); @@ -274,18 +269,6 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val if (member < UINT_MAX) return wrapper->putValue(member, value); - if (wrapper->d()->isNullWrapper) { - if (wrapper && wrapper->d()->readOnly) { - QString error = QLatin1String("Invalid write to global property \"") + id.toQString() + - QLatin1Char('"'); - ScopedString e(scope, v4->newString(error)); - v4->throwError(e); - return false; - } - - return Object::virtualPut(m, id, value, receiver); - } - // It's possible we could delay the calculation of the "actual" context (in the case // of sub contexts) until it is definitely needed. QQmlContextData *context = wrapper->getContext(); @@ -321,14 +304,10 @@ bool QQmlContextWrapper::virtualPut(Managed *m, PropertyKey id, const Value &val expressionContext->unresolvedNames = true; - if (wrapper->d()->readOnly) { - QString error = QLatin1String("Invalid write to global property \"") + name->toQString() + - QLatin1Char('"'); - v4->throwError(error); - return false; - } - - return Object::virtualPut(m, id, value, receiver); + QString error = QLatin1String("Invalid write to global property \"") + name->toQString() + + QLatin1Char('"'); + v4->throwError(error); + return false; } void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContextWrapper *qml) @@ -339,30 +318,6 @@ void Heap::QmlContext::init(QV4::ExecutionContext *outerContext, QV4::QQmlContex this->activation.set(internalClass->engine, qml->d()); } -Heap::QmlContext *QmlContext::createWorkerContext(ExecutionContext *parent, const QUrl &source, Value *sendFunction) -{ - Scope scope(parent); - - QQmlContextData *context = new QQmlContextData; - context->baseUrl = source; - context->baseUrlString = source.toString(); - context->isInternal = true; - context->isJSContext = true; - - Scoped<QQmlContextWrapper> qml(scope, scope.engine->memoryManager->allocate<QQmlContextWrapper>(context, (QObject*)nullptr)); - qml->d()->isNullWrapper = true; - - qml->setReadOnly(false); - QV4::ScopedObject api(scope, scope.engine->newObject()); - api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), *sendFunction); - qml->QV4::Object::put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api); - qml->setReadOnly(true); - - Heap::QmlContext *c = scope.engine->memoryManager->alloc<QmlContext>(parent, qml); - Q_ASSERT(c->vtable() == staticVTable()); - return c; -} - Heap::QmlContext *QmlContext::create(ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject) { Scope scope(parent); diff --git a/src/qml/jsruntime/qv4qmlcontext_p.h b/src/qml/jsruntime/qv4qmlcontext_p.h index b9061a3f58..4fe34a0a06 100644 --- a/src/qml/jsruntime/qv4qmlcontext_p.h +++ b/src/qml/jsruntime/qv4qmlcontext_p.h @@ -69,8 +69,6 @@ namespace Heap { struct QQmlContextWrapper : Object { void init(QQmlContextData *context, QObject *scopeObject); void destroy(); - bool readOnly; - bool isNullWrapper; QQmlContextDataRef *context; QQmlQPointer<QObject> scopeObject; @@ -96,8 +94,6 @@ struct Q_QML_EXPORT QQmlContextWrapper : Object inline QObject *getScopeObject() const { return d()->scopeObject; } inline QQmlContextData *getContext() const { return *d()->context; } - void setReadOnly(bool b) { d()->readOnly = b; } - static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty); static bool virtualPut(Managed *m, PropertyKey id, const Value &value, Value *receiver); }; @@ -107,7 +103,6 @@ struct Q_QML_EXPORT QmlContext : public ExecutionContext V4_MANAGED(QmlContext, ExecutionContext) V4_INTERNALCLASS(QmlContext) - static Heap::QmlContext *createWorkerContext(QV4::ExecutionContext *parent, const QUrl &source, Value *sendFunction); static Heap::QmlContext *create(QV4::ExecutionContext *parent, QQmlContextData *context, QObject *scopeObject); QObject *qmlScope() const { diff --git a/src/qml/types/qquickworkerscript.cpp b/src/qml/types/qquickworkerscript.cpp index 9fc374acb0..706982ba97 100644 --- a/src/qml/types/qquickworkerscript.cpp +++ b/src/qml/types/qquickworkerscript.cpp @@ -145,7 +145,7 @@ public: WorkerEngine(QQuickWorkerScriptEnginePrivate *parent); ~WorkerEngine() override; - void init(); + void init(int id); #if QT_CONFIG(qml_network) QNetworkAccessManager *networkAccessManager() override; @@ -173,16 +173,14 @@ public: QWaitCondition m_wait; struct WorkerScript { - WorkerScript(QQuickWorkerScriptEnginePrivate *parent); + WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent); ~WorkerScript(); QV4::ExecutionEngine *v4() const { return QV8Engine::getV4(workerEngine.data()); } QScopedPointer<WorkerEngine> workerEngine; int id; QUrl source; - bool initialized; QQuickWorkerScript *owner; - QV4::PersistentValue qmlContext; }; QHash<int, WorkerScript *> workers; @@ -221,17 +219,17 @@ QQuickWorkerScriptEnginePrivate::WorkerEngine::~WorkerEngine() delete m_v4Engine; } -void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() +void QQuickWorkerScriptEnginePrivate::WorkerEngine::init(int id) { initQmlGlobalObject(); #define CALL_ONMESSAGE_SCRIPT \ - "(function(object, message) { "\ + "(function(message) { "\ "var isfunction = false; "\ "try { "\ - "isfunction = object.WorkerScript.onMessage instanceof Function; "\ + "isfunction = WorkerScript.onMessage instanceof Function; "\ "} catch (e) {}" \ "if (isfunction) "\ - "object.WorkerScript.onMessage(message); "\ + "WorkerScript.onMessage(message); "\ "})" #define SEND_MESSAGE_CREATE_SCRIPT \ @@ -256,6 +254,12 @@ void QQuickWorkerScriptEnginePrivate::WorkerEngine::init() 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 @@ -316,20 +320,6 @@ QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::method_sendMessage(const QV4 return QV4::Encode::undefined(); } -QV4::ReturnedValue QQuickWorkerScriptEnginePrivate::getWorker(WorkerScript *script) -{ - if (!script->initialized) { - script->initialized = true; - - QV4::ExecutionEngine *v4 = QV8Engine::getV4(script->workerEngine.get()); - QV4::Scope scope(v4); - QV4::ScopedValue v(scope, script->workerEngine->sendFunction(script->id)); - script->qmlContext.set(v4, QV4::QmlContext::createWorkerContext(v4->rootContext(), script->source, v)); - } - - return script->qmlContext.value(); -} - bool QQuickWorkerScriptEnginePrivate::event(QEvent *event) { if (event->type() == (QEvent::Type)WorkerDataEvent::WorkerData) { @@ -367,13 +357,10 @@ void QQuickWorkerScriptEnginePrivate::processMessage(int id, const QByteArray &d QV4::ScopedFunctionObject f(scope, script->workerEngine->onmessage.value()); QV4::ScopedValue value(scope, QV4::Serialize::deserialize(data, v4)); - QV4::Scoped<QV4::QmlContext> qmlContext(scope, script->qmlContext.value()); - Q_ASSERT(!!qmlContext); - QV4::JSCallData jsCallData(scope, 2); + QV4::JSCallData jsCallData(scope, 1); *jsCallData->thisObject = v4->global(); - jsCallData->args[0] = qmlContext->d()->qml(); // ### - jsCallData->args[1] = value; + jsCallData->args[0] = value; f->call(jsCallData); if (scope.hasException()) { QQmlError error = scope.engine->catchExceptionAsQmlError(); @@ -398,11 +385,8 @@ void QQuickWorkerScriptEnginePrivate::processLoad(int id, const QUrl &url) script->source = url; - QV4::Scoped<QV4::QmlContext> qmlContext(scope, getWorker(script)); - Q_ASSERT(!!qmlContext); - QString error; - program.reset(QV4::Script::createFromFileOrCache(v4, qmlContext, fileName, url, &error)); + program.reset(QV4::Script::createFromFileOrCache(v4, /*qml context*/nullptr, fileName, url, &error)); if (program.isNull()) { if (!error.isEmpty()) qWarning().nospace() << error; @@ -512,11 +496,11 @@ QQuickWorkerScriptEngine::~QQuickWorkerScriptEngine() d->deleteLater(); } -QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript(QQuickWorkerScriptEnginePrivate *parent) -: id(-1), initialized(false), owner(nullptr) +QQuickWorkerScriptEnginePrivate::WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent) +: id(id), owner(nullptr) { workerEngine.reset(new QQuickWorkerScriptEnginePrivate::WorkerEngine(parent)); - workerEngine->init(); + workerEngine->init(id); } QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript() @@ -526,9 +510,8 @@ QQuickWorkerScriptEnginePrivate::WorkerScript::~WorkerScript() int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner) { typedef QQuickWorkerScriptEnginePrivate::WorkerScript WorkerScript; - WorkerScript *script = new WorkerScript(d); + WorkerScript *script = new WorkerScript(d->m_nextId++, d); - script->id = d->m_nextId++; script->owner = owner; d->m_lock.lock(); diff --git a/tests/auto/qml/qquickworkerscript/data/script_global.js b/tests/auto/qml/qquickworkerscript/data/script_global.js deleted file mode 100644 index cce4f2ceca..0000000000 --- a/tests/auto/qml/qquickworkerscript/data/script_global.js +++ /dev/null @@ -1,5 +0,0 @@ -WorkerScript.onMessage = function(msg) { - world = "World" - WorkerScript.sendMessage(msg + " " + world) -} - diff --git a/tests/auto/qml/qquickworkerscript/data/script_global2.js b/tests/auto/qml/qquickworkerscript/data/script_global2.js deleted file mode 100644 index 0867f7ee76..0000000000 --- a/tests/auto/qml/qquickworkerscript/data/script_global2.js +++ /dev/null @@ -1,6 +0,0 @@ -world = "World" - -WorkerScript.onMessage = function(msg) { - WorkerScript.sendMessage(msg + " " + world) -} - diff --git a/tests/auto/qml/qquickworkerscript/data/worker_global.qml b/tests/auto/qml/qquickworkerscript/data/worker_global.qml deleted file mode 100644 index 546afd2f39..0000000000 --- a/tests/auto/qml/qquickworkerscript/data/worker_global.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.0 - -BaseWorker { - source: "script_global.js" -} diff --git a/tests/auto/qml/qquickworkerscript/data/worker_global2.qml b/tests/auto/qml/qquickworkerscript/data/worker_global2.qml deleted file mode 100644 index 42cad3852b..0000000000 --- a/tests/auto/qml/qquickworkerscript/data/worker_global2.qml +++ /dev/null @@ -1,5 +0,0 @@ -import QtQuick 2.0 - -BaseWorker { - source: "script_global2.js" -} diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp index e8a4be6faf..e21a53b4f3 100644 --- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp +++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp @@ -57,7 +57,6 @@ private slots: void scriptError_onCall(); void script_function(); void script_var(); - void script_global(); void stressDispose(); private: @@ -311,47 +310,6 @@ void tst_QQuickWorkerScript::script_var() delete worker; } -void tst_QQuickWorkerScript::script_global() -{ - { - QQmlComponent component(&m_engine, testFileUrl("worker_global.qml")); - QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create()); - QVERIFY(worker != nullptr); - - QString value("Hello"); - - QtMessageHandler previousMsgHandler = qInstallMessageHandler(qquickworkerscript_warningsHandler); - - QVERIFY(QMetaObject::invokeMethod(worker, "testSend", Q_ARG(QVariant, value))); - - QTRY_COMPARE(qquickworkerscript_lastWarning, - testFileUrl("script_global.js").toString() + QLatin1String(":2: Invalid write to global property \"world\"")); - - qInstallMessageHandler(previousMsgHandler); - - qApp->processEvents(); - delete worker; - } - - qquickworkerscript_lastWarning = QString(); - - { - QtMessageHandler previousMsgHandler = qInstallMessageHandler(qquickworkerscript_warningsHandler); - - QQmlComponent component(&m_engine, testFileUrl("worker_global2.qml")); - QQuickWorkerScript *worker = qobject_cast<QQuickWorkerScript*>(component.create()); - QVERIFY(worker != nullptr); - - QTRY_COMPARE(qquickworkerscript_lastWarning, - testFileUrl("script_global2.js").toString() + QLatin1String(":1: Invalid write to global property \"world\"")); - - qInstallMessageHandler(previousMsgHandler); - - qApp->processEvents(); - delete worker; - } -} - // Rapidly create and destroy worker scripts to test resources are being disposed // in the correct isolate void tst_QQuickWorkerScript::stressDispose() |