diff options
author | Valery Kotov <kotov.valery@gmail.com> | 2015-04-07 20:34:44 +0300 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@theqtcompany.com> | 2015-04-16 17:44:29 +0000 |
commit | 43961057a973715856486c596959213bd911df73 (patch) | |
tree | 95a93b3f273a0540c5063331e942da738207bd27 | |
parent | 4930941197576c6017451856beb59a0ff8d045bd (diff) |
QML Engine: JSON XHR response type support
Support for "json" response type for QQmlXMLHttpRequest was
added.
[ChangeLog][QtQml][QQmlXMLHttpRequest] QQmlXMLHttpRequest now
supports "json" binary response type.
Change-Id: I21b7659c02dfdc6b64a73e1d2003e269d90b3b23
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
-rw-r--r-- | src/qml/jsruntime/qv4jsonobject.cpp | 28 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4jsonobject_p.h | 28 | ||||
-rw-r--r-- | src/qml/qml/qqmlxmlhttprequest.cpp | 25 | ||||
-rw-r--r-- | tests/auto/qml/qqmlxmlhttprequest/data/json.data | 6 | ||||
-rw-r--r-- | tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml | 22 | ||||
-rw-r--r-- | tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect | 7 | ||||
-rw-r--r-- | tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply | 3 | ||||
-rw-r--r-- | tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp | 18 |
8 files changed, 109 insertions, 28 deletions
diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index 4580ff16d8..e826261010 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -39,7 +39,6 @@ #include <qv4scopedvalue_p.h> #include <qv4runtime_p.h> -#include <qjsondocument.h> #include <qstack.h> #include <qstringlist.h> @@ -62,33 +61,6 @@ static int indent = 0; DEFINE_OBJECT_VTABLE(JsonObject); -class JsonParser -{ -public: - JsonParser(ExecutionEngine *engine, const QChar *json, int length); - - ReturnedValue parse(QJsonParseError *error); - -private: - inline bool eatSpace(); - inline QChar nextToken(); - - ReturnedValue parseObject(); - ReturnedValue parseArray(); - bool parseMember(Object *o); - bool parseString(QString *string); - bool parseValue(Value *val); - bool parseNumber(Value *val); - - ExecutionEngine *engine; - const QChar *head; - const QChar *json; - const QChar *end; - - int nestingLevel; - QJsonParseError::ParseError lastError; -}; - static const int nestingLimit = 1024; diff --git a/src/qml/jsruntime/qv4jsonobject_p.h b/src/qml/jsruntime/qv4jsonobject_p.h index 81a783ee92..b8b9cf3093 100644 --- a/src/qml/jsruntime/qv4jsonobject_p.h +++ b/src/qml/jsruntime/qv4jsonobject_p.h @@ -37,6 +37,7 @@ #include <qjsonarray.h> #include <qjsonobject.h> #include <qjsonvalue.h> +#include <qjsondocument.h> QT_BEGIN_NAMESPACE @@ -79,6 +80,33 @@ private: }; +class JsonParser +{ +public: + JsonParser(ExecutionEngine *engine, const QChar *json, int length); + + ReturnedValue parse(QJsonParseError *error); + +private: + inline bool eatSpace(); + inline QChar nextToken(); + + ReturnedValue parseObject(); + ReturnedValue parseArray(); + bool parseMember(Object *o); + bool parseString(QString *string); + bool parseValue(Value *val); + bool parseNumber(Value *val); + + ExecutionEngine *engine; + const QChar *head; + const QChar *json; + const QChar *end; + + int nestingLevel; + QJsonParseError::ParseError lastError; +}; + } QT_END_NAMESPACE diff --git a/src/qml/qml/qqmlxmlhttprequest.cpp b/src/qml/qml/qqmlxmlhttprequest.cpp index 74577adfab..3c8a549325 100644 --- a/src/qml/qml/qqmlxmlhttprequest.cpp +++ b/src/qml/qml/qqmlxmlhttprequest.cpp @@ -60,6 +60,7 @@ #include <private/qv4objectproto_p.h> #include <private/qv4scopedvalue_p.h> #include <private/qv4arraybuffer_p.h> +#include <private/qv4jsonobject_p.h> using namespace QV4; @@ -1026,6 +1027,8 @@ public: const QString & responseType() const; void setResponseType(const QString &); + + QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*); private slots: void readyRead(); void error(QNetworkReply::NetworkError); @@ -1076,6 +1079,7 @@ private: QNetworkAccessManager *networkAccessManager() { return m_nam; } QString m_responseType; + QV4::PersistentValue m_parsedJson; }; QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessManager *manager) @@ -1083,6 +1087,7 @@ QQmlXMLHttpRequest::QQmlXMLHttpRequest(ExecutionEngine *engine, QNetworkAccessMa , m_state(Unsent), m_errorFlag(false), m_sendFlag(false) , m_redirectCount(0), m_gotXml(false), m_textCodec(0), m_network(0), m_nam(manager) , m_responseType() + , m_parsedJson() { } @@ -1478,6 +1483,24 @@ void QQmlXMLHttpRequest::setResponseType(const QString &responseType) m_responseType = responseType; } +QV4::ReturnedValue QQmlXMLHttpRequest::jsonResponseBody(QV4::ExecutionEngine* engine) +{ + if (m_parsedJson.isEmpty()) { + Scope scope(engine); + + QJsonParseError error; + const QString& jtext = responseBody(); + JsonParser parser(scope.engine, jtext.constData(), jtext.length()); + ScopedValue jsonObject(scope, parser.parse(&error)); + if (error.error != QJsonParseError::NoError) + return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error")); + + m_parsedJson.set(scope.engine, jsonObject); + } + + return m_parsedJson.value(); +} + #ifndef QT_NO_TEXTCODEC QTextCodec* QQmlXMLHttpRequest::findTextCodec() const @@ -1986,6 +2009,8 @@ ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(CallContext *ctx) return QV4::Encode(scope.engine->newString(r->responseBody())); } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) { return QV4::Encode(scope.engine->newArrayBuffer(r->rawResponseBody())); + } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) { + return r->jsonResponseBody(scope.engine); } else { return QV4::Encode(scope.engine->newString(QString())); } diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/json.data b/tests/auto/qml/qqmlxmlhttprequest/data/json.data new file mode 100644 index 0000000000..7925375293 --- /dev/null +++ b/tests/auto/qml/qqmlxmlhttprequest/data/json.data @@ -0,0 +1,6 @@ +{"widget": { + "debug": "on", + "window": { + "name": "main_window", + "width": 500 +}}} diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml b/tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml new file mode 100644 index 0000000000..3fc116e675 --- /dev/null +++ b/tests/auto/qml/qqmlxmlhttprequest/data/receiveJsonData.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 + +QtObject { + property string url; + property bool result: false + property string correctjsondata : "{\"widget\":{\"debug\":\"on\",\"window\":{\"name\":\"main_window\",\"width\":500}}}" + + Component.onCompleted: { + var request = new XMLHttpRequest(); + request.open("GET", url, true); + request.responseType = "json"; + + request.onreadystatechange = function() { + if (request.readyState == XMLHttpRequest.DONE) { + var jsonData = JSON.stringify(request.response); + result = (correctjsondata == jsonData); + } + } + + request.send(null); + } +} diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect new file mode 100644 index 0000000000..59a7806bc9 --- /dev/null +++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.expect @@ -0,0 +1,7 @@ +GET /json.data HTTP/1.1 +Accept-Language: en-US,* +Content-Type: application/jsonrequest +Connection: Keep-Alive +Accept-Encoding: gzip, deflate +User-Agent: Mozilla/5.0 +Host: 127.0.0.1:14445 diff --git a/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply new file mode 100644 index 0000000000..f1ee73d623 --- /dev/null +++ b/tests/auto/qml/qqmlxmlhttprequest/data/receive_json_data.reply @@ -0,0 +1,3 @@ +HTTP/1.1 200 OK +Connection: close +Content-Type: application/jsonrequest diff --git a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp index dd70f81d5e..d901c4dd14 100644 --- a/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp +++ b/tests/auto/qml/qqmlxmlhttprequest/tst_qqmlxmlhttprequest.cpp @@ -88,6 +88,7 @@ private slots: void getAllResponseHeaders_sent(); void getAllResponseHeaders_args(); void getBinaryData(); + void getJsonData(); void status(); void status_data(); void statusText(); @@ -835,6 +836,23 @@ void tst_qqmlxmlhttprequest::getBinaryData() QTRY_VERIFY(object->property("readSize").toInt() == fileInfo.size()); } +void tst_qqmlxmlhttprequest::getJsonData() +{ + TestHTTPServer server; + QVERIFY2(server.listen(SERVER_PORT), qPrintable(server.errorString())); + QVERIFY(server.wait(testFileUrl("receive_json_data.expect"), + testFileUrl("receive_binary_data.reply"), + testFileUrl("json.data"))); + + QQmlComponent component(&engine, testFileUrl("receiveJsonData.qml")); + QScopedPointer<QObject> object(component.beginCreate(engine.rootContext())); + QVERIFY(!object.isNull()); + object->setProperty("url", "http://127.0.0.1:14445/json.data"); + component.completeCreate(); + + QTRY_VERIFY(object->property("result").toBool()); +} + void tst_qqmlxmlhttprequest::status() { QFETCH(QUrl, replyUrl); |