aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-01-03 10:32:01 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2020-01-03 12:02:18 +0000
commit01bbd7e41ac8444d2282ac6ca1862c3748f685a1 (patch)
treead46297d0f39957fd2597f19f2e5eacbeb0240d5
parenta4150b040e8492e070d6bfefb190ae0852644f11 (diff)
QV4::ExecutionEngine: provide QNAM accessor
In XMLHttpRequest, we need to get the QNetworkAccessManager from the engine. However, if the request originates from a WorkerScript, there exists no qmlEngine. We therefore add a new indirection to access the QNAM, and set it up accordinly in registerWorkerScript. Fixes: QTBUG-81055 Change-Id: I8915202b6d6b7139c8386304b3d1d7a22a82045e Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/jsruntime/qv4engine.cpp5
-rw-r--r--src/qml/jsruntime/qv4engine_p.h11
-rw-r--r--src/qml/qml/qqmlxmlhttprequest.cpp2
-rw-r--r--src/qmlworkerscript/qquickworkerscript.cpp11
-rw-r--r--tests/auto/qml/qquickworkerscript/data/doRequest.mjs6
-rw-r--r--tests/auto/qml/qquickworkerscript/data/xmlHttpRequest.qml16
-rw-r--r--tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp8
7 files changed, 57 insertions, 2 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index 885f06a3e3..23582e0ccb 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -2323,4 +2323,9 @@ int ExecutionEngine::registerExtension()
return registrationData()->extensionCount++;
}
+QNetworkAccessManager *QV4::detail::getNetworkAccessManager(ExecutionEngine *engine)
+{
+ return engine->qmlEngine()->networkAccessManager();
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index d233347060..081859f4cc 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -91,7 +91,14 @@ class PageAllocation;
QT_BEGIN_NAMESPACE
-namespace QV4 { struct QObjectMethod; }
+class QNetworkAccessManager;
+
+namespace QV4 {
+struct QObjectMethod;
+namespace detail {
+QNetworkAccessManager *getNetworkAccessManager(ExecutionEngine *engine);
+}
+}
// Used to allow a QObject method take and return raw V4 handles without having to expose
// 48 in the public API.
@@ -348,6 +355,8 @@ public:
FunctionObject *getStackFunction() const { return reinterpret_cast<FunctionObject *>(jsObjects + GetStack_Function); }
FunctionObject *thrower() const { return reinterpret_cast<FunctionObject *>(jsObjects + ThrowerObject); }
+ std::function<QNetworkAccessManager*(ExecutionEngine*)> networkAccessManager = detail::getNetworkAccessManager;
+
enum JSStrings {
String_Empty,
String_undefined,
diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp
index 4db0562c0e..021aa369fa 100644
--- a/src/qml/qml/qqmlxmlhttprequest.cpp
+++ b/src/qml/qml/qqmlxmlhttprequest.cpp
@@ -1647,7 +1647,7 @@ struct QQmlXMLHttpRequestCtor : public FunctionObject
Scope scope(f->engine());
const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
- QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->qmlEngine()->networkAccessManager(), scope.engine);
+ QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->networkAccessManager(scope.engine), scope.engine);
Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
ScopedObject proto(scope, ctor->d()->proto);
w->setPrototypeUnchecked(proto);
diff --git a/src/qmlworkerscript/qquickworkerscript.cpp b/src/qmlworkerscript/qquickworkerscript.cpp
index 8b236697b9..c39433c74d 100644
--- a/src/qmlworkerscript/qquickworkerscript.cpp
+++ b/src/qmlworkerscript/qquickworkerscript.cpp
@@ -130,6 +130,7 @@ struct WorkerScript : public QV4::ExecutionEngine {
QQuickWorkerScriptEnginePrivate *p = nullptr;
QUrl source;
QQuickWorkerScript *owner = nullptr;
+ QScopedPointer<QNetworkAccessManager> scriptLocalNAM;
int id = -1;
};
@@ -389,6 +390,16 @@ WorkerScript::WorkerScript(int id, QQuickWorkerScriptEnginePrivate *parent)
QV4::ScopedValue sendMessage(scope, QV4::FunctionObject::createBuiltinFunction(this, name, QQuickWorkerScriptEnginePrivate::method_sendMessage, 1));
api->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("sendMessage"))), sendMessage);
globalObject->put(QV4::ScopedString(scope, scope.engine->newString(QStringLiteral("WorkerScript"))), api);
+ networkAccessManager = [this](QV4::ExecutionEngine *engine){
+ auto *workerScript = static_cast<WorkerScript *>(engine);
+ if (workerScript->scriptLocalNAM)
+ return workerScript->scriptLocalNAM.get();
+ if (auto *namFactory = p->qmlengine->networkAccessManagerFactory())
+ workerScript->scriptLocalNAM.reset(namFactory->create(p));
+ else
+ workerScript->scriptLocalNAM.reset(new QNetworkAccessManager(p));
+ return workerScript->scriptLocalNAM.get();
+ };
}
int QQuickWorkerScriptEngine::registerWorkerScript(QQuickWorkerScript *owner)
diff --git a/tests/auto/qml/qquickworkerscript/data/doRequest.mjs b/tests/auto/qml/qquickworkerscript/data/doRequest.mjs
new file mode 100644
index 0000000000..d607c3400d
--- /dev/null
+++ b/tests/auto/qml/qquickworkerscript/data/doRequest.mjs
@@ -0,0 +1,6 @@
+WorkerScript.onMessage = function(message)
+{
+ var req = new XMLHttpRequest();
+ req.open("GET", message.url, true);
+ req.send();
+};
diff --git a/tests/auto/qml/qquickworkerscript/data/xmlHttpRequest.qml b/tests/auto/qml/qquickworkerscript/data/xmlHttpRequest.qml
new file mode 100644
index 0000000000..42136d78f0
--- /dev/null
+++ b/tests/auto/qml/qquickworkerscript/data/xmlHttpRequest.qml
@@ -0,0 +1,16 @@
+import QtQuick 2.14
+
+Rectangle
+{
+ width: 100
+ height: 100
+
+ WorkerScript
+ {
+ source: "doRequest.mjs"
+ Component.onCompleted:
+ {
+ sendMessage({"url": "https://example.com"});
+ }
+ }
+}
diff --git a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
index bea9978f0b..d11e7bde4b 100644
--- a/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
+++ b/tests/auto/qml/qquickworkerscript/tst_qquickworkerscript.cpp
@@ -59,6 +59,7 @@ private slots:
void script_function();
void script_var();
void stressDispose();
+ void xmlHttpRequest();
private:
void waitForEchoMessage(QQuickWorkerScript *worker) {
@@ -341,6 +342,13 @@ void tst_QQuickWorkerScript::stressDispose()
}
}
+void tst_QQuickWorkerScript::xmlHttpRequest()
+{
+ QQmlComponent component(&m_engine, testFileUrl("xmlHttpRequest.qml"));
+ QScopedPointer<QObject> root{component.create()}; // should not crash
+ QVERIFY(root);
+}
+
QTEST_MAIN(tst_QQuickWorkerScript)
#include "tst_qquickworkerscript.moc"