9#include <private/qqmlrefcount_p.h>
12#include <private/qv4domerrors_p.h>
13#include <private/qv4engine_p.h>
14#include <private/qv4functionobject_p.h>
15#include <private/qv4scopedvalue_p.h>
16#include <private/qv4jscall_p.h>
18#include <QtCore/qobject.h>
19#include <QtQml/qjsvalue.h>
20#include <QtQml/qjsengine.h>
21#include <QtQml/qqmlfile.h>
22#include <QtNetwork/qnetworkreply.h>
24#include <QtCore/qpointer.h>
25#include <QtCore/qstringconverter.h>
26#include <QtCore/qxmlstream.h>
27#include <QtCore/qstack.h>
28#include <QtCore/qdebug.h>
29#include <QtCore/qbuffer.h>
31#include <private/qv4objectproto_p.h>
32#include <private/qv4scopedvalue_p.h>
33#include <private/qv4arraybuffer_p.h>
34#include <private/qv4jsonobject_p.h>
38#define V4THROW_REFERENCE(string)
40 ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string)));
41 return scope.engine->throwError(error);
87 qDeleteAll(attributes);
122class DocumentImpl
final :
public QQmlRefCounted<DocumentImpl>,
public NodeImpl
124 using Base1 = QQmlRefCounted<DocumentImpl>;
152 if (listPtr ==
nullptr)
153 listPtr =
new QList<NodeImpl *>;
270 Scope scope(internalClass->engine);
271 ScopedObject o(scope,
this);
273 o->defineAccessorProperty(QStringLiteral(
"nodeName"), QV4::NodePrototype::method_get_nodeName,
nullptr);
274 o->defineAccessorProperty(QStringLiteral(
"nodeValue"), QV4::NodePrototype::method_get_nodeValue,
nullptr);
275 o->defineAccessorProperty(QStringLiteral(
"nodeType"), QV4::NodePrototype::method_get_nodeType,
nullptr);
276 o->defineAccessorProperty(QStringLiteral(
"namespaceUri"), QV4::NodePrototype::method_get_namespaceUri,
nullptr);
278 o->defineAccessorProperty(QStringLiteral(
"parentNode"), QV4::NodePrototype::method_get_parentNode,
nullptr);
279 o->defineAccessorProperty(QStringLiteral(
"childNodes"), QV4::NodePrototype::method_get_childNodes,
nullptr);
280 o->defineAccessorProperty(QStringLiteral(
"firstChild"), QV4::NodePrototype::method_get_firstChild,
nullptr);
281 o->defineAccessorProperty(QStringLiteral(
"lastChild"), QV4::NodePrototype::method_get_lastChild,
nullptr);
282 o->defineAccessorProperty(QStringLiteral(
"previousSibling"), QV4::NodePrototype::method_get_previousSibling,
nullptr);
283 o->defineAccessorProperty(QStringLiteral(
"nextSibling"), QV4::NodePrototype::method_get_nextSibling,
nullptr);
284 o->defineAccessorProperty(QStringLiteral(
"attributes"), QV4::NodePrototype::method_get_attributes,
nullptr);
292 V4_OBJECT2(
Node, Object)
377void NodeImpl::addref()
382void NodeImpl::release()
387ReturnedValue NodePrototype::method_get_nodeName(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
390 Scoped<Node> r(scope, thisObject->as<Node>());
395 switch (r->d()->d->type) {
396 case NodeImpl::Document:
397 name = QStringLiteral(
"#document");
399 case NodeImpl::CDATA:
400 name = QStringLiteral(
"#cdata-section");
403 name = QStringLiteral(
"#text");
406 name = r->d()->d->name;
409 return Encode(scope.engine->newString(name));
412ReturnedValue NodePrototype::method_get_nodeValue(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
415 Scoped<Node> r(scope, thisObject->as<Node>());
419 if (r->d()->d->type == NodeImpl::Document ||
420 r->d()->d->type == NodeImpl::DocumentFragment ||
421 r->d()->d->type == NodeImpl::DocumentType ||
422 r->d()->d->type == NodeImpl::Element ||
423 r->d()->d->type == NodeImpl::Entity ||
424 r->d()->d->type == NodeImpl::EntityReference ||
425 r->d()->d->type == NodeImpl::Notation)
426 RETURN_RESULT(Encode::null());
428 return Encode(scope.engine->newString(r->d()->d->data));
431ReturnedValue NodePrototype::method_get_nodeType(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
434 Scoped<Node> r(scope, thisObject->as<Node>());
438 return Encode(r->d()->d->type);
441ReturnedValue NodePrototype::method_get_namespaceUri(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
444 Scoped<Node> r(scope, thisObject->as<Node>());
448 return Encode(scope.engine->newString(r->d()->d->namespaceUri));
451ReturnedValue NodePrototype::method_get_parentNode(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
454 Scoped<Node> r(scope, thisObject->as<Node>());
458 if (r->d()->d->parent)
459 return Node::create(scope.engine, r->d()->d->parent);
461 return Encode::null();
464ReturnedValue NodePrototype::method_get_childNodes(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
467 Scoped<Node> r(scope, thisObject->as<Node>());
471 return NodeList::create(scope.engine, r->d()->d);
474ReturnedValue NodePrototype::method_get_firstChild(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
477 Scoped<Node> r(scope, thisObject->as<Node>());
481 if (r->d()->d->children.isEmpty())
482 return Encode::null();
484 return Node::create(scope.engine, r->d()->d->children.constFirst());
487ReturnedValue NodePrototype::method_get_lastChild(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
490 Scoped<Node> r(scope, thisObject->as<Node>());
494 if (r->d()->d->children.isEmpty())
495 return Encode::null();
497 return Node::create(scope.engine, r->d()->d->children.constLast());
500ReturnedValue NodePrototype::method_get_previousSibling(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
503 Scoped<Node> r(scope, thisObject->as<Node>());
507 if (!r->d()->d->parent)
508 RETURN_RESULT(Encode::null());
510 for (
int ii = 0; ii < r->d()->d->parent->children.size(); ++ii) {
511 if (r->d()->d->parent->children.at(ii) == r->d()->d) {
513 return Encode::null();
515 return Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1));
519 return Encode::null();
522ReturnedValue NodePrototype::method_get_nextSibling(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
525 Scoped<Node> r(scope, thisObject->as<Node>());
529 if (!r->d()->d->parent)
530 RETURN_RESULT(Encode::null());
532 for (
int ii = 0; ii < r->d()->d->parent->children.size(); ++ii) {
533 if (r->d()->d->parent->children.at(ii) == r->d()->d) {
534 if ((ii + 1) == r->d()->d->parent->children.size())
535 return Encode::null();
537 return Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1));
541 return Encode::null();
544ReturnedValue NodePrototype::method_get_attributes(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
547 Scoped<Node> r(scope, thisObject->as<Node>());
551 if (r->d()->d->type != NodeImpl::Element)
552 return Encode::null();
554 return NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes);
557ReturnedValue NodePrototype::getProto(ExecutionEngine *v4)
560 QQmlXMLHttpRequestData *d = xhrdata(v4);
561 if (d->nodePrototype.isUndefined()) {
562 ScopedObject p(scope, v4->memoryManager->allocate<NodePrototype>());
563 d->nodePrototype.set(v4, p);
566 return d->nodePrototype.value();
569ReturnedValue Node::create(ExecutionEngine *v4, NodeImpl *data)
573 Scoped<Node> instance(scope, v4->memoryManager->allocate<Node>(data));
574 ScopedObject p(scope);
576 switch (data->type) {
578 instance->setPrototypeUnchecked((p = Attr::prototype(v4)));
580 case NodeImpl::Comment:
581 case NodeImpl::Document:
582 case NodeImpl::DocumentFragment:
583 case NodeImpl::DocumentType:
584 case NodeImpl::Entity:
585 case NodeImpl::EntityReference:
586 case NodeImpl::Notation:
587 case NodeImpl::ProcessingInstruction:
588 return Encode::undefined();
589 case NodeImpl::CDATA:
590 instance->setPrototypeUnchecked((p = CDATA::prototype(v4)));
593 instance->setPrototypeUnchecked((p = Text::prototype(v4)));
595 case NodeImpl::Element:
596 instance->setPrototypeUnchecked((p = Element::prototype(v4)));
600 return instance.asReturnedValue();
603ReturnedValue Element::prototype(ExecutionEngine *engine)
605 QQmlXMLHttpRequestData *d = xhrdata(engine);
606 if (d->elementPrototype.isUndefined()) {
608 ScopedObject p(scope, engine->newObject());
609 ScopedObject pp(scope);
610 p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
611 p->defineAccessorProperty(QStringLiteral(
"tagName"), NodePrototype::method_get_nodeName,
nullptr);
612 d->elementPrototype.set(engine, p);
613 engine->freezeObject(p);
615 return d->elementPrototype.value();
618ReturnedValue Attr::prototype(ExecutionEngine *engine)
620 QQmlXMLHttpRequestData *d = xhrdata(engine);
621 if (d->attrPrototype.isUndefined()) {
623 ScopedObject p(scope, engine->newObject());
624 ScopedObject pp(scope);
625 p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
626 p->defineAccessorProperty(QStringLiteral(
"name"), method_name,
nullptr);
627 p->defineAccessorProperty(QStringLiteral(
"value"), method_value,
nullptr);
628 p->defineAccessorProperty(QStringLiteral(
"ownerElement"), method_ownerElement,
nullptr);
629 d->attrPrototype.set(engine, p);
630 engine->freezeObject(p);
632 return d->attrPrototype.value();
635ReturnedValue Attr::method_name(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
638 Scoped<Node> r(scope, thisObject->as<Node>());
642 return Encode(scope.engine->newString(r->d()->d->name));
645ReturnedValue Attr::method_value(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
648 Scoped<Node> r(scope, thisObject->as<Node>());
652 return Encode(scope.engine->newString(r->d()->d->data));
655ReturnedValue Attr::method_ownerElement(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
658 Scoped<Node> r(scope, thisObject->as<Node>());
662 return Node::create(scope.engine, r->d()->d->parent);
665ReturnedValue CharacterData::method_length(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
668 Scoped<Node> r(scope, thisObject->as<Node>());
672 return Encode(
int(r->d()->d->data.size()));
675ReturnedValue CharacterData::prototype(ExecutionEngine *v4)
677 QQmlXMLHttpRequestData *d = xhrdata(v4);
678 if (d->characterDataPrototype.isUndefined()) {
680 ScopedObject p(scope, v4->newObject());
681 ScopedObject pp(scope);
682 p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
683 p->defineAccessorProperty(QStringLiteral(
"data"), NodePrototype::method_get_nodeValue,
nullptr);
684 p->defineAccessorProperty(QStringLiteral(
"length"), method_length,
nullptr);
685 d->characterDataPrototype.set(v4, p);
688 return d->characterDataPrototype.value();
691ReturnedValue Text::method_isElementContentWhitespace(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
694 Scoped<Node> r(scope, thisObject->as<Node>());
698 return Encode(QStringView(r->d()->d->data).trimmed().isEmpty());
701ReturnedValue Text::method_wholeText(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
704 Scoped<Node> r(scope, thisObject->as<Node>());
708 return Encode(scope.engine->newString(r->d()->d->data));
711ReturnedValue Text::prototype(ExecutionEngine *v4)
713 QQmlXMLHttpRequestData *d = xhrdata(v4);
714 if (d->textPrototype.isUndefined()) {
716 ScopedObject p(scope, v4->newObject());
717 ScopedObject pp(scope);
718 p->setPrototypeUnchecked((pp = CharacterData::prototype(v4)));
719 p->defineAccessorProperty(QStringLiteral(
"isElementContentWhitespace"), method_isElementContentWhitespace,
nullptr);
720 p->defineAccessorProperty(QStringLiteral(
"wholeText"), method_wholeText,
nullptr);
721 d->textPrototype.set(v4, p);
724 return d->textPrototype.value();
727ReturnedValue CDATA::prototype(ExecutionEngine *v4)
730 QQmlXMLHttpRequestData *d = xhrdata(v4);
731 if (d->cdataPrototype.isUndefined()) {
733 ScopedObject p(scope, v4->newObject());
734 ScopedObject pp(scope);
735 p->setPrototypeUnchecked((pp = Text::prototype(v4)));
736 d->cdataPrototype.set(v4, p);
739 return d->cdataPrototype.value();
742ReturnedValue Document::prototype(ExecutionEngine *v4)
744 QQmlXMLHttpRequestData *d = xhrdata(v4);
745 if (d->documentPrototype.isUndefined()) {
747 ScopedObject p(scope, v4->newObject());
748 ScopedObject pp(scope);
749 p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
750 p->defineAccessorProperty(QStringLiteral(
"xmlVersion"), method_xmlVersion,
nullptr);
751 p->defineAccessorProperty(QStringLiteral(
"xmlEncoding"), method_xmlEncoding,
nullptr);
752 p->defineAccessorProperty(QStringLiteral(
"xmlStandalone"), method_xmlStandalone,
nullptr);
753 p->defineAccessorProperty(QStringLiteral(
"documentElement"), method_documentElement,
nullptr);
754 d->documentPrototype.set(v4, p);
757 return d->documentPrototype.value();
760ReturnedValue Document::load(ExecutionEngine *v4,
const QByteArray &data)
764 DocumentImpl *document =
nullptr;
765 QStack<NodeImpl *> nodeStack;
767 QXmlStreamReader reader(data);
769 while (!reader.atEnd()) {
770 switch (reader.readNext()) {
771 case QXmlStreamReader::NoToken:
773 case QXmlStreamReader::Invalid:
775 case QXmlStreamReader::StartDocument:
777 document =
new DocumentImpl;
778 document->document = document;
779 document->version = reader.documentVersion().toString();
780 document->encoding = reader.documentEncoding().toString();
781 document->isStandalone = reader.isStandaloneDocument();
783 case QXmlStreamReader::EndDocument:
785 case QXmlStreamReader::StartElement:
788 NodeImpl *node =
new NodeImpl;
789 node->document = document;
790 node->namespaceUri = reader.namespaceUri().toString();
791 node->name = reader.name().toString();
792 if (nodeStack.isEmpty()) {
793 document->root = node;
795 node->parent = nodeStack.top();
796 node->parent->children.append(node);
798 nodeStack.append(node);
800 const auto attributes = reader.attributes();
801 for (
const QXmlStreamAttribute &a : attributes) {
802 NodeImpl *attr =
new NodeImpl;
803 attr->document = document;
804 attr->type = NodeImpl::Attr;
805 attr->namespaceUri = a.namespaceUri().toString();
806 attr->name = a.name().toString();
807 attr->data = a.value().toString();
809 node->attributes.append(attr);
813 case QXmlStreamReader::EndElement:
816 case QXmlStreamReader::Characters:
818 NodeImpl *node =
new NodeImpl;
819 node->document = document;
820 node->type = reader.isCDATA()?NodeImpl::CDATA:NodeImpl::Text;
821 node->parent = nodeStack.top();
822 node->parent->children.append(node);
823 node->data = reader.text().toString();
826 case QXmlStreamReader::Comment:
828 case QXmlStreamReader::DTD:
830 case QXmlStreamReader::EntityReference:
832 case QXmlStreamReader::ProcessingInstruction:
837 if (!document || reader.hasError()) {
840 return Encode::null();
843 ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document));
845 ScopedObject p(scope);
846 instance->setPrototypeUnchecked((p = Document::prototype(v4)));
847 return instance.asReturnedValue();
850bool Node::isNull()
const
852 return d()->d ==
nullptr;
855ReturnedValue NamedNodeMap::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
bool *hasProperty)
857 Q_ASSERT(m->as<NamedNodeMap>());
859 const NamedNodeMap *r =
static_cast<
const NamedNodeMap *>(m);
860 QV4::ExecutionEngine *v4 = r->engine();
862 if (id.isArrayIndex()) {
863 uint index = id.asArrayIndex();
865 if ((
int)index < r->d()->list().size()) {
868 return Node::create(v4, r->d()->list().at(index));
871 *hasProperty =
false;
872 return Encode::undefined();
876 return Object::virtualGet(m, id, receiver, hasProperty);
878 if (id == v4->id_length()->propertyKey())
879 return Value::fromInt32(r->d()->list().size()).asReturnedValue();
881 QString str = id.toQString();
882 for (
int ii = 0; ii < r->d()->list().size(); ++ii) {
883 if (r->d()->list().at(ii)->name == str) {
886 return Node::create(v4, r->d()->list().at(ii));
891 *hasProperty =
false;
892 return Encode::undefined();
895ReturnedValue NamedNodeMap::create(ExecutionEngine *v4, NodeImpl *data,
const QList<NodeImpl *> &list)
897 return (v4->memoryManager->allocate<NamedNodeMap>(data, list))->asReturnedValue();
900ReturnedValue NodeList::virtualGet(
const Managed *m, PropertyKey id,
const Value *receiver,
bool *hasProperty)
902 Q_ASSERT(m->as<NodeList>());
903 const NodeList *r =
static_cast<
const NodeList *>(m);
904 QV4::ExecutionEngine *v4 = r->engine();
906 if (id.isArrayIndex()) {
907 uint index = id.asArrayIndex();
908 if ((
int)index < r->d()->d->children.size()) {
911 return Node::create(v4, r->d()->d->children.at(index));
914 *hasProperty =
false;
915 return Encode::undefined();
918 if (id == v4->id_length()->propertyKey())
919 return Value::fromInt32(r->d()->d->children.size()).asReturnedValue();
920 return Object::virtualGet(m, id, receiver, hasProperty);
923ReturnedValue NodeList::create(ExecutionEngine *v4, NodeImpl *data)
925 return (v4->memoryManager->allocate<NodeList>(data))->asReturnedValue();
928ReturnedValue Document::method_documentElement(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
931 Scoped<Node> r(scope, thisObject->as<Node>());
932 if (!r || r->d()->d->type != NodeImpl::Document)
935 return Node::create(scope.engine,
static_cast<DocumentImpl *>(r->d()->d)->root);
938ReturnedValue Document::method_xmlStandalone(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
941 Scoped<Node> r(scope, thisObject->as<Node>());
942 if (!r || r->d()->d->type != NodeImpl::Document)
945 return Encode(
static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
948ReturnedValue Document::method_xmlVersion(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
951 Scoped<Node> r(scope, thisObject->as<Node>());
952 if (!r || r->d()->d->type != NodeImpl::Document)
955 return Encode(scope.engine->newString(
static_cast<DocumentImpl *>(r->d()->d)->version));
958ReturnedValue Document::method_xmlEncoding(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
961 Scoped<Node> r(scope, thisObject->as<Node>());
962 if (!r || r->d()->d->type != NodeImpl::Document)
965 return Encode(scope.engine->newString(
static_cast<DocumentImpl *>(r->d()->d)->encoding));
1019 void error(QV4::Heap::Object *thisObject, QNetworkReply::NetworkError);
1020 void finished(QV4::Heap::Object *thisObject);
1023 void requestFromUrl(QV4::Heap::Object *thisObject,
const QUrl &url);
1030 QByteArray m_responseEntityBody;
1032 int m_redirectCount;
1034 typedef std::pair<QByteArray, QByteArray> HeaderPair;
1035 typedef QList<HeaderPair> HeadersList;
1036 HeadersList m_headersList;
1037 void fillHeadersList();
1041 QByteArray m_charset;
1042 QByteArray m_overrideMime;
1043 QByteArray m_overrideCharset;
1045 QStringDecoder findTextDecoder()
const;
1046 void readEncoding();
1048 PersistentValue m_thisObject;
1049 QQmlRefPointer<QQmlContextData> m_qmlContext;
1050 bool m_wasConstructedWithQmlContext =
true;
1052 void dispatchCallbackNow(Heap::Object *thisObj);
1053 static void dispatchCallbackNow(Heap::Object *thisObj,
bool done,
bool error);
1054 void dispatchCallbackSafely(Heap::Object *thisObject);
1056 template<
typename F>
1057 void withThisObjectIfValid(Heap::Object *expected, F &&f)
const
1059 Object *thisObject = m_thisObject.as<Object>();
1060 if (thisObject && thisObject->d() == expected) {
1062 QV4::Scope scope(thisObject->engine());
1063 QV4::ScopedObject scoped(scope, thisObject);
1069 QString m_statusText;
1070 QNetworkRequest m_request;
1071 QStringList m_addedHeaders;
1072 QPointer<QNetworkReply> m_network;
1073 void destroyNetwork();
1075 QNetworkAccessManager *m_nam;
1076 QNetworkAccessManager *networkAccessManager() {
return m_nam; }
1078 QString m_responseType;
1079 QV4::PersistentValue m_parsedDocument;
1083 : m_state(
Unsent), m_errorFlag(
false), m_sendFlag(
false)
1084 , m_redirectCount(0), m_gotXml(
false),
m_network(
nullptr), m_nam(manager)
1086 m_wasConstructedWithQmlContext = !v4->callingQmlContext().isNull();
1116 return m_statusText;
1123 m_errorFlag =
false;
1124 m_responseEntityBody = QByteArray();
1127 m_request.setAttribute(QNetworkRequest::SynchronousRequestAttribute, loadType == SynchronousLoad);
1129 m_addedHeaders.clear();
1130 dispatchCallbackNow(thisObject);
1131 return Encode::undefined();
1136 QByteArray utfname = name.toUtf8();
1138 if (m_addedHeaders.contains(name, Qt::CaseInsensitive)) {
1139 m_request.setRawHeader(utfname, m_request.rawHeader(utfname) +
',' + value.toUtf8());
1141 m_request.setRawHeader(utfname, value.toUtf8());
1142 m_addedHeaders.append(name);
1148 if (!m_headersList.isEmpty()) {
1149 const QByteArray utfname = name.toLower().toUtf8();
1150 for (
const HeaderPair &header : m_headersList) {
1151 if (header.first == utfname)
1152 return QString::fromUtf8(header.second);
1162 for (
const HeaderPair &header : m_headersList) {
1164 ret.append(QLatin1String(
"\r\n"));
1165 ret += QString::fromUtf8(header.first) + QLatin1String(
": ")
1166 + QString::fromUtf8(header.second);
1173 const QList<QByteArray> headerList = m_network->rawHeaderList();
1175 m_headersList.clear();
1176 for (
const QByteArray &header : headerList) {
1177 HeaderPair pair (header.toLower(), m_network->rawHeader(header));
1178 if (pair.first ==
"set-cookie" ||
1179 pair.first ==
"set-cookie2")
1182 m_headersList << pair;
1189 QNetworkRequest request = m_request;
1191 if (QQmlFile::isLocalFile(url)) {
1192 if (m_method == QLatin1String(
"PUT"))
1194 if (!xhrFileWrite()) {
1195 qWarning(
"XMLHttpRequest: Using PUT on a local file is disabled by default.\n"
1196 "Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature.");
1199 }
else if (m_method == QLatin1String(
"GET")) {
1200 if (!xhrFileRead()) {
1201 qWarning(
"XMLHttpRequest: Using GET on a local file is disabled by default.\n"
1202 "Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature.");
1206 qWarning(
"XMLHttpRequest: Unsupported method used on a local file");
1211 request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::ManualRedirectPolicy);
1212 request.setUrl(url);
1213 if(m_method == QLatin1String(
"POST") ||
1214 m_method == QLatin1String(
"PUT")) {
1215 QVariant var = request.header(QNetworkRequest::ContentTypeHeader);
1216 if (var.isValid()) {
1217 QString str = var.toString();
1218 int charsetIdx = str.indexOf(QLatin1String(
"charset="));
1219 if (charsetIdx == -1) {
1221 if (!str.isEmpty()) str.append(QLatin1Char(
';'));
1222 str.append(QLatin1String(
"charset=UTF-8"));
1226 int semiColon = str.indexOf(QLatin1Char(
';'), charsetIdx);
1227 if (semiColon == -1) {
1228 n = str.size() - charsetIdx;
1230 n = semiColon - charsetIdx;
1233 str.replace(charsetIdx, n, QLatin1String(
"UTF-8"));
1235 request.setHeader(QNetworkRequest::ContentTypeHeader, str);
1237 request.setHeader(QNetworkRequest::ContentTypeHeader,
1238 QLatin1String(
"text/plain;charset=UTF-8"));
1243 qWarning().nospace() <<
"XMLHttpRequest: " << qPrintable(m_method) <<
' ' << qPrintable(url.toString());
1244 if (!m_data.isEmpty()) {
1245 qWarning().nospace() <<
" "
1246 << qPrintable(QString::fromUtf8(m_data));
1250 if (m_method == QLatin1String(
"GET")) {
1251 m_network = networkAccessManager()->get(request);
1252 }
else if (m_method == QLatin1String(
"HEAD")) {
1253 m_network = networkAccessManager()->head(request);
1254 }
else if (m_method == QLatin1String(
"POST")) {
1255 m_network = networkAccessManager()->post(request, m_data);
1256 }
else if (m_method == QLatin1String(
"PUT")) {
1257 m_network = networkAccessManager()->put(request, m_data);
1258 }
else if (m_method == QLatin1String(
"DELETE")) {
1259 m_network = networkAccessManager()->deleteResource(request);
1260 }
else if ((m_method == QLatin1String(
"OPTIONS")) ||
1261 m_method == QLatin1String(
"PROPFIND") ||
1262 m_method == QLatin1String(
"PATCH")) {
1263 QBuffer *buffer =
new QBuffer;
1264 buffer->setData(m_data);
1265 buffer->open(QIODevice::ReadOnly);
1266 m_network = networkAccessManager()->sendCustomRequest(request, QByteArray(m_method.toUtf8().constData()), buffer);
1267 buffer->setParent(m_network);
1270 if (m_request.attribute(QNetworkRequest::SynchronousRequestAttribute).toBool()) {
1271 if (m_network->bytesAvailable() > 0)
1272 readyRead(thisObject);
1274 QNetworkReply::NetworkError networkError = m_network->error();
1275 if (networkError != QNetworkReply::NoError) {
1276 error(thisObject, networkError);
1278 finished(thisObject);
1281 QObject::connect(m_network, &QNetworkReply::readyRead,
this, [
this, thisObject]() {
1282 withThisObjectIfValid(thisObject,
1283 [
this](Heap::Object *thisObject) { readyRead(thisObject); });
1285 QObject::connect(m_network, &QNetworkReply::errorOccurred,
this,
1286 [
this, thisObject](QNetworkReply::NetworkError networkError) {
1287 withThisObjectIfValid(thisObject, [
this, networkError](Heap::Object *thisObject) {
1288 error(thisObject, networkError);
1291 QObject::connect(m_network, &QNetworkReply::finished,
this, [
this, thisObject]() {
1292 withThisObjectIfValid(thisObject,
1293 [
this](Heap::Object *thisObject) { finished(thisObject); });
1299 Heap::Object *thisObject,
const QQmlRefPointer<QQmlContextData> &context,
const QByteArray &data)
1301 m_errorFlag =
false;
1303 m_redirectCount = 0;
1306 m_thisObject.set(thisObject->internalClass->engine, thisObject);
1307 m_qmlContext = context;
1309 requestFromUrl(thisObject, m_url);
1311 return Encode::undefined();
1317 m_responseEntityBody = QByteArray();
1319 m_request = QNetworkRequest();
1321 if (!(m_state ==
Unsent ||
1322 (m_state ==
Opened && !m_sendFlag) ||
1327 dispatchCallbackNow(thisObject);
1331 m_thisObject.clear();
1333 return Encode::undefined();
1339 m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
1341 QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
1347 dispatchCallbackSafely(thisObject);
1350 bool wasEmpty = m_responseEntityBody.isEmpty();
1351 m_responseEntityBody.append(m_network->readAll());
1352 if (wasEmpty && !m_responseEntityBody.isEmpty())
1355 dispatchCallbackSafely(thisObject);
1360 int idx = QNetworkReply::staticMetaObject.indexOfEnumerator(
"NetworkError");
1361 if (idx == -1)
return "EnumLookupFailed";
1363 QMetaEnum e = QNetworkReply::staticMetaObject.enumerator(idx);
1365 const char *name = e.valueToKey(error);
1366 if (!name)
return "EnumLookupFailed";
1370void QQmlXMLHttpRequest::error(Heap::Object *thisObject, QNetworkReply::NetworkError error)
1373 m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
1375 QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
1377 m_request = QNetworkRequest();
1382 qWarning().nospace() <<
"XMLHttpRequest: ERROR " << qPrintable(m_url.toString());
1383 qWarning().nospace() <<
" " << error <<
' ' << errorToString(error) <<
' ' << m_statusText;
1386 if (error == QNetworkReply::ContentAccessDenied ||
1387 error == QNetworkReply::ContentOperationNotPermittedError ||
1388 error == QNetworkReply::ContentNotFoundError ||
1389 error == QNetworkReply::AuthenticationRequiredError ||
1390 error == QNetworkReply::ContentReSendError ||
1391 error == QNetworkReply::ContentConflictError ||
1392 error == QNetworkReply::ContentGoneError ||
1393 error == QNetworkReply::UnknownContentError ||
1394 error == QNetworkReply::ProtocolInvalidOperationError ||
1395 error == QNetworkReply::InternalServerError ||
1396 error == QNetworkReply::OperationNotImplementedError ||
1397 error == QNetworkReply::ServiceUnavailableError ||
1398 error == QNetworkReply::UnknownServerError) {
1400 dispatchCallbackSafely(thisObject);
1403 m_responseEntityBody = QByteArray();
1407 m_thisObject.clear();
1408 dispatchCallbackSafely(thisObject);
1411#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
1416 QVariant redirect = m_network->attribute(QNetworkRequest::RedirectionTargetAttribute);
1417 if (redirect.isValid()) {
1418 QUrl url = m_network->url().resolved(redirect.toUrl());
1419 if (!QQmlFile::isLocalFile(url)) {
1422 const QVariant code = m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute);
1423 if (code.isValid() && code.toInt() == 303 && m_method != QLatin1String(
"GET"))
1424 m_method = QStringLiteral(
"GET");
1428 m_responseEntityBody = QByteArray();
1430 requestFromUrl(thisObject, url);
1437 m_network->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
1439 QString::fromUtf8(m_network->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toByteArray());
1444 dispatchCallbackSafely(thisObject);
1446 m_responseEntityBody.append(m_network->readAll());
1450 qWarning().nospace() <<
"XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
1451 if (!m_responseEntityBody.isEmpty()) {
1452 qWarning().nospace() <<
" "
1453 << qPrintable(QString::fromUtf8(m_responseEntityBody));
1461 dispatchCallbackSafely(thisObject);
1466 m_thisObject.clear();
1467 dispatchCallbackSafely(thisObject);
1473 for (
const HeaderPair &header : std::as_const(m_headersList)) {
1474 if (header.first ==
"content-type") {
1475 int separatorIdx = header.second.indexOf(
';');
1476 if (separatorIdx == -1) {
1477 m_mime = header.second;
1479 m_mime = header.second.mid(0, separatorIdx);
1480 int charsetIdx = header.second.indexOf(
"charset=");
1481 if (charsetIdx != -1) {
1483 separatorIdx = header.second.indexOf(
';', charsetIdx);
1484 m_charset = header.second.mid(charsetIdx, separatorIdx >= 0 ? separatorIdx : header.second.size());
1491 const auto mime = mimeType();
1492 if (mime.isEmpty() || mime ==
"text/xml" || mime ==
"application/xml" || mime.endsWith(
"+xml"))
1510 return m_overrideMime.isEmpty() ? m_mime : m_overrideMime;
1517 return m_overrideCharset.isEmpty() ? m_charset : m_overrideCharset;
1522 return m_responseType;
1527 m_responseType = responseType;
1532 if (m_parsedDocument.isEmpty()) {
1533 Scope scope(engine);
1535 QJsonParseError error;
1536 const QString& jtext = responseBody();
1537 JsonParser parser(scope.engine, jtext.constData(), jtext.size());
1538 ScopedValue jsonObject(scope, parser.parse(&error));
1539 if (error.error != QJsonParseError::NoError)
1540 return engine->throwSyntaxError(QStringLiteral(
"JSON.parse: Parse error"));
1542 m_parsedDocument.set(scope.engine, jsonObject);
1545 return m_parsedDocument.value();
1550 if (m_parsedDocument.isEmpty()) {
1551 m_parsedDocument.set(engine, Document::load(engine, rawResponseBody()));
1554 return m_parsedDocument.value();
1559 QStringDecoder decoder;
1561 if (!charset().isEmpty())
1562 decoder = QStringDecoder(charset());
1564 if (!decoder.isValid() && m_gotXml) {
1565 QXmlStreamReader reader(m_responseEntityBody);
1567 decoder = QStringDecoder(reader.documentEncoding().toString().toUtf8());
1570 if (!decoder.isValid() && mimeType() ==
"text/html")
1571 decoder = QStringDecoder::decoderForHtml(m_responseEntityBody);
1573 if (!decoder.isValid()) {
1574 auto encoding = QStringConverter::encodingForData(m_responseEntityBody);
1576 decoder = QStringDecoder(*encoding);
1579 if (!decoder.isValid())
1580 decoder = QStringDecoder(QStringDecoder::Utf8);
1587 QStringDecoder toUtf16 = findTextDecoder();
1588 return toUtf16(m_responseEntityBody);
1593 return m_responseEntityBody;
1598 dispatchCallbackNow(thisObj, m_state == Done, m_errorFlag);
1601void QQmlXMLHttpRequest::dispatchCallbackNow(Heap::Object *thisObj,
bool done,
bool error)
1605 const auto dispatch = [thisObj](
const QString &eventName) {
1606 QV4::Scope scope(thisObj->internalClass->engine);
1607 ScopedString s(scope, scope.engine->newString(eventName));
1608 QV4::ScopedObject callbackOwner(scope, thisObj);
1609 ScopedFunctionObject callback(scope, callbackOwner->get(s));
1614 QV4::JSCallArguments jsCallData(scope);
1615 callback->call(jsCallData);
1617 if (scope.hasException()) {
1618 QQmlError error = scope.engine->catchExceptionAsQmlError();
1619 QQmlEnginePrivate *qmlEnginePrivate = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) :
nullptr;
1620 QQmlEnginePrivate::warning(qmlEnginePrivate, error);
1624 dispatch(QStringLiteral(
"onreadystatechange"));
1627 dispatch(QStringLiteral(
"onerror"));
1629 dispatch(QStringLiteral(
"onload"));
1630 dispatch(QStringLiteral(
"onloadend"));
1636 if (m_wasConstructedWithQmlContext && m_qmlContext.isNull()) {
1644 dispatchCallbackNow(thisObject);
1650 m_network->disconnect();
1651 m_network->deleteLater();
1652 m_network =
nullptr;
1672#define QQmlXMLHttpRequestCtorMembers(class, Member)
1673 Member(class, Pointer, Object *, proto)
1676 DECLARE_MARKOBJECTS(QQmlXMLHttpRequestCtor)
1677 void init(ExecutionEngine *engine);
1695 Scope scope(f->engine());
1699 scope.engine->getNetworkAccessManager(), scope.engine);
1700 Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
1701 ScopedObject proto(scope, ctor->d()->proto);
1702 w->setPrototypeUnchecked(proto);
1703 return w.asReturnedValue();
1707 return Encode::undefined();
1735void Heap::QQmlXMLHttpRequestCtor::init(ExecutionEngine *engine)
1737 Heap::FunctionObject::init(engine, QStringLiteral(
"XMLHttpRequest"));
1738 Scope scope(engine);
1739 Scoped<QV4::QQmlXMLHttpRequestCtor> ctor(scope,
this);
1741 ctor->defineReadonlyProperty(QStringLiteral(
"UNSENT"), Value::fromInt32(QQmlXMLHttpRequest::Unsent));
1742 ctor->defineReadonlyProperty(QStringLiteral(
"OPENED"), Value::fromInt32(QQmlXMLHttpRequest::Opened));
1743 ctor->defineReadonlyProperty(QStringLiteral(
"HEADERS_RECEIVED"), Value::fromInt32(QQmlXMLHttpRequest::HeadersReceived));
1744 ctor->defineReadonlyProperty(QStringLiteral(
"LOADING"), Value::fromInt32(QQmlXMLHttpRequest::Loading));
1745 ctor->defineReadonlyProperty(QStringLiteral(
"DONE"), Value::fromInt32(QQmlXMLHttpRequest::Done));
1747 if (!ctor->d()->proto)
1749 ScopedString s(scope, engine->id_prototype());
1750 ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
1755void QQmlXMLHttpRequestCtor::setupProto()
1757 ExecutionEngine *v4 = engine();
1759 ScopedObject p(scope, v4->newObject());
1760 d()->proto.set(scope.engine, p->d());
1763 p->defineDefaultProperty(QStringLiteral(
"open"), method_open);
1764 p->defineDefaultProperty(QStringLiteral(
"setRequestHeader"), method_setRequestHeader);
1765 p->defineDefaultProperty(QStringLiteral(
"send"), method_send);
1766 p->defineDefaultProperty(QStringLiteral(
"abort"), method_abort);
1767 p->defineDefaultProperty(QStringLiteral(
"getResponseHeader"), method_getResponseHeader);
1768 p->defineDefaultProperty(QStringLiteral(
"getAllResponseHeaders"), method_getAllResponseHeaders);
1769 p->defineDefaultProperty(QStringLiteral(
"overrideMimeType"), method_overrideMimeType);
1772 p->defineAccessorProperty(QStringLiteral(
"readyState"), method_get_readyState,
nullptr);
1773 p->defineAccessorProperty(QStringLiteral(
"status"),method_get_status,
nullptr);
1774 p->defineAccessorProperty(QStringLiteral(
"statusText"),method_get_statusText,
nullptr);
1775 p->defineAccessorProperty(QStringLiteral(
"responseText"),method_get_responseText,
nullptr);
1776 p->defineAccessorProperty(QStringLiteral(
"responseXML"),method_get_responseXML,
nullptr);
1777 p->defineAccessorProperty(QStringLiteral(
"response"),method_get_response,
nullptr);
1778 p->defineAccessorProperty(QStringLiteral(
"responseURL"),method_get_responseURL,
nullptr);
1781 p->defineAccessorProperty(QStringLiteral(
"responseType"), method_get_responseType, method_set_responseType);
1784 p->defineReadonlyProperty(QStringLiteral(
"UNSENT"), Value::fromInt32(0));
1785 p->defineReadonlyProperty(QStringLiteral(
"OPENED"), Value::fromInt32(1));
1786 p->defineReadonlyProperty(QStringLiteral(
"HEADERS_RECEIVED"), Value::fromInt32(2));
1787 p->defineReadonlyProperty(QStringLiteral(
"LOADING"), Value::fromInt32(3));
1788 p->defineReadonlyProperty(QStringLiteral(
"DONE"), Value::fromInt32(4));
1793ReturnedValue QQmlXMLHttpRequestCtor::method_open(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1796 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1799 QQmlXMLHttpRequest *r = w->d()->request;
1801 if (argc < 2 || argc > 5)
1802 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Incorrect argument count");
1805 QString method = argv[0].toQStringNoThrow().toUpper();
1806 if (method != QLatin1String(
"GET") &&
1807 method != QLatin1String(
"PUT") &&
1808 method != QLatin1String(
"HEAD") &&
1809 method != QLatin1String(
"POST") &&
1810 method != QLatin1String(
"DELETE") &&
1811 method != QLatin1String(
"OPTIONS") &&
1812 method != QLatin1String(
"PROPFIND") &&
1813 method != QLatin1String(
"PATCH"))
1814 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Unsupported HTTP method type");
1817 QUrl url = QUrl(argv[1].toQStringNoThrow());
1819 if (url.isRelative()) {
1820 if (QQmlRefPointer<QQmlContextData> qmlContextData = scope.engine->callingQmlContext())
1821 url = qmlContextData->resolvedUrl(url);
1823 url = scope.engine->resolvedUrl(url.url());
1829 async = argv[2].booleanValue();
1833 QString username, password;
1835 username = argv[3].toQStringNoThrow();
1837 password = argv[4].toQStringNoThrow();
1840 url.setFragment(QString());
1843 if (!username.isNull()) url.setUserName(username);
1844 if (!password.isNull()) url.setPassword(password);
1846 return r->open(w->d(), method, url,
1847 async ? QQmlXMLHttpRequest::AsynchronousLoad
1848 : QQmlXMLHttpRequest::SynchronousLoad);
1851ReturnedValue QQmlXMLHttpRequestCtor::method_setRequestHeader(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1854 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1857 QQmlXMLHttpRequest *r = w->d()->request;
1860 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Incorrect argument count");
1862 if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag())
1863 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
1865 QString name = argv[0].toQStringNoThrow();
1866 QString value = argv[1].toQStringNoThrow();
1870 QString nameUpper = name.toUpper();
1871 if (nameUpper == QLatin1String(
"ACCEPT-CHARSET") ||
1872 nameUpper == QLatin1String(
"ACCEPT-ENCODING") ||
1873 nameUpper == QLatin1String(
"CONNECTION") ||
1874 nameUpper == QLatin1String(
"CONTENT-LENGTH") ||
1875 nameUpper == QLatin1String(
"COOKIE") ||
1876 nameUpper == QLatin1String(
"COOKIE2") ||
1877 nameUpper == QLatin1String(
"CONTENT-TRANSFER-ENCODING") ||
1878 nameUpper == QLatin1String(
"DATE") ||
1879 nameUpper == QLatin1String(
"EXPECT") ||
1880 nameUpper == QLatin1String(
"HOST") ||
1881 nameUpper == QLatin1String(
"KEEP-ALIVE") ||
1882 nameUpper == QLatin1String(
"REFERER") ||
1883 nameUpper == QLatin1String(
"TE") ||
1884 nameUpper == QLatin1String(
"TRAILER") ||
1885 nameUpper == QLatin1String(
"TRANSFER-ENCODING") ||
1886 nameUpper == QLatin1String(
"UPGRADE") ||
1887 nameUpper == QLatin1String(
"VIA") ||
1888 nameUpper.startsWith(QLatin1String(
"PROXY-")) ||
1889 nameUpper.startsWith(QLatin1String(
"SEC-")))
1892 r->addHeader(name, value);
1897ReturnedValue QQmlXMLHttpRequestCtor::method_send(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1900 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1903 QQmlXMLHttpRequest *r = w->d()->request;
1905 if (r->readyState() != QQmlXMLHttpRequest::Opened ||
1907 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
1911 if (
const ArrayBuffer *buffer = argv[0].as<ArrayBuffer>()) {
1912 data = buffer->asByteArray();
1914 data = argv[0].toQStringNoThrow().toUtf8();
1918 return r->send(w->d(), scope.engine->callingQmlContext(), data);
1921ReturnedValue QQmlXMLHttpRequestCtor::method_abort(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
1924 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1927 QQmlXMLHttpRequest *r = w->d()->request;
1929 return r->abort(w->d());
1932ReturnedValue QQmlXMLHttpRequestCtor::method_getResponseHeader(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
1935 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1938 QQmlXMLHttpRequest *r = w->d()->request;
1941 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Incorrect argument count");
1943 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1944 r->readyState() != QQmlXMLHttpRequest::Done &&
1945 r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
1946 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
1948 return Encode(scope.engine->newString(r->header(argv[0].toQStringNoThrow())));
1951ReturnedValue QQmlXMLHttpRequestCtor::method_getAllResponseHeaders(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int argc)
1954 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1957 QQmlXMLHttpRequest *r = w->d()->request;
1960 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Incorrect argument count");
1962 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1963 r->readyState() != QQmlXMLHttpRequest::Done &&
1964 r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
1965 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
1967 return Encode(scope.engine->newString(r->headers()));
1971ReturnedValue QQmlXMLHttpRequestCtor::method_get_readyState(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
1974 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1977 QQmlXMLHttpRequest *r = w->d()->request;
1979 return Encode(r->readyState());
1982ReturnedValue QQmlXMLHttpRequestCtor::method_get_status(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
1985 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1988 QQmlXMLHttpRequest *r = w->d()->request;
1990 if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
1991 r->readyState() == QQmlXMLHttpRequest::Opened)
1992 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
1997 return Encode(r->replyStatus());
2000ReturnedValue QQmlXMLHttpRequestCtor::method_get_statusText(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
2003 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2006 QQmlXMLHttpRequest *r = w->d()->request;
2008 if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
2009 r->readyState() == QQmlXMLHttpRequest::Opened)
2010 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
2013 return Encode(scope.engine->newString(QString()));
2015 return Encode(scope.engine->newString(r->replyStatusText()));
2018ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseText(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
2021 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2024 QQmlXMLHttpRequest *r = w->d()->request;
2026 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2027 r->readyState() != QQmlXMLHttpRequest::Done)
2028 return Encode(scope.engine->newString(QString()));
2030 return Encode(scope.engine->newString(r->responseBody()));
2033ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseXML(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
2036 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2039 QQmlXMLHttpRequest *r = w->d()->request;
2041 if (!r->receivedXml() ||
2042 (r->readyState() != QQmlXMLHttpRequest::Loading &&
2043 r->readyState() != QQmlXMLHttpRequest::Done)) {
2044 return Encode::null();
2046 if (r->responseType().isEmpty())
2047 r->setResponseType(QLatin1String(
"document"));
2048 return r->xmlResponseBody(scope.engine);
2052ReturnedValue QQmlXMLHttpRequestCtor::method_get_response(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
2055 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2058 QQmlXMLHttpRequest *r = w->d()->request;
2060 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2061 r->readyState() != QQmlXMLHttpRequest::Done)
2062 RETURN_RESULT(scope.engine->newString(QString()));
2064 const QString& responseType = r->responseType();
2065 if (responseType.compare(QLatin1String(
"text"), Qt::CaseInsensitive) == 0 || responseType.isEmpty()) {
2066 RETURN_RESULT(scope.engine->newString(r->responseBody()));
2067 }
else if (responseType.compare(QLatin1String(
"arraybuffer"), Qt::CaseInsensitive) == 0) {
2068 RETURN_RESULT(scope.engine->newArrayBuffer(r->rawResponseBody()));
2069 }
else if (responseType.compare(QLatin1String(
"json"), Qt::CaseInsensitive) == 0) {
2070 RETURN_RESULT(r->jsonResponseBody(scope.engine));
2071 }
else if (responseType.compare(QLatin1String(
"document"), Qt::CaseInsensitive) == 0) {
2072 RETURN_RESULT(r->xmlResponseBody(scope.engine));
2074 RETURN_RESULT(scope.engine->newString(QString()));
2079ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseType(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
2082 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2085 QQmlXMLHttpRequest *r = w->d()->request;
2086 return Encode(scope.engine->newString(r->responseType()));
2089ReturnedValue QQmlXMLHttpRequestCtor::method_set_responseType(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
2092 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2095 QQmlXMLHttpRequest *r = w->d()->request;
2098 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Incorrect argument count");
2101 r->setResponseType(argv[0].toQStringNoThrow());
2103 return Encode::undefined();
2106ReturnedValue QQmlXMLHttpRequestCtor::method_get_responseURL(
const FunctionObject *b,
const Value *thisObject,
const Value *,
int)
2109 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2112 QQmlXMLHttpRequest *r = w->d()->request;
2114 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2115 r->readyState() != QQmlXMLHttpRequest::Done) {
2116 return Encode(scope.engine->newString(QString()));
2118 QUrl url = r->url();
2119 url.setFragment(QString());
2120 return Encode(scope.engine->newString(url.toString()));
2124ReturnedValue QQmlXMLHttpRequestCtor::method_overrideMimeType(
const FunctionObject *b,
const Value *thisObject,
const Value *argv,
int argc)
2127 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2130 QQmlXMLHttpRequest *r = w->d()->request;
2133 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR,
"Incorrect argument count");
2136 if (r->readyState() == QQmlXMLHttpRequest::Loading ||
2137 r->readyState() == QQmlXMLHttpRequest::Done)
2138 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR,
"Invalid state");
2141 r->setOverrideMimeType(QStringLiteral(
"application/octet-stream"));
2142 const auto parts = argv[0].toQStringNoThrow().split(QLatin1Char(
';'));
2143 const auto type = parts.at(0).trimmed();
2145 const auto mimeInvalidCharacter = [](QChar uni) {
2146 if (uni.unicode() > 127)
2148 const char ch =
char(uni.unicode());
2149 return !(ch ==
'-' || ch ==
'/' || isAsciiLetterOrNumber(ch));
2153 if (type.count(QLatin1Char(
'/')) == 1
2154 && std::find_if(type.begin(), type.end(), mimeInvalidCharacter) == type.end()) {
2156 r->setOverrideMimeType(type);
2158 for (
const auto &part : parts) {
2159 const QLatin1String charset(
"charset=");
2161 if (part.trimmed().startsWith(charset)) {
2163 const int offset(part.indexOf(charset) + charset.size());
2164 r->setOverrideCharset(part.sliced(offset).trimmed());
2168 return Encode::undefined();
2181 Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocate<QQmlXMLHttpRequestCtor>(v4));
2182 ScopedString s(scope, v4->newString(QStringLiteral(
"XMLHttpRequest")));
2183 v4->globalObject->defineReadonlyProperty(s, ctor);
2191#include <qqmlxmlhttprequest.moc>
friend class QQmlEnginePrivate
void setOverrideCharset(QStringView charset)
void setResponseType(const QString &)
void setOverrideMimeType(QStringView mimeType)
QQmlXMLHttpRequest(QNetworkAccessManager *manager, QV4::ExecutionEngine *v4)
QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine *)
const QByteArray charset() const
quint32 readyState() const
const QByteArray & rawResponseBody() const
ReturnedValue send(Heap::Object *thisObject, const QQmlRefPointer< QQmlContextData > &context, const QByteArray &)
ReturnedValue abort(Heap::Object *thisObject)
void addHeader(const QString &, const QString &)
virtual ~QQmlXMLHttpRequest()
QString header(const QString &name) const
ReturnedValue open(Heap::Object *thisObject, const QString &, const QUrl &, LoadType)
QString replyStatusText() const
const QString & responseType() const
const QByteArray mimeType() const
QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine *)
static ReturnedValue prototype(ExecutionEngine *)
static ReturnedValue method_name(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_value(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_ownerElement(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue prototype(ExecutionEngine *v4)
static ReturnedValue prototype(ExecutionEngine *v4)
static ReturnedValue method_length(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_documentElement(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_xmlStandalone(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue load(ExecutionEngine *engine, const QByteArray &data)
static ReturnedValue prototype(ExecutionEngine *)
static ReturnedValue method_xmlVersion(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_xmlEncoding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue prototype(ExecutionEngine *)
static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
QList< NodeImpl * > attributes
QList< NodeImpl * > children
static ReturnedValue create(ExecutionEngine *, NodeImpl *)
static ReturnedValue method_get_childNodes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static void initClass(ExecutionEngine *engine)
static ReturnedValue method_get_nodeValue(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_previousSibling(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_namespaceUri(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue getProto(ExecutionEngine *v4)
static ReturnedValue method_get_parentNode(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_nextSibling(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_nodeType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_lastChild(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_firstChild(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_attributes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_nodeName(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_wholeText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue prototype(ExecutionEngine *)
static ReturnedValue method_isElementContentWhitespace(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
DECLARE_HEAP_OBJECT(QmlContext, ExecutionContext)
DEFINE_OBJECT_VTABLE(Node)
DEFINE_OBJECT_VTABLE(NodeList)
DEFINE_OBJECT_VTABLE(NamedNodeMap)
DEFINE_OBJECT_VTABLE(NodePrototype)
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
static const char * errorToString(QNetworkReply::NetworkError error)
DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestWrapper)
static QQmlXMLHttpRequestData * xhrdata(ExecutionEngine *v4)
void * qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
DEFINE_OBJECT_VTABLE(QQmlXMLHttpRequestCtor)
void qt_rem_qmlxmlhttprequest(ExecutionEngine *, void *d)
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION
#define V4THROW_REFERENCE(string)
PersistentValue characterDataPrototype
PersistentValue documentPrototype
PersistentValue nodeFunction
PersistentValue elementPrototype
PersistentValue textPrototype
PersistentValue attrPrototype
PersistentValue cdataPrototype
PersistentValue nodePrototype
~QQmlXMLHttpRequestData()
QList< NodeImpl * > * listPtr
void init(NodeImpl *data, const QList< NodeImpl * > &list)
QList< NodeImpl * > & list()
void init(NodeImpl *data)
void init(NodeImpl *data)
QQmlXMLHttpRequest * request
void init(QQmlXMLHttpRequest *request)
static ReturnedValue method_getAllResponseHeaders(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_response(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_responseURL(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue virtualCall(const FunctionObject *, const Value *, const Value *, int)
static ReturnedValue method_set_responseType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_setRequestHeader(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_readyState(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_responseText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_open(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue virtualCallAsConstructor(const FunctionObject *f, const Value *, int, const Value *)
static ReturnedValue method_overrideMimeType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_getResponseHeader(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_responseType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_responseXML(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_abort(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_statusText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_get_status(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
static ReturnedValue method_send(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)