Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlxmlhttprequest.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include "qqmlengine.h"
7#include "qqmlengine_p.h"
8#include <private/qqmlrefcount_p.h>
9#include "qqmlengine_p.h"
10#include "qqmlglobal_p.h"
11#include <private/qv4domerrors_p.h>
12#include <private/qv4engine_p.h>
13#include <private/qv4functionobject_p.h>
14#include <private/qv4scopedvalue_p.h>
15#include <private/qv4jscall_p.h>
16
17#include <QtCore/qobject.h>
18#include <QtQml/qjsvalue.h>
19#include <QtQml/qjsengine.h>
20#include <QtQml/qqmlfile.h>
21#include <QtNetwork/qnetworkreply.h>
22
23#include <QtCore/qpointer.h>
24#include <QtCore/qstringconverter.h>
25#include <QtCore/qxmlstream.h>
26#include <QtCore/qstack.h>
27#include <QtCore/qdebug.h>
28#include <QtCore/qbuffer.h>
29
30#include <private/qv4objectproto_p.h>
31#include <private/qv4scopedvalue_p.h>
32#include <private/qv4arraybuffer_p.h>
33#include <private/qv4jsonobject_p.h>
34
35using namespace QV4;
36
37#define V4THROW_REFERENCE(string) \
38 do { \
39 ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string))); \
40 return scope.engine->throwError(error); \
41 } while (false)
42
44
45DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP);
46DEFINE_BOOL_CONFIG_OPTION(xhrFileWrite, QML_XHR_ALLOW_FILE_WRITE);
47DEFINE_BOOL_CONFIG_OPTION(xhrFileRead, QML_XHR_ALLOW_FILE_READ);
48
63
65{
66 return (QQmlXMLHttpRequestData *)v4->xmlHttpRequestData();
67}
68
72
76
77namespace QV4 {
78
79class DocumentImpl;
81{
82public:
88
89 // These numbers are copied from the Node IDL definition
105
108
110
111 void addref();
112 void release();
113
116
117 QList<NodeImpl *> children;
118 QList<NodeImpl *> attributes;
119};
120
121class DocumentImpl final : public QQmlRefCounted<DocumentImpl>, public NodeImpl
122{
123 using Base1 = QQmlRefCounted<DocumentImpl>;
124public:
126 ~DocumentImpl() override {
127 delete root;
128 }
129
133
135
136 void addref() { Base1::addref(); }
138};
139
140namespace Heap {
141
143 void init(NodeImpl *data, const QList<NodeImpl *> &list);
144 void destroy() {
145 delete listPtr;
146 if (d)
147 d->release();
148 Object::destroy();
149 }
150 QList<NodeImpl *> &list() {
151 if (listPtr == nullptr)
152 listPtr = new QList<NodeImpl *>;
153 return *listPtr;
154 }
155
156 QList<NodeImpl *> *listPtr; // Only used in NamedNodeMap
158};
159
160struct NodeList : Object {
161 void init(NodeImpl *data);
162 void destroy() {
163 if (d)
164 d->release();
165 Object::destroy();
166 }
168};
169
171 void init();
172};
173
174struct Node : Object {
175 void init(NodeImpl *data);
176 void destroy() {
177 if (d)
178 d->release();
179 Object::destroy();
180 }
182};
183
184}
185
186class NamedNodeMap : public Object
187{
188public:
191
192 // C++ API
193 static ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList<NodeImpl *> &);
194
195 // JS API
196 static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
197};
198
199void Heap::NamedNodeMap::init(NodeImpl *data, const QList<NodeImpl *> &list)
200{
201 Object::init();
202 d = data;
203 this->list() = list;
204 if (d)
205 d->addref();
206}
207
209
210class NodeList : public Object
211{
212public:
215
216 // JS API
217 static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
218
219 // C++ API
221
222};
223
225{
226 Object::init();
227 d = data;
228 if (d)
229 d->addref();
230}
231
233
234class NodePrototype : public Object
235{
236public:
238
239 static void initClass(ExecutionEngine *engine);
240
241 // JS API
242 static ReturnedValue method_get_nodeName(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
243 static ReturnedValue method_get_nodeValue(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
244 static ReturnedValue method_get_nodeType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
245 static ReturnedValue method_get_namespaceUri(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
246
247 static ReturnedValue method_get_parentNode(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
248 static ReturnedValue method_get_childNodes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
249 static ReturnedValue method_get_firstChild(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
250 static ReturnedValue method_get_lastChild(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
251 static ReturnedValue method_get_previousSibling(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
252 static ReturnedValue method_get_nextSibling(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
253 static ReturnedValue method_get_attributes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
254
255 //static ReturnedValue ownerDocument(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
256 //static ReturnedValue namespaceURI(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
257 //static ReturnedValue prefix(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
258 //static ReturnedValue localName(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
259 //static ReturnedValue baseURI(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
260 //static ReturnedValue textContent(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
261
262 static ReturnedValue getProto(ExecutionEngine *v4);
263
264};
265
266void Heap::NodePrototype::init()
267{
268 Object::init();
269 Scope scope(internalClass->engine);
270 ScopedObject o(scope, this);
271
272 o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, nullptr);
273 o->defineAccessorProperty(QStringLiteral("nodeValue"), QV4::NodePrototype::method_get_nodeValue, nullptr);
274 o->defineAccessorProperty(QStringLiteral("nodeType"), QV4::NodePrototype::method_get_nodeType, nullptr);
275 o->defineAccessorProperty(QStringLiteral("namespaceUri"), QV4::NodePrototype::method_get_namespaceUri, nullptr);
276
277 o->defineAccessorProperty(QStringLiteral("parentNode"), QV4::NodePrototype::method_get_parentNode, nullptr);
278 o->defineAccessorProperty(QStringLiteral("childNodes"), QV4::NodePrototype::method_get_childNodes, nullptr);
279 o->defineAccessorProperty(QStringLiteral("firstChild"), QV4::NodePrototype::method_get_firstChild, nullptr);
280 o->defineAccessorProperty(QStringLiteral("lastChild"), QV4::NodePrototype::method_get_lastChild, nullptr);
281 o->defineAccessorProperty(QStringLiteral("previousSibling"), QV4::NodePrototype::method_get_previousSibling, nullptr);
282 o->defineAccessorProperty(QStringLiteral("nextSibling"), QV4::NodePrototype::method_get_nextSibling, nullptr);
283 o->defineAccessorProperty(QStringLiteral("attributes"), QV4::NodePrototype::method_get_attributes, nullptr);
284}
285
286
288
289struct Node : public Object
290{
293
294 // C++ API
296
297 bool isNull() const;
298};
299
301{
302 Object::init();
303 d = data;
304 if (d)
305 d->addref();
306}
307
309
310class Element : public Node
311{
312public:
313 // C++ API
314 static ReturnedValue prototype(ExecutionEngine *);
315};
316
317class Attr : public Node
318{
319public:
320 // JS API
321 static ReturnedValue method_name(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
322// static void specified(CallContext *);
323 static ReturnedValue method_value(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
324 static ReturnedValue method_ownerElement(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
325// static void schemaTypeInfo(CallContext *);
326// static void isId(CallContext *c);
327
328 // C++ API
329 static ReturnedValue prototype(ExecutionEngine *);
330};
331
332class CharacterData : public Node
333{
334public:
335 // JS API
336 static ReturnedValue method_length(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
337
338 // C++ API
339 static ReturnedValue prototype(ExecutionEngine *v4);
340};
341
342class Text : public CharacterData
343{
344public:
345 // JS API
346 static ReturnedValue method_isElementContentWhitespace(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
347 static ReturnedValue method_wholeText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
348
349 // C++ API
350 static ReturnedValue prototype(ExecutionEngine *);
351};
352
353class CDATA : public Text
354{
355public:
356 // C++ API
357 static ReturnedValue prototype(ExecutionEngine *v4);
358};
359
360class Document : public Node
361{
362public:
363 // JS API
364 static ReturnedValue method_xmlVersion(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
365 static ReturnedValue method_xmlEncoding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
366 static ReturnedValue method_xmlStandalone(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
367 static ReturnedValue method_documentElement(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
368
369 // C++ API
370 static ReturnedValue prototype(ExecutionEngine *);
372};
373
374}
375
377{
378 document->addref();
379}
380
382{
383 document->release();
384}
385
387{
388 Scope scope(b);
389 Scoped<Node> r(scope, thisObject->as<Node>());
390 if (!r)
392
394 switch (r->d()->d->type) {
396 name = QStringLiteral("#document");
397 break;
398 case NodeImpl::CDATA:
399 name = QStringLiteral("#cdata-section");
400 break;
401 case NodeImpl::Text:
402 name = QStringLiteral("#text");
403 break;
404 default:
405 name = r->d()->d->name;
406 break;
407 }
408 return Encode(scope.engine->newString(name));
409}
410
412{
413 QV4::Scope scope(b);
414 Scoped<Node> r(scope, thisObject->as<Node>());
415 if (!r)
417
418 if (r->d()->d->type == NodeImpl::Document ||
419 r->d()->d->type == NodeImpl::DocumentFragment ||
420 r->d()->d->type == NodeImpl::DocumentType ||
421 r->d()->d->type == NodeImpl::Element ||
422 r->d()->d->type == NodeImpl::Entity ||
423 r->d()->d->type == NodeImpl::EntityReference ||
424 r->d()->d->type == NodeImpl::Notation)
426
427 return Encode(scope.engine->newString(r->d()->d->data));
428}
429
431{
432 QV4::Scope scope(b);
433 Scoped<Node> r(scope, thisObject->as<Node>());
434 if (!r)
436
437 return Encode(r->d()->d->type);
438}
439
441{
442 QV4::Scope scope(b);
443 Scoped<Node> r(scope, thisObject->as<Node>());
444 if (!r)
446
447 return Encode(scope.engine->newString(r->d()->d->namespaceUri));
448}
449
451{
452 QV4::Scope scope(b);
453 Scoped<Node> r(scope, thisObject->as<Node>());
454 if (!r)
456
457 if (r->d()->d->parent)
458 return Node::create(scope.engine, r->d()->d->parent);
459 else
460 return Encode::null();
461}
462
464{
465 QV4::Scope scope(b);
466 Scoped<Node> r(scope, thisObject->as<Node>());
467 if (!r)
469
470 return NodeList::create(scope.engine, r->d()->d);
471}
472
474{
475 QV4::Scope scope(b);
476 Scoped<Node> r(scope, thisObject->as<Node>());
477 if (!r)
479
480 if (r->d()->d->children.isEmpty())
481 return Encode::null();
482 else
483 return Node::create(scope.engine, r->d()->d->children.constFirst());
484}
485
487{
488 QV4::Scope scope(b);
489 Scoped<Node> r(scope, thisObject->as<Node>());
490 if (!r)
492
493 if (r->d()->d->children.isEmpty())
494 return Encode::null();
495 else
496 return Node::create(scope.engine, r->d()->d->children.constLast());
497}
498
500{
501 QV4::Scope scope(b);
502 Scoped<Node> r(scope, thisObject->as<Node>());
503 if (!r)
505
506 if (!r->d()->d->parent)
508
509 for (int ii = 0; ii < r->d()->d->parent->children.size(); ++ii) {
510 if (r->d()->d->parent->children.at(ii) == r->d()->d) {
511 if (ii == 0)
512 return Encode::null();
513 else
514 return Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1));
515 }
516 }
517
518 return Encode::null();
519}
520
522{
523 QV4::Scope scope(b);
524 Scoped<Node> r(scope, thisObject->as<Node>());
525 if (!r)
527
528 if (!r->d()->d->parent)
530
531 for (int ii = 0; ii < r->d()->d->parent->children.size(); ++ii) {
532 if (r->d()->d->parent->children.at(ii) == r->d()->d) {
533 if ((ii + 1) == r->d()->d->parent->children.size())
534 return Encode::null();
535 else
536 return Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1));
537 }
538 }
539
540 return Encode::null();
541}
542
544{
545 QV4::Scope scope(b);
546 Scoped<Node> r(scope, thisObject->as<Node>());
547 if (!r)
549
550 if (r->d()->d->type != NodeImpl::Element)
551 return Encode::null();
552 else
553 return NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes);
554}
555
557{
558 Scope scope(v4);
560 if (d->nodePrototype.isUndefined()) {
562 d->nodePrototype.set(v4, p);
563 v4->freezeObject(p);
564 }
565 return d->nodePrototype.value();
566}
567
569{
570 Scope scope(v4);
571
572 Scoped<Node> instance(scope, v4->memoryManager->allocate<Node>(data));
573 ScopedObject p(scope);
574
575 switch (data->type) {
576 case NodeImpl::Attr:
577 instance->setPrototypeUnchecked((p = Attr::prototype(v4)));
578 break;
583 case NodeImpl::Entity:
587 return Encode::undefined();
588 case NodeImpl::CDATA:
589 instance->setPrototypeUnchecked((p = CDATA::prototype(v4)));
590 break;
591 case NodeImpl::Text:
592 instance->setPrototypeUnchecked((p = Text::prototype(v4)));
593 break;
595 instance->setPrototypeUnchecked((p = Element::prototype(v4)));
596 break;
597 }
598
599 return instance.asReturnedValue();
600}
601
603{
605 if (d->elementPrototype.isUndefined()) {
606 Scope scope(engine);
607 ScopedObject p(scope, engine->newObject());
608 ScopedObject pp(scope);
609 p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
610 p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, nullptr);
611 d->elementPrototype.set(engine, p);
612 engine->freezeObject(p);
613 }
614 return d->elementPrototype.value();
615}
616
618{
620 if (d->attrPrototype.isUndefined()) {
621 Scope scope(engine);
622 ScopedObject p(scope, engine->newObject());
623 ScopedObject pp(scope);
624 p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
625 p->defineAccessorProperty(QStringLiteral("name"), method_name, nullptr);
626 p->defineAccessorProperty(QStringLiteral("value"), method_value, nullptr);
627 p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, nullptr);
628 d->attrPrototype.set(engine, p);
629 engine->freezeObject(p);
630 }
631 return d->attrPrototype.value();
632}
633
634ReturnedValue Attr::method_name(const FunctionObject *b, const Value *thisObject, const Value *, int)
635{
636 QV4::Scope scope(b);
637 Scoped<Node> r(scope, thisObject->as<Node>());
638 if (!r)
640
641 return Encode(scope.engine->newString(r->d()->d->name));
642}
643
644ReturnedValue Attr::method_value(const FunctionObject *b, const Value *thisObject, const Value *, int)
645{
646 QV4::Scope scope(b);
647 Scoped<Node> r(scope, thisObject->as<Node>());
648 if (!r)
650
651 return Encode(scope.engine->newString(r->d()->d->data));
652}
653
654ReturnedValue Attr::method_ownerElement(const FunctionObject *b, const Value *thisObject, const Value *, int)
655{
656 QV4::Scope scope(b);
657 Scoped<Node> r(scope, thisObject->as<Node>());
658 if (!r)
660
661 return Node::create(scope.engine, r->d()->d->parent);
662}
663
665{
666 QV4::Scope scope(b);
667 Scoped<Node> r(scope, thisObject->as<Node>());
668 if (!r)
670
671 return Encode(int(r->d()->d->data.size()));
672}
673
675{
677 if (d->characterDataPrototype.isUndefined()) {
678 Scope scope(v4);
679 ScopedObject p(scope, v4->newObject());
680 ScopedObject pp(scope);
681 p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
682 p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, nullptr);
683 p->defineAccessorProperty(QStringLiteral("length"), method_length, nullptr);
684 d->characterDataPrototype.set(v4, p);
685 v4->freezeObject(p);
686 }
687 return d->characterDataPrototype.value();
688}
689
691{
692 QV4::Scope scope(b);
693 Scoped<Node> r(scope, thisObject->as<Node>());
694 if (!r)
696
697 return Encode(QStringView(r->d()->d->data).trimmed().isEmpty());
698}
699
700ReturnedValue Text::method_wholeText(const FunctionObject *b, const Value *thisObject, const Value *, int)
701{
702 QV4::Scope scope(b);
703 Scoped<Node> r(scope, thisObject->as<Node>());
704 if (!r)
706
707 return Encode(scope.engine->newString(r->d()->d->data));
708}
709
711{
713 if (d->textPrototype.isUndefined()) {
714 Scope scope(v4);
715 ScopedObject p(scope, v4->newObject());
716 ScopedObject pp(scope);
717 p->setPrototypeUnchecked((pp = CharacterData::prototype(v4)));
718 p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, nullptr);
719 p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, nullptr);
720 d->textPrototype.set(v4, p);
721 v4->freezeObject(p);
722 }
723 return d->textPrototype.value();
724}
725
727{
728 // ### why not just use TextProto???
730 if (d->cdataPrototype.isUndefined()) {
731 Scope scope(v4);
732 ScopedObject p(scope, v4->newObject());
733 ScopedObject pp(scope);
734 p->setPrototypeUnchecked((pp = Text::prototype(v4)));
735 d->cdataPrototype.set(v4, p);
736 v4->freezeObject(p);
737 }
738 return d->cdataPrototype.value();
739}
740
742{
744 if (d->documentPrototype.isUndefined()) {
745 Scope scope(v4);
746 ScopedObject p(scope, v4->newObject());
747 ScopedObject pp(scope);
748 p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
749 p->defineAccessorProperty(QStringLiteral("xmlVersion"), method_xmlVersion, nullptr);
750 p->defineAccessorProperty(QStringLiteral("xmlEncoding"), method_xmlEncoding, nullptr);
751 p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, nullptr);
752 p->defineAccessorProperty(QStringLiteral("documentElement"), method_documentElement, nullptr);
753 d->documentPrototype.set(v4, p);
754 v4->freezeObject(p);
755 }
756 return d->documentPrototype.value();
757}
758
760{
761 Scope scope(v4);
762
763 DocumentImpl *document = nullptr;
764 QStack<NodeImpl *> nodeStack;
765
766 QXmlStreamReader reader(data);
767
768 while (!reader.atEnd()) {
769 switch (reader.readNext()) {
770 case QXmlStreamReader::NoToken:
771 break;
772 case QXmlStreamReader::Invalid:
773 break;
774 case QXmlStreamReader::StartDocument:
775 Q_ASSERT(!document);
776 document = new DocumentImpl;
777 document->document = document;
778 document->version = reader.documentVersion().toString();
779 document->encoding = reader.documentEncoding().toString();
780 document->isStandalone = reader.isStandaloneDocument();
781 break;
782 case QXmlStreamReader::EndDocument:
783 break;
784 case QXmlStreamReader::StartElement:
785 {
786 Q_ASSERT(document);
787 NodeImpl *node = new NodeImpl;
788 node->document = document;
789 node->namespaceUri = reader.namespaceUri().toString();
790 node->name = reader.name().toString();
791 if (nodeStack.isEmpty()) {
792 document->root = node;
793 } else {
794 node->parent = nodeStack.top();
795 node->parent->children.append(node);
796 }
797 nodeStack.append(node);
798
799 const auto attributes = reader.attributes();
800 for (const QXmlStreamAttribute &a : attributes) {
801 NodeImpl *attr = new NodeImpl;
802 attr->document = document;
803 attr->type = NodeImpl::Attr;
804 attr->namespaceUri = a.namespaceUri().toString();
805 attr->name = a.name().toString();
806 attr->data = a.value().toString();
807 attr->parent = node;
808 node->attributes.append(attr);
809 }
810 }
811 break;
812 case QXmlStreamReader::EndElement:
813 nodeStack.pop();
814 break;
815 case QXmlStreamReader::Characters:
816 {
817 NodeImpl *node = new NodeImpl;
818 node->document = document;
819 node->type = reader.isCDATA()?NodeImpl::CDATA:NodeImpl::Text;
820 node->parent = nodeStack.top();
821 node->parent->children.append(node);
822 node->data = reader.text().toString();
823 }
824 break;
825 case QXmlStreamReader::Comment:
826 break;
827 case QXmlStreamReader::DTD:
828 break;
829 case QXmlStreamReader::EntityReference:
830 break;
831 case QXmlStreamReader::ProcessingInstruction:
832 break;
833 }
834 }
835
836 if (!document || reader.hasError()) {
837 if (document)
838 document->release();
839 return Encode::null();
840 }
841
842 ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document));
843 document->release(); // the GC should own the NodeImpl via Node now
844 ScopedObject p(scope);
846 return instance.asReturnedValue();
847}
848
849bool Node::isNull() const
850{
851 return d()->d == nullptr;
852}
853
854ReturnedValue NamedNodeMap::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
855{
856 Q_ASSERT(m->as<NamedNodeMap>());
857
858 const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
859 QV4::ExecutionEngine *v4 = r->engine();
860
861 if (id.isArrayIndex()) {
862 uint index = id.asArrayIndex();
863
864 if ((int)index < r->d()->list().size()) {
865 if (hasProperty)
866 *hasProperty = true;
867 return Node::create(v4, r->d()->list().at(index));
868 }
869 if (hasProperty)
870 *hasProperty = false;
871 return Encode::undefined();
872 }
873
874 if (id.isSymbol())
875 return Object::virtualGet(m, id, receiver, hasProperty);
876
877 if (id == v4->id_length()->propertyKey())
878 return Value::fromInt32(r->d()->list().size()).asReturnedValue();
879
880 QString str = id.toQString();
881 for (int ii = 0; ii < r->d()->list().size(); ++ii) {
882 if (r->d()->list().at(ii)->name == str) {
883 if (hasProperty)
884 *hasProperty = true;
885 return Node::create(v4, r->d()->list().at(ii));
886 }
887 }
888
889 if (hasProperty)
890 *hasProperty = false;
891 return Encode::undefined();
892}
893
895{
896 return (v4->memoryManager->allocate<NamedNodeMap>(data, list))->asReturnedValue();
897}
898
899ReturnedValue NodeList::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
900{
901 Q_ASSERT(m->as<NodeList>());
902 const NodeList *r = static_cast<const NodeList *>(m);
903 QV4::ExecutionEngine *v4 = r->engine();
904
905 if (id.isArrayIndex()) {
906 uint index = id.asArrayIndex();
907 if ((int)index < r->d()->d->children.size()) {
908 if (hasProperty)
909 *hasProperty = true;
910 return Node::create(v4, r->d()->d->children.at(index));
911 }
912 if (hasProperty)
913 *hasProperty = false;
914 return Encode::undefined();
915 }
916
917 if (id == v4->id_length()->propertyKey())
918 return Value::fromInt32(r->d()->d->children.size()).asReturnedValue();
919 return Object::virtualGet(m, id, receiver, hasProperty);
920}
921
923{
924 return (v4->memoryManager->allocate<NodeList>(data))->asReturnedValue();
925}
926
928{
929 Scope scope(b);
930 Scoped<Node> r(scope, thisObject->as<Node>());
931 if (!r || r->d()->d->type != NodeImpl::Document)
933
934 return Node::create(scope.engine, static_cast<DocumentImpl *>(r->d()->d)->root);
935}
936
938{
939 Scope scope(b);
940 Scoped<Node> r(scope, thisObject->as<Node>());
941 if (!r || r->d()->d->type != NodeImpl::Document)
943
944 return Encode(static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
945}
946
947ReturnedValue Document::method_xmlVersion(const FunctionObject *b, const Value *thisObject, const Value *, int)
948{
949 Scope scope(b);
950 Scoped<Node> r(scope, thisObject->as<Node>());
951 if (!r || r->d()->d->type != NodeImpl::Document)
953
954 return Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->version));
955}
956
958{
959 Scope scope(b);
960 Scoped<Node> r(scope, thisObject->as<Node>());
961 if (!r || r->d()->d->type != NodeImpl::Document)
963
964 return Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->encoding));
965}
966
968{
970public:
971 enum LoadType {
973 SynchronousLoad
974 };
975 enum State {
976 Unsent = 0,
977 Opened = 1,
978 HeadersReceived = 2,
979 Loading = 3,
980 Done = 4
981 };
982
984 virtual ~QQmlXMLHttpRequest();
985
986 bool sendFlag() const;
987 bool errorFlag() const;
988 quint32 readyState() const;
989 int replyStatus() const;
990 QString replyStatusText() const;
991
992 ReturnedValue open(Object *thisObject, const QString &, const QUrl &, LoadType);
993 ReturnedValue send(Object *thisObject, const QQmlRefPointer<QQmlContextData> &context,
994 const QByteArray &);
995 ReturnedValue abort(Object *thisObject);
996
997 void addHeader(const QString &, const QString &);
998 QString header(const QString &name) const;
999 QString headers() const;
1000
1001 QString responseBody();
1002 const QByteArray & rawResponseBody() const;
1003 bool receivedXml() const;
1004 QUrl url() const;
1005
1006 const QString & responseType() const;
1007 void setResponseType(const QString &);
1008 void setOverrideMimeType(QStringView mimeType) { m_overrideMime = mimeType.toUtf8(); }
1009 void setOverrideCharset(QStringView charset) { m_overrideCharset = charset.toUtf8(); }
1010
1011 const QByteArray mimeType() const;
1012 const QByteArray charset() const;
1013
1014 QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*);
1015 QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine*);
1016private slots:
1017 void readyRead();
1019 void finished();
1020
1021private:
1022 void requestFromUrl(const QUrl &url);
1023
1024 State m_state;
1025 bool m_errorFlag;
1026 bool m_sendFlag;
1027 QString m_method;
1028 QUrl m_url;
1029 QByteArray m_responseEntityBody;
1031 int m_redirectCount;
1032
1033 typedef QPair<QByteArray, QByteArray> HeaderPair;
1034 typedef QList<HeaderPair> HeadersList;
1035 HeadersList m_headersList;
1036 void fillHeadersList();
1037
1038 bool m_gotXml;
1039 QByteArray m_mime;
1040 QByteArray m_charset;
1041 QByteArray m_overrideMime;
1042 QByteArray m_overrideCharset;
1043
1044 QStringDecoder findTextDecoder() const;
1045 void readEncoding();
1046
1047 PersistentValue m_thisObject;
1048 QQmlRefPointer<QQmlContextData> m_qmlContext;
1049 bool m_wasConstructedWithQmlContext = true;
1050
1051 void dispatchCallbackNow(Object *thisObj);
1052 static void dispatchCallbackNow(Object *thisObj, bool done, bool error);
1053 void dispatchCallbackSafely();
1054
1055 int m_status;
1056 QString m_statusText;
1057 QNetworkRequest m_request;
1058 QStringList m_addedHeaders;
1059 QPointer<QNetworkReply> m_network;
1060 void destroyNetwork();
1061
1062 QNetworkAccessManager *m_nam;
1063 QNetworkAccessManager *networkAccessManager() { return m_nam; }
1064
1065 QString m_responseType;
1066 QV4::PersistentValue m_parsedDocument;
1067};
1068
1070 : m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
1071 , m_redirectCount(0), m_gotXml(false), m_network(nullptr), m_nam(manager)
1072{
1073 m_wasConstructedWithQmlContext = !v4->callingQmlContext().isNull();
1074}
1075
1077{
1078 destroyNetwork();
1079}
1080
1082{
1083 return m_sendFlag;
1084}
1085
1087{
1088 return m_errorFlag;
1089}
1090
1092{
1093 return m_state;
1094}
1095
1097{
1098 return m_status;
1099}
1100
1102{
1103 return m_statusText;
1104}
1105
1107{
1108 destroyNetwork();
1109 m_sendFlag = false;
1110 m_errorFlag = false;
1111 m_responseEntityBody = QByteArray();
1112 m_method = method;
1113 m_url = url;
1115 m_state = Opened;
1116 m_addedHeaders.clear();
1117 dispatchCallbackNow(thisObject);
1118 return Encode::undefined();
1119}
1120
1122{
1123 QByteArray utfname = name.toUtf8();
1124
1125 if (m_addedHeaders.contains(name, Qt::CaseInsensitive)) {
1126 m_request.setRawHeader(utfname, m_request.rawHeader(utfname) + ',' + value.toUtf8());
1127 } else {
1128 m_request.setRawHeader(utfname, value.toUtf8());
1129 m_addedHeaders.append(name);
1130 }
1131}
1132
1134{
1135 if (!m_headersList.isEmpty()) {
1136 const QByteArray utfname = name.toLower().toUtf8();
1137 for (const HeaderPair &header : m_headersList) {
1138 if (header.first == utfname)
1139 return QString::fromUtf8(header.second);
1140 }
1141 }
1142 return QString();
1143}
1144
1146{
1147 QString ret;
1148
1149 for (const HeaderPair &header : m_headersList) {
1150 if (ret.size())
1151 ret.append(QLatin1String("\r\n"));
1153 + QString::fromUtf8(header.second);
1154 }
1155 return ret;
1156}
1157
1158void QQmlXMLHttpRequest::fillHeadersList()
1159{
1160 const QList<QByteArray> headerList = m_network->rawHeaderList();
1161
1162 m_headersList.clear();
1163 for (const QByteArray &header : headerList) {
1164 HeaderPair pair (header.toLower(), m_network->rawHeader(header));
1165 if (pair.first == "set-cookie" ||
1166 pair.first == "set-cookie2")
1167 continue;
1168
1169 m_headersList << pair;
1170 }
1171}
1172
1173void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
1174{
1175 m_url = url;
1176 QNetworkRequest request = m_request;
1177
1179 if (m_method == QLatin1String("PUT"))
1180 {
1181 if (!xhrFileWrite()) {
1182 qWarning("XMLHttpRequest: Using PUT on a local file is disabled by default.\n"
1183 "Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature.");
1184 return;
1185 }
1186 } else if (m_method == QLatin1String("GET")) {
1187 if (!xhrFileRead()) {
1188 qWarning("XMLHttpRequest: Using GET on a local file is disabled by default.\n"
1189 "Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature.");
1190 return;
1191 }
1192 } else {
1193 qWarning("XMLHttpRequest: Unsupported method used on a local file");
1194 return;
1195 }
1196 }
1197
1200 if(m_method == QLatin1String("POST") ||
1201 m_method == QLatin1String("PUT")) {
1203 if (var.isValid()) {
1204 QString str = var.toString();
1205 int charsetIdx = str.indexOf(QLatin1String("charset="));
1206 if (charsetIdx == -1) {
1207 // No charset - append
1208 if (!str.isEmpty()) str.append(QLatin1Char(';'));
1209 str.append(QLatin1String("charset=UTF-8"));
1210 } else {
1211 charsetIdx += 8;
1212 int n = 0;
1213 int semiColon = str.indexOf(QLatin1Char(';'), charsetIdx);
1214 if (semiColon == -1) {
1215 n = str.size() - charsetIdx;
1216 } else {
1217 n = semiColon - charsetIdx;
1218 }
1219
1220 str.replace(charsetIdx, n, QLatin1String("UTF-8"));
1221 }
1223 } else {
1225 QLatin1String("text/plain;charset=UTF-8"));
1226 }
1227 }
1228
1229 if (xhrDump()) {
1230 qWarning().nospace() << "XMLHttpRequest: " << qPrintable(m_method) << ' ' << qPrintable(url.toString());
1231 if (!m_data.isEmpty()) {
1232 qWarning().nospace() << " "
1233 << qPrintable(QString::fromUtf8(m_data));
1234 }
1235 }
1236
1237 if (m_method == QLatin1String("GET")) {
1238 m_network = networkAccessManager()->get(request);
1239 } else if (m_method == QLatin1String("HEAD")) {
1240 m_network = networkAccessManager()->head(request);
1241 } else if (m_method == QLatin1String("POST")) {
1242 m_network = networkAccessManager()->post(request, m_data);
1243 } else if (m_method == QLatin1String("PUT")) {
1244 m_network = networkAccessManager()->put(request, m_data);
1245 } else if (m_method == QLatin1String("DELETE")) {
1246 m_network = networkAccessManager()->deleteResource(request);
1247 } else if ((m_method == QLatin1String("OPTIONS")) ||
1248 m_method == QLatin1String("PROPFIND") ||
1249 m_method == QLatin1String("PATCH")) {
1250 QBuffer *buffer = new QBuffer;
1251 buffer->setData(m_data);
1253 m_network = networkAccessManager()->sendCustomRequest(request, QByteArray(m_method.toUtf8().constData()), buffer);
1254 buffer->setParent(m_network);
1255 }
1256
1258 if (m_network->bytesAvailable() > 0)
1259 readyRead();
1260
1261 QNetworkReply::NetworkError networkError = m_network->error();
1262 if (networkError != QNetworkReply::NoError) {
1263 error(networkError);
1264 } else {
1265 finished();
1266 }
1267 } else {
1268 QObject::connect(m_network, SIGNAL(readyRead()),
1269 this, SLOT(readyRead()));
1270 QObject::connect(m_network, SIGNAL(errorOccurred(QNetworkReply::NetworkError)),
1272 QObject::connect(m_network, SIGNAL(finished()),
1273 this, SLOT(finished()));
1274 }
1275}
1276
1278 Object *thisObject, const QQmlRefPointer<QQmlContextData> &context, const QByteArray &data)
1279{
1280 m_errorFlag = false;
1281 m_sendFlag = true;
1282 m_redirectCount = 0;
1283 m_data = data;
1284
1285 m_thisObject = thisObject;
1286 m_qmlContext = context;
1287
1288 requestFromUrl(m_url);
1289
1290 return Encode::undefined();
1291}
1292
1294{
1295 destroyNetwork();
1296 m_responseEntityBody = QByteArray();
1297 m_errorFlag = true;
1298 m_request = QNetworkRequest();
1299
1300 if (!(m_state == Unsent ||
1301 (m_state == Opened && !m_sendFlag) ||
1302 m_state == Done)) {
1303
1304 m_state = Done;
1305 m_sendFlag = false;
1306 dispatchCallbackNow(thisObject);
1307 }
1308
1309 m_state = Unsent;
1310
1311 return Encode::undefined();
1312}
1313
1314void QQmlXMLHttpRequest::readyRead()
1315{
1316 m_status =
1318 m_statusText =
1320
1321 // ### We assume if this is called the headers are now available
1322 if (m_state < HeadersReceived) {
1323 m_state = HeadersReceived;
1324 fillHeadersList();
1325 dispatchCallbackSafely();
1326 }
1327
1328 bool wasEmpty = m_responseEntityBody.isEmpty();
1329 m_responseEntityBody.append(m_network->readAll());
1330 if (wasEmpty && !m_responseEntityBody.isEmpty())
1331 m_state = Loading;
1332
1333 dispatchCallbackSafely();
1334}
1335
1337{
1338 int idx = QNetworkReply::staticMetaObject.indexOfEnumerator("NetworkError");
1339 if (idx == -1) return "EnumLookupFailed";
1340
1341 QMetaEnum e = QNetworkReply::staticMetaObject.enumerator(idx);
1342
1343 const char *name = e.valueToKey(error);
1344 if (!name) return "EnumLookupFailed";
1345 else return name;
1346}
1347
1348void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
1349{
1350 m_status =
1352 m_statusText =
1354
1355 m_request = QNetworkRequest();
1356 m_data.clear();
1357 destroyNetwork();
1358
1359 if (xhrDump()) {
1360 qWarning().nospace() << "XMLHttpRequest: ERROR " << qPrintable(m_url.toString());
1361 qWarning().nospace() << " " << error << ' ' << errorToString(error) << ' ' << m_statusText;
1362 }
1363
1375 m_state = Loading;
1376 dispatchCallbackSafely();
1377 } else {
1378 m_errorFlag = true;
1379 m_responseEntityBody = QByteArray();
1380 }
1381
1382 m_state = Done;
1383 dispatchCallbackSafely();
1384}
1385
1386#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
1387void QQmlXMLHttpRequest::finished()
1388{
1389 m_redirectCount++;
1390 if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
1392 if (redirect.isValid()) {
1393 QUrl url = m_network->url().resolved(redirect.toUrl());
1394 if (!QQmlFile::isLocalFile(url)) {
1395 // See http://www.ietf.org/rfc/rfc2616.txt, section 10.3.4 "303 See Other":
1396 // Result of 303 redirection should be a new "GET" request.
1398 if (code.isValid() && code.toInt() == 303 && m_method != QLatin1String("GET"))
1399 m_method = QStringLiteral("GET");
1400 destroyNetwork();
1401
1402 // Discard redirect response body
1403 m_responseEntityBody = QByteArray();
1404
1405 requestFromUrl(url);
1406 return;
1407 }
1408 }
1409 }
1410
1411 m_status =
1413 m_statusText =
1415
1416 if (m_state < HeadersReceived) {
1417 m_state = HeadersReceived;
1418 fillHeadersList ();
1419 dispatchCallbackSafely();
1420 }
1421 m_responseEntityBody.append(m_network->readAll());
1422 readEncoding();
1423
1424 if (xhrDump()) {
1425 qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
1426 if (!m_responseEntityBody.isEmpty()) {
1427 qWarning().nospace() << " "
1428 << qPrintable(QString::fromUtf8(m_responseEntityBody));
1429 }
1430 }
1431
1432 m_data.clear();
1433 destroyNetwork();
1434 if (m_state < Loading) {
1435 m_state = Loading;
1436 dispatchCallbackSafely();
1437 }
1438 m_state = Done;
1439
1440 dispatchCallbackSafely();
1441
1442 m_thisObject.clear();
1443 m_qmlContext.reset();
1444}
1445
1446
1447void QQmlXMLHttpRequest::readEncoding()
1448{
1449 for (const HeaderPair &header : std::as_const(m_headersList)) {
1450 if (header.first == "content-type") {
1451 int separatorIdx = header.second.indexOf(';');
1452 if (separatorIdx == -1) {
1453 m_mime = header.second;
1454 } else {
1455 m_mime = header.second.mid(0, separatorIdx);
1456 int charsetIdx = header.second.indexOf("charset=");
1457 if (charsetIdx != -1) {
1458 charsetIdx += 8;
1459 separatorIdx = header.second.indexOf(';', charsetIdx);
1460 m_charset = header.second.mid(charsetIdx, separatorIdx >= 0 ? separatorIdx : header.second.size());
1461 }
1462 }
1463 break;
1464 }
1465 }
1466
1467 const auto mime = mimeType();
1468 if (mime.isEmpty() || mime == "text/xml" || mime == "application/xml" || mime.endsWith("+xml"))
1469 m_gotXml = true;
1470}
1471
1473{
1474 return m_gotXml;
1475}
1476
1478{
1479 return m_url;
1480}
1481
1483{
1484 // Final MIME type is the override MIME type unless that is null in which
1485 // case it is the response MIME type.
1486 return m_overrideMime.isEmpty() ? m_mime : m_overrideMime;
1487}
1488
1490{
1491 // Final charset is the override charset unless that is null in which case
1492 // it is the response charset.
1493 return m_overrideCharset.isEmpty() ? m_charset : m_overrideCharset;
1494}
1495
1497{
1498 return m_responseType;
1499}
1500
1502{
1503 m_responseType = responseType;
1504}
1505
1507{
1508 if (m_parsedDocument.isEmpty()) {
1509 Scope scope(engine);
1510
1512 const QString& jtext = responseBody();
1513 JsonParser parser(scope.engine, jtext.constData(), jtext.size());
1514 ScopedValue jsonObject(scope, parser.parse(&error));
1515 if (error.error != QJsonParseError::NoError)
1516 return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
1517
1518 m_parsedDocument.set(scope.engine, jsonObject);
1519 }
1520
1521 return m_parsedDocument.value();
1522}
1523
1525{
1526 if (m_parsedDocument.isEmpty()) {
1527 m_parsedDocument.set(engine, Document::load(engine, rawResponseBody()));
1528 }
1529
1530 return m_parsedDocument.value();
1531}
1532
1533QStringDecoder QQmlXMLHttpRequest::findTextDecoder() const
1534{
1535 QStringDecoder decoder;
1536
1537 if (!charset().isEmpty())
1538 decoder = QStringDecoder(charset());
1539
1540 if (!decoder.isValid() && m_gotXml) {
1541 QXmlStreamReader reader(m_responseEntityBody);
1542 reader.readNext();
1543 decoder = QStringDecoder(reader.documentEncoding().toString().toUtf8());
1544 }
1545
1546 if (!decoder.isValid() && mimeType() == "text/html")
1547 decoder = QStringDecoder::decoderForHtml(m_responseEntityBody);
1548
1549 if (!decoder.isValid()) {
1550 auto encoding = QStringConverter::encodingForData(m_responseEntityBody);
1551 if (encoding)
1552 decoder = QStringDecoder(*encoding);
1553 }
1554
1555 if (!decoder.isValid())
1557
1558 return decoder;
1559}
1560
1562{
1563 QStringDecoder toUtf16 = findTextDecoder();
1564 return toUtf16(m_responseEntityBody);
1565}
1566
1568{
1569 return m_responseEntityBody;
1570}
1571
1572void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj)
1573{
1574 dispatchCallbackNow(thisObj, m_state == Done, m_errorFlag);
1575}
1576
1577void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj, bool done, bool error)
1578{
1579 Q_ASSERT(thisObj);
1580
1581 const auto dispatch = [thisObj](const QString &eventName) {
1582 QV4::Scope scope(thisObj->engine());
1583 ScopedString s(scope, scope.engine->newString(eventName));
1584 ScopedFunctionObject callback(scope, thisObj->get(s));
1585 // not an error, but no event handler to call.
1586 if (!callback)
1587 return;
1588
1589 QV4::JSCallArguments jsCallData(scope);
1590 callback->call(jsCallData);
1591
1592 if (scope.hasException()) {
1593 QQmlError error = scope.engine->catchExceptionAsQmlError();
1594 QQmlEnginePrivate *qmlEnginePrivate = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr;
1595 QQmlEnginePrivate::warning(qmlEnginePrivate, error);
1596 }
1597 };
1598
1599 dispatch(QStringLiteral("onreadystatechange"));
1600 if (done) {
1601 if (error)
1602 dispatch(QStringLiteral("onerror"));
1603 else
1604 dispatch(QStringLiteral("onload"));
1605 dispatch(QStringLiteral("onloadend"));
1606 }
1607}
1608
1609void QQmlXMLHttpRequest::dispatchCallbackSafely()
1610{
1611 if (m_wasConstructedWithQmlContext && m_qmlContext.isNull()) {
1612 // if the calling context object is no longer valid, then it has been
1613 // deleted explicitly (e.g., by a Loader deleting the itemContext when
1614 // the source is changed). We do nothing in this case, as the evaluation
1615 // cannot succeed.
1616 return;
1617 }
1618
1619 dispatchCallbackNow(m_thisObject.as<Object>());
1620}
1621
1622void QQmlXMLHttpRequest::destroyNetwork()
1623{
1624 if (m_network) {
1625 m_network->disconnect();
1626 m_network->deleteLater();
1627 m_network = nullptr;
1628 }
1629}
1630
1631namespace QV4 {
1632namespace Heap {
1633
1636 Object::init();
1637 this->request = request;
1638 }
1639
1640 void destroy() {
1641 delete request;
1642 Object::destroy();
1643 }
1645};
1646
1647#define QQmlXMLHttpRequestCtorMembers(class, Member) \
1648 Member(class, Pointer, Object *, proto)
1649
1654
1655}
1656
1662
1663// https://xhr.spec.whatwg.org/
1665{
1667
1669 {
1670 Scope scope(f->engine());
1671 const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
1672
1673 QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->networkAccessManager(scope.engine), scope.engine);
1674 Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
1675 ScopedObject proto(scope, ctor->d()->proto);
1676 w->setPrototypeUnchecked(proto);
1677 return w.asReturnedValue();
1678 }
1679
1680 static ReturnedValue virtualCall(const FunctionObject *, const Value *, const Value *, int) {
1681 return Encode::undefined();
1682 }
1683
1684 void setupProto();
1685
1686 static ReturnedValue method_open(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1687 static ReturnedValue method_setRequestHeader(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1688 static ReturnedValue method_send(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1689 static ReturnedValue method_abort(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1690 static ReturnedValue method_getResponseHeader(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1691 static ReturnedValue method_getAllResponseHeaders(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1692 static ReturnedValue method_overrideMimeType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1693
1694 static ReturnedValue method_get_readyState(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1695 static ReturnedValue method_get_status(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1696 static ReturnedValue method_get_statusText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1697 static ReturnedValue method_get_responseText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1698 static ReturnedValue method_get_responseXML(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1699 static ReturnedValue method_get_response(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1700 static ReturnedValue method_get_responseType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1701 static ReturnedValue method_set_responseType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1702 static ReturnedValue method_get_responseURL(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1703};
1704
1705}
1706
1708
1709void Heap::QQmlXMLHttpRequestCtor::init(ExecutionEngine *engine)
1710{
1711 Heap::FunctionObject::init(engine, QStringLiteral("XMLHttpRequest"));
1712 Scope scope(engine);
1713 Scoped<QV4::QQmlXMLHttpRequestCtor> ctor(scope, this);
1714
1715 ctor->defineReadonlyProperty(QStringLiteral("UNSENT"), Value::fromInt32(QQmlXMLHttpRequest::Unsent));
1716 ctor->defineReadonlyProperty(QStringLiteral("OPENED"), Value::fromInt32(QQmlXMLHttpRequest::Opened));
1717 ctor->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Value::fromInt32(QQmlXMLHttpRequest::HeadersReceived));
1718 ctor->defineReadonlyProperty(QStringLiteral("LOADING"), Value::fromInt32(QQmlXMLHttpRequest::Loading));
1719 ctor->defineReadonlyProperty(QStringLiteral("DONE"), Value::fromInt32(QQmlXMLHttpRequest::Done));
1720
1721 if (!ctor->d()->proto)
1722 ctor->setupProto();
1723 ScopedString s(scope, engine->id_prototype());
1724 ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
1725}
1726
1728
1730{
1731 ExecutionEngine *v4 = engine();
1732 Scope scope(v4);
1733 ScopedObject p(scope, v4->newObject());
1734 d()->proto.set(scope.engine, p->d());
1735
1736 // Methods
1737 p->defineDefaultProperty(QStringLiteral("open"), method_open);
1738 p->defineDefaultProperty(QStringLiteral("setRequestHeader"), method_setRequestHeader);
1739 p->defineDefaultProperty(QStringLiteral("send"), method_send);
1740 p->defineDefaultProperty(QStringLiteral("abort"), method_abort);
1741 p->defineDefaultProperty(QStringLiteral("getResponseHeader"), method_getResponseHeader);
1742 p->defineDefaultProperty(QStringLiteral("getAllResponseHeaders"), method_getAllResponseHeaders);
1743 p->defineDefaultProperty(QStringLiteral("overrideMimeType"), method_overrideMimeType);
1744
1745 // Read-only properties
1746 p->defineAccessorProperty(QStringLiteral("readyState"), method_get_readyState, nullptr);
1747 p->defineAccessorProperty(QStringLiteral("status"),method_get_status, nullptr);
1748 p->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, nullptr);
1749 p->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, nullptr);
1750 p->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, nullptr);
1751 p->defineAccessorProperty(QStringLiteral("response"),method_get_response, nullptr);
1752 p->defineAccessorProperty(QStringLiteral("responseURL"),method_get_responseURL, nullptr);
1753
1754 // Read-write properties
1755 p->defineAccessorProperty(QStringLiteral("responseType"), method_get_responseType, method_set_responseType);
1756
1757 // State values
1758 p->defineReadonlyProperty(QStringLiteral("UNSENT"), Value::fromInt32(0));
1759 p->defineReadonlyProperty(QStringLiteral("OPENED"), Value::fromInt32(1));
1760 p->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Value::fromInt32(2));
1761 p->defineReadonlyProperty(QStringLiteral("LOADING"), Value::fromInt32(3));
1762 p->defineReadonlyProperty(QStringLiteral("DONE"), Value::fromInt32(4));
1763}
1764
1765
1766// XMLHttpRequest methods
1767ReturnedValue QQmlXMLHttpRequestCtor::method_open(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1768{
1769 Scope scope(b);
1770 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1771 if (!w)
1772 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1773 QQmlXMLHttpRequest *r = w->d()->request;
1774
1775 if (argc < 2 || argc > 5)
1776 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1777
1778 // Argument 0 - Method
1779 QString method = argv[0].toQStringNoThrow().toUpper();
1780 if (method != QLatin1String("GET") &&
1781 method != QLatin1String("PUT") &&
1782 method != QLatin1String("HEAD") &&
1783 method != QLatin1String("POST") &&
1784 method != QLatin1String("DELETE") &&
1785 method != QLatin1String("OPTIONS") &&
1786 method != QLatin1String("PROPFIND") &&
1787 method != QLatin1String("PATCH"))
1788 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
1789
1790 // Argument 1 - URL
1791 QUrl url = QUrl(argv[1].toQStringNoThrow());
1792
1793 if (url.isRelative()) {
1794 if (QQmlRefPointer<QQmlContextData> qmlContextData = scope.engine->callingQmlContext())
1795 url = qmlContextData->resolvedUrl(url);
1796 else
1797 url = scope.engine->resolvedUrl(url.url());
1798 }
1799
1800 bool async = true;
1801 // Argument 2 - async (optional)
1802 if (argc > 2) {
1803 async = argv[2].booleanValue();
1804 }
1805
1806 // Argument 3/4 - user/pass (optional)
1807 QString username, password;
1808 if (argc > 3)
1809 username = argv[3].toQStringNoThrow();
1810 if (argc > 4)
1811 password = argv[4].toQStringNoThrow();
1812
1813 // Clear the fragment (if any)
1815
1816 // Set username/password
1817 if (!username.isNull()) url.setUserName(username);
1818 if (!password.isNull()) url.setPassword(password);
1819
1821}
1822
1824{
1825 Scope scope(b);
1826 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1827 if (!w)
1828 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1829 QQmlXMLHttpRequest *r = w->d()->request;
1830
1831 if (argc != 2)
1832 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1833
1834 if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag())
1835 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1836
1837 QString name = argv[0].toQStringNoThrow();
1838 QString value = argv[1].toQStringNoThrow();
1839
1840 // ### Check that name and value are well formed
1841
1842 QString nameUpper = name.toUpper();
1843 if (nameUpper == QLatin1String("ACCEPT-CHARSET") ||
1844 nameUpper == QLatin1String("ACCEPT-ENCODING") ||
1845 nameUpper == QLatin1String("CONNECTION") ||
1846 nameUpper == QLatin1String("CONTENT-LENGTH") ||
1847 nameUpper == QLatin1String("COOKIE") ||
1848 nameUpper == QLatin1String("COOKIE2") ||
1849 nameUpper == QLatin1String("CONTENT-TRANSFER-ENCODING") ||
1850 nameUpper == QLatin1String("DATE") ||
1851 nameUpper == QLatin1String("EXPECT") ||
1852 nameUpper == QLatin1String("HOST") ||
1853 nameUpper == QLatin1String("KEEP-ALIVE") ||
1854 nameUpper == QLatin1String("REFERER") ||
1855 nameUpper == QLatin1String("TE") ||
1856 nameUpper == QLatin1String("TRAILER") ||
1857 nameUpper == QLatin1String("TRANSFER-ENCODING") ||
1858 nameUpper == QLatin1String("UPGRADE") ||
1859 nameUpper == QLatin1String("VIA") ||
1860 nameUpper.startsWith(QLatin1String("PROXY-")) ||
1861 nameUpper.startsWith(QLatin1String("SEC-")))
1863
1864 r->addHeader(name, value);
1865
1867}
1868
1869ReturnedValue QQmlXMLHttpRequestCtor::method_send(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1870{
1871 Scope scope(b);
1872 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1873 if (!w)
1874 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1875 QQmlXMLHttpRequest *r = w->d()->request;
1876
1877 if (r->readyState() != QQmlXMLHttpRequest::Opened ||
1878 r->sendFlag())
1879 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1880
1882 if (argc > 0) {
1883 if (const ArrayBuffer *buffer = argv[0].as<ArrayBuffer>()) {
1884 data = buffer->asByteArray();
1885 } else {
1886 data = argv[0].toQStringNoThrow().toUtf8();
1887 }
1888 }
1889
1890 return r->send(w, scope.engine->callingQmlContext(), data);
1891}
1892
1894{
1895 Scope scope(b);
1896 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1897 if (!w)
1898 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1899 QQmlXMLHttpRequest *r = w->d()->request;
1900
1901 return r->abort(w);
1902}
1903
1905{
1906 Scope scope(b);
1907 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1908 if (!w)
1909 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1910 QQmlXMLHttpRequest *r = w->d()->request;
1911
1912 if (argc != 1)
1913 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1914
1915 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1916 r->readyState() != QQmlXMLHttpRequest::Done &&
1917 r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
1918 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1919
1920 return Encode(scope.engine->newString(r->header(argv[0].toQStringNoThrow())));
1921}
1922
1924{
1925 Scope scope(b);
1926 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1927 if (!w)
1928 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1929 QQmlXMLHttpRequest *r = w->d()->request;
1930
1931 if (argc != 0)
1932 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1933
1934 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1935 r->readyState() != QQmlXMLHttpRequest::Done &&
1936 r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
1937 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1938
1939 return Encode(scope.engine->newString(r->headers()));
1940}
1941
1942// XMLHttpRequest properties
1944{
1945 Scope scope(b);
1946 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1947 if (!w)
1948 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1949 QQmlXMLHttpRequest *r = w->d()->request;
1950
1951 return Encode(r->readyState());
1952}
1953
1955{
1956 Scope scope(b);
1957 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1958 if (!w)
1959 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1960 QQmlXMLHttpRequest *r = w->d()->request;
1961
1962 if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
1963 r->readyState() == QQmlXMLHttpRequest::Opened)
1964 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1965
1966 if (r->errorFlag())
1967 return Encode(0);
1968 else
1969 return Encode(r->replyStatus());
1970}
1971
1973{
1974 Scope scope(b);
1975 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1976 if (!w)
1977 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1978 QQmlXMLHttpRequest *r = w->d()->request;
1979
1980 if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
1981 r->readyState() == QQmlXMLHttpRequest::Opened)
1982 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1983
1984 if (r->errorFlag())
1985 return Encode(scope.engine->newString(QString()));
1986 else
1987 return Encode(scope.engine->newString(r->replyStatusText()));
1988}
1989
1991{
1992 Scope scope(b);
1993 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
1994 if (!w)
1995 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1996 QQmlXMLHttpRequest *r = w->d()->request;
1997
1998 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1999 r->readyState() != QQmlXMLHttpRequest::Done)
2000 return Encode(scope.engine->newString(QString()));
2001 else
2002 return Encode(scope.engine->newString(r->responseBody()));
2003}
2004
2006{
2007 Scope scope(b);
2008 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2009 if (!w)
2010 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2011 QQmlXMLHttpRequest *r = w->d()->request;
2012
2013 if (!r->receivedXml() ||
2014 (r->readyState() != QQmlXMLHttpRequest::Loading &&
2015 r->readyState() != QQmlXMLHttpRequest::Done)) {
2016 return Encode::null();
2017 } else {
2018 if (r->responseType().isEmpty())
2019 r->setResponseType(QLatin1String("document"));
2020 return r->xmlResponseBody(scope.engine);
2021 }
2022}
2023
2025{
2026 Scope scope(b);
2027 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2028 if (!w)
2029 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2030 QQmlXMLHttpRequest *r = w->d()->request;
2031
2032 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2033 r->readyState() != QQmlXMLHttpRequest::Done)
2035
2036 const QString& responseType = r->responseType();
2037 if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0 || responseType.isEmpty()) {
2038 RETURN_RESULT(scope.engine->newString(r->responseBody()));
2039 } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
2040 RETURN_RESULT(scope.engine->newArrayBuffer(r->rawResponseBody()));
2041 } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) {
2042 RETURN_RESULT(r->jsonResponseBody(scope.engine));
2043 } else if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) {
2044 RETURN_RESULT(r->xmlResponseBody(scope.engine));
2045 } else {
2047 }
2048}
2049
2050
2052{
2053 Scope scope(b);
2054 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2055 if (!w)
2056 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2057 QQmlXMLHttpRequest *r = w->d()->request;
2058 return Encode(scope.engine->newString(r->responseType()));
2059}
2060
2062{
2063 Scope scope(b);
2064 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2065 if (!w)
2066 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2067 QQmlXMLHttpRequest *r = w->d()->request;
2068
2069 if (argc < 1)
2070 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
2071
2072 // Argument 0 - response type
2073 r->setResponseType(argv[0].toQStringNoThrow());
2074
2075 return Encode::undefined();
2076}
2077
2079{
2080 Scope scope(b);
2081 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2082 if (!w)
2083 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2084 QQmlXMLHttpRequest *r = w->d()->request;
2085
2086 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2087 r->readyState() != QQmlXMLHttpRequest::Done) {
2088 return Encode(scope.engine->newString(QString()));
2089 } else {
2090 QUrl url = r->url();
2092 return Encode(scope.engine->newString(url.toString()));
2093 }
2094}
2095
2097{
2098 Scope scope(b);
2099 Scoped<QQmlXMLHttpRequestWrapper> w(scope, thisObject->as<QQmlXMLHttpRequestWrapper>());
2100 if (!w)
2101 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2102 QQmlXMLHttpRequest *r = w->d()->request;
2103
2104 if (argc != 1)
2105 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
2106
2107 // If state is loading or done, throw an InvalidStateError exception.
2108 if (r->readyState() == QQmlXMLHttpRequest::Loading ||
2109 r->readyState() == QQmlXMLHttpRequest::Done)
2110 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
2111
2112 // Set override MIME type to `application/octet-stream`.
2113 r->setOverrideMimeType(QStringLiteral("application/octet-stream"));
2114 const auto parts = argv[0].toQStringNoThrow().split(QLatin1Char(';'));
2115 const auto type = parts.at(0).trimmed();
2116
2117 const auto mimeInvalidCharacter = [](QChar uni) {
2118 if (uni.unicode() > 127) // Only accept ASCII
2119 return true;
2120 const char ch = char(uni.unicode());
2121 return !(ch == '-' || ch == '/' || isAsciiLetterOrNumber(ch));
2122 };
2123
2124 // If mime is a parsable MIME type, ...
2125 if (type.count(QLatin1Char('/')) == 1
2126 && std::find_if(type.begin(), type.end(), mimeInvalidCharacter) == type.end()) {
2127 // ... then set override MIME type to its MIME type portion.
2128 r->setOverrideMimeType(type);
2129 }
2130 for (const auto &part : parts) {
2131 const QLatin1String charset("charset=");
2132 // If override MIME type has a `charset` parameter, ...
2133 if (part.trimmed().startsWith(charset)) {
2134 // ... then set override charset to its value.
2135 const int offset(part.indexOf(charset) + charset.size());
2136 r->setOverrideCharset(part.sliced(offset).trimmed());
2137 }
2138 }
2139
2140 return Encode::undefined();
2141}
2142
2143void qt_rem_qmlxmlhttprequest(ExecutionEngine * /* engine */, void *d)
2144{
2146 delete data;
2147}
2148
2150{
2151 Scope scope(v4);
2152
2153 Scoped<QQmlXMLHttpRequestCtor> ctor(scope, v4->memoryManager->allocate<QQmlXMLHttpRequestCtor>(v4));
2154 ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
2156
2158 return data;
2159}
2160
2162
2163#include <qqmlxmlhttprequest.moc>
NSData * m_data
Definition main.cpp:8
\inmodule QtCore \reentrant
Definition qbuffer.h:16
void setData(const QByteArray &data)
Sets the contents of the internal buffer to be data.
Definition qbuffer.cpp:259
\inmodule QtCore
Definition qbytearray.h:57
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:107
void clear()
Clears the contents of the byte array and makes it null.
QByteArray toLower() const &
Definition qbytearray.h:254
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore
QByteArray readAll()
Reads all remaining data from the device, and returns it as a byte array.
virtual qint64 bytesAvailable() const
Returns the number of bytes that are available for reading.
QString text(const QString &key) const
QJSValue newObject()
Creates a JavaScript object of class Object.
constexpr qsizetype size() const noexcept
bool startsWith(QStringView s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
bool isEmpty() const noexcept
Definition qlist.h:401
void clear()
Definition qlist.h:434
\inmodule QtCore
const char * valueToKey(int value) const
Returns the string that is used as the name of the given enumeration value, or \nullptr if value is n...
The QNetworkAccessManager class allows the application to send network requests and receive replies.
QNetworkReply * put(const QNetworkRequest &request, QIODevice *data)
Uploads the contents of data to the destination request and returns a new QNetworkReply object that w...
QNetworkReply * head(const QNetworkRequest &request)
Posts a request to obtain the network headers for request and returns a new QNetworkReply object whic...
QNetworkReply * post(const QNetworkRequest &request, QIODevice *data)
Sends an HTTP POST request to the destination specified by request and returns a new QNetworkReply ob...
QNetworkReply * get(const QNetworkRequest &request)
Posts a request to obtain the contents of the target request and returns a new QNetworkReply object o...
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data=nullptr)
QNetworkReply * deleteResource(const QNetworkRequest &request)
QByteArray rawHeader(QAnyStringView headerName) const
Returns the raw contents of the header headerName as sent by the remote server.
QVariant attribute(QNetworkRequest::Attribute code) const
Returns the attribute associated with the code code.
NetworkError error() const
Returns the error that was found during the processing of this request.
NetworkError
Indicates all possible error conditions found during the processing of the request.
@ ContentOperationNotPermittedError
@ OperationNotImplementedError
@ ProtocolInvalidOperationError
@ AuthenticationRequiredError
QList< QByteArray > rawHeaderList() const
Returns a list of headers fields that were sent by the remote server, in the order that they were sen...
QUrl url() const
Returns the URL of the content downloaded or uploaded.
The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
void setHeader(KnownHeaders header, const QVariant &value)
Sets the value of the known header header to be value, overriding any previously set headers.
void setAttribute(Attribute code, const QVariant &value)
Sets the attribute associated with code code to be value value.
QVariant attribute(Attribute code, const QVariant &defaultValue=QVariant()) const
Returns the attribute associated with the code code.
QVariant header(KnownHeaders header) const
Returns the value of the known network header header if it is present in this request.
void setRawHeader(const QByteArray &headerName, const QByteArray &value)
Sets the header headerName to be of value headerValue.
QByteArray rawHeader(QAnyStringView headerName) const
Returns the raw form of header headerName.
void setUrl(const QUrl &url)
Sets the URL this network request is referring to be url.
\inmodule QtCore
Definition qobject.h:103
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2195
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void deleteLater()
\threadsafe
Definition qobject.cpp:2435
void warning(const QQmlError &)
static QQmlEnginePrivate * get(QQmlEngine *e)
The QQmlError class encapsulates a QML error.
Definition qqmlerror.h:18
static bool isLocalFile(const QString &url)
Returns true if url is a local file that can be opened with \l{QFile}.
Definition qqmlfile.cpp:644
void addref() const
void reset(T *t=nullptr)
bool isNull() const
void setOverrideCharset(QStringView charset)
void setResponseType(const QString &)
void setOverrideMimeType(QStringView mimeType)
ReturnedValue abort(Object *thisObject)
QQmlXMLHttpRequest(QNetworkAccessManager *manager, QV4::ExecutionEngine *v4)
QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine *)
const QByteArray charset() const
const QByteArray & rawResponseBody() const
void addHeader(const QString &, const QString &)
QString header(const QString &name) const
QString replyStatusText() const
const QString & responseType() const
const QByteArray mimeType() const
QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine *)
ReturnedValue send(Object *thisObject, const QQmlRefPointer< QQmlContextData > &context, const QByteArray &)
ReturnedValue open(Object *thisObject, const QString &, const QUrl &, LoadType)
bool isValid() const noexcept
Returns true if this is a valid string converter that can be used for encoding or decoding text.
static Q_CORE_EXPORT std::optional< Encoding > encodingForData(QByteArrayView data, char16_t expectedFirstCharacter=0) noexcept
Returns the encoding for the content of data if it can be determined.
\inmodule QtCore
static Q_CORE_EXPORT QStringDecoder decoderForHtml(QByteArrayView data)
Tries to determine the encoding of the HTML in data by looking at leading byte order marks or a chars...
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
constexpr bool isEmpty() const noexcept
Returns whether this string view is empty - that is, whether {size() == 0}.
QByteArray toUtf8() const
Returns a UTF-8 representation of the string view as a QByteArray.
QStringView trimmed() const noexcept
Strips leading and trailing whitespace and returns the result.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
qsizetype indexOf(QLatin1StringView s, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4517
int toInt(bool *ok=nullptr, int base=10) const
Returns the string converted to an int using base base, which is 10 by default and must be between 2 ...
Definition qstring.h:731
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3824
QStringList split(const QString &sep, Qt::SplitBehavior behavior=Qt::KeepEmptyParts, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Splits the string into substrings wherever sep occurs, and returns the list of those strings.
Definition qstring.cpp:8218
QString mid(qsizetype position, qsizetype n=-1) const &
Definition qstring.cpp:5300
bool isEmpty() const noexcept
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:192
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:994
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
QString first(qsizetype n) const &
Definition qstring.h:390
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6664
QString toLower() const &
Definition qstring.h:435
QString & append(QChar c)
Definition qstring.cpp:3252
QByteArray toUtf8() const &
Definition qstring.h:634
QString toUpper() const &
Definition qstring.h:439
\inmodule QtCore
Definition qurl.h:94
QString url(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2817
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition qurl.cpp:2725
void setPassword(const QString &password, ParsingMode mode=DecodedMode)
Sets the URL's password to password.
Definition qurl.cpp:2227
void setUserName(const QString &userName, ParsingMode mode=DecodedMode)
Sets the URL's user name to userName.
Definition qurl.cpp:2164
void setFragment(const QString &fragment, ParsingMode mode=TolerantMode)
Sets the fragment of the URL to fragment.
Definition qurl.cpp:2648
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
Definition qurl.cpp:2800
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2831
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)
ReturnedValue parse(QJsonParseError *error)
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:298
static V4_NEEDS_DESTROY ReturnedValue create(ExecutionEngine *, NodeImpl *, const QList< NodeImpl * > &)
QList< NodeImpl * > attributes
DocumentImpl * document
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 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)
ReturnedValue value() const
void set(ExecutionEngine *engine, const Value &value)
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)
\inmodule QtCore
Definition qvariant.h:65
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:714
int toInt(bool *ok=nullptr) const
Returns the variant as an int if the variant has userType() \l QMetaType::Int, \l QMetaType::Bool,...
QString toString() const
Returns the variant as a QString if the variant has a userType() including, but not limited to:
bool toBool() const
Returns the variant as a bool if the variant has userType() Bool.
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has userType() \l QMetaType::QByteArray or \l QMet...
QUrl toUrl() const
Returns the variant as a QUrl if the variant has userType() \l QMetaType::QUrl; otherwise returns an ...
QString str
[2]
p1 load("image.bmp")
qDeleteAll(list.begin(), list.end())
Combined button and popup list for selecting options.
Scoped< FunctionObject > ScopedFunctionObject
quint64 ReturnedValue
Scoped< Object > ScopedObject
Scoped< String > ScopedString
@ CaseInsensitive
static void * context
DBusConnection const char DBusError * error
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
static QString header(const QString &name)
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const char * mimeType
#define qWarning
Definition qlogging.h:166
return ret
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLboolean GLboolean GLboolean b
const GLfloat * m
GLfloat GLfloat GLfloat w
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLboolean r
[2]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLenum GLuint buffer
GLenum type
GLenum GLuint GLintptr offset
GLuint name
GLfloat n
GLdouble s
[6]
Definition qopenglext.h:235
GLfloat GLfloat p
[1]
#define DEFINE_BOOL_CONFIG_OPTION(name, var)
static const char * errorToString(QNetworkReply::NetworkError error)
static QQmlXMLHttpRequestData * xhrdata(ExecutionEngine *v4)
void * qt_add_qmlxmlhttprequest(ExecutionEngine *v4)
void qt_rem_qmlxmlhttprequest(ExecutionEngine *, void *d)
#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION
#define V4THROW_REFERENCE(string)
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define qPrintable(string)
Definition qstring.h:1531
QLatin1StringView QLatin1String
Definition qstringfwd.h:31
#define QStringLiteral(str)
static QT_BEGIN_NAMESPACE void init(QTextBoundaryFinder::BoundaryType type, QStringView str, QCharAttributes *attributes)
#define Q_OBJECT
#define slots
unsigned int quint32
Definition qtypes.h:50
unsigned int uint
Definition qtypes.h:34
#define DOMEXCEPTION_SYNTAX_ERR
#define THROW_DOM(error, string)
#define DOMEXCEPTION_INVALID_STATE_ERR
#define V4_NEEDS_DESTROY
#define DECLARE_HEAP_OBJECT(name, base)
#define DECLARE_MARKOBJECTS(class)
#define THROW_TYPE_ERROR()
#define RETURN_UNDEFINED()
#define RETURN_RESULT(r)
#define DEFINE_OBJECT_VTABLE(classname)
#define V4_OBJECT2(DataClass, superClass)
QList< int > list
[14]
file open(QIODevice::ReadOnly)
QUrl url("example.com")
[constructor-url-reference]
application x qt windows mime
[2]
QObject::connect nullptr
QNetworkAccessManager manager
QNetworkRequest request(url)
view create()
QJSEngine engine
[0]
\inmodule QtCore\reentrant
\inmodule QtCore \reentrant
Definition qchar.h:18
PersistentValue characterDataPrototype
PersistentValue documentPrototype
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
MemoryManager * memoryManager
QQmlRefPointer< QQmlContextData > callingQmlContext() const
String * id_length() const
Heap::Object * newObject()
Heap::String * newString(char16_t c)
QUrl resolvedUrl(const QString &file)
void freezeObject(const QV4::Value &value)
Heap::ArrayBuffer * newArrayBuffer(const QByteArray &array)
QList< NodeImpl * > * listPtr
void init(NodeImpl *data, const QList< NodeImpl * > &list)
QList< NodeImpl * > & list()
void init(NodeImpl *data)
void init(NodeImpl *data)
void init(QQmlXMLHttpRequest *request)
Heap::InternalClass * internalClass() const
ExecutionEngine * engine() const
static V4_NEEDS_DESTROY ReturnedValue create(ExecutionEngine *v4, NodeImpl *)
bool hasProperty(PropertyKey id) const
void setPrototypeUnchecked(const Object *p)
void defineReadonlyProperty(const QString &name, const Value &value)
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 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)
ExecutionEngine * engine
QML_NEARLY_ALWAYS_INLINE ReturnedValue asReturnedValue() const
bool booleanValue() const
PropertyKey propertyKey() const
static constexpr VTable::CallAsConstructor virtualCallAsConstructor
static constexpr VTable::Get virtualGet
static constexpr Value fromInt32(int i)
Definition qv4value_p.h:187
const T * as() const
Definition qv4value_p.h:132
QString toQStringNoThrow() const
Definition qv4value.cpp:122
bool isSymbol() const
Definition qv4value_p.h:296
Definition moc.h:23