Qt 6.x
The Qt SDK
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#include <QtCore/qstringconverter.h>
23#include <QtCore/qxmlstream.h>
24#include <QtCore/qstack.h>
25#include <QtCore/qdebug.h>
26#include <QtCore/qbuffer.h>
27
28#include <private/qv4objectproto_p.h>
29#include <private/qv4scopedvalue_p.h>
30#include <private/qv4arraybuffer_p.h>
31#include <private/qv4jsonobject_p.h>
32
33using namespace QV4;
34
35#define V4THROW_REFERENCE(string) \
36 do { \
37 ScopedObject error(scope, scope.engine->newReferenceErrorObject(QStringLiteral(string))); \
38 return scope.engine->throwError(error); \
39 } while (false)
40
42
43DEFINE_BOOL_CONFIG_OPTION(xhrDump, QML_XHR_DUMP);
44DEFINE_BOOL_CONFIG_OPTION(xhrFileWrite, QML_XHR_ALLOW_FILE_WRITE);
45DEFINE_BOOL_CONFIG_OPTION(xhrFileRead, QML_XHR_ALLOW_FILE_READ);
46
50
52
60};
61
63{
64 return (QQmlXMLHttpRequestData *)v4->xmlHttpRequestData();
65}
66
68{
69}
70
72{
73}
74
75namespace QV4 {
76
77class DocumentImpl;
79{
80public:
82 virtual ~NodeImpl() {
85 }
86
87 // These numbers are copied from the Node IDL definition
88 enum Type {
89 Attr = 2,
90 CDATA = 4,
96 Entity = 6,
100 Text = 3
101 };
103
106
108
109 void addref();
110 void release();
111
114
117};
118
119class DocumentImpl final : public QQmlRefCounted<DocumentImpl>, public NodeImpl
120{
122public:
124 ~DocumentImpl() override {
125 delete root;
126 }
127
131
133
134 void addref() { Base1::addref(); }
136};
137
138namespace Heap {
139
141 void init(NodeImpl *data, const QList<NodeImpl *> &list);
142 void destroy() {
143 delete listPtr;
144 if (d)
145 d->release();
146 Object::destroy();
147 }
149 if (listPtr == nullptr)
151 return *listPtr;
152 }
153
154 QList<NodeImpl *> *listPtr; // Only used in NamedNodeMap
156};
157
158struct NodeList : Object {
159 void init(NodeImpl *data);
160 void destroy() {
161 if (d)
162 d->release();
163 Object::destroy();
164 }
166};
167
169 void init();
170};
171
172struct Node : Object {
173 void init(NodeImpl *data);
174 void destroy() {
175 if (d)
176 d->release();
177 Object::destroy();
178 }
180};
181
182}
183
184class NamedNodeMap : public Object
185{
186public:
189
190 // C++ API
192
193 // JS API
194 static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
195};
196
198{
199 Object::init();
200 d = data;
201 this->list() = list;
202 if (d)
203 d->addref();
204}
205
207
208class NodeList : public Object
209{
210public:
213
214 // JS API
215 static ReturnedValue virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty);
216
217 // C++ API
219
220};
221
223{
224 Object::init();
225 d = data;
226 if (d)
227 d->addref();
228}
229
231
232class NodePrototype : public Object
233{
234public:
236
237 static void initClass(ExecutionEngine *engine);
238
239 // JS API
240 static ReturnedValue method_get_nodeName(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
241 static ReturnedValue method_get_nodeValue(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
242 static ReturnedValue method_get_nodeType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
243 static ReturnedValue method_get_namespaceUri(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
244
245 static ReturnedValue method_get_parentNode(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
246 static ReturnedValue method_get_childNodes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
247 static ReturnedValue method_get_firstChild(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
248 static ReturnedValue method_get_lastChild(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
249 static ReturnedValue method_get_previousSibling(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
250 static ReturnedValue method_get_nextSibling(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
251 static ReturnedValue method_get_attributes(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
252
253 //static ReturnedValue ownerDocument(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
254 //static ReturnedValue namespaceURI(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
255 //static ReturnedValue prefix(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
256 //static ReturnedValue localName(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
257 //static ReturnedValue baseURI(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
258 //static ReturnedValue textContent(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
259
260 static ReturnedValue getProto(ExecutionEngine *v4);
261
262};
263
264void Heap::NodePrototype::init()
265{
266 Object::init();
267 Scope scope(internalClass->engine);
268 ScopedObject o(scope, this);
269
270 o->defineAccessorProperty(QStringLiteral("nodeName"), QV4::NodePrototype::method_get_nodeName, nullptr);
271 o->defineAccessorProperty(QStringLiteral("nodeValue"), QV4::NodePrototype::method_get_nodeValue, nullptr);
272 o->defineAccessorProperty(QStringLiteral("nodeType"), QV4::NodePrototype::method_get_nodeType, nullptr);
273 o->defineAccessorProperty(QStringLiteral("namespaceUri"), QV4::NodePrototype::method_get_namespaceUri, nullptr);
274
275 o->defineAccessorProperty(QStringLiteral("parentNode"), QV4::NodePrototype::method_get_parentNode, nullptr);
276 o->defineAccessorProperty(QStringLiteral("childNodes"), QV4::NodePrototype::method_get_childNodes, nullptr);
277 o->defineAccessorProperty(QStringLiteral("firstChild"), QV4::NodePrototype::method_get_firstChild, nullptr);
278 o->defineAccessorProperty(QStringLiteral("lastChild"), QV4::NodePrototype::method_get_lastChild, nullptr);
279 o->defineAccessorProperty(QStringLiteral("previousSibling"), QV4::NodePrototype::method_get_previousSibling, nullptr);
280 o->defineAccessorProperty(QStringLiteral("nextSibling"), QV4::NodePrototype::method_get_nextSibling, nullptr);
281 o->defineAccessorProperty(QStringLiteral("attributes"), QV4::NodePrototype::method_get_attributes, nullptr);
282}
283
284
286
287struct Node : public Object
288{
291
292 // C++ API
294
295 bool isNull() const;
296};
297
299{
300 Object::init();
301 d = data;
302 if (d)
303 d->addref();
304}
305
307
308class Element : public Node
309{
310public:
311 // C++ API
312 static ReturnedValue prototype(ExecutionEngine *);
313};
314
315class Attr : public Node
316{
317public:
318 // JS API
319 static ReturnedValue method_name(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
320// static void specified(CallContext *);
321 static ReturnedValue method_value(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
322 static ReturnedValue method_ownerElement(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
323// static void schemaTypeInfo(CallContext *);
324// static void isId(CallContext *c);
325
326 // C++ API
327 static ReturnedValue prototype(ExecutionEngine *);
328};
329
330class CharacterData : public Node
331{
332public:
333 // JS API
334 static ReturnedValue method_length(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
335
336 // C++ API
337 static ReturnedValue prototype(ExecutionEngine *v4);
338};
339
340class Text : public CharacterData
341{
342public:
343 // JS API
344 static ReturnedValue method_isElementContentWhitespace(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
345 static ReturnedValue method_wholeText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
346
347 // C++ API
348 static ReturnedValue prototype(ExecutionEngine *);
349};
350
351class CDATA : public Text
352{
353public:
354 // C++ API
355 static ReturnedValue prototype(ExecutionEngine *v4);
356};
357
358class Document : public Node
359{
360public:
361 // JS API
362 static ReturnedValue method_xmlVersion(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
363 static ReturnedValue method_xmlEncoding(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
364 static ReturnedValue method_xmlStandalone(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
365 static ReturnedValue method_documentElement(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
366
367 // C++ API
368 static ReturnedValue prototype(ExecutionEngine *);
370};
371
372}
373
375{
376 document->addref();
377}
378
380{
381 document->release();
382}
383
385{
386 Scope scope(b);
387 Scoped<Node> r(scope, thisObject->as<Node>());
388 if (!r)
390
392 switch (r->d()->d->type) {
394 name = QStringLiteral("#document");
395 break;
396 case NodeImpl::CDATA:
397 name = QStringLiteral("#cdata-section");
398 break;
399 case NodeImpl::Text:
400 name = QStringLiteral("#text");
401 break;
402 default:
403 name = r->d()->d->name;
404 break;
405 }
406 return Encode(scope.engine->newString(name));
407}
408
410{
411 QV4::Scope scope(b);
412 Scoped<Node> r(scope, thisObject->as<Node>());
413 if (!r)
415
416 if (r->d()->d->type == NodeImpl::Document ||
417 r->d()->d->type == NodeImpl::DocumentFragment ||
418 r->d()->d->type == NodeImpl::DocumentType ||
419 r->d()->d->type == NodeImpl::Element ||
420 r->d()->d->type == NodeImpl::Entity ||
421 r->d()->d->type == NodeImpl::EntityReference ||
422 r->d()->d->type == NodeImpl::Notation)
424
425 return Encode(scope.engine->newString(r->d()->d->data));
426}
427
429{
430 QV4::Scope scope(b);
431 Scoped<Node> r(scope, thisObject->as<Node>());
432 if (!r)
434
435 return Encode(r->d()->d->type);
436}
437
439{
440 QV4::Scope scope(b);
441 Scoped<Node> r(scope, thisObject->as<Node>());
442 if (!r)
444
445 return Encode(scope.engine->newString(r->d()->d->namespaceUri));
446}
447
449{
450 QV4::Scope scope(b);
451 Scoped<Node> r(scope, thisObject->as<Node>());
452 if (!r)
454
455 if (r->d()->d->parent)
456 return Node::create(scope.engine, r->d()->d->parent);
457 else
458 return Encode::null();
459}
460
462{
463 QV4::Scope scope(b);
464 Scoped<Node> r(scope, thisObject->as<Node>());
465 if (!r)
467
468 return NodeList::create(scope.engine, r->d()->d);
469}
470
472{
473 QV4::Scope scope(b);
474 Scoped<Node> r(scope, thisObject->as<Node>());
475 if (!r)
477
478 if (r->d()->d->children.isEmpty())
479 return Encode::null();
480 else
481 return Node::create(scope.engine, r->d()->d->children.constFirst());
482}
483
485{
486 QV4::Scope scope(b);
487 Scoped<Node> r(scope, thisObject->as<Node>());
488 if (!r)
490
491 if (r->d()->d->children.isEmpty())
492 return Encode::null();
493 else
494 return Node::create(scope.engine, r->d()->d->children.constLast());
495}
496
498{
499 QV4::Scope scope(b);
500 Scoped<Node> r(scope, thisObject->as<Node>());
501 if (!r)
503
504 if (!r->d()->d->parent)
506
507 for (int ii = 0; ii < r->d()->d->parent->children.size(); ++ii) {
508 if (r->d()->d->parent->children.at(ii) == r->d()->d) {
509 if (ii == 0)
510 return Encode::null();
511 else
512 return Node::create(scope.engine, r->d()->d->parent->children.at(ii - 1));
513 }
514 }
515
516 return Encode::null();
517}
518
520{
521 QV4::Scope scope(b);
522 Scoped<Node> r(scope, thisObject->as<Node>());
523 if (!r)
525
526 if (!r->d()->d->parent)
528
529 for (int ii = 0; ii < r->d()->d->parent->children.size(); ++ii) {
530 if (r->d()->d->parent->children.at(ii) == r->d()->d) {
531 if ((ii + 1) == r->d()->d->parent->children.size())
532 return Encode::null();
533 else
534 return Node::create(scope.engine, r->d()->d->parent->children.at(ii + 1));
535 }
536 }
537
538 return Encode::null();
539}
540
542{
543 QV4::Scope scope(b);
544 Scoped<Node> r(scope, thisObject->as<Node>());
545 if (!r)
547
548 if (r->d()->d->type != NodeImpl::Element)
549 return Encode::null();
550 else
551 return NamedNodeMap::create(scope.engine, r->d()->d, r->d()->d->attributes);
552}
553
555{
556 Scope scope(v4);
558 if (d->nodePrototype.isUndefined()) {
560 d->nodePrototype.set(v4, p);
561 v4->freezeObject(p);
562 }
563 return d->nodePrototype.value();
564}
565
567{
568 Scope scope(v4);
569
570 Scoped<Node> instance(scope, v4->memoryManager->allocate<Node>(data));
571 ScopedObject p(scope);
572
573 switch (data->type) {
574 case NodeImpl::Attr:
575 instance->setPrototypeUnchecked((p = Attr::prototype(v4)));
576 break;
581 case NodeImpl::Entity:
585 return Encode::undefined();
586 case NodeImpl::CDATA:
587 instance->setPrototypeUnchecked((p = CDATA::prototype(v4)));
588 break;
589 case NodeImpl::Text:
590 instance->setPrototypeUnchecked((p = Text::prototype(v4)));
591 break;
593 instance->setPrototypeUnchecked((p = Element::prototype(v4)));
594 break;
595 }
596
597 return instance.asReturnedValue();
598}
599
601{
603 if (d->elementPrototype.isUndefined()) {
604 Scope scope(engine);
605 ScopedObject p(scope, engine->newObject());
606 ScopedObject pp(scope);
607 p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
608 p->defineAccessorProperty(QStringLiteral("tagName"), NodePrototype::method_get_nodeName, nullptr);
609 d->elementPrototype.set(engine, p);
610 engine->freezeObject(p);
611 }
612 return d->elementPrototype.value();
613}
614
616{
618 if (d->attrPrototype.isUndefined()) {
619 Scope scope(engine);
620 ScopedObject p(scope, engine->newObject());
621 ScopedObject pp(scope);
622 p->setPrototypeUnchecked((pp = NodePrototype::getProto(engine)));
623 p->defineAccessorProperty(QStringLiteral("name"), method_name, nullptr);
624 p->defineAccessorProperty(QStringLiteral("value"), method_value, nullptr);
625 p->defineAccessorProperty(QStringLiteral("ownerElement"), method_ownerElement, nullptr);
626 d->attrPrototype.set(engine, p);
627 engine->freezeObject(p);
628 }
629 return d->attrPrototype.value();
630}
631
632ReturnedValue Attr::method_name(const FunctionObject *b, const Value *thisObject, const Value *, int)
633{
634 QV4::Scope scope(b);
635 Scoped<Node> r(scope, thisObject->as<Node>());
636 if (!r)
638
639 return Encode(scope.engine->newString(r->d()->d->name));
640}
641
642ReturnedValue Attr::method_value(const FunctionObject *b, const Value *thisObject, const Value *, int)
643{
644 QV4::Scope scope(b);
645 Scoped<Node> r(scope, thisObject->as<Node>());
646 if (!r)
648
649 return Encode(scope.engine->newString(r->d()->d->data));
650}
651
652ReturnedValue Attr::method_ownerElement(const FunctionObject *b, const Value *thisObject, const Value *, int)
653{
654 QV4::Scope scope(b);
655 Scoped<Node> r(scope, thisObject->as<Node>());
656 if (!r)
658
659 return Node::create(scope.engine, r->d()->d->parent);
660}
661
663{
664 QV4::Scope scope(b);
665 Scoped<Node> r(scope, thisObject->as<Node>());
666 if (!r)
668
669 return Encode(int(r->d()->d->data.size()));
670}
671
673{
675 if (d->characterDataPrototype.isUndefined()) {
676 Scope scope(v4);
677 ScopedObject p(scope, v4->newObject());
678 ScopedObject pp(scope);
679 p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
680 p->defineAccessorProperty(QStringLiteral("data"), NodePrototype::method_get_nodeValue, nullptr);
681 p->defineAccessorProperty(QStringLiteral("length"), method_length, nullptr);
682 d->characterDataPrototype.set(v4, p);
683 v4->freezeObject(p);
684 }
685 return d->characterDataPrototype.value();
686}
687
689{
690 QV4::Scope scope(b);
691 Scoped<Node> r(scope, thisObject->as<Node>());
692 if (!r)
694
695 return Encode(QStringView(r->d()->d->data).trimmed().isEmpty());
696}
697
698ReturnedValue Text::method_wholeText(const FunctionObject *b, const Value *thisObject, const Value *, int)
699{
700 QV4::Scope scope(b);
701 Scoped<Node> r(scope, thisObject->as<Node>());
702 if (!r)
704
705 return Encode(scope.engine->newString(r->d()->d->data));
706}
707
709{
711 if (d->textPrototype.isUndefined()) {
712 Scope scope(v4);
713 ScopedObject p(scope, v4->newObject());
714 ScopedObject pp(scope);
715 p->setPrototypeUnchecked((pp = CharacterData::prototype(v4)));
716 p->defineAccessorProperty(QStringLiteral("isElementContentWhitespace"), method_isElementContentWhitespace, nullptr);
717 p->defineAccessorProperty(QStringLiteral("wholeText"), method_wholeText, nullptr);
718 d->textPrototype.set(v4, p);
719 v4->freezeObject(p);
720 }
721 return d->textPrototype.value();
722}
723
725{
726 // ### why not just use TextProto???
728 if (d->cdataPrototype.isUndefined()) {
729 Scope scope(v4);
730 ScopedObject p(scope, v4->newObject());
731 ScopedObject pp(scope);
732 p->setPrototypeUnchecked((pp = Text::prototype(v4)));
733 d->cdataPrototype.set(v4, p);
734 v4->freezeObject(p);
735 }
736 return d->cdataPrototype.value();
737}
738
740{
742 if (d->documentPrototype.isUndefined()) {
743 Scope scope(v4);
744 ScopedObject p(scope, v4->newObject());
745 ScopedObject pp(scope);
746 p->setPrototypeUnchecked((pp = NodePrototype::getProto(v4)));
747 p->defineAccessorProperty(QStringLiteral("xmlVersion"), method_xmlVersion, nullptr);
748 p->defineAccessorProperty(QStringLiteral("xmlEncoding"), method_xmlEncoding, nullptr);
749 p->defineAccessorProperty(QStringLiteral("xmlStandalone"), method_xmlStandalone, nullptr);
750 p->defineAccessorProperty(QStringLiteral("documentElement"), method_documentElement, nullptr);
751 d->documentPrototype.set(v4, p);
752 v4->freezeObject(p);
753 }
754 return d->documentPrototype.value();
755}
756
758{
759 Scope scope(v4);
760
761 DocumentImpl *document = nullptr;
762 QStack<NodeImpl *> nodeStack;
763
764 QXmlStreamReader reader(data);
765
766 while (!reader.atEnd()) {
767 switch (reader.readNext()) {
768 case QXmlStreamReader::NoToken:
769 break;
770 case QXmlStreamReader::Invalid:
771 break;
772 case QXmlStreamReader::StartDocument:
773 Q_ASSERT(!document);
774 document = new DocumentImpl;
775 document->document = document;
776 document->version = reader.documentVersion().toString();
777 document->encoding = reader.documentEncoding().toString();
778 document->isStandalone = reader.isStandaloneDocument();
779 break;
780 case QXmlStreamReader::EndDocument:
781 break;
782 case QXmlStreamReader::StartElement:
783 {
784 Q_ASSERT(document);
785 NodeImpl *node = new NodeImpl;
786 node->document = document;
787 node->namespaceUri = reader.namespaceUri().toString();
788 node->name = reader.name().toString();
789 if (nodeStack.isEmpty()) {
790 document->root = node;
791 } else {
792 node->parent = nodeStack.top();
793 node->parent->children.append(node);
794 }
795 nodeStack.append(node);
796
797 const auto attributes = reader.attributes();
798 for (const QXmlStreamAttribute &a : attributes) {
799 NodeImpl *attr = new NodeImpl;
800 attr->document = document;
801 attr->type = NodeImpl::Attr;
802 attr->namespaceUri = a.namespaceUri().toString();
803 attr->name = a.name().toString();
804 attr->data = a.value().toString();
805 attr->parent = node;
806 node->attributes.append(attr);
807 }
808 }
809 break;
810 case QXmlStreamReader::EndElement:
811 nodeStack.pop();
812 break;
813 case QXmlStreamReader::Characters:
814 {
815 NodeImpl *node = new NodeImpl;
816 node->document = document;
817 node->type = reader.isCDATA()?NodeImpl::CDATA:NodeImpl::Text;
818 node->parent = nodeStack.top();
819 node->parent->children.append(node);
820 node->data = reader.text().toString();
821 }
822 break;
823 case QXmlStreamReader::Comment:
824 break;
825 case QXmlStreamReader::DTD:
826 break;
827 case QXmlStreamReader::EntityReference:
828 break;
829 case QXmlStreamReader::ProcessingInstruction:
830 break;
831 }
832 }
833
834 if (!document || reader.hasError()) {
835 if (document)
836 document->release();
837 return Encode::null();
838 }
839
840 ScopedObject instance(scope, v4->memoryManager->allocate<Node>(document));
841 document->release(); // the GC should own the NodeImpl via Node now
842 ScopedObject p(scope);
843 instance->setPrototypeUnchecked((p = Document::prototype(v4)));
844 return instance.asReturnedValue();
845}
846
847bool Node::isNull() const
848{
849 return d()->d == nullptr;
850}
851
852ReturnedValue NamedNodeMap::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
853{
854 Q_ASSERT(m->as<NamedNodeMap>());
855
856 const NamedNodeMap *r = static_cast<const NamedNodeMap *>(m);
857 QV4::ExecutionEngine *v4 = r->engine();
858
859 if (id.isArrayIndex()) {
860 uint index = id.asArrayIndex();
861
862 if ((int)index < r->d()->list().size()) {
863 if (hasProperty)
864 *hasProperty = true;
865 return Node::create(v4, r->d()->list().at(index));
866 }
867 if (hasProperty)
868 *hasProperty = false;
869 return Encode::undefined();
870 }
871
872 if (id.isSymbol())
873 return Object::virtualGet(m, id, receiver, hasProperty);
874
875 if (id == v4->id_length()->propertyKey())
876 return Value::fromInt32(r->d()->list().size()).asReturnedValue();
877
878 QString str = id.toQString();
879 for (int ii = 0; ii < r->d()->list().size(); ++ii) {
880 if (r->d()->list().at(ii)->name == str) {
881 if (hasProperty)
882 *hasProperty = true;
883 return Node::create(v4, r->d()->list().at(ii));
884 }
885 }
886
887 if (hasProperty)
888 *hasProperty = false;
889 return Encode::undefined();
890}
891
893{
894 return (v4->memoryManager->allocate<NamedNodeMap>(data, list))->asReturnedValue();
895}
896
897ReturnedValue NodeList::virtualGet(const Managed *m, PropertyKey id, const Value *receiver, bool *hasProperty)
898{
899 Q_ASSERT(m->as<NodeList>());
900 const NodeList *r = static_cast<const NodeList *>(m);
901 QV4::ExecutionEngine *v4 = r->engine();
902
903 if (id.isArrayIndex()) {
904 uint index = id.asArrayIndex();
905 if ((int)index < r->d()->d->children.size()) {
906 if (hasProperty)
907 *hasProperty = true;
908 return Node::create(v4, r->d()->d->children.at(index));
909 }
910 if (hasProperty)
911 *hasProperty = false;
912 return Encode::undefined();
913 }
914
915 if (id == v4->id_length()->propertyKey())
916 return Value::fromInt32(r->d()->d->children.size()).asReturnedValue();
917 return Object::virtualGet(m, id, receiver, hasProperty);
918}
919
921{
922 return (v4->memoryManager->allocate<NodeList>(data))->asReturnedValue();
923}
924
926{
927 Scope scope(b);
928 Scoped<Node> r(scope, thisObject->as<Node>());
929 if (!r || r->d()->d->type != NodeImpl::Document)
931
932 return Node::create(scope.engine, static_cast<DocumentImpl *>(r->d()->d)->root);
933}
934
936{
937 Scope scope(b);
938 Scoped<Node> r(scope, thisObject->as<Node>());
939 if (!r || r->d()->d->type != NodeImpl::Document)
941
942 return Encode(static_cast<DocumentImpl *>(r->d()->d)->isStandalone);
943}
944
945ReturnedValue Document::method_xmlVersion(const FunctionObject *b, const Value *thisObject, const Value *, int)
946{
947 Scope scope(b);
948 Scoped<Node> r(scope, thisObject->as<Node>());
949 if (!r || r->d()->d->type != NodeImpl::Document)
951
952 return Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->version));
953}
954
956{
957 Scope scope(b);
958 Scoped<Node> r(scope, thisObject->as<Node>());
959 if (!r || r->d()->d->type != NodeImpl::Document)
961
962 return Encode(scope.engine->newString(static_cast<DocumentImpl *>(r->d()->d)->encoding));
963}
964
966{
968public:
969 enum LoadType {
971 SynchronousLoad
972 };
973 enum State {
974 Unsent = 0,
975 Opened = 1,
976 HeadersReceived = 2,
977 Loading = 3,
978 Done = 4
979 };
980
982 virtual ~QQmlXMLHttpRequest();
983
984 bool sendFlag() const;
985 bool errorFlag() const;
986 quint32 readyState() const;
987 int replyStatus() const;
988 QString replyStatusText() const;
989
990 ReturnedValue open(Object *thisObject, const QString &, const QUrl &, LoadType);
992 const QByteArray &);
993 ReturnedValue abort(Object *thisObject);
994
995 void addHeader(const QString &, const QString &);
996 QString header(const QString &name) const;
997 QString headers() const;
998
999 QString responseBody();
1000 const QByteArray & rawResponseBody() const;
1001 bool receivedXml() const;
1002 QUrl url() const;
1003
1004 const QString & responseType() const;
1005 void setResponseType(const QString &);
1006 void setOverrideMimeType(QStringView mimeType) { m_overrideMime = mimeType.toUtf8(); }
1007 void setOverrideCharset(QStringView charset) { m_overrideCharset = charset.toUtf8(); }
1008
1009 const QByteArray mimeType() const;
1010 const QByteArray charset() const;
1011
1012 QV4::ReturnedValue jsonResponseBody(QV4::ExecutionEngine*);
1013 QV4::ReturnedValue xmlResponseBody(QV4::ExecutionEngine*);
1014private slots:
1015 void readyRead();
1017 void finished();
1018
1019private:
1020 void requestFromUrl(const QUrl &url);
1021
1022 State m_state;
1023 bool m_errorFlag;
1024 bool m_sendFlag;
1025 QString m_method;
1026 QUrl m_url;
1027 QByteArray m_responseEntityBody;
1029 int m_redirectCount;
1030
1031 typedef QPair<QByteArray, QByteArray> HeaderPair;
1032 typedef QList<HeaderPair> HeadersList;
1033 HeadersList m_headersList;
1034 void fillHeadersList();
1035
1036 bool m_gotXml;
1037 QByteArray m_mime;
1038 QByteArray m_charset;
1039 QByteArray m_overrideMime;
1040 QByteArray m_overrideCharset;
1041
1042 QStringDecoder findTextDecoder() const;
1043 void readEncoding();
1044
1045 PersistentValue m_thisObject;
1047 bool m_wasConstructedWithQmlContext = true;
1048
1049 void dispatchCallbackNow(Object *thisObj);
1050 static void dispatchCallbackNow(Object *thisObj, bool done, bool error);
1051 void dispatchCallbackSafely();
1052
1053 int m_status;
1054 QString m_statusText;
1055 QNetworkRequest m_request;
1056 QStringList m_addedHeaders;
1057 QPointer<QNetworkReply> m_network;
1058 void destroyNetwork();
1059
1060 QNetworkAccessManager *m_nam;
1061 QNetworkAccessManager *networkAccessManager() { return m_nam; }
1062
1063 QString m_responseType;
1064 QV4::PersistentValue m_parsedDocument;
1065};
1066
1068 : m_state(Unsent), m_errorFlag(false), m_sendFlag(false)
1069 , m_redirectCount(0), m_gotXml(false), m_network(nullptr), m_nam(manager)
1070{
1071 m_wasConstructedWithQmlContext = !v4->callingQmlContext().isNull();
1072}
1073
1075{
1076 destroyNetwork();
1077}
1078
1080{
1081 return m_sendFlag;
1082}
1083
1085{
1086 return m_errorFlag;
1087}
1088
1090{
1091 return m_state;
1092}
1093
1095{
1096 return m_status;
1097}
1098
1100{
1101 return m_statusText;
1102}
1103
1105{
1106 destroyNetwork();
1107 m_sendFlag = false;
1108 m_errorFlag = false;
1109 m_responseEntityBody = QByteArray();
1110 m_method = method;
1111 m_url = url;
1113 m_state = Opened;
1114 m_addedHeaders.clear();
1115 dispatchCallbackNow(thisObject);
1116 return Encode::undefined();
1117}
1118
1120{
1121 QByteArray utfname = name.toUtf8();
1122
1123 if (m_addedHeaders.contains(name, Qt::CaseInsensitive)) {
1124 m_request.setRawHeader(utfname, m_request.rawHeader(utfname) + ',' + value.toUtf8());
1125 } else {
1126 m_request.setRawHeader(utfname, value.toUtf8());
1127 m_addedHeaders.append(name);
1128 }
1129}
1130
1132{
1133 if (!m_headersList.isEmpty()) {
1134 const QByteArray utfname = name.toLower().toUtf8();
1135 for (const HeaderPair &header : m_headersList) {
1136 if (header.first == utfname)
1137 return QString::fromUtf8(header.second);
1138 }
1139 }
1140 return QString();
1141}
1142
1144{
1145 QString ret;
1146
1147 for (const HeaderPair &header : m_headersList) {
1148 if (ret.size())
1149 ret.append(QLatin1String("\r\n"));
1151 + QString::fromUtf8(header.second);
1152 }
1153 return ret;
1154}
1155
1156void QQmlXMLHttpRequest::fillHeadersList()
1157{
1158 const QList<QByteArray> headerList = m_network->rawHeaderList();
1159
1160 m_headersList.clear();
1161 for (const QByteArray &header : headerList) {
1162 HeaderPair pair (header.toLower(), m_network->rawHeader(header));
1163 if (pair.first == "set-cookie" ||
1164 pair.first == "set-cookie2")
1165 continue;
1166
1167 m_headersList << pair;
1168 }
1169}
1170
1171void QQmlXMLHttpRequest::requestFromUrl(const QUrl &url)
1172{
1173 m_url = url;
1174 QNetworkRequest request = m_request;
1175
1177 if (m_method == QLatin1String("PUT"))
1178 {
1179 if (!xhrFileWrite()) {
1180 qWarning("XMLHttpRequest: Using PUT on a local file is disabled by default.\n"
1181 "Set QML_XHR_ALLOW_FILE_WRITE to 1 to enable this feature.");
1182 return;
1183 }
1184 } else if (m_method == QLatin1String("GET")) {
1185 if (!xhrFileRead()) {
1186 qWarning("XMLHttpRequest: Using GET on a local file is disabled by default.\n"
1187 "Set QML_XHR_ALLOW_FILE_READ to 1 to enable this feature.");
1188 return;
1189 }
1190 } else {
1191 qWarning("XMLHttpRequest: Unsupported method used on a local file");
1192 return;
1193 }
1194 }
1195
1198 if(m_method == QLatin1String("POST") ||
1199 m_method == QLatin1String("PUT")) {
1201 if (var.isValid()) {
1202 QString str = var.toString();
1203 int charsetIdx = str.indexOf(QLatin1String("charset="));
1204 if (charsetIdx == -1) {
1205 // No charset - append
1206 if (!str.isEmpty()) str.append(QLatin1Char(';'));
1207 str.append(QLatin1String("charset=UTF-8"));
1208 } else {
1209 charsetIdx += 8;
1210 int n = 0;
1211 int semiColon = str.indexOf(QLatin1Char(';'), charsetIdx);
1212 if (semiColon == -1) {
1213 n = str.size() - charsetIdx;
1214 } else {
1215 n = semiColon - charsetIdx;
1216 }
1217
1218 str.replace(charsetIdx, n, QLatin1String("UTF-8"));
1219 }
1221 } else {
1223 QLatin1String("text/plain;charset=UTF-8"));
1224 }
1225 }
1226
1227 if (xhrDump()) {
1228 qWarning().nospace() << "XMLHttpRequest: " << qPrintable(m_method) << ' ' << qPrintable(url.toString());
1229 if (!m_data.isEmpty()) {
1230 qWarning().nospace() << " "
1231 << qPrintable(QString::fromUtf8(m_data));
1232 }
1233 }
1234
1235 if (m_method == QLatin1String("GET")) {
1236 m_network = networkAccessManager()->get(request);
1237 } else if (m_method == QLatin1String("HEAD")) {
1238 m_network = networkAccessManager()->head(request);
1239 } else if (m_method == QLatin1String("POST")) {
1240 m_network = networkAccessManager()->post(request, m_data);
1241 } else if (m_method == QLatin1String("PUT")) {
1242 m_network = networkAccessManager()->put(request, m_data);
1243 } else if (m_method == QLatin1String("DELETE")) {
1244 m_network = networkAccessManager()->deleteResource(request);
1245 } else if ((m_method == QLatin1String("OPTIONS")) ||
1246 m_method == QLatin1String("PROPFIND") ||
1247 m_method == QLatin1String("PATCH")) {
1248 QBuffer *buffer = new QBuffer;
1249 buffer->setData(m_data);
1251 m_network = networkAccessManager()->sendCustomRequest(request, QByteArray(m_method.toUtf8().constData()), buffer);
1252 buffer->setParent(m_network);
1253 }
1254
1256 if (m_network->bytesAvailable() > 0)
1257 readyRead();
1258
1259 QNetworkReply::NetworkError networkError = m_network->error();
1260 if (networkError != QNetworkReply::NoError) {
1261 error(networkError);
1262 } else {
1263 finished();
1264 }
1265 } else {
1266 QObject::connect(m_network, SIGNAL(readyRead()),
1267 this, SLOT(readyRead()));
1268 QObject::connect(m_network, SIGNAL(errorOccurred(QNetworkReply::NetworkError)),
1269 this, SLOT(error(QNetworkReply::NetworkError)));
1270 QObject::connect(m_network, SIGNAL(finished()),
1271 this, SLOT(finished()));
1272 }
1273}
1274
1276 Object *thisObject, const QQmlRefPointer<QQmlContextData> &context, const QByteArray &data)
1277{
1278 m_errorFlag = false;
1279 m_sendFlag = true;
1280 m_redirectCount = 0;
1281 m_data = data;
1282
1283 m_thisObject = thisObject;
1284 m_qmlContext = context;
1285
1286 requestFromUrl(m_url);
1287
1288 return Encode::undefined();
1289}
1290
1292{
1293 destroyNetwork();
1294 m_responseEntityBody = QByteArray();
1295 m_errorFlag = true;
1296 m_request = QNetworkRequest();
1297
1298 if (!(m_state == Unsent ||
1299 (m_state == Opened && !m_sendFlag) ||
1300 m_state == Done)) {
1301
1302 m_state = Done;
1303 m_sendFlag = false;
1304 dispatchCallbackNow(thisObject);
1305 }
1306
1307 m_state = Unsent;
1308
1309 return Encode::undefined();
1310}
1311
1312void QQmlXMLHttpRequest::readyRead()
1313{
1314 m_status =
1316 m_statusText =
1318
1319 // ### We assume if this is called the headers are now available
1320 if (m_state < HeadersReceived) {
1321 m_state = HeadersReceived;
1322 fillHeadersList();
1323 dispatchCallbackSafely();
1324 }
1325
1326 bool wasEmpty = m_responseEntityBody.isEmpty();
1327 m_responseEntityBody.append(m_network->readAll());
1328 if (wasEmpty && !m_responseEntityBody.isEmpty())
1329 m_state = Loading;
1330
1331 dispatchCallbackSafely();
1332}
1333
1335{
1336 int idx = QNetworkReply::staticMetaObject.indexOfEnumerator("NetworkError");
1337 if (idx == -1) return "EnumLookupFailed";
1338
1339 QMetaEnum e = QNetworkReply::staticMetaObject.enumerator(idx);
1340
1341 const char *name = e.valueToKey(error);
1342 if (!name) return "EnumLookupFailed";
1343 else return name;
1344}
1345
1346void QQmlXMLHttpRequest::error(QNetworkReply::NetworkError error)
1347{
1348 m_status =
1350 m_statusText =
1352
1353 m_request = QNetworkRequest();
1354 m_data.clear();
1355 destroyNetwork();
1356
1357 if (xhrDump()) {
1358 qWarning().nospace() << "XMLHttpRequest: ERROR " << qPrintable(m_url.toString());
1359 qWarning().nospace() << " " << error << ' ' << errorToString(error) << ' ' << m_statusText;
1360 }
1361
1373 m_state = Loading;
1374 dispatchCallbackSafely();
1375 } else {
1376 m_errorFlag = true;
1377 m_responseEntityBody = QByteArray();
1378 }
1379
1380 m_state = Done;
1381 dispatchCallbackSafely();
1382}
1383
1384#define XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION 15
1385void QQmlXMLHttpRequest::finished()
1386{
1387 m_redirectCount++;
1388 if (m_redirectCount < XMLHTTPREQUEST_MAXIMUM_REDIRECT_RECURSION) {
1390 if (redirect.isValid()) {
1391 QUrl url = m_network->url().resolved(redirect.toUrl());
1392 if (!QQmlFile::isLocalFile(url)) {
1393 // See http://www.ietf.org/rfc/rfc2616.txt, section 10.3.4 "303 See Other":
1394 // Result of 303 redirection should be a new "GET" request.
1396 if (code.isValid() && code.toInt() == 303 && m_method != QLatin1String("GET"))
1397 m_method = QStringLiteral("GET");
1398 destroyNetwork();
1399
1400 // Discard redirect response body
1401 m_responseEntityBody = QByteArray();
1402
1403 requestFromUrl(url);
1404 return;
1405 }
1406 }
1407 }
1408
1409 m_status =
1411 m_statusText =
1413
1414 if (m_state < HeadersReceived) {
1415 m_state = HeadersReceived;
1416 fillHeadersList ();
1417 dispatchCallbackSafely();
1418 }
1419 m_responseEntityBody.append(m_network->readAll());
1420 readEncoding();
1421
1422 if (xhrDump()) {
1423 qWarning().nospace() << "XMLHttpRequest: RESPONSE " << qPrintable(m_url.toString());
1424 if (!m_responseEntityBody.isEmpty()) {
1425 qWarning().nospace() << " "
1426 << qPrintable(QString::fromUtf8(m_responseEntityBody));
1427 }
1428 }
1429
1430 m_data.clear();
1431 destroyNetwork();
1432 if (m_state < Loading) {
1433 m_state = Loading;
1434 dispatchCallbackSafely();
1435 }
1436 m_state = Done;
1437
1438 dispatchCallbackSafely();
1439
1440 m_thisObject.clear();
1441 m_qmlContext.reset();
1442}
1443
1444
1445void QQmlXMLHttpRequest::readEncoding()
1446{
1447 for (const HeaderPair &header : std::as_const(m_headersList)) {
1448 if (header.first == "content-type") {
1449 int separatorIdx = header.second.indexOf(';');
1450 if (separatorIdx == -1) {
1451 m_mime = header.second;
1452 } else {
1453 m_mime = header.second.mid(0, separatorIdx);
1454 int charsetIdx = header.second.indexOf("charset=");
1455 if (charsetIdx != -1) {
1456 charsetIdx += 8;
1457 separatorIdx = header.second.indexOf(';', charsetIdx);
1458 m_charset = header.second.mid(charsetIdx, separatorIdx >= 0 ? separatorIdx : header.second.size());
1459 }
1460 }
1461 break;
1462 }
1463 }
1464
1465 const auto mime = mimeType();
1466 if (mime.isEmpty() || mime == "text/xml" || mime == "application/xml" || mime.endsWith("+xml"))
1467 m_gotXml = true;
1468}
1469
1471{
1472 return m_gotXml;
1473}
1474
1476{
1477 return m_url;
1478}
1479
1481{
1482 // Final MIME type is the override MIME type unless that is null in which
1483 // case it is the response MIME type.
1484 return m_overrideMime.isEmpty() ? m_mime : m_overrideMime;
1485}
1486
1488{
1489 // Final charset is the override charset unless that is null in which case
1490 // it is the response charset.
1491 return m_overrideCharset.isEmpty() ? m_charset : m_overrideCharset;
1492}
1493
1495{
1496 return m_responseType;
1497}
1498
1500{
1501 m_responseType = responseType;
1502}
1503
1505{
1506 if (m_parsedDocument.isEmpty()) {
1507 Scope scope(engine);
1508
1510 const QString& jtext = responseBody();
1511 JsonParser parser(scope.engine, jtext.constData(), jtext.size());
1512 ScopedValue jsonObject(scope, parser.parse(&error));
1513 if (error.error != QJsonParseError::NoError)
1514 return engine->throwSyntaxError(QStringLiteral("JSON.parse: Parse error"));
1515
1516 m_parsedDocument.set(scope.engine, jsonObject);
1517 }
1518
1519 return m_parsedDocument.value();
1520}
1521
1523{
1524 if (m_parsedDocument.isEmpty()) {
1525 m_parsedDocument.set(engine, Document::load(engine, rawResponseBody()));
1526 }
1527
1528 return m_parsedDocument.value();
1529}
1530
1531QStringDecoder QQmlXMLHttpRequest::findTextDecoder() const
1532{
1533 QStringDecoder decoder;
1534
1535 if (!charset().isEmpty())
1536 decoder = QStringDecoder(charset());
1537
1538 if (!decoder.isValid() && m_gotXml) {
1539 QXmlStreamReader reader(m_responseEntityBody);
1540 reader.readNext();
1541 decoder = QStringDecoder(reader.documentEncoding().toString().toUtf8());
1542 }
1543
1544 if (!decoder.isValid() && mimeType() == "text/html")
1545 decoder = QStringDecoder::decoderForHtml(m_responseEntityBody);
1546
1547 if (!decoder.isValid()) {
1548 auto encoding = QStringConverter::encodingForData(m_responseEntityBody);
1549 if (encoding)
1550 decoder = QStringDecoder(*encoding);
1551 }
1552
1553 if (!decoder.isValid())
1555
1556 return decoder;
1557}
1558
1560{
1561 QStringDecoder toUtf16 = findTextDecoder();
1562 return toUtf16(m_responseEntityBody);
1563}
1564
1566{
1567 return m_responseEntityBody;
1568}
1569
1570void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj)
1571{
1572 dispatchCallbackNow(thisObj, m_state == Done, m_errorFlag);
1573}
1574
1575void QQmlXMLHttpRequest::dispatchCallbackNow(Object *thisObj, bool done, bool error)
1576{
1577 Q_ASSERT(thisObj);
1578
1579 const auto dispatch = [thisObj](const QString &eventName) {
1580 QV4::Scope scope(thisObj->engine());
1581 ScopedString s(scope, scope.engine->newString(eventName));
1582 ScopedFunctionObject callback(scope, thisObj->get(s));
1583 // not an error, but no event handler to call.
1584 if (!callback)
1585 return;
1586
1587 QV4::JSCallArguments jsCallData(scope);
1588 callback->call(jsCallData);
1589
1590 if (scope.hasException()) {
1591 QQmlError error = scope.engine->catchExceptionAsQmlError();
1592 QQmlEnginePrivate *qmlEnginePrivate = scope.engine->qmlEngine() ? QQmlEnginePrivate::get(scope.engine->qmlEngine()) : nullptr;
1593 QQmlEnginePrivate::warning(qmlEnginePrivate, error);
1594 }
1595 };
1596
1597 dispatch(QStringLiteral("onreadystatechange"));
1598 if (done) {
1599 if (error)
1600 dispatch(QStringLiteral("onerror"));
1601 else
1602 dispatch(QStringLiteral("onload"));
1603 dispatch(QStringLiteral("onloadend"));
1604 }
1605}
1606
1607void QQmlXMLHttpRequest::dispatchCallbackSafely()
1608{
1609 if (m_wasConstructedWithQmlContext && m_qmlContext.isNull()) {
1610 // if the calling context object is no longer valid, then it has been
1611 // deleted explicitly (e.g., by a Loader deleting the itemContext when
1612 // the source is changed). We do nothing in this case, as the evaluation
1613 // cannot succeed.
1614 return;
1615 }
1616
1617 dispatchCallbackNow(m_thisObject.as<Object>());
1618}
1619
1620void QQmlXMLHttpRequest::destroyNetwork()
1621{
1622 if (m_network) {
1623 m_network->disconnect();
1624 m_network->deleteLater();
1625 m_network = nullptr;
1626 }
1627}
1628
1629namespace QV4 {
1630namespace Heap {
1631
1634 Object::init();
1635 this->request = request;
1636 }
1637
1638 void destroy() {
1639 delete request;
1640 Object::destroy();
1641 }
1643};
1644
1645#define QQmlXMLHttpRequestCtorMembers(class, Member) \
1646 Member(class, Pointer, Object *, proto)
1647
1651};
1652
1653}
1654
1656{
1659};
1660
1661// https://xhr.spec.whatwg.org/
1663{
1665
1667 {
1668 Scope scope(f->engine());
1669 const QQmlXMLHttpRequestCtor *ctor = static_cast<const QQmlXMLHttpRequestCtor *>(f);
1670
1671 QQmlXMLHttpRequest *r = new QQmlXMLHttpRequest(scope.engine->networkAccessManager(scope.engine), scope.engine);
1672 Scoped<QQmlXMLHttpRequestWrapper> w(scope, scope.engine->memoryManager->allocate<QQmlXMLHttpRequestWrapper>(r));
1673 ScopedObject proto(scope, ctor->d()->proto);
1674 w->setPrototypeUnchecked(proto);
1675 return w.asReturnedValue();
1676 }
1677
1678 static ReturnedValue virtualCall(const FunctionObject *, const Value *, const Value *, int) {
1679 return Encode::undefined();
1680 }
1681
1682 void setupProto();
1683
1684 static ReturnedValue method_open(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1685 static ReturnedValue method_setRequestHeader(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1686 static ReturnedValue method_send(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1687 static ReturnedValue method_abort(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1688 static ReturnedValue method_getResponseHeader(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1689 static ReturnedValue method_getAllResponseHeaders(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1690 static ReturnedValue method_overrideMimeType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1691
1692 static ReturnedValue method_get_readyState(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1693 static ReturnedValue method_get_status(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1694 static ReturnedValue method_get_statusText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1695 static ReturnedValue method_get_responseText(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1696 static ReturnedValue method_get_responseXML(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1697 static ReturnedValue method_get_response(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1698 static ReturnedValue method_get_responseType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1699 static ReturnedValue method_set_responseType(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1700 static ReturnedValue method_get_responseURL(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc);
1701};
1702
1703}
1704
1706
1707void Heap::QQmlXMLHttpRequestCtor::init(ExecutionEngine *engine)
1708{
1709 Heap::FunctionObject::init(engine->rootContext(), QStringLiteral("XMLHttpRequest"));
1710 Scope scope(engine);
1711 Scoped<QV4::QQmlXMLHttpRequestCtor> ctor(scope, this);
1712
1713 ctor->defineReadonlyProperty(QStringLiteral("UNSENT"), Value::fromInt32(QQmlXMLHttpRequest::Unsent));
1714 ctor->defineReadonlyProperty(QStringLiteral("OPENED"), Value::fromInt32(QQmlXMLHttpRequest::Opened));
1715 ctor->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Value::fromInt32(QQmlXMLHttpRequest::HeadersReceived));
1716 ctor->defineReadonlyProperty(QStringLiteral("LOADING"), Value::fromInt32(QQmlXMLHttpRequest::Loading));
1717 ctor->defineReadonlyProperty(QStringLiteral("DONE"), Value::fromInt32(QQmlXMLHttpRequest::Done));
1718
1719 if (!ctor->d()->proto)
1720 ctor->setupProto();
1721 ScopedString s(scope, engine->id_prototype());
1722 ctor->defineDefaultProperty(s, ScopedObject(scope, ctor->d()->proto));
1723}
1724
1726
1728{
1729 ExecutionEngine *v4 = engine();
1730 Scope scope(v4);
1731 ScopedObject p(scope, v4->newObject());
1732 d()->proto.set(scope.engine, p->d());
1733
1734 // Methods
1735 p->defineDefaultProperty(QStringLiteral("open"), method_open);
1736 p->defineDefaultProperty(QStringLiteral("setRequestHeader"), method_setRequestHeader);
1737 p->defineDefaultProperty(QStringLiteral("send"), method_send);
1738 p->defineDefaultProperty(QStringLiteral("abort"), method_abort);
1739 p->defineDefaultProperty(QStringLiteral("getResponseHeader"), method_getResponseHeader);
1740 p->defineDefaultProperty(QStringLiteral("getAllResponseHeaders"), method_getAllResponseHeaders);
1741 p->defineDefaultProperty(QStringLiteral("overrideMimeType"), method_overrideMimeType);
1742
1743 // Read-only properties
1744 p->defineAccessorProperty(QStringLiteral("readyState"), method_get_readyState, nullptr);
1745 p->defineAccessorProperty(QStringLiteral("status"),method_get_status, nullptr);
1746 p->defineAccessorProperty(QStringLiteral("statusText"),method_get_statusText, nullptr);
1747 p->defineAccessorProperty(QStringLiteral("responseText"),method_get_responseText, nullptr);
1748 p->defineAccessorProperty(QStringLiteral("responseXML"),method_get_responseXML, nullptr);
1749 p->defineAccessorProperty(QStringLiteral("response"),method_get_response, nullptr);
1750 p->defineAccessorProperty(QStringLiteral("responseURL"),method_get_responseURL, nullptr);
1751
1752 // Read-write properties
1753 p->defineAccessorProperty(QStringLiteral("responseType"), method_get_responseType, method_set_responseType);
1754
1755 // State values
1756 p->defineReadonlyProperty(QStringLiteral("UNSENT"), Value::fromInt32(0));
1757 p->defineReadonlyProperty(QStringLiteral("OPENED"), Value::fromInt32(1));
1758 p->defineReadonlyProperty(QStringLiteral("HEADERS_RECEIVED"), Value::fromInt32(2));
1759 p->defineReadonlyProperty(QStringLiteral("LOADING"), Value::fromInt32(3));
1760 p->defineReadonlyProperty(QStringLiteral("DONE"), Value::fromInt32(4));
1761}
1762
1763
1764// XMLHttpRequest methods
1765ReturnedValue QQmlXMLHttpRequestCtor::method_open(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1766{
1767 Scope scope(b);
1769 if (!w)
1770 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1771 QQmlXMLHttpRequest *r = w->d()->request;
1772
1773 if (argc < 2 || argc > 5)
1774 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1775
1776 // Argument 0 - Method
1777 QString method = argv[0].toQStringNoThrow().toUpper();
1778 if (method != QLatin1String("GET") &&
1779 method != QLatin1String("PUT") &&
1780 method != QLatin1String("HEAD") &&
1781 method != QLatin1String("POST") &&
1782 method != QLatin1String("DELETE") &&
1783 method != QLatin1String("OPTIONS") &&
1784 method != QLatin1String("PROPFIND") &&
1785 method != QLatin1String("PATCH"))
1786 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Unsupported HTTP method type");
1787
1788 // Argument 1 - URL
1789 QUrl url = QUrl(argv[1].toQStringNoThrow());
1790
1791 if (url.isRelative()) {
1792 if (QQmlRefPointer<QQmlContextData> qmlContextData = scope.engine->callingQmlContext())
1793 url = qmlContextData->resolvedUrl(url);
1794 else
1795 url = scope.engine->resolvedUrl(url.url());
1796 }
1797
1798 bool async = true;
1799 // Argument 2 - async (optional)
1800 if (argc > 2) {
1801 async = argv[2].booleanValue();
1802 }
1803
1804 // Argument 3/4 - user/pass (optional)
1805 QString username, password;
1806 if (argc > 3)
1807 username = argv[3].toQStringNoThrow();
1808 if (argc > 4)
1809 password = argv[4].toQStringNoThrow();
1810
1811 // Clear the fragment (if any)
1813
1814 // Set username/password
1815 if (!username.isNull()) url.setUserName(username);
1816 if (!password.isNull()) url.setPassword(password);
1817
1819}
1820
1822{
1823 Scope scope(b);
1825 if (!w)
1826 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1827 QQmlXMLHttpRequest *r = w->d()->request;
1828
1829 if (argc != 2)
1830 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1831
1832 if (r->readyState() != QQmlXMLHttpRequest::Opened || r->sendFlag())
1833 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1834
1835 QString name = argv[0].toQStringNoThrow();
1836 QString value = argv[1].toQStringNoThrow();
1837
1838 // ### Check that name and value are well formed
1839
1840 QString nameUpper = name.toUpper();
1841 if (nameUpper == QLatin1String("ACCEPT-CHARSET") ||
1842 nameUpper == QLatin1String("ACCEPT-ENCODING") ||
1843 nameUpper == QLatin1String("CONNECTION") ||
1844 nameUpper == QLatin1String("CONTENT-LENGTH") ||
1845 nameUpper == QLatin1String("COOKIE") ||
1846 nameUpper == QLatin1String("COOKIE2") ||
1847 nameUpper == QLatin1String("CONTENT-TRANSFER-ENCODING") ||
1848 nameUpper == QLatin1String("DATE") ||
1849 nameUpper == QLatin1String("EXPECT") ||
1850 nameUpper == QLatin1String("HOST") ||
1851 nameUpper == QLatin1String("KEEP-ALIVE") ||
1852 nameUpper == QLatin1String("REFERER") ||
1853 nameUpper == QLatin1String("TE") ||
1854 nameUpper == QLatin1String("TRAILER") ||
1855 nameUpper == QLatin1String("TRANSFER-ENCODING") ||
1856 nameUpper == QLatin1String("UPGRADE") ||
1857 nameUpper == QLatin1String("VIA") ||
1858 nameUpper.startsWith(QLatin1String("PROXY-")) ||
1859 nameUpper.startsWith(QLatin1String("SEC-")))
1861
1862 r->addHeader(name, value);
1863
1865}
1866
1867ReturnedValue QQmlXMLHttpRequestCtor::method_send(const FunctionObject *b, const Value *thisObject, const Value *argv, int argc)
1868{
1869 Scope scope(b);
1871 if (!w)
1872 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1873 QQmlXMLHttpRequest *r = w->d()->request;
1874
1875 if (r->readyState() != QQmlXMLHttpRequest::Opened ||
1876 r->sendFlag())
1877 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1878
1880 if (argc > 0) {
1881 if (const ArrayBuffer *buffer = argv[0].as<ArrayBuffer>()) {
1882 data = buffer->asByteArray();
1883 } else {
1884 data = argv[0].toQStringNoThrow().toUtf8();
1885 }
1886 }
1887
1888 return r->send(w, scope.engine->callingQmlContext(), data);
1889}
1890
1892{
1893 Scope scope(b);
1895 if (!w)
1896 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1897 QQmlXMLHttpRequest *r = w->d()->request;
1898
1899 return r->abort(w);
1900}
1901
1903{
1904 Scope scope(b);
1906 if (!w)
1907 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1908 QQmlXMLHttpRequest *r = w->d()->request;
1909
1910 if (argc != 1)
1911 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1912
1913 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1914 r->readyState() != QQmlXMLHttpRequest::Done &&
1915 r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
1916 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1917
1918 return Encode(scope.engine->newString(r->header(argv[0].toQStringNoThrow())));
1919}
1920
1922{
1923 Scope scope(b);
1925 if (!w)
1926 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1927 QQmlXMLHttpRequest *r = w->d()->request;
1928
1929 if (argc != 0)
1930 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
1931
1932 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1933 r->readyState() != QQmlXMLHttpRequest::Done &&
1934 r->readyState() != QQmlXMLHttpRequest::HeadersReceived)
1935 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1936
1937 return Encode(scope.engine->newString(r->headers()));
1938}
1939
1940// XMLHttpRequest properties
1942{
1943 Scope scope(b);
1945 if (!w)
1946 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1947 QQmlXMLHttpRequest *r = w->d()->request;
1948
1949 return Encode(r->readyState());
1950}
1951
1953{
1954 Scope scope(b);
1956 if (!w)
1957 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1958 QQmlXMLHttpRequest *r = w->d()->request;
1959
1960 if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
1961 r->readyState() == QQmlXMLHttpRequest::Opened)
1962 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1963
1964 if (r->errorFlag())
1965 return Encode(0);
1966 else
1967 return Encode(r->replyStatus());
1968}
1969
1971{
1972 Scope scope(b);
1974 if (!w)
1975 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1976 QQmlXMLHttpRequest *r = w->d()->request;
1977
1978 if (r->readyState() == QQmlXMLHttpRequest::Unsent ||
1979 r->readyState() == QQmlXMLHttpRequest::Opened)
1980 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
1981
1982 if (r->errorFlag())
1983 return Encode(scope.engine->newString(QString()));
1984 else
1985 return Encode(scope.engine->newString(r->replyStatusText()));
1986}
1987
1989{
1990 Scope scope(b);
1992 if (!w)
1993 V4THROW_REFERENCE("Not an XMLHttpRequest object");
1994 QQmlXMLHttpRequest *r = w->d()->request;
1995
1996 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
1997 r->readyState() != QQmlXMLHttpRequest::Done)
1998 return Encode(scope.engine->newString(QString()));
1999 else
2000 return Encode(scope.engine->newString(r->responseBody()));
2001}
2002
2004{
2005 Scope scope(b);
2007 if (!w)
2008 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2009 QQmlXMLHttpRequest *r = w->d()->request;
2010
2011 if (!r->receivedXml() ||
2012 (r->readyState() != QQmlXMLHttpRequest::Loading &&
2013 r->readyState() != QQmlXMLHttpRequest::Done)) {
2014 return Encode::null();
2015 } else {
2016 if (r->responseType().isEmpty())
2017 r->setResponseType(QLatin1String("document"));
2018 return r->xmlResponseBody(scope.engine);
2019 }
2020}
2021
2023{
2024 Scope scope(b);
2026 if (!w)
2027 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2028 QQmlXMLHttpRequest *r = w->d()->request;
2029
2030 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2031 r->readyState() != QQmlXMLHttpRequest::Done)
2032 RETURN_RESULT(scope.engine->newString(QString()));
2033
2034 const QString& responseType = r->responseType();
2035 if (responseType.compare(QLatin1String("text"), Qt::CaseInsensitive) == 0 || responseType.isEmpty()) {
2036 RETURN_RESULT(scope.engine->newString(r->responseBody()));
2037 } else if (responseType.compare(QLatin1String("arraybuffer"), Qt::CaseInsensitive) == 0) {
2038 RETURN_RESULT(scope.engine->newArrayBuffer(r->rawResponseBody()));
2039 } else if (responseType.compare(QLatin1String("json"), Qt::CaseInsensitive) == 0) {
2040 RETURN_RESULT(r->jsonResponseBody(scope.engine));
2041 } else if (responseType.compare(QLatin1String("document"), Qt::CaseInsensitive) == 0) {
2042 RETURN_RESULT(r->xmlResponseBody(scope.engine));
2043 } else {
2044 RETURN_RESULT(scope.engine->newString(QString()));
2045 }
2046}
2047
2048
2050{
2051 Scope scope(b);
2053 if (!w)
2054 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2055 QQmlXMLHttpRequest *r = w->d()->request;
2056 return Encode(scope.engine->newString(r->responseType()));
2057}
2058
2060{
2061 Scope scope(b);
2063 if (!w)
2064 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2065 QQmlXMLHttpRequest *r = w->d()->request;
2066
2067 if (argc < 1)
2068 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
2069
2070 // Argument 0 - response type
2071 r->setResponseType(argv[0].toQStringNoThrow());
2072
2073 return Encode::undefined();
2074}
2075
2077{
2078 Scope scope(b);
2080 if (!w)
2081 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2082 QQmlXMLHttpRequest *r = w->d()->request;
2083
2084 if (r->readyState() != QQmlXMLHttpRequest::Loading &&
2085 r->readyState() != QQmlXMLHttpRequest::Done) {
2086 return Encode(scope.engine->newString(QString()));
2087 } else {
2088 QUrl url = r->url();
2090 return Encode(scope.engine->newString(url.toString()));
2091 }
2092}
2093
2095{
2096 Scope scope(b);
2098 if (!w)
2099 V4THROW_REFERENCE("Not an XMLHttpRequest object");
2100 QQmlXMLHttpRequest *r = w->d()->request;
2101
2102 if (argc != 1)
2103 THROW_DOM(DOMEXCEPTION_SYNTAX_ERR, "Incorrect argument count");
2104
2105 // If state is loading or done, throw an InvalidStateError exception.
2106 if (r->readyState() == QQmlXMLHttpRequest::Loading ||
2107 r->readyState() == QQmlXMLHttpRequest::Done)
2108 THROW_DOM(DOMEXCEPTION_INVALID_STATE_ERR, "Invalid state");
2109
2110 // Set override MIME type to `application/octet-stream`.
2111 r->setOverrideMimeType(QStringLiteral("application/octet-stream"));
2112 const auto parts = argv[0].toQStringNoThrow().split(QLatin1Char(';'));
2113 const auto type = parts.at(0).trimmed();
2114
2115 const auto mimeInvalidCharacter = [](QChar uni) {
2116 if (uni.unicode() > 127) // Only accept ASCII
2117 return true;
2118 const char ch = char(uni.unicode());
2119 return !(ch == '-' || ch == '/' || isAsciiLetterOrNumber(ch));
2120 };
2121
2122 // If mime is a parsable MIME type, ...
2123 if (type.count(QLatin1Char('/')) == 1
2124 && std::find_if(type.begin(), type.end(), mimeInvalidCharacter) == type.end()) {
2125 // ... then set override MIME type to its MIME type portion.
2126 r->setOverrideMimeType(type);
2127 }
2128 for (const auto &part : parts) {
2129 const QLatin1String charset("charset=");
2130 // If override MIME type has a `charset` parameter, ...
2131 if (part.trimmed().startsWith(charset)) {
2132 // ... then set override charset to its value.
2133 const int offset(part.indexOf(charset) + charset.size());
2134 r->setOverrideCharset(part.sliced(offset).trimmed());
2135 }
2136 }
2137
2138 return Encode::undefined();
2139}
2140
2141void qt_rem_qmlxmlhttprequest(ExecutionEngine * /* engine */, void *d)
2142{
2144 delete data;
2145}
2146
2148{
2149 Scope scope(v4);
2150
2152 ScopedString s(scope, v4->newString(QStringLiteral("XMLHttpRequest")));
2154
2156 return data;
2157}
2158
2160
2161#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:122
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
void clear()
Clears the contents of the byte array and makes it null.
QByteArray toLower() const &
Definition qbytearray.h:190
QByteArray & append(char c)
This is an overloaded member function, provided for convenience. It differs from the above function o...
\inmodule QtCore
Definition qchar.h:48
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
Definition qlist.h:74
bool isEmpty() const noexcept
Definition qlist.h:390
void append(parameter_type t)
Definition qlist.h:441
void clear()
Definition qlist.h:417
\inmodule QtCore
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(const QByteArray &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.
void setUrl(const QUrl &url)
Sets the URL this network request is referring to be url.
QByteArray rawHeader(const QByteArray &headerName) const
Returns the raw form of header headerName.
\inmodule QtCore
Definition qobject.h:90
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
void setParent(QObject *parent)
Makes the object a child of parent.
Definition qobject.cpp:2142
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
void deleteLater()
\threadsafe
Definition qobject.cpp:2352
\inmodule QtCore
Definition qpointer.h:18
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 QFile.
Definition qqmlfile.cpp:549
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)
\inmodule QtCore
Definition qstack.h:13
T & top()
Returns a reference to the stack's top item.
Definition qstack.h:19
T pop()
Removes the top item from the stack and returns it.
Definition qstack.h:18
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:76
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:127
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:660
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition qstring.cpp:5299
QString & replace(qsizetype i, qsizetype len, QChar after)
Definition qstring.cpp:3794
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:7956
const QChar * constData() const
Returns a pointer to the data stored in the QString.
Definition qstring.h:1101
bool isNull() const
Returns true if this string is null; otherwise returns false.
Definition qstring.h:898
qsizetype size() const
Returns the number of characters in this string.
Definition qstring.h:182
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:5857
QString mid(qsizetype position, qsizetype n=-1) const
Returns a string that contains n characters of this string, starting at the specified position index.
Definition qstring.cpp:5204
QString first(qsizetype n) const
Definition qstring.h:337
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition qstring.h:1083
int compare(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const noexcept
Definition qstring.cpp:6498
QString toLower() const &
Definition qstring.h:368
QString & append(QChar c)
Definition qstring.cpp:3227
static QString static QString qsizetype indexOf(QChar c, qsizetype from=0, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition qstring.cpp:4420
QByteArray toUtf8() const &
Definition qstring.h:563
QString toUpper() const &
Definition qstring.h:372
\inmodule QtCore
Definition qurl.h:94
QString url(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2814
QUrl resolved(const QUrl &relative) const
Returns the result of the merge of this URL with relative.
Definition qurl.cpp:2722
void setPassword(const QString &password, ParsingMode mode=DecodedMode)
Sets the URL's password to password.
Definition qurl.cpp:2224
void setUserName(const QString &userName, ParsingMode mode=DecodedMode)
Sets the URL's user name to userName.
Definition qurl.cpp:2161
void setFragment(const QString &fragment, ParsingMode mode=TolerantMode)
Sets the fragment of the URL to fragment.
Definition qurl.cpp:2645
bool isRelative() const
Returns true if the URL is relative; otherwise returns false.
Definition qurl.cpp:2797
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
Definition qurl.cpp:2828
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 *)
ReturnedValue parse(QJsonParseError *error)
ObjectType::Data * allocate(Args &&... args)
Definition qv4mm_p.h:199
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:64
bool isValid() const
Returns true if the storage type of this variant is not QMetaType::UnknownType; otherwise returns fal...
Definition qvariant.h:707
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())
double e
Combined button and popup list for selecting options.
\qmltype Particle \inqmlmodule QtQuick.Particles
quint64 ReturnedValue
Scoped< Object > ScopedObject
@ CaseInsensitive
static void * context
std::pair< T1, T2 > QPair
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)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
const char * mimeType
#define qWarning
Definition qlogging.h:162
return ret
#define SLOT(a)
Definition qobjectdefs.h:51
#define SIGNAL(a)
Definition qobjectdefs.h:52
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]
GLfloat GLfloat f
GLenum GLuint buffer
GLenum type
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
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:1391
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:45
unsigned int uint
Definition qtypes.h:29
#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:17
PersistentValue characterDataPrototype
PersistentValue documentPrototype
static constexpr ReturnedValue undefined()
static constexpr ReturnedValue null()
MemoryManager * memoryManager
QQmlRefPointer< QQmlContextData > callingQmlContext() const
Heap::String * newString(const QString &s=QString())
String * id_length() const
Heap::Object * newObject()
void freezeObject(const QV4::Value &value)
Heap::ExecutionContext * scope() const
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 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
constexpr 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:24